MachineModuleInfo: Move HasSplitStack handling to AsmPrinter

This is used to emit one field in doFinalization for the module. We
can accumulate this when emitting all individual functions directly in
the AsmPrinter, rather than accumulating additional state in
MachineModuleInfo.

Move the special case behavior predicate into MachineFrameInfo to
share it. This now promotes it to generic behavior. I'm assuming this
is fine because no other target implements adjustForSegmentedStacks,
or has tests using the split-stack attribute.
This commit is contained in:
Matt Arsenault 2022-04-17 10:47:38 -04:00
parent 8544523dcb
commit d7938b1a81
9 changed files with 44 additions and 58 deletions

View File

@ -210,6 +210,16 @@ private:
/// CFISection type the module needs i.e. either .eh_frame or .debug_frame. /// CFISection type the module needs i.e. either .eh_frame or .debug_frame.
CFISection ModuleCFISection = CFISection::None; CFISection ModuleCFISection = CFISection::None;
/// True if the module contains split-stack functions. This is used to
/// emit .note.GNU-split-stack section as required by the linker for
/// special handling split-stack function calling no-split-stack function.
bool HasSplitStack = false;
/// True if the module contains no-split-stack functions. This is used to emit
/// .note.GNU-no-split-stack section when it also contains functions without a
/// split stack prologue.
bool HasNoSplitStack = false;
protected: protected:
explicit AsmPrinter(TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer); explicit AsmPrinter(TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer);

View File

@ -385,6 +385,20 @@ public:
bool hasPatchPoint() const { return HasPatchPoint; } bool hasPatchPoint() const { return HasPatchPoint; }
void setHasPatchPoint(bool s = true) { HasPatchPoint = s; } void setHasPatchPoint(bool s = true) { HasPatchPoint = s; }
/// Return true if this function requires a split stack prolog, even if it
/// uses no stack space. This is only meaningful for functions where
/// MachineFunction::shouldSplitStack() returns true.
//
// For non-leaf functions we have to allow for the possibility that the call
// is to a non-split function, as in PR37807. This function could also take
// the address of a non-split function. When the linker tries to adjust its
// non-existent prologue, it would fail with an error. Mark the object file so
// that such failures are not errors. See this Go language bug-report
// https://go-review.googlesource.com/c/go/+/148819/
bool needsSplitStackProlog() const {
return getStackSize() != 0 || hasTailCall();
}
/// Return the minimum frame object index. /// Return the minimum frame object index.
int getObjectIndexBegin() const { return -NumFixedObjects; } int getObjectIndexBegin() const { return -NumFixedObjects; }

View File

@ -129,16 +129,6 @@ class MachineModuleInfo {
/// comments in lib/Target/X86/X86FrameLowering.cpp for more details. /// comments in lib/Target/X86/X86FrameLowering.cpp for more details.
bool UsesMorestackAddr; bool UsesMorestackAddr;
/// True if the module contains split-stack functions. This is used to
/// emit .note.GNU-split-stack section as required by the linker for
/// special handling split-stack function calling no-split-stack function.
bool HasSplitStack;
/// True if the module contains no-split-stack functions. This is used to
/// emit .note.GNU-no-split-stack section when it also contains split-stack
/// functions.
bool HasNosplitStack;
/// Maps IR Functions to their corresponding MachineFunctions. /// Maps IR Functions to their corresponding MachineFunctions.
DenseMap<const Function*, std::unique_ptr<MachineFunction>> MachineFunctions; DenseMap<const Function*, std::unique_ptr<MachineFunction>> MachineFunctions;
/// Next unique number available for a MachineFunction. /// Next unique number available for a MachineFunction.
@ -213,22 +203,6 @@ public:
UsesMorestackAddr = b; UsesMorestackAddr = b;
} }
bool hasSplitStack() const {
return HasSplitStack;
}
void setHasSplitStack(bool b) {
HasSplitStack = b;
}
bool hasNosplitStack() const {
return HasNosplitStack;
}
void setHasNosplitStack(bool b) {
HasNosplitStack = b;
}
/// Return the symbol to be used for the specified basic block when its /// Return the symbol to be used for the specified basic block when its
/// address is taken. This cannot be its normal LBB label because the block /// address is taken. This cannot be its normal LBB label because the block
/// may be accessed outside its containing function. /// may be accessed outside its containing function.

View File

@ -257,6 +257,8 @@ void AsmPrinter::getAnalysisUsage(AnalysisUsage &AU) const {
bool AsmPrinter::doInitialization(Module &M) { bool AsmPrinter::doInitialization(Module &M) {
auto *MMIWP = getAnalysisIfAvailable<MachineModuleInfoWrapperPass>(); auto *MMIWP = getAnalysisIfAvailable<MachineModuleInfoWrapperPass>();
MMI = MMIWP ? &MMIWP->getMMI() : nullptr; MMI = MMIWP ? &MMIWP->getMMI() : nullptr;
HasSplitStack = false;
HasNoSplitStack = false;
// Initialize TargetLoweringObjectFile. // Initialize TargetLoweringObjectFile.
const_cast<TargetLoweringObjectFile&>(getObjFileLowering()) const_cast<TargetLoweringObjectFile&>(getObjFileLowering())
@ -1921,10 +1923,10 @@ bool AsmPrinter::doFinalization(Module &M) {
// Emit .note.GNU-split-stack and .note.GNU-no-split-stack sections if // Emit .note.GNU-split-stack and .note.GNU-no-split-stack sections if
// split-stack is used. // split-stack is used.
if (TM.getTargetTriple().isOSBinFormatELF() && MMI->hasSplitStack()) { if (TM.getTargetTriple().isOSBinFormatELF() && HasSplitStack) {
OutStreamer->SwitchSection( OutStreamer->SwitchSection(
OutContext.getELFSection(".note.GNU-split-stack", ELF::SHT_PROGBITS, 0)); OutContext.getELFSection(".note.GNU-split-stack", ELF::SHT_PROGBITS, 0));
if (MMI->hasNosplitStack()) if (HasNoSplitStack)
OutStreamer->SwitchSection( OutStreamer->SwitchSection(
OutContext.getELFSection(".note.GNU-no-split-stack", ELF::SHT_PROGBITS, 0)); OutContext.getELFSection(".note.GNU-no-split-stack", ELF::SHT_PROGBITS, 0));
} }
@ -1991,6 +1993,16 @@ void AsmPrinter::SetupMachineFunction(MachineFunction &MF) {
this->MF = &MF; this->MF = &MF;
const Function &F = MF.getFunction(); const Function &F = MF.getFunction();
// Record that there are split-stack functions, so we will emit a special
// section to tell the linker.
if (MF.shouldSplitStack()) {
HasSplitStack = true;
if (!MF.getFrameInfo().needsSplitStackProlog())
HasNoSplitStack = true;
} else
HasNoSplitStack = true;
// Get the function symbol. // Get the function symbol.
if (!MAI->needsFunctionDescriptors()) { if (!MAI->needsFunctionDescriptors()) {
CurrentFnSym = getSymbol(&MF.getFunction()); CurrentFnSym = getSymbol(&MF.getFunction());

View File

@ -203,7 +203,6 @@ void MachineModuleInfo::initialize() {
CurCallSite = 0; CurCallSite = 0;
NextFnNum = 0; NextFnNum = 0;
UsesMSVCFloatingPoint = UsesMorestackAddr = false; UsesMSVCFloatingPoint = UsesMorestackAddr = false;
HasSplitStack = HasNosplitStack = false;
AddrLabelSymbols = nullptr; AddrLabelSymbols = nullptr;
DbgInfoAvailable = false; DbgInfoAvailable = false;
} }
@ -232,8 +231,6 @@ MachineModuleInfo::MachineModuleInfo(MachineModuleInfo &&MMI)
CurCallSite = MMI.CurCallSite; CurCallSite = MMI.CurCallSite;
UsesMSVCFloatingPoint = MMI.UsesMSVCFloatingPoint; UsesMSVCFloatingPoint = MMI.UsesMSVCFloatingPoint;
UsesMorestackAddr = MMI.UsesMorestackAddr; UsesMorestackAddr = MMI.UsesMorestackAddr;
HasSplitStack = MMI.HasSplitStack;
HasNosplitStack = MMI.HasNosplitStack;
AddrLabelSymbols = MMI.AddrLabelSymbols; AddrLabelSymbols = MMI.AddrLabelSymbols;
ExternalContext = MMI.ExternalContext; ExternalContext = MMI.ExternalContext;
TheModule = MMI.TheModule; TheModule = MMI.TheModule;

View File

@ -1144,11 +1144,7 @@ void PEI::insertPrologEpilogCode(MachineFunction &MF) {
if (MF.shouldSplitStack()) { if (MF.shouldSplitStack()) {
for (MachineBasicBlock *SaveBlock : SaveBlocks) for (MachineBasicBlock *SaveBlock : SaveBlocks)
TFI.adjustForSegmentedStacks(MF, *SaveBlock); TFI.adjustForSegmentedStacks(MF, *SaveBlock);
// Record that there are split-stack functions, so we will emit a }
// special section to tell the linker.
MF.getMMI().setHasSplitStack(true);
} else
MF.getMMI().setHasNosplitStack(true);
// Emit additional code that is required to explicitly handle the stack in // Emit additional code that is required to explicitly handle the stack in
// HiPE native code (if needed) when loaded in the Erlang/OTP runtime. The // HiPE native code (if needed) when loaded in the Erlang/OTP runtime. The

View File

@ -24,6 +24,7 @@
#include "llvm/ADT/SetVector.h" #include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallString.h"
#include "llvm/BinaryFormat/COFF.h" #include "llvm/BinaryFormat/COFF.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineJumpTableInfo.h" #include "llvm/CodeGen/MachineJumpTableInfo.h"
#include "llvm/CodeGen/MachineModuleInfoImpls.h" #include "llvm/CodeGen/MachineModuleInfoImpls.h"

View File

@ -2506,19 +2506,10 @@ void ARMFrameLowering::adjustForSegmentedStacks(
ARMFunctionInfo *ARMFI = MF.getInfo<ARMFunctionInfo>(); ARMFunctionInfo *ARMFI = MF.getInfo<ARMFunctionInfo>();
DebugLoc DL; DebugLoc DL;
uint64_t StackSize = MFI.getStackSize(); if (!MFI.needsSplitStackProlog())
// Do not generate a prologue for leaf functions with a stack of size zero.
// For non-leaf functions we have to allow for the possibility that the
// callis to a non-split function, as in PR37807. This function could also
// take the address of a non-split function. When the linker tries to adjust
// its non-existent prologue, it would fail with an error. Mark the object
// file so that such failures are not errors. See this Go language bug-report
// https://go-review.googlesource.com/c/go/+/148819/
if (StackSize == 0 && !MFI.hasTailCall()) {
MF.getMMI().setHasNosplitStack(true);
return; return;
}
uint64_t StackSize = MFI.getStackSize();
// Use R4 and R5 as scratch registers. // Use R4 and R5 as scratch registers.
// We save R4 and R5 before use and restore them before leaving the function. // We save R4 and R5 before use and restore them before leaving the function.

View File

@ -2944,17 +2944,8 @@ void X86FrameLowering::adjustForSegmentedStacks(
// prologue. // prologue.
StackSize = MFI.getStackSize(); StackSize = MFI.getStackSize();
// Do not generate a prologue for leaf functions with a stack of size zero. if (!MFI.needsSplitStackProlog())
// For non-leaf functions we have to allow for the possibility that the
// callis to a non-split function, as in PR37807. This function could also
// take the address of a non-split function. When the linker tries to adjust
// its non-existent prologue, it would fail with an error. Mark the object
// file so that such failures are not errors. See this Go language bug-report
// https://go-review.googlesource.com/c/go/+/148819/
if (StackSize == 0 && !MFI.hasTailCall()) {
MF.getMMI().setHasNosplitStack(true);
return; return;
}
MachineBasicBlock *allocMBB = MF.CreateMachineBasicBlock(); MachineBasicBlock *allocMBB = MF.CreateMachineBasicBlock();
MachineBasicBlock *checkMBB = MF.CreateMachineBasicBlock(); MachineBasicBlock *checkMBB = MF.CreateMachineBasicBlock();