//===--------------- LLVMContextImpl.cpp - Implementation ------*- C++ -*--===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file implements LLVMContextImpl, the opaque implementation // of LLVMContext. // //===----------------------------------------------------------------------===// #include "LLVMContextImpl.h" #include "llvm/Constants.h" #include "llvm/DerivedTypes.h" #include "llvm/LLVMContext.h" #include "llvm/MDNode.h" using namespace llvm; static char getValType(ConstantAggregateZero *CPZ) { return 0; } static std::vector getValType(ConstantArray *CA) { std::vector Elements; Elements.reserve(CA->getNumOperands()); for (unsigned i = 0, e = CA->getNumOperands(); i != e; ++i) Elements.push_back(cast(CA->getOperand(i))); return Elements; } static std::vector getValType(ConstantStruct *CS) { std::vector Elements; Elements.reserve(CS->getNumOperands()); for (unsigned i = 0, e = CS->getNumOperands(); i != e; ++i) Elements.push_back(cast(CS->getOperand(i))); return Elements; } static std::vector getValType(ConstantVector *CP) { std::vector Elements; Elements.reserve(CP->getNumOperands()); for (unsigned i = 0, e = CP->getNumOperands(); i != e; ++i) Elements.push_back(CP->getOperand(i)); return Elements; } LLVMContextImpl::LLVMContextImpl(LLVMContext &C) : Context(C), TheTrueVal(0), TheFalseVal(0) { } ConstantFP *LLVMContextImpl::getConstantFP(const APFloat &V) { DenseMapAPFloatKeyInfo::KeyTy Key(V); ConstantsLock.reader_acquire(); ConstantFP *&Slot = FPConstants[Key]; ConstantsLock.reader_release(); if (!Slot) { sys::SmartScopedWriter Writer(ConstantsLock); ConstantFP *&NewSlot = FPConstants[Key]; if (!NewSlot) { const Type *Ty; if (&V.getSemantics() == &APFloat::IEEEsingle) Ty = Type::FloatTy; else if (&V.getSemantics() == &APFloat::IEEEdouble) Ty = Type::DoubleTy; else if (&V.getSemantics() == &APFloat::x87DoubleExtended) Ty = Type::X86_FP80Ty; else if (&V.getSemantics() == &APFloat::IEEEquad) Ty = Type::FP128Ty; else { assert(&V.getSemantics() == &APFloat::PPCDoubleDouble && "Unknown FP format"); Ty = Type::PPC_FP128Ty; } NewSlot = new ConstantFP(Ty, V); } return NewSlot; } return Slot; } MDString *LLVMContextImpl::getMDString(const char *StrBegin, unsigned StrLength) { sys::SmartScopedWriter Writer(ConstantsLock); StringMapEntry &Entry = MDStringCache.GetOrCreateValue(StringRef(StrBegin, StrLength)); MDString *&S = Entry.getValue(); if (!S) S = new MDString(Entry.getKeyData(), Entry.getKeyLength()); return S; } MDNode *LLVMContextImpl::getMDNode(Value*const* Vals, unsigned NumVals) { FoldingSetNodeID ID; for (unsigned i = 0; i != NumVals; ++i) ID.AddPointer(Vals[i]); ConstantsLock.reader_acquire(); void *InsertPoint; MDNode *N = MDNodeSet.FindNodeOrInsertPos(ID, InsertPoint); ConstantsLock.reader_release(); if (!N) { sys::SmartScopedWriter Writer(ConstantsLock); N = MDNodeSet.FindNodeOrInsertPos(ID, InsertPoint); if (!N) { // InsertPoint will have been set by the FindNodeOrInsertPos call. N = new MDNode(Vals, NumVals); MDNodeSet.InsertNode(N, InsertPoint); } } return N; } ConstantAggregateZero* LLVMContextImpl::getConstantAggregateZero(const Type *Ty) { assert((isa(Ty) || isa(Ty) || isa(Ty)) && "Cannot create an aggregate zero of non-aggregate type!"); // Implicitly locked. return AggZeroConstants.getOrCreate(Ty, 0); } Constant *LLVMContextImpl::getConstantArray(const ArrayType *Ty, const std::vector &V) { // If this is an all-zero array, return a ConstantAggregateZero object if (!V.empty()) { Constant *C = V[0]; if (!C->isNullValue()) { // Implicitly locked. return ArrayConstants.getOrCreate(Ty, V); } for (unsigned i = 1, e = V.size(); i != e; ++i) if (V[i] != C) { // Implicitly locked. return ArrayConstants.getOrCreate(Ty, V); } } return Context.getConstantAggregateZero(Ty); } Constant *LLVMContextImpl::getConstantStruct(const StructType *Ty, const std::vector &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); } Constant *LLVMContextImpl::getConstantVector(const VectorType *Ty, const std::vector &V) { assert(!V.empty() && "Vectors can't be empty"); // If this is an all-undef or alll-zero vector, return a // ConstantAggregateZero or UndefValue. Constant *C = V[0]; bool isZero = C->isNullValue(); bool isUndef = isa(C); if (isZero || isUndef) { for (unsigned i = 1, e = V.size(); i != e; ++i) if (V[i] != C) { isZero = isUndef = false; break; } } if (isZero) return Context.getConstantAggregateZero(Ty); if (isUndef) return Context.getUndef(Ty); // Implicitly locked. return VectorConstants.getOrCreate(Ty, V); } // *** erase methods *** void LLVMContextImpl::erase(MDString *M) { sys::SmartScopedWriter Writer(ConstantsLock); MDStringCache.erase(MDStringCache.find(StringRef(M->StrBegin, M->length()))); } void LLVMContextImpl::erase(MDNode *M) { sys::SmartScopedWriter Writer(ConstantsLock); MDNodeSet.RemoveNode(M); } void LLVMContextImpl::erase(ConstantAggregateZero *Z) { AggZeroConstants.remove(Z); } void LLVMContextImpl::erase(ConstantArray *C) { ArrayConstants.remove(C); } void LLVMContextImpl::erase(ConstantStruct *S) { StructConstants.remove(S); } void LLVMContextImpl::erase(ConstantVector *V) { VectorConstants.remove(V); } // *** RAUW helpers *** Constant *LLVMContextImpl::replaceUsesOfWithOnConstant(ConstantArray *CA, Value *From, Value *To, Use *U) { assert(isa(To) && "Cannot make Constant refer to non-constant!"); Constant *ToC = cast(To); std::pair Lookup; Lookup.first.first = CA->getType(); Lookup.second = CA; std::vector &Values = Lookup.first.second; Values.reserve(CA->getNumOperands()); // Build replacement array. // Fill values with the modified operands of the constant array. Also, // compute whether this turns into an all-zeros array. bool isAllZeros = false; unsigned NumUpdated = 0; if (!ToC->isNullValue()) { for (Use *O = CA->OperandList, *E = CA->OperandList + CA->getNumOperands(); O != E; ++O) { Constant *Val = cast(O->get()); if (Val == From) { Val = ToC; ++NumUpdated; } Values.push_back(Val); } } else { isAllZeros = true; for (Use *O = CA->OperandList, *E = CA->OperandList + CA->getNumOperands(); O != E; ++O) { Constant *Val = cast(O->get()); if (Val == From) { Val = ToC; ++NumUpdated; } Values.push_back(Val); if (isAllZeros) isAllZeros = Val->isNullValue(); } } Constant *Replacement = 0; if (isAllZeros) { Replacement = Context.getConstantAggregateZero(CA->getType()); } else { // Check to see if we have this array type already. sys::SmartScopedWriter Writer(ConstantsLock); bool Exists; ArrayConstantsTy::MapTy::iterator I = ArrayConstants.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 array, inserting it, replaceallusesof'ing the // old with the new, then deleting the old... just update the current one // in place! ArrayConstants.MoveConstantToNewSlot(CA, I); // Update to the new value. Optimize for the case when we have a single // operand that we're changing, but handle bulk updates efficiently. if (NumUpdated == 1) { unsigned OperandToUpdate = U - CA->OperandList; assert(CA->getOperand(OperandToUpdate) == From && "ReplaceAllUsesWith broken!"); CA->setOperand(OperandToUpdate, ToC); } else { for (unsigned i = 0, e = CA->getNumOperands(); i != e; ++i) if (CA->getOperand(i) == From) CA->setOperand(i, ToC); } return 0; } } return Replacement; } Constant *LLVMContextImpl::replaceUsesOfWithOnConstant(ConstantStruct *CS, Value *From, Value *To, Use *U) { assert(isa(To) && "Cannot make Constant refer to non-constant!"); Constant *ToC = cast(To); unsigned OperandToUpdate = U - CS->OperandList; assert(CS->getOperand(OperandToUpdate) == From && "ReplaceAllUsesWith broken!"); std::pair Lookup; Lookup.first.first = CS->getType(); Lookup.second = CS; std::vector &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(O->get())); } else { isAllZeros = true; for (Use *O = CS->OperandList, *E = CS->OperandList + CS->getNumOperands(); O != E; ++O) { Constant *Val = cast(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 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; }