[llvm] [GOFF] Add writing text records to yaml2obj (PR #93863)
via llvm-commits
llvm-commits at lists.llvm.org
Thu May 30 12:03:58 PDT 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-objectyaml
Author: Kai Nacke (redstar)
<details>
<summary>Changes</summary>
- **[GOFF] Refactor writing GOFF records**
- **[GOFF] Add writing text records to yaml2obj**
---
Patch is 34.29 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/93863.diff
15 Files Affected:
- (modified) llvm/include/llvm/BinaryFormat/GOFF.h (+6)
- (modified) llvm/include/llvm/ObjectYAML/GOFFYAML.h (+91-12)
- (modified) llvm/lib/ObjectYAML/GOFFEmitter.cpp (+132-153)
- (modified) llvm/lib/ObjectYAML/GOFFYAML.cpp (+102-18)
- (removed) llvm/test/tools/yaml2obj/GOFF/GOFF-header-settings.yaml (-26)
- (removed) llvm/test/tools/yaml2obj/GOFF/GOFF-no-header.yaml (-7)
- (added) llvm/test/tools/yaml2obj/GOFF/end-amode-const.yaml (+15)
- (added) llvm/test/tools/yaml2obj/GOFF/end-long-name.yaml (+70)
- (added) llvm/test/tools/yaml2obj/GOFF/end-only.yaml (+22)
- (renamed) llvm/test/tools/yaml2obj/GOFF/header-end.yaml (+8-6)
- (added) llvm/test/tools/yaml2obj/GOFF/header-only.yaml (+18)
- (added) llvm/test/tools/yaml2obj/GOFF/invalid-record.yaml (+7)
- (added) llvm/test/tools/yaml2obj/GOFF/text-default.yaml (+15)
- (added) llvm/test/tools/yaml2obj/GOFF/text-only.yaml (+22)
- (added) llvm/test/tools/yaml2obj/GOFF/text-style-const.yaml (+15)
``````````diff
diff --git a/llvm/include/llvm/BinaryFormat/GOFF.h b/llvm/include/llvm/BinaryFormat/GOFF.h
index 443bcfc9479a8..9a5637d0abe5f 100644
--- a/llvm/include/llvm/BinaryFormat/GOFF.h
+++ b/llvm/include/llvm/BinaryFormat/GOFF.h
@@ -157,6 +157,12 @@ enum ESDAlignment : uint8_t {
ESD_ALIGN_4Kpage = 12,
};
+enum TXTRecordStyle : uint8_t {
+ TXT_TS_Byte = 0,
+ TXT_TS_Structured = 1,
+ TXT_TS_Unstructured = 2,
+};
+
enum ENDEntryPointRequest : uint8_t {
END_EPR_None = 0,
END_EPR_EsdidOffset = 1,
diff --git a/llvm/include/llvm/ObjectYAML/GOFFYAML.h b/llvm/include/llvm/ObjectYAML/GOFFYAML.h
index f9bf45e95bd3a..1308422b9d3fa 100644
--- a/llvm/include/llvm/ObjectYAML/GOFFYAML.h
+++ b/llvm/include/llvm/ObjectYAML/GOFFYAML.h
@@ -25,25 +25,104 @@ namespace llvm {
// to use yaml::IO, we use these structures which are closer to the source.
namespace GOFFYAML {
-struct FileHeader {
- uint32_t TargetEnvironment = 0;
- uint32_t TargetOperatingSystem = 0;
- uint16_t CCSID = 0;
- StringRef CharacterSetName;
- StringRef LanguageProductIdentifier;
- uint32_t ArchitectureLevel = 0;
- std::optional<uint16_t> InternalCCSID;
- std::optional<uint8_t> TargetSoftwareEnvironment;
+LLVM_YAML_STRONG_TYPEDEF(uint8_t, GOFF_AMODE)
+LLVM_YAML_STRONG_TYPEDEF(uint8_t, GOFF_TXTRECORDSTYLE)
+LLVM_YAML_STRONG_TYPEDEF(uint8_t, GOFF_ENDFLAGS)
+
+// The GOFF format uses different kinds of logical records. The format imposes
+// some rules on those records (e.g. the module header must come first, no
+// forward references to records, etc.). However, to be able to specify invalid
+// GOFF files, we treat all records the same way.
+struct RecordBase {
+ enum RecordBaseKind {
+ RBK_ModuleHeader,
+ RBK_RelocationDirectory,
+ RBK_Symbol,
+ RBK_Text,
+ RBK_DeferredLength,
+ RBK_EndOfModule
+ };
+
+private:
+ const RecordBaseKind Kind;
+
+protected:
+ RecordBase(RecordBaseKind Kind) : Kind(Kind) {}
+
+public:
+ RecordBaseKind getKind() const { return Kind; }
+};
+using RecordPtr = std::unique_ptr<RecordBase>;
+
+struct ModuleHeader : public RecordBase {
+ ModuleHeader() : RecordBase(RBK_ModuleHeader) {}
+
+ uint32_t ArchitectureLevel;
+ uint16_t PropertiesLength;
+ std::optional<yaml::BinaryRef> Properties;
+
+ static bool classof(const RecordBase *S) {
+ return S->getKind() == RBK_ModuleHeader;
+ }
+};
+
+struct Text : public RecordBase {
+ Text() : RecordBase(RBK_Text) {}
+
+ GOFF_TXTRECORDSTYLE Style;
+ uint32_t ESDID;
+ uint32_t Offset;
+ uint32_t TrueLength;
+ uint16_t Encoding;
+ uint16_t DataLength;
+ std::optional<yaml::BinaryRef> Data;
+
+ static bool classof(const RecordBase *S) { return S->getKind() == RBK_Text; }
+};
+
+struct EndOfModule : public RecordBase {
+ EndOfModule() : RecordBase(RBK_EndOfModule) {}
+
+ GOFF_ENDFLAGS Flags;
+ GOFF_AMODE AMODE;
+ uint32_t RecordCount;
+ uint32_t ESDID;
+ uint32_t Offset;
+ uint16_t NameLength;
+ StringRef EntryName;
+
+ static bool classof(const RecordBase *S) {
+ return S->getKind() == RBK_EndOfModule;
+ }
};
struct Object {
- FileHeader Header;
- Object();
+ // A GOFF file is a sequence of records.
+ std::vector<RecordPtr> Records;
};
} // end namespace GOFFYAML
} // end namespace llvm
-LLVM_YAML_DECLARE_MAPPING_TRAITS(GOFFYAML::FileHeader)
+LLVM_YAML_DECLARE_ENUM_TRAITS(GOFFYAML::GOFF_AMODE)
+LLVM_YAML_DECLARE_ENUM_TRAITS(GOFFYAML::GOFF_TXTRECORDSTYLE)
+LLVM_YAML_DECLARE_ENUM_TRAITS(GOFFYAML::GOFF_ENDFLAGS)
+
+LLVM_YAML_IS_SEQUENCE_VECTOR(GOFFYAML::RecordPtr)
+LLVM_YAML_DECLARE_MAPPING_TRAITS(GOFFYAML::RecordPtr)
+
+LLVM_YAML_DECLARE_MAPPING_TRAITS(GOFFYAML::ModuleHeader)
+LLVM_YAML_DECLARE_MAPPING_TRAITS(GOFFYAML::Text)
+LLVM_YAML_DECLARE_MAPPING_TRAITS(GOFFYAML::EndOfModule)
LLVM_YAML_DECLARE_MAPPING_TRAITS(GOFFYAML::Object)
+namespace llvm {
+namespace yaml {
+
+template <> struct CustomMappingTraits<GOFFYAML::RecordPtr> {
+ static void inputOne(IO &IO, StringRef Key, GOFFYAML::RecordPtr &Elem);
+ static void output(IO &IO, GOFFYAML::RecordPtr &Elem);
+};
+
+} // namespace yaml
+} // namespace llvm
#endif // LLVM_OBJECTYAML_GOFFYAML_H
diff --git a/llvm/lib/ObjectYAML/GOFFEmitter.cpp b/llvm/lib/ObjectYAML/GOFFEmitter.cpp
index 345904407e1d2..e8fa37dbbd1d8 100644
--- a/llvm/lib/ObjectYAML/GOFFEmitter.cpp
+++ b/llvm/lib/ObjectYAML/GOFFEmitter.cpp
@@ -11,11 +11,12 @@
///
//===----------------------------------------------------------------------===//
-#include "llvm/ADT/IndexedMap.h"
-#include "llvm/ObjectYAML/ObjectYAML.h"
+#include "llvm/BinaryFormat/GOFF.h"
+#include "llvm/ObjectYAML/GOFFYAML.h"
#include "llvm/ObjectYAML/yaml2obj.h"
#include "llvm/Support/ConvertEBCDIC.h"
#include "llvm/Support/Endian.h"
+#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
@@ -25,10 +26,10 @@ namespace {
// Common flag values on records.
enum {
// Flag: This record is continued.
- Rec_Continued = 1,
+ Rec_Continued = 1 << 0,
// Flag: This record is a continuation.
- Rec_Continuation = 1 << (8 - 6 - 1),
+ Rec_Continuation = 1 << 1,
};
template <typename ValueType> struct BinaryBeImpl {
@@ -62,119 +63,91 @@ ZerosImpl zeros(const size_t NumBytes) { return ZerosImpl{NumBytes}; }
// The GOFFOstream is responsible to write the data into the fixed physical
// records of the format. A user of this class announces the start of a new
-// logical record and the size of its payload. While writing the payload, the
-// physical records are created for the data. Possible fill bytes at the end of
-// a physical record are written automatically.
-class GOFFOstream : public raw_ostream {
+// logical record, and writes the full logical block. The physical records are
+// created while the content is written to the underlying stream. Possible fill
+// bytes at the end of a physical record are written automatically.
+// The implementation aims at simplicity, not speed.
+class GOFFOStream {
public:
- explicit GOFFOstream(raw_ostream &OS)
- : OS(OS), LogicalRecords(0), RemainingSize(0), NewLogicalRecord(false) {
- SetBufferSize(GOFF::PayloadLength);
- }
-
- ~GOFFOstream() { finalize(); }
+ explicit GOFFOStream(raw_ostream &OS)
+ : OS(OS), CurrentType(GOFF::RecordType(-1)) {}
- void makeNewRecord(GOFF::RecordType Type, size_t Size) {
- fillRecord();
- CurrentType = Type;
- RemainingSize = Size;
- if (size_t Gap = (RemainingSize % GOFF::PayloadLength))
- RemainingSize += GOFF::PayloadLength - Gap;
- NewLogicalRecord = true;
- ++LogicalRecords;
+ GOFFOStream &operator<<(StringRef Str) {
+ write(Str);
+ return *this;
}
- void finalize() { fillRecord(); }
-
- uint32_t logicalRecords() { return LogicalRecords; }
+ void newRecord(GOFF::RecordType Type) { CurrentType = Type; }
private:
// The underlying raw_ostream.
raw_ostream &OS;
- // The number of logical records emitted so far.
- uint32_t LogicalRecords;
-
- // The remaining size of this logical record, including fill bytes.
- size_t RemainingSize;
-
// The type of the current (logical) record.
GOFF::RecordType CurrentType;
- // Signals start of new record.
- bool NewLogicalRecord;
-
- // Return the number of bytes left to write until next physical record.
- // Please note that we maintain the total number of bytes left, not the
- // written size.
- size_t bytesToNextPhysicalRecord() {
- size_t Bytes = RemainingSize % GOFF::PayloadLength;
- return Bytes ? Bytes : GOFF::PayloadLength;
- }
-
// Write the record prefix of a physical record, using the current record
// type.
- static void writeRecordPrefix(raw_ostream &OS, GOFF::RecordType Type,
- size_t RemainingSize,
- uint8_t Flags = Rec_Continuation) {
- uint8_t TypeAndFlags = Flags | (Type << 4);
- if (RemainingSize > GOFF::RecordLength)
- TypeAndFlags |= Rec_Continued;
- OS << binaryBe(static_cast<unsigned char>(GOFF::PTVPrefix))
- << binaryBe(static_cast<unsigned char>(TypeAndFlags))
- << binaryBe(static_cast<unsigned char>(0));
- }
+ void writeRecordPrefix(uint8_t Flags);
- // Fill the last physical record of a logical record with zero bytes.
- void fillRecord() {
- assert((GetNumBytesInBuffer() <= RemainingSize) &&
- "More bytes in buffer than expected");
- size_t Remains = RemainingSize - GetNumBytesInBuffer();
- if (Remains) {
- assert((Remains < GOFF::RecordLength) &&
- "Attempting to fill more than one physical record");
- raw_ostream::write_zeros(Remains);
- }
- flush();
- assert(RemainingSize == 0 && "Not fully flushed");
- assert(GetNumBytesInBuffer() == 0 && "Buffer not fully empty");
- }
+ // Write a logical record.
+ void write(StringRef Str);
+};
- // See raw_ostream::write_impl.
- void write_impl(const char *Ptr, size_t Size) override {
- assert((RemainingSize >= Size) && "Attempt to write too much data");
- assert(RemainingSize && "Logical record overflow");
- if (!(RemainingSize % GOFF::PayloadLength)) {
- writeRecordPrefix(OS, CurrentType, RemainingSize,
- NewLogicalRecord ? 0 : Rec_Continuation);
- NewLogicalRecord = false;
- }
- assert(!NewLogicalRecord &&
- "New logical record not on physical record boundary");
-
- size_t Idx = 0;
- while (Size > 0) {
- size_t BytesToWrite = bytesToNextPhysicalRecord();
- if (BytesToWrite > Size)
- BytesToWrite = Size;
- OS.write(Ptr + Idx, BytesToWrite);
- Idx += BytesToWrite;
- Size -= BytesToWrite;
- RemainingSize -= BytesToWrite;
- if (Size) {
- writeRecordPrefix(OS, CurrentType, RemainingSize);
- }
- }
+void GOFFOStream::writeRecordPrefix(uint8_t Flags) {
+ uint8_t TypeAndFlags = Flags | (CurrentType << 4);
+ OS << binaryBe(static_cast<unsigned char>(GOFF::PTVPrefix))
+ << binaryBe(static_cast<unsigned char>(TypeAndFlags))
+ << binaryBe(static_cast<unsigned char>(0));
+}
+
+void GOFFOStream::write(StringRef Str) {
+ // The flags are determined by the flags of the prvious record, and by the
+ // remaining size of data.
+ uint8_t Flags = 0;
+ size_t Ptr = 0;
+ size_t Size = Str.size();
+ while (Size >= GOFF::RecordContentLength) {
+ if (Flags) {
+ Flags |= Rec_Continuation;
+ if (Size == GOFF::RecordContentLength)
+ Flags &= ~Rec_Continued;
+ } else
+ Flags |= (Size == GOFF::RecordContentLength) ? 0 : Rec_Continued;
+ writeRecordPrefix(Flags);
+ OS.write(&Str.data()[Ptr], GOFF::RecordContentLength);
+ Size -= GOFF::RecordContentLength;
+ Ptr += GOFF::RecordContentLength;
}
+ if (Size) {
+ Flags &= ~Rec_Continued;
+ writeRecordPrefix(Flags);
+ OS.write(&Str.data()[Ptr], Size);
+ OS.write_zeros(GOFF::RecordContentLength - Size);
+ }
+}
+
+// A LogicalRecord buffers the data of a record.
+class LogicalRecord : public raw_svector_ostream {
+ GOFFOStream &OS;
+ SmallVector<char, 0> Buffer;
+
+ void anchor() override {};
- // Return the current position within the stream, not counting the bytes
- // currently in the buffer.
- uint64_t current_pos() const override { return OS.tell(); }
+public:
+ LogicalRecord(GOFFOStream &OS) : raw_svector_ostream(Buffer), OS(OS) {}
+ ~LogicalRecord() override { OS << str(); }
+
+ LogicalRecord &operator<<(yaml::BinaryRef B) {
+ B.writeAsBinary(*this);
+ return *this;
+ }
};
class GOFFState {
- void writeHeader(GOFFYAML::FileHeader &FileHdr);
- void writeEnd();
+ void writeHeader(GOFFYAML::ModuleHeader &ModHdr);
+ void writeText(GOFFYAML::Text &Txt);
+ void writeEnd(GOFFYAML::EndOfModule &EndMod);
void reportError(const Twine &Msg) {
ErrHandler(Msg);
@@ -185,8 +158,6 @@ class GOFFState {
yaml::ErrorHandler ErrHandler)
: GW(OS), Doc(Doc), ErrHandler(ErrHandler), HasError(false) {}
- ~GOFFState() { GW.finalize(); }
-
bool writeObject();
public:
@@ -194,72 +165,80 @@ class GOFFState {
yaml::ErrorHandler ErrHandler);
private:
- GOFFOstream GW;
+ GOFFOStream GW;
GOFFYAML::Object &Doc;
yaml::ErrorHandler ErrHandler;
bool HasError;
};
-void GOFFState::writeHeader(GOFFYAML::FileHeader &FileHdr) {
- SmallString<16> CCSIDName;
- if (std::error_code EC =
- ConverterEBCDIC::convertToEBCDIC(FileHdr.CharacterSetName, CCSIDName))
- reportError("Conversion error on " + FileHdr.CharacterSetName);
- if (CCSIDName.size() > 16) {
- reportError("CharacterSetName too long");
- CCSIDName.resize(16);
- }
- SmallString<16> LangProd;
- if (std::error_code EC = ConverterEBCDIC::convertToEBCDIC(
- FileHdr.LanguageProductIdentifier, LangProd))
- reportError("Conversion error on " + FileHdr.LanguageProductIdentifier);
- if (LangProd.size() > 16) {
- reportError("LanguageProductIdentifier too long");
- LangProd.resize(16);
- }
+void GOFFState::writeHeader(GOFFYAML::ModuleHeader &ModHdr) {
+ GW.newRecord(GOFF::RT_HDR);
+ LogicalRecord LR(GW);
+ LR << zeros(45) // Reserved.
+ << binaryBe(ModHdr.ArchitectureLevel) // The architecture level.
+ << binaryBe(ModHdr.PropertiesLength) // Length of module properties.
+ << zeros(6); // Reserved.
+ if (ModHdr.Properties)
+ LR << *ModHdr.Properties; // Module properties.
+}
- GW.makeNewRecord(GOFF::RT_HDR, GOFF::PayloadLength);
- GW << binaryBe(FileHdr.TargetEnvironment) // TargetEnvironment
- << binaryBe(FileHdr.TargetOperatingSystem) // TargetOperatingSystem
- << zeros(2) // Reserved
- << binaryBe(FileHdr.CCSID) // CCSID
- << CCSIDName // CharacterSetName
- << zeros(16 - CCSIDName.size()) // Fill bytes
- << LangProd // LanguageProductIdentifier
- << zeros(16 - LangProd.size()) // Fill bytes
- << binaryBe(FileHdr.ArchitectureLevel); // ArchitectureLevel
- // The module propties are optional. Figure out if we need to write them.
- uint16_t ModPropLen = 0;
- if (FileHdr.TargetSoftwareEnvironment)
- ModPropLen = 3;
- else if (FileHdr.InternalCCSID)
- ModPropLen = 2;
- if (ModPropLen) {
- GW << binaryBe(ModPropLen) << zeros(6);
- if (ModPropLen >= 2)
- GW << binaryBe(FileHdr.InternalCCSID ? *FileHdr.InternalCCSID : 0);
- if (ModPropLen >= 3)
- GW << binaryBe(FileHdr.TargetSoftwareEnvironment
- ? *FileHdr.TargetSoftwareEnvironment
- : 0);
- }
+void GOFFState::writeText(GOFFYAML::Text &Txt) {
+ GW.newRecord(GOFF::RT_TXT);
+ LogicalRecord LR(GW);
+ LR << binaryBe(uint8_t(Txt.Style)) // Text record style.
+ << binaryBe(
+ Txt.ESDID) // ESDID of the element/part to which this data belongs.
+ << zeros(4) // Reserved.
+ << binaryBe(Txt.Offset) // Starting offset from element/part.
+ << binaryBe(Txt.TrueLength) // True length if encoded.
+ << binaryBe(Txt.Encoding) // Encoding.
+ << binaryBe(Txt.DataLength); // Total length of data.
+ if (Txt.Data)
+ LR << *Txt.Data; // Data.
+ else
+ LR << zeros(Txt.DataLength);
}
-void GOFFState::writeEnd() {
- GW.makeNewRecord(GOFF::RT_END, GOFF::PayloadLength);
- GW << binaryBe(uint8_t(0)) // No entry point
- << binaryBe(uint8_t(0)) // No AMODE
- << zeros(3) // Reserved
- << binaryBe(GW.logicalRecords());
- // No entry point yet. Automatically fill remaining space with zero bytes.
- GW.finalize();
+void GOFFState::writeEnd(GOFFYAML::EndOfModule &EndMod) {
+ SmallString<16> EntryName;
+ if (std::error_code EC =
+ ConverterEBCDIC::convertToEBCDIC(EndMod.EntryName, EntryName))
+ reportError("Conversion error on " + EndMod.EntryName);
+
+ GW.newRecord(GOFF::RT_END);
+ LogicalRecord LR(GW);
+ LR << binaryBe(uint8_t(EndMod.Flags)) // The flags.
+ << binaryBe(uint8_t(EndMod.AMODE)) // The addressing mode.
+ << zeros(3) // Reserved.
+ << binaryBe(EndMod.RecordCount) // The record count.
+ << binaryBe(EndMod.ESDID) // ESDID of the entry point.
+ << zeros(4) // Reserved.
+ << binaryBe(EndMod.Offset) // Offset of entry point.
+ << binaryBe(EndMod.NameLength) // Length of external name.
+ << EntryName; // Name of the entry point.
}
bool GOFFState::writeObject() {
- writeHeader(Doc.Header);
- if (HasError)
- return false;
- writeEnd();
+ for (auto &RecPtr : Doc.Records) {
+ auto *Rec = RecPtr.get();
+ switch (Rec->getKind()) {
+ case GOFFYAML::RecordBase::RBK_ModuleHeader:
+ writeHeader(*static_cast<GOFFYAML::ModuleHeader *>(Rec));
+ break;
+ case GOFFYAML::RecordBase::RBK_Text:
+ writeText(*static_cast<GOFFYAML::Text *>(Rec));
+ break;
+ case GOFFYAML::RecordBase::RBK_EndOfModule:
+ writeEnd(*static_cast<GOFFYAML::EndOfModule *>(Rec));
+ break;
+ case GOFFYAML::RecordBase::RBK_RelocationDirectory:
+ case GOFFYAML::RecordBase::RBK_Symbol:
+ case GOFFYAML::RecordBase::RBK_DeferredLength:
+ llvm_unreachable(("Not yet implemented"));
+ }
+ if (HasError)
+ return false;
+ }
return true;
}
diff --git a/llvm/lib/ObjectYAML/GOFFYAML.cpp b/llvm/lib/ObjectYAML/GOFFYAML.cpp
index ae857980a521b..d3c8b02bcb6a3 100644
--- a/llvm/lib/ObjectYAML/GOFFYAML.cpp
+++ b/llvm/lib/ObjectYAML/GOFFYAML.cpp
@@ -12,34 +12,118 @@
#include "llvm/ObjectYAML/GOFFYAML.h"
#include "llvm/BinaryFormat/GOFF.h"
-#include <string.h>
namespace llvm {
-namespace GOFFYAML {
-Object::Object() {}
+namespace yaml {
-} // namespace GOFFYAML
+void ScalarEnumerationTraits<GOFFYAML::GOFF_AMODE>::enumeration(
+ IO &IO, GOFFYAML::GOFF_AMODE &Value) {
+#define ECase(X) IO.enumCase(Value, #X, GOFF::ESD_##X)
+ ECase(AMODE_None);
+ ECase(AMODE_24);
+ ECase(AMODE_31);
+ ECase(AMODE_ANY);
+ ECase(AMODE_64);
+ ECase(AMODE_MIN);
+#undef ECase
+ IO.enumFallback<Hex8>(Value);
+}
-namespace yaml {
+void ScalarEnumerationTraits<GOFFYAML::GOFF_TXTRECORDSTYLE>::enumeration(
+ IO &IO, GOFFYAML::GOFF_TXTRECORDSTYLE &Value) {
+#define ECase(X) IO.enumCase(Value, #X, GOFF::TXT_##X)
+ ECase(TS_Byte);
+ ECase(TS_Structured);
+ ECase(TS_Unstructured);
+#undef ECase
+ IO.enumFallback<Hex8>(Value);
+}
+
+void ScalarEnumerationTraits<GOFFYAML::GOFF_ENDFLAGS>::enumeration(
+ IO &IO, GOFFYAML::GOFF_ENDFLAGS &Value) {
+#define ECase(X) IO.enumCase(Value, #X, unsigned(GOFF::END_##X) << 6)
+ ECase(EPR_None);
+ ECase(EPR_EsdidOffset);
+ ECase(EPR_ExternalName);
+ ECase(EPR_Reserved);
+#undef ECase
+ IO.enumFallback<Hex8>(Value);
+}
+
+void MappingTraits<GOFFYAML::ModuleHeader>::mapping(
+ IO &IO, GOFFYAML::ModuleHeader &ModHdr) {
+ IO.mapOptional("ArchitectureLevel", ModHdr.ArchitectureLevel, 0);
+ IO.mapOptional("PropertiesLength", ModHdr.PropertiesLength, 0);
+ IO.mapOptional("Properties", ModHdr.Properties);
+}
+
+void MappingTraits<GOFFYAML::Text>::mapping(IO &IO, GOFFYAML::Text &Txt) {
+ IO.mapOptional("TextStyle", Txt.Style, GOFF::TXT_TS_Byte);
+ IO.mapOptional("ESDID", Txt.ESDID, 0);
+ IO.mapOptional("Offset", Txt.Offset, 0);
+ IO.mapOptional("TrueLength", Txt.TrueLength, 0);
+ IO.mapOptional("TextEncoding", Txt.Encoding, 0);
+ IO.mapOptional("DataLength", Txt.DataLength, 0);
+ IO.mapOptional("Data", Txt.Data);
+}
+
+void MappingTraits<GOFFYAML::EndOfModule>::mapping(IO &IO,
+ GOFFYAML::EndOfModule &End) {
+ IO.mapOptional("Flags", End.Flags, 0);
+ IO.mapOptional("AMODE", End.AMODE, 0);
+ IO.mapOptional("RecordCount", End.RecordCount, 0);
+ IO.mapOptional("ESDID", End.ESDID, 0);
+ IO.mapOptional("Offset", End.Offset, 0);
+ IO.mapOptional("NameLength", End.NameLength, 0);
+ IO.mapOptional("EntryName", End.EntryName);
+}
+
+void CustomMappingTraits<GOFFYAML::RecordPtr>::inputOne(
+ IO &IO, StringRef Key, GOFFYAML::RecordPtr &Elem) {
+ if (Key == "ModuleHeader") {
+ GOFFYAML::ModuleHeader ModHdr;
+ IO.mapRequired("ModuleHeader", ModHdr);
+ Elem = std::make_unique<GOFFYAML::ModuleHeader>(std::move(ModHdr));
+ } else if (Key == "Text") {
+ GOFFYAML::Text Txt;
+ IO.mapRequired("Text", Txt);
+ Elem = std::make_unique<GOFFYAML::Text>(std::move(Txt));
+ } else if (Key ...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/93863
More information about the llvm-commits
mailing list