Skip to content

Commit 571c7d8

Browse files
DavidSpicketttstellar
authored andcommitted
Reland "[llvm][AArch64] Insert "bti j" after call to setjmp"
Cherry-picked from c3b9819 which was originally reviewed as https://reviews.llvm.org/D121707. This reverts commit edb7ba7. This changes BLR_BTI to take variable_ops meaning that we can accept a register or a label. The pattern still expects one argument so we'll never get more than one. Then later we can check the type of the operand to choose BL or BLR to emit. (this is what BLR_RVMARKER does but I missed this detail of it first time around) Also require NoSLSBLRMitigation which I missed in the first version.
1 parent 0f56ce0 commit 571c7d8

File tree

15 files changed

+284
-6
lines changed

15 files changed

+284
-6
lines changed

clang/docs/ClangCommandLineReference.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3293,7 +3293,7 @@ Work around VLLDM erratum CVE-2021-35465 (ARM only)
32933293

32943294
.. option:: -mno-bti-at-return-twice
32953295

3296-
Do not add a BTI instruction after a setjmp or other return-twice construct (Arm only)
3296+
Do not add a BTI instruction after a setjmp or other return-twice construct (AArch32/AArch64 only)
32973297

32983298
.. option:: -mno-movt
32993299

clang/docs/ReleaseNotes.rst

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -381,6 +381,11 @@ Arm and AArch64 Support in Clang
381381
- The ``attribute((target("branch-protection=...)))`` attributes will now also
382382
work for the ARM backend.
383383

384+
- When using ``-mbranch-protection=bti`` with AArch64, calls to setjmp will
385+
now be followed by a BTI instruction. This is done to be compatible with
386+
setjmp implementations that return with a br instead of a ret. You can
387+
disable this behaviour using the ``-mno-bti-at-return-twice`` option.
388+
384389
SPIR-V Support in Clang
385390
-----------------------
386391

@@ -391,7 +396,6 @@ SPIR-V Support in Clang
391396
- Added linking of separate object files in SPIR-V format using external
392397
``spirv-link`` tool.
393398

394-
395399
Floating Point Support in Clang
396400
-------------------------------
397401
- The default setting of FP contraction (FMA) is now -ffp-contract=on (for

clang/include/clang/Driver/Options.td

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3372,7 +3372,7 @@ def mmark_bti_property : Flag<["-"], "mmark-bti-property">,
33723372
def mno_bti_at_return_twice : Flag<["-"], "mno-bti-at-return-twice">,
33733373
Group<m_arm_Features_Group>,
33743374
HelpText<"Do not add a BTI instruction after a setjmp or other"
3375-
" return-twice construct (Arm only)">;
3375+
" return-twice construct (Arm/AArch64 only)">;
33763376

33773377
foreach i = {1-31} in
33783378
def ffixed_x#i : Flag<["-"], "ffixed-x"#i>, Group<m_Group>,

clang/lib/Driver/ToolChains/Arch/AArch64.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -592,4 +592,7 @@ void aarch64::getAArch64TargetFeatures(const Driver &D,
592592
// Enabled A53 errata (835769) workaround by default on android
593593
Features.push_back("+fix-cortex-a53-835769");
594594
}
595+
596+
if (Args.getLastArg(options::OPT_mno_bti_at_return_twice))
597+
Features.push_back("+no-bti-at-return-twice");
595598
}

llvm/lib/Target/AArch64/AArch64.td

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -464,6 +464,11 @@ def FeatureEL3 : SubtargetFeature<"el3", "HasEL3", "true",
464464
def FeatureFixCortexA53_835769 : SubtargetFeature<"fix-cortex-a53-835769",
465465
"FixCortexA53_835769", "true", "Mitigate Cortex-A53 Erratum 835769">;
466466

467+
def FeatureNoBTIAtReturnTwice : SubtargetFeature<"no-bti-at-return-twice",
468+
"NoBTIAtReturnTwice", "true",
469+
"Don't place a BTI instruction "
470+
"after a return-twice">;
471+
467472
//===----------------------------------------------------------------------===//
468473
// Architectures.
469474
//

llvm/lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ class AArch64ExpandPseudo : public MachineFunctionPass {
8686
unsigned N);
8787
bool expandCALL_RVMARKER(MachineBasicBlock &MBB,
8888
MachineBasicBlock::iterator MBBI);
89+
bool expandCALL_BTI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI);
8990
bool expandStoreSwiftAsyncContext(MachineBasicBlock &MBB,
9091
MachineBasicBlock::iterator MBBI);
9192
};
@@ -759,6 +760,37 @@ bool AArch64ExpandPseudo::expandCALL_RVMARKER(
759760
return true;
760761
}
761762

763+
bool AArch64ExpandPseudo::expandCALL_BTI(MachineBasicBlock &MBB,
764+
MachineBasicBlock::iterator MBBI) {
765+
// Expand CALL_BTI pseudo to:
766+
// - a branch to the call target
767+
// - a BTI instruction
768+
// Mark the sequence as a bundle, to avoid passes moving other code in
769+
// between.
770+
771+
MachineInstr &MI = *MBBI;
772+
MachineOperand &CallTarget = MI.getOperand(0);
773+
assert((CallTarget.isGlobal() || CallTarget.isReg()) &&
774+
"invalid operand for regular call");
775+
unsigned Opc = CallTarget.isGlobal() ? AArch64::BL : AArch64::BLR;
776+
MachineInstr *Call =
777+
BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(Opc)).getInstr();
778+
Call->addOperand(CallTarget);
779+
780+
MachineInstr *BTI =
781+
BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(AArch64::HINT))
782+
// BTI J so that setjmp can to BR to this.
783+
.addImm(36)
784+
.getInstr();
785+
786+
if (MI.shouldUpdateCallSiteInfo())
787+
MBB.getParent()->moveCallSiteInfo(&MI, Call);
788+
789+
MI.eraseFromParent();
790+
finalizeBundle(MBB, Call->getIterator(), std::next(BTI->getIterator()));
791+
return true;
792+
}
793+
762794
bool AArch64ExpandPseudo::expandStoreSwiftAsyncContext(
763795
MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI) {
764796
Register CtxReg = MBBI->getOperand(0).getReg();
@@ -1238,6 +1270,8 @@ bool AArch64ExpandPseudo::expandMI(MachineBasicBlock &MBB,
12381270
return expandSVESpillFill(MBB, MBBI, AArch64::LDR_ZXI, 2);
12391271
case AArch64::BLR_RVMARKER:
12401272
return expandCALL_RVMARKER(MBB, MBBI);
1273+
case AArch64::BLR_BTI:
1274+
return expandCALL_BTI(MBB, MBBI);
12411275
case AArch64::StoreSwiftAsyncContext:
12421276
return expandStoreSwiftAsyncContext(MBB, MBBI);
12431277
}

llvm/lib/Target/AArch64/AArch64FastISel.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
#include "AArch64.h"
1616
#include "AArch64CallingConvention.h"
17+
#include "AArch64MachineFunctionInfo.h"
1718
#include "AArch64RegisterInfo.h"
1819
#include "AArch64Subtarget.h"
1920
#include "MCTargetDesc/AArch64AddressingModes.h"
@@ -3127,6 +3128,13 @@ bool AArch64FastISel::fastLowerCall(CallLoweringInfo &CLI) {
31273128
if (!Callee && !Symbol)
31283129
return false;
31293130

3131+
// Allow SelectionDAG isel to handle calls to functions like setjmp that need
3132+
// a bti instruction following the call.
3133+
if (CLI.CB && CLI.CB->hasFnAttr(Attribute::ReturnsTwice) &&
3134+
!Subtarget->noBTIAtReturnTwice() &&
3135+
MF->getInfo<AArch64FunctionInfo>()->branchTargetEnforcement())
3136+
return false;
3137+
31303138
// Allow SelectionDAG isel to handle tail calls.
31313139
if (IsTailCall)
31323140
return false;

llvm/lib/Target/AArch64/AArch64ISelLowering.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2278,6 +2278,7 @@ const char *AArch64TargetLowering::getTargetNodeName(unsigned Opcode) const {
22782278
MAKE_CASE(AArch64ISD::MOPS_MEMSET_TAGGING)
22792279
MAKE_CASE(AArch64ISD::MOPS_MEMCOPY)
22802280
MAKE_CASE(AArch64ISD::MOPS_MEMMOVE)
2281+
MAKE_CASE(AArch64ISD::CALL_BTI)
22812282
}
22822283
#undef MAKE_CASE
22832284
return nullptr;
@@ -6106,6 +6107,12 @@ AArch64TargetLowering::LowerCall(CallLoweringInfo &CLI,
61066107
AArch64FunctionInfo *FuncInfo = MF.getInfo<AArch64FunctionInfo>();
61076108
bool TailCallOpt = MF.getTarget().Options.GuaranteedTailCallOpt;
61086109
bool IsSibCall = false;
6110+
bool GuardWithBTI = false;
6111+
6112+
if (CLI.CB && CLI.CB->getAttributes().hasFnAttr(Attribute::ReturnsTwice) &&
6113+
!Subtarget->noBTIAtReturnTwice()) {
6114+
GuardWithBTI = FuncInfo->branchTargetEnforcement();
6115+
}
61096116

61106117
// Check callee args/returns for SVE registers and set calling convention
61116118
// accordingly.
@@ -6540,7 +6547,8 @@ AArch64TargetLowering::LowerCall(CallLoweringInfo &CLI,
65406547
Function *ARCFn = *objcarc::getAttachedARCFunction(CLI.CB);
65416548
auto GA = DAG.getTargetGlobalAddress(ARCFn, DL, PtrVT);
65426549
Ops.insert(Ops.begin() + 1, GA);
6543-
}
6550+
} else if (GuardWithBTI)
6551+
CallOpc = AArch64ISD::CALL_BTI;
65446552

65456553
// Returns a chain and a flag for retval copy to use.
65466554
Chain = DAG.getNode(CallOpc, DL, NodeTys, Ops);

llvm/lib/Target/AArch64/AArch64ISelLowering.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ enum NodeType : unsigned {
5555
// x29, x29` marker instruction.
5656
CALL_RVMARKER,
5757

58+
CALL_BTI, // Function call followed by a BTI instruction.
59+
5860
// Produces the full sequence of instructions for getting the thread pointer
5961
// offset of a variable into X0, using the TLSDesc model.
6062
TLSDESC_CALLSEQ,

llvm/lib/Target/AArch64/AArch64InstrInfo.td

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -473,6 +473,11 @@ def AArch64call : SDNode<"AArch64ISD::CALL",
473473
[SDNPHasChain, SDNPOptInGlue, SDNPOutGlue,
474474
SDNPVariadic]>;
475475

476+
def AArch64call_bti : SDNode<"AArch64ISD::CALL_BTI",
477+
SDTypeProfile<0, -1, [SDTCisPtrTy<0>]>,
478+
[SDNPHasChain, SDNPOptInGlue, SDNPOutGlue,
479+
SDNPVariadic]>;
480+
476481
def AArch64call_rvmarker: SDNode<"AArch64ISD::CALL_RVMARKER",
477482
SDTypeProfile<0, -1, [SDTCisPtrTy<0>]>,
478483
[SDNPHasChain, SDNPOptInGlue, SDNPOutGlue,
@@ -2320,6 +2325,8 @@ let isCall = 1, Defs = [LR], Uses = [SP] in {
23202325
PseudoInstExpansion<(BLR GPR64:$Rn)>;
23212326
def BLR_RVMARKER : Pseudo<(outs), (ins variable_ops), []>,
23222327
Sched<[WriteBrReg]>;
2328+
def BLR_BTI : Pseudo<(outs), (ins variable_ops), []>,
2329+
Sched<[WriteBrReg]>;
23232330
} // isCall
23242331

23252332
def : Pat<(AArch64call GPR64:$Rn),
@@ -2333,6 +2340,10 @@ def : Pat<(AArch64call_rvmarker (i64 tglobaladdr:$rvfunc), GPR64:$Rn),
23332340
(BLR_RVMARKER tglobaladdr:$rvfunc, GPR64:$Rn)>,
23342341
Requires<[NoSLSBLRMitigation]>;
23352342

2343+
def : Pat<(AArch64call_bti GPR64:$Rn),
2344+
(BLR_BTI GPR64:$Rn)>,
2345+
Requires<[NoSLSBLRMitigation]>;
2346+
23362347
let isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1 in {
23372348
def BR : BranchReg<0b0000, "br", [(brind GPR64:$Rn)]>;
23382349
} // isBranch, isTerminator, isBarrier, isIndirectBranch

0 commit comments

Comments
 (0)