From 7b107cd845e9117077ba96657cd01fc76ce9f70e Mon Sep 17 00:00:00 2001 From: Alessandro Decina Date: Tue, 8 Mar 2022 11:22:37 +1100 Subject: [PATCH] Dynamic stack frame size support (#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 --- llvm/include/llvm/BinaryFormat/ELF.h | 6 ++++ llvm/lib/Target/BPF/BPF.td | 22 +++++++----- llvm/lib/Target/BPF/BPFFrameLowering.cpp | 35 +++++++++++++++++-- llvm/lib/Target/BPF/BPFRegisterInfo.cpp | 29 ++++++--------- llvm/lib/Target/BPF/BPFSubtarget.cpp | 14 +++++--- llvm/lib/Target/BPF/BPFSubtarget.h | 4 +++ .../BPF/MCTargetDesc/BPFMCTargetDesc.cpp | 20 +++++++++-- 7 files changed, 94 insertions(+), 36 deletions(-) diff --git a/llvm/include/llvm/BinaryFormat/ELF.h b/llvm/include/llvm/BinaryFormat/ELF.h index 6148f968cdbaa3..e64b9824a3c57b 100644 --- a/llvm/include/llvm/BinaryFormat/ELF.h +++ b/llvm/include/llvm/BinaryFormat/ELF.h @@ -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" diff --git a/llvm/lib/Target/BPF/BPF.td b/llvm/lib/Target/BPF/BPF.td index 38f033b800187e..85c480667ff32f 100644 --- a/llvm/lib/Target/BPF/BPF.td +++ b/llvm/lib/Target/BPF/BPF.td @@ -14,15 +14,6 @@ include "BPFInstrInfo.td" def BPFInstrInfo : InstrInfo; -class Proc Features> - : Processor; - -def : Proc<"generic", []>; -def : Proc<"v1", []>; -def : Proc<"v2", []>; -def : Proc<"v3", []>; -def : Proc<"probe", []>; - def DummyFeature : SubtargetFeature<"dummy", "isDummyMode", "true", "unused feature">; @@ -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 Features> + : Processor; + +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; diff --git a/llvm/lib/Target/BPF/BPFFrameLowering.cpp b/llvm/lib/Target/BPF/BPFFrameLowering.cpp index 8812cfdd86da43..c3b088ae2991ac 100644 --- a/llvm/lib/Target/BPF/BPFFrameLowering.cpp +++ b/llvm/lib/Target/BPF/BPFFrameLowering.cpp @@ -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(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().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().getHasDynamicFrames()) { + return; + } + MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr(); + adjustStackPointer(MF, MBB, MBBI, BPF::ADD_ri); +} void BPFFrameLowering::determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs, diff --git a/llvm/lib/Target/BPF/BPFRegisterInfo.cpp b/llvm/lib/Target/BPF/BPFRegisterInfo.cpp index fd9cffe6ccc0c3..2fb147427e6499 100644 --- a/llvm/lib/Target/BPF/BPFRegisterInfo.cpp +++ b/llvm/lib/Target/BPF/BPFRegisterInfo.cpp @@ -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().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); } } @@ -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().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) @@ -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().getHasDynamicFrames()) { + WarnSize(Offset, MF, DL); + } if (MI.getOpcode() == BPF::FI_ri) { // architecture does not really support FI_ri, replace it with diff --git a/llvm/lib/Target/BPF/BPFSubtarget.cpp b/llvm/lib/Target/BPF/BPFSubtarget.cpp index 3e842a5466c773..ad126818ba3c92 100644 --- a/llvm/lib/Target/BPF/BPFSubtarget.cpp +++ b/llvm/lib/Target/BPF/BPFSubtarget.cpp @@ -30,7 +30,6 @@ BPFSubtarget &BPFSubtarget::initializeSubtargetDependencies(const Triple &TT, StringRef FS) { initializeEnvironment(TT); initSubtargetFeatures(CPU, FS); - ParseSubtargetFeatures(CPU, /*TuneCPU*/ CPU, FS); return *this; } @@ -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); } } diff --git a/llvm/lib/Target/BPF/BPFSubtarget.h b/llvm/lib/Target/BPF/BPFSubtarget.h index 6ec94a21cd3c91..401f3972ddead0 100644 --- a/llvm/lib/Target/BPF/BPFSubtarget.h +++ b/llvm/lib/Target/BPF/BPFSubtarget.h @@ -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; @@ -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; } diff --git a/llvm/lib/Target/BPF/MCTargetDesc/BPFMCTargetDesc.cpp b/llvm/lib/Target/BPF/MCTargetDesc/BPFMCTargetDesc.cpp index 975404a00ee7cc..ee3538106b4dc4 100644 --- a/llvm/lib/Target/BPF/MCTargetDesc/BPFMCTargetDesc.cpp +++ b/llvm/lib/Target/BPF/MCTargetDesc/BPFMCTargetDesc.cpp @@ -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" @@ -54,8 +60,18 @@ static MCStreamer *createBPFMCStreamer(const Triple &T, MCContext &Ctx, std::unique_ptr &&OW, std::unique_ptr &&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,