29#define DEBUG_TYPE "goff-writer"
65 char *BufferPtr = Buffer;
68 char Buffer[BufferSize];
80 uint32_t getNumLogicalRecords() {
return LogicalRecords; }
86 void write_zeros(
unsigned NumZeros);
89 template <
typename value_type>
void writebe(value_type
Value) {
92 write((
const char *)&
Value,
sizeof(value_type));
99 void finalizeRecord();
104 void updateFlagsAndWritePrefix(
bool IsContinued);
107 size_t getRemainingSize();
113GOFFOstream::~GOFFOstream() { finalizeRecord(); }
115void GOFFOstream::updateFlagsAndWritePrefix(
bool IsContinued) {
117 if (TypeAndFlags & RecContinued)
118 TypeAndFlags |= RecContinuation;
120 TypeAndFlags |= RecContinued;
122 TypeAndFlags &= ~RecContinued;
125 <<
static_cast<unsigned char>(TypeAndFlags)
126 <<
static_cast<unsigned char>(0);
131size_t GOFFOstream::getRemainingSize() {
132 return size_t(&Buffer[BufferSize] - BufferPtr);
135void GOFFOstream::write(
const char *Ptr,
size_t Size) {
136 size_t RemainingSize = getRemainingSize();
140 memcpy(BufferPtr, Ptr,
Size);
147 updateFlagsAndWritePrefix(
true);
148 OS.
write(Buffer,
size_t(BufferPtr - Buffer));
149 if (RemainingSize > 0) {
150 OS.
write(Ptr, RemainingSize);
151 Ptr += RemainingSize;
152 Size -= RemainingSize;
155 while (
Size > BufferSize) {
156 updateFlagsAndWritePrefix(
true);
157 OS.
write(Ptr, BufferSize);
163 memcpy(Buffer, Ptr,
Size);
164 BufferPtr = &Buffer[
Size];
167void GOFFOstream::write_zeros(
unsigned NumZeros) {
168 assert(NumZeros <= 16 &&
"Range for zeros too large");
171 size_t RemainingSize = getRemainingSize();
173 memset(BufferPtr, 0, NumZeros);
174 BufferPtr += NumZeros;
179 static char Zeros[16] = {
182 write(Zeros, NumZeros);
187 TypeAndFlags =
Type << 4;
191void GOFFOstream::finalizeRecord() {
192 if (Buffer == BufferPtr)
194 updateFlagsAndWritePrefix(
false);
195 OS.
write(Buffer,
size_t(BufferPtr - Buffer));
206 uint32_t ParentEsdId;
213 GOFF::BehavioralAttributes BehavAttrs;
214 GOFF::SymbolFlags SymbolFlags;
215 uint32_t SortKey = 0;
216 uint32_t SectionLength = 0;
217 uint32_t ADAEsdId = 0;
218 uint32_t EASectionEDEsdId = 0;
219 uint32_t EASectionOffset = 0;
220 uint8_t FillByteValue = 0;
222 GOFFSymbol() : EsdId(0), ParentEsdId(0) {}
224 GOFFSymbol(StringRef Name, uint32_t EsdID,
const GOFF::SDAttr &Attr)
231 GOFFSymbol(StringRef Name, uint32_t EsdID, uint32_t ParentEsdID,
232 const GOFF::EDAttr &Attr)
242 BehavAttrs.setRmode(Attr.
Rmode);
249 GOFFSymbol(StringRef Name, uint32_t EsdID, uint32_t ParentEsdID,
256 BehavAttrs.setLinkageType(Attr.
Linkage);
257 BehavAttrs.setAmode(Attr.
Amode);
261 GOFFSymbol(StringRef Name, uint32_t EsdID, uint32_t ParentEsdID,
262 const GOFF::EDAttr &EDAttr,
const GOFF::PRAttr &Attr)
267 BehavAttrs.setLinkageType(Attr.
Linkage);
269 BehavAttrs.setAlignment(EDAttr.
Alignment);
272 GOFFSymbol(StringRef Name, uint32_t EsdID, uint32_t ParentEsdID,
273 const GOFF::ERAttr &Attr)
279 BehavAttrs.setLinkageType(Attr.
Linkage);
280 BehavAttrs.setAmode(Attr.
Amode);
289 MCSectionGOFF *RootSD;
292 std::vector<GOFFRelocationEntry> &Relocations;
295 void writeSymbol(
const GOFFSymbol &Symbol);
296 void writeText(
const MCSectionGOFF *MC);
297 void writeRelocations();
300 void defineSectionSymbols(
const MCSectionGOFF &Section);
301 void defineLabel(
const MCSymbolGOFF &Symbol);
302 void defineExtern(
const MCSymbolGOFF &Symbol);
303 void defineSymbols();
306 GOFFWriter(raw_pwrite_stream &OS, MCAssembler &Asm, MCSectionGOFF *RootSD,
307 std::vector<GOFFRelocationEntry> &Relocations);
308 uint64_t writeObject();
312GOFFWriter::GOFFWriter(raw_pwrite_stream &OS, MCAssembler &Asm,
313 MCSectionGOFF *RootSD,
314 std::vector<GOFFRelocationEntry> &Relocations)
315 : OS(OS),
Asm(
Asm), RootSD(RootSD), Relocations(Relocations) {}
317void GOFFWriter::defineSectionSymbols(
const MCSectionGOFF &Section) {
332 MCSectionGOFF *Parent =
Section.getParent();
337 if (
Section.requiresNonZeroLength()) {
343 if (!PR.SectionLength)
344 PR.SectionLength = 2;
350void GOFFWriter::defineLabel(
const MCSymbolGOFF &Symbol) {
351 MCSectionGOFF &
Section =
static_cast<MCSectionGOFF &
>(
Symbol.getSection());
354 GOFF::LDAttr{false, Symbol.getCodeData(),
355 Symbol.getBindingStrength(), Symbol.getLinkage(),
356 GOFF::ESD_AMODE_64, Symbol.getBindingScope()});
358 LD.ADAEsdId =
Symbol.getADA()->getOrdinal();
363void GOFFWriter::defineExtern(
const MCSymbolGOFF &Symbol) {
365 MCSectionGOFF *ED =
Symbol.getADA()->getParent();
368 GOFF::PRAttr{ false, Symbol.getCodeData(),
369 Symbol.getLinkage(), Symbol.getBindingScope(),
373 GOFFSymbol ER(
Symbol.getExternalName(),
Symbol.getIndex(),
375 GOFF::ERAttr{Symbol.isIndirect(), Symbol.getCodeData(),
376 Symbol.getBindingStrength(), Symbol.getLinkage(),
377 GOFF::ESD_AMODE_64, Symbol.getBindingScope()});
382void GOFFWriter::defineSymbols() {
383 unsigned Ordinal = 0;
385 for (MCSection &S : Asm) {
386 auto &
Section =
static_cast<MCSectionGOFF &
>(S);
388 defineSectionSymbols(Section);
392 for (
const MCSymbol &Sym :
Asm.symbols()) {
393 if (Sym.isTemporary())
395 auto &
Symbol =
static_cast<const MCSymbolGOFF &
>(Sym);
396 if (!
Symbol.isDefined()) {
397 Symbol.setIndex(++Ordinal);
398 defineExtern(Symbol);
399 }
else if (
Symbol.isInEDSection()) {
400 Symbol.setIndex(++Ordinal);
409void GOFFWriter::writeHeader() {
412 OS.writebe<uint32_t>(0);
413 OS.writebe<uint32_t>(0);
415 OS.writebe<uint16_t>(0);
418 OS.writebe<uint32_t>(1);
419 OS.writebe<uint16_t>(0);
423void GOFFWriter::writeSymbol(
const GOFFSymbol &Symbol) {
424 if (
Symbol.Offset >= (((uint64_t)1) << 31))
428 SmallString<256>
Name;
435 uint16_t NameLength =
Name.size();
438 OS.writebe<uint8_t>(
Symbol.SymbolType);
439 OS.writebe<uint32_t>(
Symbol.EsdId);
440 OS.writebe<uint32_t>(
Symbol.ParentEsdId);
441 OS.writebe<uint32_t>(0);
442 OS.writebe<uint32_t>(
443 static_cast<uint32_t
>(
Symbol.Offset));
444 OS.writebe<uint32_t>(0);
445 OS.writebe<uint32_t>(
Symbol.SectionLength);
446 OS.writebe<uint32_t>(
Symbol.EASectionEDEsdId);
447 OS.writebe<uint32_t>(
Symbol.EASectionOffset);
448 OS.writebe<uint32_t>(0);
449 OS.writebe<uint8_t>(
Symbol.NameSpace);
450 OS.writebe<uint8_t>(
Symbol.SymbolFlags);
451 OS.writebe<uint8_t>(
Symbol.FillByteValue);
452 OS.writebe<uint8_t>(0);
453 OS.writebe<uint32_t>(
Symbol.ADAEsdId);
454 OS.writebe<uint32_t>(
Symbol.SortKey);
455 OS.writebe<uint64_t>(0);
456 for (
auto F :
Symbol.BehavAttrs.Attr)
457 OS.writebe<uint8_t>(
F);
458 OS.writebe<uint16_t>(NameLength);
459 OS.write(
Name.data(), NameLength);
464class TextStream :
public raw_ostream {
473 char Buffer[BufferSize];
480 const uint32_t EsdId;
486 void write_impl(
const char *Ptr,
size_t Size)
override;
488 uint64_t current_pos()
const override {
return Offset; }
491 explicit TextStream(GOFFOstream &OS, uint32_t EsdId,
493 : OS(OS),
Offset(0), EsdId(EsdId), RecordStyle(RecordStyle) {
494 SetBuffer(Buffer,
sizeof(Buffer));
497 ~TextStream()
override { flush(); }
501void TextStream::write_impl(
const char *Ptr,
size_t Size) {
502 size_t WrittenLength = 0;
505 if (
Offset +
Size > std::numeric_limits<int32_t>::max())
508 while (WrittenLength <
Size) {
509 size_t ToWriteLength =
513 OS.writebe<uint8_t>(GOFF::Flags(4, 4, RecordStyle));
514 OS.writebe<uint32_t>(EsdId);
515 OS.writebe<uint32_t>(0);
516 OS.writebe<uint32_t>(
static_cast<uint32_t
>(
Offset));
517 OS.writebe<uint32_t>(0);
518 OS.writebe<uint16_t>(0);
519 OS.writebe<uint16_t>(ToWriteLength);
520 OS.write(Ptr + WrittenLength, ToWriteLength);
522 WrittenLength += ToWriteLength;
527void GOFFWriter::writeText(
const MCSectionGOFF *Section) {
533 Asm.writeSectionData(S, Section);
538class RelocDataItemBuffer {
543 RelocDataItemBuffer() : Ptr(Buffer) {}
544 const char *
data() {
return Buffer; }
545 size_t size() {
return Ptr - Buffer; }
546 void reset() { Ptr = Buffer; }
548 template <
typename T>
void writebe(
T Val) {
549 assert(fits(
sizeof(
T)) &&
"Out-of-bounds write");
556void GOFFWriter::writeRelocations() {
558 for (
auto &RelocEntry : Relocations) {
559 auto GetRptr = [](
const MCSymbolGOFF *Sym) -> uint32_t {
560 if (Sym->isTemporary())
561 return static_cast<MCSectionGOFF &
>(Sym->getSection())
564 return Sym->getIndex();
567 RelocEntry.PEsdId = RelocEntry.Pptr->getOrdinal();
568 RelocEntry.REsdId = GetRptr(RelocEntry.Rptr);
573 Relocations.begin(), Relocations.end(),
574 [](
const GOFFRelocationEntry &
Left,
const GOFFRelocationEntry &
Right) {
575 return std::tie(Left.PEsdId, Left.REsdId, Left.POffset) <
576 std::tie(Right.PEsdId, Right.REsdId, Right.POffset);
580 RelocDataItemBuffer Buffer;
581 for (
auto I = Relocations.begin(),
E = Relocations.end();
I !=
E;) {
584 uint32_t PrevResdId = -1;
585 uint32_t PrevPesdId = -1;
586 uint64_t PrevPOffset = -1;
587 for (;
I !=
E; ++
I) {
588 const GOFFRelocationEntry &Rel = *
I;
590 bool SameREsdId = (Rel.
REsdId == PrevResdId);
591 bool SamePEsdId = (Rel.
PEsdId == PrevPesdId);
592 bool SamePOffset = (Rel.
POffset == PrevPOffset);
593 bool EightByteOffset = ((Rel.
POffset >> 32) & 0xffffffff);
603 ItemSize += (EightByteOffset ? 8 : 4);
604 if (!Buffer.fits(ItemSize))
607 GOFF::Flags RelocFlags[6];
608 RelocFlags[0].
set(0, 1, SameREsdId);
609 RelocFlags[0].
set(1, 1, SamePEsdId);
610 RelocFlags[0].
set(2, 1, SamePOffset);
611 RelocFlags[0].
set(6, 1, EightByteOffset);
621 for (
auto F : RelocFlags)
622 Buffer.writebe<uint8_t>(
F);
623 Buffer.writebe<uint16_t>(0);
625 Buffer.writebe<uint32_t>(Rel.
REsdId);
627 Buffer.writebe<uint32_t>(Rel.
PEsdId);
630 Buffer.writebe<uint64_t>(Rel.
POffset);
632 Buffer.writebe<uint32_t>(Rel.
POffset);
641 OS.writebe<uint8_t>(0);
642 OS.writebe<uint16_t>(Buffer.size());
643 OS.write(Buffer.data(), Buffer.size());
647void GOFFWriter::writeEnd() {
655 OS.writebe<uint8_t>(GOFF::Flags(6, 2,
F));
656 OS.writebe<uint8_t>(AMODE);
661 OS.writebe<uint32_t>(0);
662 OS.writebe<uint32_t>(ESDID);
665uint64_t GOFFWriter::writeObject() {
670 for (
const MCSection &Section : Asm)
671 writeText(
static_cast<const MCSectionGOFF *
>(&Section));
681 <<
" logical records.");
683 return OS.getWrittenSize();
688 : TargetObjectWriter(
std::
move(MOTW)), OS(OS) {}
702 Asm->getBackend().getFixupKindInfo(
Fixup.getKind());
707 unsigned RelocType = TargetObjectWriter->getRelocType(
Target,
Fixup);
713 if (
A.isUndefined()) {
718 .
concat(
" must be defined for a relative immediate relocation"));
721 if (&
A.getSection() != PSection) {
724 Twine(
"relative immediate relocation section mismatch: ")
735 Twine(
"subtractive symbol ")
737 .
concat(
" not supported for a relative immediate relocation"));
740 FixedValue =
Asm->getSymbolOffset(
A) - FixupOffset +
Target.getConstant();
743 FixedValue =
Target.getConstant();
746 FixedValue +=
A.isTemporary() ?
Asm->getSymbolOffset(
A) : 0;
749 FixedValue -=
B->isTemporary() ?
Asm->getSymbolOffset(*
B) : 0;
763 "No dependent relocations expected");
790 dbgs() <<
"Reloc " <<
N <<
": " << Con
791 <<
" Rptr: " << Sym->getExternalName()
793 <<
" Offset: " << FixupOffset <<
" Fixed Imm: " << FixedValue
800 Relocations.emplace_back(PSection, &
A,
ReferenceType, ReferentType,
804 Relocations.emplace_back(
811 uint64_t Size = GOFFWriter(OS, *
Asm, RootSD, Relocations).writeObject();
815std::unique_ptr<MCObjectWriter>
818 return std::make_unique<GOFFObjectWriter>(std::move(MOTW), OS);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#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.
PowerPC TLS Dynamic Call Fixup
GOFFObjectWriter(std::unique_ptr< MCGOFFObjectTargetWriter > MOTW, raw_pwrite_stream &OS)
void reset() override
lifetime management
uint64_t writeObject() override
Write the object file and returns the number of bytes written.
~GOFFObjectWriter() override
void recordRelocation(const MCFragment &F, const MCFixup &Fixup, MCValue Target, uint64_t &FixedValue) override
Record a relocation entry.
constexpr void set(uint8_t BitIndex, uint8_t Length, T NewValue)
LLVM_ABI bool getSymbolOffset(const MCSymbol &S, uint64_t &Val) const
LLVM_ABI uint64_t getSectionAddressSize(const MCSection &Sec) const
Encode information on a single operation to perform on a byte sequence (e.g., an encoded instruction)...
virtual void reset()
lifetime management
GOFF::EDAttr getEDAttributes() const
StringRef getExternalName() const
unsigned getOrdinal() const
Target - Wrapper for Target specific information.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Twine concat(const Twine &Suffix) 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)
void writeHeader(support::endian::Writer &W, bool Is64Bit, uint8_t OSABI, uint8_t ABIVersion, uint16_t EMachine, uint32_t EFlags, uint64_t SHOff, uint16_t SHNum, uint16_t SHStrNdx)
Write an ELF file header (Elf32_Ehdr or Elf64_Ehdr) for an ET_REL object.
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
@ ESD_ST_ExternalReference
value_type byte_swap(value_type value, endianness endian)
void write(void *memory, value_type value, endianness endian)
Write a value to memory with a particular endianness.
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.
detail::concat_range< ValueT, RangeTs... > concat(RangeTs &&...Ranges)
Returns a concatenated range across two or more ranges.
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.
LLVM_ABI Error write(DWPWriter &Out, ArrayRef< std::string > Inputs, OnCuIndexOverflow OverflowOptValue, Dwarf64StrOffsetsPromotion StrOffsetsOptValue, raw_pwrite_stream *OS=nullptr)
Implement std::hash so that hash_code can be used in STL containers.
GOFF::RLDReferenceType ReferenceType
GOFF::RLDFetchStore FetchStore
GOFF::RLDReferentType ReferentType
GOFF::ESDReserveQwords ReservedQwords
GOFF::ESDAlignment Alignment
GOFF::ESDTextStyle TextStyle
GOFF::ESDLoadingBehavior LoadBehavior
GOFF::ESDNameSpaceId NameSpace
GOFF::ESDBindingAlgorithm BindAlgorithm
GOFF::ESDBindingScope BindingScope
GOFF::ESDBindingStrength BindingStrength
GOFF::ESDLinkageType Linkage
GOFF::ESDExecutable Executable
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
Target independent information on a fixup kind.
uint8_t TargetSize
The number of bits written by this fixup.