[llvm-commits] [poolalloc] r114670 - in /poolalloc/trunk/lib/PoolAllocate: PoolAllocate.cpp TransformFunctionBody.cpp

John Criswell criswell at uiuc.edu
Thu Sep 23 10:29:44 PDT 2010


Author: criswell
Date: Thu Sep 23 12:29:43 2010
New Revision: 114670

URL: http://llvm.org/viewvc/llvm-project?rev=114670&view=rev
Log:
Added code to get automatic pool allocation to start playing nice with the new
SAFECode.
Have the poolalloc pass create a poolalloc_init() function because SAFECode
expects there to be one.
Have the poolalloc transform also correctly fill in pool handles into SAFECode
run-time checks.
Added a FIXME of something that needs to be fixed in order to work with
SAFECode correctly.

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

Modified: poolalloc/trunk/lib/PoolAllocate/PoolAllocate.cpp
URL: http://llvm.org/viewvc/llvm-project/poolalloc/trunk/lib/PoolAllocate/PoolAllocate.cpp?rev=114670&r1=114669&r2=114670&view=diff
==============================================================================
--- poolalloc/trunk/lib/PoolAllocate/PoolAllocate.cpp (original)
+++ poolalloc/trunk/lib/PoolAllocate/PoolAllocate.cpp Thu Sep 23 12:29:43 2010
@@ -82,6 +82,29 @@
 
 }
 
+static void
+createPoolAllocInit (Module & M) {
+  //
+  // Create the __poolalloc_init() function.
+  //
+  const Type * VoidType = Type::getVoidTy(M.getContext());
+  FunctionType * FTy = FunctionType::get(VoidType,
+                                         std::vector<const Type*>(),
+                                         false);
+  Function *InitFunc = Function::Create (FTy,
+                                         GlobalValue::ExternalLinkage,
+                                         "__poolalloc_init",
+                                         &M);
+
+  //
+  // Add an entry basic block that just returns.
+  //
+  BasicBlock * BB = BasicBlock::Create (M.getContext(), "entry", InitFunc);
+  ReturnInst::Create(M.getContext(), BB);
+
+  return;
+}
+
 void PoolAllocate::getAnalysisUsage(AnalysisUsage &AU) const {
   if (dsa_pass_to_use == PASS_EQTD) {
     AU.addRequiredTransitive<EQTDDataStructures>();
@@ -285,6 +308,12 @@
   }
 
   //
+  // Add an empty __poolalloc_init() function.  SAFECode will call this to
+  // intialize things; we don't make use of it with real pool allocation.
+  //
+  createPoolAllocInit (M);
+
+  //
   // FIXME: Make name more descriptive and explain, in a comment here, what this
   //        code is trying to do (namely, avoid optimizations for performance
   //        overhead measurements?).
@@ -1316,6 +1345,10 @@
       }
     }
 #else
+    //
+    // FIXME: This is not correct for SAFECode; all DSNodes will need to be
+    //        poolallocated.
+    //
     if ((N->isHeapNode()) || (BoundsChecksEnabled && (N->isArrayNode())) ||
     	(GlobalsGraphNodeMapping.count(N) &&
        GlobalsGraphNodeMapping[N].getNode()->isHeapNode())) {
@@ -1392,8 +1425,26 @@
 void PoolAllocate::CalculateLivePoolFreeBlocks(std::set<BasicBlock*>&LiveBlocks,
                                                Value *PD) {
   for (Value::use_iterator I = PD->use_begin(), E = PD->use_end(); I != E; ++I){
-    // The only users of the pool should be call & invoke instructions.
-    CallSite U = CallSite::get(*I);
+    //
+    // The only users of the pool should be call, invoke, and cast
+    // instructions.  We know that poolfree() and pooldestroy() do not need to
+    // cast pool handles, so if we see a non-call instruction, we know it's not
+    // used in a poolfree() or pooldestroy() call.
+    //
+    if (Instruction * Inst = dyn_cast<Instruction>(I)) {
+      if (!isa<CallInst>(*I)) {
+        // This block and every block that can reach this block must keep pool
+        // frees.
+        for (idf_ext_iterator<BasicBlock*, std::set<BasicBlock*> >
+               DI = idf_ext_begin(Inst->getParent(), LiveBlocks),
+               DE = idf_ext_end(Inst->getParent(), LiveBlocks);
+             DI != DE; ++DI)
+          /* empty */;
+        continue;
+      }
+    }
+
+    CallSite U = CallSite::get(I->stripPointerCasts());
     if (U.getCalledValue() != PoolFree && U.getCalledValue() != PoolDestroy) {
       // This block and every block that can reach this block must keep pool
       // frees.

Modified: poolalloc/trunk/lib/PoolAllocate/TransformFunctionBody.cpp
URL: http://llvm.org/viewvc/llvm-project/poolalloc/trunk/lib/PoolAllocate/TransformFunctionBody.cpp?rev=114670&r1=114669&r2=114670&view=diff
==============================================================================
--- poolalloc/trunk/lib/PoolAllocate/TransformFunctionBody.cpp (original)
+++ poolalloc/trunk/lib/PoolAllocate/TransformFunctionBody.cpp Thu Sep 23 12:29:43 2010
@@ -72,6 +72,7 @@
     void visitReallocCall(CallSite CS);
     void visitMemAlignCall(CallSite CS);
     void visitStrdupCall(CallSite CS);
+    void visitRuntimeCheck(CallSite CS);
     //void visitFreeInst(FreeInst &FI);
     void visitFreeCall(CallSite &CS);
     void visitCallSite(CallSite &CS);
@@ -137,6 +138,28 @@
   };
 }
 
+static inline Value *
+castTo (Value * V, const Type * Ty, std::string Name, Instruction * InsertPt) {
+  //
+  // Don't bother creating a cast if it's already the correct type.
+  //
+  if (V->getType() == Ty)
+    return V;
+
+  //
+  // If it's a constant, just create a constant expression.
+  //
+  if (Constant * C = dyn_cast<Constant>(V)) {
+    Constant * CE = ConstantExpr::getZExtOrBitCast (C, Ty);
+    return CE;
+  }
+
+  //
+  // Otherwise, insert a cast instruction.
+  //
+  return CastInst::CreateZExtOrBitCast (V, Ty, Name, InsertPt);
+}
+
 void
 PoolAllocate::TransformBody (DSGraph* g, PA::FuncInfo &fi,
                              std::multimap<AllocaInst*,Instruction*> &poolUses,
@@ -709,6 +732,40 @@
 }
 
 //
+// Method: visitRuntimeCheck()
+//
+// Description:
+//  Visit a call to a run-time check (or related function) and insert pool
+//  arguments where needed.
+//
+void
+FuncTransform::visitRuntimeCheck (CallSite CS) {
+  // A run-time check should have at least one argument for a pool
+  assert ((CS.arg_size() > 1) && "strdup takes one argument!");
+
+  //
+  // Get the pool handle for the pointer argument.
+  //
+  Value *PH = getPoolHandle(CS.getArgument(1)->stripPointerCasts());
+  //assert (PH && "Pool Handle for run-time checks is null!\n");
+
+  //
+  // Insert the pool handle into the run-time check.
+  //
+  if (PH) {
+    const Type * Int8Type  = Type::getInt8Ty(CS.getInstruction()->getContext());
+    const Type * VoidPtrTy = PointerType::getUnqual(Int8Type);
+    PH = castTo (PH, VoidPtrTy, PH->getName(), CS.getInstruction());
+    CS.setArgument (0, PH);
+
+    //
+    // Record that we've used the pool here.
+    //
+    AddPoolUse (*(CS.getInstruction()), PH, PoolUses);
+  }
+}
+
+//
 // Method: visitCallSite()
 //
 // Description:
@@ -780,6 +837,20 @@
     } else if (CF->getName() == "valloc") {
       errs() << "VALLOC USED BUT NOT HANDLED!\n";
       abort();
+    } else if ((CF->getName() == "sc.lscheck") ||
+               (CF->getName() == "sc.lscheckui") ||
+               (CF->getName() == "sc.lscheckalign") ||
+               (CF->getName() == "sc.lscheckalignui") ||
+               (CF->getName() == "sc.boundscheck") ||
+               (CF->getName() == "sc.boundscheckui") ||
+               (CF->getName() == "sc.pool_register_stack") ||
+               (CF->getName() == "sc.pool_unregister_stack") ||
+               (CF->getName() == "sc.pool_register_global") ||
+               (CF->getName() == "sc.pool_unregister_global") ||
+               (CF->getName() == "sc.pool_register") ||
+               (CF->getName() == "sc.pool_unregister") ||
+               (CF->getName() == "sc.get_actual_val")) {
+      visitRuntimeCheck (CS);
     } else if (CF->getName() == "pthread_create") {
       thread_creation_point = true;
 





More information about the llvm-commits mailing list