[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:37 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);
+    }
----------------
uweigand wrote:

This seems odd.  Why do we use the length of some random text section here?

https://github.com/llvm/llvm-project/pull/85851


More information about the llvm-commits mailing list