For PR387:\
[oota-llvm.git] / lib / Transforms / Utils / LowerAllocations.cpp
1 //===- LowerAllocations.cpp - Reduce malloc & free insts to calls ---------===//
2 // 
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file was developed by the LLVM research group and is distributed under
6 // the University of Illinois Open Source License. See LICENSE.TXT for details.
7 // 
8 //===----------------------------------------------------------------------===//
9 //
10 // The LowerAllocations transformation is a target-dependent tranformation
11 // because it depends on the size of data types and alignment constraints.
12 //
13 //===----------------------------------------------------------------------===//
14
15 #include "llvm/Transforms/Scalar.h"
16 #include "llvm/Module.h"
17 #include "llvm/DerivedTypes.h"
18 #include "llvm/Instructions.h"
19 #include "llvm/Constants.h"
20 #include "llvm/Pass.h"
21 #include "llvm/ADT/Statistic.h"
22 using namespace llvm;
23
24 namespace {
25   Statistic<> NumLowered("lowerallocs", "Number of allocations lowered");
26
27   /// LowerAllocations - Turn malloc and free instructions into %malloc and
28   /// %free calls.
29   ///
30   class LowerAllocations : public BasicBlockPass {
31     Function *MallocFunc;   // Functions in the module we are processing
32     Function *FreeFunc;     // Initialized by doInitialization
33   public:
34     LowerAllocations() : MallocFunc(0), FreeFunc(0) {}
35
36     /// doPassInitialization - For the lower allocations pass, this ensures that
37     /// a module contains a declaration for a malloc and a free function.
38     ///
39     bool doInitialization(Module &M);
40
41     virtual bool doInitialization(Function&f) 
42       { return BasicBlockPass::doInitialization(f); }
43     
44     /// runOnBasicBlock - This method does the actual work of converting
45     /// instructions over, assuming that the pass has already been initialized.
46     ///
47     bool runOnBasicBlock(BasicBlock &BB);
48   };
49
50   RegisterOpt<LowerAllocations>
51   X("lowerallocs", "Lower allocations from instructions to calls");
52 }
53
54 // createLowerAllocationsPass - Interface to this file...
55 FunctionPass *llvm::createLowerAllocationsPass() {
56   return new LowerAllocations();
57 }
58
59
60 // doInitialization - For the lower allocations pass, this ensures that a
61 // module contains a declaration for a malloc and a free function.
62 //
63 // This function is always successful.
64 //
65 bool LowerAllocations::doInitialization(Module &M) {
66   const Type *SBPTy = PointerType::get(Type::SByteTy);
67   MallocFunc = M.getNamedFunction("malloc");
68   FreeFunc   = M.getNamedFunction("free");
69
70   if (MallocFunc == 0)
71     MallocFunc = M.getOrInsertFunction("malloc", SBPTy, Type::UIntTy, 0);
72   if (FreeFunc == 0)
73     FreeFunc   = M.getOrInsertFunction("free"  , Type::VoidTy, SBPTy, 0);
74
75   return true;
76 }
77
78 static Constant *getSizeof(const Type *Ty) {
79   Constant *Ret = ConstantPointerNull::get(PointerType::get(Ty));
80   std::vector<Constant*> Idx;
81   Idx.push_back(ConstantUInt::get(Type::UIntTy, 1));
82   Ret = ConstantExpr::getGetElementPtr(Ret, Idx);
83   return ConstantExpr::getCast(Ret, Type::UIntTy);
84 }
85
86 // runOnBasicBlock - This method does the actual work of converting
87 // instructions over, assuming that the pass has already been initialized.
88 //
89 bool LowerAllocations::runOnBasicBlock(BasicBlock &BB) {
90   bool Changed = false;
91   assert(MallocFunc && FreeFunc && "Pass not initialized!");
92
93   BasicBlock::InstListType &BBIL = BB.getInstList();
94
95   // Loop over all of the instructions, looking for malloc or free instructions
96   for (BasicBlock::iterator I = BB.begin(), E = BB.end(); I != E; ++I) {
97     if (MallocInst *MI = dyn_cast<MallocInst>(I)) {
98       const Type *AllocTy = MI->getType()->getElementType();
99       
100       // malloc(type) becomes sbyte *malloc(size)
101       Value *MallocArg = getSizeof(AllocTy);
102       if (MI->isArrayAllocation()) {
103         if (isa<ConstantUInt>(MallocArg) &&
104             cast<ConstantUInt>(MallocArg)->getValue() == 1) {
105           MallocArg = MI->getOperand(0);         // Operand * 1 = Operand
106         } else if (Constant *CO = dyn_cast<Constant>(MI->getOperand(0))) {
107           MallocArg = ConstantExpr::getMul(CO, cast<Constant>(MallocArg));
108         } else {
109           // Multiply it by the array size if necessary...
110           MallocArg = BinaryOperator::create(Instruction::Mul,
111                                              MI->getOperand(0),
112                                              MallocArg, "", I);
113         }
114       }
115
116       const FunctionType *MallocFTy = MallocFunc->getFunctionType();
117       std::vector<Value*> MallocArgs;
118       
119       if (MallocFTy->getNumParams() > 0 || MallocFTy->isVarArg()) {
120         if (MallocFTy->getNumParams() > 0 &&
121             MallocFTy->getParamType(0) != Type::UIntTy)
122           MallocArg = new CastInst(MallocArg, MallocFTy->getParamType(0), "",I);
123         MallocArgs.push_back(MallocArg);
124       }
125
126       // If malloc is prototyped to take extra arguments, pass nulls.
127       for (unsigned i = 1; i < MallocFTy->getNumParams(); ++i)
128        MallocArgs.push_back(Constant::getNullValue(MallocFTy->getParamType(i)));
129
130       // Create the call to Malloc...
131       CallInst *MCall = new CallInst(MallocFunc, MallocArgs, "", I);
132       
133       // Create a cast instruction to convert to the right type...
134       Value *MCast;
135       if (MCall->getType() != Type::VoidTy)
136         MCast = new CastInst(MCall, MI->getType(), "", I);
137       else
138         MCast = Constant::getNullValue(MI->getType());
139       
140       // Replace all uses of the old malloc inst with the cast inst
141       MI->replaceAllUsesWith(MCast);
142       I = --BBIL.erase(I);         // remove and delete the malloc instr...
143       Changed = true;
144       ++NumLowered;
145     } else if (FreeInst *FI = dyn_cast<FreeInst>(I)) {
146       const FunctionType *FreeFTy = FreeFunc->getFunctionType();
147       std::vector<Value*> FreeArgs;
148       
149       if (FreeFTy->getNumParams() > 0 || FreeFTy->isVarArg()) {
150         Value *MCast = FI->getOperand(0);
151         if (FreeFTy->getNumParams() > 0 &&
152             FreeFTy->getParamType(0) != MCast->getType())
153           MCast = new CastInst(MCast, FreeFTy->getParamType(0), "", I);
154         FreeArgs.push_back(MCast);
155       }
156
157       // If malloc is prototyped to take extra arguments, pass nulls.
158       for (unsigned i = 1; i < FreeFTy->getNumParams(); ++i)
159        FreeArgs.push_back(Constant::getNullValue(FreeFTy->getParamType(i)));
160       
161       // Insert a call to the free function...
162       new CallInst(FreeFunc, FreeArgs, "", I);
163       
164       // Delete the old free instruction
165       I = --BBIL.erase(I);
166       Changed = true;
167       ++NumLowered;
168     }
169   }
170
171   return Changed;
172 }
173