Index: lib/Target/Mips/MipsLongBranch.cpp |
diff --git a/lib/Target/Mips/MipsLongBranch.cpp b/lib/Target/Mips/MipsLongBranch.cpp |
index 24b42b9150447a9da5925368352fe8c3e9e0dbdb..e8fe1214bb0273a9272aa5a9eeeff39b141e24d0 100644 |
--- a/lib/Target/Mips/MipsLongBranch.cpp |
+++ b/lib/Target/Mips/MipsLongBranch.cpp |
@@ -68,7 +68,8 @@ namespace { |
TII(static_cast<const MipsInstrInfo*>(tm.getInstrInfo())), |
IsPIC(TM.getRelocationModel() == Reloc::PIC_), |
ABI(TM.getSubtarget<MipsSubtarget>().getTargetABI()), |
- LongBranchSeqSize(!IsPIC ? 2 : (ABI == MipsSubtarget::N64 ? 13 : 9)) {} |
+ LongBranchSeqSize(!IsPIC ? 2 : (ABI == MipsSubtarget::N64 ? 13 : |
+ (/*@LOCALMOD*/Triple(TM.getTargetTriple()).isOSNaCl() ? 10 : 9))) {} |
virtual const char *getPassName() const { |
return "Mips Long Branch"; |
@@ -263,7 +264,9 @@ void MipsLongBranch::expandToLongBranch(MBBInfo &I) { |
BalTgtMBB->addSuccessor(TgtMBB); |
int64_t TgtAddress = MBBInfos[TgtMBB->getNumber()].Address; |
- unsigned BalTgtMBBSize = 5; |
+ // @LOCALMOD-START |
+ unsigned BalTgtMBBSize = Triple(TM.getTargetTriple()).isOSNaCl() ? 6 : 5; |
+ // @LOCALMOD-END |
int64_t Offset = TgtAddress - (I.Address + I.Size - BalTgtMBBSize * 4); |
int64_t Lo = SignExtend64<16>(Offset & 0xffff); |
int64_t Hi = SignExtend64<16>(((Offset + 0x8000) >> 16) & 0xffff); |
@@ -290,23 +293,69 @@ void MipsLongBranch::expandToLongBranch(MBBInfo &I) { |
BuildMI(*LongBrMBB, Pos, DL, TII->get(Mips::SW)).addReg(Mips::RA) |
.addReg(Mips::SP).addImm(0); |
- MIBundleBuilder(*LongBrMBB, Pos) |
- .append(BuildMI(*MF, DL, TII->get(Mips::BAL_BR)).addMBB(BalTgtMBB)) |
- .append(BuildMI(*MF, DL, TII->get(Mips::LUi), Mips::AT).addImm(Hi)); |
- |
- Pos = BalTgtMBB->begin(); |
- |
- BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::ADDiu), Mips::AT) |
- .addReg(Mips::AT).addImm(Lo); |
- BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::ADDu), Mips::AT) |
- .addReg(Mips::RA).addReg(Mips::AT); |
- BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::LW), Mips::RA) |
- .addReg(Mips::SP).addImm(0); |
- |
- MIBundleBuilder(*BalTgtMBB, Pos) |
- .append(BuildMI(*MF, DL, TII->get(Mips::JR)).addReg(Mips::AT)) |
- .append(BuildMI(*MF, DL, TII->get(Mips::ADDiu), Mips::SP) |
- .addReg(Mips::SP).addImm(8)); |
+ if (Triple(TM.getTargetTriple()).isOSNaCl()) { |
+ // @LOCALMOD-START |
+ // LUi and ADDiu instructions create 32-bit offset of the target basic |
+ // block from the BAL target. We cannot use immediate value as the |
+ // offset (as non-NaCl version does) because it does not take |
+ // sandboxed instructions into account ("sanboxing" is run after this |
+ // pass). We therefore replace it with relocation expressions |
+ // %hi($tgt-$baltgt) and %lo($tgt-$baltgt). This expressions are |
+ // resolved during the fixup after all sandboxing code is added, so the |
+ // values will always be correct. |
+ // |
+ // Since we cannot create %hi($tgt-$baltgt) and %lo($tgt-$baltgt) |
+ // expressions at this point (it is possible only at the MC layer), |
+ // we replace LUi and ADDiu with pseudo instructions |
+ // NACL_LONG_BRANCH_LUi and NACL_LONG_BRANCH_ADDiu, and add both basic |
+ // block as operands to these instructions. When lowering these pseudo |
+ // instructions to LUi and ADDiu in the MC layer, we will create |
+ // %hi($tgt-$baltgt) and %lo($tgt-$baltgt) expressions add add them as |
+ // operands to lowered instructions. |
+ MIBundleBuilder(*LongBrMBB, Pos) |
+ .append(BuildMI(*MF, DL, TII->get(Mips::BAL_BR)).addMBB(BalTgtMBB)) |
+ .append(BuildMI(*MF, DL, TII->get(Mips::NACL_LONG_BRANCH_LUi), |
+ Mips::AT).addMBB(TgtMBB).addMBB(BalTgtMBB)); |
+ |
+ Pos = BalTgtMBB->begin(); |
+ |
+ BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::NACL_LONG_BRANCH_ADDiu), |
+ Mips::AT).addReg(Mips::AT).addMBB(TgtMBB).addMBB(BalTgtMBB); |
+ BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::ADDu), Mips::AT) |
+ .addReg(Mips::RA).addReg(Mips::AT); |
+ BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::LW), Mips::RA) |
+ .addReg(Mips::SP).addImm(0); |
+ |
+ // In NaCl, modifying sp is not allowed in branch delay slot. |
+ BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::ADDiu), Mips::SP) |
+ .addReg(Mips::SP).addImm(8); |
+ |
+ MIBundleBuilder(*BalTgtMBB, Pos) |
+ .append(BuildMI(*MF, DL, TII->get(Mips::JR)).addReg(Mips::AT)) |
+ .append(BuildMI(*MF, DL, TII->get(Mips::NOP))); |
+ |
+ // Align target of JR instruction. |
+ TgtMBB->setAlignment(4); |
+ // @LOCALMOD-END |
+ } else { |
+ MIBundleBuilder(*LongBrMBB, Pos) |
+ .append(BuildMI(*MF, DL, TII->get(Mips::BAL_BR)).addMBB(BalTgtMBB)) |
+ .append(BuildMI(*MF, DL, TII->get(Mips::LUi), Mips::AT).addImm(Hi)); |
+ |
+ Pos = BalTgtMBB->begin(); |
+ |
+ BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::ADDiu), Mips::AT) |
+ .addReg(Mips::AT).addImm(Lo); |
+ BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::ADDu), Mips::AT) |
+ .addReg(Mips::RA).addReg(Mips::AT); |
+ BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::LW), Mips::RA) |
+ .addReg(Mips::SP).addImm(0); |
+ |
+ MIBundleBuilder(*BalTgtMBB, Pos) |
+ .append(BuildMI(*MF, DL, TII->get(Mips::JR)).addReg(Mips::AT)) |
+ .append(BuildMI(*MF, DL, TII->get(Mips::ADDiu), Mips::SP) |
+ .addReg(Mips::SP).addImm(8)); |
+ } |
} else { |
// $longbr: |
// daddiu $sp, $sp, -16 |
@@ -430,8 +479,23 @@ bool MipsLongBranch::runOnMachineFunction(MachineFunction &F) { |
continue; |
// Check if offset fits into 16-bit immediate field of branches. |
- if (!ForceLongBranch && isInt<16>(computeOffset(I->Br) / 4)) |
- continue; |
+ if (Triple(TM.getTargetTriple()).isOSNaCl()) { |
+ // @LOCALMOD-START |
+ int64_t Offset = computeOffset(I->Br) / 4; |
+ |
+ // This offset calculation does not include sandboxing instructions |
+ // that will be added later in the MC layer. Since at this point we |
+ // don't know the exact amount of code that "sanboxing" will add, we |
+ // conservatively estimate that code will not grow more than 100%. |
+ Offset *= 2; |
+ |
+ if (!ForceLongBranch && isInt<16>(Offset)) |
+ continue; |
+ // @LOCALMOD-END |
+ } else { |
+ if (!ForceLongBranch && isInt<16>(computeOffset(I->Br) / 4)) |
+ continue; |
+ } |
I->HasLongBranch = true; |
I->Size += LongBranchSeqSize * 4; |