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