[llvm] [SystemZ][z/OS] Implement executePostLayoutBinding for GOFFObjectWriter (PR #67868)
via llvm-commits
llvm-commits at lists.llvm.org
Fri Oct 6 12:28:24 PDT 2023
================
@@ -216,34 +220,471 @@ void GOFFOstream::write_impl(const char *Ptr, size_t Size) {
}
}
+/// \brief Wrapper class for symbols used exclusively for the symbol table in a
+/// GOFF file.
+class GOFFSymbol {
+public:
+ std::string Name;
+ uint32_t EsdId;
+ uint32_t ParentEsdId;
+ const MCSymbolGOFF *MCSym;
+ GOFF::ESDSymbolType SymbolType;
+
+ GOFF::ESDNameSpaceId NameSpace = GOFF::ESD_NS_NormalName;
+ GOFF::ESDAmode Amode = GOFF::ESD_AMODE_64;
+ GOFF::ESDRmode Rmode = GOFF::ESD_RMODE_64;
+ GOFF::ESDLinkageType Linkage = GOFF::ESD_LT_XPLink;
+ GOFF::ESDExecutable Executable = GOFF::ESD_EXE_Unspecified;
+ GOFF::ESDAlignment Alignment = GOFF::ESD_ALIGN_Byte;
+ GOFF::ESDTextStyle TextStyle = GOFF::ESD_TS_ByteOriented;
+ GOFF::ESDBindingAlgorithm BindAlgorithm = GOFF::ESD_BA_Concatenate;
+ GOFF::ESDLoadingBehavior LoadBehavior = GOFF::ESD_LB_Initial;
+ GOFF::ESDBindingScope BindingScope = GOFF::ESD_BSC_Unspecified;
+ GOFF::ESDBindingStrength BindingStrength = GOFF::ESD_BST_Strong;
+ uint32_t SortKey = 0;
+ uint32_t SectionLength = 0;
+ uint32_t ADAEsdId = 0;
+ bool Indirect = false;
+ bool ForceRent = false;
+ bool Renamable = false;
+ bool ReadOnly = false;
+ uint32_t EASectionEsdId = 0;
+ uint32_t EASectionOffset = 0;
+
+ GOFFSymbol(StringRef Name, GOFF::ESDSymbolType Type, uint32_t EsdID,
+ uint32_t ParentEsdID)
+ : Name(Name.data(), Name.size()), EsdId(EsdID), ParentEsdId(ParentEsdID),
+ MCSym(nullptr), SymbolType(Type) {}
+
+ bool isForceRent() const { return ForceRent; }
+ bool isReadOnly() const { return ReadOnly; }
+ bool isRemovable() const { return false; }
+ bool isExecutable() const { return Executable == GOFF::ESD_EXE_CODE; }
+ bool isExecUnspecified() const {
+ return Executable == GOFF::ESD_EXE_Unspecified;
+ }
+ bool isWeakRef() const { return BindingStrength == GOFF::ESD_BST_Weak; }
+ bool isExternal() const {
+ return (BindingScope == GOFF::ESD_BSC_Library) ||
+ (BindingScope == GOFF::ESD_BSC_ImportExport);
+ }
+
+ void setAlignment(Align A) {
+ // The GOFF alignment is encoded as log_2 value.
+ uint8_t Log = Log2(A);
+ if (Log <= GOFF::ESD_ALIGN_4Kpage)
+ Alignment = static_cast<GOFF::ESDAlignment>(Log);
+ else
+ llvm_unreachable("Unsupported alignment");
+ }
+
+ void setMaxAlignment(Align A) {
+ GOFF::ESDAlignment CurrAlign = Alignment;
+ setAlignment(A);
+ if (CurrAlign > Alignment)
+ Alignment = CurrAlign;
+ }
+};
+
+/// \brief Wrapper class for sections used exclusively for representing sections
+/// of the GOFF output that have actual bytes. This could be a ED or a PR.
+/// Relocations will always have a P-pointer to the ESDID of one of these.
+class GOFFSection {
+public:
+ GOFFSymbol *Pptr = nullptr;
+ GOFFSymbol *Rptr = nullptr;
+ GOFFSymbol *SD = nullptr;
+ const MCSectionGOFF *MCSec = nullptr;
+ bool IsStructured = false;
+
+ GOFFSection(GOFFSymbol *Pptr, GOFFSymbol *Rptr, GOFFSymbol *SD,
+ const MCSectionGOFF *MCSec)
+ : Pptr(Pptr), Rptr(Rptr), SD(SD), MCSec(MCSec), IsStructured(false) {}
+};
+
class GOFFObjectWriter : public MCObjectWriter {
+ typedef std::vector<std::unique_ptr<GOFFSymbol>> SymbolListType;
+ typedef DenseMap<MCSymbol const *, GOFFSymbol *> SymbolMapType;
+ typedef std::vector<std::unique_ptr<GOFFSection>> SectionListType;
+ typedef DenseMap<MCSection const *, GOFFSection *> SectionMapType;
+
// The target specific GOFF writer instance.
std::unique_ptr<MCGOFFObjectTargetWriter> TargetObjectWriter;
+ /// The symbol table for a GOFF file. It is order sensitive.
+ SymbolListType EsdSymbols;
+
+ /// Lookup table for MCSymbols to GOFFSymbols. Needed to determine EsdIds
+ /// of symbols in Relocations.
+ SymbolMapType SymbolMap;
+
+ /// The list of sections for the GOFF file.
+ SectionListType Sections;
+
+ /// Lookup table for MCSections to GOFFSections. Needed to determine
+ /// SymbolType on GOFFSymbols that reside in GOFFSections.
+ SectionMapType SectionMap;
+
// The stream used to write the GOFF records.
GOFFOstream OS;
+ uint32_t EsdCounter = 1;
+
+ GOFFSymbol *RootSD = nullptr;
+ GOFFSymbol *CodeLD = nullptr;
+ GOFFSymbol *ADA = nullptr;
+ bool HasADA = false;
+
public:
GOFFObjectWriter(std::unique_ptr<MCGOFFObjectTargetWriter> MOTW,
raw_pwrite_stream &OS)
: TargetObjectWriter(std::move(MOTW)), OS(OS) {}
~GOFFObjectWriter() override {}
+private:
// Write GOFF records.
void writeHeader();
+
+ void writeSymbol(const GOFFSymbol &Symbol, const MCAsmLayout &Layout);
+ void writeText(const GOFFSection &Section, const MCAssembler &Asm,
+ const MCAsmLayout &Layout);
+
void writeEnd();
+public:
// Implementation of the MCObjectWriter interface.
void recordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout,
const MCFragment *Fragment, const MCFixup &Fixup,
MCValue Target, uint64_t &FixedValue) override {}
void executePostLayoutBinding(MCAssembler &Asm,
- const MCAsmLayout &Layout) override {}
+ const MCAsmLayout &Layout) override;
uint64_t writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) override;
+
+private:
+ GOFFSection *createGOFFSection(GOFFSymbol *Pptr, GOFFSymbol *Rptr,
+ GOFFSymbol *SD, const MCSectionGOFF *MC);
+ GOFFSymbol *createGOFFSymbol(StringRef Name, GOFF::ESDSymbolType Type,
+ uint32_t ParentEsdId);
+ GOFFSymbol *createSDSymbol(StringRef Name);
+ GOFFSymbol *createEDSymbol(StringRef Name, uint32_t ParentEsdId);
+ GOFFSymbol *createLDSymbol(StringRef Name, uint32_t ParentEsdId);
+ GOFFSymbol *createERSymbol(StringRef Name, uint32_t ParentEsdId,
+ const MCSymbolGOFF *Source = nullptr);
+ GOFFSymbol *createPRSymbol(StringRef Name, uint32_t ParentEsdId);
+
+ GOFFSymbol *createWSASymbol(uint32_t ParentEsdId);
+ void defineRootAndADASD(MCAssembler &Asm);
+ void defineSectionSymbols(const MCAssembler &Asm,
+ const MCSectionGOFF &Section,
+ const MCAsmLayout &Layout);
+ void processSymbolDefinedInModule(const MCSymbolGOFF &MCSymbol,
+ const MCAssembler &Asm,
+ const MCAsmLayout &Layout);
+ void processSymbolDeclaredInModule(const MCSymbolGOFF &Symbol);
};
} // end anonymous namespace
+GOFFSection *GOFFObjectWriter::createGOFFSection(GOFFSymbol *Pptr,
+ GOFFSymbol *Rptr,
+ GOFFSymbol *SD,
+ const MCSectionGOFF *MC) {
+ Sections.push_back(std::make_unique<GOFFSection>(Pptr, Rptr, SD, MC));
+
+ return Sections.back().get();
+}
+
+GOFFSymbol *GOFFObjectWriter::createGOFFSymbol(StringRef Name,
+ GOFF::ESDSymbolType Type,
+ uint32_t ParentEsdId) {
+ EsdSymbols.push_back(
+ std::make_unique<GOFFSymbol>(Name, Type, EsdCounter, ParentEsdId));
+ ++EsdCounter;
+ return EsdSymbols.back().get();
+}
+
+GOFFSymbol *GOFFObjectWriter::createSDSymbol(StringRef Name) {
+ return createGOFFSymbol(Name, GOFF::ESD_ST_SectionDefinition, 0);
+}
+
+GOFFSymbol *GOFFObjectWriter::createEDSymbol(StringRef Name,
+ uint32_t ParentEsdId) {
+ GOFFSymbol *ED =
+ createGOFFSymbol(Name, GOFF::ESD_ST_ElementDefinition, ParentEsdId);
+
+ ED->Alignment = GOFF::ESD_ALIGN_Doubleword;
+ return ED;
+}
+
+GOFFSymbol *GOFFObjectWriter::createLDSymbol(StringRef Name,
+ uint32_t ParentEsdId) {
+ return createGOFFSymbol(Name, GOFF::ESD_ST_LabelDefinition, ParentEsdId);
+}
+
+GOFFSymbol *GOFFObjectWriter::createERSymbol(StringRef Name,
+ uint32_t ParentEsdId,
+ const MCSymbolGOFF *Source) {
+ GOFFSymbol *ER =
+ createGOFFSymbol(Name, GOFF::ESD_ST_ExternalReference, ParentEsdId);
+
+ if (Source) {
+ ER->Linkage = GOFF::ESDLinkageType::ESD_LT_XPLink;
+ ER->Executable = Source->getExecutable();
+ ER->BindingScope = Source->isExternal()
+ ? GOFF::ESDBindingScope::ESD_BSC_Library
+ : GOFF::ESDBindingScope::ESD_BSC_Section;
+ ER->BindingStrength = Source->isWeak()
+ ? GOFF::ESDBindingStrength::ESD_BST_Weak
+ : GOFF::ESDBindingStrength::ESD_BST_Strong;
+ }
+
+ return ER;
+}
+
+GOFFSymbol *GOFFObjectWriter::createPRSymbol(StringRef Name,
+ uint32_t ParentEsdId) {
+ return createGOFFSymbol(Name, GOFF::ESD_ST_PartReference, ParentEsdId);
+}
+
+GOFFSymbol *GOFFObjectWriter::createWSASymbol(uint32_t ParentEsdId) {
+ const char *WSAClassName = "C_WSA64";
+ GOFFSymbol *WSA = createEDSymbol(WSAClassName, ParentEsdId);
+
+ WSA->Executable = GOFF::ESD_EXE_DATA;
+ WSA->TextStyle = GOFF::ESD_TS_ByteOriented;
+ WSA->BindAlgorithm = GOFF::ESD_BA_Merge;
+ WSA->Alignment = GOFF::ESD_ALIGN_Quadword;
+ WSA->LoadBehavior = GOFF::ESD_LB_Deferred;
+ WSA->NameSpace = GOFF::ESD_NS_Parts;
+ WSA->SectionLength = 0;
+
+ return WSA;
+}
+
+void GOFFObjectWriter::defineRootAndADASD(MCAssembler &Asm) {
+ assert(!RootSD && !ADA && "SD already initialzed");
+ StringRef FileName = "";
+ if (Asm.getFileNames().size())
+ FileName = sys::path::stem((*(Asm.getFileNames().begin())).first);
+ std::pair<std::string, std::string> CsectNames = Asm.getCsectNames();
+ if (CsectNames.first.empty()) {
+ RootSD = createSDSymbol(FileName.str().append("#C"));
+ RootSD->BindingScope = GOFF::ESD_BSC_Section;
+ } else {
+ RootSD = createSDSymbol(CsectNames.first);
+ }
+ RootSD->Executable = GOFF::ESD_EXE_CODE;
+
+ GOFFSymbol *ADAED = createWSASymbol(RootSD->EsdId);
+ if (CsectNames.second.empty()) {
+ ADA = createPRSymbol(FileName.str().append("#S"), ADAED->EsdId);
+ ADA->BindingScope = GOFF::ESD_BSC_Section;
+ } else {
+ ADA = createPRSymbol(CsectNames.second, ADAED->EsdId);
+ ADA->BindingScope = GOFF::ESD_BSC_Library;
+ }
+ ADA->Executable = GOFF::ESD_EXE_DATA;
+ ADA->NameSpace = GOFF::ESD_NS_Parts;
+ ADA->Alignment = GOFF::ESD_ALIGN_Quadword;
+ // The ADA Section length can increase after this point. The final ADA
+ // length is assigned in populateADASection().
+ // We need to be careful, because a value of 0 causes issues with function
+ // labels. In populateADASection(), we make sure that the ADA content is
+ // defined before createing function labels.
+ ADA->SectionLength = 0;
+ // Assume there is an ADA.
+ HasADA = true;
+}
+
+void GOFFObjectWriter::defineSectionSymbols(const MCAssembler &Asm,
+ const MCSectionGOFF &Section,
+ const MCAsmLayout &Layout) {
+ GOFFSection *GSection = nullptr;
+ SectionKind Kind = Section.getKind();
+
+ if (Kind.isText()) {
+ GOFFSymbol *SD = RootSD;
+ const char *CodeClassName = "C_CODE64";
+ GOFFSymbol *ED = createEDSymbol(CodeClassName, SD->EsdId);
+ GOFFSymbol *LD = createLDSymbol(SD->Name, ED->EsdId);
+
+ ED->SectionLength = Layout.getSectionAddressSize(&Section);
+ ED->Executable = GOFF::ESD_EXE_CODE;
+ ED->ForceRent = true;
+
+ LD->Executable = GOFF::ESD_EXE_CODE;
+ if (SD->BindingScope == GOFF::ESD_BSC_Section) {
+ LD->BindingScope = GOFF::ESD_BSC_Section;
+ } else {
+ LD->BindingScope = GOFF::ESD_BSC_Library;
+ }
+
+ CodeLD = LD;
+
+ GSection = createGOFFSection(ED, LD, SD, &Section);
+ } else if (Section.getName().equals(".ada")) {
+ // Symbols already defined in defineRootAndADASD, nothing to do.
+ ADA->SectionLength = Layout.getSectionAddressSize(&Section);
+ if (ADA->SectionLength)
+ CodeLD->ADAEsdId = ADA->EsdId;
+ else {
+ // We cannot have a zero-length section for data. If we do, artificially
+ // inflate it. Use 2 bytes to avoid odd alignments.
+ ADA->SectionLength = 2;
+ HasADA = false;
+ }
+ GSection = createGOFFSection(ADA, ADA, RootSD, &Section);
+ } else if (Kind.isBSS() || Kind.isData()) {
+ // Statics and globals that are defined.
+ StringRef SectionName = Section.getName();
+ GOFFSymbol *SD = createSDSymbol(SectionName);
+
+ // Determine if static/global variable is marked with the norent attribute.
+ MCContext &Ctx = Asm.getContext();
+ auto *Sym = cast_or_null<MCSymbolGOFF>(Ctx.lookupSymbol(SectionName));
+
+ if (Sym) {
+ GOFFSymbol *ED = createWSASymbol(SD->EsdId);
+ GOFFSymbol *PR = createPRSymbol(SectionName, ED->EsdId);
+ ED->Alignment =
+ std::max(static_cast<GOFF::ESDAlignment>(Log2(Section.getAlign())),
+ GOFF::ESD_ALIGN_Quadword);
+
+ PR->Executable = GOFF::ESD_EXE_DATA;
+ PR->NameSpace = GOFF::ESD_NS_Parts;
+
+ GSection = createGOFFSection(PR, PR, SD, &Section);
+ }
+ } else
+ llvm_unreachable("Unhandled section kind");
+
+ SectionMap[&Section] = GSection;
+}
+
+void GOFFObjectWriter::processSymbolDefinedInModule(
+ const MCSymbolGOFF &MCSymbol, const MCAssembler &Asm,
+ const MCAsmLayout &Layout) {
+ MCSection &Section = MCSymbol.getSection();
+ SectionKind Kind = Section.getKind();
+ auto &Sec = cast<MCSectionGOFF>(Section);
+
+ GOFFSection *GSection = SectionMap[&Sec];
+ assert(GSection && "No corresponding section found");
+
+ GOFFSymbol *GSectionSym = GSection->Pptr;
+ assert(GSectionSym &&
+ "Defined symbols must exist in an initialized GSection");
+
+ StringRef SymbolName = MCSymbol.getName();
+ // If it's a text section, then create a label for it.
+ if (Kind.isText()) {
+ GOFFSymbol *LD = createLDSymbol(SymbolName, GSectionSym->EsdId);
+ LD->BindingStrength = MCSymbol.isWeak()
+ ? GOFF::ESDBindingStrength::ESD_BST_Weak
+ : GOFF::ESDBindingStrength::ESD_BST_Strong;
+
+ // If we don't know if it is code or data, assume it is code.
+ LD->Executable = MCSymbol.getExecutable();
+ if (LD->isExecUnspecified())
+ LD->Executable = GOFF::ESD_EXE_CODE;
+
+ // Determine the binding scope. Please note that the combination
+ // !isExternal && isExported makes no sense.
+ LD->BindingScope = MCSymbol.isExternal()
+ ? (MCSymbol.isExported()
+ ? GOFF::ESD_BSC_ImportExport
+ : (LD->isExecutable() ? GOFF::ESD_BSC_Library
+ : GOFF::ESD_BSC_Module))
+ : GOFF::ESD_BSC_Section;
+
+ if (ADA && ADA->SectionLength > 0)
+ LD->ADAEsdId = ADA->EsdId;
+ else
+ LD->ADAEsdId = 0;
+
+ GSectionSym->setMaxAlignment(MCSymbol.getAlignment());
+
+ LD->MCSym = &MCSymbol;
+ SymbolMap[&MCSymbol] = LD;
+ } else if (Kind.isBSS() || Kind.isData()) {
+ GSectionSym = GSection->Rptr;
+ GSectionSym->BindingScope =
----------------
diggerlin wrote:
do you want to add an assert here before using it?
https://github.com/llvm/llvm-project/pull/67868
More information about the llvm-commits
mailing list