diff options
Diffstat (limited to 'bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp')
| -rw-r--r-- | bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp | 41 |
1 files changed, 41 insertions, 0 deletions
diff --git a/bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp b/bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp index a74eda8e4a56..5220d305b838 100644 --- a/bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp +++ b/bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp @@ -1054,6 +1054,47 @@ public: return true; } + InstructionListType createIndirectPltCall(const MCInst &DirectCall, + const MCSymbol *TargetLocation, + MCContext *Ctx) override { + const bool IsTailCall = isTailCall(DirectCall); + assert((DirectCall.getOpcode() == AArch64::BL || + (DirectCall.getOpcode() == AArch64::B && IsTailCall)) && + "64-bit direct (tail) call instruction expected"); + + InstructionListType Code; + // Code sequence for indirect plt call: + // adrp x16 <symbol> + // ldr x17, [x16, #<offset>] + // blr x17 ; or 'br' for tail calls + + MCInst InstAdrp; + InstAdrp.setOpcode(AArch64::ADRP); + InstAdrp.addOperand(MCOperand::createReg(AArch64::X16)); + InstAdrp.addOperand(MCOperand::createImm(0)); + setOperandToSymbolRef(InstAdrp, /* OpNum */ 1, TargetLocation, + /* Addend */ 0, Ctx, ELF::R_AARCH64_ADR_GOT_PAGE); + Code.emplace_back(InstAdrp); + + MCInst InstLoad; + InstLoad.setOpcode(AArch64::LDRXui); + InstLoad.addOperand(MCOperand::createReg(AArch64::X17)); + InstLoad.addOperand(MCOperand::createReg(AArch64::X16)); + InstLoad.addOperand(MCOperand::createImm(0)); + setOperandToSymbolRef(InstLoad, /* OpNum */ 2, TargetLocation, + /* Addend */ 0, Ctx, ELF::R_AARCH64_LD64_GOT_LO12_NC); + Code.emplace_back(InstLoad); + + MCInst InstCall; + InstCall.setOpcode(IsTailCall ? AArch64::BR : AArch64::BLR); + InstCall.addOperand(MCOperand::createReg(AArch64::X17)); + if (IsTailCall) + setTailCall(InstCall); + Code.emplace_back(InstCall); + + return Code; + } + bool lowerTailCall(MCInst &Inst) override { removeAnnotation(Inst, MCPlus::MCAnnotation::kTailCall); if (getConditionalTailCall(Inst)) |
