Skip to content

Commit d68d1a1

Browse files
jaidTwkcloudy0717
authored andcommitted
[RISCV] Emit lpad for function with returns-twice attribute (llvm#170520)
Insert the landing pad after the functions with attribute "returns-twice" as such function could return from a indirect branch (e.g. `setcontext`, `swapcontext`, `setjmp`), so that they could use a normal indirect branch which is safer than a software-guarded branch.
1 parent 040e0da commit d68d1a1

File tree

2 files changed

+101
-4
lines changed

2 files changed

+101
-4
lines changed

llvm/lib/Target/RISCV/RISCVIndirectBranchTracking.cpp

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,12 @@
1616
#include "RISCVInstrInfo.h"
1717
#include "RISCVSubtarget.h"
1818
#include "llvm/ADT/Statistic.h"
19+
#include "llvm/CodeGen/MachineBasicBlock.h"
1920
#include "llvm/CodeGen/MachineFunctionPass.h"
2021
#include "llvm/CodeGen/MachineInstrBuilder.h"
2122
#include "llvm/CodeGen/MachineModuleInfo.h"
2223

23-
#define DEBUG_TYPE "riscv-indrect-branch-tracking"
24+
#define DEBUG_TYPE "riscv-indirect-branch-tracking"
2425
#define PASS_NAME "RISC-V Indirect Branch Tracking"
2526

2627
using namespace llvm;
@@ -54,13 +55,25 @@ FunctionPass *llvm::createRISCVIndirectBranchTrackingPass() {
5455
return new RISCVIndirectBranchTracking();
5556
}
5657

57-
static void emitLpad(MachineBasicBlock &MBB, const RISCVInstrInfo *TII,
58-
uint32_t Label) {
59-
auto I = MBB.begin();
58+
static void
59+
emitLpad(MachineBasicBlock &MBB, const RISCVInstrInfo *TII, uint32_t Label,
60+
MachineBasicBlock::iterator I = MachineBasicBlock::iterator{}) {
61+
if (!I.isValid())
62+
I = MBB.begin();
6063
BuildMI(MBB, I, MBB.findDebugLoc(I), TII->get(RISCV::AUIPC), RISCV::X0)
6164
.addImm(Label);
6265
}
6366

67+
static bool isCallReturnTwice(const MachineOperand &MOp) {
68+
if (!MOp.isGlobal())
69+
return false;
70+
auto *CalleeFn = dyn_cast<Function>(MOp.getGlobal());
71+
if (!CalleeFn)
72+
return false;
73+
AttributeList Attrs = CalleeFn->getAttributes();
74+
return Attrs.hasFnAttr(Attribute::ReturnsTwice);
75+
}
76+
6477
bool RISCVIndirectBranchTracking::runOnMachineFunction(MachineFunction &MF) {
6578
const auto &Subtarget = MF.getSubtarget<RISCVSubtarget>();
6679
const RISCVInstrInfo *TII = Subtarget.getInstrInfo();
@@ -100,5 +113,18 @@ bool RISCVIndirectBranchTracking::runOnMachineFunction(MachineFunction &MF) {
100113
}
101114
}
102115

116+
// Check for calls to functions with ReturnsTwice attribute and insert
117+
// LPAD after such calls
118+
for (MachineBasicBlock &MBB : MF) {
119+
for (MachineBasicBlock::iterator I = MBB.begin(); I != MBB.end(); ++I) {
120+
if (I->isCall() && I->getNumOperands() > 0 &&
121+
isCallReturnTwice(I->getOperand(0))) {
122+
auto NextI = std::next(I);
123+
emitLpad(MBB, TII, FixedLabel, NextI);
124+
Changed = true;
125+
}
126+
}
127+
}
128+
103129
return Changed;
104130
}

llvm/test/CodeGen/RISCV/lpad.ll

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,3 +289,74 @@ define void @interrupt() "interrupt"="machine" {
289289
; FIXED-ONE-NEXT: mret
290290
ret void
291291
}
292+
293+
declare i32 @setjmp(ptr) returns_twice
294+
295+
define i32 @test_returns_twice() {
296+
; RV32-LABEL: test_returns_twice:
297+
; RV32: # %bb.0:
298+
; RV32-NEXT: lpad 0
299+
; RV32-NEXT: addi sp, sp, -16
300+
; RV32-NEXT: .cfi_def_cfa_offset 16
301+
; RV32-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
302+
; RV32-NEXT: .cfi_offset ra, -4
303+
; RV32-NEXT: addi a0, sp, 8
304+
; RV32-NEXT: call setjmp
305+
; RV32-NEXT: lpad 0
306+
; RV32-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
307+
; RV32-NEXT: .cfi_restore ra
308+
; RV32-NEXT: addi sp, sp, 16
309+
; RV32-NEXT: .cfi_def_cfa_offset 0
310+
; RV32-NEXT: ret
311+
;
312+
; RV64-LABEL: test_returns_twice:
313+
; RV64: # %bb.0:
314+
; RV64-NEXT: lpad 0
315+
; RV64-NEXT: addi sp, sp, -16
316+
; RV64-NEXT: .cfi_def_cfa_offset 16
317+
; RV64-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
318+
; RV64-NEXT: .cfi_offset ra, -8
319+
; RV64-NEXT: addi a0, sp, 4
320+
; RV64-NEXT: call setjmp
321+
; RV64-NEXT: lpad 0
322+
; RV64-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
323+
; RV64-NEXT: .cfi_restore ra
324+
; RV64-NEXT: addi sp, sp, 16
325+
; RV64-NEXT: .cfi_def_cfa_offset 0
326+
; RV64-NEXT: ret
327+
;
328+
; FIXED-ONE-RV32-LABEL: test_returns_twice:
329+
; FIXED-ONE-RV32: # %bb.0:
330+
; FIXED-ONE-RV32-NEXT: lpad 1
331+
; FIXED-ONE-RV32-NEXT: addi sp, sp, -16
332+
; FIXED-ONE-RV32-NEXT: .cfi_def_cfa_offset 16
333+
; FIXED-ONE-RV32-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
334+
; FIXED-ONE-RV32-NEXT: .cfi_offset ra, -4
335+
; FIXED-ONE-RV32-NEXT: addi a0, sp, 8
336+
; FIXED-ONE-RV32-NEXT: call setjmp
337+
; FIXED-ONE-RV32-NEXT: lpad 1
338+
; FIXED-ONE-RV32-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
339+
; FIXED-ONE-RV32-NEXT: .cfi_restore ra
340+
; FIXED-ONE-RV32-NEXT: addi sp, sp, 16
341+
; FIXED-ONE-RV32-NEXT: .cfi_def_cfa_offset 0
342+
; FIXED-ONE-RV32-NEXT: ret
343+
;
344+
; FIXED-ONE-RV64-LABEL: test_returns_twice:
345+
; FIXED-ONE-RV64: # %bb.0:
346+
; FIXED-ONE-RV64-NEXT: lpad 1
347+
; FIXED-ONE-RV64-NEXT: addi sp, sp, -16
348+
; FIXED-ONE-RV64-NEXT: .cfi_def_cfa_offset 16
349+
; FIXED-ONE-RV64-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
350+
; FIXED-ONE-RV64-NEXT: .cfi_offset ra, -8
351+
; FIXED-ONE-RV64-NEXT: addi a0, sp, 4
352+
; FIXED-ONE-RV64-NEXT: call setjmp
353+
; FIXED-ONE-RV64-NEXT: lpad 1
354+
; FIXED-ONE-RV64-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
355+
; FIXED-ONE-RV64-NEXT: .cfi_restore ra
356+
; FIXED-ONE-RV64-NEXT: addi sp, sp, 16
357+
; FIXED-ONE-RV64-NEXT: .cfi_def_cfa_offset 0
358+
; FIXED-ONE-RV64-NEXT: ret
359+
%buf = alloca [1 x i32], align 4
360+
%call = call i32 @setjmp(ptr %buf)
361+
ret i32 %call
362+
}

0 commit comments

Comments
 (0)