if there is already a prototype for malloc/free, use it, even if it's incorrect.
[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/iMemory.h"
19 #include "llvm/iOther.h"
20 #include "llvm/Constants.h"
21 #include "llvm/Pass.h"
22 #include "llvm/Target/TargetData.h"
23 #include "Support/Statistic.h"
24 using namespace llvm;
25
26 namespace {
27   Statistic<> NumLowered("lowerallocs", "Number of allocations lowered");
28
29   /// LowerAllocations - Turn malloc and free instructions into %malloc and
30   /// %free calls.
31   ///
32   class LowerAllocations : public BasicBlockPass {
33     Function *MallocFunc;   // Functions in the module we are processing
34     Function *FreeFunc;     // Initialized by doInitialization
35   public:
36     LowerAllocations() : MallocFunc(0), FreeFunc(0) {}
37
38     virtual void getAnalysisUsage(AnalysisUsage &AU) const {
39       AU.addRequired<TargetData>();
40     }
41
42     /// doPassInitialization - For the lower allocations pass, this ensures that
43     /// a module contains a declaration for a malloc and a free function.
44     ///
45     bool doInitialization(Module &M);
46     
47     /// runOnBasicBlock - This method does the actual work of converting
48     /// instructions over, assuming that the pass has already been initialized.
49     ///
50     bool runOnBasicBlock(BasicBlock &BB);
51   };
52
53   RegisterOpt<LowerAllocations>
54   X("lowerallocs", "Lower allocations from instructions to calls");
55 }
56
57 // createLowerAllocationsPass - Interface to this file...
58 FunctionPass *llvm::createLowerAllocationsPass() {
59   return new LowerAllocations();
60 }
61
62
63 // doInitialization - For the lower allocations pass, this ensures that a
64 // module contains a declaration for a malloc and a free function.
65 //
66 // This function is always successful.
67 //
68 bool LowerAllocations::doInitialization(Module &M) {
69   const Type *SBPTy = PointerType::get(Type::SByteTy);
70   MallocFunc = M.getNamedFunction("malloc");
71   FreeFunc   = M.getNamedFunction("free");
72
73   if (MallocFunc == 0)
74     MallocFunc = M.getOrInsertFunction("malloc", SBPTy, Type::UIntTy, 0);
75   if (FreeFunc == 0)
76     FreeFunc   = M.getOrInsertFunction("free"  , Type::VoidTy, SBPTy, 0);
77
78   return true;
79 }
80
81 // runOnBasicBlock - This method does the actual work of converting
82 // instructions over, assuming that the pass has already been initialized.
83 //
84 bool LowerAllocations::runOnBasicBlock(BasicBlock &BB) {
85   bool Changed = false;
86   assert(MallocFunc && FreeFunc && "Pass not initialized!");
87
88   BasicBlock::InstListType &BBIL = BB.getInstList();
89   TargetData &DataLayout = getAnalysis<TargetData>();
90
91   // Loop over all of the instructions, looking for malloc or free instructions
92   for (BasicBlock::iterator I = BB.begin(), E = BB.end(); I != E; ++I) {
93     if (MallocInst *MI = dyn_cast<MallocInst>(I)) {
94       const Type *AllocTy = MI->getType()->getElementType();
95       
96       // Get the number of bytes to be allocated for one element of the
97       // requested type...
98       unsigned Size = DataLayout.getTypeSize(AllocTy);
99       
100       // malloc(type) becomes sbyte *malloc(constint)
101       Value *MallocArg = ConstantUInt::get(Type::UIntTy, Size);
102       if (MI->getNumOperands() && Size == 1) {
103         MallocArg = MI->getOperand(0);         // Operand * 1 = Operand
104       } else if (MI->getNumOperands()) {
105         // Multiply it by the array size if necessary...
106         MallocArg = BinaryOperator::create(Instruction::Mul, MI->getOperand(0),
107                                            MallocArg, "", I);
108       }
109
110       const FunctionType *MallocFTy = MallocFunc->getFunctionType();
111       std::vector<Value*> MallocArgs;
112       
113       if (MallocFTy->getNumParams() > 0 || MallocFTy->isVarArg()) {
114         if (MallocFTy->getNumParams() > 0 &&
115             MallocFTy->getParamType(0) != Type::UIntTy)
116           MallocArg = new CastInst(MallocArg, MallocFTy->getParamType(0), "",I);
117         MallocArgs.push_back(MallocArg);
118       }
119
120       // If malloc is prototyped to take extra arguments, pass nulls.
121       for (unsigned i = 1; i < MallocFTy->getNumParams(); ++i)
122        MallocArgs.push_back(Constant::getNullValue(MallocFTy->getParamType(i)));
123
124       // Create the call to Malloc...
125       CallInst *MCall = new CallInst(MallocFunc, MallocArgs, "", I);
126       
127       // Create a cast instruction to convert to the right type...
128       Value *MCast;
129       if (MCall->getType() != Type::VoidTy)
130         MCast = new CastInst(MCall, MI->getType(), "", I);
131       else
132         MCast = Constant::getNullValue(MI->getType());
133       
134       // Replace all uses of the old malloc inst with the cast inst
135       MI->replaceAllUsesWith(MCast);
136       I = --BBIL.erase(I);         // remove and delete the malloc instr...
137       Changed = true;
138       ++NumLowered;
139     } else if (FreeInst *FI = dyn_cast<FreeInst>(I)) {
140       const FunctionType *FreeFTy = FreeFunc->getFunctionType();
141       std::vector<Value*> FreeArgs;
142       
143       if (FreeFTy->getNumParams() > 0 || FreeFTy->isVarArg()) {
144         Value *MCast = FI->getOperand(0);
145         if (FreeFTy->getNumParams() > 0 &&
146             FreeFTy->getParamType(0) != MCast->getType())
147           MCast = new CastInst(MCast, FreeFTy->getParamType(0), "", I);
148         FreeArgs.push_back(MCast);
149       }
150
151       // If malloc is prototyped to take extra arguments, pass nulls.
152       for (unsigned i = 1; i < FreeFTy->getNumParams(); ++i)
153        FreeArgs.push_back(Constant::getNullValue(FreeFTy->getParamType(i)));
154       
155       // Insert a call to the free function...
156       new CallInst(FreeFunc, FreeArgs, "", I);
157       
158       // Delete the old free instruction
159       I = --BBIL.erase(I);
160       Changed = true;
161       ++NumLowered;
162     }
163   }
164
165   return Changed;
166 }
167