summaryrefslogtreecommitdiff
path: root/bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp')
-rw-r--r--bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp41
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))