llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-mc Author: Kai Nacke (redstar) <details> <summary>Changes</summary> The GOFF format uses symbol definitions to represent sections and symbols. Introducing a section can require up to 3 symbol definitions. However, most of these details are not needed by the AsmPrinter. To mapped from a section (a MCSectionGOFF) to the symbol definitions, a new class called MCGOFFSymbolMapper is used. The same information can also be used by the assembly output, which justifies this centralized approach. Writing the mapped symbols is then straight forward. --- Patch is 35.69 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/133799.diff 8 Files Affected: - (modified) llvm/include/llvm/BinaryFormat/GOFF.h (+85) - (added) llvm/include/llvm/MC/MCGOFFSymbolMapper.h (+148) - (modified) llvm/lib/MC/CMakeLists.txt (+1) - (modified) llvm/lib/MC/GOFFObjectWriter.cpp (+253-37) - (added) llvm/lib/MC/MCGOFFSymbolMapper.cpp (+203) - (modified) llvm/lib/MC/MCObjectFileInfo.cpp (+1-1) - (modified) llvm/test/CodeGen/SystemZ/zos-ppa2.ll (+1-1) - (added) llvm/test/MC/GOFF/section.ll (+73) ``````````diff diff --git a/llvm/include/llvm/BinaryFormat/GOFF.h b/llvm/include/llvm/BinaryFormat/GOFF.h index 443bcfc9479a8..43d80e0c247e9 100644 --- a/llvm/include/llvm/BinaryFormat/GOFF.h +++ b/llvm/include/llvm/BinaryFormat/GOFF.h @@ -169,6 +169,91 @@ enum SubsectionKind : uint8_t { SK_PPA1 = 2, SK_PPA2 = 4, }; + +// The standard System/390 convention is to name the high-order (leftmost) bit +// in a byte as bit zero. The Flags type helps to set bits in byte according +// to this numeration order. +class Flags { + uint8_t Val; + + constexpr static uint8_t bits(uint8_t BitIndex, uint8_t Length, uint8_t Value, + uint8_t OldValue) { + uint8_t Pos = 8 - BitIndex - Length; + uint8_t Mask = ((1 << Length) - 1) << Pos; + Value = Value << Pos; + return (OldValue & ~Mask) | Value; + } + +public: + constexpr Flags() : Val(0) {} + constexpr Flags(uint8_t BitIndex, uint8_t Length, uint8_t Value) + : Val(bits(BitIndex, Length, Value, 0)) {} + + template <typename T> + constexpr void set(uint8_t BitIndex, uint8_t Length, T NewValue) { + Val = bits(BitIndex, Length, static_cast<uint8_t>(NewValue), Val); + } + + template <typename T> + constexpr T get(uint8_t BitIndex, uint8_t Length) const { + return static_cast<T>((Val >> (8 - BitIndex - Length)) & + ((1 << Length) - 1)); + } + + constexpr operator uint8_t() const { return Val; } +}; + +// Structure for the flag field of a symbol. See +// https://www.ibm.com/docs/en/zos/3.1.0?topic=formats-external-symbol-definition-record, +// offset 41, for the definition. +struct SymbolFlags { + Flags SymFlags; + +#define GOFF_SYMBOL_FLAG(NAME, TYPE, BITINDEX, LENGTH) \ + void set##NAME(TYPE Val) { SymFlags.set<TYPE>(BITINDEX, LENGTH, Val); } \ + TYPE get##NAME() const { return SymFlags.get<TYPE>(BITINDEX, LENGTH); } + + GOFF_SYMBOL_FLAG(FillBytePresence, bool, 0, 1) + GOFF_SYMBOL_FLAG(Mangled, bool, 1, 1) + GOFF_SYMBOL_FLAG(Renameable, bool, 2, 1) + GOFF_SYMBOL_FLAG(RemovableClass, bool, 3, 1) + GOFF_SYMBOL_FLAG(ReservedQwords, ESDReserveQwords, 5, 3) + +#undef GOFF_SYMBOL_FLAG + +constexpr operator uint8_t() const { return static_cast<uint8_t>(SymFlags); } +}; + +// Structure for the behavioral attributes. See +// https://www.ibm.com/docs/en/zos/3.1.0?topic=record-external-symbol-definition-behavioral-attributes +// for the definition. +struct BehavioralAttributes { + Flags Attr[10]; + +#define GOFF_BEHAVIORAL_ATTRIBUTE(NAME, TYPE, ATTRIDX, BITINDEX, LENGTH) \ + void set##NAME(TYPE Val) { Attr[ATTRIDX].set<TYPE>(BITINDEX, LENGTH, Val); } \ + TYPE get##NAME() const { return Attr[ATTRIDX].get<TYPE>(BITINDEX, LENGTH); } + + GOFF_BEHAVIORAL_ATTRIBUTE(Amode, GOFF::ESDAmode, 0, 0, 8) + GOFF_BEHAVIORAL_ATTRIBUTE(Rmode, GOFF::ESDRmode, 1, 0, 8) + GOFF_BEHAVIORAL_ATTRIBUTE(TextStyle, GOFF::ESDTextStyle, 2, 0, 4) + GOFF_BEHAVIORAL_ATTRIBUTE(BindingAlgorithm, GOFF::ESDBindingAlgorithm, 2, 4, + 4) + GOFF_BEHAVIORAL_ATTRIBUTE(TaskingBehavior, GOFF::ESDTaskingBehavior, 3, 0, 3) + GOFF_BEHAVIORAL_ATTRIBUTE(ReadOnly, bool, 3, 4, 1) + GOFF_BEHAVIORAL_ATTRIBUTE(Executable, GOFF::ESDExecutable, 3, 5, 3) + GOFF_BEHAVIORAL_ATTRIBUTE(DuplicateSymbolSeverity, + GOFF::ESDDuplicateSymbolSeverity, 4, 2, 2) + GOFF_BEHAVIORAL_ATTRIBUTE(BindingStrength, GOFF::ESDBindingStrength, 4, 4, 4) + GOFF_BEHAVIORAL_ATTRIBUTE(LoadingBehavior, GOFF::ESDLoadingBehavior, 5, 0, 2) + GOFF_BEHAVIORAL_ATTRIBUTE(COMMON, bool, 5, 2, 1) + GOFF_BEHAVIORAL_ATTRIBUTE(IndirectReference, bool, 5, 3, 1) + GOFF_BEHAVIORAL_ATTRIBUTE(BindingScope, GOFF::ESDBindingScope, 5, 4, 4) + GOFF_BEHAVIORAL_ATTRIBUTE(LinkageType, GOFF::ESDLinkageType, 6, 2, 1) + GOFF_BEHAVIORAL_ATTRIBUTE(Alignment, GOFF::ESDAlignment, 6, 3, 5) + +#undef GOFF_BEHAVIORAL_ATTRIBUTE +}; } // end namespace GOFF } // end namespace llvm diff --git a/llvm/include/llvm/MC/MCGOFFSymbolMapper.h b/llvm/include/llvm/MC/MCGOFFSymbolMapper.h new file mode 100644 index 0000000000000..dbdc1408dab2f --- /dev/null +++ b/llvm/include/llvm/MC/MCGOFFSymbolMapper.h @@ -0,0 +1,148 @@ +//===- MCGOFFSymbolMapper.h - Maps MC section/symbol to GOFF symbols ------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Maps a section or a symbol to the GOFF symbols it is composed of, and their +// attributes. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCGOFFSYMBOLMAPPER_H +#define LLVM_MC_MCGOFFSYMBOLMAPPER_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/BinaryFormat/GOFF.h" +#include "llvm/Support/Alignment.h" +#include <string> +#include <utility> + +namespace llvm { +class MCAssembler; +class MCContext; +class MCSectionGOFF; + +// An "External Symbol Definition" in the GOFF file has a type, and depending on +// the type a different subset of the fields is used. +// +// Unlike other formats, a 2 dimensional structure is used to define the +// location of data. For example, the equivalent of the ELF .text section is +// made up of a Section Definition (SD) and a class (Element Definition; ED). +// The name of the SD symbol depends on the application, while the class has the +// predefined name C_CODE64. +// +// Data can be placed into this structure in 2 ways. First, the data (in a text +// record) can be associated with an ED symbol. To refer to data, a Label +// Definition (LD) is used to give an offset into the data a name. When binding, +// the whole data is pulled into the resulting executable, and the addresses +// given by the LD symbols are resolved. +// +// The alternative is to use a Part Defiition (PR). In this case, the data (in a +// text record) is associated with the part. When binding, only the data of +// referenced PRs is pulled into the resulting binary. +// +// Both approaches are used, which means that the equivalent of a section in ELF +// results in 3 GOFF symbol, either SD/ED/LD or SD/ED/PR. Moreover, certain +// sections are fine with just defining SD/ED symbols. The SymbolMapper takes +// care of all those details. + +// Attributes for SD symbols. +struct SDAttr { + GOFF::ESDTaskingBehavior TaskingBehavior = GOFF::ESD_TA_Unspecified; + GOFF::ESDBindingScope BindingScope = GOFF::ESD_BSC_Unspecified; +}; + +// Attributes for ED symbols. +struct EDAttr { + bool IsReadOnly = false; + GOFF::ESDExecutable Executable = GOFF::ESD_EXE_Unspecified; + GOFF::ESDAmode Amode; + GOFF::ESDRmode Rmode; + GOFF::ESDNameSpaceId NameSpace = GOFF::ESD_NS_NormalName; + GOFF::ESDTextStyle TextStyle = GOFF::ESD_TS_ByteOriented; + GOFF::ESDBindingAlgorithm BindAlgorithm = GOFF::ESD_BA_Concatenate; + GOFF::ESDLoadingBehavior LoadBehavior = GOFF::ESD_LB_Initial; + GOFF::ESDReserveQwords ReservedQwords = GOFF::ESD_RQ_0; + GOFF::ESDAlignment Alignment = GOFF::ESD_ALIGN_Doubleword; +}; + +// Attributes for LD symbols. +struct LDAttr { + bool IsRenamable = false; + GOFF::ESDExecutable Executable = GOFF::ESD_EXE_Unspecified; + GOFF::ESDNameSpaceId NameSpace = GOFF::ESD_NS_NormalName; + GOFF::ESDBindingStrength BindingStrength = GOFF::ESD_BST_Strong; + GOFF::ESDLinkageType Linkage = GOFF::ESD_LT_XPLink; + GOFF::ESDAmode Amode; + GOFF::ESDBindingScope BindingScope = GOFF::ESD_BSC_Unspecified; +}; + +// Attributes for PR symbols. +struct PRAttr { + bool IsRenamable = false; + bool IsReadOnly = false; // ???? Not documented. + GOFF::ESDExecutable Executable = GOFF::ESD_EXE_Unspecified; + GOFF::ESDNameSpaceId NameSpace = GOFF::ESD_NS_NormalName; + GOFF::ESDLinkageType Linkage = GOFF::ESD_LT_XPLink; + GOFF::ESDAmode Amode; + GOFF::ESDBindingScope BindingScope = GOFF::ESD_BSC_Unspecified; + GOFF::ESDDuplicateSymbolSeverity DuplicateSymbolSeverity = + GOFF::ESD_DSS_NoWarning; + GOFF::ESDAlignment Alignment = GOFF::ESD_ALIGN_Byte; + uint32_t SortKey = 0; +}; + +struct GOFFSectionData { + // Name and attributes of SD symbol. + StringRef SDName; + SDAttr SDAttributes; + + // Name and attributes of ED symbol. + StringRef EDName; + EDAttr EDAttributes; + + // Name and attributes of LD or PR symbol. + StringRef LDorPRName; + LDAttr LDAttributes; + PRAttr PRAttributes; + + // Indicates if there is a LD or PR symbol. + enum { None, LD, PR } Tag; + + // Indicates if the SD symbol is to root symbol (aka the Csect Code). + bool IsSDRootSD; +}; + +class GOFFSymbolMapper { + MCContext &Ctx; + + std::string RootSDName; + SDAttr RootSDAttributes; + + std::string ADALDName; + + StringRef BaseName; + + bool IsCsectCodeNameEmpty; + bool Is64Bit; + bool UsesXPLINK; + +public: + GOFFSymbolMapper(MCContext &Ctx); + GOFFSymbolMapper(MCAssembler &Asm); + + // Required order: .text first, then .ada. + std::pair<GOFFSectionData, bool> getSection(const MCSectionGOFF &Section); + + void setBaseName(); + void determineRootSD(StringRef CSectCodeName); + llvm::StringRef getRootSDName() const; + const SDAttr &getRootSD() const; +}; + +} // namespace llvm + +#endif diff --git a/llvm/lib/MC/CMakeLists.txt b/llvm/lib/MC/CMakeLists.txt index f49f14c848b90..967ec73a2be5b 100644 --- a/llvm/lib/MC/CMakeLists.txt +++ b/llvm/lib/MC/CMakeLists.txt @@ -26,6 +26,7 @@ add_llvm_component_library(LLVMMC MCExpr.cpp MCFragment.cpp MCGOFFStreamer.cpp + MCGOFFSymbolMapper.cpp MCInst.cpp MCInstPrinter.cpp MCInstrAnalysis.cpp diff --git a/llvm/lib/MC/GOFFObjectWriter.cpp b/llvm/lib/MC/GOFFObjectWriter.cpp index efaf5ff006ddc..92603c6fb1002 100644 --- a/llvm/lib/MC/GOFFObjectWriter.cpp +++ b/llvm/lib/MC/GOFFObjectWriter.cpp @@ -13,7 +13,11 @@ #include "llvm/BinaryFormat/GOFF.h" #include "llvm/MC/MCAssembler.h" #include "llvm/MC/MCGOFFObjectWriter.h" +#include "llvm/MC/MCGOFFSymbolMapper.h" +#include "llvm/MC/MCSectionGOFF.h" #include "llvm/MC/MCValue.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/ConvertEBCDIC.h" #include "llvm/Support/Debug.h" #include "llvm/Support/Endian.h" #include "llvm/Support/raw_ostream.h" @@ -23,44 +27,13 @@ using namespace llvm; #define DEBUG_TYPE "goff-writer" namespace { - -// The standard System/390 convention is to name the high-order (leftmost) bit -// in a byte as bit zero. The Flags type helps to set bits in a byte according -// to this numeration order. -class Flags { - uint8_t Val; - - constexpr static uint8_t bits(uint8_t BitIndex, uint8_t Length, uint8_t Value, - uint8_t OldValue) { - assert(BitIndex < 8 && "Bit index out of bounds!"); - assert(Length + BitIndex <= 8 && "Bit length too long!"); - - uint8_t Mask = ((1 << Length) - 1) << (8 - BitIndex - Length); - Value = Value << (8 - BitIndex - Length); - assert((Value & Mask) == Value && "Bits set outside of range!"); - - return (OldValue & ~Mask) | Value; - } - -public: - constexpr Flags() : Val(0) {} - constexpr Flags(uint8_t BitIndex, uint8_t Length, uint8_t Value) - : Val(bits(BitIndex, Length, Value, 0)) {} - - void set(uint8_t BitIndex, uint8_t Length, uint8_t Value) { - Val = bits(BitIndex, Length, Value, Val); - } - - constexpr operator uint8_t() const { return Val; } -}; - // Common flag values on records. // Flag: This record is continued. -constexpr uint8_t RecContinued = Flags(7, 1, 1); +constexpr uint8_t RecContinued = GOFF::Flags(7, 1, 1); // Flag: This record is a continuation. -constexpr uint8_t RecContinuation = Flags(6, 1, 1); +constexpr uint8_t RecContinuation = GOFF::Flags(6, 1, 1); // The GOFFOstream is responsible to write the data into the fixed physical // records of the format. A user of this class announces the begin of a new @@ -223,13 +196,113 @@ void GOFFOstream::finalizeRecord() { } namespace { +// A GOFFSymbol holds all the data required for writing an ESD record. +class GOFFSymbol { +public: + std::string Name; + uint32_t EsdId; + uint32_t ParentEsdId; + uint64_t Offset = 0; // Offset of the symbol into the section. LD only. + // Offset is only 32 bit, the larger type is used to + // enable error checking. + GOFF::ESDSymbolType SymbolType; + GOFF::ESDNameSpaceId NameSpace = GOFF::ESD_NS_ProgramManagementBinder; + + GOFF::BehavioralAttributes BehavAttrs; + GOFF::SymbolFlags SymbolFlags; + uint32_t SortKey = 0; + uint32_t SectionLength = 0; + uint32_t ADAEsdId = 0; + uint32_t EASectionEDEsdId = 0; + uint32_t EASectionOffset = 0; + uint8_t FillByteValue = 0; + + GOFFSymbol() : EsdId(0), ParentEsdId(0) {} + + GOFFSymbol(StringRef Name, uint32_t EsdID, const SDAttr &Attr) + : Name(Name.data(), Name.size()), EsdId(EsdID), ParentEsdId(0), + SymbolType(GOFF::ESD_ST_SectionDefinition) { + BehavAttrs.setTaskingBehavior(Attr.TaskingBehavior); + BehavAttrs.setBindingScope(Attr.BindingScope); + } + + GOFFSymbol(StringRef Name, uint32_t EsdID, uint32_t ParentEsdID, + const EDAttr &Attr) + : Name(Name.data(), Name.size()), EsdId(EsdID), ParentEsdId(ParentEsdID), + SymbolType(GOFF::ESD_ST_ElementDefinition) { + this->NameSpace = Attr.NameSpace; + // TODO Do we need/should set the "mangled" flag? + SymbolFlags.setFillBytePresence(1); + SymbolFlags.setReservedQwords(Attr.ReservedQwords); + BehavAttrs.setReadOnly(Attr.IsReadOnly); + BehavAttrs.setExecutable(Attr.Executable); + BehavAttrs.setAmode(Attr.Amode); + BehavAttrs.setRmode(Attr.Rmode); + BehavAttrs.setTextStyle(Attr.TextStyle); + BehavAttrs.setBindingAlgorithm(Attr.BindAlgorithm); + BehavAttrs.setLoadingBehavior(Attr.LoadBehavior); + BehavAttrs.setAlignment(Attr.Alignment); + } + + GOFFSymbol(StringRef Name, uint32_t EsdID, uint32_t ParentEsdID, + const LDAttr &Attr) + : Name(Name.data(), Name.size()), EsdId(EsdID), ParentEsdId(ParentEsdID), + SymbolType(GOFF::ESD_ST_LabelDefinition) { + this->NameSpace = Attr.NameSpace; + SymbolFlags.setRenameable(Attr.IsRenamable); + BehavAttrs.setExecutable(Attr.Executable); + BehavAttrs.setBindingStrength(Attr.BindingStrength); + BehavAttrs.setLinkageType(Attr.Linkage); + BehavAttrs.setAmode(Attr.Amode); + BehavAttrs.setBindingScope(Attr.BindingScope); + } + + GOFFSymbol(StringRef Name, uint32_t EsdID, uint32_t ParentEsdID, + const PRAttr &Attr) + : Name(Name.data(), Name.size()), EsdId(EsdID), ParentEsdId(ParentEsdID), + SymbolType(GOFF::ESD_ST_PartReference) { + this->NameSpace = Attr.NameSpace; + SymbolFlags.setRenameable(Attr.IsRenamable); + BehavAttrs.setExecutable(Attr.Executable); + BehavAttrs.setAlignment(Attr.Alignment); + BehavAttrs.setAmode(Attr.Amode); + BehavAttrs.setLinkageType(Attr.Linkage); + BehavAttrs.setBindingScope(Attr.BindingScope); + BehavAttrs.setDuplicateSymbolSeverity(Attr.DuplicateSymbolSeverity); + BehavAttrs.setReadOnly(Attr.IsReadOnly); + } +}; + class GOFFWriter { GOFFOstream OS; [[maybe_unused]] MCAssembler &Asm; + /// Mapping from MCSectionGOFF/MCSymbolGOFF to GOFF symbols and attributes. + GOFFSymbolMapper SymbolMapper; + + /// Counter for symbol id's. + uint32_t EsdIdCounter = 0; + + /// Id's of some special symbols. + uint32_t RootSDEsdId = 0; + uint32_t ADAEsdId = 0; + void writeHeader(); + void writeSymbol(const GOFFSymbol &Symbol); void writeEnd(); + GOFFSymbol createGOFFSymbol(StringRef Name, const SDAttr &Attr); + GOFFSymbol createGOFFSymbol(StringRef Name, const EDAttr &Attr, + uint32_t ParentEsdId); + GOFFSymbol createGOFFSymbol(StringRef Name, const LDAttr &Attr, + uint32_t ParentEsdId); + GOFFSymbol createGOFFSymbol(StringRef Name, const PRAttr &Attr, + uint32_t ParentEsdId); + + void defineRootSymbol(const MCSectionGOFF *Text); + void defineSectionSymbols(const MCSectionGOFF &Section); + void defineSymbols(); + public: GOFFWriter(raw_pwrite_stream &OS, MCAssembler &Asm); uint64_t writeObject(); @@ -237,7 +310,108 @@ class GOFFWriter { } // namespace GOFFWriter::GOFFWriter(raw_pwrite_stream &OS, MCAssembler &Asm) - : OS(OS), Asm(Asm) {} + : OS(OS), Asm(Asm), SymbolMapper(Asm) {} + +GOFFSymbol GOFFWriter::createGOFFSymbol(StringRef Name, const SDAttr &Attr) { + return GOFFSymbol(Name, ++EsdIdCounter, Attr); +} + +GOFFSymbol GOFFWriter::createGOFFSymbol(StringRef Name, const EDAttr &Attr, + uint32_t ParentEsdId) { + return GOFFSymbol(Name, ++EsdIdCounter, ParentEsdId, Attr); +} + +GOFFSymbol GOFFWriter::createGOFFSymbol(StringRef Name, const LDAttr &Attr, + uint32_t ParentEsdId) { + return GOFFSymbol(Name, ++EsdIdCounter, ParentEsdId, Attr); +} + +GOFFSymbol GOFFWriter::createGOFFSymbol(StringRef Name, const PRAttr &Attr, + uint32_t ParentEsdId) { + return GOFFSymbol(Name, ++EsdIdCounter, ParentEsdId, Attr); +} + +void GOFFWriter::defineRootSymbol(const MCSectionGOFF *Text) { + // There is always a text section except for DWARF unit tests. + SymbolMapper.determineRootSD(""); + GOFFSymbol RootSD = + createGOFFSymbol(SymbolMapper.getRootSDName(), SymbolMapper.getRootSD()); + writeSymbol(RootSD); + RootSDEsdId = RootSD.EsdId; +} + +void GOFFWriter::defineSectionSymbols(const MCSectionGOFF &Section) { + auto [GOFFSectionData, Found] = SymbolMapper.getSection(Section); + if (Found) { + uint32_t SDEsdId = RootSDEsdId; + if (!GOFFSectionData.IsSDRootSD) { + GOFFSymbol SD = createGOFFSymbol(GOFFSectionData.SDName, + GOFFSectionData.SDAttributes); + SDEsdId = SD.EsdId; + writeSymbol(SD); + } + + GOFFSymbol ED = createGOFFSymbol(GOFFSectionData.EDName, + GOFFSectionData.EDAttributes, SDEsdId); + if (GOFFSectionData.Tag == GOFFSectionData::None || + GOFFSectionData.Tag == GOFFSectionData::LD) { + ED.SectionLength = Asm.getSectionAddressSize(Section); + } + writeSymbol(ED); + + if (GOFFSectionData.Tag == GOFFSectionData::LD) { + GOFFSymbol LD = createGOFFSymbol(GOFFSectionData.LDorPRName, + GOFFSectionData.LDAttributes, ED.EsdId); + if (Section.isText()) + LD.ADAEsdId = ADAEsdId; + writeSymbol(LD); + } + + if (GOFFSectionData.Tag == GOFFSectionData::PR) { + GOFFSymbol PR = createGOFFSymbol(GOFFSectionData.LDorPRName, + GOFFSectionData.PRAttributes, ED.EsdId); + PR.SectionLength = Asm.getSectionAddressSize(Section); + if (Section.getName() == ".ada") { + // We cannot have a zero-length section for data. If we do, + // artificially inflate it. Use 2 bytes to avoid odd alignments. Note: + // if this is ever changed, you will need to update the code in + // SystemZAsmPrinter::emitCEEMAIN and SystemZAsmPrinter::emitCELQMAIN to + // generate -1 if there is no ADA + if (!PR.SectionLength) + PR.SectionLength = 2; + ADAEsdId = PR.EsdId; + } + writeSymbol(PR); + } + return; + } + // TODO It is possible to get here. This will be handled later. +} + +void GOFFWriter::defineSymbols() { + // Search for .text and .ada sections. These should be the first sections in + // the list, so the loop should be cheap. + MCSectionGOFF *Text = nullptr; + MCSectionGOFF *ADA = nullptr; + for (MCSection &S : Asm) { + if (S.getName() == ".text") + Text = &cast<MCSectionGOFF>(S); + if (S.getName() == ".ada") + ADA = &cast<MCSectionGOFF>(S); + } + defineRootSymbol(Text); + if (ADA) + defineSectionSymbols(*ADA); + if (Text) + defineSectionSymbols(*Text); + + // Process the other sections. + for (MCSection &S : Asm) { + auto &Section = cast<MCSectionGOFF>(S); + if (Text != &Section && ADA != &Section) + defineSectionSymbols(Section); + } +} void GOFFWriter::writeHeader() { OS.newRecord(GOFF::RT_HDR); @@ -253,6 +427,45 @@ void GOFFWriter::writeHeader() { OS.write_zeros(6); // Reserved } +void GOFFWriter::writeSymbol(const GOFFSymbol &Symbol) { + if (Symbol.Offset >= (((... [truncated] `````````` </details> https://github.com/llvm/llvm-project/pull/133799 _______________________________________________ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits