Index: llvm/include/llvm/CodeGen/AsmPrinter.h =================================================================== --- llvm/include/llvm/CodeGen/AsmPrinter.h +++ llvm/include/llvm/CodeGen/AsmPrinter.h @@ -21,6 +21,7 @@ #include "llvm/CodeGen/AsmPrinterHandler.h" #include "llvm/CodeGen/DwarfStringPoolEntry.h" #include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/StackMaps.h" #include "llvm/IR/InlineAsm.h" #include "llvm/Support/ErrorHandling.h" #include @@ -68,7 +69,6 @@ class Module; class PseudoProbeHandler; class raw_ostream; -class StackMaps; class StringRef; class TargetLoweringObjectFile; class TargetMachine; @@ -199,6 +199,8 @@ std::vector Handlers; size_t NumUserHandlers = 0; + StackMaps SM; + private: /// If generated on the fly this own the instance. std::unique_ptr OwnedMDT; @@ -500,7 +502,7 @@ void emitGlobalGOTEquivs(); /// Emit the stack maps. - void emitStackMaps(StackMaps &SM); + void emitStackMaps(); //===------------------------------------------------------------------===// // Overridable Hooks Index: llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp =================================================================== --- llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -354,7 +354,8 @@ AsmPrinter::AsmPrinter(TargetMachine &tm, std::unique_ptr Streamer) : MachineFunctionPass(ID), TM(tm), MAI(tm.getMCAsmInfo()), - OutContext(Streamer->getContext()), OutStreamer(std::move(Streamer)) { + OutContext(Streamer->getContext()), OutStreamer(std::move(Streamer)), + SM(*this) { VerboseAsm = OutStreamer->isVerboseAsm(); } @@ -2068,6 +2069,12 @@ if (auto *TS = OutStreamer->getTargetStreamer()) TS->emitConstantPools(); + // Emit Stack maps before any debug info. Mach-O requires that no data or + // text sections come after debug info has been emitted. This matters for + // stack maps as they are arbitrary data, and may even have a custom format + // through user plugins. + emitStackMaps(); + // Finalize debug and EH information. for (const HandlerInfo &HI : Handlers) { NamedRegionTimer T(HI.TimerName, HI.TimerDescription, HI.TimerGroupName, @@ -3734,7 +3741,7 @@ report_fatal_error("no GCMetadataPrinter registered for GC: " + Twine(Name)); } -void AsmPrinter::emitStackMaps(StackMaps &SM) { +void AsmPrinter::emitStackMaps() { GCModuleInfo *MI = getAnalysisIfAvailable(); assert(MI && "AsmPrinter didn't require GCModuleInfo?"); bool NeedsDefault = false; Index: llvm/lib/MC/MCMachOStreamer.cpp =================================================================== --- llvm/lib/MC/MCMachOStreamer.cpp +++ llvm/lib/MC/MCMachOStreamer.cpp @@ -173,9 +173,7 @@ if (SegName == "__DWARF") CreatedADWARFSection = true; else if (Created && DWARFMustBeAtTheEnd && !canGoAfterDWARF(MSec)) - assert((!CreatedADWARFSection || - Section == getContext().getObjectFileInfo()->getStackMapSection()) - && "Creating regular section after DWARF"); + assert(!CreatedADWARFSection && "Creating regular section after DWARF"); // Output a linker-local symbol so we don't need section-relative local // relocations. The linker hates us when we do that. Index: llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp =================================================================== --- llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp +++ llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp @@ -70,7 +70,6 @@ class AArch64AsmPrinter : public AsmPrinter { AArch64MCInstLower MCInstLowering; - StackMaps SM; FaultMaps FM; const AArch64Subtarget *STI; bool ShouldEmitWeakSwiftAsyncExtendedFramePointerFlags = false; @@ -78,7 +77,7 @@ public: AArch64AsmPrinter(TargetMachine &TM, std::unique_ptr Streamer) : AsmPrinter(TM, std::move(Streamer)), MCInstLowering(OutContext, *this), - SM(*this), FM(*this) {} + FM(*this) {} StringRef getPassName() const override { return "AArch64 Assembly Printer"; } @@ -687,7 +686,6 @@ } // Emit stack and fault map information. - emitStackMaps(SM); FM.serializeToFaultMapSection(); } Index: llvm/lib/Target/X86/X86AsmPrinter.h =================================================================== --- llvm/lib/Target/X86/X86AsmPrinter.h +++ llvm/lib/Target/X86/X86AsmPrinter.h @@ -26,7 +26,6 @@ class LLVM_LIBRARY_VISIBILITY X86AsmPrinter : public AsmPrinter { const X86Subtarget *Subtarget = nullptr; - StackMaps SM; FaultMaps FM; std::unique_ptr CodeEmitter; bool EmitFPOData = false; Index: llvm/lib/Target/X86/X86AsmPrinter.cpp =================================================================== --- llvm/lib/Target/X86/X86AsmPrinter.cpp +++ llvm/lib/Target/X86/X86AsmPrinter.cpp @@ -49,7 +49,7 @@ X86AsmPrinter::X86AsmPrinter(TargetMachine &TM, std::unique_ptr Streamer) - : AsmPrinter(TM, std::move(Streamer)), SM(*this), FM(*this) {} + : AsmPrinter(TM, std::move(Streamer)), FM(*this) {} //===----------------------------------------------------------------------===// // Primitive Helper Functions. @@ -889,8 +889,7 @@ // global table for symbol lookup. emitNonLazyStubs(MMI, *OutStreamer); - // Emit stack and fault map information. - emitStackMaps(SM); + // Emit fault map information. FM.serializeToFaultMapSection(); // This flag tells the linker that no global symbols contain code that fall @@ -920,9 +919,7 @@ OutStreamer->emitSymbolAttribute(S, MCSA_Global); return; } - emitStackMaps(SM); } else if (TT.isOSBinFormatELF()) { - emitStackMaps(SM); FM.serializeToFaultMapSection(); } Index: llvm/test/CodeGen/X86/stackmap-macho.ll =================================================================== --- llvm/test/CodeGen/X86/stackmap-macho.ll +++ llvm/test/CodeGen/X86/stackmap-macho.ll @@ -0,0 +1,28 @@ +; RUN: llc -verify-machineinstrs < %s | FileCheck %s + +; Used to crash with assertions when emitting object files. +; RUN: llc -filetype=obj %s -o /dev/null + +; Check stack map section is emitted before debug info. +; CHECK: .section __LLVM_STACKMAPS +; CHECK: .section __DWARF + +target triple = "x86_64-apple-macosx12.0" + +declare void @func() + +define ptr addrspace(1) @test1(ptr addrspace(1) %arg) gc "statepoint-example" { +entry: + %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)] + %reloc1 = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %safepoint_token, i32 0, i32 0) + ret ptr addrspace(1) %reloc1 +} + +declare token @llvm.experimental.gc.statepoint.p0(i64, i32, ptr, i32, i32, ...) +declare ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token, i32, i32) + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!2} +!0 = distinct !DICompileUnit(language: DW_LANG_C89, producer: "clang", isOptimized: true, emissionKind: FullDebug, file: !1, enums: !{}, retainedTypes: !{}) +!1 = !DIFile(filename: "t.c", directory: "") +!2 = !{i32 2, !"Debug Info Version", i32 3} Index: llvm/test/CodeGen/X86/statepoint-stackmap-size.ll =================================================================== --- llvm/test/CodeGen/X86/statepoint-stackmap-size.ll +++ llvm/test/CodeGen/X86/statepoint-stackmap-size.ll @@ -3,7 +3,7 @@ ; Without removal of duplicate entries, the size is 62 lines ; CHECK: .section .llvm_stackmaps,{{.*$}} ; CHECK-NEXT:{{(.+$[[:space:]]){48}[[:space:]]}} -; CHECK-NOT:{{.|[[:space:]]}} +; CHECK-SAME: .section target triple = "x86_64-pc-linux-gnu"