diff options
Diffstat (limited to 'llvm')
| -rw-r--r-- | llvm/lib/Transforms/IPO/RaiseAllocations.cpp | 129 | 
1 files changed, 75 insertions, 54 deletions
| diff --git a/llvm/lib/Transforms/IPO/RaiseAllocations.cpp b/llvm/lib/Transforms/IPO/RaiseAllocations.cpp index a1ad2c2918f..62355be8780 100644 --- a/llvm/lib/Transforms/IPO/RaiseAllocations.cpp +++ b/llvm/lib/Transforms/IPO/RaiseAllocations.cpp @@ -5,13 +5,13 @@  //  //===----------------------------------------------------------------------===// -#include "llvm/Transforms/Scalar.h" -#include "llvm/Transforms/Utils/BasicBlockUtils.h" +#include "llvm/Transforms/IPO.h"  #include "llvm/Module.h"  #include "llvm/DerivedTypes.h"  #include "llvm/iMemory.h"  #include "llvm/iOther.h"  #include "llvm/Pass.h" +#include "llvm/Support/CallSite.h"  #include "Support/Statistic.h"  namespace { @@ -20,7 +20,7 @@ namespace {    // RaiseAllocations - Turn %malloc and %free calls into the appropriate    // instruction.    // -  class RaiseAllocations : public BasicBlockPass { +  class RaiseAllocations : public Pass {      Function *MallocFunc;   // Functions in the module we are processing      Function *FreeFunc;     // Initialized by doPassInitializationVirt    public: @@ -29,12 +29,11 @@ namespace {      // doPassInitialization - For the raise allocations pass, this finds a      // declaration for malloc and free if they exist.      // -    bool doInitialization(Module &M); +    void doInitialization(Module &M); -    // runOnBasicBlock - This method does the actual work of converting -    // instructions over, assuming that the pass has already been initialized. +    // run - This method does the actual work of converting instructions over.      // -    bool runOnBasicBlock(BasicBlock &BB); +    bool run(Module &M);    };    RegisterOpt<RaiseAllocations> @@ -48,15 +47,15 @@ Pass *createRaiseAllocationsPass() {  } -bool RaiseAllocations::doInitialization(Module &M) { -  // If the module has a symbol table, they might be referring to the malloc -  // and free functions.  If this is the case, grab the method pointers that  -  // the module is using. -  // -  // Lookup %malloc and %free in the symbol table, for later use.  If they -  // don't exist, or are not external, we do not worry about converting calls -  // to that function into the appropriate instruction. -  // +// If the module has a symbol table, they might be referring to the malloc and +// free functions.  If this is the case, grab the method pointers that the +// module is using. +// +// Lookup %malloc and %free in the symbol table, for later use.  If they don't +// exist, or are not external, we do not worry about converting calls to that +// function into the appropriate instruction. +// +void RaiseAllocations::doInitialization(Module &M) {    const FunctionType *MallocType =   // Get the type for malloc      FunctionType::get(PointerType::get(Type::SByteTy),                      std::vector<const Type*>(1, Type::ULongTy), false); @@ -100,52 +99,74 @@ bool RaiseAllocations::doInitialization(Module &M) {      FreeFunc = M.getFunction("free", FreeType);    } -    // Don't mess with locally defined versions of these functions...    if (MallocFunc && !MallocFunc->isExternal()) MallocFunc = 0;    if (FreeFunc && !FreeFunc->isExternal())     FreeFunc = 0; -  return false;  } -// runOnBasicBlock - Process a basic block, fixing it up... +// run - Transform calls into instructions...  // -bool RaiseAllocations::runOnBasicBlock(BasicBlock &BB) { +bool RaiseAllocations::run(Module &M) { +  // Find the malloc/free prototypes... +  doInitialization(M); +    bool Changed = false; -  BasicBlock::InstListType &BIL = BB.getInstList(); - -  for (BasicBlock::iterator BI = BB.begin(); BI != BB.end(); ++BI) { -    Instruction *I = BI; - -    if (CallInst *CI = dyn_cast<CallInst>(I)) { -      if (CI->getCalledValue() == MallocFunc) {      // Replace call to malloc? -        Value *Source = CI->getOperand(1); -         -        // If no prototype was provided for malloc, we may need to cast the -        // source size. -        if (Source->getType() != Type::UIntTy) -          Source = new CastInst(Source, Type::UIntTy, "MallocAmtCast", BI); - -        std::string Name(CI->getName()); CI->setName(""); -        BI = new MallocInst(Type::SByteTy, Source, Name, BI); -        CI->replaceAllUsesWith(BI); -        BIL.erase(I); -        Changed = true; -        ++NumRaised; -      } else if (CI->getCalledValue() == FreeFunc) { // Replace call to free? -        // If no prototype was provided for free, we may need to cast the -        // source pointer.  This should be really uncommon, but it's necessary -        // just in case we are dealing with wierd code like this: -        //   free((long)ptr); -        // -        Value *Source = CI->getOperand(1); -        if (!isa<PointerType>(Source->getType())) -          Source = new CastInst(Source, PointerType::get(Type::SByteTy), -                                "FreePtrCast", BI); -        BI = new FreeInst(Source, BI); -        BIL.erase(I); -        Changed = true; -        ++NumRaised; + +  // First, process all of the malloc calls... +  if (MallocFunc) { +    std::vector<User*> Users(MallocFunc->use_begin(), MallocFunc->use_end()); +    while (!Users.empty()) { +      if (Instruction *I = dyn_cast<Instruction>(Users.back())) { +        CallSite CS = CallSite::get(I); +        if (CS.getInstruction() && CS.getCalledFunction() == MallocFunc && +            CS.arg_begin() != CS.arg_end()) { +          Value *Source = *CS.arg_begin(); +           +          // If no prototype was provided for malloc, we may need to cast the +          // source size. +          if (Source->getType() != Type::UIntTy) +            Source = new CastInst(Source, Type::UIntTy, "MallocAmtCast", I); +           +          std::string Name(I->getName()); I->setName(""); +          MallocInst *MI = new MallocInst(Type::SByteTy, Source, Name, I); +          I->replaceAllUsesWith(MI); +          MI->getParent()->getInstList().erase(I); +          Changed = true; +          ++NumRaised; +        } +      } + +      Users.pop_back(); +    } +  } + +  // Next, process all free calls... +  if (FreeFunc) { +    std::vector<User*> Users(FreeFunc->use_begin(), FreeFunc->use_end()); + +    while (!Users.empty()) { +      if (Instruction *I = dyn_cast<Instruction>(Users.back())) { +        CallSite CS = CallSite::get(I); +        if (CS.getInstruction() && CS.getCalledFunction() == FreeFunc && +            CS.arg_begin() != CS.arg_end()) { +           +          // If no prototype was provided for free, we may need to cast the +          // source pointer.  This should be really uncommon, but it's necessary +          // just in case we are dealing with wierd code like this: +          //   free((long)ptr); +          // +          Value *Source = *CS.arg_begin(); +          if (!isa<PointerType>(Source->getType())) +            Source = new CastInst(Source, PointerType::get(Type::SByteTy), +                                  "FreePtrCast", I); +          new FreeInst(Source, I); +          I->getParent()->getInstList().erase(I); +          Changed = true; +          ++NumRaised; +        }        } +       +      Users.pop_back();      }    } | 

