Skip to content

Commit

Permalink
Dynamic stack frame size support (rust-lang#26)
Browse files Browse the repository at this point in the history
[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 <dmakarov@alumni.stanford.edu>
  • Loading branch information
alessandrod and dmakarov committed Mar 8, 2022
1 parent 321d9c0 commit 7b107cd
Show file tree
Hide file tree
Showing 7 changed files with 94 additions and 36 deletions.
6 changes: 6 additions & 0 deletions llvm/include/llvm/BinaryFormat/ELF.h
Original file line number Diff line number Diff line change
Expand Up @@ -807,6 +807,12 @@ enum {
#include "ELFRelocs/AMDGPU.def"
};

// SBF specific e_flags

enum : unsigned {
EF_SBF_V2 = 0x20,
};

// ELF Relocation types for BPF
enum {
#include "ELFRelocs/BPF.def"
Expand Down
22 changes: 13 additions & 9 deletions llvm/lib/Target/BPF/BPF.td
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,6 @@ include "BPFInstrInfo.td"

def BPFInstrInfo : InstrInfo;

class Proc<string Name, list<SubtargetFeature> Features>
: Processor<Name, NoItineraries, Features>;

def : Proc<"generic", []>;
def : Proc<"v1", []>;
def : Proc<"v2", []>;
def : Proc<"v3", []>;
def : Proc<"probe", []>;

def DummyFeature : SubtargetFeature<"dummy", "isDummyMode",
"true", "unused feature">;

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

def FeatureDynamicFrames : SubtargetFeature<"dynamic-frames", "HasDynamicFrames", "true",
"Enable dynamic frames">;

class Proc<string Name, list<SubtargetFeature> Features>
: Processor<Name, NoItineraries, Features>;

def : Proc<"generic", []>;
def : Proc<"v1", []>;
def : Proc<"v2", []>;
def : Proc<"v3", []>;
def : Proc<"probe", []>;
def : Proc<"sbfv2", [FeatureSolana, FeatureDynamicFrames]>;

def BPFInstPrinter : AsmWriter {
string AsmWriterClassName = "InstPrinter";
bit isMCAsmWriter = 1;
Expand Down
35 changes: 33 additions & 2 deletions llvm/lib/Target/BPF/BPFFrameLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,44 @@

using namespace llvm;

namespace {

void adjustStackPointer(MachineFunction &MF, MachineBasicBlock &MBB,
MachineBasicBlock::iterator &MBBI,
unsigned int Opcode) {
MachineFrameInfo &MFI = MF.getFrameInfo();
int NumBytes = (int)MFI.getStackSize();
if (NumBytes) {
DebugLoc Dl;
const BPFInstrInfo &TII =
*static_cast<const BPFInstrInfo *>(MF.getSubtarget().getInstrInfo());
BuildMI(MBB, MBBI, Dl, TII.get(Opcode), BPF::R11)
.addReg(BPF::R11)
.addImm(NumBytes);
}
}

} // namespace

bool BPFFrameLowering::hasFP(const MachineFunction &MF) const { return true; }

void BPFFrameLowering::emitPrologue(MachineFunction &MF,
MachineBasicBlock &MBB) const {}
MachineBasicBlock &MBB) const {
if (!MF.getSubtarget<BPFSubtarget>().getHasDynamicFrames()) {
return;
}
MachineBasicBlock::iterator MBBI = MBB.begin();
adjustStackPointer(MF, MBB, MBBI, BPF::SUB_ri);
}

void BPFFrameLowering::emitEpilogue(MachineFunction &MF,
MachineBasicBlock &MBB) const {}
MachineBasicBlock &MBB) const {
if (!MF.getSubtarget<BPFSubtarget>().getHasDynamicFrames()) {
return;
}
MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
adjustStackPointer(MF, MBB, MBBI, BPF::ADD_ri);
}

void BPFFrameLowering::determineCalleeSaves(MachineFunction &MF,
BitVector &SavedRegs,
Expand Down
29 changes: 11 additions & 18 deletions llvm/lib/Target/BPF/BPFRegisterInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,22 +52,11 @@ static void WarnSize(int Offset, MachineFunction &MF, DebugLoc& DL)
OldMF = &(MF.getFunction());
int MaxOffset = -1 * BPFRegisterInfo::FrameLength;
if (Offset <= MaxOffset) {
if (MF.getSubtarget<BPFSubtarget>().isSolana()) {
dbgs() << "Error:";
if (DL) {
dbgs() << " ";
DL.print(dbgs());
}
dbgs() << " Function " << MF.getFunction().getName() << " Stack offset of " << -Offset
<< " exceeded max offset of " << -MaxOffset << " by "
<< MaxOffset - Offset << " bytes, please minimize large stack variables\n";
} else {
DiagnosticInfoUnsupported DiagStackSize(MF.getFunction(),
"BPF stack limit of 512 bytes is exceeded. "
"Please move large on stack variables into BPF per-cpu array map.\n",
DL);
MF.getFunction().getContext().diagnose(DiagStackSize);
}
DiagnosticInfoUnsupported DiagStackSize(MF.getFunction(),
"BPF stack limit of 512 bytes is exceeded. "
"Please move large on stack variables into BPF per-cpu array map.\n",
DL);
MF.getFunction().getContext().diagnose(DiagStackSize);
}
}

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

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

WarnSize(Offset, MF, DL);
if (!MF.getSubtarget<BPFSubtarget>().getHasDynamicFrames()) {
WarnSize(Offset, MF, DL);
}

if (MI.getOpcode() == BPF::FI_ri) {
// architecture does not really support FI_ri, replace it with
Expand Down
14 changes: 9 additions & 5 deletions llvm/lib/Target/BPF/BPFSubtarget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ BPFSubtarget &BPFSubtarget::initializeSubtargetDependencies(const Triple &TT,
StringRef FS) {
initializeEnvironment(TT);
initSubtargetFeatures(CPU, FS);
ParseSubtargetFeatures(CPU, /*TuneCPU*/ CPU, FS);
return *this;
}

Expand All @@ -39,23 +38,28 @@ void BPFSubtarget::initializeEnvironment(const Triple &TT) {
HasJmpExt = false;
HasJmp32 = false;
HasAlu32 = false;
HasDynamicFrames = false;
UseDwarfRIS = false;
}

void BPFSubtarget::initSubtargetFeatures(StringRef CPU, StringRef FS) {
if (CPU == "probe")
CPU = sys::detail::getHostCPUNameForBPF();
if (CPU == "generic" || CPU == "v1")
return;

ParseSubtargetFeatures(CPU, /*TuneCPU*/ CPU, FS);

if (CPU == "v2") {
HasJmpExt = true;
return;
}

if (CPU == "v3") {
HasJmpExt = true;
HasJmp32 = true;
HasAlu32 = true;
return;
}

if (CPU == "sbfv2" && !HasDynamicFrames) {
report_fatal_error("sbfv2 requires dynamic-frames\n", false);
}
}

Expand Down
4 changes: 4 additions & 0 deletions llvm/lib/Target/BPF/BPFSubtarget.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ class BPFSubtarget : public BPFGenSubtargetInfo {
// whether the cpu supports alu32 instructions.
bool HasAlu32;

// whether we should use fixed or dynamic frames
bool HasDynamicFrames;

// whether we should enable MCAsmInfo DwarfUsesRelocationsAcrossSections
bool UseDwarfRIS;

Expand All @@ -75,6 +78,7 @@ class BPFSubtarget : public BPFGenSubtargetInfo {
bool getHasJmpExt() const { return HasJmpExt; }
bool getHasJmp32() const { return HasJmp32; }
bool getHasAlu32() const { return HasAlu32; }
bool getHasDynamicFrames() const { return HasDynamicFrames; }
bool getUseDwarfRIS() const { return UseDwarfRIS; }

const BPFInstrInfo *getInstrInfo() const override { return &InstrInfo; }
Expand Down
20 changes: 18 additions & 2 deletions llvm/lib/Target/BPF/MCTargetDesc/BPFMCTargetDesc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,14 @@
#include "MCTargetDesc/BPFInstPrinter.h"
#include "MCTargetDesc/BPFMCAsmInfo.h"
#include "TargetInfo/BPFTargetInfo.h"
#include "llvm/BinaryFormat/ELF.h"
#include "llvm/MC/MCAsmBackend.h"
#include "llvm/MC/MCCodeEmitter.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCELFStreamer.h"
#include "llvm/MC/MCInstrAnalysis.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCObjectWriter.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/Support/Host.h"
Expand Down Expand Up @@ -54,8 +60,18 @@ static MCStreamer *createBPFMCStreamer(const Triple &T, MCContext &Ctx,
std::unique_ptr<MCObjectWriter> &&OW,
std::unique_ptr<MCCodeEmitter> &&Emitter,
bool RelaxAll) {
return createELFStreamer(Ctx, std::move(MAB), std::move(OW), std::move(Emitter),
RelaxAll);
MCELFStreamer *S =
new MCELFStreamer(Ctx, std::move(MAB), std::move(OW), std::move(Emitter));
MCAssembler &A = S->getAssembler();
if (RelaxAll)
A.setRelaxAll(true);

const MCSubtargetInfo *STI = Ctx.getSubtargetInfo();
if (STI->getCPU() == "sbfv2") {
A.setELFHeaderEFlags(llvm::ELF::EF_SBF_V2);
}

return S;
}

static MCInstPrinter *createBPFMCInstPrinter(const Triple &T,
Expand Down

0 comments on commit 7b107cd

Please sign in to comment.