Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(368)

Side by Side Diff: lib/Transforms/NaCl/ReplacePtrsWithInts.cpp

Issue 14262011: PNaCl: Add ReplacePtrsWithInts pass for stripping out pointer types (Closed) Base URL: http://git.chromium.org/native_client/pnacl-llvm.git@master
Patch Set: Review nits Created 7 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « lib/Transforms/NaCl/ExpandVarArgs.cpp ('k') | test/Transforms/NaCl/replace-ptrs-with-ints.ll » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 //===- ReplacePtrsWithInts.cpp - Convert pointer values to integer values--===//
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 strips out aggregate pointer types and replaces them with
11 // the integer type iPTR, which is i32 for PNaCl (though this pass
12 // will allow iPTR to be i64 if the DataLayout specifies 64-bit
13 // pointers).
14 //
15 // The pass converts IR to the following normal form:
16 //
17 // All inttoptr and ptrtoint instructions use the same integer size
18 // (iPTR), so they do not implicitly truncate or zero-extend.
19 //
20 // alloca always allocates an i8 array type.
21 //
22 // Pointer types only appear in the following instructions:
23 // * loads and stores: the pointer operand is a NormalizedPtr.
24 // * function calls: the function operand is a NormalizedPtr.
25 // * intrinsic calls: any pointer arguments are NormalizedPtrs.
26 // * alloca
27 // * bitcast and inttoptr: only used as part of a NormalizedPtr.
28 // * ptrtoint: the operand is an InherentPtr.
29 //
30 // Where an InherentPtr is defined as a pointer value that is:
31 // * an alloca;
32 // * a GlobalValue (a function or global variable); or
33 // * an intrinsic call.
34 //
35 // And a NormalizedPtr is defined as a pointer value that is:
36 // * an inttoptr instruction;
37 // * an InherentPtr; or
38 // * a bitcast of an InherentPtr.
39 //
40 // This pass currently strips out lifetime markers (that is, calls to
41 // the llvm.lifetime.start/end intrinsics).
42 //
43 //===----------------------------------------------------------------------===//
44
45 #include "llvm/ADT/DenseMap.h"
46 #include "llvm/IR/DataLayout.h"
47 #include "llvm/IR/DerivedTypes.h"
48 #include "llvm/IR/Function.h"
49 #include "llvm/IR/IRBuilder.h"
50 #include "llvm/IR/Instructions.h"
51 #include "llvm/IR/IntrinsicInst.h"
52 #include "llvm/IR/Module.h"
53 #include "llvm/IR/Type.h"
54 #include "llvm/Pass.h"
55 #include "llvm/Support/raw_ostream.h"
56 #include "llvm/Transforms/NaCl.h"
57
58 using namespace llvm;
59
60 namespace {
61 // This is a ModulePass because the pass must recreate functions in
62 // order to change their argument and return types.
63 struct ReplacePtrsWithInts : public ModulePass {
64 static char ID; // Pass identification, replacement for typeid
65 ReplacePtrsWithInts() : ModulePass(ID) {
66 initializeReplacePtrsWithIntsPass(*PassRegistry::getPassRegistry());
67 }
68
69 virtual bool runOnModule(Module &M);
70 };
71
72 // FunctionConverter stores the state for mapping old instructions
73 // (of pointer type) to converted instructions (of integer type)
74 // within a function, and provides methods for doing the conversion.
75 class FunctionConverter {
76 // Int type that pointer types are to be replaced with, typically i32.
77 Type *IntPtrType;
78
79 struct RewrittenVal {
80 RewrittenVal(): IsPlaceholder(true), NewIntVal(NULL) {}
81 bool IsPlaceholder;
82 Value *NewIntVal;
83 };
84 // Maps from old values (of pointer type) to converted values (of
85 // IntPtrType type).
86 DenseMap<Value *, RewrittenVal> RewriteMap;
87 // Number of placeholders; used for detecting unhandled cases.
88 int PlaceholderCount;
89 // List of instructions whose deletion has been deferred.
90 SmallVector<Instruction *, 20> ToErase;
91
92 public:
93 FunctionConverter(Type *IntPtrType)
94 : IntPtrType(IntPtrType), PlaceholderCount(0) {}
95
96 // Returns the normalized version of the given type, converting
97 // pointer types to IntPtrType.
98 Type *convertType(Type *Ty);
99 // Returns the normalized version of the given function type by
100 // normalizing the function's argument types.
101 FunctionType *convertFuncType(FunctionType *FTy);
102
103 // Records that 'To' is the normalized version of 'From'. If 'To'
104 // is not of pointer type, no type conversion is required, so this
105 // can take the short cut of replacing 'To' with 'From'.
106 void recordConverted(Value *From, Value *To);
107 void recordConvertedAndErase(Instruction *From, Value *To);
108
109 // Returns the normalized version of the given value.
110 Value *convert(Value *Val);
111 // Returns the NormalizedPtr form of the given pointer value.
112 // Inserts conversion instructions at InsertPt.
113 Value *convertBackToPtr(Value *Val, Instruction *InsertPt);
114 // Returns the NormalizedPtr form of the given function pointer.
115 // Inserts conversion instructions at InsertPt.
116 Value *convertFunctionPtr(Value *Callee, Instruction *InsertPt);
117 // Converts an instruction without recreating it, by wrapping its
118 // operands and result.
119 void convertInPlace(Instruction *Inst);
120
121 void eraseReplacedInstructions();
122 };
123 }
124
125 Type *FunctionConverter::convertType(Type *Ty) {
126 if (Ty->isPointerTy())
127 return IntPtrType;
128 return Ty;
129 }
130
131 FunctionType *FunctionConverter::convertFuncType(FunctionType *FTy) {
132 SmallVector<Type *, 8> ArgTypes;
133 for (FunctionType::param_iterator ArgTy = FTy->param_begin(),
134 E = FTy->param_end(); ArgTy != E; ++ArgTy) {
135 ArgTypes.push_back(convertType(*ArgTy));
136 }
137 return FunctionType::get(convertType(FTy->getReturnType()), ArgTypes,
138 FTy->isVarArg());
139 }
140
141 void FunctionConverter::recordConverted(Value *From, Value *To) {
142 if (!From->getType()->isPointerTy()) {
143 From->replaceAllUsesWith(To);
144 return;
145 }
146 RewrittenVal *RV = &RewriteMap[From];
147 if (RV->NewIntVal) {
148 assert(RV->IsPlaceholder);
149 // Resolve placeholder.
150 RV->NewIntVal->replaceAllUsesWith(To);
151 delete RV->NewIntVal;
152 RV->IsPlaceholder = false;
153 --PlaceholderCount;
154 }
155 RV->NewIntVal = To;
156 }
157
158 void FunctionConverter::recordConvertedAndErase(Instruction *From, Value *To) {
159 recordConverted(From, To);
160 // There may still be references to this value, so defer deleting it.
161 ToErase.push_back(From);
162 }
163
164 Value *FunctionConverter::convert(Value *Val) {
165 if (!Val->getType()->isPointerTy())
166 return Val;
167 if (Constant *C = dyn_cast<Constant>(Val))
168 return ConstantExpr::getPtrToInt(C, IntPtrType);
169 RewrittenVal *RV = &RewriteMap[Val];
170 if (!RV->NewIntVal) {
171 // No converted value available yet, so create a placeholder.
172 Argument *Placeholder = new Argument(convertType(Val->getType()));
173 RV->NewIntVal = Placeholder;
174 ++PlaceholderCount;
175 }
176 return RV->NewIntVal;
177 }
178
179 Value *FunctionConverter::convertBackToPtr(Value *Val, Instruction *InsertPt) {
180 Type *NewTy =
181 convertType(Val->getType()->getPointerElementType())->getPointerTo();
182 Value *Conv = convert(Val);
183 return new IntToPtrInst(Conv, NewTy, Conv->getName() + ".asptr", InsertPt);
184 }
185
186 Value *FunctionConverter::convertFunctionPtr(Value *Callee,
187 Instruction *InsertPt) {
188 FunctionType *FuncType = cast<FunctionType>(
189 Callee->getType()->getPointerElementType());
190 Value *Conv = convert(Callee);
191 return new IntToPtrInst(Conv, convertFuncType(FuncType)->getPointerTo(),
192 Conv->getName() + ".asfuncptr", InsertPt);
193 }
194
195 static bool ShouldLeaveAlone(Value *V) {
196 if (Function *F = dyn_cast<Function>(V))
197 return F->isIntrinsic();
198 if (isa<InlineAsm>(V))
199 return true;
200 return false;
201 }
202
203 void FunctionConverter::convertInPlace(Instruction *Inst) {
204 // Convert operands.
205 for (unsigned I = 0; I < Inst->getNumOperands(); ++I) {
206 Value *Arg = Inst->getOperand(I);
207 if (Arg->getType()->isPointerTy() && !ShouldLeaveAlone(Arg)) {
208 Value *Conv = convert(Arg);
209 Inst->setOperand(I, new IntToPtrInst(convert(Arg), Arg->getType(),
210 Conv->getName() + ".asptr", Inst));
211 }
212 }
213 // Convert result.
214 if (Inst->getType()->isPointerTy()) {
215 Instruction *Cast = new PtrToIntInst(
216 Inst, convertType(Inst->getType()), Inst->getName() + ".asint");
217 Cast->insertAfter(Inst);
218 recordConverted(Inst, Cast);
219 }
220 }
221
222 void FunctionConverter::eraseReplacedInstructions() {
223 if (PlaceholderCount) {
224 for (DenseMap<Value *, RewrittenVal>::iterator I = RewriteMap.begin(),
225 E = RewriteMap.end(); I != E; ++I) {
226 if (I->second.IsPlaceholder)
227 errs() << "Not converted: " << *I->first << "\n";
228 }
229 report_fatal_error("Case not handled in ReplacePtrsWithInts");
230 }
231 // We must do dropAllReferences() before doing eraseFromParent(),
232 // otherwise we will try to erase instructions that are still
233 // referenced.
234 for (SmallVectorImpl<Instruction *>::iterator I = ToErase.begin(),
235 E = ToErase.end();
236 I != E; ++I) {
237 (*I)->dropAllReferences();
238 }
239 for (SmallVectorImpl<Instruction *>::iterator I = ToErase.begin(),
240 E = ToErase.end();
241 I != E; ++I) {
242 (*I)->eraseFromParent();
243 }
244 }
245
246 static void ConvertMetadataOperand(FunctionConverter *FC,
247 IntrinsicInst *Call, int Index) {
248 MDNode *MD = cast<MDNode>(Call->getArgOperand(Index));
249 if (MD->getNumOperands() != 1)
250 return;
251 Value *MDArg = MD->getOperand(0);
252 if (MDArg && (isa<Argument>(MDArg) || isa<Instruction>(MDArg))) {
253 MDArg = FC->convert(MDArg);
254 if (PtrToIntInst *Cast = dyn_cast<PtrToIntInst>(MDArg)) {
255 // Unwrapping this is necessary for llvm.dbg.declare to work.
256 MDArg = Cast->getPointerOperand();
257 }
258 SmallVector<Value *, 1> Args;
259 Args.push_back(MDArg);
260 Call->setArgOperand(Index, MDNode::get(Call->getContext(), Args));
261 }
262 }
263
264 // Remove attributes that only apply to pointer arguments. Returns
265 // the updated AttributeSet.
266 static AttributeSet RemovePointerAttrs(LLVMContext &Context,
267 AttributeSet Attrs) {
268 SmallVector<AttributeSet, 8> AttrList;
269 for (unsigned Slot = 0; Slot < Attrs.getNumSlots(); ++Slot) {
270 unsigned Index = Attrs.getSlotIndex(Slot);
271 AttrBuilder AB;
272 for (AttributeSet::iterator Attr = Attrs.begin(Slot), E = Attrs.end(Slot);
273 Attr != E; ++Attr) {
274 switch (Attr->getKindAsEnum()) {
275 // ByVal and StructRet should already have been removed by the
276 // ExpandByVal pass.
277 case Attribute::ByVal:
278 case Attribute::StructRet:
279 case Attribute::Nest:
280 Attrs.dump();
281 report_fatal_error("ReplacePtrsWithInts cannot handle "
282 "byval, sret or nest attrs");
283 break;
284 // Strip NoCapture and NoAlias because they are only allowed
285 // on arguments of pointer type, and we are removing the
286 // pointer types.
287 case Attribute::NoCapture:
288 case Attribute::NoAlias:
289 break;
290 default:
291 AB.addAttribute(*Attr);
292 }
293 }
294 AttrList.push_back(AttributeSet::get(Context, Index, AB));
295 }
296 return AttributeSet::get(Context, AttrList);
297 }
298
299 template <class InstType>
300 static void CopyLoadOrStoreAttrs(InstType *Dest, InstType *Src) {
301 Dest->setVolatile(Src->isVolatile());
302 Dest->setAlignment(Src->getAlignment());
303 Dest->setOrdering(Src->getOrdering());
304 Dest->setSynchScope(Src->getSynchScope());
305 }
306
307 static void ConvertInstruction(DataLayout *DL, Type *IntPtrType,
308 FunctionConverter *FC, Instruction *Inst) {
309 if (ReturnInst *Ret = dyn_cast<ReturnInst>(Inst)) {
310 Value *Result = Ret->getReturnValue();
311 if (Result)
312 Result = FC->convert(Result);
313 CopyDebug(ReturnInst::Create(Ret->getContext(), Result, Ret), Inst);
314 Ret->eraseFromParent();
315 } else if (PHINode *Phi = dyn_cast<PHINode>(Inst)) {
316 PHINode *Phi2 = PHINode::Create(FC->convertType(Phi->getType()),
317 Phi->getNumIncomingValues(),
318 "", Phi);
319 CopyDebug(Phi2, Phi);
320 for (unsigned I = 0; I < Phi->getNumIncomingValues(); ++I) {
321 Phi2->addIncoming(FC->convert(Phi->getIncomingValue(I)),
322 Phi->getIncomingBlock(I));
323 }
324 Phi2->takeName(Phi);
325 FC->recordConvertedAndErase(Phi, Phi2);
326 } else if (SelectInst *Op = dyn_cast<SelectInst>(Inst)) {
327 Instruction *Op2 = SelectInst::Create(Op->getCondition(),
328 FC->convert(Op->getTrueValue()),
329 FC->convert(Op->getFalseValue()),
330 "", Op);
331 CopyDebug(Op2, Op);
332 Op2->takeName(Op);
333 FC->recordConvertedAndErase(Op, Op2);
334 } else if (isa<PtrToIntInst>(Inst) || isa<IntToPtrInst>(Inst)) {
335 Value *Arg = FC->convert(Inst->getOperand(0));
336 Type *ResultTy = FC->convertType(Inst->getType());
337 IRBuilder<> Builder(Inst);
338 Builder.SetCurrentDebugLocation(Inst->getDebugLoc());
339 Value *Result = Builder.CreateZExtOrTrunc(Arg, ResultTy, "");
340 if (Result != Arg)
341 Result->takeName(Inst);
342 FC->recordConvertedAndErase(Inst, Result);
343 } else if (isa<BitCastInst>(Inst)) {
344 if (Inst->getType()->isPointerTy()) {
345 FC->recordConvertedAndErase(Inst, FC->convert(Inst->getOperand(0)));
346 }
347 } else if (ICmpInst *Cmp = dyn_cast<ICmpInst>(Inst)) {
348 Value *Cmp2 = CopyDebug(new ICmpInst(Inst, Cmp->getPredicate(),
349 FC->convert(Cmp->getOperand(0)),
350 FC->convert(Cmp->getOperand(1)), ""),
351 Inst);
352 Cmp2->takeName(Cmp);
353 Cmp->replaceAllUsesWith(Cmp2);
354 Cmp->eraseFromParent();
355 } else if (LoadInst *Load = dyn_cast<LoadInst>(Inst)) {
356 Value *Ptr = FC->convertBackToPtr(Load->getPointerOperand(), Inst);
357 LoadInst *Result = new LoadInst(Ptr, "", Inst);
358 Result->takeName(Inst);
359 CopyDebug(Result, Inst);
360 CopyLoadOrStoreAttrs(Result, Load);
361 FC->recordConvertedAndErase(Inst, Result);
362 } else if (StoreInst *Store = dyn_cast<StoreInst>(Inst)) {
363 Value *Ptr = FC->convertBackToPtr(Store->getPointerOperand(), Inst);
364 StoreInst *Result = new StoreInst(FC->convert(Store->getValueOperand()),
365 Ptr, Inst);
366 CopyDebug(Result, Inst);
367 CopyLoadOrStoreAttrs(Result, Store);
368 Inst->eraseFromParent();
369 } else if (CallInst *Call = dyn_cast<CallInst>(Inst)) {
370 if (IntrinsicInst *ICall = dyn_cast<IntrinsicInst>(Inst)) {
371 if (ICall->getIntrinsicID() == Intrinsic::lifetime_start ||
372 ICall->getIntrinsicID() == Intrinsic::lifetime_end) {
373 // Remove alloca lifetime markers for now. This is because
374 // the GVN pass can introduce lifetime markers taking PHI
375 // nodes as arguments. If ReplacePtrsWithInts converts the
376 // PHI node to int type, we will render those lifetime markers
377 // ineffective. But dropping a subset of lifetime markers is
378 // not safe in general. So, until LLVM better defines the
379 // semantics of lifetime markers, we drop them all. See:
380 // https://code.google.com/p/nativeclient/issues/detail?id=3443
381 Inst->eraseFromParent();
382 } else {
383 if (ICall->getIntrinsicID() == Intrinsic::dbg_declare) {
384 ConvertMetadataOperand(FC, ICall, 0);
385 }
386 FC->convertInPlace(Inst);
387 }
388 } else if (isa<InlineAsm>(Call->getCalledValue())) {
389 FC->convertInPlace(Inst);
390 } else {
391 SmallVector<Value *, 10> Args;
392 for (unsigned I = 0; I < Call->getNumArgOperands(); ++I)
393 Args.push_back(FC->convert(Call->getArgOperand(I)));
394 CallInst *NewCall = CallInst::Create(
395 FC->convertFunctionPtr(Call->getCalledValue(), Call),
396 Args, "", Inst);
397 CopyDebug(NewCall, Call);
398 NewCall->setAttributes(RemovePointerAttrs(Call->getContext(),
399 Call->getAttributes()));
400 NewCall->setCallingConv(Call->getCallingConv());
401 NewCall->takeName(Call);
402 FC->recordConvertedAndErase(Call, NewCall);
403 }
404 } else if (InvokeInst *Call = dyn_cast<InvokeInst>(Inst)) {
405 SmallVector<Value *, 10> Args;
406 for (unsigned I = 0; I < Call->getNumArgOperands(); ++I)
407 Args.push_back(FC->convert(Call->getArgOperand(I)));
408 InvokeInst *NewCall = InvokeInst::Create(
409 FC->convertFunctionPtr(Call->getCalledValue(), Call),
410 Call->getNormalDest(),
411 Call->getUnwindDest(),
412 Args, "", Inst);
413 CopyDebug(NewCall, Call);
414 NewCall->setAttributes(RemovePointerAttrs(Call->getContext(),
415 Call->getAttributes()));
416 NewCall->setCallingConv(Call->getCallingConv());
417 NewCall->takeName(Call);
418 FC->recordConvertedAndErase(Call, NewCall);
419 } else if (AllocaInst *Alloca = dyn_cast<AllocaInst>(Inst)) {
420 Type *ElementTy = Inst->getType()->getPointerElementType();
421 Type *ElementTy2 = ArrayType::get(Type::getInt8Ty(Inst->getContext()),
422 DL->getTypeAllocSize(ElementTy));
423 unsigned Alignment = Alloca->getAlignment();
424 if (Alignment == 0)
425 Alignment = DL->getPrefTypeAlignment(ElementTy);
426 Value *Tmp = CopyDebug(new AllocaInst(ElementTy2, Alloca->getArraySize(),
427 Alignment, "", Inst),
428 Inst);
429 Tmp->takeName(Alloca);
430 Value *Alloca2 = new PtrToIntInst(Tmp, IntPtrType,
431 Tmp->getName() + ".asint", Inst);
432 FC->recordConvertedAndErase(Alloca, Alloca2);
433 } else if (// These atomics only operate on integer pointers, not
434 // other pointers, so we don't need to recreate the
435 // instruction.
436 isa<AtomicCmpXchgInst>(Inst) ||
437 isa<AtomicRMWInst>(Inst) ||
438 // Handle these instructions as a convenience to allow
439 // the pass to be used in more situations, even though we
440 // don't expect them in PNaCl's stable ABI.
441 isa<GetElementPtrInst>(Inst) ||
442 isa<VAArgInst>(Inst) ||
443 isa<IndirectBrInst>(Inst) ||
444 isa<ExtractValueInst>(Inst) ||
445 isa<InsertValueInst>(Inst)) {
446 FC->convertInPlace(Inst);
447 }
448 }
449
450 // Convert ptrtoint+inttoptr to a bitcast because it's shorter and
451 // because some intrinsics work on bitcasts but not on
452 // ptrtoint+inttoptr, in particular:
453 // * llvm.lifetime.start/end (although we strip these out)
454 // * llvm.eh.typeid.for
455 static void SimplifyCasts(Instruction *Inst, Type *IntPtrType) {
456 if (IntToPtrInst *Cast1 = dyn_cast<IntToPtrInst>(Inst)) {
457 if (PtrToIntInst *Cast2 = dyn_cast<PtrToIntInst>(Cast1->getOperand(0))) {
458 assert(Cast2->getType() == IntPtrType);
459 Value *V = Cast2->getPointerOperand();
460 if (V->getType() != Cast1->getType())
461 V = new BitCastInst(V, Cast1->getType(), V->getName() + ".bc", Cast1);
462 Cast1->replaceAllUsesWith(V);
463 if (Cast1->use_empty())
464 Cast1->eraseFromParent();
465 if (Cast2->use_empty())
466 Cast2->eraseFromParent();
467 }
468 }
469 }
470
471 static void CleanUpFunction(Function *Func, Type *IntPtrType) {
472 // Remove the ptrtoint/bitcast ConstantExprs we introduced for
473 // referencing globals.
474 FunctionPass *Pass = createExpandConstantExprPass();
475 Pass->runOnFunction(*Func);
476 delete Pass;
477
478 for (Function::iterator BB = Func->begin(), E = Func->end();
479 BB != E; ++BB) {
480 for (BasicBlock::iterator Iter = BB->begin(), E = BB->end();
481 Iter != E; ) {
482 SimplifyCasts(Iter++, IntPtrType);
483 }
484 }
485 // Cleanup: Remove ptrtoints that were introduced for allocas but not used.
486 for (Function::iterator BB = Func->begin(), E = Func->end();
487 BB != E; ++BB) {
488 for (BasicBlock::iterator Iter = BB->begin(), E = BB->end();
489 Iter != E; ) {
490 Instruction *Inst = Iter++;
491 if (isa<PtrToIntInst>(Inst) && Inst->use_empty())
492 Inst->eraseFromParent();
493 }
494 }
495 }
496
497 char ReplacePtrsWithInts::ID = 0;
498 INITIALIZE_PASS(ReplacePtrsWithInts, "replace-ptrs-with-ints",
499 "Convert pointer values to integer values",
500 false, false)
501
502 bool ReplacePtrsWithInts::runOnModule(Module &M) {
503 DataLayout DL(&M);
504 Type *IntPtrType = DL.getIntPtrType(M.getContext());
505
506 for (Module::iterator Iter = M.begin(), E = M.end(); Iter != E; ) {
507 Function *OldFunc = Iter++;
508 // Intrinsics' types must be left alone.
509 if (OldFunc->isIntrinsic())
510 continue;
511
512 FunctionConverter FC(IntPtrType);
513 FunctionType *NFTy = FC.convertFuncType(OldFunc->getFunctionType());
514
515 // In order to change the function's argument types, we have to
516 // recreate the function.
517 Function *NewFunc = Function::Create(NFTy, OldFunc->getLinkage());
518 NewFunc->copyAttributesFrom(OldFunc);
519 NewFunc->setAttributes(RemovePointerAttrs(M.getContext(),
520 NewFunc->getAttributes()));
521 M.getFunctionList().insert(OldFunc, NewFunc);
522 NewFunc->takeName(OldFunc);
523 NewFunc->getBasicBlockList().splice(NewFunc->begin(),
524 OldFunc->getBasicBlockList());
525
526 // Move the arguments across to the new function.
527 for (Function::arg_iterator Arg = OldFunc->arg_begin(),
528 E = OldFunc->arg_end(), NewArg = NewFunc->arg_begin();
529 Arg != E; ++Arg, ++NewArg) {
530 FC.recordConverted(Arg, NewArg);
531 NewArg->takeName(Arg);
532 }
533
534 // Convert the function body.
535 for (Function::iterator BB = NewFunc->begin(), E = NewFunc->end();
536 BB != E; ++BB) {
537 for (BasicBlock::iterator Iter = BB->begin(), E = BB->end();
538 Iter != E; ) {
539 ConvertInstruction(&DL, IntPtrType, &FC, Iter++);
540 }
541 }
542 FC.eraseReplacedInstructions();
543 OldFunc->replaceAllUsesWith(ConstantExpr::getBitCast(NewFunc,
544 OldFunc->getType()));
545 OldFunc->eraseFromParent();
546 }
547 // Now that all functions have their normalized types, we can remove
548 // various casts.
549 for (Module::iterator Func = M.begin(), E = M.end(); Func != E; ++Func) {
550 CleanUpFunction(Func, IntPtrType);
551 }
552 return true;
553 }
554
555 ModulePass *llvm::createReplacePtrsWithIntsPass() {
556 return new ReplacePtrsWithInts();
557 }
OLDNEW
« no previous file with comments | « lib/Transforms/NaCl/ExpandVarArgs.cpp ('k') | test/Transforms/NaCl/replace-ptrs-with-ints.ll » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698