aboutsummaryrefslogtreecommitdiff
path: root/bolt/lib/Target
diff options
context:
space:
mode:
Diffstat (limited to 'bolt/lib/Target')
-rw-r--r--bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp112
-rw-r--r--bolt/lib/Target/X86/X86MCPlusBuilder.cpp6
2 files changed, 112 insertions, 6 deletions
diff --git a/bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp b/bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp
index 3c77091..5881d3f 100644
--- a/bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp
+++ b/bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp
@@ -164,11 +164,53 @@ public:
bool isPush(const MCInst &Inst) const override {
return isStoreToStack(Inst);
- };
+ }
bool isPop(const MCInst &Inst) const override {
return isLoadFromStack(Inst);
- };
+ }
+
+ // We look for instructions that load from stack or make stack pointer
+ // adjustment, and assume the basic block is an epilogue if and only if
+ // such instructions are present and also immediately precede the branch
+ // instruction that ends the basic block.
+ bool isEpilogue(const BinaryBasicBlock &BB) const override {
+ if (BB.succ_size())
+ return false;
+
+ bool SeenLoadFromStack = false;
+ bool SeenStackPointerAdjustment = false;
+ for (const MCInst &Instr : BB) {
+ // Skip CFI pseudo instruction.
+ if (isCFI(Instr))
+ continue;
+
+ bool IsPop = isPop(Instr);
+ // A load from stack instruction could do SP adjustment in pre-index or
+ // post-index form, which we can skip to check for epilogue recognition
+ // purpose.
+ bool IsSPAdj = (isADD(Instr) || isMOVW(Instr)) &&
+ Instr.getOperand(0).isReg() &&
+ Instr.getOperand(0).getReg() == AArch64::SP;
+ SeenLoadFromStack |= IsPop;
+ SeenStackPointerAdjustment |= IsSPAdj;
+
+ if (!SeenLoadFromStack && !SeenStackPointerAdjustment)
+ continue;
+ if (IsPop || IsSPAdj || isPAuthOnLR(Instr))
+ continue;
+ if (isReturn(Instr))
+ return true;
+ if (isBranch(Instr))
+ break;
+
+ // Any previously seen load from stack or stack adjustment instruction
+ // is definitely not part of epilogue code sequence, so reset these two.
+ SeenLoadFromStack = false;
+ SeenStackPointerAdjustment = false;
+ }
+ return SeenLoadFromStack || SeenStackPointerAdjustment;
+ }
void createCall(MCInst &Inst, const MCSymbol *Target,
MCContext *Ctx) override {
@@ -271,6 +313,33 @@ public:
Inst.getOpcode() == AArch64::RETABSPPCr;
}
+ void createMatchingAuth(const MCInst &AuthAndRet, MCInst &Auth) override {
+ Auth.clear();
+ Auth.setOperands(AuthAndRet.getOperands());
+ switch (AuthAndRet.getOpcode()) {
+ case AArch64::RETAA:
+ Auth.setOpcode(AArch64::AUTIASP);
+ break;
+ case AArch64::RETAB:
+ Auth.setOpcode(AArch64::AUTIBSP);
+ break;
+ case AArch64::RETAASPPCi:
+ Auth.setOpcode(AArch64::AUTIASPPCi);
+ break;
+ case AArch64::RETABSPPCi:
+ Auth.setOpcode(AArch64::AUTIBSPPCi);
+ break;
+ case AArch64::RETAASPPCr:
+ Auth.setOpcode(AArch64::AUTIASPPCr);
+ break;
+ case AArch64::RETABSPPCr:
+ Auth.setOpcode(AArch64::AUTIBSPPCr);
+ break;
+ default:
+ llvm_unreachable("Unhandled fused pauth-and-return instruction");
+ }
+ }
+
std::optional<MCPhysReg> getSignedReg(const MCInst &Inst) const override {
switch (Inst.getOpcode()) {
case AArch64::PACIA:
@@ -1793,14 +1862,12 @@ public:
}
bool isNoop(const MCInst &Inst) const override {
- return Inst.getOpcode() == AArch64::HINT &&
- Inst.getOperand(0).getImm() == 0;
+ return Inst.getOpcode() == AArch64::NOP;
}
void createNoop(MCInst &Inst) const override {
- Inst.setOpcode(AArch64::HINT);
+ Inst.setOpcode(AArch64::NOP);
Inst.clear();
- Inst.addOperand(MCOperand::createImm(0));
}
bool isTrap(const MCInst &Inst) const override {
@@ -2706,6 +2773,39 @@ public:
return Insts;
}
+ void createBTI(MCInst &Inst, bool CallTarget,
+ bool JumpTarget) const override {
+ Inst.setOpcode(AArch64::HINT);
+ unsigned HintNum = getBTIHintNum(CallTarget, JumpTarget);
+ Inst.addOperand(MCOperand::createImm(HintNum));
+ }
+
+ bool isBTILandingPad(MCInst &Inst, bool CallTarget,
+ bool JumpTarget) const override {
+ unsigned HintNum = getBTIHintNum(CallTarget, JumpTarget);
+ bool IsExplicitBTI =
+ Inst.getOpcode() == AArch64::HINT && Inst.getNumOperands() == 1 &&
+ Inst.getOperand(0).isImm() && Inst.getOperand(0).getImm() == HintNum;
+
+ bool IsImplicitBTI = HintNum == 34 && isImplicitBTIC(Inst);
+ return IsExplicitBTI || IsImplicitBTI;
+ }
+
+ bool isImplicitBTIC(MCInst &Inst) const override {
+ // PACI[AB]SP are always implicitly BTI C, independently of
+ // SCTLR_EL1.BT[01].
+ return Inst.getOpcode() == AArch64::PACIASP ||
+ Inst.getOpcode() == AArch64::PACIBSP;
+ }
+
+ void updateBTIVariant(MCInst &Inst, bool CallTarget,
+ bool JumpTarget) const override {
+ assert(Inst.getOpcode() == AArch64::HINT && "Not a BTI instruction.");
+ unsigned HintNum = getBTIHintNum(CallTarget, JumpTarget);
+ Inst.clear();
+ Inst.addOperand(MCOperand::createImm(HintNum));
+ }
+
InstructionListType materializeAddress(const MCSymbol *Target, MCContext *Ctx,
MCPhysReg RegName,
int64_t Addend = 0) const override {
diff --git a/bolt/lib/Target/X86/X86MCPlusBuilder.cpp b/bolt/lib/Target/X86/X86MCPlusBuilder.cpp
index 5fca5e8..7c24c2c 100644
--- a/bolt/lib/Target/X86/X86MCPlusBuilder.cpp
+++ b/bolt/lib/Target/X86/X86MCPlusBuilder.cpp
@@ -219,6 +219,12 @@ public:
return getPopSize(Inst) == 0 ? false : true;
}
+ bool isEpilogue(const BinaryBasicBlock &BB) const override {
+ return ::llvm::any_of(BB, [&](const MCInst &Instr) {
+ return isLeave(Instr) || isPop(Instr);
+ });
+ }
+
bool isTerminateBranch(const MCInst &Inst) const override {
return Inst.getOpcode() == X86::ENDBR32 || Inst.getOpcode() == X86::ENDBR64;
}