LLVM: lib/MC/GOFFObjectWriter.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
24
25using namespace llvm;
26
27#define DEBUG_TYPE "goff-writer"
28
29namespace {
30
31
32
34
35
37
38
39
40
41
42
43
44
45
46
47
48
49class GOFFOstream {
50
52
53
55
56
58
59
61
62
63 char *BufferPtr = Buffer;
64
65
66 char Buffer[BufferSize];
67
68
69
71
72public:
74 ~GOFFOstream();
75
77 size_t getWrittenSize() const { return PhysicalRecords * GOFF::RecordLength; }
78 uint32_t getNumLogicalRecords() { return LogicalRecords; }
79
80
81 void write(const char *Ptr, size_t Size);
82
83
84 void write_zeros(unsigned NumZeros);
85
86
87 template <typename value_type> void writebe(value_type Value) {
90 write((const char *)&Value, sizeof(value_type));
91 }
92
93
95
96
97 void finalizeRecord();
98
99private:
100
101
102 void updateFlagsAndWritePrefix(bool IsContinued);
103
104
105 size_t getRemainingSize();
106};
107}
108
110
111GOFFOstream::~GOFFOstream() { finalizeRecord(); }
112
113void GOFFOstream::updateFlagsAndWritePrefix(bool IsContinued) {
114
115 if (TypeAndFlags & RecContinued)
116 TypeAndFlags |= RecContinuation;
117 if (IsContinued)
118 TypeAndFlags |= RecContinued;
119 else
120 TypeAndFlags &= ~RecContinued;
121
122 OS << static_cast(GOFF::PTVPrefix)
123 << static_cast<unsigned char>(TypeAndFlags)
124 << static_cast<unsigned char>(0);
125
126 ++PhysicalRecords;
127}
128
129size_t GOFFOstream::getRemainingSize() {
130 return size_t(&Buffer[BufferSize] - BufferPtr);
131}
132
133void GOFFOstream::write(const char *Ptr, size_t Size) {
134 size_t RemainingSize = getRemainingSize();
135
136
138 memcpy(BufferPtr, Ptr, Size);
139 BufferPtr += Size;
140 return;
141 }
142
143
144
145 updateFlagsAndWritePrefix(true);
146 OS.write(Buffer, size_t(BufferPtr - Buffer));
147 if (RemainingSize > 0) {
148 OS.write(Ptr, RemainingSize);
149 Ptr += RemainingSize;
150 Size -= RemainingSize;
151 }
152
153 while (Size > BufferSize) {
154 updateFlagsAndWritePrefix(true);
155 OS.write(Ptr, BufferSize);
156 Ptr += BufferSize;
157 Size -= BufferSize;
158 }
159
160
161 memcpy(Buffer, Ptr, Size);
162 BufferPtr = &Buffer[Size];
163}
164
165void GOFFOstream::write_zeros(unsigned NumZeros) {
166 assert(NumZeros <= 16 && "Range for zeros too large");
167
168
169 size_t RemainingSize = getRemainingSize();
170 if (LLVM_LIKELY(RemainingSize >= NumZeros)) {
171 memset(BufferPtr, 0, NumZeros);
172 BufferPtr += NumZeros;
173 return;
174 }
175
176
177 static char Zeros[16] = {
178 0,
179 };
180 write(Zeros, NumZeros);
181}
182
184 finalizeRecord();
185 TypeAndFlags = Type << 4;
186 ++LogicalRecords;
187}
188
189void GOFFOstream::finalizeRecord() {
190 if (Buffer == BufferPtr)
191 return;
192 updateFlagsAndWritePrefix(false);
193 OS.write(Buffer, size_t(BufferPtr - Buffer));
195 BufferPtr = Buffer;
196}
197
198namespace {
199
200class GOFFSymbol {
201public:
202 std::string Name;
203 uint32_t EsdId;
204 uint32_t ParentEsdId;
205 uint64_t Offset = 0;
206
207
210
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;
219
220 GOFFSymbol() : EsdId(0), ParentEsdId(0) {}
221
222 GOFFSymbol(StringRef Name, uint32_t EsdID, const GOFF::SDAttr &Attr)
226 BehavAttrs.setBindingScope(Attr.BindingScope);
227 }
228
229 GOFFSymbol(StringRef Name, uint32_t EsdID, uint32_t ParentEsdID,
230 const GOFF::EDAttr &Attr)
233 this->NameSpace = Attr.NameSpace;
234
238
239 BehavAttrs.setReadOnly(Attr.IsReadOnly);
240 BehavAttrs.setRmode(Attr.Rmode);
241 BehavAttrs.setTextStyle(Attr.TextStyle);
242 BehavAttrs.setBindingAlgorithm(Attr.BindAlgorithm);
243 BehavAttrs.setLoadingBehavior(Attr.LoadBehavior);
244 BehavAttrs.setAlignment(Attr.Alignment);
245 }
246
247 GOFFSymbol(StringRef Name, uint32_t EsdID, uint32_t ParentEsdID,
252 BehavAttrs.setExecutable(Attr.Executable);
254 BehavAttrs.setLinkageType(Attr.Linkage);
255 BehavAttrs.setAmode(Attr.Amode);
256 BehavAttrs.setBindingScope(Attr.BindingScope);
257 }
258
259 GOFFSymbol(StringRef Name, uint32_t EsdID, uint32_t ParentEsdID,
260 const GOFF::EDAttr &EDAttr, const GOFF::PRAttr &Attr)
264 BehavAttrs.setExecutable(Attr.Executable);
265 BehavAttrs.setLinkageType(Attr.Linkage);
266 BehavAttrs.setBindingScope(Attr.BindingScope);
267 BehavAttrs.setAlignment(EDAttr.Alignment);
268 }
269};
270
271class GOFFWriter {
272 GOFFOstream OS;
273 MCAssembler &Asm;
274
275 void writeHeader();
276 void writeSymbol(const GOFFSymbol &Symbol);
277 void writeText(const MCSectionGOFF *MC);
278 void writeEnd();
279
280 void defineSectionSymbols(const MCSectionGOFF &Section);
281 void defineLabel(const MCSymbolGOFF &Symbol);
282 void defineSymbols();
283
284public:
285 GOFFWriter(raw_pwrite_stream &OS, MCAssembler &Asm);
286 uint64_t writeObject();
287};
288}
289
290GOFFWriter::GOFFWriter(raw_pwrite_stream &OS, MCAssembler &Asm)
292
293void GOFFWriter::defineSectionSymbols(const MCSectionGOFF &Section) {
295 GOFFSymbol SD(Section.getName(), Section.getOrdinal(),
296 Section.getSDAttributes());
297 writeSymbol(SD);
298 }
299
301 GOFFSymbol ED(Section.getName(), Section.getOrdinal(),
302 Section.getParent()->getOrdinal(), Section.getEDAttributes());
304 writeSymbol(ED);
305 }
306
308 MCSectionGOFF *Parent = Section.getParent();
312 if (Section.requiresNonZeroLength()) {
313
314
315
316
317
318 if (!PR.SectionLength)
319 PR.SectionLength = 2;
320 }
321 writeSymbol(PR);
322 }
323}
324
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();
331 writeSymbol(LD);
332}
333
334void GOFFWriter::defineSymbols() {
335 unsigned Ordinal = 0;
336
337 for (MCSection &S : Asm) {
338 auto &Section = static_cast<MCSectionGOFF &>(S);
339 Section.setOrdinal(++Ordinal);
340 defineSectionSymbols(Section);
341 }
342
343
344 for (const MCSymbol &Sym : Asm.symbols()) {
345 if (Sym.isTemporary())
346 continue;
347 auto &Symbol = static_cast<const MCSymbolGOFF &>(Sym);
348 if (Symbol.hasLDAttributes()) {
349 Symbol.setIndex(++Ordinal);
350 defineLabel(Symbol);
351 }
352 }
353}
354
355void GOFFWriter::writeHeader() {
357 OS.write_zeros(1);
358 OS.writebe<uint32_t>(0);
359 OS.writebe<uint32_t>(0);
360 OS.write_zeros(2);
361 OS.writebe<uint16_t>(0);
362 OS.write_zeros(16);
363 OS.write_zeros(16);
364 OS.writebe<uint32_t>(1);
365 OS.writebe<uint16_t>(0);
366 OS.write_zeros(6);
367}
368
369void GOFFWriter::writeSymbol(const GOFFSymbol &Symbol) {
370 if (Symbol.Offset >= (((uint64_t)1) << 31))
372
373
374 SmallString<256> Name;
376
377
378
381 uint16_t NameLength = Name.size();
382
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);
406}
407
408namespace {
409
410class TextStream : public raw_ostream {
411
412 GOFFOstream &OS;
413
414
416
417
418
419 char Buffer[BufferSize];
420
421
422
424
425
426 const uint32_t EsdId;
427
428
430
431
432 void write_impl(const char *Ptr, size_t Size) override;
433
434 uint64_t current_pos() const override { return Offset; }
435
436public:
437 explicit TextStream(GOFFOstream &OS, uint32_t EsdId,
439 : OS(OS), Offset(0), EsdId(EsdId), RecordStyle(RecordStyle) {
440 SetBuffer(Buffer, sizeof(Buffer));
441 }
442
443 ~TextStream() override { flush(); }
444};
445}
446
447void TextStream::write_impl(const char *Ptr, size_t Size) {
448 size_t WrittenLength = 0;
449
450
451 if (Offset + Size > std::numeric_limits<int32_t>::max())
453
454 while (WrittenLength < Size) {
455 size_t ToWriteLength =
457
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);
467
468 WrittenLength += ToWriteLength;
469 Offset += ToWriteLength;
470 }
471}
472
473void GOFFWriter::writeText(const MCSectionGOFF *Section) {
474
476 return;
477
478 TextStream S(OS, Section->getOrdinal(), Section->getTextStyle());
479 Asm.writeSectionData(S, Section);
480}
481
482void GOFFWriter::writeEnd() {
484 uint8_t AMODE = 0;
485 uint32_t ESDID = 0;
486
487
488
490 OS.writebe<uint8_t>(GOFF::Flags(6, 2, F));
491 OS.writebe<uint8_t>(AMODE);
492 OS.write_zeros(3);
493
494
495
496 OS.writebe<uint32_t>(0);
497 OS.writebe<uint32_t>(ESDID);
498}
499
500uint64_t GOFFWriter::writeObject() {
501 writeHeader();
502
503 defineSymbols();
504
505 for (const MCSection &Section : Asm)
506 writeText(static_cast<const MCSectionGOFF *>(&Section));
507
508 writeEnd();
509
510
511 OS.finalizeRecord();
512
513 LLVM_DEBUG(dbgs() << "Wrote " << OS.getNumLogicalRecords()
514 << " logical records.");
515
516 return OS.getWrittenSize();
517}
518
520 std::unique_ptr MOTW, raw_pwrite_stream &OS)
521 : TargetObjectWriter(std::move(MOTW)), OS(OS) {}
522
524
529
530std::unique_ptr
533 return std::make_unique(std::move(MOTW), OS);
534}
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)
Definition GOFFObjectWriter.cpp:519
uint64_t writeObject() override
Write the object file and returns the number of bytes written.
Definition GOFFObjectWriter.cpp:525
~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.
Definition GOFFObjectWriter.cpp:531
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(MCStreamer &Out, ArrayRef< std::string > Inputs, OnCuIndexOverflow OverflowOptValue, Dwarf64StrOffsetsPromotion StrOffsetsOptValue)
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