[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:
Sasa Stankovic
2014-04-30 15:06:25 +00:00
parent 99b44bacab
commit fbe7448e5d
10 changed files with 294 additions and 16499 deletions

View File

@@ -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) {