Changes For Bug 352
[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     /// runOnBasicBlock - This method does the actual work of converting
42     /// instructions over, assuming that the pass has already been initialized.
43     ///
44     bool runOnBasicBlock(BasicBlock &BB);
45   };
46
47   RegisterOpt<LowerAllocations>
48   X("lowerallocs", "Lower allocations from instructions to calls");
49 }
50
51 // createLowerAllocationsPass - Interface to this file...
52 FunctionPass *llvm::createLowerAllocationsPass() {
53   return new LowerAllocations();
54 }
55
56
57 // doInitialization - For the lower allocations pass, this ensures that a
58 // module contains a declaration for a malloc and a free function.
59 //
60 // This function is always successful.
61 //
62 bool LowerAllocations::doInitialization(Module &M) {
63   const Type *SBPTy = PointerType::get(Type::SByteTy);
64   MallocFunc = M.getNamedFunction("malloc");
65   FreeFunc   = M.getNamedFunction("free");
66
67   if (MallocFunc == 0)
68     MallocFunc = M.getOrInsertFunction("malloc", SBPTy, Type::UIntTy, 0);
69   if (FreeFunc == 0)
70     FreeFunc   = M.getOrInsertFunction("free"  , Type::VoidTy, SBPTy, 0);
71
72   return true;
73 }
74
75 static Constant *getSizeof(const Type *Ty) {
76   Constant *Ret = ConstantPointerNull::get(PointerType::get(Ty));
77   std::vector<Constant*> Idx;
78   Idx.push_back(ConstantUInt::get(Type::UIntTy, 1));
79   Ret = ConstantExpr::getGetElementPtr(Ret, Idx);
80   return ConstantExpr::getCast(Ret, Type::UIntTy);
81 }
82
83 // runOnBasicBlock - This method does the actual work of converting
84 // instructions over, assuming that the pass has already been initialized.
85 //
86 bool LowerAllocations::runOnBasicBlock(BasicBlock &BB) {
87   bool Changed = false;
88   assert(MallocFunc && FreeFunc && "Pass not initialized!");
89
90   BasicBlock::InstListType &BBIL = BB.getInstList();
91
92   // Loop over all of the instructions, looking for malloc or free instructions
93   for (BasicBlock::iterator I = BB.begin(), E = BB.end(); I != E; ++I) {
94     if (MallocInst *MI = dyn_cast<MallocInst>(I)) {
95       const Type *AllocTy = MI->getType()->getElementType();
96       
97       // malloc(type) becomes sbyte *malloc(size)
98       Value *MallocArg = getSizeof(AllocTy);
99       if (MI->isArrayAllocation()) {
100         if (isa<ConstantUInt>(MallocArg) &&
101             cast<ConstantUInt>(MallocArg)->getValue() == 1) {
102           MallocArg = MI->getOperand(0);         // Operand * 1 = Operand
103         } else if (Constant *CO = dyn_cast<Constant>(MI->getOperand(0))) {
104           MallocArg = ConstantExpr::getMul(CO, cast<Constant>(MallocArg));
105         } else {
106           // Multiply it by the array size if necessary...
107           MallocArg = BinaryOperator::create(Instruction::Mul,
108                                              MI->getOperand(0),
109                                              MallocArg, "", I);
110         }
111       }
112
113       const FunctionType *MallocFTy = MallocFunc->getFunctionType();
114       std::vector<Value*> MallocArgs;
115       
116       if (MallocFTy->getNumParams() > 0 || MallocFTy->isVarArg()) {
117         if (MallocFTy->getNumParams() > 0 &&
118             MallocFTy->getParamType(0) != Type::UIntTy)
119           MallocArg = new CastInst(MallocArg, MallocFTy->getParamType(0), "",I);
120         MallocArgs.push_back(MallocArg);
121       }
122
123       // If malloc is prototyped to take extra arguments, pass nulls.
124       for (unsigned i = 1; i < MallocFTy->getNumParams(); ++i)
125        MallocArgs.push_back(Constant::getNullValue(MallocFTy->getParamType(i)));
126
127       // Create the call to Malloc...
128       CallInst *MCall = new CallInst(MallocFunc, MallocArgs, "", I);
129       
130       // Create a cast instruction to convert to the right type...
131       Value *MCast;
132       if (MCall->getType() != Type::VoidTy)
133         MCast = new CastInst(MCall, MI->getType(), "", I);
134       else
135         MCast = Constant::getNullValue(MI->getType());
136       
137       // Replace all uses of the old malloc inst with the cast inst
138       MI->replaceAllUsesWith(MCast);
139       I = --BBIL.erase(I);         // remove and delete the malloc instr...
140       Changed = true;
141       ++NumLowered;
142     } else if (FreeInst *FI = dyn_cast<FreeInst>(I)) {
143       const FunctionType *FreeFTy = FreeFunc->getFunctionType();
144       std::vector<Value*> FreeArgs;
145       
146       if (FreeFTy->getNumParams() > 0 || FreeFTy->isVarArg()) {
147         Value *MCast = FI->getOperand(0);
148         if (FreeFTy->getNumParams() > 0 &&
149             FreeFTy->getParamType(0) != MCast->getType())
150           MCast = new CastInst(MCast, FreeFTy->getParamType(0), "", I);
151         FreeArgs.push_back(MCast);
152       }
153
154       // If malloc is prototyped to take extra arguments, pass nulls.
155       for (unsigned i = 1; i < FreeFTy->getNumParams(); ++i)
156        FreeArgs.push_back(Constant::getNullValue(FreeFTy->getParamType(i)));
157       
158       // Insert a call to the free function...
159       new CallInst(FreeFunc, FreeArgs, "", I);
160       
161       // Delete the old free instruction
162       I = --BBIL.erase(I);
163       Changed = true;
164       ++NumLowered;
165     }
166   }
167
168   return Changed;
169 }
170