mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-07-24 06:25:18 +00:00
[mips] Fix MipsLongBranch pass to work when the offset from the branch to the
target cannot be determined accurately. This is the case for NaCl where the sandboxing instructions are added in MC layer, after the MipsLongBranch pass. It is also the case when the code has inline assembly. Instead of calculating offset in the MipsLongBranch pass, use %hi(sym1 - sym2) and %lo(sym1 - sym2) expressions that are resolved during the fixup. This patch also deletes microMIPS test file test/CodeGen/Mips/micromips-long-branch.ll and implements microMIPS CHECKs in a much simpler way in a file test/CodeGen/Mips/longbranch.ll, together with MIPS32 and MIPS64. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@207656 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -151,7 +151,82 @@ MCOperand MipsMCInstLower::LowerOperand(const MachineOperand &MO,
|
||||
return MCOperand();
|
||||
}
|
||||
|
||||
MCOperand MipsMCInstLower::createSub(MachineBasicBlock *BB1,
|
||||
MachineBasicBlock *BB2,
|
||||
MCSymbolRefExpr::VariantKind Kind) const {
|
||||
const MCSymbolRefExpr *Sym1 = MCSymbolRefExpr::Create(BB1->getSymbol(), *Ctx);
|
||||
const MCSymbolRefExpr *Sym2 = MCSymbolRefExpr::Create(BB2->getSymbol(), *Ctx);
|
||||
const MCBinaryExpr *Sub = MCBinaryExpr::CreateSub(Sym1, Sym2, *Ctx);
|
||||
|
||||
return MCOperand::CreateExpr(MipsMCExpr::Create(Kind, Sub, *Ctx));
|
||||
}
|
||||
|
||||
void MipsMCInstLower::
|
||||
lowerLongBranchLUi(const MachineInstr *MI, MCInst &OutMI, int Opcode,
|
||||
MCSymbolRefExpr::VariantKind Kind) const {
|
||||
OutMI.setOpcode(Opcode);
|
||||
|
||||
// Lower register operand.
|
||||
OutMI.addOperand(LowerOperand(MI->getOperand(0)));
|
||||
|
||||
// Create %hi($tgt-$baltgt) or %highest($tgt-$baltgt).
|
||||
OutMI.addOperand(createSub(MI->getOperand(1).getMBB(),
|
||||
MI->getOperand(2).getMBB(), Kind));
|
||||
}
|
||||
|
||||
void MipsMCInstLower::
|
||||
lowerLongBranchADDiu(const MachineInstr *MI, MCInst &OutMI, int Opcode,
|
||||
MCSymbolRefExpr::VariantKind Kind) const {
|
||||
OutMI.setOpcode(Opcode);
|
||||
|
||||
// Lower two register operands.
|
||||
for (unsigned I = 0, E = 2; I != E; ++I) {
|
||||
const MachineOperand &MO = MI->getOperand(I);
|
||||
OutMI.addOperand(LowerOperand(MO));
|
||||
}
|
||||
|
||||
// Create %lo($tgt-$baltgt), %hi($tgt-$baltgt) or %higher($tgt-$baltgt).
|
||||
OutMI.addOperand(createSub(MI->getOperand(2).getMBB(),
|
||||
MI->getOperand(3).getMBB(), Kind));
|
||||
}
|
||||
|
||||
bool MipsMCInstLower::lowerLongBranch(const MachineInstr *MI,
|
||||
MCInst &OutMI) const {
|
||||
switch (MI->getOpcode()) {
|
||||
default:
|
||||
return false;
|
||||
case Mips::LONG_BRANCH_LUi:
|
||||
lowerLongBranchLUi(MI, OutMI, Mips::LUi, MCSymbolRefExpr::VK_Mips_ABS_HI);
|
||||
return true;
|
||||
case Mips::LONG_BRANCH_LUi64:
|
||||
lowerLongBranchLUi(MI, OutMI, Mips::LUi64,
|
||||
MCSymbolRefExpr::VK_Mips_HIGHEST);
|
||||
return true;
|
||||
case Mips::LONG_BRANCH_ADDiu:
|
||||
lowerLongBranchADDiu(MI, OutMI, Mips::ADDiu,
|
||||
MCSymbolRefExpr::VK_Mips_ABS_LO);
|
||||
return true;
|
||||
case Mips::LONG_BRANCH_DADDiu:
|
||||
unsigned TargetFlags = MI->getOperand(2).getTargetFlags();
|
||||
if (TargetFlags == MipsII::MO_HIGHER)
|
||||
lowerLongBranchADDiu(MI, OutMI, Mips::DADDiu,
|
||||
MCSymbolRefExpr::VK_Mips_HIGHER);
|
||||
else if (TargetFlags == MipsII::MO_ABS_HI)
|
||||
lowerLongBranchADDiu(MI, OutMI, Mips::DADDiu,
|
||||
MCSymbolRefExpr::VK_Mips_ABS_HI);
|
||||
else if (TargetFlags == MipsII::MO_ABS_LO)
|
||||
lowerLongBranchADDiu(MI, OutMI, Mips::DADDiu,
|
||||
MCSymbolRefExpr::VK_Mips_ABS_LO);
|
||||
else
|
||||
report_fatal_error("Unexpected flags for LONG_BRANCH_DADDiu");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void MipsMCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const {
|
||||
if (lowerLongBranch(MI, OutMI))
|
||||
return;
|
||||
|
||||
OutMI.setOpcode(MI->getOpcode());
|
||||
|
||||
for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
|
||||
|
Reference in New Issue
Block a user