27#define DEBUG_TYPE "goff-writer"
63 char *BufferPtr = Buffer;
66 char Buffer[BufferSize];
78 uint32_t getNumLogicalRecords() {
return LogicalRecords; }
84 void write_zeros(
unsigned NumZeros);
87 template <
typename value_type>
void writebe(value_type
Value) {
90 write((
const char *)&
Value,
sizeof(value_type));
97 void finalizeRecord();
102 void updateFlagsAndWritePrefix(
bool IsContinued);
105 size_t getRemainingSize();
111GOFFOstream::~GOFFOstream() { finalizeRecord(); }
113void GOFFOstream::updateFlagsAndWritePrefix(
bool IsContinued) {
115 if (TypeAndFlags & RecContinued)
116 TypeAndFlags |= RecContinuation;
118 TypeAndFlags |= RecContinued;
120 TypeAndFlags &= ~RecContinued;
123 <<
static_cast<unsigned char>(TypeAndFlags)
124 <<
static_cast<unsigned char>(0);
129size_t GOFFOstream::getRemainingSize() {
130 return size_t(&Buffer[BufferSize] - BufferPtr);
133void GOFFOstream::write(
const char *
Ptr,
size_t Size) {
134 size_t RemainingSize = getRemainingSize();
145 updateFlagsAndWritePrefix(
true);
146 OS.
write(Buffer,
size_t(BufferPtr - Buffer));
147 if (RemainingSize > 0) {
149 Ptr += RemainingSize;
150 Size -= RemainingSize;
153 while (
Size > BufferSize) {
154 updateFlagsAndWritePrefix(
true);
162 BufferPtr = &Buffer[
Size];
165void GOFFOstream::write_zeros(
unsigned NumZeros) {
166 assert(NumZeros <= 16 &&
"Range for zeros too large");
169 size_t RemainingSize = getRemainingSize();
171 memset(BufferPtr, 0, NumZeros);
172 BufferPtr += NumZeros;
177 static char Zeros[16] = {
180 write(Zeros, NumZeros);
185 TypeAndFlags =
Type << 4;
189void GOFFOstream::finalizeRecord() {
190 if (Buffer == BufferPtr)
192 updateFlagsAndWritePrefix(
false);
193 OS.
write(Buffer,
size_t(BufferPtr - Buffer));
204 uint32_t ParentEsdId;
211 GOFF::BehavioralAttributes BehavAttrs;
212 GOFF::SymbolFlags SymbolFlags;
213 uint32_t SortKey = 0;
214 uint32_t SectionLength = 0;
215 uint32_t ADAEsdId = 0;
216 uint32_t EASectionEDEsdId = 0;
217 uint32_t EASectionOffset = 0;
218 uint8_t FillByteValue = 0;
220 GOFFSymbol() : EsdId(0), ParentEsdId(0) {}
222 GOFFSymbol(StringRef Name, uint32_t EsdID,
const GOFF::SDAttr &Attr)
229 GOFFSymbol(StringRef Name, uint32_t EsdID, uint32_t ParentEsdID,
230 const GOFF::EDAttr &Attr)
240 BehavAttrs.setRmode(Attr.
Rmode);
247 GOFFSymbol(StringRef Name, uint32_t EsdID, uint32_t ParentEsdID,
254 BehavAttrs.setLinkageType(Attr.
Linkage);
255 BehavAttrs.setAmode(Attr.
Amode);
259 GOFFSymbol(StringRef Name, uint32_t EsdID, uint32_t ParentEsdID,
260 const GOFF::EDAttr &EDAttr,
const GOFF::PRAttr &Attr)
265 BehavAttrs.setLinkageType(Attr.
Linkage);
267 BehavAttrs.setAlignment(EDAttr.
Alignment);
276 void writeSymbol(
const GOFFSymbol &Symbol);
277 void writeText(
const MCSectionGOFF *MC);
280 void defineSectionSymbols(
const MCSectionGOFF &Section);
281 void defineLabel(
const MCSymbolGOFF &Symbol);
282 void defineSymbols();
285 GOFFWriter(raw_pwrite_stream &OS, MCAssembler &Asm);
286 uint64_t writeObject();
290GOFFWriter::GOFFWriter(raw_pwrite_stream &OS, MCAssembler &Asm)
293void GOFFWriter::defineSectionSymbols(
const MCSectionGOFF &Section) {
308 MCSectionGOFF *Parent =
Section.getParent();
312 if (
Section.requiresNonZeroLength()) {
318 if (!PR.SectionLength)
319 PR.SectionLength = 2;
325void GOFFWriter::defineLabel(
const MCSymbolGOFF &Symbol) {
326 MCSectionGOFF &
Section =
static_cast<MCSectionGOFF &
>(
Symbol.getSection());
328 Section.getEDAttributes().NameSpace,
Symbol.getLDAttributes());
330 LD.ADAEsdId =
Symbol.getADA()->getOrdinal();
334void GOFFWriter::defineSymbols() {
335 unsigned Ordinal = 0;
337 for (MCSection &S : Asm) {
338 auto &
Section =
static_cast<MCSectionGOFF &
>(S);
340 defineSectionSymbols(Section);
344 for (
const MCSymbol &Sym :
Asm.symbols()) {
345 if (Sym.isTemporary())
347 auto &
Symbol =
static_cast<const MCSymbolGOFF &
>(Sym);
348 if (
Symbol.hasLDAttributes()) {
349 Symbol.setIndex(++Ordinal);
355void GOFFWriter::writeHeader() {
358 OS.writebe<uint32_t>(0);
359 OS.writebe<uint32_t>(0);
361 OS.writebe<uint16_t>(0);
364 OS.writebe<uint32_t>(1);
365 OS.writebe<uint16_t>(0);
369void GOFFWriter::writeSymbol(
const GOFFSymbol &Symbol) {
370 if (
Symbol.Offset >= (((uint64_t)1) << 31))
374 SmallString<256>
Name;
381 uint16_t NameLength =
Name.size();
384 OS.writebe<uint8_t>(
Symbol.SymbolType);
385 OS.writebe<uint32_t>(
Symbol.EsdId);
386 OS.writebe<uint32_t>(
Symbol.ParentEsdId);
387 OS.writebe<uint32_t>(0);
388 OS.writebe<uint32_t>(
389 static_cast<uint32_t
>(
Symbol.Offset));
390 OS.writebe<uint32_t>(0);
391 OS.writebe<uint32_t>(
Symbol.SectionLength);
392 OS.writebe<uint32_t>(
Symbol.EASectionEDEsdId);
393 OS.writebe<uint32_t>(
Symbol.EASectionOffset);
394 OS.writebe<uint32_t>(0);
395 OS.writebe<uint8_t>(
Symbol.NameSpace);
396 OS.writebe<uint8_t>(
Symbol.SymbolFlags);
397 OS.writebe<uint8_t>(
Symbol.FillByteValue);
398 OS.writebe<uint8_t>(0);
399 OS.writebe<uint32_t>(
Symbol.ADAEsdId);
400 OS.writebe<uint32_t>(
Symbol.SortKey);
401 OS.writebe<uint64_t>(0);
402 for (
auto F :
Symbol.BehavAttrs.Attr)
403 OS.writebe<uint8_t>(
F);
404 OS.writebe<uint16_t>(NameLength);
405 OS.write(
Name.data(), NameLength);
410class TextStream :
public raw_ostream {
419 char Buffer[BufferSize];
426 const uint32_t EsdId;
432 void write_impl(
const char *
Ptr,
size_t Size)
override;
434 uint64_t current_pos()
const override {
return Offset; }
437 explicit TextStream(GOFFOstream &OS, uint32_t EsdId,
439 : OS(OS),
Offset(0), EsdId(EsdId), RecordStyle(RecordStyle) {
440 SetBuffer(Buffer,
sizeof(Buffer));
443 ~TextStream() { flush(); }
447void TextStream::write_impl(
const char *
Ptr,
size_t Size) {
448 size_t WrittenLength = 0;
451 if (
Offset +
Size > std::numeric_limits<int32_t>::max())
454 while (WrittenLength <
Size) {
455 size_t ToWriteLength =
459 OS.writebe<uint8_t>(GOFF::Flags(4, 4, RecordStyle));
460 OS.writebe<uint32_t>(EsdId);
461 OS.writebe<uint32_t>(0);
462 OS.writebe<uint32_t>(
static_cast<uint32_t
>(
Offset));
463 OS.writebe<uint32_t>(0);
464 OS.writebe<uint16_t>(0);
465 OS.writebe<uint16_t>(ToWriteLength);
466 OS.write(
Ptr + WrittenLength, ToWriteLength);
468 WrittenLength += ToWriteLength;
473void GOFFWriter::writeText(
const MCSectionGOFF *Section) {
479 Asm.writeSectionData(S, Section);
482void GOFFWriter::writeEnd() {
490 OS.writebe<uint8_t>(GOFF::Flags(6, 2,
F));
491 OS.writebe<uint8_t>(AMODE);
496 OS.writebe<uint32_t>(0);
497 OS.writebe<uint32_t>(ESDID);
500uint64_t GOFFWriter::writeObject() {
505 for (
const MCSection &Section : Asm)
506 writeText(
static_cast<const MCSectionGOFF *
>(&Section));
514 <<
" logical records.");
516 return OS.getWrittenSize();
521 : TargetObjectWriter(
std::
move(MOTW)), OS(OS) {}
530std::unique_ptr<MCObjectWriter>
533 return std::make_unique<GOFFObjectWriter>(std::move(MOTW), OS);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
#define LLVM_LIKELY(EXPR)
This file provides utility functions for converting between EBCDIC-1047 and UTF-8.
This file declares the MCSectionGOFF class, which contains all of the necessary machine code sections...
This file contains the MCSymbolGOFF class.
GOFFObjectWriter(std::unique_ptr< MCGOFFObjectTargetWriter > MOTW, raw_pwrite_stream &OS)
uint64_t writeObject() override
Write the object file and returns the number of bytes written.
~GOFFObjectWriter() override
LLVM_ABI uint64_t getSectionAddressSize(const MCSection &Sec) const
GOFF::EDAttr getEDAttributes() const
unsigned getOrdinal() const
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM Value Representation.
raw_ostream & write_zeros(unsigned NumZeros)
write_zeros - Insert 'NumZeros' nulls.
raw_ostream & write(unsigned char C)
An abstract base class for streams implementations that also support a pwrite operation.
LLVM_ABI std::error_code convertToEBCDIC(StringRef Source, SmallVectorImpl< char > &Result)
constexpr uint8_t PayloadLength
constexpr uint16_t MaxDataLength
Maximum data length before starting a new card for RLD and TXT data.
constexpr uint8_t PTVPrefix
Prefix byte on every record. This indicates GOFF format.
constexpr uint8_t RecordLength
Length of the parts of a physical GOFF record.
@ ESD_NS_ProgramManagementBinder
@ ESD_ST_ElementDefinition
@ ESD_ST_SectionDefinition
value_type byte_swap(value_type value, endianness endian)
This is an optimization pass for GlobalISel generic memory operations.
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
std::unique_ptr< MCObjectWriter > createGOFFObjectWriter(std::unique_ptr< MCGOFFObjectTargetWriter > MOTW, raw_pwrite_stream &OS)
Construct a new GOFF writer instance.
LLVM_ABI Error write(MCStreamer &Out, ArrayRef< std::string > Inputs, OnCuIndexOverflow OverflowOptValue)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Implement std::hash so that hash_code can be used in STL containers.
GOFF::ESDReserveQwords ReservedQwords
GOFF::ESDAlignment Alignment
GOFF::ESDTextStyle TextStyle
GOFF::ESDLoadingBehavior LoadBehavior
GOFF::ESDNameSpaceId NameSpace
GOFF::ESDBindingAlgorithm BindAlgorithm
GOFF::ESDBindingStrength BindingStrength
GOFF::ESDExecutable Executable
GOFF::ESDBindingScope BindingScope
GOFF::ESDLinkageType Linkage
GOFF::ESDLinkageType Linkage
GOFF::ESDBindingScope BindingScope
GOFF::ESDExecutable Executable
GOFF::ESDTaskingBehavior TaskingBehavior
GOFF::ESDBindingScope BindingScope