[llvm-commits] [poolalloc] r130962 - in /poolalloc/trunk: include/assistDS/TypeChecks.h lib/AssistDS/TypeChecks.cpp

Arushi Aggarwal aggarwa4 at illinois.edu
Thu May 5 15:38:31 PDT 2011


Author: aggarwa4
Date: Thu May  5 17:38:30 2011
New Revision: 130962

URL: http://llvm.org/viewvc/llvm-project?rev=130962&view=rev
Log:
Updated handling of byval arguments, to take care
of both internal/external functions, correctly.

Detailed comments inline.

Olden/bh now works.

Modified:
    poolalloc/trunk/include/assistDS/TypeChecks.h
    poolalloc/trunk/lib/AssistDS/TypeChecks.cpp

Modified: poolalloc/trunk/include/assistDS/TypeChecks.h
URL: http://llvm.org/viewvc/llvm-project/poolalloc/trunk/include/assistDS/TypeChecks.h?rev=130962&r1=130961&r2=130962&view=diff
==============================================================================
--- poolalloc/trunk/include/assistDS/TypeChecks.h (original)
+++ poolalloc/trunk/include/assistDS/TypeChecks.h Thu May  5 17:38:30 2011
@@ -59,6 +59,9 @@
   bool visitCallInst(Module &M, CallInst &CI);
   bool visitInvokeInst(Module &M, InvokeInst &CI);
   bool visitCallSite(Module &M, CallSite CS);
+  bool visitInternalFunction(Module &M, Function &F); 
+  bool visitExternalFunction(Module &M, Function &F); 
+  bool visitByValFunction(Module &M, Function &F); 
   bool visitLoadInst(Module &M, LoadInst &LI);
   bool visitStoreInst(Module &M, StoreInst &SI);
   bool visitGlobal(Module &M, GlobalVariable &GV, 

Modified: poolalloc/trunk/lib/AssistDS/TypeChecks.cpp
URL: http://llvm.org/viewvc/llvm-project/poolalloc/trunk/lib/AssistDS/TypeChecks.cpp?rev=130962&r1=130961&r2=130962&view=diff
==============================================================================
--- poolalloc/trunk/lib/AssistDS/TypeChecks.cpp (original)
+++ poolalloc/trunk/lib/AssistDS/TypeChecks.cpp Thu May  5 17:38:30 2011
@@ -13,6 +13,7 @@
 
 #include "assistDS/TypeChecks.h"
 #include "llvm/Constants.h"
+#include "llvm/Transforms/Utils/Cloning.h"
 #include "llvm/DerivedTypes.h"
 #include "llvm/Module.h"
 #include "llvm/Assembly/Writer.h"
@@ -108,9 +109,11 @@
     modified |= visitGlobal(M, *I, I->getInitializer(), *MainI, 0);
   }
 
+  std::vector<Function *> toProcess;
   for (Module::iterator MI = M.begin(), ME = M.end(); MI != ME; ++MI) {
     IncorporateType(MI->getType());
     Function &F = *MI;
+    toProcess.push_back(&F);
 
     // Loop over all of the instructions in the function, 
     // adding their return type as well as the types of their operands.
@@ -138,7 +141,6 @@
       } else if (CallInst *CI = dyn_cast<CallInst>(&I)) {
         modified |= visitCallInst(M, *CI);
       } else if (InvokeInst *II = dyn_cast<InvokeInst>(&I)) {
-        II->dump();
         modified |= visitInvokeInst(M, *II);
       }
     }
@@ -146,70 +148,259 @@
 
   // Record types for byval arguments.
 
-  // Split fn into 2 clones. One internal, such that
-  // we can find all call sites to it, and also pass in the
-  // original ptr/metadata.
-  // One that sets it just to initialized memory
-  // so that it can be called from external code.
-  for (Module::iterator MI = M.begin(), ME = M.end(); MI != ME; ++MI) {
-    Function &F = *MI;
-    typedef SmallVector<Value *, 4> RegisteredArgTy;
-    RegisteredArgTy registeredArguments;
-    for (Function::arg_iterator I = F.arg_begin(), E = F.arg_end(); I != E; ++I) {
-      if (I->hasByValAttr()) {
-        assert (isa<PointerType>(I->getType()));
-        const PointerType * PT = cast<PointerType>(I->getType());
-        const Type * ET = PT->getElementType();
-        Value * AllocSize = ConstantInt::get(Int64Ty, TD->getTypeAllocSize(ET));
-        Instruction * InsertBefore = &(F.getEntryBlock().front());
-        CastInst *BCI = BitCastInst::CreatePointerCast(I, VoidPtrTy, "", InsertBefore);
-        std::vector<Value *> Args;
-        Args.push_back(BCI);
-        Args.push_back(AllocSize);
-        Args.push_back(ConstantInt::get(Int32Ty, tagCounter++));
-        Constant *F = M.getOrInsertFunction("trackInitInst", VoidTy, VoidPtrTy, Int64Ty, Int32Ty, NULL);
-        CallInst::Create(F, Args.begin(), Args.end(), "", InsertBefore);
-        registeredArguments.push_back(&*I);
-      }
+  while(!toProcess.empty()) {
+    Function *F = toProcess.back();
+    toProcess.pop_back();
+    if(F->isDeclaration())
+      continue;
+    modified |= visitByValFunction(M, *F);
+  }
+
+  return modified;
+}
+
+bool
+TypeChecks::visitByValFunction(Module &M, Function &F) {
+
+  bool hasByValArg = false;
+  for (Function::arg_iterator I = F.arg_begin(), E = F.arg_end(); I != E; ++I) {
+    if (I->hasByValAttr()) {
+      hasByValArg = true;
+      break;
     }
-    //
-    // Find all basic blocks which terminate the function.
-    //
-    std::set<BasicBlock *> exitBlocks;
-    for (inst_iterator I = inst_begin(&F), E = inst_end(&F); I != E; ++I) {
-      if (isa<ReturnInst>(*I) || isa<UnwindInst>(*I)) {
-        exitBlocks.insert(I->getParent());
-      }
+  }
+  if(!hasByValArg)
+    return false;
+
+  // For internal functions
+  //   Replace with a cloned function with extra arguments
+  //   That takes as argument the original pointers without a byval parameter too
+  //   Use them to copy the metadata over to the byval arguments
+  //   Also update all the call sites.
+
+  // For external functions
+  //  Create an internal clone (treated same as internal functions)
+  //  Modify the original function
+  //  To assume that the metadata for the byval arguments is TOP 
+  
+  if(F.hasInternalLinkage()) {
+    visitInternalFunction(M, F);
+  } else {
+    // create internal clone
+    Function *F_clone = CloneFunction(&F);
+    F_clone->setName(F.getNameStr() + "internal");
+    F.setLinkage(GlobalValue::InternalLinkage);
+    F.getParent()->getFunctionList().push_back(F_clone);
+    visitInternalFunction(M, *F_clone);
+    visitExternalFunction(M, F);
+  }
+  return true;
+}
+
+bool TypeChecks::visitInternalFunction(Module &M, Function &F) {
+
+  // Create a list of the argument types in the new function.
+  std::vector<const Type*>TP;
+  for (Function::arg_iterator I = F.arg_begin(), E = F.arg_end(); I != E; ++I) {
+    TP.push_back(I->getType());
+    // for every byval argument, add a new argument that indicates the source of
+    // the metadata. It is of the same type as the byval argument.
+    if (I->hasByValAttr())
+      TP.push_back(I->getType());
+  }
+  // Create the new function prototype
+  const FunctionType *NewFTy = FunctionType::get(F.getReturnType(), TP, false);
+  Function *NewF = Function::Create(NewFTy,
+                                    GlobalValue::InternalLinkage,
+                                    F.getNameStr() + ".INT",
+                                    &M);
+
+  Function::arg_iterator NI = NewF->arg_begin();
+  DenseMap<const Value*, Value*> ValueMap;
+  for (Function::arg_iterator II = F.arg_begin(); NI != NewF->arg_end(); ++II, ++NI) {
+    // Each new argument maps to the argument in the old function
+    // For these arguments, also copy over the attributes
+    ValueMap[II] = NI;
+    NI->setName(II->getName());
+    NI->addAttr(F.getAttributes().getParamAttributes(II->getArgNo() + 1));
+    // If we have encountered a byval argument in the old function
+    // We must skip over the next argument in the new function, as that is 
+    // the newly added source argument.
+    if(II->hasByValAttr()) {
+      NI++;
+      // Give this new argument some name, for clarity
+      NI->setName("src");
+    }
+  }
+  // Copy over the attributes for the function.
+  NewF->setAttributes(NewF->getAttributes()
+                      .addAttr(0, F.getAttributes().getRetAttributes()));
+  NewF->setAttributes(NewF->getAttributes().addAttr(~0, F.getAttributes().getFnAttributes()));
+
+  // Perform the cloning.
+  SmallVector<ReturnInst*,100> Returns;
+  CloneFunctionInto(NewF, &F, ValueMap, Returns);
+ 
+  // Add calls to the runtime to copy metadata from source to the byval argument pointer. 
+  typedef SmallVector<Value *, 4> RegisteredArgTy;
+  // Keep track of the byval arguments.
+  RegisteredArgTy registeredArguments;
+  for (Function::arg_iterator I = NewF->arg_begin(), E = NewF->arg_end(); I != E; ++I) {
+    if (I->hasByValAttr()) {
+      registeredArguments.push_back(&*I);
+      assert (isa<PointerType>(I->getType()));
+      const PointerType * PT = cast<PointerType>(I->getType());
+      const Type * ET = PT->getElementType();
+      Value * AllocSize = ConstantInt::get(Int64Ty, TD->getTypeAllocSize(ET));
+      Instruction * InsertBefore = &(NewF->getEntryBlock().front());
+      // If I is the byval argument, the next argument is the source
+      CastInst *BCI_Dest = BitCastInst::CreatePointerCast(I, VoidPtrTy, "", InsertBefore);
+      CastInst *BCI_Src = BitCastInst::CreatePointerCast(++I, VoidPtrTy, "", InsertBefore);
+      std::vector<Value *> Args;
+      Args.push_back(BCI_Dest);
+      Args.push_back(BCI_Src);
+      Args.push_back(AllocSize);
+      Args.push_back(ConstantInt::get(Int32Ty, tagCounter++));
+      Constant *F = M.getOrInsertFunction("copyTypeInfo", VoidTy, VoidPtrTy, VoidPtrTy, Int64Ty, Int32Ty, NULL);
+      CallInst::Create(F, Args.begin(), Args.end(), "", InsertBefore);
+    }
+  }
+  
+  // Find all basic blocks which terminate the function.
+  std::set<BasicBlock *> exitBlocks;
+  for (inst_iterator I = inst_begin(NewF), E = inst_end(NewF); I != E; ++I) {
+    if (isa<ReturnInst>(*I) || isa<UnwindInst>(*I)) {
+      exitBlocks.insert(I->getParent());
     }
+  }
 
-    //
-    // At each function exit, insert code to deregister all byval arguments.
-    //
-    for (std::set<BasicBlock*>::const_iterator BI = exitBlocks.begin(),
-         BE = exitBlocks.end();
-         BI != BE; ++BI) {
-      for (RegisteredArgTy::const_iterator I = registeredArguments.begin(),
-           E = registeredArguments.end();
-           I != E; ++I) {
-        SmallVector<Value *, 2> args;
-        Instruction * Pt = &((*BI)->back());
-        const PointerType * PT = cast<PointerType>((*I)->getType());
-        const Type * ET = PT->getElementType();
-        Value * AllocSize = ConstantInt::get(Int64Ty, TD->getTypeAllocSize(ET));
-        CastInst *BCI = BitCastInst::CreatePointerCast(*I, VoidPtrTy, "", Pt);
-        std::vector<Value *> Args;
-        Args.push_back(BCI);
-        Args.push_back(AllocSize);
-        Args.push_back(ConstantInt::get(Int32Ty, tagCounter++));
-        Constant *F = M.getOrInsertFunction("trackUnInitInst", VoidTy, VoidPtrTy, Int64Ty, Int32Ty, NULL);
-        CallInst::Create(F, Args.begin(), Args.end(), "", Pt);
-      }
+  // At each function exit, insert code to set the metadata as uninitialized.
+  for (std::set<BasicBlock*>::const_iterator BI = exitBlocks.begin(),
+       BE = exitBlocks.end();
+       BI != BE; ++BI) {
+    for (RegisteredArgTy::const_iterator I = registeredArguments.begin(),
+         E = registeredArguments.end();
+         I != E; ++I) {
+      SmallVector<Value *, 2> args;
+      Instruction * Pt = &((*BI)->back());
+      const PointerType * PT = cast<PointerType>((*I)->getType());
+      const Type * ET = PT->getElementType();
+      Value * AllocSize = ConstantInt::get(Int64Ty, TD->getTypeAllocSize(ET));
+      CastInst *BCI = BitCastInst::CreatePointerCast(*I, VoidPtrTy, "", Pt);
+      std::vector<Value *> Args;
+      Args.push_back(BCI);
+      Args.push_back(AllocSize);
+      Args.push_back(ConstantInt::get(Int32Ty, tagCounter++));
+      Constant *F = M.getOrInsertFunction("trackUnInitInst", VoidTy, VoidPtrTy, Int64Ty, Int32Ty, NULL);
+      CallInst::Create(F, Args.begin(), Args.end(), "", Pt);
     }
   }
 
-  return modified;
+  // Update the call sites
+  for(Value::use_iterator ui = F.use_begin(), ue = F.use_end();
+      ui != ue;)  {
+    // Check that F is the called value
+    if(CallInst *CI = dyn_cast<CallInst>(ui++)) {
+      if(CI->getCalledFunction() == &F) {
+        SmallVector<Value*, 8> Args;
+        SmallVector<AttributeWithIndex, 8> AttributesVec;
+
+        // Get the initial attributes of the call
+        AttrListPtr CallPAL = CI->getAttributes();
+        Attributes RAttrs = CallPAL.getRetAttributes();
+        Attributes FnAttrs = CallPAL.getFnAttributes();
+        
+        Function::arg_iterator II = F.arg_begin();
+
+        for(unsigned j =1;j<CI->getNumOperands();j++, II++) {
+          // Add the original argument
+          Args.push_back(CI->getOperand(j));
+          // If there are attributes on this argument, copy them to the correct 
+          // position in the AttributesVec
+          if (Attributes Attrs = CallPAL.getParamAttributes(j))
+            AttributesVec.push_back(AttributeWithIndex::get(Args.size(), Attrs));
+          // If it is a value passed as byval, add it again, as the source
+          if(II->hasByValAttr()) 
+            Args.push_back(CI->getOperand(j));
+        }
+        
+        // Create the new attributes vec.
+        if (FnAttrs != Attribute::None)
+          AttributesVec.push_back(AttributeWithIndex::get(~0, FnAttrs));
+        if (RAttrs)
+          AttributesVec.push_back(AttributeWithIndex::get(0, RAttrs));
+
+        AttrListPtr NewCallPAL = AttrListPtr::get(AttributesVec.begin(),
+                                                  AttributesVec.end());
+
+
+        // Create the substitute call
+        CallInst *CallI = CallInst::Create(NewF,Args.begin(), Args.end(),"", CI);
+        CallI->setCallingConv(CI->getCallingConv());
+        CallI->setAttributes(NewCallPAL);
+        CI->replaceAllUsesWith(CallI);
+        CI->eraseFromParent();
+      }
+    }
+  }
+  return true;
 }
 
+bool TypeChecks::visitExternalFunction(Module &M, Function &F) {
+
+  // A list of the byval arguments that we are setting metadata for
+  typedef SmallVector<Value *, 4> RegisteredArgTy;
+  RegisteredArgTy registeredArguments;
+  for (Function::arg_iterator I = F.arg_begin(), E = F.arg_end(); I != E; ++I) {
+    if (I->hasByValAttr()) {
+      assert (isa<PointerType>(I->getType()));
+      const PointerType * PT = cast<PointerType>(I->getType());
+      const Type * ET = PT->getElementType();
+      Value * AllocSize = ConstantInt::get(Int64Ty, TD->getTypeAllocSize(ET));
+      Instruction * InsertBefore = &(F.getEntryBlock().front());
+      CastInst *BCI = BitCastInst::CreatePointerCast(I, VoidPtrTy, "", InsertBefore);
+      std::vector<Value *> Args;
+      Args.push_back(BCI);
+      Args.push_back(AllocSize);
+      Args.push_back(ConstantInt::get(Int32Ty, tagCounter++));
+      // Set the metadata for the byval argument to TOP/Initialized
+      Constant *F = M.getOrInsertFunction("trackInitInst", VoidTy, VoidPtrTy, Int64Ty, Int32Ty, NULL);
+      CallInst::Create(F, Args.begin(), Args.end(), "", InsertBefore);
+      registeredArguments.push_back(&*I);
+    }
+  }
+  
+  // Find all basic blocks which terminate the function.
+  std::set<BasicBlock *> exitBlocks;
+  for (inst_iterator I = inst_begin(&F), E = inst_end(&F); I != E; ++I) {
+    if (isa<ReturnInst>(*I) || isa<UnwindInst>(*I)) {
+      exitBlocks.insert(I->getParent());
+    }
+  }
+
+  // At each function exit, insert code to set the metadata as uninitialized.
+  for (std::set<BasicBlock*>::const_iterator BI = exitBlocks.begin(),
+       BE = exitBlocks.end();
+       BI != BE; ++BI) {
+    for (RegisteredArgTy::const_iterator I = registeredArguments.begin(),
+         E = registeredArguments.end();
+         I != E; ++I) {
+      SmallVector<Value *, 2> args;
+      Instruction * Pt = &((*BI)->back());
+      const PointerType * PT = cast<PointerType>((*I)->getType());
+      const Type * ET = PT->getElementType();
+      Value * AllocSize = ConstantInt::get(Int64Ty, TD->getTypeAllocSize(ET));
+      CastInst *BCI = BitCastInst::CreatePointerCast(*I, VoidPtrTy, "", Pt);
+      std::vector<Value *> Args;
+      Args.push_back(BCI);
+      Args.push_back(AllocSize);
+      Args.push_back(ConstantInt::get(Int32Ty, tagCounter++));
+      Constant *F = M.getOrInsertFunction("trackUnInitInst", VoidTy, VoidPtrTy, Int64Ty, Int32Ty, NULL);
+      CallInst::Create(F, Args.begin(), Args.end(), "", Pt);
+    }
+  }
+  return true;
+}
 // Print the types found in the module. If the optional Module parameter is
 // passed in, then the types are printed symbolically if possible, using the
 // symbol table from the module.





More information about the llvm-commits mailing list