Skip to content

Commit 7b107cd

Browse files
Dynamic stack frame size support (rust-lang#26)
[SOL] Introduce dynamic stack frames and the SBFv2 flag Introduce dynamic stack frames, which are currently opt-in and enabled setting cpu=sbfv2. When sbfv2 is used, ELF files are flagged with e_flags=EF_SBF_V2 so the runtime can detect it and react accordingly. Co-authored-by: Dmitri Makarov <[email protected]>
1 parent 321d9c0 commit 7b107cd

File tree

7 files changed

+94
-36
lines changed

7 files changed

+94
-36
lines changed

llvm/include/llvm/BinaryFormat/ELF.h

+6
Original file line numberDiff line numberDiff line change
@@ -807,6 +807,12 @@ enum {
807807
#include "ELFRelocs/AMDGPU.def"
808808
};
809809

810+
// SBF specific e_flags
811+
812+
enum : unsigned {
813+
EF_SBF_V2 = 0x20,
814+
};
815+
810816
// ELF Relocation types for BPF
811817
enum {
812818
#include "ELFRelocs/BPF.def"

llvm/lib/Target/BPF/BPF.td

+13-9
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,6 @@ include "BPFInstrInfo.td"
1414

1515
def BPFInstrInfo : InstrInfo;
1616

17-
class Proc<string Name, list<SubtargetFeature> Features>
18-
: Processor<Name, NoItineraries, Features>;
19-
20-
def : Proc<"generic", []>;
21-
def : Proc<"v1", []>;
22-
def : Proc<"v2", []>;
23-
def : Proc<"v3", []>;
24-
def : Proc<"probe", []>;
25-
2617
def DummyFeature : SubtargetFeature<"dummy", "isDummyMode",
2718
"true", "unused feature">;
2819

@@ -35,6 +26,19 @@ def DwarfRIS: SubtargetFeature<"dwarfris", "UseDwarfRIS", "true",
3526
def FeatureSolana : SubtargetFeature<"solana", "IsSolana", "true",
3627
"Enable Solana extensions">;
3728

29+
def FeatureDynamicFrames : SubtargetFeature<"dynamic-frames", "HasDynamicFrames", "true",
30+
"Enable dynamic frames">;
31+
32+
class Proc<string Name, list<SubtargetFeature> Features>
33+
: Processor<Name, NoItineraries, Features>;
34+
35+
def : Proc<"generic", []>;
36+
def : Proc<"v1", []>;
37+
def : Proc<"v2", []>;
38+
def : Proc<"v3", []>;
39+
def : Proc<"probe", []>;
40+
def : Proc<"sbfv2", [FeatureSolana, FeatureDynamicFrames]>;
41+
3842
def BPFInstPrinter : AsmWriter {
3943
string AsmWriterClassName = "InstPrinter";
4044
bit isMCAsmWriter = 1;

llvm/lib/Target/BPF/BPFFrameLowering.cpp

+33-2
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,44 @@
2020

2121
using namespace llvm;
2222

23+
namespace {
24+
25+
void adjustStackPointer(MachineFunction &MF, MachineBasicBlock &MBB,
26+
MachineBasicBlock::iterator &MBBI,
27+
unsigned int Opcode) {
28+
MachineFrameInfo &MFI = MF.getFrameInfo();
29+
int NumBytes = (int)MFI.getStackSize();
30+
if (NumBytes) {
31+
DebugLoc Dl;
32+
const BPFInstrInfo &TII =
33+
*static_cast<const BPFInstrInfo *>(MF.getSubtarget().getInstrInfo());
34+
BuildMI(MBB, MBBI, Dl, TII.get(Opcode), BPF::R11)
35+
.addReg(BPF::R11)
36+
.addImm(NumBytes);
37+
}
38+
}
39+
40+
} // namespace
41+
2342
bool BPFFrameLowering::hasFP(const MachineFunction &MF) const { return true; }
2443

2544
void BPFFrameLowering::emitPrologue(MachineFunction &MF,
26-
MachineBasicBlock &MBB) const {}
45+
MachineBasicBlock &MBB) const {
46+
if (!MF.getSubtarget<BPFSubtarget>().getHasDynamicFrames()) {
47+
return;
48+
}
49+
MachineBasicBlock::iterator MBBI = MBB.begin();
50+
adjustStackPointer(MF, MBB, MBBI, BPF::SUB_ri);
51+
}
2752

2853
void BPFFrameLowering::emitEpilogue(MachineFunction &MF,
29-
MachineBasicBlock &MBB) const {}
54+
MachineBasicBlock &MBB) const {
55+
if (!MF.getSubtarget<BPFSubtarget>().getHasDynamicFrames()) {
56+
return;
57+
}
58+
MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
59+
adjustStackPointer(MF, MBB, MBBI, BPF::ADD_ri);
60+
}
3061

3162
void BPFFrameLowering::determineCalleeSaves(MachineFunction &MF,
3263
BitVector &SavedRegs,

llvm/lib/Target/BPF/BPFRegisterInfo.cpp

+11-18
Original file line numberDiff line numberDiff line change
@@ -52,22 +52,11 @@ static void WarnSize(int Offset, MachineFunction &MF, DebugLoc& DL)
5252
OldMF = &(MF.getFunction());
5353
int MaxOffset = -1 * BPFRegisterInfo::FrameLength;
5454
if (Offset <= MaxOffset) {
55-
if (MF.getSubtarget<BPFSubtarget>().isSolana()) {
56-
dbgs() << "Error:";
57-
if (DL) {
58-
dbgs() << " ";
59-
DL.print(dbgs());
60-
}
61-
dbgs() << " Function " << MF.getFunction().getName() << " Stack offset of " << -Offset
62-
<< " exceeded max offset of " << -MaxOffset << " by "
63-
<< MaxOffset - Offset << " bytes, please minimize large stack variables\n";
64-
} else {
65-
DiagnosticInfoUnsupported DiagStackSize(MF.getFunction(),
66-
"BPF stack limit of 512 bytes is exceeded. "
67-
"Please move large on stack variables into BPF per-cpu array map.\n",
68-
DL);
69-
MF.getFunction().getContext().diagnose(DiagStackSize);
70-
}
55+
DiagnosticInfoUnsupported DiagStackSize(MF.getFunction(),
56+
"BPF stack limit of 512 bytes is exceeded. "
57+
"Please move large on stack variables into BPF per-cpu array map.\n",
58+
DL);
59+
MF.getFunction().getContext().diagnose(DiagStackSize);
7160
}
7261
}
7362

@@ -102,7 +91,9 @@ void BPFRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
10291
if (MI.getOpcode() == BPF::MOV_rr) {
10392
int Offset = MF.getFrameInfo().getObjectOffset(FrameIndex);
10493

105-
WarnSize(Offset, MF, DL);
94+
if (!MF.getSubtarget<BPFSubtarget>().getHasDynamicFrames()) {
95+
WarnSize(Offset, MF, DL);
96+
}
10697
MI.getOperand(i).ChangeToRegister(FrameReg, false);
10798
Register reg = MI.getOperand(i - 1).getReg();
10899
BuildMI(MBB, ++II, DL, TII.get(BPF::ADD_ri), reg)
@@ -117,7 +108,9 @@ void BPFRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
117108
if (!isInt<32>(Offset))
118109
llvm_unreachable("bug in frame offset");
119110

120-
WarnSize(Offset, MF, DL);
111+
if (!MF.getSubtarget<BPFSubtarget>().getHasDynamicFrames()) {
112+
WarnSize(Offset, MF, DL);
113+
}
121114

122115
if (MI.getOpcode() == BPF::FI_ri) {
123116
// architecture does not really support FI_ri, replace it with

llvm/lib/Target/BPF/BPFSubtarget.cpp

+9-5
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ BPFSubtarget &BPFSubtarget::initializeSubtargetDependencies(const Triple &TT,
3030
StringRef FS) {
3131
initializeEnvironment(TT);
3232
initSubtargetFeatures(CPU, FS);
33-
ParseSubtargetFeatures(CPU, /*TuneCPU*/ CPU, FS);
3433
return *this;
3534
}
3635

@@ -39,23 +38,28 @@ void BPFSubtarget::initializeEnvironment(const Triple &TT) {
3938
HasJmpExt = false;
4039
HasJmp32 = false;
4140
HasAlu32 = false;
41+
HasDynamicFrames = false;
4242
UseDwarfRIS = false;
4343
}
4444

4545
void BPFSubtarget::initSubtargetFeatures(StringRef CPU, StringRef FS) {
4646
if (CPU == "probe")
4747
CPU = sys::detail::getHostCPUNameForBPF();
48-
if (CPU == "generic" || CPU == "v1")
49-
return;
48+
49+
ParseSubtargetFeatures(CPU, /*TuneCPU*/ CPU, FS);
50+
5051
if (CPU == "v2") {
5152
HasJmpExt = true;
52-
return;
5353
}
54+
5455
if (CPU == "v3") {
5556
HasJmpExt = true;
5657
HasJmp32 = true;
5758
HasAlu32 = true;
58-
return;
59+
}
60+
61+
if (CPU == "sbfv2" && !HasDynamicFrames) {
62+
report_fatal_error("sbfv2 requires dynamic-frames\n", false);
5963
}
6064
}
6165

llvm/lib/Target/BPF/BPFSubtarget.h

+4
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@ class BPFSubtarget : public BPFGenSubtargetInfo {
5757
// whether the cpu supports alu32 instructions.
5858
bool HasAlu32;
5959

60+
// whether we should use fixed or dynamic frames
61+
bool HasDynamicFrames;
62+
6063
// whether we should enable MCAsmInfo DwarfUsesRelocationsAcrossSections
6164
bool UseDwarfRIS;
6265

@@ -75,6 +78,7 @@ class BPFSubtarget : public BPFGenSubtargetInfo {
7578
bool getHasJmpExt() const { return HasJmpExt; }
7679
bool getHasJmp32() const { return HasJmp32; }
7780
bool getHasAlu32() const { return HasAlu32; }
81+
bool getHasDynamicFrames() const { return HasDynamicFrames; }
7882
bool getUseDwarfRIS() const { return UseDwarfRIS; }
7983

8084
const BPFInstrInfo *getInstrInfo() const override { return &InstrInfo; }

llvm/lib/Target/BPF/MCTargetDesc/BPFMCTargetDesc.cpp

+18-2
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,14 @@
1414
#include "MCTargetDesc/BPFInstPrinter.h"
1515
#include "MCTargetDesc/BPFMCAsmInfo.h"
1616
#include "TargetInfo/BPFTargetInfo.h"
17+
#include "llvm/BinaryFormat/ELF.h"
18+
#include "llvm/MC/MCAsmBackend.h"
19+
#include "llvm/MC/MCCodeEmitter.h"
20+
#include "llvm/MC/MCContext.h"
21+
#include "llvm/MC/MCELFStreamer.h"
1722
#include "llvm/MC/MCInstrAnalysis.h"
1823
#include "llvm/MC/MCInstrInfo.h"
24+
#include "llvm/MC/MCObjectWriter.h"
1925
#include "llvm/MC/MCRegisterInfo.h"
2026
#include "llvm/MC/MCSubtargetInfo.h"
2127
#include "llvm/Support/Host.h"
@@ -54,8 +60,18 @@ static MCStreamer *createBPFMCStreamer(const Triple &T, MCContext &Ctx,
5460
std::unique_ptr<MCObjectWriter> &&OW,
5561
std::unique_ptr<MCCodeEmitter> &&Emitter,
5662
bool RelaxAll) {
57-
return createELFStreamer(Ctx, std::move(MAB), std::move(OW), std::move(Emitter),
58-
RelaxAll);
63+
MCELFStreamer *S =
64+
new MCELFStreamer(Ctx, std::move(MAB), std::move(OW), std::move(Emitter));
65+
MCAssembler &A = S->getAssembler();
66+
if (RelaxAll)
67+
A.setRelaxAll(true);
68+
69+
const MCSubtargetInfo *STI = Ctx.getSubtargetInfo();
70+
if (STI->getCPU() == "sbfv2") {
71+
A.setELFHeaderEFlags(llvm::ELF::EF_SBF_V2);
72+
}
73+
74+
return S;
5975
}
6076

6177
static MCInstPrinter *createBPFMCInstPrinter(const Triple &T,

0 commit comments

Comments
 (0)