Move ConstantStruct back to 2.5 API.
[oota-llvm.git] / lib / VMCore / LLVMContextImpl.cpp
1 //===--------------- LLVMContextImpl.cpp - Implementation ------*- C++ -*--===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 //  This file implements LLVMContextImpl, the opaque implementation 
11 //  of LLVMContext.
12 //
13 //===----------------------------------------------------------------------===//
14
15 #include "LLVMContextImpl.h"
16 #include "llvm/Constants.h"
17 #include "llvm/DerivedTypes.h"
18 #include "llvm/LLVMContext.h"
19 #include "llvm/MDNode.h"
20 using namespace llvm;
21
22 static char getValType(ConstantAggregateZero *CPZ) { return 0; }
23
24 static std::vector<Constant*> getValType(ConstantArray *CA) {
25   std::vector<Constant*> Elements;
26   Elements.reserve(CA->getNumOperands());
27   for (unsigned i = 0, e = CA->getNumOperands(); i != e; ++i)
28     Elements.push_back(cast<Constant>(CA->getOperand(i)));
29   return Elements;
30 }
31
32 static std::vector<Constant*> getValType(ConstantVector *CP) {
33   std::vector<Constant*> Elements;
34   Elements.reserve(CP->getNumOperands());
35   for (unsigned i = 0, e = CP->getNumOperands(); i != e; ++i)
36     Elements.push_back(CP->getOperand(i));
37   return Elements;
38 }
39
40
41 LLVMContextImpl::LLVMContextImpl(LLVMContext &C) :
42     Context(C), TheTrueVal(0), TheFalseVal(0) { }
43
44 MDString *LLVMContextImpl::getMDString(const char *StrBegin,
45                                        unsigned StrLength) {
46   sys::SmartScopedWriter<true> Writer(ConstantsLock);
47   StringMapEntry<MDString *> &Entry = 
48     MDStringCache.GetOrCreateValue(StringRef(StrBegin, StrLength));
49   MDString *&S = Entry.getValue();
50   if (!S) S = new MDString(Entry.getKeyData(),
51                            Entry.getKeyLength());
52
53   return S;
54 }
55
56 MDNode *LLVMContextImpl::getMDNode(Value*const* Vals, unsigned NumVals) {
57   FoldingSetNodeID ID;
58   for (unsigned i = 0; i != NumVals; ++i)
59     ID.AddPointer(Vals[i]);
60
61   ConstantsLock.reader_acquire();
62   void *InsertPoint;
63   MDNode *N = MDNodeSet.FindNodeOrInsertPos(ID, InsertPoint);
64   ConstantsLock.reader_release();
65   
66   if (!N) {
67     sys::SmartScopedWriter<true> Writer(ConstantsLock);
68     N = MDNodeSet.FindNodeOrInsertPos(ID, InsertPoint);
69     if (!N) {
70       // InsertPoint will have been set by the FindNodeOrInsertPos call.
71       N = new MDNode(Vals, NumVals);
72       MDNodeSet.InsertNode(N, InsertPoint);
73     }
74   }
75
76   return N;
77 }
78
79 ConstantAggregateZero*
80 LLVMContextImpl::getConstantAggregateZero(const Type *Ty) {
81   assert((isa<StructType>(Ty) || isa<ArrayType>(Ty) || isa<VectorType>(Ty)) &&
82          "Cannot create an aggregate zero of non-aggregate type!");
83
84   // Implicitly locked.
85   return AggZeroConstants.getOrCreate(Ty, 0);
86 }
87
88 Constant *LLVMContextImpl::getConstantArray(const ArrayType *Ty,
89                              const std::vector<Constant*> &V) {
90   // If this is an all-zero array, return a ConstantAggregateZero object
91   if (!V.empty()) {
92     Constant *C = V[0];
93     if (!C->isNullValue()) {
94       // Implicitly locked.
95       return ArrayConstants.getOrCreate(Ty, V);
96     }
97     for (unsigned i = 1, e = V.size(); i != e; ++i)
98       if (V[i] != C) {
99         // Implicitly locked.
100         return ArrayConstants.getOrCreate(Ty, V);
101       }
102   }
103   
104   return Context.getConstantAggregateZero(Ty);
105 }
106
107 Constant *LLVMContextImpl::getConstantVector(const VectorType *Ty,
108                               const std::vector<Constant*> &V) {
109   assert(!V.empty() && "Vectors can't be empty");
110   // If this is an all-undef or alll-zero vector, return a
111   // ConstantAggregateZero or UndefValue.
112   Constant *C = V[0];
113   bool isZero = C->isNullValue();
114   bool isUndef = isa<UndefValue>(C);
115
116   if (isZero || isUndef) {
117     for (unsigned i = 1, e = V.size(); i != e; ++i)
118       if (V[i] != C) {
119         isZero = isUndef = false;
120         break;
121       }
122   }
123   
124   if (isZero)
125     return Context.getConstantAggregateZero(Ty);
126   if (isUndef)
127     return Context.getUndef(Ty);
128     
129   // Implicitly locked.
130   return VectorConstants.getOrCreate(Ty, V);
131 }
132
133 // *** erase methods ***
134
135 void LLVMContextImpl::erase(MDString *M) {
136   sys::SmartScopedWriter<true> Writer(ConstantsLock);
137   MDStringCache.erase(MDStringCache.find(M->getString()));
138 }
139
140 void LLVMContextImpl::erase(MDNode *M) {
141   sys::SmartScopedWriter<true> Writer(ConstantsLock);
142   MDNodeSet.RemoveNode(M);
143 }
144
145 void LLVMContextImpl::erase(ConstantAggregateZero *Z) {
146   AggZeroConstants.remove(Z);
147 }
148
149 void LLVMContextImpl::erase(ConstantArray *C) {
150   ArrayConstants.remove(C);
151 }
152
153 void LLVMContextImpl::erase(ConstantVector *V) {
154   VectorConstants.remove(V);
155 }
156
157 // *** RAUW helpers ***
158
159 Constant *LLVMContextImpl::replaceUsesOfWithOnConstant(ConstantArray *CA,
160                                                Value *From, Value *To, Use *U) {
161   assert(isa<Constant>(To) && "Cannot make Constant refer to non-constant!");
162   Constant *ToC = cast<Constant>(To);
163
164   std::pair<ArrayConstantsTy::MapKey, Constant*> Lookup;
165   Lookup.first.first = CA->getType();
166   Lookup.second = CA;
167
168   std::vector<Constant*> &Values = Lookup.first.second;
169   Values.reserve(CA->getNumOperands());  // Build replacement array.
170
171   // Fill values with the modified operands of the constant array.  Also, 
172   // compute whether this turns into an all-zeros array.
173   bool isAllZeros = false;
174   unsigned NumUpdated = 0;
175   if (!ToC->isNullValue()) {
176     for (Use *O = CA->OperandList, *E = CA->OperandList + CA->getNumOperands();
177          O != E; ++O) {
178       Constant *Val = cast<Constant>(O->get());
179       if (Val == From) {
180         Val = ToC;
181         ++NumUpdated;
182       }
183       Values.push_back(Val);
184     }
185   } else {
186     isAllZeros = true;
187     for (Use *O = CA->OperandList, *E = CA->OperandList + CA->getNumOperands();
188          O != E; ++O) {
189       Constant *Val = cast<Constant>(O->get());
190       if (Val == From) {
191         Val = ToC;
192         ++NumUpdated;
193       }
194       Values.push_back(Val);
195       if (isAllZeros) isAllZeros = Val->isNullValue();
196     }
197   }
198   
199   Constant *Replacement = 0;
200   if (isAllZeros) {
201     Replacement = Context.getConstantAggregateZero(CA->getType());
202   } else {
203     // Check to see if we have this array type already.
204     sys::SmartScopedWriter<true> Writer(ConstantsLock);
205     bool Exists;
206     ArrayConstantsTy::MapTy::iterator I =
207       ArrayConstants.InsertOrGetItem(Lookup, Exists);
208     
209     if (Exists) {
210       Replacement = I->second;
211     } else {
212       // Okay, the new shape doesn't exist in the system yet.  Instead of
213       // creating a new constant array, inserting it, replaceallusesof'ing the
214       // old with the new, then deleting the old... just update the current one
215       // in place!
216       ArrayConstants.MoveConstantToNewSlot(CA, I);
217       
218       // Update to the new value.  Optimize for the case when we have a single
219       // operand that we're changing, but handle bulk updates efficiently.
220       if (NumUpdated == 1) {
221         unsigned OperandToUpdate = U - CA->OperandList;
222         assert(CA->getOperand(OperandToUpdate) == From &&
223                "ReplaceAllUsesWith broken!");
224         CA->setOperand(OperandToUpdate, ToC);
225       } else {
226         for (unsigned i = 0, e = CA->getNumOperands(); i != e; ++i)
227           if (CA->getOperand(i) == From)
228             CA->setOperand(i, ToC);
229       }
230       return 0;
231     }
232   }
233   
234   return Replacement;
235 }