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)

291 : OS(OS), Asm(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