本文整理汇总了C++中SwitchInst::addCase方法的典型用法代码示例。如果您正苦于以下问题:C++ SwitchInst::addCase方法的具体用法?C++ SwitchInst::addCase怎么用?C++ SwitchInst::addCase使用的例子?那么恭喜您, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类SwitchInst
的用法示例。
在下文中一共展示了SwitchInst::addCase方法的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: adjustFpuPrecision
static Value* adjustFpuPrecision(BasicBlock *&b, Value *fpuval)
{
// We only expect to be called on native FPU types that need to be
// adjusted.
NASSERT(fpuval->getType()->isX86_FP80Ty());
// Read precision flag.
// switch (pc)
// case 0: single precision
// case 2: double precision
// default: double extended (native x86)
Value *pc = F_READ(b, "FPU_PC");
CREATE_BLOCK(native_precision, b);
CREATE_BLOCK(single_precision, b);
CREATE_BLOCK(double_precision, b);
CREATE_BLOCK(done_adjusting, b);
SwitchInst *pcSwitch = SwitchInst::Create(pc, block_native_precision, 3, b);
pcSwitch->addCase(CONST_V<2>(b, 0), block_single_precision);
pcSwitch->addCase(CONST_V<2>(b, 2), block_double_precision);
pcSwitch->addCase(CONST_V<2>(b, 3), block_native_precision);
// Populate native block - no adjustment needed.
BranchInst::Create(block_done_adjusting, block_native_precision);
// Populate single precision - convert to single precision type,
// convert back to native precision, return.
Value *singlep = new FPTruncInst(fpuval,
llvm::Type::getFloatTy(block_single_precision->getContext()),
"", block_single_precision);
Value *single_ton = new FPExtInst(singlep,
llvm::Type::getX86_FP80Ty(block_single_precision->getContext()),
"", block_single_precision);
BranchInst::Create(block_done_adjusting, block_single_precision);
// Populate double precision - convert to double and then back to native.
Value *doublep = new FPTruncInst(fpuval,
llvm::Type::getDoubleTy(block_double_precision->getContext()),
"", block_double_precision);
Value *double_ton = new FPExtInst(doublep,
llvm::Type::getX86_FP80Ty(block_double_precision->getContext()),
"", block_double_precision);
BranchInst::Create(block_done_adjusting, block_double_precision);
// Populate done_adjusting block.
PHINode *adjustedVal =
PHINode::Create(Type::getX86_FP80Ty(block_done_adjusting->getContext()),
3,
"fpu_precision_adjust",
block_done_adjusting);
adjustedVal->addIncoming(fpuval, block_native_precision);
adjustedVal->addIncoming(single_ton, block_single_precision);
adjustedVal->addIncoming(double_ton, block_double_precision);
b = block_done_adjusting;
return adjustedVal;
}
示例2: switchIndirect
Function* PrepareCSI::switchIndirect(Function* F, GlobalVariable* switcher,
vector<Function*>& replicas){
F->dropAllReferences();
BasicBlock* newEntry = BasicBlock::Create(*Context, "newEntry", F);
vector<Value*> callArgs;
for(Function::arg_iterator k = F->arg_begin(), ke = F->arg_end(); k != ke; ++k)
callArgs.push_back(k);
// set up the switch
LoadInst* whichCall = new LoadInst(switcher, "chooseCall", true, newEntry);
SwitchInst* callSwitch = NULL;
// stuff we need
IntegerType* tInt = Type::getInt32Ty(*Context);
// create one bb for each possible call (instrumentation scheme)
bool aZero = false;
for(unsigned int i = 0; i < replicas.size(); ++i){
Function* newF = replicas[i];
BasicBlock* bb = BasicBlock::Create(*Context, "call", F);
if(callSwitch == NULL){
callSwitch = SwitchInst::Create(whichCall, bb, replicas.size(),
newEntry);
}
string funcName = newF->getName().str();
if(funcName.length() > 5 &&
funcName.substr(funcName.length()-5, 5) == "$none"){
callSwitch->addCase(ConstantInt::get(tInt, 0), bb);
if(aZero)
report_fatal_error("multiple defaults for function '" +
F->getName() + "'");
aZero = true;
}
else
callSwitch->addCase(ConstantInt::get(tInt, i+1), bb);
CallInst* oneCall = CallInst::Create(newF, callArgs,
(F->getReturnType()->isVoidTy()) ? "" : "theCall", bb);
oneCall->setTailCall(true);
if(F->getReturnType()->isVoidTy())
ReturnInst::Create(*Context, bb);
else
ReturnInst::Create(*Context, oneCall, bb);
}
// note that we intentionally started numbering the cases from 1 so that the
// zero case is reserved for the uninstrumented variant (if there is one)
if(!aZero)
switcher->setInitializer(ConstantInt::get(tInt, 1));
return(F);
}
示例3: doJumpIndexTableViaSwitch
void doJumpIndexTableViaSwitch(
BasicBlock *&block,
InstPtr ip)
{
Function *F = block->getParent();
Module *M = F->getParent();
// we know this conforms to
// movzx reg32, [base+disp]
// sanity check
const MCInst &inst = ip->get_inst();
const MCOperand& dest = OP(0);
const MCOperand& base = OP(1);
TASSERT(base.isReg(), "Conformant jump index tables need base to be a register");
TASSERT(dest.isReg(), "Conformant jump index tables need to write to a register");
JumpIndexTablePtr idxptr = ip->get_jump_index_table();
// to ensure no negative entries
Value *adjustment = CONST_V<32>(block, idxptr->getInitialEntry());
Value *reg_val = R_READ<32>(block, base.getReg());
Value *real_index =
BinaryOperator::Create(Instruction::Add, adjustment, reg_val, "", block);
BasicBlock *continueBlock =
BasicBlock::Create(block->getContext(), "", F, 0);
// create a default block that just traps
BasicBlock *defaultBlock =
BasicBlock::Create(block->getContext(), "", F, 0);
Function *trapFn = Intrinsic::getDeclaration(M, Intrinsic::trap);
CallInst::Create(trapFn, "", defaultBlock);
BranchInst::Create(continueBlock, defaultBlock);
// end default block
const std::vector<uint8_t> &idxblocks = idxptr->getJumpIndexTable();
// create a switch inst
SwitchInst *theSwitch = SwitchInst::Create(
real_index,
defaultBlock,
idxblocks.size(),
block);
// populate switch
int myindex = 0;
for(std::vector<uint8_t>::const_iterator itr = idxblocks.begin();
itr != idxblocks.end();
itr++)
{
BasicBlock *writeBl = emitJumpIndexWrite(F, *itr, dest.getReg(), continueBlock );
theSwitch->addCase(CONST_V<32>(block, myindex), writeBl);
++myindex;
}
// new block to write to is continue block
block = continueBlock;
}
示例4: buildCFICheck
/// buildCFICheck - emits __cfi_check for the current module.
void CrossDSOCFI::buildCFICheck() {
// FIXME: verify that __cfi_check ends up near the end of the code section,
// but before the jump slots created in LowerBitSets.
llvm::DenseSet<uint64_t> BitSetIds;
NamedMDNode *BitSetNM = M->getNamedMetadata("llvm.bitsets");
if (BitSetNM)
for (unsigned I = 0, E = BitSetNM->getNumOperands(); I != E; ++I)
if (ConstantInt *TypeId = extractBitSetTypeId(BitSetNM->getOperand(I)))
BitSetIds.insert(TypeId->getZExtValue());
LLVMContext &Ctx = M->getContext();
Constant *C = M->getOrInsertFunction(
"__cfi_check",
FunctionType::get(
Type::getVoidTy(Ctx),
{Type::getInt64Ty(Ctx), PointerType::getUnqual(Type::getInt8Ty(Ctx))},
false));
Function *F = dyn_cast<Function>(C);
F->setAlignment(4096);
auto args = F->arg_begin();
Argument &CallSiteTypeId = *(args++);
CallSiteTypeId.setName("CallSiteTypeId");
Argument &Addr = *(args++);
Addr.setName("Addr");
assert(args == F->arg_end());
BasicBlock *BB = BasicBlock::Create(Ctx, "entry", F);
BasicBlock *TrapBB = BasicBlock::Create(Ctx, "trap", F);
IRBuilder<> IRBTrap(TrapBB);
Function *TrapFn = Intrinsic::getDeclaration(M, Intrinsic::trap);
llvm::CallInst *TrapCall = IRBTrap.CreateCall(TrapFn);
TrapCall->setDoesNotReturn();
TrapCall->setDoesNotThrow();
IRBTrap.CreateUnreachable();
BasicBlock *ExitBB = BasicBlock::Create(Ctx, "exit", F);
IRBuilder<> IRBExit(ExitBB);
IRBExit.CreateRetVoid();
IRBuilder<> IRB(BB);
SwitchInst *SI = IRB.CreateSwitch(&CallSiteTypeId, TrapBB, BitSetIds.size());
for (uint64_t TypeId : BitSetIds) {
ConstantInt *CaseTypeId = ConstantInt::get(Type::getInt64Ty(Ctx), TypeId);
BasicBlock *TestBB = BasicBlock::Create(Ctx, "test", F);
IRBuilder<> IRBTest(TestBB);
Function *BitsetTestFn =
Intrinsic::getDeclaration(M, Intrinsic::bitset_test);
Value *Test = IRBTest.CreateCall(
BitsetTestFn, {&Addr, MetadataAsValue::get(
Ctx, ConstantAsMetadata::get(CaseTypeId))});
BranchInst *BI = IRBTest.CreateCondBr(Test, ExitBB, TrapBB);
BI->setMetadata(LLVMContext::MD_prof, VeryLikelyWeights);
SI->addCase(CaseTypeId, TestBB);
++TypeIds;
}
}
示例5: doJumpTableViaSwitch
void doJumpTableViaSwitch(
NativeModulePtr natM,
BasicBlock *& block,
InstPtr ip,
MCInst &inst)
{
llvm::dbgs() << __FUNCTION__ << ": Doing jumpt table via switch\n";
Function *F = block->getParent();
Module *M = F->getParent();
// we know this conforms to
// jmp [reg*4+displacement]
// sanity check
const MCOperand& scale = OP(1);
const MCOperand& index = OP(2);
TASSERT(index.isReg(), "Conformant jump tables need index to be a register");
TASSERT(scale.isImm() && scale.getImm() == 4, "Conformant jump tables have scale == 4");
MCSJumpTablePtr jmpptr = ip->get_jump_table();
// to ensure no negative entries
Value *adjustment = CONST_V<32>(block, jmpptr->getInitialEntry());
Value *reg_val = R_READ<32>(block, index.getReg());
Value *real_index =
BinaryOperator::Create(Instruction::Add, adjustment, reg_val, "", block);
// create a default block that just traps
BasicBlock *defaultBlock =
BasicBlock::Create(block->getContext(), "", block->getParent(), 0);
Function *trapFn = Intrinsic::getDeclaration(M, Intrinsic::trap);
CallInst::Create(trapFn, "", defaultBlock);
ReturnInst::Create(defaultBlock->getContext(), defaultBlock);
// end default block
const std::vector<VA> &jmpblocks = jmpptr->getJumpTable();
// create a switch inst
SwitchInst *theSwitch = SwitchInst::Create(
real_index,
defaultBlock,
jmpblocks.size(),
block);
// populate switch
int myindex = 0;
for(std::vector<VA>::const_iterator itr = jmpblocks.begin();
itr != jmpblocks.end();
itr++)
{
std::string bbname = "block_0x"+to_string<VA>(*itr, std::hex);
BasicBlock *toBlock = bbFromStrName(bbname, F);
TASSERT(toBlock != NULL, "Could not find block: "+bbname);
theSwitch->addCase(CONST_V<32>(block, myindex), toBlock);
++myindex;
}
}
示例6: switch_to
void cgs_sisd::switch_to( multi_value const& cond, std::vector< std::pair<multi_value, insert_point_t> > const& cases, insert_point_t const& default_branch )
{
assert(parallel_factor_ == 1);
Value* v = cond.load()[0];
SwitchInst* inst = builder().CreateSwitch( v, default_branch.block, static_cast<unsigned>(cases.size()) );
for( size_t i_case = 0; i_case < cases.size(); ++i_case ){
inst->addCase( llvm::cast<ConstantInt>( cases[i_case].first.load()[0] ), cases[i_case].second.block );
}
}
示例7: doJumpTableViaSwitchReg
void doJumpTableViaSwitchReg(
BasicBlock *& block,
InstPtr ip,
Value *regVal,
BasicBlock *&default_block)
{
llvm::dbgs() << __FUNCTION__ << ": Doing jumpt table via switch(reg)\n";
Function *F = block->getParent();
Module *M = F->getParent();
MCSJumpTablePtr jmpptr = ip->get_jump_table();
// create a default block that just traps
default_block =
BasicBlock::Create(block->getContext(), "", block->getParent(), 0);
// end default block
const std::vector<VA> &jmpblocks = jmpptr->getJumpTable();
std::unordered_set<VA> uniq_blocks(jmpblocks.begin(), jmpblocks.end());
// create a switch inst
SwitchInst *theSwitch = SwitchInst::Create(
regVal,
default_block,
uniq_blocks.size(),
block);
// populate switch
for(auto blockVA : uniq_blocks)
{
std::string bbname = "block_0x"+to_string<VA>(blockVA, std::hex);
BasicBlock *toBlock = bbFromStrName(bbname, F);
llvm::dbgs() << __FUNCTION__ << ": Mapping from " << to_string<VA>(blockVA, std::hex) << " => " << bbname << "\n";
TASSERT(toBlock != NULL, "Could not find block: "+bbname);
theSwitch->addCase(CONST_V<32>(block, blockVA), toBlock);
}
}
示例8: GetFPUTagV
// This is the equivalent of return fpuregs[regslot];
// FPU registers are referenced as ST(i) where i [0-7], and references a
// register slot based on the value of the TOP flag.
// So if TOP == 5, then ST(0) references register slot 5, and ST(3) references
// register slot 0.
static Value *FPUR_READV(BasicBlock *&b, Value *regslot)
{
// Check TAG register
// If TAG(regslot) != 0, then we have a problem.
Value *tagval = GetFPUTagV(b, regslot);
Function *F = b->getParent();
BasicBlock *read_normal_block =
BasicBlock::Create(b->getContext(), "fpu_read_normal", F);
//BasicBlock *read_zero_block =
// BasicBlock::Create(b->getContext(), "fpu_read_zero", F);
//BasicBlock *read_special_block =
// BasicBlock::Create(b->getContext(), "fpu_read_special", F);
BasicBlock *read_empty_block =
BasicBlock::Create(b->getContext(), "fpu_read_empty", F);
BasicBlock *fpu_read_continue =
BasicBlock::Create(b->getContext(), "fpu_read_continue", F);
// The default case should never be hit. Use LLVM Switch Node.
SwitchInst *tagSwitch = SwitchInst::Create(tagval, read_empty_block, 4, b);
tagSwitch->addCase(CONST_V<2>(b, FPU_TAG_VALID), read_normal_block);
tagSwitch->addCase(CONST_V<2>(b, FPU_TAG_ZERO), read_normal_block);
tagSwitch->addCase(CONST_V<2>(b, FPU_TAG_SPECIAL), read_normal_block);
//tagSwitch->addCase(CONST_V<2>(b, 1), read_zero_block);
//tagSwitch->addCase(CONST_V<2>(b, 2), read_special_block);
//tagSwitch->addCase(CONST_V<2>(b, 3), read_empty_block);
Value *streg = GetFPURegV(read_normal_block, regslot);
Value *loadVal = new LoadInst(streg, "", read_normal_block);
// C1 is set load needs to round up and cleared otherwise.
FPUF_CLEAR(read_normal_block, "C1");
BranchInst::Create(fpu_read_continue, read_normal_block);
// Populate read zero block.
// This is the zero block. Return zero.
// But there are two zeros - negative and positive.
// Check the sign of the number, then return +0 or -0.
//Value *streg_z = GetFPURegV(read_zero_block, regslot);
//Value *loadVal_z = new LoadInst(streg_z, "", read_zero_block);
//Value *neg_zero = ConstantFP::getNegativeZero(Type::getX86_FP80Ty(read_zero_block->getContext()));
// Is the value we loaded less than or equal to -0.0?
//Value *fcmp_inst = new FCmpInst(*read_zero_block, FCmpInst::FCMP_OLE, loadVal_z, neg_zero, "");
// if val <= -0.0, return -0.0. Otherwise, return +0.0.
//Value *zval = SelectInst::Create(fcmp_inst, neg_zero,
// CONSTFP_V(read_zero_block, 0.0), "", read_zero_block);
//BranchInst::Create(fpu_read_continue, read_zero_block);
// Populate read special block.
// TODO: Check if we need special NaN handling.
//BranchInst::Create(fpu_read_continue, read_special_block);
//Value *streg_s = GetFPURegV(read_special_block, regslot);
//Value *loadVal_s = new LoadInst(streg_s, "", read_special_block);
//BranchInst::Create(fpu_read_continue, read_special_block);
// Populate read empty block.
// For now, just branch to fpu_read_continue and clear C1 to indicate stack
// underflow.
// TODO: Throw an exception.
FPUF_CLEAR(read_empty_block, "C1");
Value *zval = CONSTFP_V(read_empty_block, 0.0);
BranchInst::Create(fpu_read_continue, read_empty_block);
// Populate continue block.
// Use phi instruction to determine value that was loaded.
PHINode *whichval =
PHINode::Create(Type::getX86_FP80Ty(F->getContext()),
2,
"fpu_switch_phinode",
fpu_read_continue);
whichval->addIncoming(loadVal, read_normal_block);
//whichval->addIncoming(zval, read_zero_block);
//whichval->addIncoming(loadVal_s, read_special_block);
// Would not get here, but throw exception?
whichval->addIncoming(zval, read_empty_block);
b = fpu_read_continue;
// Read PC flag and adjust precision based on its value.
Value *precision_adjusted = adjustFpuPrecision(b, whichval);
return precision_adjusted;
}
示例9: convertFunction
static bool convertFunction(Function *Func) {
bool Changed = false;
IntegerType *I32 = Type::getInt32Ty(Func->getContext());
// Skip zero in case programs treat a null pointer as special.
uint32_t NextNum = 1;
DenseMap<BasicBlock *, ConstantInt *> LabelNums;
BasicBlock *DefaultBB = NULL;
// Replace each indirectbr with a switch.
//
// If there are multiple indirectbr instructions in the function,
// this could be expensive. While an indirectbr is usually
// converted to O(1) machine instructions, the switch we generate
// here will be O(n) in the number of target labels.
//
// However, Clang usually generates just a single indirectbr per
// function anyway when compiling C computed gotos.
//
// We could try to generate one switch to handle all the indirectbr
// instructions in the function, but that would be complicated to
// implement given that variables that are live at one indirectbr
// might not be live at others.
for (llvm::Function::iterator BB = Func->begin(), E = Func->end();
BB != E; ++BB) {
if (IndirectBrInst *Br = dyn_cast<IndirectBrInst>(BB->getTerminator())) {
Changed = true;
if (!DefaultBB) {
DefaultBB = BasicBlock::Create(Func->getContext(),
"indirectbr_default", Func);
new UnreachableInst(Func->getContext(), DefaultBB);
}
// An indirectbr can list the same target block multiple times.
// Keep track of the basic blocks we've handled to avoid adding
// the same case multiple times.
DenseSet<BasicBlock *> BlocksSeen;
Value *Cast = new PtrToIntInst(Br->getAddress(), I32,
"indirectbr_cast", Br);
unsigned Count = Br->getNumSuccessors();
SwitchInst *Switch = SwitchInst::Create(Cast, DefaultBB, Count, Br);
for (unsigned I = 0; I < Count; ++I) {
BasicBlock *Dest = Br->getSuccessor(I);
if (!BlocksSeen.insert(Dest).second) {
// Remove duplicated entries from phi nodes.
for (BasicBlock::iterator Inst = Dest->begin(); ; ++Inst) {
PHINode *Phi = dyn_cast<PHINode>(Inst);
if (!Phi)
break;
Phi->removeIncomingValue(Br->getParent());
}
continue;
}
ConstantInt *Val;
if (LabelNums.count(Dest) == 0) {
Val = ConstantInt::get(I32, NextNum++);
LabelNums[Dest] = Val;
BlockAddress *BA = BlockAddress::get(Func, Dest);
Value *ValAsPtr = ConstantExpr::getIntToPtr(Val, BA->getType());
BA->replaceAllUsesWith(ValAsPtr);
BA->destroyConstant();
} else {
Val = LabelNums[Dest];
}
Switch->addCase(Val, Br->getSuccessor(I));
}
Br->eraseFromParent();
}
}
// If there are any blockaddresses that are never used by an
// indirectbr, replace them with dummy values.
SmallVector<Value *, 20> Users(Func->user_begin(), Func->user_end());
for (auto U : Users) {
if (BlockAddress *BA = dyn_cast<BlockAddress>(U)) {
Changed = true;
Value *DummyVal = ConstantExpr::getIntToPtr(ConstantInt::get(I32, ~0L),
BA->getType());
BA->replaceAllUsesWith(DummyVal);
BA->destroyConstant();
}
}
return Changed;
}
示例10: buildCFICheck
/// buildCFICheck - emits __cfi_check for the current module.
void CrossDSOCFI::buildCFICheck(Module &M) {
// FIXME: verify that __cfi_check ends up near the end of the code section,
// but before the jump slots created in LowerTypeTests.
llvm::DenseSet<uint64_t> TypeIds;
SmallVector<MDNode *, 2> Types;
for (GlobalObject &GO : M.global_objects()) {
Types.clear();
GO.getMetadata(LLVMContext::MD_type, Types);
for (MDNode *Type : Types) {
// Sanity check. GO must not be a function declaration.
assert(!isa<Function>(&GO) || !cast<Function>(&GO)->isDeclaration());
if (ConstantInt *TypeId = extractNumericTypeId(Type))
TypeIds.insert(TypeId->getZExtValue());
}
}
LLVMContext &Ctx = M.getContext();
Constant *C = M.getOrInsertFunction(
"__cfi_check", Type::getVoidTy(Ctx), Type::getInt64Ty(Ctx),
Type::getInt8PtrTy(Ctx), Type::getInt8PtrTy(Ctx), nullptr);
Function *F = dyn_cast<Function>(C);
F->setAlignment(4096);
auto args = F->arg_begin();
Value &CallSiteTypeId = *(args++);
CallSiteTypeId.setName("CallSiteTypeId");
Value &Addr = *(args++);
Addr.setName("Addr");
Value &CFICheckFailData = *(args++);
CFICheckFailData.setName("CFICheckFailData");
assert(args == F->arg_end());
BasicBlock *BB = BasicBlock::Create(Ctx, "entry", F);
BasicBlock *ExitBB = BasicBlock::Create(Ctx, "exit", F);
BasicBlock *TrapBB = BasicBlock::Create(Ctx, "fail", F);
IRBuilder<> IRBFail(TrapBB);
Constant *CFICheckFailFn = M.getOrInsertFunction(
"__cfi_check_fail", Type::getVoidTy(Ctx), Type::getInt8PtrTy(Ctx),
Type::getInt8PtrTy(Ctx), nullptr);
IRBFail.CreateCall(CFICheckFailFn, {&CFICheckFailData, &Addr});
IRBFail.CreateBr(ExitBB);
IRBuilder<> IRBExit(ExitBB);
IRBExit.CreateRetVoid();
IRBuilder<> IRB(BB);
SwitchInst *SI = IRB.CreateSwitch(&CallSiteTypeId, TrapBB, TypeIds.size());
for (uint64_t TypeId : TypeIds) {
ConstantInt *CaseTypeId = ConstantInt::get(Type::getInt64Ty(Ctx), TypeId);
BasicBlock *TestBB = BasicBlock::Create(Ctx, "test", F);
IRBuilder<> IRBTest(TestBB);
Function *BitsetTestFn = Intrinsic::getDeclaration(&M, Intrinsic::type_test);
Value *Test = IRBTest.CreateCall(
BitsetTestFn, {&Addr, MetadataAsValue::get(
Ctx, ConstantAsMetadata::get(CaseTypeId))});
BranchInst *BI = IRBTest.CreateCondBr(Test, ExitBB, TrapBB);
BI->setMetadata(LLVMContext::MD_prof, VeryLikelyWeights);
SI->addCase(CaseTypeId, TestBB);
++NumTypeIds;
}
}
示例11: runSjLjOnFunction
//.........这里部分代码省略.........
assert(ThrewResetSI && "Cannot find __THREW__ store after invoke");
Tail = SplitBlock(BB, ThrewResetSI->getNextNode());
} else {
// Wrap call with invoke wrapper and generate preamble/postamble
Threw = wrapInvoke(CI);
ToErase.push_back(CI);
Tail = SplitBlock(BB, CI->getNextNode());
}
// We need to replace the terminator in Tail - SplitBlock makes BB go
// straight to Tail, we need to check if a longjmp occurred, and go to the
// right setjmp-tail if so
ToErase.push_back(BB->getTerminator());
// Generate a function call to testSetjmp function and preamble/postamble
// code to figure out (1) whether longjmp occurred (2) if longjmp
// occurred, which setjmp it corresponds to
Value *Label = nullptr;
Value *LongjmpResult = nullptr;
BasicBlock *EndBB = nullptr;
wrapTestSetjmp(BB, CI, Threw, SetjmpTable, SetjmpTableSize, Label,
LongjmpResult, EndBB);
assert(Label && LongjmpResult && EndBB);
// Create switch instruction
IRB.SetInsertPoint(EndBB);
SwitchInst *SI = IRB.CreateSwitch(Label, Tail, SetjmpRetPHIs.size());
// -1 means no longjmp happened, continue normally (will hit the default
// switch case). 0 means a longjmp that is not ours to handle, needs a
// rethrow. Otherwise the index is the same as the index in P+1 (to avoid
// 0).
for (unsigned i = 0; i < SetjmpRetPHIs.size(); i++) {
SI->addCase(IRB.getInt32(i + 1), SetjmpRetPHIs[i]->getParent());
SetjmpRetPHIs[i]->addIncoming(LongjmpResult, EndBB);
}
// We are splitting the block here, and must continue to find other calls
// in the block - which is now split. so continue to traverse in the Tail
BBs.push_back(Tail);
}
}
// Erase everything we no longer need in this function
for (Instruction *I : ToErase)
I->eraseFromParent();
// Free setjmpTable buffer before each return instruction
for (BasicBlock &BB : F) {
TerminatorInst *TI = BB.getTerminator();
if (isa<ReturnInst>(TI))
CallInst::CreateFree(SetjmpTable, TI);
}
// Every call to saveSetjmp can change setjmpTable and setjmpTableSize
// (when buffer reallocation occurs)
// entry:
// setjmpTableSize = 4;
// setjmpTable = (int *) malloc(40);
// setjmpTable[0] = 0;
// ...
// somebb:
// setjmpTable = saveSetjmp(buf, label, setjmpTable, setjmpTableSize);
// setjmpTableSize = __tempRet0;
// So we need to make sure the SSA for these variables is valid so that every
// saveSetjmp and testSetjmp calls have the correct arguments.
示例12: LoadInst
BasicBlock *
cpu_translate_all(cpu_t *cpu, BasicBlock *bb_ret, BasicBlock *bb_trap)
{
// find all instructions that need labels and create basic blocks for them
int bbs = 0;
addr_t pc;
pc = cpu->code_start;
while (pc < cpu->code_end) {
// Do not create the basic block if it is already present in some other function.
if (is_start_of_basicblock(cpu, pc) && !(get_tag(cpu, pc) & TAG_TRANSLATED)) {
create_basicblock(cpu, pc, cpu->cur_func, BB_TYPE_NORMAL);
bbs++;
}
pc++;
}
LOG("bbs: %d\n", bbs);
// create dispatch basicblock
BasicBlock* bb_dispatch = BasicBlock::Create(_CTX(), "dispatch", cpu->cur_func, 0);
Value *v_pc = new LoadInst(cpu->ptr_PC, "", false, bb_dispatch);
SwitchInst* sw = SwitchInst::Create(v_pc, bb_ret, bbs, bb_dispatch);
// translate basic blocks
bbaddr_map &bb_addr = cpu->func_bb[cpu->cur_func];
bbaddr_map::const_iterator it;
for (it = bb_addr.begin(); it != bb_addr.end(); it++) {
pc = it->first;
BasicBlock *cur_bb = it->second;
tag_t tag;
BasicBlock *bb_target = NULL, *bb_next = NULL, *bb_cont = NULL;
// Tag the function as translated.
or_tag(cpu, pc, TAG_TRANSLATED);
LOG("basicblock: L%08llx\n", (unsigned long long)pc);
// Add dispatch switch case for basic block.
ConstantInt* c = ConstantInt::get(getIntegerType(cpu->info.address_size), pc);
sw->addCase(c, cur_bb);
do {
tag_t dummy1;
if (LOGGING)
disasm_instr(cpu, pc);
tag = get_tag(cpu, pc);
/* get address of the following instruction */
addr_t new_pc, next_pc;
cpu->f.tag_instr(cpu, pc, &dummy1, &new_pc, &next_pc);
/* get target basic block */
if (tag & TAG_RET)
bb_target = bb_dispatch;
if (tag & (TAG_CALL|TAG_BRANCH)) {
if (new_pc == NEW_PC_NONE) /* translate_instr() will set PC */
bb_target = bb_dispatch;
else
bb_target = (BasicBlock*)lookup_basicblock(cpu, cpu->cur_func, new_pc, bb_ret, BB_TYPE_NORMAL);
}
/* get not-taken basic block */
if (tag & TAG_CONDITIONAL)
bb_next = (BasicBlock*)lookup_basicblock(cpu, cpu->cur_func, next_pc, bb_ret, BB_TYPE_NORMAL);
bb_cont = translate_instr(cpu, pc, tag, bb_target, bb_trap, bb_next, cur_bb);
pc = next_pc;
} while (
/* new basic block starts here (and we haven't translated it yet)*/
(!is_start_of_basicblock(cpu, pc)) &&
/* end of code section */ //XXX no: this is whether it's TAG_CODE
is_code(cpu, pc) &&
/* last intruction jumped away */
bb_cont
);
/* link with next basic block if there isn't a control flow instr. already */
if (bb_cont) {
BasicBlock *target = (BasicBlock*)lookup_basicblock(cpu, cpu->cur_func, pc, bb_ret, BB_TYPE_NORMAL);
LOG("info: linking continue $%04llx!\n", (unsigned long long)pc);
BranchInst::Create(target, bb_cont);
}
}
return bb_dispatch;
}
示例13: compile
llvm::Function* compile(PyCodeObject* co, int inlineopcodes = 1) {
using namespace llvm;
std::string fname = make_function_name(co);
// XXX check if function already exists
Function* func = Function::Create(ty_jitted_function, Function::ExternalLinkage, fname.c_str(), the_module);
Function::arg_iterator func_args = func->arg_begin();
Value* func_f = func_args++;
func_f->setName("f");
Value* func_tstate = func_args++;
func_tstate->setName("tstate");
Value* func_throwflag = func_args++; // XXX
func_throwflag->setName("throwflag");
std::vector<CallInst*> to_inline;
const uint8_t* bytecode = (const uint8_t*) PyString_AS_STRING(co->co_code);
Py_ssize_t codelen = PyString_Size(co->co_code);
BasicBlock* entry = BasicBlock::Create("entry", func);
BasicBlock* gen_throw_block = BasicBlock::Create("gen_throw", func);
IRBuilder<> builder(entry);
Value* st_var = builder.CreateAlloca(the_module->getTypeByName("struct.interpreter_state"), 0, "st");
CallInst* init_st = builder.CreateCall3(the_module->getFunction("init_interpreter_state"), st_var, func_f, func_tstate);
to_inline.push_back(init_st);
Value* dispatch_var = builder.CreateAlloca(Type::Int32Ty, 0, "dispatch_to_instr");
BasicBlock* end_block = BasicBlock::Create("end", func);
{
builder.SetInsertPoint(end_block);
CallInst* retvalval = builder.CreateCall(the_module->getFunction("get_retval"), st_var);
to_inline.push_back(retvalval);
builder.CreateRet(retvalval);
}
// create the opcode blocks
BasicBlock* dispatch_block = BasicBlock::Create("dispatch", func);
builder.SetInsertPoint(dispatch_block);
Value* dispatch_val = builder.CreateLoad(dispatch_var);
SwitchInst* dispatch_switch = builder.CreateSwitch(dispatch_val, end_block);
std::vector<BasicBlock*> opblocks(codelen);
for (const uint8_t* cur_instr = bytecode; *cur_instr; ++cur_instr) {
int line = cur_instr - bytecode;
unsigned int opcode = *cur_instr;
if (HAS_ARG(opcode)) cur_instr += 2;
char opblockname[20];
sprintf(opblockname, "__op_%d", line);
BasicBlock* opblock = BasicBlock::Create(std::string(opblockname), func);
opblocks[line] = opblock;
dispatch_switch->addCase(constant(line), opblock);
}
BasicBlock* block_end_block = BasicBlock::Create("block_end", func);
// if throwflag goto block_end else dispatch to opblocks[f_lasti+1]
builder.SetInsertPoint(entry);
CallInst* gli = builder.CreateCall(the_module->getFunction("get_lasti"),
func_f);
to_inline.push_back(gli);
Value* lastipp = builder.CreateAdd(gli, constant(1));
builder.CreateStore(lastipp, dispatch_var);
builder.CreateCondBr(is_zero(builder, func_throwflag), dispatch_block, gen_throw_block);
builder.SetInsertPoint(gen_throw_block);
to_inline.push_back(builder.CreateCall2(the_module->getFunction("set_why"), st_var, constant(WHY_EXCEPTION)));
builder.CreateBr(block_end_block);
// fill in the opcode blocks
for (const uint8_t* cur_instr = bytecode; *cur_instr; ++cur_instr) {
int line = cur_instr - bytecode;
unsigned int opcode = *cur_instr;
unsigned int oparg = 0;
if (HAS_ARG(opcode)) {
unsigned int arg1 = *++cur_instr;
unsigned int arg2 = *++cur_instr;
oparg = (arg2 << 8) + arg1;
}
builder.SetInsertPoint(opblocks[line]);
std::vector<Value*> opcode_args = vector_of
(st_var)
(constant(line))
(constant(opcode))
(constant(oparg))
.move();
Function* ophandler;
CallInst* opret;
# define DEFAULT_HANDLER \
if (opcode_funcs.count(opcode)) ophandler = opcode_funcs[opcode]; \
else ophandler = opcode_unimplemented; \
assert(ophandler); \
opret = builder.CreateCall(ophandler, opcode_args.begin(), opcode_args.end()); \
//.........这里部分代码省略.........
示例14: runOnModule
//.........这里部分代码省略.........
Function *F = I->first;
Phis& P = I->second;
CallInst::Create(PrepSetjmp, "", F->begin()->begin());
// Update each call that can longjmp so it can return to a setjmp where relevant
for (Function::iterator BBI = F->begin(), E = F->end(); BBI != E; ) {
BasicBlock *BB = BBI++;
for (BasicBlock::iterator Iter = BB->begin(), E = BB->end(); Iter != E; ) {
Instruction *I = Iter++;
CallInst *CI;
if ((CI = dyn_cast<CallInst>(I))) {
Value *V = CI->getCalledValue();
if (V == PrepSetjmp || V == EmSetjmp || V == CheckLongjmp || V == GetLongjmpResult || V == PreInvoke || V == PostInvoke) continue;
if (Function *CF = dyn_cast<Function>(V)) if (CF->isIntrinsic()) continue;
// TODO: proper analysis of what can actually longjmp. Currently we assume anything but setjmp can.
// This may longjmp, so we need to check if it did. Split at that point, and
// envelop the call in pre/post invoke, if we need to
CallInst *After;
Instruction *Check = NULL;
if (Iter != E && (After = dyn_cast<CallInst>(Iter)) && After->getCalledValue() == PostInvoke) {
// use the pre|postinvoke that exceptions lowering already made
Check = Iter++;
}
BasicBlock *Tail = SplitBlock(BB, Iter); // Iter already points to the next instruction, as we need
TerminatorInst *TI = BB->getTerminator();
if (!Check) {
// no existing pre|postinvoke, create our own
CallInst::Create(PreInvoke, "", CI);
Check = CallInst::Create(PostInvoke, "", TI); // CI is at the end of the block
// If we are calling a function that is noreturn, we must remove that attribute. The code we
// insert here does expect it to return, after we catch the exception.
if (CI->doesNotReturn()) {
if (Function *F = dyn_cast<Function>(CI->getCalledValue())) {
F->removeFnAttr(Attribute::NoReturn);
}
CI->setAttributes(CI->getAttributes().removeAttribute(TheModule->getContext(), AttributeSet::FunctionIndex, Attribute::NoReturn));
assert(!CI->doesNotReturn());
}
}
// We need to replace the terminator in Tail - SplitBlock makes BB go straight to Tail, we need to check if a longjmp occurred, and
// go to the right setjmp-tail if so
SmallVector<Value *, 1> Args;
Args.push_back(Check);
Instruction *LongjmpCheck = CallInst::Create(CheckLongjmp, Args, "", BB);
Instruction *LongjmpResult = CallInst::Create(GetLongjmpResult, Args, "", BB);
SwitchInst *SI = SwitchInst::Create(LongjmpCheck, Tail, 2, BB);
// -1 means no longjmp happened, continue normally (will hit the default switch case). 0 means a longjmp that is not ours to handle, needs a rethrow. Otherwise
// the index mean is the same as the index in P+1 (to avoid 0).
for (unsigned i = 0; i < P.size(); i++) {
SI->addCase(cast<ConstantInt>(ConstantInt::get(i32, i+1)), P[i]->getParent());
P[i]->addIncoming(LongjmpResult, BB);
}
ToErase.push_back(TI); // new terminator is now the switch
// we are splitting the block here, and must continue to find other calls in the block - which is now split. so continue
// to traverse in the Tail
BB = Tail;
Iter = BB->begin();
E = BB->end();
} else if (InvokeInst *CI = dyn_cast<InvokeInst>(I)) { // XXX check if target is setjmp
(void)CI;
report_fatal_error("TODO: invoke inside setjmping functions");
}
}
}
// add a cleanup before each return
for (Function::iterator BBI = F->begin(), E = F->end(); BBI != E; ) {
BasicBlock *BB = BBI++;
TerminatorInst *TI = BB->getTerminator();
if (isa<ReturnInst>(TI)) {
CallInst::Create(CleanupSetjmp, "", TI);
}
}
}
for (unsigned i = 0; i < ToErase.size(); i++) {
ToErase[i]->eraseFromParent();
}
// Finally, our modifications to the cfg can break dominance of SSA variables. For example,
// if (x()) { .. setjmp() .. }
// if (y()) { .. longjmp() .. }
// We must split the longjmp block, and it can jump into the setjmp one. But that means that when
// we split the setjmp block, it's first part no longer dominates its second part - there is
// a theoretically possible control flow path where x() is false, then y() is true and we
// reach the second part of the setjmp block, without ever reaching the first part. So,
// we recalculate regs vs. mem
for (FunctionPhisMap::iterator I = SetjmpOutputPhis.begin(); I != SetjmpOutputPhis.end(); I++) {
Function *F = I->first;
doRegToMem(*F);
doMemToReg(*F);
}
return true;
}
示例15: TErr
static BasicBlock *doCmpsV(BasicBlock *pred) {
Value *lhsRegVal = R_READ<32>(pred, X86::ESI);
Value *lhsFromMem = M_READ_0<width>(pred, lhsRegVal);
Value *rhsRegVal = R_READ<32>(pred, X86::EDI);
Value *rhsFromMem = M_READ_0<width>(pred, rhsRegVal);
//perform a subtraction
Value *res = BinaryOperator::CreateSub(lhsFromMem, rhsFromMem, "", pred);
//set flags according to this result
WritePF<width>(pred, res);
WriteZF<width>(pred, res);
WriteSF<width>(pred, res);
WriteCFSub(pred, lhsFromMem, rhsFromMem);
WriteAFAddSub<width>(pred, res, lhsFromMem, rhsFromMem);
WriteOFSub<width>(pred, res, lhsFromMem, rhsFromMem);
//now, either increment or decrement EDI based on the DF flag
CREATE_BLOCK(df_zero, pred);
CREATE_BLOCK(df_one, pred);
CREATE_BLOCK(post_write, pred);
Value *df = F_READ(pred, DF);
SwitchInst *dfSwitch = SwitchInst::Create(df, block_df_zero, 2, pred);
dfSwitch->addCase(CONST_V<1>(pred, 0), block_df_zero);
dfSwitch->addCase(CONST_V<1>(pred, 1), block_df_one);
uint32_t disp;
switch(width) {
case 8:
disp = 1;
break;
case 16:
disp = 2;
break;
case 32:
disp = 4;
break;
case 64:
disp = 8;
break;
default:
throw TErr(__LINE__, __FILE__, "Invalid width");
}
//if zero, then add to src and dst registers
Value *add_lhs =
BinaryOperator::CreateAdd( lhsRegVal,
CONST_V<32>(block_df_zero, disp),
"",
block_df_zero);
Value *add_rhs =
BinaryOperator::CreateAdd( rhsRegVal,
CONST_V<32>(block_df_zero, disp),
"",
block_df_zero);
R_WRITE<32>(block_df_zero, X86::ESI, add_lhs);
R_WRITE<32>(block_df_zero, X86::EDI, add_rhs);
// return to a single block, to which we will add new instructions
BranchInst::Create(block_post_write, block_df_zero);
//if one, then sub to src and dst registers
Value *sub_lhs =
BinaryOperator::CreateSub( lhsRegVal,
CONST_V<32>(block_df_one, disp),
"",
block_df_one);
Value *sub_rhs =
BinaryOperator::CreateSub( rhsRegVal,
CONST_V<32>(block_df_one, disp),
"",
block_df_one);
R_WRITE<32>(block_df_one, X86::ESI, sub_lhs);
R_WRITE<32>(block_df_one, X86::EDI, sub_rhs);
// return to a single block, to which we will add new instructions
BranchInst::Create(block_post_write, block_df_one);
return block_post_write;
}