Keep track of memory allocated by alloca so that it is freed appropriately
authorChris Lattner <sabre@nondot.org>
Tue, 19 Feb 2002 18:50:09 +0000 (18:50 +0000)
committerChris Lattner <sabre@nondot.org>
Tue, 19 Feb 2002 18:50:09 +0000 (18:50 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@1776 91177308-0d34-0410-b5e6-96231b3b80d8

lib/ExecutionEngine/Interpreter/Execution.cpp
lib/ExecutionEngine/Interpreter/Interpreter.h

index 9f6317fd3937b25aae661ddcbb9b4c523f041bb5..8b910f68af9ec35fc1bd85e7f1f31bc795ba92b5 100644 (file)
@@ -741,15 +741,16 @@ void Interpreter::executeAllocInst(AllocationInst *I, ExecutionContext &SF) {
   }
 
   // Allocate enough memory to hold the type...
-  GenericValue Result;
   // FIXME: Don't use CALLOC, use a tainted malloc.
-  Result.PointerVal = (PointerTy)calloc(NumElements, TD.getTypeSize(Ty));
+  void *Memory = calloc(NumElements, TD.getTypeSize(Ty));
+
+  GenericValue Result;
+  Result.PointerVal = (PointerTy)Memory;
   assert(Result.PointerVal != 0 && "Null pointer returned by malloc!");
   SetValue(I, Result, SF);
 
-  if (I->getOpcode() == Instruction::Alloca) {
-    // TODO: FIXME: alloca should keep track of memory to free it later...
-  }
+  if (I->getOpcode() == Instruction::Alloca)
+    ECStack.back().Allocas.add(Memory);
 }
 
 static void executeFreeInst(FreeInst *I, ExecutionContext &SF) {
index 050b7d332d2f9038a75299675bb94725f18f1f4a..8576f9ce2257843ea3f51f346eeb0b29aa62aab2 100644 (file)
@@ -42,6 +42,36 @@ union GenericValue {
   PointerTy       PointerVal;
 };
 
+// AllocaHolder - Object to track all of the blocks of memory allocated by
+// alloca.  When the function returns, this object is poped off the execution
+// stack, which causes the dtor to be run, which frees all the alloca'd memory.
+//
+class AllocaHolder {
+  friend class AllocaHolderHandle;
+  std::vector<void*> Allocations;
+  unsigned RefCnt;
+public:
+  AllocaHolder() : RefCnt(0) {}
+  void add(void *mem) { Allocations.push_back(mem); }
+  ~AllocaHolder() {
+    for (unsigned i = 0; i < Allocations.size(); ++i)
+      free(Allocations[i]);
+  }
+};
+
+// AllocaHolderHandle gives AllocaHolder value semantics so we can stick it into
+// a vector...
+//
+class AllocaHolderHandle {
+  AllocaHolder *H;
+public:
+  AllocaHolderHandle() : H(new AllocaHolder()) { H->RefCnt++; }
+  AllocaHolderHandle(const AllocaHolderHandle &AH) : H(AH.H) { H->RefCnt++; }
+  ~AllocaHolderHandle() { if (--H->RefCnt == 0) delete H; }
+
+  void add(void *mem) { H->add(mem); }
+};
+
 typedef std::vector<GenericValue> ValuePlaneTy;
 
 // ExecutionContext struct - This struct represents one stack frame currently
@@ -57,6 +87,7 @@ struct ExecutionContext {
   BasicBlock           *PrevBB;     // The previous BB or null if in first BB
   CallInst             *Caller;     // Holds the call that called subframes.
                                     // NULL if main func or debugger invoked fn
+  AllocaHolderHandle    Allocas;    // Track memory allocated by alloca
 };
 
 // Interpreter - This class represents the entirety of the interpreter.