Skip to content

Commit fe73b94

Browse files
scottconstabletstellar
authored andcommitted
[X86][NFC] Generalize the naming of "Retpoline Thunks" and related code to "Indirect Thunks"
There are applications for indirect call/branch thunks other than retpoline for Spectre v2, e.g., https://software.intel.com/security-software-guidance/software-guidance/load-value-injection Therefore it makes sense to refactor X86RetpolineThunks as a more general capability. Differential Revision: https://reviews.llvm.org/D76810
1 parent 34f7e00 commit fe73b94

16 files changed

+137
-115
lines changed

llvm/lib/Target/X86/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ set(sources
4444
X86ISelDAGToDAG.cpp
4545
X86ISelLowering.cpp
4646
X86IndirectBranchTracking.cpp
47+
X86IndirectThunks.cpp
4748
X86InterleavedAccess.cpp
4849
X86InsertPrefetch.cpp
4950
X86InstrFMA3Info.cpp
@@ -58,7 +59,6 @@ set(sources
5859
X86PadShortFunction.cpp
5960
X86RegisterBankInfo.cpp
6061
X86RegisterInfo.cpp
61-
X86RetpolineThunks.cpp
6262
X86SelectionDAGInfo.cpp
6363
X86ShuffleDecodeConstantPool.cpp
6464
X86SpeculativeLoadHardening.cpp

llvm/lib/Target/X86/X86.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ FunctionPass *createX86DomainReassignmentPass();
120120
FunctionPass *createX86EvexToVexInsts();
121121

122122
/// This pass creates the thunks for the retpoline feature.
123-
FunctionPass *createX86RetpolineThunksPass();
123+
FunctionPass *createX86IndirectThunksPass();
124124

125125
/// This pass ensures instructions featuring a memory operand
126126
/// have distinctive <LineNumber, Discriminator> (with respect to eachother)

llvm/lib/Target/X86/X86FastISel.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3202,8 +3202,8 @@ bool X86FastISel::fastLowerCall(CallLoweringInfo &CLI) {
32023202
(CalledFn && CalledFn->hasFnAttribute("no_caller_saved_registers")))
32033203
return false;
32043204

3205-
// Functions using retpoline for indirect calls need to use SDISel.
3206-
if (Subtarget->useRetpolineIndirectCalls())
3205+
// Functions using thunks for indirect calls need to use SDISel.
3206+
if (Subtarget->useIndirectThunkCalls())
32073207
return false;
32083208

32093209
// Handle only C, fastcc, and webkit_js calling conventions for now.

llvm/lib/Target/X86/X86FrameLowering.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -765,10 +765,10 @@ void X86FrameLowering::emitStackProbeCall(MachineFunction &MF,
765765
bool InProlog) const {
766766
bool IsLargeCodeModel = MF.getTarget().getCodeModel() == CodeModel::Large;
767767

768-
// FIXME: Add retpoline support and remove this.
769-
if (Is64Bit && IsLargeCodeModel && STI.useRetpolineIndirectCalls())
768+
// FIXME: Add indirect thunk support and remove this.
769+
if (Is64Bit && IsLargeCodeModel && STI.useIndirectThunkCalls())
770770
report_fatal_error("Emitting stack probe calls on 64-bit with the large "
771-
"code model and retpoline not yet implemented.");
771+
"code model and indirect thunks not yet implemented.");
772772

773773
unsigned CallOp;
774774
if (Is64Bit)
@@ -2493,9 +2493,9 @@ void X86FrameLowering::adjustForSegmentedStacks(
24932493
// is laid out within 2^31 bytes of each function body, but this seems
24942494
// to be sufficient for JIT.
24952495
// FIXME: Add retpoline support and remove the error here..
2496-
if (STI.useRetpolineIndirectCalls())
2496+
if (STI.useIndirectThunkCalls())
24972497
report_fatal_error("Emitting morestack calls on 64-bit with the large "
2498-
"code model and retpoline not yet implemented.");
2498+
"code model and thunks not yet implemented.");
24992499
BuildMI(allocMBB, DL, TII.get(X86::CALL64m))
25002500
.addReg(X86::RIP)
25012501
.addImm(0)

llvm/lib/Target/X86/X86ISelDAGToDAG.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -987,7 +987,7 @@ void X86DAGToDAGISel::PreprocessISelDAG() {
987987
if (OptLevel != CodeGenOpt::None &&
988988
// Only do this when the target can fold the load into the call or
989989
// jmp.
990-
!Subtarget->useRetpolineIndirectCalls() &&
990+
!Subtarget->useIndirectThunkCalls() &&
991991
((N->getOpcode() == X86ISD::CALL && !Subtarget->slowTwoMemOps()) ||
992992
(N->getOpcode() == X86ISD::TC_RETURN &&
993993
(Subtarget->is64Bit() ||

llvm/lib/Target/X86/X86ISelLowering.cpp

Lines changed: 42 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -30221,8 +30221,8 @@ bool X86TargetLowering::isVectorClearMaskLegal(ArrayRef<int> Mask,
3022130221
}
3022230222

3022330223
bool X86TargetLowering::areJTsAllowed(const Function *Fn) const {
30224-
// If the subtarget is using retpolines, we need to not generate jump tables.
30225-
if (Subtarget.useRetpolineIndirectBranches())
30224+
// If the subtarget is using thunks, we need to not generate jump tables.
30225+
if (Subtarget.useIndirectThunkBranches())
3022630226
return false;
3022730227

3022830228
// Otherwise, fallback on the generic logic.
@@ -31345,22 +31345,22 @@ X86TargetLowering::EmitLoweredTLSCall(MachineInstr &MI,
3134531345
return BB;
3134631346
}
3134731347

31348-
static unsigned getOpcodeForRetpoline(unsigned RPOpc) {
31348+
static unsigned getOpcodeForIndirectThunk(unsigned RPOpc) {
3134931349
switch (RPOpc) {
31350-
case X86::RETPOLINE_CALL32:
31350+
case X86::INDIRECT_THUNK_CALL32:
3135131351
return X86::CALLpcrel32;
31352-
case X86::RETPOLINE_CALL64:
31352+
case X86::INDIRECT_THUNK_CALL64:
3135331353
return X86::CALL64pcrel32;
31354-
case X86::RETPOLINE_TCRETURN32:
31354+
case X86::INDIRECT_THUNK_TCRETURN32:
3135531355
return X86::TCRETURNdi;
31356-
case X86::RETPOLINE_TCRETURN64:
31356+
case X86::INDIRECT_THUNK_TCRETURN64:
3135731357
return X86::TCRETURNdi64;
3135831358
}
31359-
llvm_unreachable("not retpoline opcode");
31359+
llvm_unreachable("not indirect thunk opcode");
3136031360
}
3136131361

31362-
static const char *getRetpolineSymbol(const X86Subtarget &Subtarget,
31363-
unsigned Reg) {
31362+
static const char *getIndirectThunkSymbol(const X86Subtarget &Subtarget,
31363+
unsigned Reg) {
3136431364
if (Subtarget.useRetpolineExternalThunk()) {
3136531365
// When using an external thunk for retpolines, we pick names that match the
3136631366
// names GCC happens to use as well. This helps simplify the implementation
@@ -31392,39 +31392,43 @@ static const char *getRetpolineSymbol(const X86Subtarget &Subtarget,
3139231392
assert(Subtarget.is64Bit() && "Should not be using a 64-bit thunk!");
3139331393
return "__x86_indirect_thunk_r11";
3139431394
}
31395-
llvm_unreachable("unexpected reg for retpoline");
31395+
llvm_unreachable("unexpected reg for external indirect thunk");
3139631396
}
3139731397

31398-
// When targeting an internal COMDAT thunk use an LLVM-specific name.
31399-
switch (Reg) {
31400-
case X86::EAX:
31401-
assert(!Subtarget.is64Bit() && "Should not be using a 32-bit thunk!");
31402-
return "__llvm_retpoline_eax";
31403-
case X86::ECX:
31404-
assert(!Subtarget.is64Bit() && "Should not be using a 32-bit thunk!");
31405-
return "__llvm_retpoline_ecx";
31406-
case X86::EDX:
31407-
assert(!Subtarget.is64Bit() && "Should not be using a 32-bit thunk!");
31408-
return "__llvm_retpoline_edx";
31409-
case X86::EDI:
31410-
assert(!Subtarget.is64Bit() && "Should not be using a 32-bit thunk!");
31411-
return "__llvm_retpoline_edi";
31412-
case X86::R11:
31413-
assert(Subtarget.is64Bit() && "Should not be using a 64-bit thunk!");
31414-
return "__llvm_retpoline_r11";
31398+
if (Subtarget.useRetpolineIndirectCalls() ||
31399+
Subtarget.useRetpolineIndirectBranches()) {
31400+
// When targeting an internal COMDAT thunk use an LLVM-specific name.
31401+
switch (Reg) {
31402+
case X86::EAX:
31403+
assert(!Subtarget.is64Bit() && "Should not be using a 32-bit thunk!");
31404+
return "__llvm_retpoline_eax";
31405+
case X86::ECX:
31406+
assert(!Subtarget.is64Bit() && "Should not be using a 32-bit thunk!");
31407+
return "__llvm_retpoline_ecx";
31408+
case X86::EDX:
31409+
assert(!Subtarget.is64Bit() && "Should not be using a 32-bit thunk!");
31410+
return "__llvm_retpoline_edx";
31411+
case X86::EDI:
31412+
assert(!Subtarget.is64Bit() && "Should not be using a 32-bit thunk!");
31413+
return "__llvm_retpoline_edi";
31414+
case X86::R11:
31415+
assert(Subtarget.is64Bit() && "Should not be using a 64-bit thunk!");
31416+
return "__llvm_retpoline_r11";
31417+
}
31418+
llvm_unreachable("unexpected reg for retpoline");
3141531419
}
31416-
llvm_unreachable("unexpected reg for retpoline");
31420+
llvm_unreachable("getIndirectThunkSymbol() invoked without thunk feature");
3141731421
}
3141831422

3141931423
MachineBasicBlock *
31420-
X86TargetLowering::EmitLoweredRetpoline(MachineInstr &MI,
31421-
MachineBasicBlock *BB) const {
31424+
X86TargetLowering::EmitLoweredIndirectThunk(MachineInstr &MI,
31425+
MachineBasicBlock *BB) const {
3142231426
// Copy the virtual register into the R11 physical register and
3142331427
// call the retpoline thunk.
3142431428
DebugLoc DL = MI.getDebugLoc();
3142531429
const X86InstrInfo *TII = Subtarget.getInstrInfo();
3142631430
Register CalleeVReg = MI.getOperand(0).getReg();
31427-
unsigned Opc = getOpcodeForRetpoline(MI.getOpcode());
31431+
unsigned Opc = getOpcodeForIndirectThunk(MI.getOpcode());
3142831432

3142931433
// Find an available scratch register to hold the callee. On 64-bit, we can
3143031434
// just use R11, but we scan for uses anyway to ensure we don't generate
@@ -31458,7 +31462,7 @@ X86TargetLowering::EmitLoweredRetpoline(MachineInstr &MI,
3145831462
report_fatal_error("calling convention incompatible with retpoline, no "
3145931463
"available registers");
3146031464

31461-
const char *Symbol = getRetpolineSymbol(Subtarget, AvailableReg);
31465+
const char *Symbol = getIndirectThunkSymbol(Subtarget, AvailableReg);
3146231466

3146331467
BuildMI(*BB, MI, DL, TII->get(TargetOpcode::COPY), AvailableReg)
3146431468
.addReg(CalleeVReg);
@@ -32234,11 +32238,11 @@ X86TargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
3223432238
case X86::TLS_base_addr32:
3223532239
case X86::TLS_base_addr64:
3223632240
return EmitLoweredTLSAddr(MI, BB);
32237-
case X86::RETPOLINE_CALL32:
32238-
case X86::RETPOLINE_CALL64:
32239-
case X86::RETPOLINE_TCRETURN32:
32240-
case X86::RETPOLINE_TCRETURN64:
32241-
return EmitLoweredRetpoline(MI, BB);
32241+
case X86::INDIRECT_THUNK_CALL32:
32242+
case X86::INDIRECT_THUNK_CALL64:
32243+
case X86::INDIRECT_THUNK_TCRETURN32:
32244+
case X86::INDIRECT_THUNK_TCRETURN64:
32245+
return EmitLoweredIndirectThunk(MI, BB);
3224232246
case X86::CATCHRET:
3224332247
return EmitLoweredCatchRet(MI, BB);
3224432248
case X86::CATCHPAD:

llvm/lib/Target/X86/X86ISelLowering.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1482,8 +1482,8 @@ namespace llvm {
14821482
MachineBasicBlock *EmitLoweredTLSCall(MachineInstr &MI,
14831483
MachineBasicBlock *BB) const;
14841484

1485-
MachineBasicBlock *EmitLoweredRetpoline(MachineInstr &MI,
1486-
MachineBasicBlock *BB) const;
1485+
MachineBasicBlock *EmitLoweredIndirectThunk(MachineInstr &MI,
1486+
MachineBasicBlock *BB) const;
14871487

14881488
MachineBasicBlock *emitEHSjLjSetJmp(MachineInstr &MI,
14891489
MachineBasicBlock *MBB) const;

llvm/lib/Target/X86/X86RetpolineThunks.cpp renamed to llvm/lib/Target/X86/X86IndirectThunks.cpp

Lines changed: 44 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//======- X86RetpolineThunks.cpp - Construct retpoline thunks for x86 --=====//
1+
//==- X86IndirectThunks.cpp - Construct indirect call/jump thunks for x86 --=//
22
//
33
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
44
// See https://llvm.org/LICENSE.txt for license information.
@@ -7,12 +7,18 @@
77
//===----------------------------------------------------------------------===//
88
/// \file
99
///
10-
/// Pass that injects an MI thunk implementing a "retpoline". This is
11-
/// a RET-implemented trampoline that is used to lower indirect calls in a way
10+
/// Pass that injects an MI thunk that is used to lower indirect calls in a way
1211
/// that prevents speculation on some x86 processors and can be used to mitigate
1312
/// security vulnerabilities due to targeted speculative execution and side
1413
/// channels such as CVE-2017-5715.
1514
///
15+
/// Currently supported thunks include:
16+
/// - Retpoline -- A RET-implemented trampoline that lowers indirect calls
17+
///
18+
/// Note that the reason that this is implemented as a MachineFunctionPass and
19+
/// not a ModulePass is that ModulePasses at this point in the LLVM X86 pipeline
20+
/// serialize all transformations, which can consume lots of memory.
21+
///
1622
/// TODO(chandlerc): All of this code could use better comments and
1723
/// documentation.
1824
///
@@ -37,21 +43,21 @@ using namespace llvm;
3743

3844
#define DEBUG_TYPE "x86-retpoline-thunks"
3945

40-
static const char ThunkNamePrefix[] = "__llvm_retpoline_";
41-
static const char R11ThunkName[] = "__llvm_retpoline_r11";
42-
static const char EAXThunkName[] = "__llvm_retpoline_eax";
43-
static const char ECXThunkName[] = "__llvm_retpoline_ecx";
44-
static const char EDXThunkName[] = "__llvm_retpoline_edx";
45-
static const char EDIThunkName[] = "__llvm_retpoline_edi";
46+
static const char RetpolineNamePrefix[] = "__llvm_retpoline_";
47+
static const char R11RetpolineName[] = "__llvm_retpoline_r11";
48+
static const char EAXRetpolineName[] = "__llvm_retpoline_eax";
49+
static const char ECXRetpolineName[] = "__llvm_retpoline_ecx";
50+
static const char EDXRetpolineName[] = "__llvm_retpoline_edx";
51+
static const char EDIRetpolineName[] = "__llvm_retpoline_edi";
4652

4753
namespace {
48-
class X86RetpolineThunks : public MachineFunctionPass {
54+
class X86IndirectThunks : public MachineFunctionPass {
4955
public:
5056
static char ID;
5157

52-
X86RetpolineThunks() : MachineFunctionPass(ID) {}
58+
X86IndirectThunks() : MachineFunctionPass(ID) {}
5359

54-
StringRef getPassName() const override { return "X86 Retpoline Thunks"; }
60+
StringRef getPassName() const override { return "X86 Indirect Thunks"; }
5561

5662
bool doInitialization(Module &M) override;
5763
bool runOnMachineFunction(MachineFunction &F) override;
@@ -72,24 +78,24 @@ class X86RetpolineThunks : public MachineFunctionPass {
7278
bool InsertedThunks = false;
7379

7480
void createThunkFunction(Module &M, StringRef Name);
75-
void insertRegReturnAddrClobber(MachineBasicBlock &MBB, unsigned Reg);
76-
void populateThunk(MachineFunction &MF, unsigned Reg);
81+
void insertRegReturnAddrClobber(MachineBasicBlock &MBB, Register Reg);
82+
void populateThunk(MachineFunction &MF, Register Reg);
7783
};
7884

7985
} // end anonymous namespace
8086

81-
FunctionPass *llvm::createX86RetpolineThunksPass() {
82-
return new X86RetpolineThunks();
87+
FunctionPass *llvm::createX86IndirectThunksPass() {
88+
return new X86IndirectThunks();
8389
}
8490

85-
char X86RetpolineThunks::ID = 0;
91+
char X86IndirectThunks::ID = 0;
8692

87-
bool X86RetpolineThunks::doInitialization(Module &M) {
93+
bool X86IndirectThunks::doInitialization(Module &M) {
8894
InsertedThunks = false;
8995
return false;
9096
}
9197

92-
bool X86RetpolineThunks::runOnMachineFunction(MachineFunction &MF) {
98+
bool X86IndirectThunks::runOnMachineFunction(MachineFunction &MF) {
9399
LLVM_DEBUG(dbgs() << getPassName() << '\n');
94100

95101
TM = &MF.getTarget();;
@@ -102,7 +108,7 @@ bool X86RetpolineThunks::runOnMachineFunction(MachineFunction &MF) {
102108

103109
// If this function is not a thunk, check to see if we need to insert
104110
// a thunk.
105-
if (!MF.getName().startswith(ThunkNamePrefix)) {
111+
if (!MF.getName().startswith(RetpolineNamePrefix)) {
106112
// If we've already inserted a thunk, nothing else to do.
107113
if (InsertedThunks)
108114
return false;
@@ -124,10 +130,11 @@ bool X86RetpolineThunks::runOnMachineFunction(MachineFunction &MF) {
124130
// pass. We extract the module and insert a new function (and machine
125131
// function) directly into the module.
126132
if (Is64Bit)
127-
createThunkFunction(M, R11ThunkName);
133+
createThunkFunction(M, R11RetpolineName);
128134
else
129135
for (StringRef Name :
130-
{EAXThunkName, ECXThunkName, EDXThunkName, EDIThunkName})
136+
{EAXRetpolineName, ECXRetpolineName, EDXRetpolineName,
137+
EDIRetpolineName})
131138
createThunkFunction(M, Name);
132139
InsertedThunks = true;
133140
return true;
@@ -177,13 +184,13 @@ bool X86RetpolineThunks::runOnMachineFunction(MachineFunction &MF) {
177184
// ... # Same setup
178185
// movl %edi, (%esp)
179186
// retl
180-
if (MF.getName() == EAXThunkName)
187+
if (MF.getName() == EAXRetpolineName)
181188
populateThunk(MF, X86::EAX);
182-
else if (MF.getName() == ECXThunkName)
189+
else if (MF.getName() == ECXRetpolineName)
183190
populateThunk(MF, X86::ECX);
184-
else if (MF.getName() == EDXThunkName)
191+
else if (MF.getName() == EDXRetpolineName)
185192
populateThunk(MF, X86::EDX);
186-
else if (MF.getName() == EDIThunkName)
193+
else if (MF.getName() == EDIRetpolineName)
187194
populateThunk(MF, X86::EDI);
188195
else
189196
llvm_unreachable("Invalid thunk name on x86-32!");
@@ -192,8 +199,8 @@ bool X86RetpolineThunks::runOnMachineFunction(MachineFunction &MF) {
192199
return true;
193200
}
194201

195-
void X86RetpolineThunks::createThunkFunction(Module &M, StringRef Name) {
196-
assert(Name.startswith(ThunkNamePrefix) &&
202+
void X86IndirectThunks::createThunkFunction(Module &M, StringRef Name) {
203+
assert(Name.startswith(RetpolineNamePrefix) &&
197204
"Created a thunk with an unexpected prefix!");
198205

199206
LLVMContext &Ctx = M.getContext();
@@ -226,16 +233,16 @@ void X86RetpolineThunks::createThunkFunction(Module &M, StringRef Name) {
226233
MF.insert(MF.end(), EntryMBB);
227234
}
228235

229-
void X86RetpolineThunks::insertRegReturnAddrClobber(MachineBasicBlock &MBB,
230-
unsigned Reg) {
236+
void X86IndirectThunks::insertRegReturnAddrClobber(MachineBasicBlock &MBB,
237+
Register Reg) {
231238
const unsigned MovOpc = Is64Bit ? X86::MOV64mr : X86::MOV32mr;
232-
const unsigned SPReg = Is64Bit ? X86::RSP : X86::ESP;
239+
const Register SPReg = Is64Bit ? X86::RSP : X86::ESP;
233240
addRegOffset(BuildMI(&MBB, DebugLoc(), TII->get(MovOpc)), SPReg, false, 0)
234241
.addReg(Reg);
235242
}
236243

237-
void X86RetpolineThunks::populateThunk(MachineFunction &MF,
238-
unsigned Reg) {
244+
void X86IndirectThunks::populateThunk(MachineFunction &MF,
245+
Register Reg) {
239246
// Set MF properties. We never use vregs...
240247
MF.getProperties().set(MachineFunctionProperties::Property::NoVRegs);
241248

@@ -246,8 +253,10 @@ void X86RetpolineThunks::populateThunk(MachineFunction &MF,
246253
while (MF.size() > 1)
247254
MF.erase(std::next(MF.begin()));
248255

249-
MachineBasicBlock *CaptureSpec = MF.CreateMachineBasicBlock(Entry->getBasicBlock());
250-
MachineBasicBlock *CallTarget = MF.CreateMachineBasicBlock(Entry->getBasicBlock());
256+
MachineBasicBlock *CaptureSpec =
257+
MF.CreateMachineBasicBlock(Entry->getBasicBlock());
258+
MachineBasicBlock *CallTarget =
259+
MF.CreateMachineBasicBlock(Entry->getBasicBlock());
251260
MCSymbol *TargetSym = MF.getContext().createTempSymbol();
252261
MF.push_back(CaptureSpec);
253262
MF.push_back(CallTarget);

0 commit comments

Comments
 (0)