From a0f68874821e653f710631990d74a72d0d0dd5bc Mon Sep 17 00:00:00 2001 From: ZhouGuangyuan Date: Tue, 28 Jul 2026 00:50:37 +0800 Subject: [PATCH 1/8] llvm: preserve GoObj data metadata from IR --- llvm/include/llvm/BinaryFormat/GoObj.h | 4 ++ llvm/include/llvm/MC/MCContext.h | 39 +++++++++++ llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 66 +++++++++++++++++++ llvm/lib/MC/GoObjObjectWriter.cpp | 31 +++++++++ llvm/lib/MC/MCContext.cpp | 2 + .../CodeGen/X86/goobj-data-relocations.ll | 11 ++++ .../test/CodeGen/X86/goobj-keep-relocation.ll | 10 +++ 7 files changed, 163 insertions(+) create mode 100644 llvm/test/CodeGen/X86/goobj-data-relocations.ll create mode 100644 llvm/test/CodeGen/X86/goobj-keep-relocation.ll diff --git a/llvm/include/llvm/BinaryFormat/GoObj.h b/llvm/include/llvm/BinaryFormat/GoObj.h index c4901df392b57..c68296dea3703 100644 --- a/llvm/include/llvm/BinaryFormat/GoObj.h +++ b/llvm/include/llvm/BinaryFormat/GoObj.h @@ -206,6 +206,10 @@ enum RelocType : uint16_t { R_ARM64_LDST32 = 43, R_ARM64_LDST64 = 44, R_ARM64_LDST128 = 45, + + R_WEAK = 1u << 15, + R_WEAKADDR = R_WEAK | R_ADDR, + R_WEAKADDROFF = R_WEAK | R_ADDROFF, }; } // end namespace GoObj diff --git a/llvm/include/llvm/MC/MCContext.h b/llvm/include/llvm/MC/MCContext.h index 599124ff5d58e..cb24f88024570 100644 --- a/llvm/include/llvm/MC/MCContext.h +++ b/llvm/include/llvm/MC/MCContext.h @@ -105,6 +105,11 @@ class MCContext { int32_t Value; }; + struct GoObjRelocOverride { + uint32_t Offset; + uint16_t Type; + }; + private: Environment Env; @@ -175,6 +180,14 @@ class MCContext { /// Go object symbol flags keyed by MC symbol. DenseMap> GoObjSymbolFlags; + /// Go object data-relocation type overrides keyed by MC symbol. LLVM IR + /// constants describe an address but not Go's weak-address variants. + DenseMap> + GoObjRelocOverrides; + + /// Go object zero-width R_KEEP targets keyed by their source symbol. + DenseMap> GoObjKeepTargets; + /// Go object pcsp entries keyed by MC symbol. DenseMap> GoObjSymbolPCSPEntries; @@ -596,6 +609,32 @@ class MCContext { return It->second; } + void setGoObjRelocOverrides(const MCSymbol *Sym, + std::vector Overrides) { + GoObjRelocOverrides[Sym] = std::move(Overrides); + } + + const std::vector * + getGoObjRelocOverrides(const MCSymbol *Sym) const { + auto It = GoObjRelocOverrides.find(Sym); + if (It == GoObjRelocOverrides.end()) + return nullptr; + return &It->second; + } + + void setGoObjKeepTargets(const MCSymbol *Sym, + std::vector Targets) { + GoObjKeepTargets[Sym] = std::move(Targets); + } + + const std::vector * + getGoObjKeepTargets(const MCSymbol *Sym) const { + auto It = GoObjKeepTargets.find(Sym); + if (It == GoObjKeepTargets.end()) + return nullptr; + return &It->second; + } + void setGoObjSymbolPCSPEntries(const MCSymbol *Sym, std::vector Entries) { GoObjSymbolPCSPEntries[Sym] = std::move(Entries); diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index 7a5b10d71c815..60b41979ef0db 100644 --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -873,6 +873,55 @@ getGoObjSymbolFlagsMetadata(const GlobalObject *GO) { return std::make_pair(ReadFlag(0), ReadFlag(1)); } +static std::optional> +getGoObjRelocsMetadata(const GlobalObject *GO) { + const MDNode *MD = GO->getMetadata("goobj.relocs"); + if (!MD) + return std::nullopt; + + std::vector Result; + Result.reserve(MD->getNumOperands()); + for (const MDOperand &Operand : MD->operands()) { + const auto *Entry = dyn_cast(Operand); + if (!Entry || Entry->getNumOperands() != 2) + report_fatal_error("expected !goobj.relocs entries to have two operands"); + + const auto *Offset = + mdconst::dyn_extract(Entry->getOperand(0)); + const auto *Type = mdconst::dyn_extract(Entry->getOperand(1)); + if (!Offset || !Type || Offset->getValue().ugt(UINT32_MAX) || + Type->getValue().ugt(UINT16_MAX)) + report_fatal_error("expected !goobj.relocs entries to be i32 values"); + Result.push_back({static_cast(Offset->getZExtValue()), + static_cast(Type->getZExtValue())}); + } + + llvm::sort(Result, [](const auto &LHS, const auto &RHS) { + return LHS.Offset < RHS.Offset; + }); + for (size_t I = 1; I < Result.size(); ++I) + if (Result[I - 1].Offset == Result[I].Offset) + report_fatal_error("duplicate !goobj.relocs offset"); + return Result; +} + +static std::optional> +getGoObjKeepMetadata(const GlobalObject *GO) { + const MDNode *MD = GO->getMetadata("goobj.keep"); + if (!MD) + return std::nullopt; + + std::vector Result; + Result.reserve(MD->getNumOperands()); + for (const MDOperand &Operand : MD->operands()) { + const auto *Name = dyn_cast(Operand); + if (!Name || Name->getString().empty()) + report_fatal_error("expected !goobj.keep entries to be symbol names"); + Result.push_back(Name->getString().str()); + } + return Result; +} + /// EmitGlobalVariable - Emit the specified global variable to the .s file. void AsmPrinter::emitGlobalVariable(const GlobalVariable *GV) { bool IsEmuTLSVar = TM.useEmulatedTLS() && GV->isThreadLocal(); @@ -910,6 +959,23 @@ void AsmPrinter::emitGlobalVariable(const GlobalVariable *GV) { if (std::optional> Flags = getGoObjSymbolFlagsMetadata(GV)) OutContext.setGoObjSymbolFlags(GVSym, Flags->first, Flags->second); + if (std::optional> Relocs = + getGoObjRelocsMetadata(GV)) + OutContext.setGoObjRelocOverrides(GVSym, std::move(*Relocs)); + if (std::optional> Keep = + getGoObjKeepMetadata(GV)) { + std::vector Targets; + Targets.reserve(Keep->size()); + for (const std::string &Name : *Keep) { + const auto *Target = + dyn_cast_or_null(GV->getParent()->getNamedValue(Name)); + if (!Target) + report_fatal_error(Twine("!goobj.keep target is not an LLVM global: ") + + Name); + Targets.push_back(getSymbol(Target)); + } + OutContext.setGoObjKeepTargets(GVSym, std::move(Targets)); + } } // getOrCreateEmuTLSControlSym only creates the symbol with name and default diff --git a/llvm/lib/MC/GoObjObjectWriter.cpp b/llvm/lib/MC/GoObjObjectWriter.cpp index 01559fde3bedf..d48e801e8a6e8 100644 --- a/llvm/lib/MC/GoObjObjectWriter.cpp +++ b/llvm/lib/MC/GoObjObjectWriter.cpp @@ -840,12 +840,43 @@ uint64_t GoObjObjectWriter::writeObject() { else RelocType = GoObj::R_ADDROFF; } + if (Source.Symbol) { + if (const auto *Overrides = + Asm->getContext().getGoObjRelocOverrides(Source.Symbol)) { + auto It = std::lower_bound( + Overrides->begin(), Overrides->end(), + static_cast(LocalOffset), + [](const MCContext::GoObjRelocOverride &Override, uint32_t Offset) { + return Override.Offset < Offset; + }); + if (It != Overrides->end() && It->Offset == LocalOffset) + RelocType = It->Type; + } + } Source.Relocations.push_back({static_cast(LocalOffset), Reloc.Size, RelocType, Addend, TargetSymRef.PkgIdx, TargetSymRef.SymIdx}); } + // R_KEEP has no bytes or MC fixup. It is a Go linker reachability edge + // carried separately from normal LLVM relocations by !goobj.keep. + for (GoObjSymbol &Source : Symbols) { + if (!Source.Symbol) + continue; + const auto *Targets = Asm->getContext().getGoObjKeepTargets(Source.Symbol); + if (!Targets) + continue; + for (const MCSymbol *Target : *Targets) { + GoObjRelocationEntry Reloc; + Reloc.Symbol = Target; + int64_t Addend = 0; + GoObjSymRef TargetSymRef = GetTargetSymRef(Reloc, Addend); + Source.Relocations.push_back({0, 0, GoObj::R_KEEP, Addend, + TargetSymRef.PkgIdx, TargetSymRef.SymIdx}); + } + } + for (GoObjSymbol &Symbol : Symbols) { llvm::stable_sort(Symbol.Relocations, [](const GoObjSymbol::Relocation &LHS, diff --git a/llvm/lib/MC/MCContext.cpp b/llvm/lib/MC/MCContext.cpp index 180d3ed43a893..e9d5e1173da36 100644 --- a/llvm/lib/MC/MCContext.cpp +++ b/llvm/lib/MC/MCContext.cpp @@ -170,6 +170,8 @@ void MCContext::reset() { GoObjSymbolStackSizes.clear(); GoObjSymbolArgSizes.clear(); GoObjSymbolFlags.clear(); + GoObjRelocOverrides.clear(); + GoObjKeepTargets.clear(); GoObjSymbolPCSPEntries.clear(); Symbols.clear(); Allocator.Reset(); diff --git a/llvm/test/CodeGen/X86/goobj-data-relocations.ll b/llvm/test/CodeGen/X86/goobj-data-relocations.ll new file mode 100644 index 0000000000000..8018424aca93e --- /dev/null +++ b/llvm/test/CodeGen/X86/goobj-data-relocations.ll @@ -0,0 +1,11 @@ +; RUN: llc -mtriple=x86_64-unknown-linux-goobj -filetype=obj < %s -o %t.o +; RUN: %python %S/../../MC/GoObj/Inputs/dump-goobj.py %t.o | FileCheck %s + +@target = constant i8 0, section ".rodata", align 1 +@weak_offset = constant <{ i32 }> <{ i32 ptrtoint (ptr @target to i32) }>, section ".rodata", align 4, !goobj.relocs !0 + +!0 = !{!1} +!1 = !{i32 0, i32 32773} + +; CHECK: symdef {{[0-9]+}}: weak_offset abi=0 type=3 size=4 +; CHECK: reloc {{[0-9]+}}.{{[0-9]+}}: off=0 size=4 type=32773 add=0 target=target diff --git a/llvm/test/CodeGen/X86/goobj-keep-relocation.ll b/llvm/test/CodeGen/X86/goobj-keep-relocation.ll new file mode 100644 index 0000000000000..bc797e49cd253 --- /dev/null +++ b/llvm/test/CodeGen/X86/goobj-keep-relocation.ll @@ -0,0 +1,10 @@ +; RUN: llc -mtriple=x86_64-unknown-linux-goobj -filetype=obj < %s -o %t.o +; RUN: %python %S/../../MC/GoObj/Inputs/dump-goobj.py %t.o | FileCheck %s + +@target = constant i8 0, section ".rodata", align 1 +@source = constant i8 0, section ".rodata", align 1, !goobj.keep !0 + +!0 = !{!"target"} + +; CHECK: symdef {{[0-9]+}}: source abi=0 type=3 size=1 +; CHECK: reloc {{[0-9]+}}.{{[0-9]+}}: off=0 size=0 type=27 add=0 target=target From 2194af4408dab07b14ade06b84316a105599fe2f Mon Sep 17 00:00:00 2001 From: ZhouGuangyuan Date: Tue, 28 Jul 2026 01:21:09 +0800 Subject: [PATCH 2/8] llvm: preserve GoObj interface metadata and data alignment --- llvm/include/llvm/MC/MCContext.h | 38 ++++++++++++++ llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 52 +++++++++++++++++++ llvm/lib/MC/GoObjObjectWriter.cpp | 28 ++++++++-- llvm/lib/MC/MCContext.cpp | 2 + .../AArch64/goobj-data-section-symbol.ll | 25 +++++++++ .../CodeGen/X86/goobj-marker-relocations.ll | 16 ++++++ llvm/test/MC/GoObj/Inputs/dump-goobj.py | 3 +- 7 files changed, 160 insertions(+), 4 deletions(-) create mode 100644 llvm/test/CodeGen/AArch64/goobj-data-section-symbol.ll create mode 100644 llvm/test/CodeGen/X86/goobj-marker-relocations.ll diff --git a/llvm/include/llvm/MC/MCContext.h b/llvm/include/llvm/MC/MCContext.h index cb24f88024570..892d4b7d3149a 100644 --- a/llvm/include/llvm/MC/MCContext.h +++ b/llvm/include/llvm/MC/MCContext.h @@ -110,6 +110,12 @@ class MCContext { uint16_t Type; }; + struct GoObjMarkerReloc { + const MCSymbol *Target = nullptr; + uint16_t Type = 0; + int64_t Addend = 0; + }; + private: Environment Env; @@ -188,6 +194,13 @@ class MCContext { /// Go object zero-width R_KEEP targets keyed by their source symbol. DenseMap> GoObjKeepTargets; + /// Go object zero-width linker marker relocations keyed by source function. + DenseMap> + GoObjMarkerRelocs; + + /// Explicit LLVM global alignments for Go object data symbols. + DenseMap GoObjSymbolAlignments; + /// Go object pcsp entries keyed by MC symbol. DenseMap> GoObjSymbolPCSPEntries; @@ -635,6 +648,31 @@ class MCContext { return &It->second; } + void setGoObjMarkerRelocs(const MCSymbol *Sym, + std::vector Relocs) { + GoObjMarkerRelocs[Sym] = std::move(Relocs); + } + + const std::vector * + getGoObjMarkerRelocs(const MCSymbol *Sym) const { + auto It = GoObjMarkerRelocs.find(Sym); + if (It == GoObjMarkerRelocs.end()) + return nullptr; + return &It->second; + } + + void setGoObjSymbolAlignment(const MCSymbol *Sym, uint32_t Alignment) { + GoObjSymbolAlignments[Sym] = Alignment; + } + + std::optional + getGoObjSymbolAlignment(const MCSymbol *Sym) const { + auto It = GoObjSymbolAlignments.find(Sym); + if (It == GoObjSymbolAlignments.end()) + return std::nullopt; + return It->second; + } + void setGoObjSymbolPCSPEntries(const MCSymbol *Sym, std::vector Entries) { GoObjSymbolPCSPEntries[Sym] = std::move(Entries); diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index 60b41979ef0db..8f0f34716e4fb 100644 --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -922,6 +922,39 @@ getGoObjKeepMetadata(const GlobalObject *GO) { return Result; } +struct GoObjMarkerRelocMetadata { + std::string Target; + uint16_t Type = 0; + int64_t Addend = 0; +}; + +static std::optional> +getGoObjMarkerRelocsMetadata(const GlobalObject *GO) { + const MDNode *MD = GO->getMetadata("goobj.marker_relocs"); + if (!MD) + return std::nullopt; + + std::vector Result; + Result.reserve(MD->getNumOperands()); + for (const MDOperand &Operand : MD->operands()) { + const auto *Entry = dyn_cast(Operand); + if (!Entry || Entry->getNumOperands() != 3) + report_fatal_error( + "expected !goobj.marker_relocs entries to have three operands"); + const auto *Type = mdconst::dyn_extract(Entry->getOperand(0)); + const auto *Addend = + mdconst::dyn_extract(Entry->getOperand(1)); + const auto *Target = dyn_cast(Entry->getOperand(2)); + if (!Type || Type->getValue().ugt(UINT16_MAX) || !Addend || !Target || + Target->getString().empty()) + report_fatal_error("invalid !goobj.marker_relocs entry"); + Result.push_back({Target->getString().str(), + static_cast(Type->getZExtValue()), + Addend->getSExtValue()}); + } + return Result; +} + /// EmitGlobalVariable - Emit the specified global variable to the .s file. void AsmPrinter::emitGlobalVariable(const GlobalVariable *GV) { bool IsEmuTLSVar = TM.useEmulatedTLS() && GV->isThreadLocal(); @@ -1013,6 +1046,9 @@ void AsmPrinter::emitGlobalVariable(const GlobalVariable *GV) { // with a specified alignment is a prompt way to break globals emitted to // sections and expected to be contiguous (e.g. ObjC metadata). const Align Alignment = getGVAlignment(GV, DL); + if (TM.getTargetTriple().isOSBinFormatGoObj()) + OutContext.setGoObjSymbolAlignment( + GVSym, static_cast(Alignment.value())); for (auto &Handler : Handlers) Handler->setSymbolSize(GVSym, Size); @@ -3413,6 +3449,22 @@ void AsmPrinter::SetupMachineFunction(MachineFunction &MF) { OutContext.setGoObjSymbolArgSize( CurrentFnSym, getGoObjArgSize(F, MF.getDataLayout(), TM.getTargetTriple())); + + if (std::optional> Markers = + getGoObjMarkerRelocsMetadata(&F)) { + std::vector Relocs; + Relocs.reserve(Markers->size()); + for (const GoObjMarkerRelocMetadata &Marker : *Markers) { + const auto *Target = dyn_cast_or_null( + F.getParent()->getNamedValue(Marker.Target)); + if (!Target) + report_fatal_error( + Twine("!goobj.marker_relocs target is not an LLVM global: ") + + Marker.Target); + Relocs.push_back({getSymbol(Target), Marker.Type, Marker.Addend}); + } + OutContext.setGoObjMarkerRelocs(CurrentFnSym, std::move(Relocs)); + } } CurrentFnSymForSize = CurrentFnSym; diff --git a/llvm/lib/MC/GoObjObjectWriter.cpp b/llvm/lib/MC/GoObjObjectWriter.cpp index d48e801e8a6e8..7273a5eb29510 100644 --- a/llvm/lib/MC/GoObjObjectWriter.cpp +++ b/llvm/lib/MC/GoObjObjectWriter.cpp @@ -146,7 +146,7 @@ void addDefinedSymbol(std::vector &Symbols, const MCSymbol *MCSym, uint64_t SectionEnd, GoObj::DefinedSymbolBlock DefinedBlock, StringRef Name, uint8_t Type, uint8_t Flag, uint8_t Flag2, uint16_t ABI, - uint64_t Size, ArrayRef Data) { + uint64_t Size, uint32_t Align, ArrayRef Data) { GoObjSymbol Sym; Sym.Name = Name.str(); Sym.Symbol = MCSym; @@ -159,6 +159,7 @@ void addDefinedSymbol(std::vector &Symbols, const MCSymbol *MCSym, Sym.Flag2 = Flag2; Sym.ABI = ABI; Sym.Size = Size; + Sym.Align = Align; Sym.Data.append(Data.begin(), Data.end()); Symbols.push_back(std::move(Sym)); } @@ -508,7 +509,8 @@ uint64_t GoObjObjectWriter::writeObject() { std::vector SectionSymbols; for (const MCSymbol &Symbol : Asm->symbols()) { if (Symbol.isTemporary() || !Symbol.isInSection() || - &Symbol.getSection() != &Section) + &Symbol.getSection() != &Section || + &Symbol == Section.getBeginSymbol()) continue; uint64_t Offset = Asm->getSymbolOffset(Symbol); if (Offset > SectionSize) @@ -537,16 +539,19 @@ uint64_t GoObjObjectWriter::writeObject() { : GoObj::SymABI0; uint8_t Flag = 0; uint8_t Flag2 = 0; + uint32_t Align = 0; if (MCSym) { if (std::optional> Flags = Asm->getContext().getGoObjSymbolFlags(MCSym)) { Flag = Flags->first; Flag2 = Flags->second; } + Align = + Asm->getContext().getGoObjSymbolAlignment(MCSym).value_or(0); } addDefinedSymbol(Symbols, MCSym, &Section, Begin, End, Config.DefaultDefinedSymbolBlock, Name, Type, Flag, - Flag2, ABI, Size, Data); + Flag2, ABI, Size, Align, Data); }; if (SectionSymbols.empty()) { @@ -877,6 +882,23 @@ uint64_t GoObjObjectWriter::writeObject() { } } + for (GoObjSymbol &Source : Symbols) { + if (!Source.Symbol) + continue; + const auto *Markers = + Asm->getContext().getGoObjMarkerRelocs(Source.Symbol); + if (!Markers) + continue; + for (const MCContext::GoObjMarkerReloc &Marker : *Markers) { + GoObjRelocationEntry Reloc; + Reloc.Symbol = Marker.Target; + int64_t Addend = Marker.Addend; + GoObjSymRef TargetSymRef = GetTargetSymRef(Reloc, Addend); + Source.Relocations.push_back( + {0, 0, Marker.Type, Addend, TargetSymRef.PkgIdx, TargetSymRef.SymIdx}); + } + } + for (GoObjSymbol &Symbol : Symbols) { llvm::stable_sort(Symbol.Relocations, [](const GoObjSymbol::Relocation &LHS, diff --git a/llvm/lib/MC/MCContext.cpp b/llvm/lib/MC/MCContext.cpp index e9d5e1173da36..a61b3e379e5d1 100644 --- a/llvm/lib/MC/MCContext.cpp +++ b/llvm/lib/MC/MCContext.cpp @@ -172,6 +172,8 @@ void MCContext::reset() { GoObjSymbolFlags.clear(); GoObjRelocOverrides.clear(); GoObjKeepTargets.clear(); + GoObjMarkerRelocs.clear(); + GoObjSymbolAlignments.clear(); GoObjSymbolPCSPEntries.clear(); Symbols.clear(); Allocator.Reset(); diff --git a/llvm/test/CodeGen/AArch64/goobj-data-section-symbol.ll b/llvm/test/CodeGen/AArch64/goobj-data-section-symbol.ll new file mode 100644 index 0000000000000..19447329e1668 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/goobj-data-section-symbol.ll @@ -0,0 +1,25 @@ +; RUN: llc -mtriple=aarch64-apple-darwin-goobj -filetype=obj < %s -o %t.o +; RUN: %python %S/../../MC/GoObj/Inputs/dump-goobj.py %t.o | FileCheck %s + +@inter = external global i8 +@type = external global i8 +@method = external global i8 + +@itab = constant <{ ptr, ptr, i32, [4 x i8], i64 }> <{ + ptr @inter, + ptr @type, + i32 123, + [4 x i8] zeroinitializer, + i64 ptrtoint (ptr @method to i64) +}>, section ".rodata", align 8, !goobj.symbol.flags !0, !goobj.relocs !1 + +!0 = !{i32 1, i32 2} +!1 = !{!2, !3, !4} +!2 = !{i32 0, i32 1} +!3 = !{i32 8, i32 1} +!4 = !{i32 24, i32 32769} + +; CHECK: symdef {{[0-9]+}}: itab abi=0 type=3 size=32 align=8 +; CHECK: reloc {{[0-9]+}}.{{[0-9]+}}: off=0 size=8 type=1 add=0 target=inter +; CHECK: reloc {{[0-9]+}}.{{[0-9]+}}: off=8 size=8 type=1 add=0 target=type +; CHECK: reloc {{[0-9]+}}.{{[0-9]+}}: off=24 size=8 type=32769 add=0 target=method diff --git a/llvm/test/CodeGen/X86/goobj-marker-relocations.ll b/llvm/test/CodeGen/X86/goobj-marker-relocations.ll new file mode 100644 index 0000000000000..c211fca8f848b --- /dev/null +++ b/llvm/test/CodeGen/X86/goobj-marker-relocations.ll @@ -0,0 +1,16 @@ +; RUN: llc -mtriple=x86_64-unknown-linux-goobj -filetype=obj < %s -o %t.o +; RUN: %python %S/../../MC/GoObj/Inputs/dump-goobj.py %t.o | FileCheck %s + +@target = constant i8 0, section ".rodata", align 1 + +define goabiinternal void @source() !goobj.marker_relocs !0 { + ret void +} + +!0 = !{!1, !2} +!1 = !{i32 23, i64 0, !"target"} +!2 = !{i32 24, i64 96, !"target"} + +; CHECK: symdef {{[0-9]+}}: source abi=1 type=1 +; CHECK: reloc {{[0-9]+}}.{{[0-9]+}}: off=0 size=0 type=23 add=0 target=target +; CHECK: reloc {{[0-9]+}}.{{[0-9]+}}: off=0 size=0 type=24 add=96 target=target diff --git a/llvm/test/MC/GoObj/Inputs/dump-goobj.py b/llvm/test/MC/GoObj/Inputs/dump-goobj.py index ef8e958cedb5e..e2ed7d93b4c0d 100644 --- a/llvm/test/MC/GoObj/Inputs/dump-goobj.py +++ b/llvm/test/MC/GoObj/Inputs/dump-goobj.py @@ -57,6 +57,7 @@ def read_symbols(data, start, end): "abi": struct.unpack_from(" Date: Tue, 28 Jul 2026 01:34:33 +0800 Subject: [PATCH 3/8] llvm: preserve GoObj global size and Go type aux --- llvm/include/llvm/MC/MCContext.h | 28 +++++++++++++++ llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 25 +++++++++++++- llvm/lib/MC/GoObjObjectWriter.cpp | 34 ++++++++++++++++--- llvm/lib/MC/MCContext.cpp | 2 ++ .../AArch64/goobj-data-section-symbol.ll | 10 +++++- llvm/test/MC/GoObj/Inputs/dump-goobj.py | 1 + 6 files changed, 93 insertions(+), 7 deletions(-) diff --git a/llvm/include/llvm/MC/MCContext.h b/llvm/include/llvm/MC/MCContext.h index 892d4b7d3149a..fb0f77c1d93b5 100644 --- a/llvm/include/llvm/MC/MCContext.h +++ b/llvm/include/llvm/MC/MCContext.h @@ -201,6 +201,12 @@ class MCContext { /// Explicit LLVM global alignments for Go object data symbols. DenseMap GoObjSymbolAlignments; + /// Exact LLVM global sizes for Go object data symbols. + DenseMap GoObjSymbolSizes; + + /// Go type auxiliary targets for data symbols. + DenseMap GoObjGotypeTargets; + /// Go object pcsp entries keyed by MC symbol. DenseMap> GoObjSymbolPCSPEntries; @@ -673,6 +679,28 @@ class MCContext { return It->second; } + void setGoObjSymbolSize(const MCSymbol *Sym, uint64_t Size) { + GoObjSymbolSizes[Sym] = Size; + } + + std::optional getGoObjSymbolSize(const MCSymbol *Sym) const { + auto It = GoObjSymbolSizes.find(Sym); + if (It == GoObjSymbolSizes.end()) + return std::nullopt; + return It->second; + } + + void setGoObjGotypeTarget(const MCSymbol *Sym, const MCSymbol *Target) { + GoObjGotypeTargets[Sym] = Target; + } + + const MCSymbol *getGoObjGotypeTarget(const MCSymbol *Sym) const { + auto It = GoObjGotypeTargets.find(Sym); + if (It == GoObjGotypeTargets.end()) + return nullptr; + return It->second; + } + void setGoObjSymbolPCSPEntries(const MCSymbol *Sym, std::vector Entries) { GoObjSymbolPCSPEntries[Sym] = std::move(Entries); diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index 8f0f34716e4fb..5fb9a35ed0be7 100644 --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -922,6 +922,19 @@ getGoObjKeepMetadata(const GlobalObject *GO) { return Result; } +static std::optional +getGoObjGotypeMetadata(const GlobalObject *GO) { + const MDNode *MD = GO->getMetadata("goobj.gotype"); + if (!MD) + return std::nullopt; + if (MD->getNumOperands() != 1) + report_fatal_error("expected !goobj.gotype to have one operand"); + const auto *Name = dyn_cast(MD->getOperand(0)); + if (!Name || Name->getString().empty()) + report_fatal_error("expected !goobj.gotype operand to be a symbol name"); + return Name->getString().str(); +} + struct GoObjMarkerRelocMetadata { std::string Target; uint16_t Type = 0; @@ -1009,6 +1022,14 @@ void AsmPrinter::emitGlobalVariable(const GlobalVariable *GV) { } OutContext.setGoObjKeepTargets(GVSym, std::move(Targets)); } + if (std::optional Gotype = getGoObjGotypeMetadata(GV)) { + const auto *Target = dyn_cast_or_null( + GV->getParent()->getNamedValue(*Gotype)); + if (!Target) + report_fatal_error( + Twine("!goobj.gotype target is not an LLVM global: ") + *Gotype); + OutContext.setGoObjGotypeTarget(GVSym, getSymbol(Target)); + } } // getOrCreateEmuTLSControlSym only creates the symbol with name and default @@ -1046,9 +1067,11 @@ void AsmPrinter::emitGlobalVariable(const GlobalVariable *GV) { // with a specified alignment is a prompt way to break globals emitted to // sections and expected to be contiguous (e.g. ObjC metadata). const Align Alignment = getGVAlignment(GV, DL); - if (TM.getTargetTriple().isOSBinFormatGoObj()) + if (TM.getTargetTriple().isOSBinFormatGoObj()) { OutContext.setGoObjSymbolAlignment( GVSym, static_cast(Alignment.value())); + OutContext.setGoObjSymbolSize(GVSym, Size); + } for (auto &Handler : Handlers) Handler->setSymbolSize(GVSym, Size); diff --git a/llvm/lib/MC/GoObjObjectWriter.cpp b/llvm/lib/MC/GoObjObjectWriter.cpp index 7273a5eb29510..54f62a949ff4e 100644 --- a/llvm/lib/MC/GoObjObjectWriter.cpp +++ b/llvm/lib/MC/GoObjObjectWriter.cpp @@ -559,13 +559,24 @@ uint64_t GoObjObjectWriter::writeObject() { continue; } - if (SectionSymbols.front().Offset != 0) - AddSectionSymbol(nullptr, Section.getName(), 0, - SectionSymbols.front().Offset); - for (size_t I = 0, E = SectionSymbols.size(); I != E; ++I) { uint64_t Begin = SectionSymbols[I].Offset; - uint64_t End = I + 1 == E ? SectionSize : SectionSymbols[I + 1].Offset; + uint64_t End = SectionSize; + for (size_t J = I + 1; J != E; ++J) { + if (SectionSymbols[J].Offset > Begin) { + End = SectionSymbols[J].Offset; + break; + } + } + if (std::optional ExactSize = + Asm->getContext().getGoObjSymbolSize( + SectionSymbols[I].Symbol)) { + if (*ExactSize > SectionSize - Begin || + Begin + *ExactSize > End) + report_fatal_error( + "GoObj global size overlaps the next section symbol"); + End = Begin + *ExactSize; + } AddSectionSymbol(SectionSymbols[I].Symbol, SectionSymbols[I].Symbol->getName(), Begin, End); } @@ -899,6 +910,19 @@ uint64_t GoObjObjectWriter::writeObject() { } } + for (GoObjSymbol &Source : Symbols) { + if (!Source.Symbol) + continue; + const MCSymbol *Target = + Asm->getContext().getGoObjGotypeTarget(Source.Symbol); + if (!Target) + continue; + auto It = DefinedSymbolIndexes.find(Target); + if (It == DefinedSymbolIndexes.end()) + report_fatal_error("GoObj gotype target is not a defined symbol"); + Source.Auxiliaries.push_back({GoObj::AuxGotype, It->second}); + } + for (GoObjSymbol &Symbol : Symbols) { llvm::stable_sort(Symbol.Relocations, [](const GoObjSymbol::Relocation &LHS, diff --git a/llvm/lib/MC/MCContext.cpp b/llvm/lib/MC/MCContext.cpp index a61b3e379e5d1..926a64f5ff496 100644 --- a/llvm/lib/MC/MCContext.cpp +++ b/llvm/lib/MC/MCContext.cpp @@ -174,6 +174,8 @@ void MCContext::reset() { GoObjKeepTargets.clear(); GoObjMarkerRelocs.clear(); GoObjSymbolAlignments.clear(); + GoObjSymbolSizes.clear(); + GoObjGotypeTargets.clear(); GoObjSymbolPCSPEntries.clear(); Symbols.clear(); Allocator.Reset(); diff --git a/llvm/test/CodeGen/AArch64/goobj-data-section-symbol.ll b/llvm/test/CodeGen/AArch64/goobj-data-section-symbol.ll index 19447329e1668..0d9e7912549fb 100644 --- a/llvm/test/CodeGen/AArch64/goobj-data-section-symbol.ll +++ b/llvm/test/CodeGen/AArch64/goobj-data-section-symbol.ll @@ -5,6 +5,10 @@ @type = external global i8 @method = external global i8 +@gotype = constant i8 0, section ".rodata", align 1 +@cache0 = global <{ ptr, ptr, [8 x i8] }> zeroinitializer, section ".data", align 16, !goobj.gotype !5 +@cache1 = global <{ ptr, ptr, [8 x i8] }> zeroinitializer, section ".data", align 16, !goobj.gotype !5 + @itab = constant <{ ptr, ptr, i32, [4 x i8], i64 }> <{ ptr @inter, ptr @type, @@ -18,8 +22,12 @@ !2 = !{i32 0, i32 1} !3 = !{i32 8, i32 1} !4 = !{i32 24, i32 32769} +!5 = !{!"gotype"} -; CHECK: symdef {{[0-9]+}}: itab abi=0 type=3 size=32 align=8 +; CHECK-DAG: symdef {{[0-9]+}}: cache0 abi=0 type=7 size=24 align=16 +; CHECK-DAG: symdef {{[0-9]+}}: cache1 abi=0 type=7 size=24 align=16 +; CHECK-DAG: symdef {{[0-9]+}}: itab abi=0 type=3 size=32 align=8 ; CHECK: reloc {{[0-9]+}}.{{[0-9]+}}: off=0 size=8 type=1 add=0 target=inter ; CHECK: reloc {{[0-9]+}}.{{[0-9]+}}: off=8 size=8 type=1 add=0 target=type ; CHECK: reloc {{[0-9]+}}.{{[0-9]+}}: off=24 size=8 type=32769 add=0 target=method +; CHECK: aux {{[0-9]+}}.{{[0-9]+}}: type=gotype target=gotype diff --git a/llvm/test/MC/GoObj/Inputs/dump-goobj.py b/llvm/test/MC/GoObj/Inputs/dump-goobj.py index e2ed7d93b4c0d..6f71b8fa82768 100644 --- a/llvm/test/MC/GoObj/Inputs/dump-goobj.py +++ b/llvm/test/MC/GoObj/Inputs/dump-goobj.py @@ -33,6 +33,7 @@ AUX_SIZE = 9 AUX_TYPES = { + 0: "gotype", 1: "funcinfo", 2: "funcdata", 7: "pcsp", From 9870b00e89186219b56f30a1d966edf61efd0c18 Mon Sep 17 00:00:00 2001 From: ZhouGuangyuan Date: Tue, 28 Jul 2026 01:38:40 +0800 Subject: [PATCH 4/8] llvm: allow external Go type auxiliary targets --- llvm/lib/MC/GoObjObjectWriter.cpp | 40 +++++++++++++------ .../AArch64/goobj-data-section-symbol.ll | 5 ++- 2 files changed, 31 insertions(+), 14 deletions(-) diff --git a/llvm/lib/MC/GoObjObjectWriter.cpp b/llvm/lib/MC/GoObjObjectWriter.cpp index 54f62a949ff4e..d4cf8fe2cc0ef 100644 --- a/llvm/lib/MC/GoObjObjectWriter.cpp +++ b/llvm/lib/MC/GoObjObjectWriter.cpp @@ -44,6 +44,11 @@ int64_t MCGoObjObjectTargetWriter::getRelocAddend(const MCValue &Target, namespace { +struct GoObjSymRef { + uint32_t PkgIdx = GoObj::PkgIdxInvalid; + uint32_t SymIdx = 0; +}; + struct GoObjSymbol { struct Relocation { uint32_t Offset = 0; @@ -55,8 +60,14 @@ struct GoObjSymbol { }; struct Auxiliary { - uint8_t Type = 0; + Auxiliary(uint8_t Type, uint32_t TargetSymbolIndex) + : Type(Type), TargetSymbolIndex(TargetSymbolIndex) {} + Auxiliary(uint8_t Type, GoObjSymRef DirectTarget) + : Type(Type), DirectTarget(DirectTarget) {} + + uint8_t Type; uint32_t TargetSymbolIndex = 0; + std::optional DirectTarget; }; std::string Name; @@ -76,11 +87,6 @@ struct GoObjSymbol { std::vector Auxiliaries; }; -struct GoObjSymRef { - uint32_t PkgIdx = GoObj::PkgIdxInvalid; - uint32_t SymIdx = 0; -}; - struct GoObjPCTabEntry { uint64_t PC = 0; int32_t Value = 0; @@ -917,10 +923,13 @@ uint64_t GoObjObjectWriter::writeObject() { Asm->getContext().getGoObjGotypeTarget(Source.Symbol); if (!Target) continue; - auto It = DefinedSymbolIndexes.find(Target); - if (It == DefinedSymbolIndexes.end()) - report_fatal_error("GoObj gotype target is not a defined symbol"); - Source.Auxiliaries.push_back({GoObj::AuxGotype, It->second}); + GoObjRelocationEntry Reloc; + Reloc.Symbol = Target; + int64_t Addend = 0; + GoObjSymRef TargetSymRef = GetTargetSymRef(Reloc, Addend); + if (Addend != 0) + report_fatal_error("GoObj gotype auxiliary target has an addend"); + Source.Auxiliaries.emplace_back(GoObj::AuxGotype, TargetSymRef); } for (GoObjSymbol &Symbol : Symbols) { @@ -1052,9 +1061,14 @@ uint64_t GoObjObjectWriter::writeObject() { for (uint32_t Index : DefinedSymbolOrder) { const GoObjSymbol &Symbol = Symbols[Index]; for (const GoObjSymbol::Auxiliary &Aux : Symbol.Auxiliaries) { - if (Aux.TargetSymbolIndex >= DefinedSymRefs.size()) - report_fatal_error("GoObj auxiliary target symbol index is invalid"); - GoObjSymRef Ref = DefinedSymRefs[Aux.TargetSymbolIndex]; + GoObjSymRef Ref; + if (Aux.DirectTarget) { + Ref = *Aux.DirectTarget; + } else { + if (Aux.TargetSymbolIndex >= DefinedSymRefs.size()) + report_fatal_error("GoObj auxiliary target symbol index is invalid"); + Ref = DefinedSymRefs[Aux.TargetSymbolIndex]; + } W.write(Aux.Type); W.write(Ref.PkgIdx); W.write(Ref.SymIdx); diff --git a/llvm/test/CodeGen/AArch64/goobj-data-section-symbol.ll b/llvm/test/CodeGen/AArch64/goobj-data-section-symbol.ll index 0d9e7912549fb..ca4161df3d2a4 100644 --- a/llvm/test/CodeGen/AArch64/goobj-data-section-symbol.ll +++ b/llvm/test/CodeGen/AArch64/goobj-data-section-symbol.ll @@ -4,10 +4,11 @@ @inter = external global i8 @type = external global i8 @method = external global i8 +@external_gotype = external global i8 @gotype = constant i8 0, section ".rodata", align 1 @cache0 = global <{ ptr, ptr, [8 x i8] }> zeroinitializer, section ".data", align 16, !goobj.gotype !5 -@cache1 = global <{ ptr, ptr, [8 x i8] }> zeroinitializer, section ".data", align 16, !goobj.gotype !5 +@cache1 = global <{ ptr, ptr, [8 x i8] }> zeroinitializer, section ".data", align 16, !goobj.gotype !6 @itab = constant <{ ptr, ptr, i32, [4 x i8], i64 }> <{ ptr @inter, @@ -23,6 +24,7 @@ !3 = !{i32 8, i32 1} !4 = !{i32 24, i32 32769} !5 = !{!"gotype"} +!6 = !{!"external_gotype"} ; CHECK-DAG: symdef {{[0-9]+}}: cache0 abi=0 type=7 size=24 align=16 ; CHECK-DAG: symdef {{[0-9]+}}: cache1 abi=0 type=7 size=24 align=16 @@ -31,3 +33,4 @@ ; CHECK: reloc {{[0-9]+}}.{{[0-9]+}}: off=8 size=8 type=1 add=0 target=type ; CHECK: reloc {{[0-9]+}}.{{[0-9]+}}: off=24 size=8 type=32769 add=0 target=method ; CHECK: aux {{[0-9]+}}.{{[0-9]+}}: type=gotype target=gotype +; CHECK: aux {{[0-9]+}}.{{[0-9]+}}: type=gotype target=external_gotype From b0f2c7560f8ba6ca65ceddba8449c34853226617 Mon Sep 17 00:00:00 2001 From: ZhouGuangyuan Date: Tue, 28 Jul 2026 09:43:03 +0800 Subject: [PATCH 5/8] llvm: derive GoObj symbol flags from IR semantics --- llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 47 +++++++++++++------ .../AArch64/goobj-data-section-symbol.ll | 17 +++++-- llvm/test/MC/GoObj/Inputs/dump-goobj.py | 5 +- 3 files changed, 49 insertions(+), 20 deletions(-) diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index 5fb9a35ed0be7..5de043bcb134a 100644 --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -855,22 +855,41 @@ MCSymbol *AsmPrinter::getSymbolPreferLocal(const GlobalValue &GV) const { } static std::optional> -getGoObjSymbolFlagsMetadata(const GlobalObject *GO) { - const MDNode *MD = GO->getMetadata("goobj.symbol.flags"); - if (!MD) - return std::nullopt; +getGoObjSymbolFlags(const GlobalVariable *GV) { + uint8_t Flag = 0; + uint8_t Flag2 = 0; - if (MD->getNumOperands() != 2) - report_fatal_error("expected !goobj.symbol.flags to have two operands"); + if (GV->hasLocalLinkage()) + Flag |= GoObj::SymFlagLocal; + else if (GV->isWeakForLinker()) + Flag |= GoObj::SymFlagDupok; - auto ReadFlag = [&](unsigned I) -> uint8_t { - const auto *CI = mdconst::dyn_extract(MD->getOperand(I)); - if (!CI || CI->getValue().ugt(UINT8_MAX)) - report_fatal_error("expected !goobj.symbol.flags operands to be i8"); - return static_cast(CI->getZExtValue()); - }; + if (const auto *ST = dyn_cast(GV->getValueType()); + ST && ST->hasName()) { + if (ST->getName().starts_with("go.descriptor.")) + Flag |= GoObj::SymFlagGoType; + if (ST->getName().starts_with("go.itab.")) + Flag2 |= GoObj::SymFlagItab; + } + + if (const MDNode *MD = GV->getMetadata("goobj.symbol.flags")) { + if (MD->getNumOperands() != 2) + report_fatal_error("expected !goobj.symbol.flags to have two operands"); - return std::make_pair(ReadFlag(0), ReadFlag(1)); + auto ReadFlag = [&](unsigned I) -> uint8_t { + const auto *CI = mdconst::dyn_extract(MD->getOperand(I)); + if (!CI || CI->getValue().ugt(UINT8_MAX)) + report_fatal_error("expected !goobj.symbol.flags operands to be i8"); + return static_cast(CI->getZExtValue()); + }; + + Flag |= ReadFlag(0); + Flag2 |= ReadFlag(1); + } + + if (Flag == 0 && Flag2 == 0) + return std::nullopt; + return std::make_pair(Flag, Flag2); } static std::optional> @@ -1003,7 +1022,7 @@ void AsmPrinter::emitGlobalVariable(const GlobalVariable *GV) { if (TM.getTargetTriple().isOSBinFormatGoObj()) { if (std::optional> Flags = - getGoObjSymbolFlagsMetadata(GV)) + getGoObjSymbolFlags(GV)) OutContext.setGoObjSymbolFlags(GVSym, Flags->first, Flags->second); if (std::optional> Relocs = getGoObjRelocsMetadata(GV)) diff --git a/llvm/test/CodeGen/AArch64/goobj-data-section-symbol.ll b/llvm/test/CodeGen/AArch64/goobj-data-section-symbol.ll index ca4161df3d2a4..54f23626c4fb5 100644 --- a/llvm/test/CodeGen/AArch64/goobj-data-section-symbol.ll +++ b/llvm/test/CodeGen/AArch64/goobj-data-section-symbol.ll @@ -6,19 +6,24 @@ @method = external global i8 @external_gotype = external global i8 +%go.descriptor.test = type <{ i8 }> +%go.itab.test = type <{ ptr, ptr, i32, [4 x i8], ptr }> + @gotype = constant i8 0, section ".rodata", align 1 @cache0 = global <{ ptr, ptr, [8 x i8] }> zeroinitializer, section ".data", align 16, !goobj.gotype !5 @cache1 = global <{ ptr, ptr, [8 x i8] }> zeroinitializer, section ".data", align 16, !goobj.gotype !6 +@local = internal constant i8 0, section ".rodata", align 1 +@descriptor = weak constant %go.descriptor.test <{ i8 0 }>, section ".rodata", align 1, !goobj.symbol.flags !0 -@itab = constant <{ ptr, ptr, i32, [4 x i8], i64 }> <{ +@itab = weak constant %go.itab.test <{ ptr @inter, ptr @type, i32 123, [4 x i8] zeroinitializer, - i64 ptrtoint (ptr @method to i64) -}>, section ".rodata", align 8, !goobj.symbol.flags !0, !goobj.relocs !1 + ptr @method +}>, section ".rodata", align 8, !goobj.relocs !1 -!0 = !{i32 1, i32 2} +!0 = !{i32 4, i32 1} !1 = !{!2, !3, !4} !2 = !{i32 0, i32 1} !3 = !{i32 8, i32 1} @@ -28,7 +33,9 @@ ; CHECK-DAG: symdef {{[0-9]+}}: cache0 abi=0 type=7 size=24 align=16 ; CHECK-DAG: symdef {{[0-9]+}}: cache1 abi=0 type=7 size=24 align=16 -; CHECK-DAG: symdef {{[0-9]+}}: itab abi=0 type=3 size=32 align=8 +; CHECK-DAG: symdef {{[0-9]+}}: local abi=0 type=3 size=1 align=1 flag=2 flag2=0 +; CHECK-DAG: symdef {{[0-9]+}}: descriptor abi=0 type=3 size=1 align=1 flag=69 flag2=1 +; CHECK-DAG: symdef {{[0-9]+}}: itab abi=0 type=3 size=32 align=8 flag=1 flag2=2 ; CHECK: reloc {{[0-9]+}}.{{[0-9]+}}: off=0 size=8 type=1 add=0 target=inter ; CHECK: reloc {{[0-9]+}}.{{[0-9]+}}: off=8 size=8 type=1 add=0 target=type ; CHECK: reloc {{[0-9]+}}.{{[0-9]+}}: off=24 size=8 type=32769 add=0 target=method diff --git a/llvm/test/MC/GoObj/Inputs/dump-goobj.py b/llvm/test/MC/GoObj/Inputs/dump-goobj.py index 6f71b8fa82768..44cad0694793c 100644 --- a/llvm/test/MC/GoObj/Inputs/dump-goobj.py +++ b/llvm/test/MC/GoObj/Inputs/dump-goobj.py @@ -57,6 +57,8 @@ def read_symbols(data, start, end): "name": string_at(data, offset), "abi": struct.unpack_from(" Date: Tue, 28 Jul 2026 09:49:01 +0800 Subject: [PATCH 6/8] llvm: infer strong GoObj data relocations from IR --- llvm/include/llvm/MC/MCContext.h | 16 ++++++++++++ llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 25 +++++++++++++++++++ llvm/lib/MC/GoObjObjectWriter.cpp | 6 +++++ llvm/lib/MC/MCContext.cpp | 1 + .../AArch64/goobj-data-section-symbol.ll | 7 ++---- .../CodeGen/X86/goobj-data-relocations.ll | 7 +++--- 6 files changed, 54 insertions(+), 8 deletions(-) diff --git a/llvm/include/llvm/MC/MCContext.h b/llvm/include/llvm/MC/MCContext.h index fb0f77c1d93b5..8490b77e833fd 100644 --- a/llvm/include/llvm/MC/MCContext.h +++ b/llvm/include/llvm/MC/MCContext.h @@ -191,6 +191,9 @@ class MCContext { DenseMap> GoObjRelocOverrides; + /// Go object data relocations whose inferred relocation kind is weak. + DenseMap> GoObjWeakRelocs; + /// Go object zero-width R_KEEP targets keyed by their source symbol. DenseMap> GoObjKeepTargets; @@ -641,6 +644,19 @@ class MCContext { return &It->second; } + void setGoObjWeakRelocs(const MCSymbol *Sym, + std::vector Offsets) { + GoObjWeakRelocs[Sym] = std::move(Offsets); + } + + const std::vector * + getGoObjWeakRelocs(const MCSymbol *Sym) const { + auto It = GoObjWeakRelocs.find(Sym); + if (It == GoObjWeakRelocs.end()) + return nullptr; + return &It->second; + } + void setGoObjKeepTargets(const MCSymbol *Sym, std::vector Targets) { GoObjKeepTargets[Sym] = std::move(Targets); diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index 5de043bcb134a..8025b4a59009c 100644 --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -924,6 +924,28 @@ getGoObjRelocsMetadata(const GlobalObject *GO) { return Result; } +static std::optional> +getGoObjWeakRelocsMetadata(const GlobalObject *GO) { + const MDNode *MD = GO->getMetadata("goobj.weak_relocs"); + if (!MD) + return std::nullopt; + + std::vector Result; + Result.reserve(MD->getNumOperands()); + for (const MDOperand &Operand : MD->operands()) { + const auto *Offset = mdconst::dyn_extract(Operand); + if (!Offset || Offset->getValue().ugt(UINT32_MAX)) + report_fatal_error( + "expected !goobj.weak_relocs entries to be i32 offsets"); + Result.push_back(static_cast(Offset->getZExtValue())); + } + + llvm::sort(Result); + if (std::adjacent_find(Result.begin(), Result.end()) != Result.end()) + report_fatal_error("duplicate !goobj.weak_relocs offset"); + return Result; +} + static std::optional> getGoObjKeepMetadata(const GlobalObject *GO) { const MDNode *MD = GO->getMetadata("goobj.keep"); @@ -1027,6 +1049,9 @@ void AsmPrinter::emitGlobalVariable(const GlobalVariable *GV) { if (std::optional> Relocs = getGoObjRelocsMetadata(GV)) OutContext.setGoObjRelocOverrides(GVSym, std::move(*Relocs)); + if (std::optional> WeakRelocs = + getGoObjWeakRelocsMetadata(GV)) + OutContext.setGoObjWeakRelocs(GVSym, std::move(*WeakRelocs)); if (std::optional> Keep = getGoObjKeepMetadata(GV)) { std::vector Targets; diff --git a/llvm/lib/MC/GoObjObjectWriter.cpp b/llvm/lib/MC/GoObjObjectWriter.cpp index d4cf8fe2cc0ef..f52a39d7bb931 100644 --- a/llvm/lib/MC/GoObjObjectWriter.cpp +++ b/llvm/lib/MC/GoObjObjectWriter.cpp @@ -874,6 +874,12 @@ uint64_t GoObjObjectWriter::writeObject() { if (It != Overrides->end() && It->Offset == LocalOffset) RelocType = It->Type; } + if (const auto *WeakRelocs = + Asm->getContext().getGoObjWeakRelocs(Source.Symbol); + WeakRelocs && + std::binary_search(WeakRelocs->begin(), WeakRelocs->end(), + static_cast(LocalOffset))) + RelocType |= GoObj::R_WEAK; } Source.Relocations.push_back({static_cast(LocalOffset), diff --git a/llvm/lib/MC/MCContext.cpp b/llvm/lib/MC/MCContext.cpp index 926a64f5ff496..01d07a772c963 100644 --- a/llvm/lib/MC/MCContext.cpp +++ b/llvm/lib/MC/MCContext.cpp @@ -171,6 +171,7 @@ void MCContext::reset() { GoObjSymbolArgSizes.clear(); GoObjSymbolFlags.clear(); GoObjRelocOverrides.clear(); + GoObjWeakRelocs.clear(); GoObjKeepTargets.clear(); GoObjMarkerRelocs.clear(); GoObjSymbolAlignments.clear(); diff --git a/llvm/test/CodeGen/AArch64/goobj-data-section-symbol.ll b/llvm/test/CodeGen/AArch64/goobj-data-section-symbol.ll index 54f23626c4fb5..ef4ee19efaa30 100644 --- a/llvm/test/CodeGen/AArch64/goobj-data-section-symbol.ll +++ b/llvm/test/CodeGen/AArch64/goobj-data-section-symbol.ll @@ -21,13 +21,10 @@ i32 123, [4 x i8] zeroinitializer, ptr @method -}>, section ".rodata", align 8, !goobj.relocs !1 +}>, section ".rodata", align 8, !goobj.weak_relocs !1 !0 = !{i32 4, i32 1} -!1 = !{!2, !3, !4} -!2 = !{i32 0, i32 1} -!3 = !{i32 8, i32 1} -!4 = !{i32 24, i32 32769} +!1 = !{i32 24} !5 = !{!"gotype"} !6 = !{!"external_gotype"} diff --git a/llvm/test/CodeGen/X86/goobj-data-relocations.ll b/llvm/test/CodeGen/X86/goobj-data-relocations.ll index 8018424aca93e..c5fba381d84f4 100644 --- a/llvm/test/CodeGen/X86/goobj-data-relocations.ll +++ b/llvm/test/CodeGen/X86/goobj-data-relocations.ll @@ -1,11 +1,12 @@ ; RUN: llc -mtriple=x86_64-unknown-linux-goobj -filetype=obj < %s -o %t.o ; RUN: %python %S/../../MC/GoObj/Inputs/dump-goobj.py %t.o | FileCheck %s +%go.descriptor.weak_offset = type <{ i32 }> + @target = constant i8 0, section ".rodata", align 1 -@weak_offset = constant <{ i32 }> <{ i32 ptrtoint (ptr @target to i32) }>, section ".rodata", align 4, !goobj.relocs !0 +@weak_offset = constant %go.descriptor.weak_offset <{ i32 ptrtoint (ptr @target to i32) }>, section ".rodata", align 4, !goobj.weak_relocs !0 -!0 = !{!1} -!1 = !{i32 0, i32 32773} +!0 = !{i32 0} ; CHECK: symdef {{[0-9]+}}: weak_offset abi=0 type=3 size=4 ; CHECK: reloc {{[0-9]+}}.{{[0-9]+}}: off=0 size=4 type=32773 add=0 target=target From 7e3ebd65070d9e1d5da039d71fc3f654dc74d0dc Mon Sep 17 00:00:00 2001 From: ZhouGuangyuan Date: Tue, 28 Jul 2026 10:03:37 +0800 Subject: [PATCH 7/8] llvm: use direct references for GoObj linker metadata --- llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 168 ++++++++---------- .../AArch64/goobj-data-section-symbol.ll | 12 +- .../test/CodeGen/X86/goobj-keep-relocation.ll | 8 +- .../CodeGen/X86/goobj-marker-relocations.ll | 11 +- 4 files changed, 94 insertions(+), 105 deletions(-) diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index 8025b4a59009c..deec928033658 100644 --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -21,6 +21,7 @@ #include "llvm/ADT/APFloat.h" #include "llvm/ADT/APInt.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/DenseSet.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallString.h" @@ -581,6 +582,8 @@ void AsmPrinter::getAnalysisUsage(AnalysisUsage &AU) const { AU.addUsedIfAvailable(); } +static void collectGoObjModuleMetadata(AsmPrinter &AP, const Module &M); + bool AsmPrinter::doInitialization(Module &M) { MMI = GetMMI(); HasSplitStack = false; @@ -596,6 +599,7 @@ bool AsmPrinter::doInitialization(Module &M) { TM.getObjFileLowering()->getModuleMetadata(M); if (Target.isOSBinFormatGoObj()) { + collectGoObjModuleMetadata(*this, M); for (const Function &F : M) { if (!F.isDeclaration()) continue; @@ -946,67 +950,79 @@ getGoObjWeakRelocsMetadata(const GlobalObject *GO) { return Result; } -static std::optional> -getGoObjKeepMetadata(const GlobalObject *GO) { - const MDNode *MD = GO->getMetadata("goobj.keep"); - if (!MD) - return std::nullopt; - - std::vector Result; - Result.reserve(MD->getNumOperands()); - for (const MDOperand &Operand : MD->operands()) { - const auto *Name = dyn_cast(Operand); - if (!Name || Name->getString().empty()) - report_fatal_error("expected !goobj.keep entries to be symbol names"); - Result.push_back(Name->getString().str()); +static const GlobalValue *getGoObjMetadataGlobal(const MDOperand &Operand, + StringRef MetadataName) { + const auto *CAM = dyn_cast_or_null(Operand.get()); + const auto *GV = CAM ? dyn_cast(CAM->getValue()) : nullptr; + if (!GV) + report_fatal_error(Twine("expected !") + MetadataName + + " symbol operands to be LLVM global references"); + return GV; +} + +static void collectGoObjModuleMetadata(AsmPrinter &AP, const Module &M) { + if (const NamedMDNode *Keep = M.getNamedMetadata("goobj.keep")) { + DenseMap> Targets; + for (const MDNode *Entry : Keep->operands()) { + if (Entry->getNumOperands() != 2) + report_fatal_error("expected !goobj.keep entries to have two operands"); + const GlobalValue *Source = + getGoObjMetadataGlobal(Entry->getOperand(0), "goobj.keep"); + const GlobalValue *Target = + getGoObjMetadataGlobal(Entry->getOperand(1), "goobj.keep"); + Targets[Source].push_back(AP.getSymbol(Target)); + } + for (auto &[Source, SourceTargets] : Targets) + AP.OutContext.setGoObjKeepTargets(AP.getSymbol(Source), + std::move(SourceTargets)); } - return Result; -} - -static std::optional -getGoObjGotypeMetadata(const GlobalObject *GO) { - const MDNode *MD = GO->getMetadata("goobj.gotype"); - if (!MD) - return std::nullopt; - if (MD->getNumOperands() != 1) - report_fatal_error("expected !goobj.gotype to have one operand"); - const auto *Name = dyn_cast(MD->getOperand(0)); - if (!Name || Name->getString().empty()) - report_fatal_error("expected !goobj.gotype operand to be a symbol name"); - return Name->getString().str(); -} - -struct GoObjMarkerRelocMetadata { - std::string Target; - uint16_t Type = 0; - int64_t Addend = 0; -}; -static std::optional> -getGoObjMarkerRelocsMetadata(const GlobalObject *GO) { - const MDNode *MD = GO->getMetadata("goobj.marker_relocs"); - if (!MD) - return std::nullopt; + if (const NamedMDNode *Gotypes = M.getNamedMetadata("goobj.gotype")) { + DenseSet Sources; + for (const MDNode *Entry : Gotypes->operands()) { + if (Entry->getNumOperands() != 2) + report_fatal_error( + "expected !goobj.gotype entries to have two operands"); + const GlobalValue *Source = + getGoObjMetadataGlobal(Entry->getOperand(0), "goobj.gotype"); + const GlobalValue *Target = + getGoObjMetadataGlobal(Entry->getOperand(1), "goobj.gotype"); + if (!Sources.insert(Source).second) + report_fatal_error("duplicate !goobj.gotype source"); + AP.OutContext.setGoObjGotypeTarget(AP.getSymbol(Source), + AP.getSymbol(Target)); + } + } - std::vector Result; - Result.reserve(MD->getNumOperands()); - for (const MDOperand &Operand : MD->operands()) { - const auto *Entry = dyn_cast(Operand); - if (!Entry || Entry->getNumOperands() != 3) - report_fatal_error( - "expected !goobj.marker_relocs entries to have three operands"); - const auto *Type = mdconst::dyn_extract(Entry->getOperand(0)); - const auto *Addend = - mdconst::dyn_extract(Entry->getOperand(1)); - const auto *Target = dyn_cast(Entry->getOperand(2)); - if (!Type || Type->getValue().ugt(UINT16_MAX) || !Addend || !Target || - Target->getString().empty()) - report_fatal_error("invalid !goobj.marker_relocs entry"); - Result.push_back({Target->getString().str(), - static_cast(Type->getZExtValue()), - Addend->getSExtValue()}); + if (const NamedMDNode *Markers = + M.getNamedMetadata("goobj.marker_relocs")) { + DenseMap> + Relocs; + for (const MDNode *Entry : Markers->operands()) { + if (Entry->getNumOperands() != 4) + report_fatal_error( + "expected !goobj.marker_relocs entries to have four operands"); + const GlobalValue *Source = + getGoObjMetadataGlobal(Entry->getOperand(0), + "goobj.marker_relocs"); + const GlobalValue *Target = + getGoObjMetadataGlobal(Entry->getOperand(1), + "goobj.marker_relocs"); + const auto *Type = + mdconst::dyn_extract(Entry->getOperand(2)); + const auto *Addend = + mdconst::dyn_extract(Entry->getOperand(3)); + if (!isa(Source) || !Type || + Type->getValue().ugt(UINT16_MAX) || !Addend) + report_fatal_error("invalid !goobj.marker_relocs entry"); + Relocs[Source].push_back( + {AP.getSymbol(Target), static_cast(Type->getZExtValue()), + Addend->getSExtValue()}); + } + for (auto &[Source, SourceRelocs] : Relocs) + AP.OutContext.setGoObjMarkerRelocs(AP.getSymbol(Source), + std::move(SourceRelocs)); } - return Result; } /// EmitGlobalVariable - Emit the specified global variable to the .s file. @@ -1052,28 +1068,6 @@ void AsmPrinter::emitGlobalVariable(const GlobalVariable *GV) { if (std::optional> WeakRelocs = getGoObjWeakRelocsMetadata(GV)) OutContext.setGoObjWeakRelocs(GVSym, std::move(*WeakRelocs)); - if (std::optional> Keep = - getGoObjKeepMetadata(GV)) { - std::vector Targets; - Targets.reserve(Keep->size()); - for (const std::string &Name : *Keep) { - const auto *Target = - dyn_cast_or_null(GV->getParent()->getNamedValue(Name)); - if (!Target) - report_fatal_error(Twine("!goobj.keep target is not an LLVM global: ") + - Name); - Targets.push_back(getSymbol(Target)); - } - OutContext.setGoObjKeepTargets(GVSym, std::move(Targets)); - } - if (std::optional Gotype = getGoObjGotypeMetadata(GV)) { - const auto *Target = dyn_cast_or_null( - GV->getParent()->getNamedValue(*Gotype)); - if (!Target) - report_fatal_error( - Twine("!goobj.gotype target is not an LLVM global: ") + *Gotype); - OutContext.setGoObjGotypeTarget(GVSym, getSymbol(Target)); - } } // getOrCreateEmuTLSControlSym only creates the symbol with name and default @@ -3516,22 +3510,6 @@ void AsmPrinter::SetupMachineFunction(MachineFunction &MF) { OutContext.setGoObjSymbolArgSize( CurrentFnSym, getGoObjArgSize(F, MF.getDataLayout(), TM.getTargetTriple())); - - if (std::optional> Markers = - getGoObjMarkerRelocsMetadata(&F)) { - std::vector Relocs; - Relocs.reserve(Markers->size()); - for (const GoObjMarkerRelocMetadata &Marker : *Markers) { - const auto *Target = dyn_cast_or_null( - F.getParent()->getNamedValue(Marker.Target)); - if (!Target) - report_fatal_error( - Twine("!goobj.marker_relocs target is not an LLVM global: ") + - Marker.Target); - Relocs.push_back({getSymbol(Target), Marker.Type, Marker.Addend}); - } - OutContext.setGoObjMarkerRelocs(CurrentFnSym, std::move(Relocs)); - } } CurrentFnSymForSize = CurrentFnSym; diff --git a/llvm/test/CodeGen/AArch64/goobj-data-section-symbol.ll b/llvm/test/CodeGen/AArch64/goobj-data-section-symbol.ll index ef4ee19efaa30..8cfa1f1e6aa72 100644 --- a/llvm/test/CodeGen/AArch64/goobj-data-section-symbol.ll +++ b/llvm/test/CodeGen/AArch64/goobj-data-section-symbol.ll @@ -1,5 +1,7 @@ ; RUN: llc -mtriple=aarch64-apple-darwin-goobj -filetype=obj < %s -o %t.o ; RUN: %python %S/../../MC/GoObj/Inputs/dump-goobj.py %t.o | FileCheck %s +; RUN: opt -passes='default' -S < %s | llc -mtriple=aarch64-apple-darwin-goobj -filetype=obj -o %t.opt.o +; RUN: %python %S/../../MC/GoObj/Inputs/dump-goobj.py %t.opt.o | FileCheck %s @inter = external global i8 @type = external global i8 @@ -10,10 +12,11 @@ %go.itab.test = type <{ ptr, ptr, i32, [4 x i8], ptr }> @gotype = constant i8 0, section ".rodata", align 1 -@cache0 = global <{ ptr, ptr, [8 x i8] }> zeroinitializer, section ".data", align 16, !goobj.gotype !5 -@cache1 = global <{ ptr, ptr, [8 x i8] }> zeroinitializer, section ".data", align 16, !goobj.gotype !6 +@cache0 = global <{ ptr, ptr, [8 x i8] }> zeroinitializer, section ".data", align 16 +@cache1 = global <{ ptr, ptr, [8 x i8] }> zeroinitializer, section ".data", align 16 @local = internal constant i8 0, section ".rodata", align 1 @descriptor = weak constant %go.descriptor.test <{ i8 0 }>, section ".rodata", align 1, !goobj.symbol.flags !0 +@llvm.compiler.used = appending global [5 x ptr] [ptr @cache0, ptr @cache1, ptr @gotype, ptr @external_gotype, ptr @local], section "llvm.metadata" @itab = weak constant %go.itab.test <{ ptr @inter, @@ -25,8 +28,9 @@ !0 = !{i32 4, i32 1} !1 = !{i32 24} -!5 = !{!"gotype"} -!6 = !{!"external_gotype"} +!goobj.gotype = !{!5, !6} +!5 = !{ptr @cache0, ptr @gotype} +!6 = !{ptr @cache1, ptr @external_gotype} ; CHECK-DAG: symdef {{[0-9]+}}: cache0 abi=0 type=7 size=24 align=16 ; CHECK-DAG: symdef {{[0-9]+}}: cache1 abi=0 type=7 size=24 align=16 diff --git a/llvm/test/CodeGen/X86/goobj-keep-relocation.ll b/llvm/test/CodeGen/X86/goobj-keep-relocation.ll index bc797e49cd253..0dcc4b4c60011 100644 --- a/llvm/test/CodeGen/X86/goobj-keep-relocation.ll +++ b/llvm/test/CodeGen/X86/goobj-keep-relocation.ll @@ -1,10 +1,14 @@ ; RUN: llc -mtriple=x86_64-unknown-linux-goobj -filetype=obj < %s -o %t.o ; RUN: %python %S/../../MC/GoObj/Inputs/dump-goobj.py %t.o | FileCheck %s +; RUN: opt -passes='default' -S < %s | llc -mtriple=x86_64-unknown-linux-goobj -filetype=obj -o %t.opt.o +; RUN: %python %S/../../MC/GoObj/Inputs/dump-goobj.py %t.opt.o | FileCheck %s @target = constant i8 0, section ".rodata", align 1 -@source = constant i8 0, section ".rodata", align 1, !goobj.keep !0 +@source = constant i8 0, section ".rodata", align 1 +@llvm.compiler.used = appending global [2 x ptr] [ptr @source, ptr @target], section "llvm.metadata" -!0 = !{!"target"} +!goobj.keep = !{!0} +!0 = !{ptr @source, ptr @target} ; CHECK: symdef {{[0-9]+}}: source abi=0 type=3 size=1 ; CHECK: reloc {{[0-9]+}}.{{[0-9]+}}: off=0 size=0 type=27 add=0 target=target diff --git a/llvm/test/CodeGen/X86/goobj-marker-relocations.ll b/llvm/test/CodeGen/X86/goobj-marker-relocations.ll index c211fca8f848b..7c1965e3e85db 100644 --- a/llvm/test/CodeGen/X86/goobj-marker-relocations.ll +++ b/llvm/test/CodeGen/X86/goobj-marker-relocations.ll @@ -1,15 +1,18 @@ ; RUN: llc -mtriple=x86_64-unknown-linux-goobj -filetype=obj < %s -o %t.o ; RUN: %python %S/../../MC/GoObj/Inputs/dump-goobj.py %t.o | FileCheck %s +; RUN: opt -passes='default' -S < %s | llc -mtriple=x86_64-unknown-linux-goobj -filetype=obj -o %t.opt.o +; RUN: %python %S/../../MC/GoObj/Inputs/dump-goobj.py %t.opt.o | FileCheck %s @target = constant i8 0, section ".rodata", align 1 +@llvm.compiler.used = appending global [2 x ptr] [ptr @source, ptr @target], section "llvm.metadata" -define goabiinternal void @source() !goobj.marker_relocs !0 { +define goabiinternal void @source() { ret void } -!0 = !{!1, !2} -!1 = !{i32 23, i64 0, !"target"} -!2 = !{i32 24, i64 96, !"target"} +!goobj.marker_relocs = !{!0, !1} +!0 = !{ptr @source, ptr @target, i32 23, i64 0} +!1 = !{ptr @source, ptr @target, i32 24, i64 96} ; CHECK: symdef {{[0-9]+}}: source abi=1 type=1 ; CHECK: reloc {{[0-9]+}}.{{[0-9]+}}: off=0 size=0 type=23 add=0 target=target From 276ebe76ee77f428ab5076b763bb685eb012d8e8 Mon Sep 17 00:00:00 2001 From: ZhouGuangyuan Date: Tue, 28 Jul 2026 10:58:27 +0800 Subject: [PATCH 8/8] llvm: update GoObj section symbol tests --- llvm/test/CodeGen/X86/goobj-filetype.ll | 46 ++++++++++----------- llvm/test/CodeGen/X86/goobj-function-abi.ll | 9 ++-- 2 files changed, 26 insertions(+), 29 deletions(-) diff --git a/llvm/test/CodeGen/X86/goobj-filetype.ll b/llvm/test/CodeGen/X86/goobj-filetype.ll index 854cece739ef8..0f0867f52eb7b 100644 --- a/llvm/test/CodeGen/X86/goobj-filetype.ll +++ b/llvm/test/CodeGen/X86/goobj-filetype.ll @@ -23,30 +23,28 @@ entry: ; LINKABLE: flags: 0 ; CHECK: file-count: 1 ; CHECK-NEXT: file 0: llvm-ir -; CHECK: symdef-count: 7 -; CHECK: symdef 0: .text abi=0 type=1 size=0 -; CHECK-NEXT: symdef 1: loadg abi=0 type=1 size=8 -; CHECK-NEXT: symdef 2: caller abi=0 type=1 size=8 -; CHECK-NEXT: symdef 3: g abi=0 type=7 size=0 -; CHECK-NEXT: symdef 4: .data abi=0 type=7 size=8 -; CHECK-NEXT: symdef 5: abi=65535 type=3 size=28 -; CHECK-NEXT: symdef 6: abi=65535 type=3 size=28 +; CHECK: symdef-count: 5 +; CHECK: symdef 0: loadg abi=0 type=1 size=8 +; CHECK-NEXT: symdef 1: caller abi=0 type=1 size=8 +; CHECK-NEXT: symdef 2: g abi=0 type=7 size=8 align=8 +; CHECK-NEXT: symdef 3: abi=65535 type=3 size=28 +; CHECK-NEXT: symdef 4: abi=65535 type=3 size=28 ; CHECK: nonpkgdef-count: 12 ; CHECK: nonpkgref-count: 1 ; CHECK-NEXT: nonpkgref 0: ext abi=0 type=0 size=0 -; CHECK: aux 1.0: type=funcinfo target= args=0 locals=0 -; CHECK-NEXT: aux 1.1: type=funcdata target= data=0100000000000000 -; CHECK-NEXT: aux 1.2: type=funcdata target= data=0100000000000000 -; CHECK-NEXT: aux 1.3: type=pcsp target= -; CHECK-NEXT: aux 1.4: type=pcfile target= -; CHECK-NEXT: aux 1.5: type=pcline target= -; CHECK-NEXT: aux 1.6: type=pcdata target= pc= -; CHECK-NEXT: reloc 1.0: off=3 size=4 type=14 add=0 target=g -; CHECK-NEXT: aux 2.7: type=funcinfo target= args=0 locals=8 -; CHECK-NEXT: aux 2.8: type=funcdata target= data=0100000000000000 -; CHECK-NEXT: aux 2.9: type=funcdata target= data=0100000000000000 -; CHECK-NEXT: aux 2.10: type=pcsp target= -; CHECK-NEXT: aux 2.11: type=pcfile target= -; CHECK-NEXT: aux 2.12: type=pcline target= -; CHECK-NEXT: aux 2.13: type=pcdata target= pc= -; CHECK-NEXT: reloc 2.1: off=2 size=4 type=7 add=0 target=ext +; CHECK: aux 0.0: type=funcinfo target= args=0 locals=0 +; CHECK-NEXT: aux 0.1: type=funcdata target= data=0100000000000000 +; CHECK-NEXT: aux 0.2: type=funcdata target= data=0100000000000000 +; CHECK-NEXT: aux 0.3: type=pcsp target= +; CHECK-NEXT: aux 0.4: type=pcfile target= +; CHECK-NEXT: aux 0.5: type=pcline target= +; CHECK-NEXT: aux 0.6: type=pcdata target= pc= +; CHECK-NEXT: reloc 0.0: off=3 size=4 type=14 add=0 target=g +; CHECK-NEXT: aux 1.7: type=funcinfo target= args=0 locals=8 +; CHECK-NEXT: aux 1.8: type=funcdata target= data=0100000000000000 +; CHECK-NEXT: aux 1.9: type=funcdata target= data=0100000000000000 +; CHECK-NEXT: aux 1.10: type=pcsp target= +; CHECK-NEXT: aux 1.11: type=pcfile target= +; CHECK-NEXT: aux 1.12: type=pcline target= +; CHECK-NEXT: aux 1.13: type=pcdata target= pc= +; CHECK-NEXT: reloc 1.1: off=2 size=4 type=7 add=0 target=ext diff --git a/llvm/test/CodeGen/X86/goobj-function-abi.ll b/llvm/test/CodeGen/X86/goobj-function-abi.ll index d6c1e9c6910ba..eb21c1d272029 100644 --- a/llvm/test/CodeGen/X86/goobj-function-abi.ll +++ b/llvm/test/CodeGen/X86/goobj-function-abi.ll @@ -11,10 +11,9 @@ entry: ret void } -; CHECK: symdef-count: 5 -; CHECK: symdef 0: .text abi=0 type=1 size=0 -; CHECK-NEXT: symdef 1: abi0_func abi=0 type=1 size={{[0-9]+}} -; CHECK-NEXT: symdef 2: internal_func abi=1 type=1 size={{[0-9]+}} +; CHECK: symdef-count: 4 +; CHECK: symdef 0: abi0_func abi=0 type=1 size={{[0-9]+}} +; CHECK-NEXT: symdef 1: internal_func abi=1 type=1 size={{[0-9]+}} +; CHECK-NEXT: symdef 2: abi=65535 type=3 size={{[0-9]+}} ; CHECK-NEXT: symdef 3: abi=65535 type=3 size={{[0-9]+}} -; CHECK-NEXT: symdef 4: abi=65535 type=3 size={{[0-9]+}} ; CHECK: nonpkgref {{[0-9]+}}: runtime.morestack_noctxt abi=0 type=0 size=0