Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dynamic stack frame size support #26

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the total stack size known to llvm or does it allow overflow expecting the runtime to catch it?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It can't be known statically and the runtime needs to handle overflows anyway for hand rolled code

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
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't we want to keep displaying this message for fixed solana stack frames?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup nice catch, fixed

<< " 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