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. |
| 129 SmallVector<Value *, 20> Users(Func->user_begin(), Func->user_end()); |
| 130 for (auto U : Users) { |
| 131 if (BlockAddress *BA = dyn_cast<BlockAddress>(U)) { |
| 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 |