[llvm] [z/OS][GOFF] Implement support for writing ESD + TXT records by the GOFFObjectWriter (PR #85851)
Ulrich Weigand via llvm-commits
llvm-commits at lists.llvm.org
Fri Mar 22 06:51:35 PDT 2024
================
@@ -259,6 +633,411 @@ void GOFFObjectWriter::writeHeader() {
OS.write_zeros(6); // Reserved
}
+void GOFFObjectWriter::writeSymbol(const GOFFSymbol &Symbol,
+ const MCAsmLayout &Layout) {
+ uint32_t Offset = 0;
+ uint32_t Length = 0;
+ GOFF::ESDNameSpaceId NameSpaceId = GOFF::ESD_NS_ProgramManagementBinder;
+ Flags SymbolFlags;
+ uint8_t FillByteValue = 0;
+
+ Flags BehavAttrs[10] = {};
+ auto setAmode = [&BehavAttrs](GOFF::ESDAmode Amode) {
+ BehavAttrs[0].set(0, 8, Amode);
+ };
+ auto setRmode = [&BehavAttrs](GOFF::ESDRmode Rmode) {
+ BehavAttrs[1].set(0, 8, Rmode);
+ };
+ auto setTextStyle = [&BehavAttrs](GOFF::ESDTextStyle Style) {
+ BehavAttrs[2].set(0, 4, Style);
+ };
+ auto setBindingAlgorithm =
+ [&BehavAttrs](GOFF::ESDBindingAlgorithm Algorithm) {
+ BehavAttrs[2].set(4, 4, Algorithm);
+ };
+ auto setTaskingBehavior =
+ [&BehavAttrs](GOFF::ESDTaskingBehavior TaskingBehavior) {
+ BehavAttrs[3].set(0, 3, TaskingBehavior);
+ };
+ auto setReadOnly = [&BehavAttrs](bool ReadOnly) {
+ BehavAttrs[3].set(4, 1, ReadOnly);
+ };
+ auto setExecutable = [&BehavAttrs](GOFF::ESDExecutable Executable) {
+ BehavAttrs[3].set(5, 3, Executable);
+ };
+ auto setDuplicateSeverity =
+ [&BehavAttrs](GOFF::ESDDuplicateSymbolSeverity DSS) {
+ BehavAttrs[4].set(2, 2, DSS);
+ };
+ auto setBindingStrength = [&BehavAttrs](GOFF::ESDBindingStrength Strength) {
+ BehavAttrs[4].set(4, 4, Strength);
+ };
+ auto setLoadingBehavior = [&BehavAttrs](GOFF::ESDLoadingBehavior Behavior) {
+ BehavAttrs[5].set(0, 2, Behavior);
+ };
+ auto setIndirectReference = [&BehavAttrs](bool Indirect) {
+ uint8_t Value = Indirect ? 1 : 0;
+ BehavAttrs[5].set(3, 1, Value);
+ };
+ auto setBindingScope = [&BehavAttrs](GOFF::ESDBindingScope Scope) {
+ BehavAttrs[5].set(4, 4, Scope);
+ };
+ auto setLinkageType = [&BehavAttrs](GOFF::ESDLinkageType Type) {
+ BehavAttrs[6].set(2, 1, Type);
+ };
+ auto setAlignment = [&BehavAttrs](GOFF::ESDAlignment Alignment) {
+ BehavAttrs[6].set(3, 5, Alignment);
+ };
+
+ uint32_t AdaEsdId = 0;
+ uint32_t SortPriority = 0;
+
+ switch (Symbol.SymbolType) {
+ case GOFF::ESD_ST_SectionDefinition: {
+ if (Symbol.isExecutable()) // Unspecified otherwise
+ setTaskingBehavior(GOFF::ESD_TA_Rent);
+ if (Symbol.BindingScope == GOFF::ESD_BSC_Section)
+ setBindingScope(Symbol.BindingScope);
+ } break;
+ case GOFF::ESD_ST_ElementDefinition: {
+ SymbolFlags.set(3, 1, Symbol.isRemovable()); // Removable
+ if (Symbol.isExecutable()) {
+ setExecutable(GOFF::ESD_EXE_CODE);
+ setReadOnly(true);
+ } else {
+ if (Symbol.isExecUnspecified())
+ setExecutable(GOFF::ESD_EXE_Unspecified);
+ else
+ setExecutable(GOFF::ESD_EXE_DATA);
+
+ if (Symbol.isForceRent() || Symbol.isReadOnly()) // TODO
+ setReadOnly(true);
+ }
+ Offset = 0; // TODO ED and SD are 1-1 for now
+ setAlignment(Symbol.Alignment);
+ SymbolFlags.set(0, 1, 1); // Fill-Byte Value Presence Flag
+ FillByteValue = 0;
+ SymbolFlags.set(1, 1, 0); // Mangled Flag TODO ?
+ setAmode(Symbol.Amode);
+ setRmode(Symbol.Rmode);
+ setTextStyle(Symbol.TextStyle);
+ setBindingAlgorithm(Symbol.BindAlgorithm);
+ setLoadingBehavior(Symbol.LoadBehavior);
+ SymbolFlags.set(5, 3, GOFF::ESD_RQ_0); // Reserved Qwords
+ if (Symbol.isForceRent())
+ setReadOnly(true);
+ NameSpaceId = Symbol.NameSpace;
+ Length = Symbol.SectionLength;
+ break;
+ }
+ case GOFF::ESD_ST_LabelDefinition: {
+ if (Symbol.isExecutable())
+ setExecutable(GOFF::ESD_EXE_CODE);
+ else
+ setExecutable(GOFF::ESD_EXE_DATA);
+ setBindingStrength(Symbol.BindingStrength);
+ setLinkageType(Symbol.Linkage);
+ SymbolFlags.set(2, 1, Symbol.Renamable); // Renamable;
+ setAmode(Symbol.Amode);
+ NameSpaceId = Symbol.NameSpace;
+ setBindingScope(Symbol.BindingScope);
+ AdaEsdId = Symbol.ADAEsdId;
+
+ // Only symbol that doesn't have an MC is the SectionLabelSymbol which
+ // implicitly has 0 offset into the parent SD!
+ if (auto *MCSym = Symbol.MCSym) {
+ uint64_t Ofs = Layout.getSymbolOffset(*MCSym);
+ // We only have signed 32bits of offset!
+ assert(Ofs < (((uint64_t)1) << 31) && "ESD offset out of range.");
+ Offset = static_cast<uint32_t>(Ofs);
+ }
+ break;
+ }
+ case GOFF::ESD_ST_ExternalReference: {
+ setExecutable(Symbol.isExecutable() ? GOFF::ESD_EXE_CODE
+ : GOFF::ESD_EXE_DATA);
+ setBindingStrength(Symbol.BindingStrength);
+ setLinkageType(Symbol.Linkage);
+ SymbolFlags.set(2, 1, Symbol.Renamable); // Renamable;
+ setIndirectReference(Symbol.Indirect);
+ Offset = 0; // ERs don't do offsets
+ NameSpaceId = Symbol.NameSpace;
+ setBindingScope(Symbol.BindingScope);
+ setAmode(Symbol.Amode);
+ break;
+ }
+ case GOFF::ESD_ST_PartReference: {
+ setExecutable(Symbol.isExecutable() ? GOFF::ESD_EXE_CODE
+ : GOFF::ESD_EXE_DATA);
+ NameSpaceId = Symbol.NameSpace;
+ setAlignment(Symbol.Alignment);
+ setAmode(Symbol.Amode);
+ setLinkageType(Symbol.Linkage);
+ setBindingScope(Symbol.BindingScope);
+ SymbolFlags.set(2, 1, Symbol.Renamable); // Renamable;
+ setDuplicateSeverity(Symbol.isWeakRef() ? GOFF::ESD_DSS_NoWarning
+ : GOFF::ESD_DSS_Warning);
+ setIndirectReference(Symbol.Indirect);
+ setReadOnly(Symbol.ReadOnly);
+ SortPriority = Symbol.SortKey;
+
+ Length = Symbol.SectionLength;
+ break;
+ }
+ } // End switch
+
+ SmallString<256> Res;
+ ConverterEBCDIC::convertToEBCDIC(Symbol.Name, Res);
+ StringRef Name = Res.str();
+
+ // Assert here since this number is technically signed but we need uint for
+ // writing to records.
+ assert(Name.size() < GOFF::MaxDataLength &&
+ "Symbol max name length exceeded");
+ uint16_t NameLength = Name.size();
+
+ OS.newRecord(GOFF::RT_ESD, GOFF::ESDMetadataLength + NameLength);
+ OS.writebe<uint8_t>(Symbol.SymbolType); // Symbol Type
+ OS.writebe<uint32_t>(Symbol.EsdId); // ESDID
+ OS.writebe<uint32_t>(Symbol.ParentEsdId); // Parent or Owning ESDID
+ OS.writebe<uint32_t>(0); // Reserved
+ OS.writebe<uint32_t>(Offset); // Offset or Address
+ OS.writebe<uint32_t>(0); // Reserved
+ OS.writebe<uint32_t>(Length); // Length
+ OS.writebe<uint32_t>(Symbol.EASectionEsdId); // Extended Attribute ESDID
+ OS.writebe<uint32_t>(Symbol.EASectionOffset); // Extended Attribute Offset
+ OS.writebe<uint32_t>(0); // Reserved
+ OS.writebe<uint8_t>(NameSpaceId); // Name Space ID
+ OS.writebe<uint8_t>(SymbolFlags); // Flags
+ OS.writebe<uint8_t>(FillByteValue); // Fill-Byte Value
+ OS.writebe<uint8_t>(0); // Reserved
+ OS.writebe<uint32_t>(AdaEsdId); // ADA ESDID
+ OS.writebe<uint32_t>(SortPriority); // Sort Priority
+ OS.writebe<uint64_t>(0); // Reserved
+ for (auto F : BehavAttrs)
+ OS.writebe<uint8_t>(F); // Behavioral Attributes
+ OS.writebe<uint16_t>(NameLength); // Name Length
+ OS.write(Name.data(), NameLength); // Name
+}
+
+void GOFFObjectWriter::writeADAandCodeSectionSymbols(
+ MCAssembler &Asm, const MCAsmLayout &Layout) {
+ // Write ESD Records for ADA Section
+ GOFFSymbol ADAED = createWSASymbol(RootSD.EsdId, true);
+ StringRef FileName = "";
+ if (!Asm.getFileNames().empty())
+ FileName = sys::path::stem((*(Asm.getFileNames().begin())).first);
+ std::pair<std::string, std::string> CsectNames = Asm.getCsectNames();
+
+ GOFFSymbol ADA;
+ 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;
+
+ ADA.SectionLength = std::max(getADASectionLength(Asm, Layout), 2u);
+ writeSymbol(ADAED, Layout);
+ writeSymbol(ADA, Layout);
+
+ // Write ESD Records for Code Section
+ GOFFSymbol ED = createEDSymbol("C_CODE64", RootSD.EsdId);
+ ED.SectionLength = 0;
+ ED.Executable = GOFF::ESD_EXE_CODE;
+ ED.ForceRent = true;
+
+ for (const MCSection &MCSec : Asm) {
+ SectionKind Kind = MCSec.getKind();
+ if (Kind.isText()) {
+ if (!ED.SectionLength)
+ ED.SectionLength = Layout.getSectionAddressSize(&MCSec);
+ }
+ }
+
+ GOFFSymbol LD = createLDSymbol(RootSD.Name, ED.EsdId);
+ LD.Executable = GOFF::ESD_EXE_CODE;
+ if (RootSD.BindingScope == GOFF::ESD_BSC_Section)
+ LD.BindingScope = GOFF::ESD_BSC_Section;
+ else
+ LD.BindingScope = GOFF::ESD_BSC_Library;
+
+ LD.ADAEsdId = GOFFObjectWriter::ADAEsdId;
+
+ EntryEDEsdId = ED.EsdId;
+ CodeLDEsdId = LD.EsdId;
+ writeSymbol(ED, Layout);
+ writeSymbol(LD, Layout);
+}
+
+void GOFFObjectWriter::writeSectionSymbols(MCAssembler &Asm,
+ const MCAsmLayout &Layout) {
+ bool IsOSLinkageType = false;
+ for (MCSection &S : Asm) {
+ auto &Section = cast<MCSectionGOFF>(S);
+ SectionKind Kind = Section.getKind();
+
+ if (Kind.isText()) {
+ // The only text section is the code section and the relevant ESD Records
+ // are already created. All we need to do is populate the SectionMap.
+ uint32_t RootSDEsdId = RootSD.EsdId;
+
+ GOFFSection GoffSec = GOFFSection(EntryEDEsdId, CodeLDEsdId, RootSDEsdId);
+ SectionMap.insert(std::make_pair(&Section, GoffSec));
+ } else if (Section.getName().starts_with(".lsda")) {
+ GOFFSymbol SD = RootSD;
+
+ const char *WSAClassName = "C_WSA64";
+ GOFFSymbol ED = createEDSymbol(WSAClassName, SD.EsdId);
+ if (IsOSLinkageType)
+ ED.LoadBehavior = GOFF::ESDLoadingBehavior::ESD_LB_Deferred;
----------------
uweigand wrote:
This if is always false ... Is there a reason why the flags here should be different from all the other C_WSA64 ED symbols? Can't we use createWSASymbol here?
https://github.com/llvm/llvm-project/pull/85851
More information about the llvm-commits
mailing list