Skip to content

Commit f049b2c

Browse files
committed
[MC] Emit Stackmaps before debug info
This patch is essentially an alternative to https://reviews.llvm.org/D75836 and was mentioned by @lhames in a comment. The gist of the issue is that Mach-O has restrictions on which kind of sections are allowed after debug info has been emitted, which is also properly asserted within LLVM. Problem is that stack maps are currently emitted as one of the last sections in each target-specific AsmPrinter so far, which would cause the assertion to trigger. The current approach of special casing for the `__LLVM_STACKMAPS` section is not viable either, as downstream users can overwrite the stackmap format using plugins, which may want to use different sections. This patch fixes the issue by emitting the stack map earlier, right before debug info is emitted. The way this is implemented is by taking the choice when to emit the StackMap away from the target AsmPrinter and doing so in the base class. The only disadvantage of this approach is that the `StackMaps` member is now part of the base class, even for targets that do not support them. This is functionaly not a problem however, as emitting an empty `StackMaps` is a no-op. Differential Revision: https://reviews.llvm.org/D132708
1 parent 58645d3 commit f049b2c

File tree

11 files changed

+50
-34
lines changed

11 files changed

+50
-34
lines changed

llvm/include/llvm/CodeGen/AsmPrinter.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "llvm/CodeGen/AsmPrinterHandler.h"
2222
#include "llvm/CodeGen/DwarfStringPoolEntry.h"
2323
#include "llvm/CodeGen/MachineFunctionPass.h"
24+
#include "llvm/CodeGen/StackMaps.h"
2425
#include "llvm/IR/InlineAsm.h"
2526
#include "llvm/Support/ErrorHandling.h"
2627
#include <cstdint>
@@ -68,7 +69,6 @@ class MDNode;
6869
class Module;
6970
class PseudoProbeHandler;
7071
class raw_ostream;
71-
class StackMaps;
7272
class StringRef;
7373
class TargetLoweringObjectFile;
7474
class TargetMachine;
@@ -202,6 +202,8 @@ class AsmPrinter : public MachineFunctionPass {
202202
std::vector<HandlerInfo> Handlers;
203203
size_t NumUserHandlers = 0;
204204

205+
StackMaps SM;
206+
205207
private:
206208
/// If generated on the fly this own the instance.
207209
std::unique_ptr<MachineDominatorTree> OwnedMDT;
@@ -503,7 +505,7 @@ class AsmPrinter : public MachineFunctionPass {
503505
void emitGlobalGOTEquivs();
504506

505507
/// Emit the stack maps.
506-
void emitStackMaps(StackMaps &SM);
508+
void emitStackMaps();
507509

508510
//===------------------------------------------------------------------===//
509511
// Overridable Hooks

llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -354,7 +354,8 @@ Align AsmPrinter::getGVAlignment(const GlobalObject *GV, const DataLayout &DL,
354354

355355
AsmPrinter::AsmPrinter(TargetMachine &tm, std::unique_ptr<MCStreamer> Streamer)
356356
: MachineFunctionPass(ID), TM(tm), MAI(tm.getMCAsmInfo()),
357-
OutContext(Streamer->getContext()), OutStreamer(std::move(Streamer)) {
357+
OutContext(Streamer->getContext()), OutStreamer(std::move(Streamer)),
358+
SM(*this) {
358359
VerboseAsm = OutStreamer->isVerboseAsm();
359360
}
360361

@@ -2078,6 +2079,12 @@ bool AsmPrinter::doFinalization(Module &M) {
20782079
if (auto *TS = OutStreamer->getTargetStreamer())
20792080
TS->emitConstantPools();
20802081

2082+
// Emit Stack maps before any debug info. Mach-O requires that no data or
2083+
// text sections come after debug info has been emitted. This matters for
2084+
// stack maps as they are arbitrary data, and may even have a custom format
2085+
// through user plugins.
2086+
emitStackMaps();
2087+
20812088
// Finalize debug and EH information.
20822089
for (const HandlerInfo &HI : Handlers) {
20832090
NamedRegionTimer T(HI.TimerName, HI.TimerDescription, HI.TimerGroupName,
@@ -3745,7 +3752,7 @@ GCMetadataPrinter *AsmPrinter::GetOrCreateGCPrinter(GCStrategy &S) {
37453752
report_fatal_error("no GCMetadataPrinter registered for GC: " + Twine(Name));
37463753
}
37473754

3748-
void AsmPrinter::emitStackMaps(StackMaps &SM) {
3755+
void AsmPrinter::emitStackMaps() {
37493756
GCModuleInfo *MI = getAnalysisIfAvailable<GCModuleInfo>();
37503757
assert(MI && "AsmPrinter didn't require GCModuleInfo?");
37513758
bool NeedsDefault = false;

llvm/lib/MC/MCMachOStreamer.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -173,9 +173,7 @@ void MCMachOStreamer::changeSection(MCSection *Section,
173173
if (SegName == "__DWARF")
174174
CreatedADWARFSection = true;
175175
else if (Created && DWARFMustBeAtTheEnd && !canGoAfterDWARF(MSec))
176-
assert((!CreatedADWARFSection ||
177-
Section == getContext().getObjectFileInfo()->getStackMapSection())
178-
&& "Creating regular section after DWARF");
176+
assert(!CreatedADWARFSection && "Creating regular section after DWARF");
179177

180178
// Output a linker-local symbol so we don't need section-relative local
181179
// relocations. The linker hates us when we do that.

llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -70,15 +70,14 @@ namespace {
7070

7171
class AArch64AsmPrinter : public AsmPrinter {
7272
AArch64MCInstLower MCInstLowering;
73-
StackMaps SM;
7473
FaultMaps FM;
7574
const AArch64Subtarget *STI;
7675
bool ShouldEmitWeakSwiftAsyncExtendedFramePointerFlags = false;
7776

7877
public:
7978
AArch64AsmPrinter(TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer)
8079
: AsmPrinter(TM, std::move(Streamer)), MCInstLowering(OutContext, *this),
81-
SM(*this), FM(*this) {}
80+
FM(*this) {}
8281

8382
StringRef getPassName() const override { return "AArch64 Assembly Printer"; }
8483

@@ -685,9 +684,8 @@ void AArch64AsmPrinter::emitEndOfAsmFile(Module &M) {
685684
// generates code that does this, it is always safe to set.
686685
OutStreamer->emitAssemblerFlag(MCAF_SubsectionsViaSymbols);
687686
}
688-
687+
689688
// Emit stack and fault map information.
690-
emitStackMaps(SM);
691689
FM.serializeToFaultMapSection();
692690

693691
}

llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -140,12 +140,11 @@ class PPCAsmPrinter : public AsmPrinter {
140140
MCSymbol *>
141141
TOC;
142142
const PPCSubtarget *Subtarget = nullptr;
143-
StackMaps SM;
144143

145144
public:
146145
explicit PPCAsmPrinter(TargetMachine &TM,
147146
std::unique_ptr<MCStreamer> Streamer)
148-
: AsmPrinter(TM, std::move(Streamer)), SM(*this) {}
147+
: AsmPrinter(TM, std::move(Streamer)) {}
149148

150149
StringRef getPassName() const override { return "PowerPC Assembly Printer"; }
151150

@@ -172,8 +171,6 @@ class PPCAsmPrinter : public AsmPrinter {
172171
bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
173172
const char *ExtraCode, raw_ostream &O) override;
174173

175-
void emitEndOfAsmFile(Module &M) override;
176-
177174
void LowerSTACKMAP(StackMaps &SM, const MachineInstr &MI);
178175
void LowerPATCHPOINT(StackMaps &SM, const MachineInstr &MI);
179176
void EmitTlsCall(const MachineInstr *MI, MCSymbolRefExpr::VariantKind VK);
@@ -427,10 +424,6 @@ PPCAsmPrinter::lookUpOrCreateTOCEntry(const MCSymbol *Sym,
427424
return TOCEntry;
428425
}
429426

430-
void PPCAsmPrinter::emitEndOfAsmFile(Module &M) {
431-
emitStackMaps(SM);
432-
}
433-
434427
void PPCAsmPrinter::LowerSTACKMAP(StackMaps &SM, const MachineInstr &MI) {
435428
unsigned NumNOPBytes = MI.getOperand(1).getImm();
436429

llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -817,10 +817,6 @@ bool SystemZAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
817817
return false;
818818
}
819819

820-
void SystemZAsmPrinter::emitEndOfAsmFile(Module &M) {
821-
emitStackMaps(SM);
822-
}
823-
824820
void SystemZAsmPrinter::emitFunctionBodyEnd() {
825821
if (TM.getTargetTriple().isOSzOS()) {
826822
// Emit symbol for the end of function if the z/OS target streamer

llvm/lib/Target/SystemZ/SystemZAsmPrinter.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ class raw_ostream;
2525

2626
class LLVM_LIBRARY_VISIBILITY SystemZAsmPrinter : public AsmPrinter {
2727
private:
28-
StackMaps SM;
2928
MCSymbol *CurrentFnPPA1Sym; // PPA1 Symbol.
3029
MCSymbol *CurrentFnEPMarkerSym; // Entry Point Marker.
3130

@@ -51,14 +50,13 @@ class LLVM_LIBRARY_VISIBILITY SystemZAsmPrinter : public AsmPrinter {
5150

5251
public:
5352
SystemZAsmPrinter(TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer)
54-
: AsmPrinter(TM, std::move(Streamer)), SM(*this),
55-
CurrentFnPPA1Sym(nullptr), CurrentFnEPMarkerSym(nullptr) {}
53+
: AsmPrinter(TM, std::move(Streamer)), CurrentFnPPA1Sym(nullptr),
54+
CurrentFnEPMarkerSym(nullptr) {}
5655

5756
// Override AsmPrinter.
5857
StringRef getPassName() const override { return "SystemZ Assembly Printer"; }
5958
void emitInstruction(const MachineInstr *MI) override;
6059
void emitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) override;
61-
void emitEndOfAsmFile(Module &M) override;
6260
bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
6361
const char *ExtraCode, raw_ostream &OS) override;
6462
bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,

llvm/lib/Target/X86/X86AsmPrinter.cpp

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ using namespace llvm;
4949

5050
X86AsmPrinter::X86AsmPrinter(TargetMachine &TM,
5151
std::unique_ptr<MCStreamer> Streamer)
52-
: AsmPrinter(TM, std::move(Streamer)), SM(*this), FM(*this) {}
52+
: AsmPrinter(TM, std::move(Streamer)), FM(*this) {}
5353

5454
//===----------------------------------------------------------------------===//
5555
// Primitive Helper Functions.
@@ -889,8 +889,7 @@ void X86AsmPrinter::emitEndOfAsmFile(Module &M) {
889889
// global table for symbol lookup.
890890
emitNonLazyStubs(MMI, *OutStreamer);
891891

892-
// Emit stack and fault map information.
893-
emitStackMaps(SM);
892+
// Emit fault map information.
894893
FM.serializeToFaultMapSection();
895894

896895
// This flag tells the linker that no global symbols contain code that fall
@@ -920,9 +919,7 @@ void X86AsmPrinter::emitEndOfAsmFile(Module &M) {
920919
OutStreamer->emitSymbolAttribute(S, MCSA_Global);
921920
return;
922921
}
923-
emitStackMaps(SM);
924922
} else if (TT.isOSBinFormatELF()) {
925-
emitStackMaps(SM);
926923
FM.serializeToFaultMapSection();
927924
}
928925

llvm/lib/Target/X86/X86AsmPrinter.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ class TargetMachine;
2626

2727
class LLVM_LIBRARY_VISIBILITY X86AsmPrinter : public AsmPrinter {
2828
const X86Subtarget *Subtarget = nullptr;
29-
StackMaps SM;
3029
FaultMaps FM;
3130
std::unique_ptr<MCCodeEmitter> CodeEmitter;
3231
bool EmitFPOData = false;
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
; RUN: llc -verify-machineinstrs < %s | FileCheck %s
2+
3+
; Used to crash with assertions when emitting object files.
4+
; RUN: llc -filetype=obj %s -o /dev/null
5+
6+
; Check stack map section is emitted before debug info.
7+
; CHECK: .section __LLVM_STACKMAPS
8+
; CHECK: .section __DWARF
9+
10+
target triple = "x86_64-apple-macosx12.0"
11+
12+
declare void @func()
13+
14+
define ptr addrspace(1) @test1(ptr addrspace(1) %arg) gc "statepoint-example" {
15+
entry:
16+
%safepoint_token = call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 0, i32 0, ptr elementtype(void ()) @func, i32 0, i32 0, i32 0, i32 0) ["gc-live"(ptr addrspace(1) %arg)]
17+
%reloc1 = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %safepoint_token, i32 0, i32 0)
18+
ret ptr addrspace(1) %reloc1
19+
}
20+
21+
declare token @llvm.experimental.gc.statepoint.p0(i64, i32, ptr, i32, i32, ...)
22+
declare ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token, i32, i32)
23+
24+
!llvm.dbg.cu = !{!0}
25+
!llvm.module.flags = !{!2}
26+
!0 = distinct !DICompileUnit(language: DW_LANG_C89, producer: "clang", isOptimized: true, emissionKind: FullDebug, file: !1, enums: !{}, retainedTypes: !{})
27+
!1 = !DIFile(filename: "t.c", directory: "")
28+
!2 = !{i32 2, !"Debug Info Version", i32 3}

0 commit comments

Comments
 (0)