[llvm-commits] [poolalloc] r117015 - /poolalloc/trunk/lib/PoolAllocate/TransformFunctionBody.cpp

John Criswell criswell at uiuc.edu
Thu Oct 21 07:59:59 PDT 2010


Author: criswell
Date: Thu Oct 21 09:59:59 2010
New Revision: 117015

URL: http://llvm.org/viewvc/llvm-project?rev=117015&view=rev
Log:
Transform calloc() into poolcalloc().  This does two things:

1) It ensures that memset() is not called on a NULL pointer (in case the
allocation fails).

2) It fixes SAFECode run-time checks on calloc'ed memory (SAFECode assumes
that calloc() is transformed to poolcalloc() and that poolcalloc() does object
registration internall).

Modified:
    poolalloc/trunk/lib/PoolAllocate/TransformFunctionBody.cpp

Modified: poolalloc/trunk/lib/PoolAllocate/TransformFunctionBody.cpp
URL: http://llvm.org/viewvc/llvm-project/poolalloc/trunk/lib/PoolAllocate/TransformFunctionBody.cpp?rev=117015&r1=117014&r2=117015&view=diff
==============================================================================
--- poolalloc/trunk/lib/PoolAllocate/TransformFunctionBody.cpp (original)
+++ poolalloc/trunk/lib/PoolAllocate/TransformFunctionBody.cpp Thu Oct 21 09:59:59 2010
@@ -450,56 +450,82 @@
   TransformAllocationInstr(MI, AllocSize);
 }
 
+//
+// Method: visitCallocCall()
+//
+// Description:
+//  Transform a call to calloc() to use a pool-allocation version of calloc.
+//  We do this because pool_calloc() must check for a NULL return value before
+//  zeroing out the memory.
+//
+void
+FuncTransform::visitCallocCall (CallSite CS) {
+  //
+  // Ensure that the calloc call has the correct number of arugments.
+  //
+  assert(CS.arg_end()-CS.arg_begin() == 2 && "calloc takes two arguments!");
+
+  //
+  // Ensure that the new instruction has the same name as the old one.  This is
+  // done by removing the name of the old instruction.
+  //
+  Instruction * I = CS.getInstruction();
+  std::string Name = I->getName(); I->setName("");
 
-void FuncTransform::visitCallocCall(CallSite CS) {
-  TargetData& TD = PAInfo.getAnalysis<TargetData>();
-  const Type* Int8Type = Type::getInt8Ty(CS.getInstruction()->getContext());
   const Type* Int32Type = Type::getInt32Ty(CS.getInstruction()->getContext());
-  const Type* Int64Type = Type::getInt64Ty(CS.getInstruction()->getContext());
 
-  // FIXME: This transform is not correct; calloc does not zero the memory
-  //        if NULL is returned.
   // FIXME: Ensure that we use 32/64-bit object length sizes consistently
-  // FIXME: Rename 'useLong' to something more descriptive?
   // FIXME: Introduce 'ObjectAllocationSize' variable
   //        or similar instead of repeatedly using same expression
-  // XXX: Start new review session here ***
-  bool useLong = TD.getTypeAllocSize(PointerType::getUnqual(Int8Type)) != 4;
 
-  Module *M = CS.getInstruction()->getParent()->getParent()->getParent();
-  assert(CS.arg_end()-CS.arg_begin() == 2 && "calloc takes two arguments!");
   Value *V1 = CS.getArgument(0);
   Value *V2 = CS.getArgument(1);
-  if (V1->getType() != V2->getType()) {
-    V1 = CastInst::CreateZExtOrBitCast(V1, useLong ? Int64Type : Int32Type, V1->getName(), CS.getInstruction());
-    V2 = CastInst::CreateZExtOrBitCast(V2, useLong ? Int64Type : Int32Type, V2->getName(), CS.getInstruction());
-  }
-
-  V2 = BinaryOperator::Create(Instruction::Mul, V1, V2, "size",
-                              CS.getInstruction());
-  if (V2->getType() != (useLong ? Int64Type : Int32Type))
-    V2 = CastInst::CreateZExtOrBitCast(V2, useLong ? Int64Type : Int32Type, V2->getName(), CS.getInstruction());
-
-  BasicBlock::iterator BBI =
-    TransformAllocationInstr(CS.getInstruction(), V2);
-  Value *Ptr = BBI++;
-
-  // We just turned the call of 'calloc' into the equivalent of malloc.  To
-  // finish calloc, we need to zero out the memory.
-  Constant *MemSet =  M->getOrInsertFunction((useLong ? "llvm.memset.i64" : "llvm.memset.i32"),
-                                             Type::getVoidTy(M->getContext()),
-                                             PointerType::getUnqual(Int8Type),
-                                             Int8Type, (useLong ? Int64Type : Int32Type),
-                                             Int32Type, NULL);
-
-  if (Ptr->getType() != PointerType::getUnqual(Int8Type))
-    Ptr = CastInst::CreatePointerCast(Ptr, PointerType::getUnqual(Int8Type), Ptr->getName(),
-                       BBI);
-  
-  // We know that the memory returned by poolalloc is at least 4 byte aligned.
-  Value* Opts[4] = {Ptr, ConstantInt::get(Int8Type, 0),
-                    V2,  ConstantInt::get(Int32Type, 4)};
-  CallInst::Create(MemSet, Opts, Opts + 4, "", BBI);
+  V1 = CastInst::CreateIntegerCast(V1, Int32Type, false, V1->getName(), I);
+  V2 = CastInst::CreateIntegerCast(V2, Int32Type, false, V2->getName(), I);
+
+  // Get the pool handle--
+  // Do not change the instruction into a poolalloc() call unless we have a
+  // real pool descriptor
+  Value *PH = getPoolHandle(CS.getInstruction());
+  if (PH == 0 || isa<ConstantPointerNull>(PH))
+    return;
+
+  //
+  // Create call to poolcalloc, and record the use of the pool
+  //
+  Value* Opts[3] = {PH, V1, V2};
+  Instruction *V = CallInst::Create(PAInfo.PoolCalloc, Opts, Opts + 3, Name, I);
+  AddPoolUse(*V, PH, PoolUses);
+
+  // Cast to the appropriate type if necessary
+  // FIXME: Make use of "castTo" utility function
+  Instruction *Casted = V;
+  if (V->getType() != I->getType())
+    Casted = CastInst::CreatePointerCast(V, I->getType(), V->getName(), I);
+
+  // Update def-use info
+  I->replaceAllUsesWith(Casted);
+
+  // If we are modifying the original function, update the DSGraph.
+  if (!FI.Clone) {
+    // V and Casted now point to whatever the original allocation did.
+    G->getScalarMap().replaceScalar(I, V);
+    if (V != Casted)
+      G->getScalarMap()[Casted] = G->getScalarMap()[V];
+  } else {             // Otherwise, update the NewToOldValueMap
+    UpdateNewToOldValueMap(I, V, V != Casted ? Casted : 0);
+  }
+
+  // If this was an invoke, fix up the CFG.
+  if (InvokeInst *II = dyn_cast<InvokeInst>(I)) {
+    // FIXME: Assert out since we potentially don't handle "invoke" correctly
+    BranchInst::Create (II->getNormalDest(), I);
+    II->getUnwindDest()->removePredecessor(II->getParent(), true);
+  }
+
+  // Remove old allocation instruction.
+  I->eraseFromParent();
+  return;
 }
 
 





More information about the llvm-commits mailing list