diff options
Diffstat (limited to 'lib/VMCore/LLVMContextImpl.cpp')
-rw-r--r-- | lib/VMCore/LLVMContextImpl.cpp | 104 |
1 files changed, 104 insertions, 0 deletions
diff --git a/lib/VMCore/LLVMContextImpl.cpp b/lib/VMCore/LLVMContextImpl.cpp index 1c5af77..156d4ca 100644 --- a/lib/VMCore/LLVMContextImpl.cpp +++ b/lib/VMCore/LLVMContextImpl.cpp @@ -29,6 +29,14 @@ static std::vector<Constant*> getValType(ConstantArray *CA) { return Elements; } +static std::vector<Constant*> getValType(ConstantStruct *CS) { + std::vector<Constant*> Elements; + Elements.reserve(CS->getNumOperands()); + for (unsigned i = 0, e = CS->getNumOperands(); i != e; ++i) + Elements.push_back(cast<Constant>(CS->getOperand(i))); + return Elements; +} + namespace llvm { template<typename T, typename Alloc> struct VISIBILITY_HIDDEN ConstantTraits< std::vector<T, Alloc> > { @@ -83,6 +91,21 @@ struct ConvertConstantType<ConstantArray, ArrayType> { OldC->destroyConstant(); // This constant is now dead, destroy it. } }; + +template<> +struct ConvertConstantType<ConstantStruct, StructType> { + static void convert(ConstantStruct *OldC, const StructType *NewTy) { + // Make everyone now use a constant of the new type... + std::vector<Constant*> C; + for (unsigned i = 0, e = OldC->getNumOperands(); i != e; ++i) + C.push_back(cast<Constant>(OldC->getOperand(i))); + Constant *New = NewTy->getContext().getConstantStruct(NewTy, C); + assert(New != OldC && "Didn't replace constant??"); + + OldC->uncheckedReplaceAllUsesWith(New); + OldC->destroyConstant(); // This constant is now dead, destroy it. + } +}; } template<class ValType, class TypeClass, class ConstantClass, @@ -324,11 +347,13 @@ LLVMContextImpl::LLVMContextImpl(LLVMContext &C) : Context(C), TheTrueVal(0), TheFalseVal(0) { AggZeroConstants = new ValueMap<char, Type, ConstantAggregateZero>(); ArrayConstants = new ArrayConstantsTy(); + StructConstants = new StructConstantsTy(); } LLVMContextImpl::~LLVMContextImpl() { delete AggZeroConstants; delete ArrayConstants; + delete StructConstants; } // Get a ConstantInt from an APInt. Note that the value stored in the DenseMap @@ -456,6 +481,17 @@ Constant *LLVMContextImpl::getConstantArray(const ArrayType *Ty, return Context.getConstantAggregateZero(Ty); } +Constant *LLVMContextImpl::getConstantStruct(const StructType *Ty, + const std::vector<Constant*> &V) { + // Create a ConstantAggregateZero value if all elements are zeros... + for (unsigned i = 0, e = V.size(); i != e; ++i) + if (!V[i]->isNullValue()) + // Implicitly locked. + return StructConstants->getOrCreate(Ty, V); + + return Context.getConstantAggregateZero(Ty); +} + // *** erase methods *** void LLVMContextImpl::erase(MDString *M) { @@ -477,7 +513,12 @@ void LLVMContextImpl::erase(ConstantArray *C) { ArrayConstants->remove(C); } +void LLVMContextImpl::erase(ConstantStruct *S) { + StructConstants->remove(S); +} + // *** RAUW helpers *** + Constant *LLVMContextImpl::replaceUsesOfWithOnConstant(ConstantArray *CA, Value *From, Value *To, Use *U) { assert(isa<Constant>(To) && "Cannot make Constant refer to non-constant!"); @@ -556,3 +597,66 @@ Constant *LLVMContextImpl::replaceUsesOfWithOnConstant(ConstantArray *CA, return Replacement; } +Constant *LLVMContextImpl::replaceUsesOfWithOnConstant(ConstantStruct *CS, + Value *From, Value *To, Use *U) { + assert(isa<Constant>(To) && "Cannot make Constant refer to non-constant!"); + Constant *ToC = cast<Constant>(To); + + unsigned OperandToUpdate = U - CS->OperandList; + assert(CS->getOperand(OperandToUpdate) == From && + "ReplaceAllUsesWith broken!"); + + std::pair<StructConstantsTy::MapKey, Constant*> Lookup; + Lookup.first.first = CS->getType(); + Lookup.second = CS; + std::vector<Constant*> &Values = Lookup.first.second; + Values.reserve(CS->getNumOperands()); // Build replacement struct. + + + // Fill values with the modified operands of the constant struct. Also, + // compute whether this turns into an all-zeros struct. + bool isAllZeros = false; + if (!ToC->isNullValue()) { + for (Use *O = CS->OperandList, *E = CS->OperandList + CS->getNumOperands(); + O != E; ++O) + Values.push_back(cast<Constant>(O->get())); + } else { + isAllZeros = true; + for (Use *O = CS->OperandList, *E = CS->OperandList + CS->getNumOperands(); + O != E; ++O) { + Constant *Val = cast<Constant>(O->get()); + Values.push_back(Val); + if (isAllZeros) isAllZeros = Val->isNullValue(); + } + } + Values[OperandToUpdate] = ToC; + + Constant *Replacement = 0; + if (isAllZeros) { + Replacement = Context.getConstantAggregateZero(CS->getType()); + } else { + // Check to see if we have this array type already. + sys::SmartScopedWriter<true> Writer(ConstantsLock); + bool Exists; + StructConstantsTy::MapTy::iterator I = + StructConstants->InsertOrGetItem(Lookup, Exists); + + if (Exists) { + Replacement = I->second; + } else { + // Okay, the new shape doesn't exist in the system yet. Instead of + // creating a new constant struct, inserting it, replaceallusesof'ing the + // old with the new, then deleting the old... just update the current one + // in place! + StructConstants->MoveConstantToNewSlot(CS, I); + + // Update to the new value. + CS->setOperand(OperandToUpdate, ToC); + return 0; + } + } + + assert(Replacement != CS && "I didn't contain From!"); + + return Replacement; +}
\ No newline at end of file |