OLD | NEW |
---|---|
(Empty) | |
1 //===- ExpandIndirectBr.cpp - Expand out indirectbr and blockaddress-------===// | |
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 indirectbr instructions and blockaddress | |
11 // ConstantExprs, which are not currently supported in PNaCl's stable | |
12 // ABI. indirectbr is used to implement computed gotos (a GNU | |
13 // extension to C). This pass replaces indirectbr instructions with | |
14 // switch instructions. | |
15 // | |
16 // The resulting use of switches might not be as fast as the original | |
17 // indirectbrs. If you are compiling a program that has a | |
18 // compile-time option for using computed gotos, it's possible that | |
19 // the program will run faster with the option turned off than with | |
20 // using computed gotos + ExpandIndirectBr (for example, if the | |
21 // program does extra work to take advantage of computed gotos). | |
22 // | |
23 //===----------------------------------------------------------------------===// | |
24 | |
25 #include "llvm/ADT/DenseMap.h" | |
26 #include "llvm/ADT/DenseSet.h" | |
27 #include "llvm/IR/Constants.h" | |
28 #include "llvm/IR/Instructions.h" | |
29 #include "llvm/IR/Module.h" | |
30 #include "llvm/Pass.h" | |
31 #include "llvm/Transforms/NaCl.h" | |
32 | |
33 using namespace llvm; | |
34 | |
35 namespace { | |
36 // This is a ModulePass so that it can expand out blockaddress | |
37 // ConstantExprs inside global variable initializers. | |
38 class ExpandIndirectBr : public ModulePass { | |
39 public: | |
40 static char ID; // Pass identification, replacement for typeid | |
41 ExpandIndirectBr() : ModulePass(ID) { | |
42 initializeExpandIndirectBrPass(*PassRegistry::getPassRegistry()); | |
43 } | |
44 | |
45 virtual bool runOnModule(Module &M); | |
46 }; | |
47 } | |
48 | |
49 char ExpandIndirectBr::ID = 0; | |
50 INITIALIZE_PASS(ExpandIndirectBr, "expand-indirectbr", | |
51 "Expand out indirectbr and blockaddress (computed gotos)", | |
52 false, false) | |
53 | |
54 static bool convertFunction(Function *Func) { | |
55 bool Changed = false; | |
56 IntegerType *I32 = Type::getInt32Ty(Func->getContext()); | |
57 | |
58 // Skip zero in case programs treat a null pointer as special. | |
59 uint32_t NextNum = 1; | |
60 DenseMap<BasicBlock *, ConstantInt *> LabelNums; | |
61 BasicBlock *DefaultBB = NULL; | |
62 | |
63 // Replace each indirectbr with a switch. | |
64 // | |
65 // If there are multiple indirectbr instructions in the function, | |
66 // this could be expensive. While an indirectbr is usually | |
67 // converted to O(1) machine instructions, the switch we generate | |
68 // here will be O(n) in the number of target labels. | |
69 // | |
70 // However, Clang usually generates just a single indirectbr per | |
71 // function anyway when compiling C computed gotos. | |
72 // | |
73 // We could try to generate one switch to handle all the indirectbr | |
74 // instructions in the function, but that would be complicated to | |
75 // implement given that variables that are live at one indirectbr | |
76 // might not be live at others. | |
77 for (llvm::Function::iterator BB = Func->begin(), E = Func->end(); | |
78 BB != E; ++BB) { | |
79 if (IndirectBrInst *Br = dyn_cast<IndirectBrInst>(BB->getTerminator())) { | |
80 Changed = true; | |
81 | |
82 if (!DefaultBB) { | |
83 DefaultBB = BasicBlock::Create(Func->getContext(), | |
84 "indirectbr_default", Func); | |
85 new UnreachableInst(Func->getContext(), DefaultBB); | |
86 } | |
87 | |
88 // An indirectbr can list the same target block multiple times. | |
89 // Keep track of the basic blocks we've handled to avoid adding | |
90 // the same case multiple times. | |
91 DenseSet<BasicBlock *> BlocksSeen; | |
92 | |
93 Value *Cast = new PtrToIntInst(Br->getAddress(), I32, | |
94 "indirectbr_cast", Br); | |
95 unsigned Count = Br->getNumSuccessors(); | |
96 SwitchInst *Switch = SwitchInst::Create(Cast, DefaultBB, Count, Br); | |
97 for (unsigned I = 0; I < Count; ++I) { | |
98 BasicBlock *Dest = Br->getSuccessor(I); | |
99 if (!BlocksSeen.insert(Dest).second) { | |
100 // Remove duplicated entries from phi nodes. | |
101 for (BasicBlock::iterator Inst = Dest->begin(); ; ++Inst) { | |
102 PHINode *Phi = dyn_cast<PHINode>(Inst); | |
103 if (!Phi) | |
104 break; | |
105 Phi->removeIncomingValue(Br->getParent()); | |
106 } | |
107 continue; | |
108 } | |
109 ConstantInt *Val; | |
110 if (LabelNums.count(Dest) == 0) { | |
111 Val = ConstantInt::get(I32, NextNum++); | |
112 LabelNums[Dest] = Val; | |
113 | |
114 BlockAddress *BA = BlockAddress::get(Func, Dest); | |
115 Value *ValAsPtr = ConstantExpr::getIntToPtr(Val, BA->getType()); | |
116 BA->replaceAllUsesWith(ValAsPtr); | |
117 BA->destroyConstant(); | |
118 } else { | |
119 Val = LabelNums[Dest]; | |
120 } | |
121 Switch->addCase(Val, Br->getSuccessor(I)); | |
122 } | |
123 Br->eraseFromParent(); | |
124 } | |
125 } | |
126 | |
127 // If there are any blockaddresses that are never used by an | |
128 // indirectbr, replace them with dummy values. | |
Derek Schuff
2014/01/06 22:30:22
Why do this rather than just destroying them?
Mark Seaborn
2014/01/06 22:36:02
Because they might be used, so you can't just dest
Derek Schuff
2014/01/07 00:35:01
Ah, i didn't think there about legitimate uses oth
| |
129 for (Value::use_iterator UI = Func->use_begin(), E = Func->use_end(); | |
130 UI != E; ++UI) { | |
131 if (BlockAddress *BA = dyn_cast<BlockAddress>(*UI)) { | |
132 Changed = true; | |
133 Value *DummyVal = ConstantExpr::getIntToPtr(ConstantInt::get(I32, ~0L), | |
134 BA->getType()); | |
135 BA->replaceAllUsesWith(DummyVal); | |
136 BA->destroyConstant(); | |
137 } | |
138 } | |
139 return Changed; | |
140 } | |
141 | |
142 bool ExpandIndirectBr::runOnModule(Module &M) { | |
143 bool Changed = false; | |
144 for (Module::iterator Func = M.begin(), E = M.end(); Func != E; ++Func) { | |
145 Changed |= convertFunction(Func); | |
146 } | |
147 return Changed; | |
148 } | |
149 | |
150 ModulePass *llvm::createExpandIndirectBrPass() { | |
151 return new ExpandIndirectBr(); | |
152 } | |
OLD | NEW |