Mercurial > projects > ldc
comparison gen/passes/GarbageCollect2Stack.cpp @ 1317:4099548c80e0
Allocate objects on the stack if they (a) don't have a destructor, and
(b) don't override the delete operator (on top of the regular conditions for
stack allocation that also apply to arrays, structs, etc.).
The "no destructor" clause is not strictly necessary, but calling them at the
right time would be tricky to say the least; it would involve, among other
things, "manually" inserting a try-finally block around anything that might
throw exceptions not caught in the current function.
Note: objects with custom new operators are automatically ignored because they
don't use the regular allocation runtime call, so there's no need to pay special
attention to them.
author | Frits van Bommel <fvbommel wxs.nl> |
---|---|
date | Sat, 09 May 2009 00:50:15 +0200 |
parents | 8c65217be813 |
children | c21a6654cce2 |
comparison
equal
deleted
inserted
replaced
1316:8c65217be813 | 1317:4099548c80e0 |
---|---|
178 } | 178 } |
179 | 179 |
180 return alloca; | 180 return alloca; |
181 } | 181 } |
182 }; | 182 }; |
183 | |
184 // FunctionInfo for _d_allocclass | |
185 class AllocClassFI : public FunctionInfo { | |
186 public: | |
187 virtual bool analyze(CallSite CS, const Analysis& A) { | |
188 // This call contains no TypeInfo parameter, so don't call the | |
189 // base class implementation here... | |
190 if (CS.arg_size() != 1) | |
191 return false; | |
192 Value* arg = CS.getArgument(0)->stripPointerCasts(); | |
193 GlobalVariable* ClassInfo = dyn_cast<GlobalVariable>(arg); | |
194 if (!ClassInfo) | |
195 return false; | |
196 | |
197 std::string metaname = CD_PREFIX; | |
198 metaname.append(ClassInfo->getNameStart(), ClassInfo->getNameEnd()); | |
199 | |
200 GlobalVariable* global = A.M.getGlobalVariable(metaname); | |
201 if (!global || !global->hasInitializer()) | |
202 return false; | |
203 | |
204 MDNode* node = dyn_cast<MDNode>(global->getInitializer()); | |
205 if (!node || node->getNumOperands() != CD_NumFields) | |
206 return false; | |
207 | |
208 // Inserting destructor calls is not implemented yet, so classes | |
209 // with destructors are ignored for now. | |
210 Constant* hasDestructor = dyn_cast<Constant>(node->getOperand(CD_Finalize)); | |
211 // We can't stack-allocate if the class has a custom deallocator | |
212 // (Custom allocators don't get turned into this runtime call, so | |
213 // those can be ignored) | |
214 Constant* hasCustomDelete = dyn_cast<Constant>(node->getOperand(CD_CustomDelete)); | |
215 if (hasDestructor == NULL || hasCustomDelete == NULL) | |
216 return false; | |
217 | |
218 if (ConstantExpr::getOr(hasDestructor, hasCustomDelete) | |
219 != ConstantInt::getFalse()) | |
220 return false; | |
221 | |
222 Ty = node->getOperand(CD_BodyType)->getType(); | |
223 return true; | |
224 } | |
225 | |
226 // The default promote() should be fine. | |
227 | |
228 AllocClassFI() : FunctionInfo(-1, true) {} | |
229 }; | |
183 } | 230 } |
184 | 231 |
185 | 232 |
186 //===----------------------------------------------------------------------===// | 233 //===----------------------------------------------------------------------===// |
187 // GarbageCollect2Stack Pass Implementation | 234 // GarbageCollect2Stack Pass Implementation |
195 Module* M; | 242 Module* M; |
196 | 243 |
197 FunctionInfo AllocMemoryT; | 244 FunctionInfo AllocMemoryT; |
198 ArrayFI NewArrayVT; | 245 ArrayFI NewArrayVT; |
199 ArrayFI NewArrayT; | 246 ArrayFI NewArrayT; |
247 AllocClassFI AllocClass; | |
200 | 248 |
201 public: | 249 public: |
202 static char ID; // Pass identification | 250 static char ID; // Pass identification |
203 GarbageCollect2Stack(); | 251 GarbageCollect2Stack(); |
204 | 252 |
231 NewArrayT(0, true, true, 1) | 279 NewArrayT(0, true, true, 1) |
232 { | 280 { |
233 KnownFunctions["_d_allocmemoryT"] = &AllocMemoryT; | 281 KnownFunctions["_d_allocmemoryT"] = &AllocMemoryT; |
234 KnownFunctions["_d_newarrayvT"] = &NewArrayVT; | 282 KnownFunctions["_d_newarrayvT"] = &NewArrayVT; |
235 KnownFunctions["_d_newarrayT"] = &NewArrayT; | 283 KnownFunctions["_d_newarrayT"] = &NewArrayT; |
284 KnownFunctions["_d_allocclass"] = &AllocClass; | |
236 } | 285 } |
237 | 286 |
238 static void RemoveCall(Instruction* Inst) { | 287 static void RemoveCall(Instruction* Inst) { |
239 if (InvokeInst* Invoke = dyn_cast<InvokeInst>(Inst)) { | 288 if (InvokeInst* Invoke = dyn_cast<InvokeInst>(Inst)) { |
240 // If this was an invoke instruction, we need to do some extra | 289 // If this was an invoke instruction, we need to do some extra |