LowerSwitch.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include "Passes.h"
00018 #include <algorithm>
00019
00020 using namespace llvm;
00021
00022 namespace klee {
00023
00024 char LowerSwitchPass::ID = 0;
00025
00026
00027 struct SwitchCaseCmp {
00028 bool operator () (const LowerSwitchPass::SwitchCase& C1,
00029 const LowerSwitchPass::SwitchCase& C2) {
00030
00031 const ConstantInt* CI1 = cast<const ConstantInt>(C1.value);
00032 const ConstantInt* CI2 = cast<const ConstantInt>(C2.value);
00033 return CI1->getValue().slt(CI2->getValue());
00034 }
00035 };
00036
00037 bool LowerSwitchPass::runOnFunction(Function &F) {
00038 bool changed = false;
00039
00040 for (Function::iterator I = F.begin(), E = F.end(); I != E; ) {
00041 BasicBlock *cur = I++;
00042
00043 if (SwitchInst *SI = dyn_cast<SwitchInst>(cur->getTerminator())) {
00044 changed = true;
00045 processSwitchInst(SI);
00046 }
00047 }
00048
00049 return changed;
00050 }
00051
00052
00053
00054 void LowerSwitchPass::switchConvert(CaseItr begin, CaseItr end,
00055 Value* value, BasicBlock* origBlock,
00056 BasicBlock* defaultBlock)
00057 {
00058 BasicBlock *curHead = defaultBlock;
00059 Function *F = origBlock->getParent();
00060
00061
00062 for (CaseItr it = begin; it < end; ++it) {
00063 BasicBlock *newBlock = BasicBlock::Create("NodeBlock");
00064 Function::iterator FI = origBlock;
00065 F->getBasicBlockList().insert(++FI, newBlock);
00066
00067 ICmpInst *cmpInst = new ICmpInst(ICmpInst::ICMP_EQ,
00068 value,
00069 it->value,
00070 "Case Comparison");
00071
00072 newBlock->getInstList().push_back(cmpInst);
00073 BranchInst::Create(it->block, curHead, cmpInst, newBlock);
00074
00075
00076
00077 for (BasicBlock::iterator bi = it->block->begin(); isa<PHINode>(bi); ++bi) {
00078 PHINode* PN = cast<PHINode>(bi);
00079
00080 int blockIndex = PN->getBasicBlockIndex(origBlock);
00081 assert(blockIndex != -1 && "Switch didn't go to this successor??");
00082 PN->setIncomingBlock((unsigned)blockIndex, newBlock);
00083 }
00084
00085 curHead = newBlock;
00086 }
00087
00088
00089 BranchInst::Create(curHead, origBlock);
00090 }
00091
00092
00093
00094
00095 void LowerSwitchPass::processSwitchInst(SwitchInst *SI) {
00096 BasicBlock *origBlock = SI->getParent();
00097 BasicBlock *defaultBlock = SI->getDefaultDest();
00098 Function *F = origBlock->getParent();
00099 Value *switchValue = SI->getOperand(0);
00100
00101
00102
00103 BasicBlock* newDefault = BasicBlock::Create("newDefault");
00104
00105 F->getBasicBlockList().insert(defaultBlock, newDefault);
00106 BranchInst::Create(defaultBlock, newDefault);
00107
00108
00109
00110 for (BasicBlock::iterator I = defaultBlock->begin(); isa<PHINode>(I); ++I) {
00111 PHINode *PN = cast<PHINode>(I);
00112 int BlockIdx = PN->getBasicBlockIndex(origBlock);
00113 assert(BlockIdx != -1 && "Switch didn't go to this successor??");
00114 PN->setIncomingBlock((unsigned)BlockIdx, newDefault);
00115 }
00116
00117 CaseVector cases;
00118 for (unsigned i = 1; i < SI->getNumSuccessors(); ++i)
00119 cases.push_back(SwitchCase(SI->getSuccessorValue(i),
00120 SI->getSuccessor(i)));
00121
00122
00123
00124
00125
00126 std::reverse(cases.begin(), cases.end());
00127
00128 switchConvert(cases.begin(), cases.end(), switchValue, origBlock, newDefault);
00129
00130
00131 origBlock->getInstList().erase(SI);
00132 }
00133
00134 }