OLD | NEW |
---|---|
(Empty) | |
1 //===- ExpandVarArgs.cpp - Expand out variable argument function calls-----===// | |
2 // | |
3 // The LLVM Compiler Infrastructure | |
4 // | |
5 // This file is distributed under the University of Illinois Open Source | |
6 // License. See LICENSE.TXT for details. | |
7 // | |
8 //===----------------------------------------------------------------------===// | |
9 // | |
10 // This pass expands out all use of variable argument functions. | |
11 // | |
12 // This pass replaces a varargs function call with a function call in | |
13 // which a pointer to the variable arguments is passed explicitly. | |
14 // The callee explicitly allocates space for the variable arguments on | |
15 // the stack using "alloca". | |
16 // | |
17 // Alignment: | |
18 // | |
19 // This pass does not add any alignment padding between the arguments | |
20 // that are copied onto the stack. We assume that the only argument | |
21 // types that need to be handled are 32-bit and 64-bit -- i32, i64, | |
22 // pointers and double: | |
23 // | |
24 // * We won't see i1, i8, i16 and float as varargs arguments because | |
25 // the C standard requires the compiler to promote these to the | |
26 // types "int" and "double". | |
27 // | |
28 // * We won't see va_arg instructions of struct type because Clang | |
29 // does not yet support them in PNaCl mode. See | |
30 // https://code.google.com/p/nativeclient/issues/detail?id=2381 | |
31 // | |
32 // If such arguments do appear in the input, this pass will generate | |
33 // correct, working code, but this code might be inefficient due to | |
34 // using unaligned memory accesses. | |
35 // | |
36 //===----------------------------------------------------------------------===// | |
37 | |
38 #include "llvm/ADT/SmallVector.h" | |
39 #include "llvm/IR/DataLayout.h" | |
40 #include "llvm/IR/Function.h" | |
41 #include "llvm/IR/Instructions.h" | |
42 #include "llvm/IR/IntrinsicInst.h" | |
43 #include "llvm/IR/Module.h" | |
44 #include "llvm/Pass.h" | |
45 #include "llvm/Transforms/NaCl.h" | |
46 | |
47 using namespace llvm; | |
48 | |
49 namespace { | |
50 // This is a ModulePass because the pass recreates functions in | |
51 // order to change their argument lists. | |
52 class ExpandVarArgs : public ModulePass { | |
53 public: | |
54 static char ID; // Pass identification, replacement for typeid | |
55 ExpandVarArgs() : ModulePass(ID) { | |
56 initializeExpandVarArgsPass(*PassRegistry::getPassRegistry()); | |
57 } | |
58 | |
59 virtual bool runOnModule(Module &M); | |
60 }; | |
61 } | |
62 | |
63 char ExpandVarArgs::ID = 0; | |
64 INITIALIZE_PASS(ExpandVarArgs, "expand-varargs", | |
65 "Expand out variable argument function definitions and calls", | |
66 false, false) | |
67 | |
68 static void ExpandVarArgFunc(Function *Func) { | |
69 Type *PtrType = Type::getInt8PtrTy(Func->getContext()); | |
70 | |
71 FunctionType *FTy = Func->getFunctionType(); | |
72 SmallVector<Type*,8> Params(FTy->param_begin(), FTy->param_end()); | |
eliben
2013/03/21 18:36:40
Idiomatic LLVM style whitespace is:
SmallVector<T
Mark Seaborn
2013/03/21 19:50:55
OK, fixed.
| |
73 Params.push_back(PtrType); | |
74 FunctionType *NFTy = FunctionType::get(FTy->getReturnType(), Params, false); | |
75 | |
76 // In order to change the function's arguments, we have to recreate | |
77 // the function. | |
78 Function *NewFunc = Function::Create(NFTy, Func->getLinkage()); | |
79 NewFunc->copyAttributesFrom(Func); | |
80 Func->getParent()->getFunctionList().insert(Func, NewFunc); | |
81 NewFunc->takeName(Func); | |
82 NewFunc->getBasicBlockList().splice(NewFunc->begin(), | |
83 Func->getBasicBlockList()); | |
84 | |
85 // Move the arguments across to the new function. | |
86 for (Function::arg_iterator Arg = Func->arg_begin(), E = Func->arg_end(), | |
87 NewArg = NewFunc->arg_begin(); | |
88 Arg != E; ++Arg, ++NewArg) { | |
89 Arg->replaceAllUsesWith(NewArg); | |
90 NewArg->takeName(Arg); | |
91 } | |
92 | |
93 Func->replaceAllUsesWith( | |
94 ConstantExpr::getBitCast(NewFunc, FTy->getPointerTo())); | |
95 Func->eraseFromParent(); | |
96 | |
97 Value *VarArgsArg = --NewFunc->arg_end(); | |
98 VarArgsArg->setName("varargs"); | |
99 | |
100 // Expand out uses of llvm.va_start in this function. | |
101 for (Function::iterator BB = NewFunc->begin(), E = NewFunc->end(); | |
102 BB != E; | |
103 ++BB) { | |
104 for (BasicBlock::iterator Iter = BB->begin(), E = BB->end(); | |
105 Iter != E; ) { | |
106 Instruction *Inst = Iter++; | |
107 if (VAStartInst *VAS = dyn_cast<VAStartInst>(Inst)) { | |
108 Value *Cast = new BitCastInst(VAS->getArgList(), | |
109 PtrType->getPointerTo(), | |
110 "arglist", VAS); | |
111 new StoreInst(VarArgsArg, Cast, VAS); | |
112 VAS->eraseFromParent(); | |
113 } | |
114 } | |
115 } | |
116 } | |
117 | |
118 static void ExpandVAArgInst(VAArgInst *Inst) { | |
119 // Read the argument. We assume that no realignment of the pointer | |
120 // is required. | |
121 Value *ArgList = new BitCastInst( | |
122 Inst->getPointerOperand(), | |
123 Inst->getType()->getPointerTo()->getPointerTo(), "arglist", Inst); | |
124 Value *CurrentPtr = new LoadInst(ArgList, "arglist_current", Inst); | |
125 Value *Result = new LoadInst(CurrentPtr, "va_arg", Inst); | |
126 Result->takeName(Inst); | |
127 | |
128 // Update the va_list to point to the next argument. | |
129 SmallVector<Value*,1> Indexes; | |
eliben
2013/03/21 18:36:40
ditto
Mark Seaborn
2013/03/21 19:50:55
Done.
| |
130 Indexes.push_back(ConstantInt::get(Inst->getContext(), APInt(32, 1))); | |
131 Value *Next = GetElementPtrInst::Create(CurrentPtr, Indexes, | |
132 "arglist_next", Inst); | |
133 new StoreInst(Next, ArgList, Inst); | |
134 | |
135 Inst->replaceAllUsesWith(Result); | |
136 Inst->eraseFromParent(); | |
137 } | |
138 | |
139 static void ExpandVACopyInst(VACopyInst *Inst) { | |
140 // va_list may have more space reserved, but we only need to | |
141 // copy a single pointer. | |
142 Type *PtrTy = Type::getInt8PtrTy(Inst->getContext())->getPointerTo(); | |
143 Value *Src = new BitCastInst(Inst->getSrc(), PtrTy, "vacopy_src", Inst); | |
144 Value *Dest = new BitCastInst(Inst->getDest(), PtrTy, "vacopy_dest", Inst); | |
145 Value *CurrentPtr = new LoadInst(Src, "vacopy_currentptr", Inst); | |
146 new StoreInst(CurrentPtr, Dest, Inst); | |
147 Inst->eraseFromParent(); | |
148 } | |
149 | |
150 static void LifetimeDecl(Intrinsic::ID id, Value *Ptr, Value *Size, | |
151 Instruction *InsertPt) { | |
152 Module *M = InsertPt->getParent()->getParent()->getParent(); | |
153 Value *Func = Intrinsic::getDeclaration(M, id); | |
154 SmallVector<Value*,2> Args; | |
155 Args.push_back(Size); | |
156 Args.push_back(Ptr); | |
157 CallInst::Create(Func, Args, "", InsertPt); | |
158 } | |
159 | |
160 // CopyCall() uses argument overloading so that it can be used by the | |
161 // template ExpandVarArgCall(). | |
162 static Instruction *CopyCall(CallInst *Original, Value *Callee, | |
163 ArrayRef<Value*> Args) { | |
164 return CallInst::Create(Callee, Args, "", Original); | |
165 } | |
166 | |
167 static Instruction *CopyCall(InvokeInst *Original, Value *Callee, | |
168 ArrayRef<Value*> Args) { | |
169 return InvokeInst::Create(Callee, Original->getNormalDest(), | |
170 Original->getUnwindDest(), Args, "", Original); | |
171 } | |
172 | |
173 // ExpandVarArgCall() converts a CallInst or InvokeInst to expand out | |
174 // of varargs. It returns whether the module was modified. | |
175 template <class InstType> | |
176 static bool ExpandVarArgCall(InstType *Call, DataLayout *DL) { | |
177 FunctionType *FuncType = cast<FunctionType>( | |
178 Call->getCalledValue()->getType()->getPointerElementType()); | |
179 if (!FuncType->isFunctionVarArg()) | |
180 return false; | |
181 | |
182 LLVMContext *Context = &Call->getContext(); | |
183 | |
184 // Split argument list into fixed and variable arguments. | |
185 SmallVector<Value*,8> FixedArgs; | |
186 SmallVector<Value*,8> VarArgs; | |
187 SmallVector<Type*,8> VarArgsTypes; | |
188 for (unsigned I = 0; I < FuncType->getNumParams(); ++I) | |
189 FixedArgs.push_back(Call->getArgOperand(I)); | |
190 for (unsigned I = FuncType->getNumParams(); | |
191 I < Call->getNumArgOperands(); ++I) { | |
192 VarArgs.push_back(Call->getArgOperand(I)); | |
193 VarArgsTypes.push_back(Call->getArgOperand(I)->getType()); | |
194 } | |
195 | |
196 StructType *VarArgsTy; | |
197 Value *ArgToAdd; | |
198 Instruction *BufPtr = NULL; | |
199 Value *BufSize = NULL; | |
200 if (VarArgs.size() == 0) { | |
201 // If there are no variable arguments being passed, we still want | |
202 // to add an extra argument to the function call so that the | |
203 // number of arguments matches the callee's type. | |
204 VarArgsTy = StructType::get(*Context); | |
205 ArgToAdd = UndefValue::get(VarArgsTy->getPointerTo()); | |
206 } else { | |
207 // Create struct type for packing variable arguments into. We | |
208 // create this as packed for now and assume that no alignment | |
209 // padding is desired. | |
210 VarArgsTy = StructType::create(VarArgsTypes, "vararg_call", true); | |
211 | |
212 // Allocate space for the variable argument buffer. Do this at the | |
213 // start of the function so that we don't leak space if the function | |
214 // is called in a loop. | |
215 Function *Func = Call->getParent()->getParent(); | |
216 Instruction *Buf = new AllocaInst(VarArgsTy, "vararg_buffer"); | |
217 Func->getEntryBlock().getInstList().push_front(Buf); | |
218 ArgToAdd = Buf; | |
219 | |
220 // Call llvm.lifetime.start/end intrinsics to indicate that Buf is | |
221 // only used for the duration of the function call, so that the | |
222 // stack space can be reused elsewhere. | |
223 Type *I8Ptr = Type::getInt8Ty(*Context)->getPointerTo(); | |
224 BufPtr = new BitCastInst(Buf, I8Ptr, "vararg_lifetime_bitcast"); | |
225 BufPtr->insertAfter(Buf); | |
226 BufSize = ConstantInt::get(*Context, | |
227 APInt(64, DL->getTypeAllocSize(VarArgsTy))); | |
228 LifetimeDecl(Intrinsic::lifetime_start, BufPtr, BufSize, Call); | |
229 | |
230 // Copy variable arguments into buffer. | |
231 int Index = 0; | |
232 for (SmallVector<Value*,8>::iterator Iter = VarArgs.begin(); | |
233 Iter != VarArgs.end(); | |
234 ++Iter, ++Index) { | |
235 SmallVector<Value*,2> Indexes; | |
236 Indexes.push_back(ConstantInt::get(*Context, APInt(32, 0))); | |
237 Indexes.push_back(ConstantInt::get(*Context, APInt(32, Index))); | |
238 Value *Ptr = GetElementPtrInst::Create(Buf, Indexes, "vararg_ptr", Call); | |
239 new StoreInst(*Iter, Ptr, Call); | |
240 } | |
241 } | |
242 | |
243 // Cast function to new type to add our extra pointer argument. | |
244 SmallVector<Type*,8> ArgTypes(FuncType->param_begin(), FuncType->param_end()); | |
245 ArgTypes.push_back(VarArgsTy->getPointerTo()); | |
246 FunctionType *NFTy = FunctionType::get(FuncType->getReturnType(), | |
247 ArgTypes, false); | |
248 Value *CastFunc = new BitCastInst(Call->getCalledValue(), | |
249 NFTy->getPointerTo(), "vararg_func", Call); | |
250 | |
251 // Create the converted function call. | |
252 FixedArgs.push_back(ArgToAdd); | |
253 Value *NewCall = CopyCall(Call, CastFunc, FixedArgs); | |
254 NewCall->takeName(Call); | |
255 | |
256 if (BufPtr) { | |
257 if (isa<CallInst>(Call)) { | |
258 LifetimeDecl(Intrinsic::lifetime_end, BufPtr, BufSize, Call); | |
259 } else if (InvokeInst *Invoke = dyn_cast<InvokeInst>(Call)) { | |
260 LifetimeDecl(Intrinsic::lifetime_end, BufPtr, BufSize, | |
261 Invoke->getNormalDest()->getFirstInsertionPt()); | |
262 LifetimeDecl(Intrinsic::lifetime_end, BufPtr, BufSize, | |
263 Invoke->getUnwindDest()->getFirstInsertionPt()); | |
264 } | |
265 } | |
266 | |
267 Call->replaceAllUsesWith(NewCall); | |
268 Call->eraseFromParent(); | |
269 | |
270 return true; | |
271 } | |
272 | |
273 bool ExpandVarArgs::runOnModule(Module &M) { | |
274 bool Changed = false; | |
275 DataLayout DL(&M); | |
276 | |
277 for (Module::iterator Iter = M.begin(), E = M.end(); Iter != E; ) { | |
278 Function *Func = Iter++; | |
279 | |
280 for (Function::iterator BB = Func->begin(), E = Func->end(); | |
281 BB != E; | |
282 ++BB) { | |
283 for (BasicBlock::iterator Iter = BB->begin(), E = BB->end(); | |
284 Iter != E; ) { | |
285 Instruction *Inst = Iter++; | |
286 if (VAArgInst *VI = dyn_cast<VAArgInst>(Inst)) { | |
287 Changed = true; | |
288 ExpandVAArgInst(VI); | |
289 } else if (isa<VAEndInst>(Inst)) { | |
290 // va_end() is a no-op in this implementation. | |
291 Changed = true; | |
292 Inst->eraseFromParent(); | |
293 } else if (VACopyInst *VAC = dyn_cast<VACopyInst>(Inst)) { | |
294 Changed = true; | |
295 ExpandVACopyInst(VAC); | |
296 } else if (CallInst *Call = dyn_cast<CallInst>(Inst)) { | |
297 Changed |= ExpandVarArgCall(Call, &DL); | |
298 } else if (InvokeInst *Call = dyn_cast<InvokeInst>(Inst)) { | |
299 Changed |= ExpandVarArgCall(Call, &DL); | |
300 } | |
301 } | |
302 } | |
303 | |
304 if (Func->isVarArg()) { | |
305 Changed = true; | |
306 ExpandVarArgFunc(Func); | |
307 } | |
308 } | |
309 | |
310 return Changed; | |
311 } | |
312 | |
313 ModulePass *llvm::createExpandVarArgsPass() { | |
314 return new ExpandVarArgs(); | |
315 } | |
OLD | NEW |