diff --git a/llvm/include/llvm/BinaryFormat/GoObj.h b/llvm/include/llvm/BinaryFormat/GoObj.h index 8e3f749a07c9e..53e9ef470ba07 100644 --- a/llvm/include/llvm/BinaryFormat/GoObj.h +++ b/llvm/include/llvm/BinaryFormat/GoObj.h @@ -23,6 +23,19 @@ namespace GoObj { // Go function. GoObj serialization strips it and records ABI0 separately. inline constexpr char ABI0SymbolSuffix[] = ""; +// Compiler-generated references to predefined Go runtime symbols carry this +// prefix followed by their decimal GoObj builtin index and a closing '>'. The +// suffix keeps those declarations distinct from runtime package definitions in +// LLVM IR. GoObj serialization strips it and normally records PkgIdxBuiltin +// plus the encoded index instead. +inline constexpr char BuiltinSymbolSuffixPrefix[] = ". GoObj strips it and preserves +// name-based non-package reference classification. +inline constexpr char LinknameSymbolSuffix[] = ""; + // "GoNoSplt" encoded as the stable STACKMAP identifier for the function-level // entry argument pointer map. This record is metadata-only: it is present for // both split and nosplit functions and never denotes a callsite. diff --git a/llvm/include/llvm/CodeGen/CommandFlags.h b/llvm/include/llvm/CodeGen/CommandFlags.h index 591ecb3a9ac49..591e882d39bc6 100644 --- a/llvm/include/llvm/CodeGen/CommandFlags.h +++ b/llvm/include/llvm/CodeGen/CommandFlags.h @@ -47,6 +47,7 @@ struct GoObjConfig { std::vector Experiments; bool IsMain = false; bool IsShared = false; + bool IsStd = false; }; LLVM_ABI void setGoObjConfig(GoObjConfig Config); diff --git a/llvm/include/llvm/CodeGen/GoCallingConv.h b/llvm/include/llvm/CodeGen/GoCallingConv.h index 0e1fa62d30e7c..a94c652859816 100644 --- a/llvm/include/llvm/CodeGen/GoCallingConv.h +++ b/llvm/include/llvm/CodeGen/GoCallingConv.h @@ -20,6 +20,7 @@ #include "llvm/IR/Function.h" #include "llvm/Support/Alignment.h" #include +#include namespace llvm { @@ -123,6 +124,12 @@ bool isFloatingPiece(Type *Ty); void addGoObjABI0Callee(MachineInstrBuilder &MIB, MachineFunction &MF, StringRef SymbolName); +/// Resolve a compiler-provided Go builtin declaration by its logical linker +/// name and calling convention. The declaration name carries its GoObj builtin +/// index, so target late passes never need a duplicate builtin table. +std::string getGoObjBuiltinCalleeName(MachineFunction &MF, StringRef SymbolName, + CallingConv::ID CC); + } // namespace goabi } // namespace llvm diff --git a/llvm/include/llvm/MC/MCContext.h b/llvm/include/llvm/MC/MCContext.h index f9deff96daa40..26d0ff13a5b19 100644 --- a/llvm/include/llvm/MC/MCContext.h +++ b/llvm/include/llvm/MC/MCContext.h @@ -150,13 +150,7 @@ class MCContext { std::array Fingerprint = {}; }; - enum class GoObjSymbolRefKind : uint8_t { - Imported = 1, - Builtin = 2, - }; - - struct GoObjSymbolRef { - GoObjSymbolRefKind Kind = GoObjSymbolRefKind::Imported; + struct GoObjImportedSymbolRef { std::string PackagePrefix; uint32_t SymIdx = 0; uint8_t Flags2 = 0; @@ -290,8 +284,8 @@ class MCContext { /// Imported packages and their opaque linker fingerprints, in source order. std::vector GoObjImports; - /// Indexed imported or builtin references keyed by their MC symbol. - DenseMap GoObjSymbolRefs; + /// Indexed imported references keyed by their MC symbol. + DenseMap GoObjImportedSymbolRefs; /// Explicit LLVM global alignments for Go object data symbols. DenseMap GoObjSymbolAlignments; @@ -852,13 +846,15 @@ class MCContext { ArrayRef getGoObjImports() const { return GoObjImports; } - void setGoObjSymbolRef(const MCSymbol *Sym, GoObjSymbolRef Ref) { - GoObjSymbolRefs[Sym] = std::move(Ref); + void setGoObjImportedSymbolRef(const MCSymbol *Sym, + GoObjImportedSymbolRef Ref) { + GoObjImportedSymbolRefs[Sym] = std::move(Ref); } - const GoObjSymbolRef *getGoObjSymbolRef(const MCSymbol *Sym) const { - auto It = GoObjSymbolRefs.find(Sym); - if (It == GoObjSymbolRefs.end()) + const GoObjImportedSymbolRef * + getGoObjImportedSymbolRef(const MCSymbol *Sym) const { + auto It = GoObjImportedSymbolRefs.find(Sym); + if (It == GoObjImportedSymbolRefs.end()) return nullptr; return &It->second; } diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index 637367158b2fe..6ef7405644564 100644 --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -1153,10 +1153,15 @@ static void collectGoObjModuleMetadata(AsmPrinter &AP, const Module &M) { // The LLVM symbol name is the sole carrier of ABI0 object identity. Keep the // calling convention as an independent lowering contract and reject stale // metadata or mismatched names instead of trying to repair either one. - for (const GlobalObject &GO : M.global_objects()) + for (const GlobalObject &GO : M.global_objects()) { if (GO.getMetadata("goobj.symbol.name")) report_fatal_error( "!goobj.symbol.name is obsolete; encode ABI0 in the symbol name"); + if (GO.getMetadata("goobj.builtin")) + report_fatal_error( + "!goobj.builtin is obsolete; encode the builtin index in the symbol " + "name"); + } for (const Function &F : M) { if (F.isIntrinsic()) @@ -1201,44 +1206,34 @@ static void collectGoObjModuleMetadata(AsmPrinter &AP, const Module &M) { } // Only the optimized relocation stream decides which declarations become - // GoObj references. Attachments retain the package-local indices that LLVM - // symbol names and MC relocations cannot reconstruct. + // GoObj references. The attachment retains the package-local index that + // LLVM symbol names and MC relocations cannot reconstruct. Builtin identity + // is encoded directly in the declaration name instead. for (const GlobalObject &GO : M.global_objects()) { const MDNode *Imported = GO.getMetadata("goobj.import"); - const MDNode *Builtin = GO.getMetadata("goobj.builtin"); - if (!Imported && !Builtin) + if (!Imported) continue; - if (!GO.isDeclaration() || (Imported && Builtin)) + if (!GO.isDeclaration() || + GO.getName().contains(GoObj::BuiltinSymbolSuffixPrefix) || + GO.getName().contains(GoObj::LinknameSymbolSuffix)) report_fatal_error("invalid GoObj symbol reference attachment"); - MCContext::GoObjSymbolRef Ref; - if (Imported) { - if (Imported->getNumOperands() != 3) - report_fatal_error("expected !goobj.import to have three operands"); - StringRef Prefix = - getGoObjMetadataString(Imported->getOperand(0), "goobj.import"); - const auto *SymIdx = - mdconst::dyn_extract(Imported->getOperand(1)); - const auto *Flags2 = - mdconst::dyn_extract(Imported->getOperand(2)); - if (Prefix.empty() || !SymIdx || SymIdx->getValue().ugt(UINT32_MAX) || - !Flags2 || Flags2->getValue().ugt(UINT8_MAX)) - report_fatal_error("invalid !goobj.import attachment"); - Ref.Kind = MCContext::GoObjSymbolRefKind::Imported; - Ref.PackagePrefix = Prefix.str(); - Ref.SymIdx = static_cast(SymIdx->getZExtValue()); - Ref.Flags2 = static_cast(Flags2->getZExtValue()); - } else { - if (Builtin->getNumOperands() != 1) - report_fatal_error("expected !goobj.builtin to have one operand"); - const auto *SymIdx = - mdconst::dyn_extract(Builtin->getOperand(0)); - if (!SymIdx || SymIdx->getValue().ugt(UINT32_MAX)) - report_fatal_error("invalid !goobj.builtin attachment"); - Ref.Kind = MCContext::GoObjSymbolRefKind::Builtin; - Ref.SymIdx = static_cast(SymIdx->getZExtValue()); - } - AP.OutContext.setGoObjSymbolRef(AP.getSymbol(&GO), std::move(Ref)); + if (Imported->getNumOperands() != 3) + report_fatal_error("expected !goobj.import to have three operands"); + StringRef Prefix = + getGoObjMetadataString(Imported->getOperand(0), "goobj.import"); + const auto *SymIdx = + mdconst::dyn_extract(Imported->getOperand(1)); + const auto *Flags2 = + mdconst::dyn_extract(Imported->getOperand(2)); + if (Prefix.empty() || !SymIdx || SymIdx->getValue().ugt(UINT32_MAX) || + !Flags2 || Flags2->getValue().ugt(UINT8_MAX)) + report_fatal_error("invalid !goobj.import attachment"); + MCContext::GoObjImportedSymbolRef Ref; + Ref.PackagePrefix = Prefix.str(); + Ref.SymIdx = static_cast(SymIdx->getZExtValue()); + Ref.Flags2 = static_cast(Flags2->getZExtValue()); + AP.OutContext.setGoObjImportedSymbolRef(AP.getSymbol(&GO), std::move(Ref)); } if (const NamedMDNode *Keep = M.getNamedMetadata("goobj.keep")) { diff --git a/llvm/lib/CodeGen/CodeGenTargetMachineImpl.cpp b/llvm/lib/CodeGen/CodeGenTargetMachineImpl.cpp index dab0489df1f73..93e2593b77d95 100644 --- a/llvm/lib/CodeGen/CodeGenTargetMachineImpl.cpp +++ b/llvm/lib/CodeGen/CodeGenTargetMachineImpl.cpp @@ -250,6 +250,7 @@ CodeGenTargetMachineImpl::createMCStreamer(raw_pwrite_stream &Out, Config.Experiments = std::move(IRConfig->Experiments); Config.IsMain = IRConfig->IsMain; Config.IsShared = IRConfig->IsShared; + Config.IsStd = IRConfig->IsStd; } else { Config.PackagePath = GoObjPackagePath; if (!GoObjVersion.empty()) diff --git a/llvm/lib/CodeGen/GoCallingConv.cpp b/llvm/lib/CodeGen/GoCallingConv.cpp index 5b5dedf4b0b05..73491bbe2fa58 100644 --- a/llvm/lib/CodeGen/GoCallingConv.cpp +++ b/llvm/lib/CodeGen/GoCallingConv.cpp @@ -8,10 +8,12 @@ #include "llvm/CodeGen/GoCallingConv.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/CodeGen/CommandFlags.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/Instructions.h" +#include "llvm/IR/Module.h" #include "llvm/Support/ErrorHandling.h" #include #include @@ -20,11 +22,60 @@ using namespace llvm; namespace llvm::goabi { +std::string getGoObjBuiltinCalleeName(MachineFunction &MF, StringRef SymbolName, + CallingConv::ID CC) { + if (SymbolName.empty() || + (CC != CallingConv::GoABIInternal && CC != CallingConv::GoABI0)) + report_fatal_error("invalid logical Go builtin symbol"); + + const Module &M = *MF.getFunction().getParent(); + const Function *Match = nullptr; + for (const Function &F : M) { + StringRef Candidate = F.getName(); + bool IsABI0 = Candidate.consume_back(GoObj::ABI0SymbolSuffix); + if (IsABI0 != (CC == CallingConv::GoABI0) || + !Candidate.consume_front(SymbolName) || + !Candidate.consume_front(GoObj::BuiltinSymbolSuffixPrefix) || + !Candidate.consume_back(">") || Candidate.empty()) + continue; + uint32_t Index; + if (Candidate.getAsInteger(10, Index)) + continue; + if (F.getCallingConv() != CC) + report_fatal_error( + "Go builtin declaration has invalid calling convention"); + if (Match) + report_fatal_error("duplicate Go builtin declaration"); + Match = &F; + } + if (Match) + return Match->getName().str(); + + // Native Go disables builtin-index references for -linkshared. + if (std::optional Config = codegen::getGoObjConfig(); + Config && Config->IsShared) { + std::string StorageName = SymbolName.str(); + if (CC == CallingConv::GoABI0) + StorageName += GoObj::ABI0SymbolSuffix; + return StorageName; + } + + // Hand-written backend fixtures predate the compiler declaration contract. + // Production Go IR is self-describing and must fail closed if its late + // helper declaration is missing. + if (M.getNamedMetadata("goobj.config")) + report_fatal_error("missing Go builtin declaration for " + SymbolName); + + std::string StorageName = SymbolName.str(); + if (CC == CallingConv::GoABI0) + StorageName += GoObj::ABI0SymbolSuffix; + return StorageName; +} + void addGoObjABI0Callee(MachineInstrBuilder &MIB, MachineFunction &MF, StringRef SymbolName) { - if (SymbolName.empty() || SymbolName.ends_with(GoObj::ABI0SymbolSuffix)) - report_fatal_error("invalid logical Go ABI0 symbol name"); - std::string StorageName = (SymbolName + GoObj::ABI0SymbolSuffix).str(); + std::string StorageName = + getGoObjBuiltinCalleeName(MF, SymbolName, CallingConv::GoABI0); MIB.addExternalSymbol(MF.createExternalSymbolName(StorageName)); } diff --git a/llvm/lib/MC/GoObjObjectWriter.cpp b/llvm/lib/MC/GoObjObjectWriter.cpp index 63f03c66b78e1..3e341e671dff2 100644 --- a/llvm/lib/MC/GoObjObjectWriter.cpp +++ b/llvm/lib/MC/GoObjObjectWriter.cpp @@ -1520,20 +1520,53 @@ uint64_t GoObjObjectWriter::writeObject() { const uint64_t StartOffset = OS.tell(); StringRef ABI0Suffix = GoObj::ABI0SymbolSuffix; - auto HasABI0Suffix = [&](const MCSymbol *Sym) { - return Sym && Sym->getName().ends_with(ABI0Suffix); + StringRef BuiltinPrefix = GoObj::BuiltinSymbolSuffixPrefix; + StringRef LinknameSuffix = GoObj::LinknameSymbolSuffix; + struct GoObjSymbolIdentity { + StringRef Name; + std::optional BuiltinIndex; + bool IsLinknameRef = false; + bool IsABI0 = false; }; - auto GetSymbolName = [&](const MCSymbol *Sym) -> StringRef { + auto GetSymbolIdentity = [&](const MCSymbol *Sym) { + if (!Sym) + return GoObjSymbolIdentity{}; StringRef Name = Sym->getName(); - if (!HasABI0Suffix(Sym)) - return Name; - Name = Name.drop_back(ABI0Suffix.size()); - if (Name.empty() || Name.ends_with(ABI0Suffix)) + bool IsABI0 = Name.consume_back(ABI0Suffix); + if (IsABI0 && (Name.empty() || Name.ends_with(ABI0Suffix))) report_fatal_error("invalid Go ABI0 symbol name"); - return Name; + + bool IsLinknameRef = Name.consume_back(LinknameSuffix); + if (Name.contains(LinknameSuffix)) + report_fatal_error("invalid Go linkname symbol name"); + + std::optional BuiltinIndex; + size_t BuiltinBegin = Name.rfind(BuiltinPrefix); + if (BuiltinBegin != StringRef::npos) { + StringRef Base = Name.take_front(BuiltinBegin); + StringRef Index = Name.drop_front(BuiltinBegin + BuiltinPrefix.size()); + if (Base.empty() || Base.contains(BuiltinPrefix) || + !Index.consume_back(">") || Index.empty()) + report_fatal_error("invalid Go builtin symbol name"); + uint32_t ParsedIndex = 0; + if (Index.getAsInteger(10, ParsedIndex)) + report_fatal_error("invalid Go builtin symbol index"); + Name = Base; + BuiltinIndex = ParsedIndex; + } + if (BuiltinIndex && IsLinknameRef) + report_fatal_error("conflicting Go builtin and linkname symbol identity"); + if ((BuiltinIndex || IsLinknameRef) && + (Name.empty() || Name.contains(BuiltinPrefix) || + Name.contains(LinknameSuffix))) + report_fatal_error("invalid Go builtin symbol name"); + return GoObjSymbolIdentity{Name, BuiltinIndex, IsLinknameRef, IsABI0}; + }; + auto GetSymbolName = [&](const MCSymbol *Sym) -> StringRef { + return GetSymbolIdentity(Sym).Name; }; auto GetSymbolABI = [&](const MCSymbol *Sym, bool IsFunction) { - if (HasABI0Suffix(Sym)) { + if (GetSymbolIdentity(Sym).IsABI0) { if (!IsFunction) report_fatal_error("Go ABI0 suffix requires a function symbol"); return GoObj::SymABI0; @@ -1554,10 +1587,14 @@ uint64_t GoObjObjectWriter::writeObject() { for (const MCSymbol &Symbol : Asm->symbols()) { if (!Symbol.isCommon()) continue; - if (HasABI0Suffix(&Symbol)) + GoObjSymbolIdentity Identity = GetSymbolIdentity(&Symbol); + if (Identity.BuiltinIndex || Identity.IsLinknameRef) + report_fatal_error( + "Go builtin and linkname suffixes require an undefined symbol"); + if (Identity.IsABI0) report_fatal_error("Go ABI0 suffix requires a function symbol"); GoObjSymbol GoSym; - GoSym.Name = GetSymbolName(&Symbol).str(); + GoSym.Name = Identity.Name.str(); GoSym.Symbol = &Symbol; GoSym.DefinedBlock = Asm->getContext().isGoObjSymbolNonPackage(&Symbol) ? GoObj::DefinedSymbolBlock::Nonpkgdef @@ -1609,6 +1646,12 @@ uint64_t GoObjObjectWriter::writeObject() { auto AddSectionSymbol = [&](const MCSymbol *MCSym, StringRef Name, uint64_t Begin, uint64_t End) { + if (MCSym) { + GoObjSymbolIdentity Identity = GetSymbolIdentity(MCSym); + if (Identity.BuiltinIndex || Identity.IsLinknameRef) + report_fatal_error( + "Go builtin and linkname suffixes require an undefined symbol"); + } uint64_t Size = End - Begin; ArrayRef Data; if (!Section.isBssSection() && Size != 0) { @@ -2195,15 +2238,20 @@ uint64_t GoObjObjectWriter::writeObject() { std::vector NonPkgRefs; StringMap NonPkgRefIndexes; auto GetNonPkgRefSymIdx = [&](const MCSymbol *Sym, bool IsFunction) { - StringRef Name = GetSymbolName(Sym); + GoObjSymbolIdentity Identity = GetSymbolIdentity(Sym); + StringRef Name = Identity.Name; if (Name.empty()) report_fatal_error("GoObj relocation target has an empty name"); uint16_t ABI = GetSymbolABI(Sym, IsFunction); std::string Key = (Name + "#" + Twine(ABI)).str(); auto It = NonPkgRefIndexes.find(Key); - if (It != NonPkgRefIndexes.end()) + if (It != NonPkgRefIndexes.end()) { + if (Identity.IsLinknameRef) + NonPkgRefs[It->second - NonpkgdefSymbols.size()].Flag2 |= + GoObj::SymFlagLinkname; return It->second; + } uint32_t SymIdx = checkedUint32(NonpkgdefSymbols.size() + NonPkgRefs.size(), "non-package reference index"); @@ -2212,6 +2260,8 @@ uint64_t GoObjObjectWriter::writeObject() { GoObjSymbol Ref; Ref.Name = Name.str(); Ref.ABI = ABI; + if (Identity.IsLinknameRef) + Ref.Flag2 |= GoObj::SymFlagLinkname; NonPkgRefs.push_back(std::move(Ref)); return SymIdx; }; @@ -2287,22 +2337,18 @@ uint64_t GoObjObjectWriter::writeObject() { } if (Reloc.Symbol->isUndefined()) { - if (const MCContext::GoObjSymbolRef *Metadata = - Asm->getContext().getGoObjSymbolRef(Reloc.Symbol)) { - switch (Metadata->Kind) { - case MCContext::GoObjSymbolRefKind::Imported: { - GoObjSymRef Ref{GetPackageIndex(Metadata->PackagePrefix), - Metadata->SymIdx}; - RecordIndexedRef(Ref, TrimInlineHash(GetSymbolName(Reloc.Symbol)), - Metadata->Flags2); - return Ref; - } - case MCContext::GoObjSymbolRefKind::Builtin: - if (!Metadata->PackagePrefix.empty() || Metadata->Flags2 != 0) - report_fatal_error("invalid GoObj builtin symbol reference"); - return GoObjSymRef{GoObj::PkgIdxBuiltin, Metadata->SymIdx}; - } + GoObjSymbolIdentity Identity = GetSymbolIdentity(Reloc.Symbol); + if (const MCContext::GoObjImportedSymbolRef *Metadata = + Asm->getContext().getGoObjImportedSymbolRef(Reloc.Symbol)) { + if (Identity.BuiltinIndex || Identity.IsLinknameRef) + report_fatal_error("conflicting GoObj symbol reference identity"); + GoObjSymRef Ref{GetPackageIndex(Metadata->PackagePrefix), + Metadata->SymIdx}; + RecordIndexedRef(Ref, TrimInlineHash(Identity.Name), Metadata->Flags2); + return Ref; } + if (Identity.BuiltinIndex && !Identity.IsLinknameRef) + return GoObjSymRef{GoObj::PkgIdxBuiltin, *Identity.BuiltinIndex}; bool IsFunction; switch (Reloc.Type) { case GoObj::R_CALL: diff --git a/llvm/lib/MC/MCContext.cpp b/llvm/lib/MC/MCContext.cpp index 288de1173703e..deef64ce8c790 100644 --- a/llvm/lib/MC/MCContext.cpp +++ b/llvm/lib/MC/MCContext.cpp @@ -181,7 +181,7 @@ void MCContext::reset() { GoObjKeepTargets.clear(); GoObjMarkerRelocs.clear(); GoObjImports.clear(); - GoObjSymbolRefs.clear(); + GoObjImportedSymbolRefs.clear(); GoObjSymbolAlignments.clear(); GoObjSymbolSizes.clear(); GoObjGotypeTargets.clear(); diff --git a/llvm/lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp b/llvm/lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp index 8a31bdb358593..50b40ebe34e7b 100644 --- a/llvm/lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp +++ b/llvm/lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp @@ -20,6 +20,7 @@ #include "MCTargetDesc/AArch64AddressingModes.h" #include "Utils/AArch64BaseInfo.h" #include "llvm/BinaryFormat/GoObj.h" +#include "llvm/CodeGen/GoCallingConv.h" #include "llvm/CodeGen/LivePhysRegs.h" #include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/CodeGen/MachineConstantPool.h" @@ -1345,7 +1346,9 @@ bool AArch64ExpandPseudoImpl::expandMI(MachineBasicBlock &MBB, MachineFunction &MF = *MBB.getParent(); if (MF.getTarget().getTargetTriple().isOSBinFormatGoObj()) { MCContext &Ctx = MF.getContext(); - MCSymbol *Callee = Ctx.getOrCreateSymbol(WriteBarrierName); + std::string StorageName = goabi::getGoObjBuiltinCalleeName( + MF, WriteBarrierName, CallingConv::GoABIInternal); + MCSymbol *Callee = Ctx.getOrCreateSymbol(StorageName); Call.addSym(Callee); } else { Call.addExternalSymbol(WriteBarrierName); diff --git a/llvm/lib/Target/X86/X86ExpandPseudo.cpp b/llvm/lib/Target/X86/X86ExpandPseudo.cpp index bb2294b7de622..0d17d6fca0874 100644 --- a/llvm/lib/Target/X86/X86ExpandPseudo.cpp +++ b/llvm/lib/Target/X86/X86ExpandPseudo.cpp @@ -18,6 +18,7 @@ #include "X86MachineFunctionInfo.h" #include "X86Subtarget.h" #include "llvm/BinaryFormat/GoObj.h" +#include "llvm/CodeGen/GoCallingConv.h" #include "llvm/CodeGen/LivePhysRegs.h" #include "llvm/CodeGen/MachineDominators.h" #include "llvm/CodeGen/MachineFunctionAnalysisManager.h" @@ -300,7 +301,9 @@ bool X86ExpandPseudoImpl::expandMI(MachineBasicBlock &MBB, MachineFunction &MF = *MBB.getParent(); if (MF.getTarget().getTargetTriple().isOSBinFormatGoObj()) { MCContext &Ctx = MF.getContext(); - MCSymbol *Callee = Ctx.getOrCreateSymbol(WriteBarrierName); + std::string StorageName = goabi::getGoObjBuiltinCalleeName( + MF, WriteBarrierName, CallingConv::GoABIInternal); + MCSymbol *Callee = Ctx.getOrCreateSymbol(StorageName); Call.addSym(Callee); } else { Call.addExternalSymbol(WriteBarrierName); diff --git a/llvm/test/CodeGen/AArch64/go-gc-write-barrier.ll b/llvm/test/CodeGen/AArch64/go-gc-write-barrier.ll index d35fccce04c2a..d4ac6452b5986 100644 --- a/llvm/test/CodeGen/AArch64/go-gc-write-barrier.ll +++ b/llvm/test/CodeGen/AArch64/go-gc-write-barrier.ll @@ -9,6 +9,8 @@ ; RUN: FileCheck %s --check-prefix=OBJ declare ptr @llvm.go.gc.write.barrier(i32 immarg) +declare goabiinternal void @"runtime.gcWriteBarrier1"() +declare goabiinternal void @"runtime.gcWriteBarrier8"() define goabiinternal ptr @acquire_one() gc "statepoint-example" { ; OPT-LABEL: define goabiinternal ptr @acquire_one() @@ -54,8 +56,6 @@ define goabiinternal void @store_one(ptr %value) gc "statepoint-example" { ret void } -; OBJ: nonpkgref {{[0-9]+}}: runtime.gcWriteBarrier1 abi=1 type=0 size=0 -; OBJ: nonpkgref {{[0-9]+}}: runtime.gcWriteBarrier8 abi=1 type=0 size=0 -; OBJ-NOT: runtime.gcWriteBarrier{{[18]}} abi=0 -; OBJ: reloc {{[0-9]+}}.{{[0-9]+}}: off={{[0-9]+}} size=4 type=9 add=0 target=runtime.gcWriteBarrier1 -; OBJ: reloc {{[0-9]+}}.{{[0-9]+}}: off={{[0-9]+}} size=4 type=9 add=0 target=runtime.gcWriteBarrier8 +; OBJ-NOT: nonpkgref {{[0-9]+}}: runtime.gcWriteBarrier +; OBJ: reloc {{[0-9]+}}.{{[0-9]+}}: off={{[0-9]+}} size=4 type=9 add=0 target=builtin:234 {{.*}}pkg=builtin sym=234 +; OBJ: reloc {{[0-9]+}}.{{[0-9]+}}: off={{[0-9]+}} size=4 type=9 add=0 target=builtin:241 {{.*}}pkg=builtin sym=241 diff --git a/llvm/test/CodeGen/AArch64/goobj-ir-config.ll b/llvm/test/CodeGen/AArch64/goobj-ir-config.ll index bcf1133f8b728..eb85e8fb2e9c2 100644 --- a/llvm/test/CodeGen/AArch64/goobj-ir-config.ll +++ b/llvm/test/CodeGen/AArch64/goobj-ir-config.ll @@ -12,9 +12,9 @@ entry: } !goobj.config = !{!0} -!0 = !{!"goallc.goobj", !"darwin", !"arm64", !"go1.27", !"GOARM64", !"v8.0", !"metadata-build", !"main", !"1", !"1", !1} +!0 = !{!"goallc.goobj", !"darwin", !"arm64", !"go1.27", !"GOARM64", !"v8.0", !"metadata-build", !"main", !"1", !"1", !"1", !1} !1 = !{!"metadata-test"} ; CHECK: header: go object darwin arm64 go1.27 GOARM64=v8.0 X:metadata-test\nbuild id "metadata-build"\nmain\n\n!\n -; CHECK: flags: 1 +; CHECK: flags: 17 ; CHECK: symdef {{[0-9]+}}: main.main diff --git a/llvm/test/CodeGen/AArch64/goobj-stack-growth.ll b/llvm/test/CodeGen/AArch64/goobj-stack-growth.ll index 7ffb1f52cf568..1bec5369e70a4 100644 --- a/llvm/test/CodeGen/AArch64/goobj-stack-growth.ll +++ b/llvm/test/CodeGen/AArch64/goobj-stack-growth.ll @@ -2,9 +2,9 @@ ; RUN: llc -mtriple=aarch64-apple-darwin-goobj -verify-machineinstrs \ ; RUN: -stop-after=prolog-epilog < %s | FileCheck %s -declare goabi0 void @"runtime.morestack"() -declare goabi0 void @"runtime.morestack_noctxt"() -declare goabi0 void @"runtime.morestackc"() +declare goabi0 void @"runtime.morestack"() +declare goabi0 void @"runtime.morestack_noctxt"() +declare goabi0 void @"runtime.morestackc"() define goabiinternal i64 @closure_morestack_call( i64 %value, ptr nest %ctxt) "frame-pointer"="non-leaf" @@ -52,27 +52,27 @@ entry: ; CHECK-LABEL: name: closure_morestack_call ; CHECK-NOT: ANNOTATION_LABEL -; CHECK: BL &"runtime.morestack", implicit-def $lr, implicit $sp, +; CHECK: BL &"runtime.morestack", implicit-def $lr, implicit $sp, ; CHECK-SAME: implicit $x3, implicit $x26 ; CHECK: STACKMAP 5147419139155979380, 0 ; CHECK-NOT: STATEPOINT ; CHECK-LABEL: name: pointer_morestack_call ; CHECK: STRXui $x0, $sp, 1 -; CHECK: BL &"runtime.morestack_noctxt", implicit-def $lr, implicit $sp, +; CHECK: BL &"runtime.morestack_noctxt", implicit-def $lr, implicit $sp, ; CHECK-SAME: implicit $x3 ; CHECK: $x0 = LDRXui $sp, 1 ; CHECK: STACKMAP 5147419139155979380, 0, 1, 8, $sp, 8 ; CHECK-NOT: BL ; CHECK-LABEL: name: mixed_register_and_stack_pointer_args -; CHECK: BL &"runtime.morestack_noctxt", implicit-def $lr, implicit $sp, +; CHECK: BL &"runtime.morestack_noctxt", implicit-def $lr, implicit $sp, ; CHECK-SAME: implicit $x3 ; CHECK: STACKMAP 5147419139155979380, 0, ; CHECK-SAME: 1, 8, $sp, 16, 1, 8, $sp, 8 ; CHECK-LABEL: name: systemstack_growth ; CHECK: $x17 = LDRXui $x28, 3 -; CHECK: BL &"runtime.morestackc", implicit-def $lr, implicit $sp, +; CHECK: BL &"runtime.morestackc", implicit-def $lr, implicit $sp, ; CHECK-SAME: implicit $x3 ; CHECK: STACKMAP 5147419139155979380, 0 diff --git a/llvm/test/CodeGen/X86/go-gc-write-barrier.ll b/llvm/test/CodeGen/X86/go-gc-write-barrier.ll index c0962c5eb73d3..143cd28b99866 100644 --- a/llvm/test/CodeGen/X86/go-gc-write-barrier.ll +++ b/llvm/test/CodeGen/X86/go-gc-write-barrier.ll @@ -9,6 +9,8 @@ ; RUN: FileCheck %s --check-prefix=OBJ declare ptr @llvm.go.gc.write.barrier(i32 immarg) +declare goabiinternal void @"runtime.gcWriteBarrier1"() +declare goabiinternal void @"runtime.gcWriteBarrier8"() define goabiinternal ptr @acquire_one() gc "statepoint-example" { ; OPT-LABEL: define goabiinternal ptr @acquire_one() @@ -56,8 +58,6 @@ define goabiinternal void @store_one(ptr %value) gc "statepoint-example" { ret void } -; OBJ: nonpkgref {{[0-9]+}}: runtime.gcWriteBarrier1 abi=1 type=0 size=0 -; OBJ: nonpkgref {{[0-9]+}}: runtime.gcWriteBarrier8 abi=1 type=0 size=0 -; OBJ-NOT: runtime.gcWriteBarrier{{[18]}} abi=0 -; OBJ: reloc {{[0-9]+}}.{{[0-9]+}}: off={{[0-9]+}} size=4 type=7 add=0 target=runtime.gcWriteBarrier1 -; OBJ: reloc {{[0-9]+}}.{{[0-9]+}}: off={{[0-9]+}} size=4 type=7 add=0 target=runtime.gcWriteBarrier8 +; OBJ-NOT: nonpkgref {{[0-9]+}}: runtime.gcWriteBarrier +; OBJ: reloc {{[0-9]+}}.{{[0-9]+}}: off={{[0-9]+}} size=4 type=7 add=0 target=builtin:234 {{.*}}pkg=builtin sym=234 +; OBJ: reloc {{[0-9]+}}.{{[0-9]+}}: off={{[0-9]+}} size=4 type=7 add=0 target=builtin:241 {{.*}}pkg=builtin sym=241 diff --git a/llvm/test/CodeGen/X86/goobj-import-metadata-invalid.ll b/llvm/test/CodeGen/X86/goobj-import-metadata-invalid.ll index f1bdb42d2e3d7..257a40cbf1707 100644 --- a/llvm/test/CodeGen/X86/goobj-import-metadata-invalid.ll +++ b/llvm/test/CodeGen/X86/goobj-import-metadata-invalid.ll @@ -1,8 +1,13 @@ ; RUN: split-file %s %t ; RUN: not --crash llc -mtriple=x86_64-unknown-linux-goobj -filetype=obj %t/fingerprint.ll -o /dev/null 2>&1 | FileCheck %s --check-prefix=FINGERPRINT ; RUN: not --crash llc -mtriple=x86_64-unknown-linux-goobj -filetype=obj %t/conflicting.ll -o /dev/null 2>&1 | FileCheck %s --check-prefix=CONFLICTING +; RUN: not --crash llc -mtriple=x86_64-unknown-linux-goobj -filetype=obj %t/import-builtin.ll -o /dev/null 2>&1 | FileCheck %s --check-prefix=IMPORT-BUILTIN ; RUN: not --crash llc -mtriple=x86_64-unknown-linux-goobj -filetype=obj %t/definition.ll -o /dev/null 2>&1 | FileCheck %s --check-prefix=DEFINITION ; RUN: not --crash llc -mtriple=x86_64-unknown-linux-goobj -filetype=obj %t/duplicate-import.ll -o /dev/null 2>&1 | FileCheck %s --check-prefix=DUPLICATE-IMPORT +; RUN: not --crash llc -mtriple=x86_64-unknown-linux-goobj -filetype=obj %t/obsolete-builtin.ll -o /dev/null 2>&1 | FileCheck %s --check-prefix=OBSOLETE-BUILTIN +; RUN: not --crash llc -mtriple=x86_64-unknown-linux-goobj -filetype=obj %t/builtin-definition.ll -o /dev/null 2>&1 | FileCheck %s --check-prefix=BUILTIN-DEFINITION +; RUN: not --crash llc -mtriple=x86_64-unknown-linux-goobj -filetype=obj %t/builtin-index.ll -o /dev/null 2>&1 | FileCheck %s --check-prefix=BUILTIN-INDEX +; RUN: not --crash llc -mtriple=x86_64-unknown-linux-goobj -filetype=obj %t/builtin-linkname.ll -o /dev/null 2>&1 | FileCheck %s --check-prefix=BUILTIN-LINKNAME ;--- fingerprint.ll define goabiinternal void @f() { @@ -14,16 +19,25 @@ define goabiinternal void @f() { ; FINGERPRINT: LLVM ERROR: invalid !goobj.imports fingerprint ;--- conflicting.ll -declare !goobj.import !0 !goobj.builtin !1 goabiinternal void @external() +declare !goobj.import !0 goabiinternal void @"external"() define goabiinternal void @f() { - call goabiinternal void @external() + call goabiinternal void @"external"() ret void } !0 = !{!"pkg", i32 1, i32 0} -!1 = !{i32 2} ; CONFLICTING: LLVM ERROR: invalid GoObj symbol reference attachment +;--- import-builtin.ll +declare !goobj.import !0 goabiinternal void @"runtime.external"() +define goabiinternal void @f() { + call goabiinternal void @"runtime.external"() + ret void +} +!0 = !{!"runtime", i32 1, i32 0} + +; IMPORT-BUILTIN: LLVM ERROR: invalid GoObj symbol reference attachment + ;--- definition.ll define goabiinternal void @f() !goobj.import !0 { ret void @@ -41,3 +55,35 @@ define goabiinternal void @f() { !1 = !{!"os", !"os", !"fedcba9876543210"} ; DUPLICATE-IMPORT: LLVM ERROR: duplicate !goobj.imports package + +;--- obsolete-builtin.ll +@source = global ptr @"type:string", !goobj.builtin !0 +@"type:string" = external global i8 +!0 = !{i32 7} + +; OBSOLETE-BUILTIN: LLVM ERROR: !goobj.builtin is obsolete; encode the builtin index in the symbol name + +;--- builtin-definition.ll +define goabiinternal void @"runtime.bad"() { + ret void +} + +; BUILTIN-DEFINITION: LLVM ERROR: Go builtin and linkname suffixes require an undefined symbol + +;--- builtin-index.ll +declare goabiinternal void @"runtime.bad"() +define goabiinternal void @f() { + call goabiinternal void @"runtime.bad"() + ret void +} + +; BUILTIN-INDEX: LLVM ERROR: invalid Go builtin symbol index + +;--- builtin-linkname.ll +declare goabiinternal void @"runtime.bad"() +define goabiinternal void @f() { + call goabiinternal void @"runtime.bad"() + ret void +} + +; BUILTIN-LINKNAME: LLVM ERROR: conflicting Go builtin and linkname symbol identity diff --git a/llvm/test/CodeGen/X86/goobj-import-references.ll b/llvm/test/CodeGen/X86/goobj-import-references.ll index 332b814037791..8211969e973f8 100644 --- a/llvm/test/CodeGen/X86/goobj-import-references.ll +++ b/llvm/test/CodeGen/X86/goobj-import-references.ll @@ -10,15 +10,21 @@ @"fmt.data" = external global i8, !goobj.import !2 @"fmt.inlined#AAAAAAAAAAA=#suffix" = external global i8, !goobj.import !3 @"fmt.unused" = external global i8, !goobj.import !8 -@"type:string" = external global i8, !goobj.builtin !4 +@"type:string" = external global i8 @data_source = constant ptr @"fmt.data", section ".rodata", align 8 @inline_source = constant ptr @"fmt.inlined#AAAAAAAAAAA=#suffix", section ".rodata", align 8 -@llvm.compiler.used = appending global [6 x ptr] [ptr @source, ptr @data_source, ptr @inline_source, ptr @"fmt.data", ptr @"fmt.inlined#AAAAAAAAAAA=#suffix", ptr @"type:string"], section "llvm.metadata" +@llvm.compiler.used = appending global [9 x ptr] [ptr @source, ptr @data_source, ptr @inline_source, ptr @"fmt.data", ptr @"fmt.inlined#AAAAAAAAAAA=#suffix", ptr @"type:string", ptr @"runtime.internal", ptr @"runtime.abi0", ptr @"runtime.named"], section "llvm.metadata" declare !goobj.import !5 goabiinternal void @"os.Exit"(i64) +declare goabiinternal void @"runtime.internal"() +declare goabi0 void @"runtime.abi0"() +declare goabiinternal void @"runtime.named"() define goabiinternal void @source() "frame-pointer"="non-leaf" { call goabiinternal void @"os.Exit"(i64 1) + call goabiinternal void @"runtime.internal"() + call goabi0 void @"runtime.abi0"() + call goabiinternal void @"runtime.named"() ret void } @@ -27,11 +33,10 @@ define goabiinternal void @source() "frame-pointer"="non-leaf" { !1 = !{!"fmt", !"fmt", !"fedcba9876543210"} !2 = !{!"fmt", i32 9, i32 1} !3 = !{!"fmt", i32 10, i32 0} -!4 = !{i32 7} !5 = !{!"os", i32 15, i32 0} !goobj.marker_relocs = !{!6, !7} -!6 = !{ptr @source, ptr @"type:string", i32 23, i64 0} +!6 = !{ptr @source, ptr @"type:string", i32 23, i64 0} !7 = !{ptr @data_source, ptr @"fmt.data", i32 23, i64 0} !8 = !{!"fmt", i32 11, i32 0} @@ -46,10 +51,14 @@ define goabiinternal void @source() "frame-pointer"="non-leaf" { ; CHECK-DAG: refname [[FMTIDX]]:10: fmt.inlinedsuffix ; CHECK-DAG: refname [[OSIDX]]:15: os.Exit ; CHECK: refflags [[FMTIDX]]:9: flag=0 flag2=1 +; CHECK-DAG: nonpkgref {{[0-9]+}}: runtime.named abi=1 {{.*}}flag2=16 ; CHECK-NOT: nonpkgref {{[0-9]+}}: fmt.data ; CHECK-NOT: nonpkgref {{[0-9]+}}: os.Exit ; CHECK-NOT: fmt.unused ; CHECK-DAG: reloc {{[0-9]+}}.{{[0-9]+}}: off=0 size=8 {{.*}}target=fmt.data {{.*}}pkg=[[FMTIDX]] sym=9 ; CHECK-DAG: reloc {{[0-9]+}}.{{[0-9]+}}: off=0 size=0 type=23 add=0 target=fmt.data {{.*}}pkg=[[FMTIDX]] sym=9 ; CHECK-DAG: reloc {{[0-9]+}}.{{[0-9]+}}: off=0 size=0 type=23 add=0 target=builtin:7 {{.*}}pkg=builtin sym=7 +; CHECK-DAG: reloc {{[0-9]+}}.{{[0-9]+}}: {{.*}}target=builtin:8 {{.*}}pkg=builtin sym=8 +; CHECK-DAG: reloc {{[0-9]+}}.{{[0-9]+}}: {{.*}}target=builtin:9 {{.*}}pkg=builtin sym=9 +; CHECK-DAG: reloc {{[0-9]+}}.{{[0-9]+}}: {{.*}}target=runtime.named {{.*}}pkg=none ; CHECK-DAG: reloc {{[0-9]+}}.{{[0-9]+}}: {{.*}}target=os.Exit {{.*}}pkg=[[OSIDX]] sym=15 diff --git a/llvm/test/CodeGen/X86/goobj-late-builtin-shared.ll b/llvm/test/CodeGen/X86/goobj-late-builtin-shared.ll new file mode 100644 index 0000000000000..d7ba4f27d8cb6 --- /dev/null +++ b/llvm/test/CodeGen/X86/goobj-late-builtin-shared.ll @@ -0,0 +1,22 @@ +; REQUIRES: x86-registered-target +; RUN: llc -mtriple=x86_64-unknown-linux-goobj -verify-machineinstrs \ +; RUN: -stop-after=prolog-epilog < %s | FileCheck %s + +; Go disables builtin-index references for -linkshared. Late passes therefore +; use the ordinary ABI0 linker name when the module has no builtin declaration. + +define goabiinternal void @large_frame() { +entry: + %buf = alloca [5000 x i8], align 8 + %slot = getelementptr inbounds [5000 x i8], ptr %buf, i64 0, i64 4999 + store volatile i8 1, ptr %slot, align 1 + ret void +} + +; CHECK-LABEL: name: large_frame +; CHECK: CALL64pcrel32 &"runtime.morestack_noctxt" +; CHECK-NOT: "() -declare goabi0 void @"runtime.morestackc"() +declare goabi0 void @"runtime.morestack_noctxt"() +declare goabi0 void @"runtime.morestackc"() define goabiinternal i64 @morestack_call(i64 %value) { entry: @@ -89,7 +89,7 @@ entry: ; CHECK-LABEL: name: morestack_call ; CHECK-NOT: ANNOTATION_LABEL -; CHECK: CALL64pcrel32 &"runtime.morestack_noctxt", implicit $rsp, implicit $ssp +; CHECK: CALL64pcrel32 &"runtime.morestack_noctxt", implicit $rsp, implicit $ssp ; CHECK: STACKMAP 5147419139155979380, 0 ; CHECK-NOT: STATEPOINT @@ -105,7 +105,7 @@ entry: ; CHECK: offset: 16, size: 8 ; CHECK: offset: 8, size: 8 ; CHECK: offset: 0, size: 8 -; CHECK: CALL64pcrel32 &"runtime.morestack_noctxt", implicit $rsp, implicit $ssp +; CHECK: CALL64pcrel32 &"runtime.morestack_noctxt", implicit $rsp, implicit $ssp ; CHECK: STACKMAP 5147419139155979380, 0, ; CHECK-SAME: 1, 8, $rsp, 8, 1, 8, $rsp, 16, 1, 8, $rsp, 24 ; CHECK: renamable $rax = MOV64rm $rbp, 1, $noreg, 16, $noreg @@ -114,7 +114,7 @@ entry: ; CHECK-LABEL: name: initialized_pointer_result ; CHECK: MOV64mr $rsp, 1, $noreg, 72, $noreg, $rax -; CHECK: CALL64pcrel32 &"runtime.morestack_noctxt", implicit $rsp, implicit $ssp +; CHECK: CALL64pcrel32 &"runtime.morestack_noctxt", implicit $rsp, implicit $ssp ; The unused pointer parameter may arrive as poison. Its home is preserved for ; the ABI retry path but must not be scanned. ; CHECK: STACKMAP 5147419139155979380, 0{{$}} @@ -122,19 +122,19 @@ entry: ; CHECK-LABEL: name: partial_aggregate_result ; CHECK: MOV64mr $rsp, 1, $noreg, 80, $noreg, $rax ; CHECK: MOV64mr $rsp, 1, $noreg, 88, $noreg, $rbx -; CHECK: CALL64pcrel32 &"runtime.morestack_noctxt", implicit $rsp, implicit $ssp +; CHECK: CALL64pcrel32 &"runtime.morestack_noctxt", implicit $rsp, implicit $ssp ; CHECK: STACKMAP 5147419139155979380, 0{{$}} ; CHECK-LABEL: name: scalar_stack_argument -; CHECK: CALL64pcrel32 &"runtime.morestack_noctxt", implicit $rsp, implicit $ssp +; CHECK: CALL64pcrel32 &"runtime.morestack_noctxt", implicit $rsp, implicit $ssp ; CHECK: STACKMAP 5147419139155979380, 0, 1, 8, $rsp, 64 ; CHECK-LABEL: name: aggregate_stack_argument -; CHECK: CALL64pcrel32 &"runtime.morestack_noctxt", implicit $rsp, implicit $ssp +; CHECK: CALL64pcrel32 &"runtime.morestack_noctxt", implicit $rsp, implicit $ssp ; CHECK: STACKMAP 5147419139155979380, 0, ; CHECK-SAME: 1, 8, $rsp, 48, 1, 8, $rsp, 64 ; CHECK-LABEL: name: systemstack_growth ; CHECK: CMP64rm $r12, $r14, 1, $noreg, 24, $noreg -; CHECK: CALL64pcrel32 &"runtime.morestackc", implicit $rsp, implicit $ssp +; CHECK: CALL64pcrel32 &"runtime.morestackc", implicit $rsp, implicit $ssp ; CHECK: STACKMAP 5147419139155979380, 0 diff --git a/llvm/tools/llc/llc.cpp b/llvm/tools/llc/llc.cpp index fd290e5c0c105..712773bbad836 100644 --- a/llvm/tools/llc/llc.cpp +++ b/llvm/tools/llc/llc.cpp @@ -91,18 +91,18 @@ static Error configureGoObjFromModule(const Module &M) { "!goobj.config must contain one operand"); const MDNode &Node = *Named->getOperand(0); - if (Node.getNumOperands() != 11) + if (Node.getNumOperands() != 12) return createStringError(inconvertibleErrorCode(), - "!goobj.config must contain eleven fields"); + "!goobj.config must contain twelve fields"); - SmallVector Fields; - for (unsigned I = 0; I != 10; ++I) { + SmallVector Fields; + for (unsigned I = 0; I != 11; ++I) { Expected Field = getGoObjConfigField(Node, I); if (!Field) return Field.takeError(); Fields.push_back(std::move(*Field)); } - const auto *ExperimentNode = dyn_cast(Node.getOperand(10)); + const auto *ExperimentNode = dyn_cast(Node.getOperand(11)); if (!ExperimentNode) return createStringError(inconvertibleErrorCode(), "!goobj.config experiments must be a metadata node"); @@ -131,9 +131,11 @@ static Error configureGoObjFromModule(const Module &M) { inconvertibleErrorCode(), "!goobj.config GOARCH setting key and value must be both present or absent"); if ((Fields[8] != "0" && Fields[8] != "1") || - (Fields[9] != "0" && Fields[9] != "1")) - return createStringError(inconvertibleErrorCode(), - "!goobj.config main and shared flags must be 0 or 1"); + (Fields[9] != "0" && Fields[9] != "1") || + (Fields[10] != "0" && Fields[10] != "1")) + return createStringError( + inconvertibleErrorCode(), + "!goobj.config main, shared, and std flags must be 0 or 1"); if (!Triple(M.getTargetTriple()).isOSBinFormatGoObj()) return createStringError(inconvertibleErrorCode(), "!goobj.config requires a GoObj target triple"); @@ -148,6 +150,7 @@ static Error configureGoObjFromModule(const Module &M) { Config.PackagePath = std::move(Fields[7]); Config.IsMain = Fields[8] == "1"; Config.IsShared = Fields[9] == "1"; + Config.IsStd = Fields[10] == "1"; Config.Experiments.assign(Experiments.begin(), Experiments.end()); codegen::setGoObjConfig(std::move(Config)); return Error::success();