5315e23f8e352282189aa01388842c9a312c3348
[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(ConstantStruct *CS) {
33   std::vector<Constant*> Elements;
34   Elements.reserve(CS->getNumOperands());
35   for (unsigned i = 0, e = CS->getNumOperands(); i != e; ++i)
36     Elements.push_back(cast<Constant>(CS->getOperand(i)));
37   return Elements;
38 }
39
40 static std::vector<Constant*> getValType(ConstantVector *CP) {
41   std::vector<Constant*> Elements;
42   Elements.reserve(CP->getNumOperands());
43   for (unsigned i = 0, e = CP->getNumOperands(); i != e; ++i)
44     Elements.push_back(CP->getOperand(i));
45   return Elements;
46 }
47
48
49 LLVMContextImpl::LLVMContextImpl(LLVMContext &C) :
50     Context(C), TheTrueVal(0), TheFalseVal(0) { }
51
52 MDString *LLVMContextImpl::getMDString(const char *StrBegin,
53                                        unsigned StrLength) {
54   sys::SmartScopedWriter<true> Writer(ConstantsLock);
55   StringMapEntry<MDString *> &Entry = 
56     MDStringCache.GetOrCreateValue(StringRef(StrBegin, StrLength));
57   MDString *&S = Entry.getValue();
58   if (!S) S = new MDString(Entry.getKeyData(),
59                            Entry.getKeyLength());
60
61   return S;
62 }
63
64 MDNode *LLVMContextImpl::getMDNode(Value*const* Vals, unsigned NumVals) {
65   FoldingSetNodeID ID;
66   for (unsigned i = 0; i != NumVals; ++i)
67     ID.AddPointer(Vals[i]);
68
69   ConstantsLock.reader_acquire();
70   void *InsertPoint;
71   MDNode *N = MDNodeSet.FindNodeOrInsertPos(ID, InsertPoint);
72   ConstantsLock.reader_release();
73   
74   if (!N) {
75     sys::SmartScopedWriter<true> Writer(ConstantsLock);
76     N = MDNodeSet.FindNodeOrInsertPos(ID, InsertPoint);
77     if (!N) {
78       // InsertPoint will have been set by the FindNodeOrInsertPos call.
79       N = new MDNode(Vals, NumVals);
80       MDNodeSet.InsertNode(N, InsertPoint);
81     }
82   }
83
84   return N;
85 }
86
87 ConstantAggregateZero*
88 LLVMContextImpl::getConstantAggregateZero(const Type *Ty) {
89   assert((isa<StructType>(Ty) || isa<ArrayType>(Ty) || isa<VectorType>(Ty)) &&
90          "Cannot create an aggregate zero of non-aggregate type!");
91
92   // Implicitly locked.
93   return AggZeroConstants.getOrCreate(Ty, 0);
94 }
95
96 Constant *LLVMContextImpl::getConstantArray(const ArrayType *Ty,
97                              const std::vector<Constant*> &V) {
98   // If this is an all-zero array, return a ConstantAggregateZero object
99   if (!V.empty()) {
100     Constant *C = V[0];
101     if (!C->isNullValue()) {
102       // Implicitly locked.
103       return ArrayConstants.getOrCreate(Ty, V);
104     }
105     for (unsigned i = 1, e = V.size(); i != e; ++i)
106       if (V[i] != C) {
107         // Implicitly locked.
108         return ArrayConstants.getOrCreate(Ty, V);
109       }
110   }
111   
112   return Context.getConstantAggregateZero(Ty);
113 }
114
115 Constant *LLVMContextImpl::getConstantStruct(const StructType *Ty,
116                               const std::vector<Constant*> &V) {
117   // Create a ConstantAggregateZero value if all elements are zeros...
118   for (unsigned i = 0, e = V.size(); i != e; ++i)
119     if (!V[i]->isNullValue())
120       // Implicitly locked.
121       return StructConstants.getOrCreate(Ty, V);
122
123   return Context.getConstantAggregateZero(Ty);
124 }
125
126 Constant *LLVMContextImpl::getConstantVector(const VectorType *Ty,
127                               const std::vector<Constant*> &V) {
128   assert(!V.empty() && "Vectors can't be empty");
129   // If this is an all-undef or alll-zero vector, return a
130   // ConstantAggregateZero or UndefValue.
131   Constant *C = V[0];
132   bool isZero = C->isNullValue();
133   bool isUndef = isa<UndefValue>(C);
134
135   if (isZero || isUndef) {
136     for (unsigned i = 1, e = V.size(); i != e; ++i)
137       if (V[i] != C) {
138         isZero = isUndef = false;
139         break;
140       }
141   }
142   
143   if (isZero)
144     return Context.getConstantAggregateZero(Ty);
145   if (isUndef)
146     return Context.getUndef(Ty);
147     
148   // Implicitly locked.
149   return VectorConstants.getOrCreate(Ty, V);
150 }
151
152 // *** erase methods ***
153
154 void LLVMContextImpl::erase(MDString *M) {
155   sys::SmartScopedWriter<true> Writer(ConstantsLock);
156   MDStringCache.erase(MDStringCache.find(M->getString()));
157 }
158
159 void LLVMContextImpl::erase(MDNode *M) {
160   sys::SmartScopedWriter<true> Writer(ConstantsLock);
161   MDNodeSet.RemoveNode(M);
162 }
163
164 void LLVMContextImpl::erase(ConstantAggregateZero *Z) {
165   AggZeroConstants.remove(Z);
166 }
167
168 void LLVMContextImpl::erase(ConstantArray *C) {
169   ArrayConstants.remove(C);
170 }
171
172 void LLVMContextImpl::erase(ConstantStruct *S) {
173   StructConstants.remove(S);
174 }
175
176 void LLVMContextImpl::erase(ConstantVector *V) {
177   VectorConstants.remove(V);
178 }
179
180 // *** RAUW helpers ***
181
182 Constant *LLVMContextImpl::replaceUsesOfWithOnConstant(ConstantArray *CA,
183                                                Value *From, Value *To, Use *U) {
184   assert(isa<Constant>(To) && "Cannot make Constant refer to non-constant!");
185   Constant *ToC = cast<Constant>(To);
186
187   std::pair<ArrayConstantsTy::MapKey, Constant*> Lookup;
188   Lookup.first.first = CA->getType();
189   Lookup.second = CA;
190
191   std::vector<Constant*> &Values = Lookup.first.second;
192   Values.reserve(CA->getNumOperands());  // Build replacement array.
193
194   // Fill values with the modified operands of the constant array.  Also, 
195   // compute whether this turns into an all-zeros array.
196   bool isAllZeros = false;
197   unsigned NumUpdated = 0;
198   if (!ToC->isNullValue()) {
199     for (Use *O = CA->OperandList, *E = CA->OperandList + CA->getNumOperands();
200          O != E; ++O) {
201       Constant *Val = cast<Constant>(O->get());
202       if (Val == From) {
203         Val = ToC;
204         ++NumUpdated;
205       }
206       Values.push_back(Val);
207     }
208   } else {
209     isAllZeros = true;
210     for (Use *O = CA->OperandList, *E = CA->OperandList + CA->getNumOperands();
211          O != E; ++O) {
212       Constant *Val = cast<Constant>(O->get());
213       if (Val == From) {
214         Val = ToC;
215         ++NumUpdated;
216       }
217       Values.push_back(Val);
218       if (isAllZeros) isAllZeros = Val->isNullValue();
219     }
220   }
221   
222   Constant *Replacement = 0;
223   if (isAllZeros) {
224     Replacement = Context.getConstantAggregateZero(CA->getType());
225   } else {
226     // Check to see if we have this array type already.
227     sys::SmartScopedWriter<true> Writer(ConstantsLock);
228     bool Exists;
229     ArrayConstantsTy::MapTy::iterator I =
230       ArrayConstants.InsertOrGetItem(Lookup, Exists);
231     
232     if (Exists) {
233       Replacement = I->second;
234     } else {
235       // Okay, the new shape doesn't exist in the system yet.  Instead of
236       // creating a new constant array, inserting it, replaceallusesof'ing the
237       // old with the new, then deleting the old... just update the current one
238       // in place!
239       ArrayConstants.MoveConstantToNewSlot(CA, I);
240       
241       // Update to the new value.  Optimize for the case when we have a single
242       // operand that we're changing, but handle bulk updates efficiently.
243       if (NumUpdated == 1) {
244         unsigned OperandToUpdate = U - CA->OperandList;
245         assert(CA->getOperand(OperandToUpdate) == From &&
246                "ReplaceAllUsesWith broken!");
247         CA->setOperand(OperandToUpdate, ToC);
248       } else {
249         for (unsigned i = 0, e = CA->getNumOperands(); i != e; ++i)
250           if (CA->getOperand(i) == From)
251             CA->setOperand(i, ToC);
252       }
253       return 0;
254     }
255   }
256   
257   return Replacement;
258 }
259
260 Constant *LLVMContextImpl::replaceUsesOfWithOnConstant(ConstantStruct *CS,
261                                                Value *From, Value *To, Use *U) {
262   assert(isa<Constant>(To) && "Cannot make Constant refer to non-constant!");
263   Constant *ToC = cast<Constant>(To);
264
265   unsigned OperandToUpdate = U - CS->OperandList;
266   assert(CS->getOperand(OperandToUpdate) == From &&
267          "ReplaceAllUsesWith broken!");
268
269   std::pair<StructConstantsTy::MapKey, Constant*> Lookup;
270   Lookup.first.first = CS->getType();
271   Lookup.second = CS;
272   std::vector<Constant*> &Values = Lookup.first.second;
273   Values.reserve(CS->getNumOperands());  // Build replacement struct.
274   
275   
276   // Fill values with the modified operands of the constant struct.  Also, 
277   // compute whether this turns into an all-zeros struct.
278   bool isAllZeros = false;
279   if (!ToC->isNullValue()) {
280     for (Use *O = CS->OperandList, *E = CS->OperandList + CS->getNumOperands(); 
281          O != E; ++O)
282       Values.push_back(cast<Constant>(O->get()));
283   } else {
284     isAllZeros = true;
285     for (Use *O = CS->OperandList, *E = CS->OperandList + CS->getNumOperands(); 
286          O != E; ++O) {
287       Constant *Val = cast<Constant>(O->get());
288       Values.push_back(Val);
289       if (isAllZeros) isAllZeros = Val->isNullValue();
290     }
291   }
292   Values[OperandToUpdate] = ToC;
293   
294   Constant *Replacement = 0;
295   if (isAllZeros) {
296     Replacement = Context.getConstantAggregateZero(CS->getType());
297   } else {
298     // Check to see if we have this array type already.
299     sys::SmartScopedWriter<true> Writer(ConstantsLock);
300     bool Exists;
301     StructConstantsTy::MapTy::iterator I =
302       StructConstants.InsertOrGetItem(Lookup, Exists);
303     
304     if (Exists) {
305       Replacement = I->second;
306     } else {
307       // Okay, the new shape doesn't exist in the system yet.  Instead of
308       // creating a new constant struct, inserting it, replaceallusesof'ing the
309       // old with the new, then deleting the old... just update the current one
310       // in place!
311       StructConstants.MoveConstantToNewSlot(CS, I);
312       
313       // Update to the new value.
314       CS->setOperand(OperandToUpdate, ToC);
315       return 0;
316     }
317   }
318   
319   assert(Replacement != CS && "I didn't contain From!");
320   
321   return Replacement;
322 }