[llvm-branch-commits] [llvm] [GOFF] Add writing of section symbols (PR #133799)
via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Mon Mar 31 14:13:28 PDT 2025
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
More information about the llvm-branch-commits
mailing list