in X86/X86MachineInstructionRaiser.cpp [4017:4326]
bool X86MachineInstructionRaiser::raiseDirectBranchMachineInstr(
ControlTransferInfo *CTRec) {
const MachineInstr *MI = CTRec->CandidateMachineInstr;
BasicBlock *CandBB = CTRec->CandidateBlock;
const MCInstrDesc &MCID = MI->getDesc();
// Make sure this function was called on a direct branch instruction.
assert(X86II::isImmPCRel(MCID.TSFlags) &&
"PC-Relative control transfer expected");
// Get branch offset of the branch instruction
const MachineOperand &MO = MI->getOperand(0);
assert(MO.isImm() && "Expected immediate operand not found");
int64_t BranchOffset = MO.getImm();
MCInstRaiser *MCIR = getMCInstRaiser();
// Get MCInst offset - the offset of machine instruction in the binary
uint64_t MCInstOffset = MCIR->getMCInstIndex(*MI);
assert(MCIR != nullptr && "MCInstRaiser not initialized");
int64_t BranchTargetOffset =
MCInstOffset + MCIR->getMCInstSize(MCInstOffset) + BranchOffset;
const int64_t TgtMBBNo =
MCIR->getMBBNumberOfMCInstOffset(BranchTargetOffset, MF);
assert((TgtMBBNo != -1) && "No branch target found");
auto iter = mbbToBBMap.find(TgtMBBNo);
assert(iter != mbbToBBMap.end() &&
"BasicBlock corresponding to MachineInstr branch not found");
BasicBlock *TgtBB = (*iter).second;
if (MI->isUnconditionalBranch()) {
// Just create a branch instruction targeting TgtBB
BranchInst *UncondBr = BranchInst::Create(TgtBB);
CandBB->getInstList().push_back(UncondBr);
CTRec->Raised = true;
} else if (MI->isConditionalBranch()) {
// Find the fall through basic block
MCInstRaiser::const_mcinst_iter MCIter = MCIR->getMCInstAt(MCInstOffset);
LLVMContext &Ctx(MF.getFunction().getContext());
// Go to next non-nop instruction on the fall-through path.
bool isNop = true;
while (isNop) {
MCIter++;
isNop = isNoop(MCIter->second.getMCInst().getOpcode());
assert(MCIter != MCIR->const_mcinstr_end() &&
"Attempt to go past MCInstr stream");
}
// Get MBB number whose lead instruction is at the offset of fall-through
// non-nop instruction. This is the fall-through MBB.
int64_t FTMBBNum = MCIR->getMBBNumberOfMCInstOffset((*MCIter).first, MF);
assert((FTMBBNum != -1) && "No fall-through target found");
if (MF.getBlockNumbered(FTMBBNum)->empty())
assert(false && "Fall-through empty");
// Find raised BasicBlock corresponding to fall-through MBB
auto mapIter = mbbToBBMap.find(FTMBBNum);
assert(mapIter != mbbToBBMap.end() &&
"Fall-through BasicBlock corresponding to MachineInstr branch not "
"found");
BasicBlock *FTBB = (*mapIter).second;
// Get the condition value
assert(CTRec->RegValues.size() == EFlagBits.size() &&
"Unexpected number of EFLAGS bit values in conditional branch not "
"handled");
// Branch condition value
Value *BranchCond = nullptr;
// Predicate operation to be performed
Value *TrueValue = ConstantInt::getTrue(Ctx);
Value *FalseValue = ConstantInt::getFalse(Ctx);
auto Opcode = MI->getOpcode();
assert(((Opcode == X86::JCC_1) || (Opcode == X86::JCC_2) ||
(Opcode == X86::JCC_4)) &&
"Conditional branch instruction expected");
X86::CondCode CC = X86::COND_INVALID;
// Unfortunately X86::getCondFromBranch(MI) only looks at JCC_1. We need
// to handle JCC_2 and JCC_4 as well.
switch (MI->getOpcode()) {
default:
CC = X86::COND_INVALID;
break;
case X86::JCC_1:
case X86::JCC_2:
case X86::JCC_4:
CC = static_cast<X86::CondCode>(
MI->getOperand(MI->getDesc().getNumOperands() - 1).getImm());
}
switch (CC) {
case X86::COND_B: {
// Test CF == 1
int CFIndex = getEflagBitIndex(EFLAGS::CF);
Value *CFValue = CTRec->RegValues[CFIndex];
assert(CFValue != nullptr &&
"Failed to get EFLAGS value while raising JB");
// Construct a compare instruction
BranchCond = new ICmpInst(CmpInst::Predicate::ICMP_EQ, CFValue, TrueValue,
"CmpCF_JB");
CandBB->getInstList().push_back(dyn_cast<Instruction>(BranchCond));
} break;
case X86::COND_E: {
// Test ZF == 1
int ZFIndex = getEflagBitIndex(EFLAGS::ZF);
Value *ZFValue = CTRec->RegValues[ZFIndex];
assert(ZFValue != nullptr &&
"Failed to get EFLAGS value while raising JE");
// Construct a compare instruction
BranchCond = new ICmpInst(CmpInst::Predicate::ICMP_EQ, ZFValue, TrueValue,
"CmpZF_JE");
CandBB->getInstList().push_back(dyn_cast<Instruction>(BranchCond));
} break;
case X86::COND_NE: {
// Test ZF == 0
int ZFIndex = getEflagBitIndex(EFLAGS::ZF);
Value *ZFValue = CTRec->RegValues[ZFIndex];
assert(ZFValue != nullptr &&
"Failed to get EFLAGS value while raising JNE");
// Construct a compare instruction
BranchCond = new ICmpInst(CmpInst::Predicate::ICMP_EQ, ZFValue,
FalseValue, "CmpZF_JNE");
CandBB->getInstList().push_back(dyn_cast<Instruction>(BranchCond));
} break;
case X86::COND_S: {
// Test SF == 1
int SFIndex = getEflagBitIndex(EFLAGS::SF);
Value *SFValue = CTRec->RegValues[SFIndex];
assert(SFValue != nullptr &&
"Failed to get EFLAGS value while raising JS");
// Construct a compare instruction
BranchCond = new ICmpInst(CmpInst::Predicate::ICMP_EQ, SFValue, TrueValue,
"CmpSF_JS");
CandBB->getInstList().push_back(dyn_cast<Instruction>(BranchCond));
} break;
case X86::COND_NS: {
// Test SF == 0
int SFIndex = getEflagBitIndex(EFLAGS::SF);
Value *SFValue = CTRec->RegValues[SFIndex];
assert(SFValue != nullptr &&
"Failed to get EFLAGS value while raising JNS");
// Construct a compare instruction
BranchCond = new ICmpInst(CmpInst::Predicate::ICMP_EQ, SFValue,
FalseValue, "CmpSF_JNS");
CandBB->getInstList().push_back(dyn_cast<Instruction>(BranchCond));
} break;
case X86::COND_A: {
// CF == 0 and ZF == 0
int CFIndex = getEflagBitIndex(EFLAGS::CF);
int ZFIndex = getEflagBitIndex(EFLAGS::ZF);
Value *CFValue = CTRec->RegValues[CFIndex];
Value *ZFValue = CTRec->RegValues[ZFIndex];
assert((CFValue != nullptr) && (ZFValue != nullptr) &&
"Failed to get EFLAGS value while raising JA");
// Test CF == 0
Instruction *CFCond = new ICmpInst(CmpInst::Predicate::ICMP_EQ, CFValue,
FalseValue, "CFCmp_JA");
CandBB->getInstList().push_back(CFCond);
// Test ZF == 0
Instruction *ZFCond = new ICmpInst(CmpInst::Predicate::ICMP_EQ, ZFValue,
FalseValue, "ZFCmp_JA");
CandBB->getInstList().push_back(ZFCond);
BranchCond = BinaryOperator::CreateAnd(ZFCond, CFCond, "CFAndZF_JA");
CandBB->getInstList().push_back(dyn_cast<Instruction>(BranchCond));
} break;
case X86::COND_AE: {
// CF == 0
int CFIndex = getEflagBitIndex(EFLAGS::CF);
Value *CFValue = CTRec->RegValues[CFIndex];
assert(CFValue != nullptr &&
"Failed to get EFLAGS value while raising JAE");
// Compare CF == 0
BranchCond = new ICmpInst(CmpInst::Predicate::ICMP_EQ, CFValue,
FalseValue, "CFCmp_JAE");
CandBB->getInstList().push_back(dyn_cast<Instruction>(BranchCond));
} break;
case X86::COND_BE: {
// CF == 1 or ZF == 1
int CFIndex = getEflagBitIndex(EFLAGS::CF);
int ZFIndex = getEflagBitIndex(EFLAGS::ZF);
Value *CFValue = CTRec->RegValues[CFIndex];
Value *ZFValue = CTRec->RegValues[ZFIndex];
assert((CFValue != nullptr) && (ZFValue != nullptr) &&
"Failed to get EFLAGS value while raising JBE");
// Compare CF == 1
Instruction *CFCond = new ICmpInst(CmpInst::Predicate::ICMP_EQ, CFValue,
TrueValue, "CFCmp_JBE");
CandBB->getInstList().push_back(CFCond);
// Compare ZF == 1
Instruction *ZFCond = new ICmpInst(CmpInst::Predicate::ICMP_EQ, ZFValue,
TrueValue, "ZFCmp_JBE");
CandBB->getInstList().push_back(ZFCond);
BranchCond = BinaryOperator::CreateOr(ZFCond, CFCond, "CFAndZF_JBE");
CandBB->getInstList().push_back(dyn_cast<Instruction>(BranchCond));
} break;
case X86::COND_G: {
// ZF == 0 and (SF == OF)
int ZFIndex = getEflagBitIndex(EFLAGS::ZF);
int SFIndex = getEflagBitIndex(EFLAGS::SF);
int OFIndex = getEflagBitIndex(EFLAGS::OF);
Value *ZFValue = CTRec->RegValues[ZFIndex];
Value *SFValue = CTRec->RegValues[SFIndex];
Value *OFValue = CTRec->RegValues[OFIndex];
Instruction *ZFCond = nullptr;
Instruction *SFOFCond = nullptr;
assert(((ZFValue != nullptr) && (SFValue != nullptr) &&
(OFValue != nullptr)) &&
"Failed to get EFLAGS value while raising JG");
// Compare ZF and 0
ZFCond = new ICmpInst(CmpInst::Predicate::ICMP_EQ, ZFValue, FalseValue,
"ZFCmp_JG");
CandBB->getInstList().push_back(ZFCond);
// Test SF == OF
SFOFCond = new ICmpInst(CmpInst::Predicate::ICMP_EQ, SFValue, OFValue,
"SFOFCmp_JG");
CandBB->getInstList().push_back(SFOFCond);
BranchCond = BinaryOperator::CreateAnd(ZFCond, SFOFCond, "ZFAndSFOF_JG");
CandBB->getInstList().push_back(dyn_cast<Instruction>(BranchCond));
} break;
case X86::COND_GE: {
// SF == OF
int SFIndex = getEflagBitIndex(EFLAGS::SF);
int OFIndex = getEflagBitIndex(EFLAGS::OF);
Value *SFValue = CTRec->RegValues[SFIndex];
Value *OFValue = CTRec->RegValues[OFIndex];
assert(SFValue != nullptr && OFValue != nullptr &&
"Failed to get EFLAGS value while raising JGE");
// Compare SF and OF
BranchCond = new ICmpInst(CmpInst::Predicate::ICMP_EQ, SFValue, OFValue,
"CmpSFOF_JGE");
CandBB->getInstList().push_back(dyn_cast<Instruction>(BranchCond));
} break;
case X86::COND_L: {
// SF != OF
int SFIndex = getEflagBitIndex(EFLAGS::SF);
int OFIndex = getEflagBitIndex(EFLAGS::OF);
Value *SFValue = CTRec->RegValues[SFIndex];
Value *OFValue = CTRec->RegValues[OFIndex];
assert(((SFValue != nullptr) && (OFValue != nullptr)) &&
"Failed to get EFLAGS value while raising JL");
// Test SF != OF
BranchCond = new ICmpInst(CmpInst::Predicate::ICMP_NE, SFValue, OFValue,
"SFAndOF_JL");
CandBB->getInstList().push_back(dyn_cast<Instruction>(BranchCond));
} break;
case X86::COND_LE: {
// ZF == 1 or (SF != OF)
int ZFIndex = getEflagBitIndex(EFLAGS::ZF);
int SFIndex = getEflagBitIndex(EFLAGS::SF);
int OFIndex = getEflagBitIndex(EFLAGS::OF);
Value *ZFValue = CTRec->RegValues[ZFIndex];
Value *SFValue = CTRec->RegValues[SFIndex];
Value *OFValue = CTRec->RegValues[OFIndex];
Instruction *ZFCond = nullptr;
Instruction *SFOFCond = nullptr;
assert(((ZFValue != nullptr) && (SFValue != nullptr) &&
(OFValue != nullptr)) &&
"Failed to get EFLAGS value while raising JLE");
// Compare ZF and 1
ZFCond = new ICmpInst(CmpInst::Predicate::ICMP_EQ, ZFValue, TrueValue,
"CmpZF_JLE");
CandBB->getInstList().push_back(ZFCond);
// Test SF != OF
SFOFCond = new ICmpInst(CmpInst::Predicate::ICMP_NE, SFValue, OFValue,
"CmpOF_JLE");
CandBB->getInstList().push_back(SFOFCond);
BranchCond = BinaryOperator::CreateOr(ZFCond, SFOFCond, "ZFOrSF_JLE");
CandBB->getInstList().push_back(dyn_cast<Instruction>(BranchCond));
} break;
// Parity flag is set by instructions that abstract unordered
// result of SSE compare instructions.
// NOTE: Setting of PF is not modeled while abstracting non-SSE2
// instructions
case X86::COND_P: {
// Test PF == 1
int PFIndex = getEflagBitIndex(EFLAGS::PF);
Value *PFValue = CTRec->RegValues[PFIndex];
assert(PFValue != nullptr &&
"Failed to get EFLAGS value while raising JP");
// Construct a compare instruction
BranchCond = new ICmpInst(CmpInst::Predicate::ICMP_EQ, PFValue, TrueValue,
"CmpPF_JP");
CandBB->getInstList().push_back(dyn_cast<Instruction>(BranchCond));
} break;
case X86::COND_NP: {
// Test PF == 0
int PFIndex = getEflagBitIndex(EFLAGS::PF);
Value *PFValue = CTRec->RegValues[PFIndex];
assert(PFValue != nullptr &&
"Failed to get EFLAGS value while raising JNP");
// Construct a compare instruction
BranchCond = new ICmpInst(CmpInst::Predicate::ICMP_EQ, PFValue,
FalseValue, "CmpPF_JNP");
CandBB->getInstList().push_back(dyn_cast<Instruction>(BranchCond));
} break;
case X86::COND_INVALID:
assert(false && "Invalid condition on branch");
break;
default:
LLVM_DEBUG(MI->dump());
assert(false && "Unhandled conditional branch");
}
// Create branch instruction
BranchInst *CondBr = BranchInst::Create(TgtBB, FTBB, BranchCond);
CandBB->getInstList().push_back(CondBr);
CTRec->Raised = true;
} else {
assert(false && "Unhandled type of branch instruction");
}
return true;
}