LLVM: lib/ObjectYAML/WasmEmitter.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

20

21using namespace llvm;

22

23namespace {

24

25

26class WasmWriter {

27public:

29 : Obj(Obj), ErrHandler(EH) {}

30 bool writeWasm(raw_ostream &OS);

31

32private:

33 void writeRelocSection(raw_ostream &OS, WasmYAML::Section &Sec,

34 uint32_t SectionIndex);

35

36 void writeInitExpr(raw_ostream &OS, const WasmYAML::InitExpr &InitExpr);

37

38 void writeSectionContent(raw_ostream &OS, WasmYAML::CustomSection &Section);

39 void writeSectionContent(raw_ostream &OS, WasmYAML::TypeSection &Section);

40 void writeSectionContent(raw_ostream &OS, WasmYAML::ImportSection &Section);

41 void writeSectionContent(raw_ostream &OS, WasmYAML::FunctionSection &Section);

42 void writeSectionContent(raw_ostream &OS, WasmYAML::TableSection &Section);

43 void writeSectionContent(raw_ostream &OS, WasmYAML::MemorySection &Section);

44 void writeSectionContent(raw_ostream &OS, WasmYAML::TagSection &Section);

45 void writeSectionContent(raw_ostream &OS, WasmYAML::GlobalSection &Section);

46 void writeSectionContent(raw_ostream &OS, WasmYAML::ExportSection &Section);

47 void writeSectionContent(raw_ostream &OS, WasmYAML::StartSection &Section);

48 void writeSectionContent(raw_ostream &OS, WasmYAML::ElemSection &Section);

49 void writeSectionContent(raw_ostream &OS, WasmYAML::CodeSection &Section);

50 void writeSectionContent(raw_ostream &OS, WasmYAML::DataSection &Section);

51 void writeSectionContent(raw_ostream &OS, WasmYAML::DataCountSection &Section);

52

53

54 void writeSectionContent(raw_ostream &OS, WasmYAML::DylinkSection &Section);

55 void writeSectionContent(raw_ostream &OS, WasmYAML::NameSection &Section);

56 void writeSectionContent(raw_ostream &OS, WasmYAML::LinkingSection &Section);

57 void writeSectionContent(raw_ostream &OS, WasmYAML::ProducersSection &Section);

58 void writeSectionContent(raw_ostream &OS,

59 WasmYAML::TargetFeaturesSection &Section);

60 WasmYAML::Object &Obj;

61 uint32_t NumImportedFunctions = 0;

62 uint32_t NumImportedGlobals = 0;

63 uint32_t NumImportedTables = 0;

64 uint32_t NumImportedTags = 0;

65

66 bool HasError = false;

69};

70

71class SubSectionWriter {

72 raw_ostream &OS;

73 std::string OutString;

74 raw_string_ostream StringStream;

75

76public:

77 SubSectionWriter(raw_ostream &OS) : OS(OS), StringStream(OutString) {}

78

79 void done() {

80 StringStream.flush();

82 OS << OutString;

83 OutString.clear();

84 }

85

86 raw_ostream &getStream() { return StringStream; }

87};

88

89}

90

97

104

111

114 OS << Str;

115 return 0;

116}

117

125

126void WasmWriter::reportError(const Twine &Msg) {

127 ErrHandler(Msg);

128 HasError = true;

129}

130

131void WasmWriter::writeInitExpr(raw_ostream &OS,

132 const WasmYAML::InitExpr &InitExpr) {

135 } else {

140 break;

143 break;

146 break;

149 break;

152 break;

153 default:

154 reportError("unknown opcode in init_expr: " +

156 return;

157 }

159 }

160}

161

162void WasmWriter::writeSectionContent(raw_ostream &OS,

163 WasmYAML::DylinkSection &Section) {

165

167 SubSectionWriter SubSection(OS);

168 raw_ostream &SubOS = SubSection.getStream();

173 SubSection.done();

174

175 if (Section.Needed.size()) {

177 raw_ostream &SubOS = SubSection.getStream();

179 for (StringRef Needed : Section.Needed)

181 SubSection.done();

182 }

183 if (Section.RuntimePath.size()) {

185 raw_ostream &SubOS = SubSection.getStream();

187 for (StringRef Path : Section.RuntimePath)

189 SubSection.done();

190 }

191}

192

193void WasmWriter::writeSectionContent(raw_ostream &OS,

194 WasmYAML::LinkingSection &Section) {

197

198 SubSectionWriter SubSection(OS);

199

200

201 if (Section.SymbolTable.size()) {

205 const WasmYAML::SymbolInfo &Info = Sym.value();

209 switch (Info.Kind) {

218 break;

225 }

226 break;

229 break;

230 default:

232 }

233 }

234

235 SubSection.done();

236 }

237

238

239 if (Section.SegmentInfos.size()) {

242 for (const WasmYAML::SegmentInfo &SegmentInfo : Section.SegmentInfos) {

246 }

247 SubSection.done();

248 }

249

250

251 if (Section.InitFunctions.size()) {

254 for (const WasmYAML::InitFunction &Func : Section.InitFunctions) {

257 }

258 SubSection.done();

259 }

260

261

262 if (Section.Comdats.size()) {

265 for (const auto &C : Section.Comdats) {

267 encodeULEB128(0, SubSection.getStream());

268 encodeULEB128(C.Entries.size(), SubSection.getStream());

269 for (const WasmYAML::ComdatEntry &Entry : C.Entries) {

272 }

273 }

274 SubSection.done();

275 }

276}

277

278void WasmWriter::writeSectionContent(raw_ostream &OS,

279 WasmYAML::NameSection &Section) {

281 if (Section.FunctionNames.size()) {

283

284 SubSectionWriter SubSection(OS);

285

287 for (const WasmYAML::NameEntry &NameEntry : Section.FunctionNames) {

290 }

291

292 SubSection.done();

293 }

294 if (Section.GlobalNames.size()) {

296

297 SubSectionWriter SubSection(OS);

298

300 for (const WasmYAML::NameEntry &NameEntry : Section.GlobalNames) {

303 }

304

305 SubSection.done();

306 }

307 if (Section.DataSegmentNames.size()) {

309

310 SubSectionWriter SubSection(OS);

311

313 for (const WasmYAML::NameEntry &NameEntry : Section.DataSegmentNames) {

316 }

317

318 SubSection.done();

319 }

320}

321

322void WasmWriter::writeSectionContent(raw_ostream &OS,

323 WasmYAML::ProducersSection &Section) {

325 int Fields = int(Section.Languages.empty()) + int(Section.Tools.empty()) +

326 int(Section.SDKs.empty());

327 if (Fields == 0)

328 return;

330 for (auto &Field : {std::make_pair(StringRef("language"), &Section.Languages),

331 std::make_pair(StringRef("processed-by"), &Section.Tools),

332 std::make_pair(StringRef("sdk"), &Section.SDKs)}) {

333 if (Field.second->empty())

334 continue;

337 for (auto &Entry : *Field.second) {

340 }

341 }

342}

343

344void WasmWriter::writeSectionContent(raw_ostream &OS,

345 WasmYAML::TargetFeaturesSection &Section) {

348 for (auto &E : Section.Features) {

351 }

352}

353

354void WasmWriter::writeSectionContent(raw_ostream &OS,

355 WasmYAML::CustomSection &Section) {

357 writeSectionContent(OS, *S);

359 writeSectionContent(OS, *S);

361 writeSectionContent(OS, *S);

363 writeSectionContent(OS, *S);

365 writeSectionContent(OS, *S);

366 } else {

368 Section.Payload.writeAsBinary(OS);

369 }

370}

371

372void WasmWriter::writeSectionContent(raw_ostream &OS,

373 WasmYAML::TypeSection &Section) {

375 uint32_t ExpectedIndex = 0;

376 for (const WasmYAML::Signature &Sig : Section.Signatures) {

377 if (Sig.Index != ExpectedIndex) {

379 return;

380 }

381 ++ExpectedIndex;

384 for (auto ParamType : Sig.ParamTypes)

389 }

390}

391

392void WasmWriter::writeSectionContent(raw_ostream &OS,

393 WasmYAML::ImportSection &Section) {

395 for (const WasmYAML::Import &Import : Section.Imports) {

399 switch (Import.Kind) {

402 NumImportedFunctions++;

403 break;

407 NumImportedGlobals++;

408 break;

410 writeUint8(OS, 0);

412 NumImportedTags++;

413 break;

416 break;

420 NumImportedTables++;

421 break;

422 default:

424 return;

425 }

426 }

427}

428

429void WasmWriter::writeSectionContent(raw_ostream &OS,

430 WasmYAML::FunctionSection &Section) {

432 for (uint32_t FuncType : Section.FunctionTypes)

434}

435

436void WasmWriter::writeSectionContent(raw_ostream &OS,

437 WasmYAML::ExportSection &Section) {

439 for (const WasmYAML::Export &Export : Section.Exports) {

443 }

444}

445

446void WasmWriter::writeSectionContent(raw_ostream &OS,

447 WasmYAML::StartSection &Section) {

449}

450

451void WasmWriter::writeSectionContent(raw_ostream &OS,

452 WasmYAML::TableSection &Section) {

454 uint32_t ExpectedIndex = NumImportedTables;

455 for (auto &Table : Section.Tables) {

456 if (Table.Index != ExpectedIndex) {

457 reportError("unexpected table index: " + Twine(Table.Index));

458 return;

459 }

460 ++ExpectedIndex;

463 }

464}

465

466void WasmWriter::writeSectionContent(raw_ostream &OS,

467 WasmYAML::MemorySection &Section) {

469 for (const WasmYAML::Limits &Mem : Section.Memories)

471}

472

473void WasmWriter::writeSectionContent(raw_ostream &OS,

474 WasmYAML::TagSection &Section) {

476 for (uint32_t TagType : Section.TagTypes) {

477 writeUint8(OS, 0);

479 }

480}

481

482void WasmWriter::writeSectionContent(raw_ostream &OS,

483 WasmYAML::GlobalSection &Section) {

485 uint32_t ExpectedIndex = NumImportedGlobals;

487 if (Global.Index != ExpectedIndex) {

489 return;

490 }

491 ++ExpectedIndex;

494 writeInitExpr(OS, Global.Init);

495 }

496}

497

498void WasmWriter::writeSectionContent(raw_ostream &OS,

499 WasmYAML::ElemSection &Section) {

501 for (auto &Segment : Section.Segments) {

505

506 writeInitExpr(OS, Segment.Offset);

507

509

510

511

512 if (Segment.ElemKind != uint32_t(wasm::ValType::FUNCREF)) {

513 reportError("unexpected elemkind: " + Twine(Segment.ElemKind));

514 return;

515 }

516 const uint8_t ElemKind = 0;

518 }

519

521 for (auto &Function : Segment.Functions)

523 }

524}

525

526void WasmWriter::writeSectionContent(raw_ostream &OS,

527 WasmYAML::CodeSection &Section) {

529 uint32_t ExpectedIndex = NumImportedFunctions;

530 for (auto &Func : Section.Functions) {

531 std::string OutString;

532 raw_string_ostream StringStream(OutString);

533 if (Func.Index != ExpectedIndex) {

534 reportError("unexpected function index: " + Twine(Func.Index));

535 return;

536 }

537 ++ExpectedIndex;

538

540 for (auto &LocalDecl : Func.Locals) {

542 writeUint8(StringStream, LocalDecl.Type);

543 }

544

545 Func.Body.writeAsBinary(StringStream);

546

547

548 StringStream.flush();

550 OS << OutString;

551 }

552}

553

554void WasmWriter::writeSectionContent(raw_ostream &OS,

555 WasmYAML::DataSection &Section) {

557 for (auto &Segment : Section.Segments) {

562 writeInitExpr(OS, Segment.Offset);

563 encodeULEB128(Segment.Content.binary_size(), OS);

564 Segment.Content.writeAsBinary(OS);

565 }

566}

567

568void WasmWriter::writeSectionContent(raw_ostream &OS,

569 WasmYAML::DataCountSection &Section) {

571}

572

573void WasmWriter::writeRelocSection(raw_ostream &OS, WasmYAML::Section &Sec,

574 uint32_t SectionIndex) {

575 switch (Sec.Type) {

578 break;

581 break;

584 writeStringRef(("reloc." + CustomSection->Name).str(), OS);

585 break;

586 }

587 default:

589 }

590

593

600 }

601}

602

603bool WasmWriter::writeWasm(raw_ostream &OS) {

604

607

608

609 llvm::object::WasmSectionOrderChecker Checker;

610 for (const std::unique_ptrWasmYAML::Section &Sec : Obj.Sections) {

611 StringRef SecName = "";

613 SecName = S->Name;

615 reportError("out of order section type: " +

617 return false;

618 }

620 std::string OutString;

621 raw_string_ostream StringStream(OutString);

623 writeSectionContent(StringStream, *S);

625 writeSectionContent(StringStream, *S);

627 writeSectionContent(StringStream, *S);

629 writeSectionContent(StringStream, *S);

631 writeSectionContent(StringStream, *S);

633 writeSectionContent(StringStream, *S);

635 writeSectionContent(StringStream, *S);

637 writeSectionContent(StringStream, *S);

639 writeSectionContent(StringStream, *S);

641 writeSectionContent(StringStream, *S);

643 writeSectionContent(StringStream, *S);

645 writeSectionContent(StringStream, *S);

647 writeSectionContent(StringStream, *S);

649 writeSectionContent(StringStream, *S);

650 else

651 reportError("unknown section type: " + Twine(Sec->Type));

652

653 if (HasError)

654 return false;

655

656 StringStream.flush();

657

658 unsigned HeaderSecSizeEncodingLen =

659 Sec->HeaderSecSizeEncodingLen.value_or(5);

660 unsigned RequiredLen = getULEB128Size(OutString.size());

661

662 assert(RequiredLen <= 5);

663 if (HeaderSecSizeEncodingLen < RequiredLen) {

664 reportError("section header length can't be encoded in a LEB of size " +

665 Twine(HeaderSecSizeEncodingLen));

666 return false;

667 }

668

669 encodeULEB128(OutString.size(), OS, HeaderSecSizeEncodingLen);

670 OS << OutString;

671 }

672

673

674 uint32_t SectionIndex = 0;

675 for (const std::unique_ptrWasmYAML::Section &Sec : Obj.Sections) {

676 if (Sec->Relocations.empty()) {

677 SectionIndex++;

678 continue;

679 }

680

682 std::string OutString;

683 raw_string_ostream StringStream(OutString);

684 writeRelocSection(StringStream, *Sec, SectionIndex++);

685 StringStream.flush();

686

688 OS << OutString;

689 }

690

691 return true;

692}

693

694namespace llvm {

695namespace yaml {

696

698 WasmWriter Writer(Doc, EH);

699 return Writer.writeWasm(Out);

700}

701

702}

703}

assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")

static Error reportError(StringRef Message)

static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")

Analysis containing CSE Info

OptimizedStructLayoutField Field

static int writeUint32(raw_ostream &OS, uint32_t Value)

Definition WasmEmitter.cpp:98

static int writeLimits(const WasmYAML::Limits &Lim, raw_ostream &OS)

Definition WasmEmitter.cpp:118

static int writeStringRef(const StringRef &Str, raw_ostream &OS)

Definition WasmEmitter.cpp:112

static int writeUint8(raw_ostream &OS, uint8_t Value)

Definition WasmEmitter.cpp:105

static int writeUint64(raw_ostream &OS, uint64_t Value)

Definition WasmEmitter.cpp:91

StringRef - Represent a constant reference to a string, i.e.

Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...

LLVM Value Representation.

LLVM_ABI bool isValidSectionOrder(unsigned ID, StringRef CustomSectionName="")

This class implements an extremely fast bulk output stream that can only output to a stream.

raw_ostream & write(unsigned char C)

LLVM_ABI void writeAsBinary(raw_ostream &OS, uint64_t N=UINT64_MAX) const

Write the contents (regardless of whether it is binary or a hex string) as binary to the given raw_os...

#define llvm_unreachable(msg)

Marks that the current location is not supposed to be reachable.

@ C

The default llvm calling convention, compatible with C.

NodeAddr< FuncNode * > Func

void write64le(void *P, uint64_t V)

void write32le(void *P, uint32_t V)

const unsigned WASM_SYMBOL_UNDEFINED

@ WASM_LIMITS_FLAG_HAS_MAX

@ WASM_DATA_SEGMENT_IS_PASSIVE

@ WASM_DATA_SEGMENT_HAS_MEMINDEX

@ WASM_SYMBOL_TYPE_GLOBAL

@ WASM_SYMBOL_TYPE_SECTION

@ WASM_SYMBOL_TYPE_FUNCTION

@ WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER

LLVM_ABI bool relocTypeHasAddend(uint32_t type)

@ WASM_DYLINK_RUNTIME_PATH

@ WASM_NAMES_DATA_SEGMENT

LLVM_ABI llvm::StringRef sectionTypeToString(uint32_t type)

const unsigned WASM_SYMBOL_EXPLICIT_NAME

const unsigned WASM_ELEM_SEGMENT_MASK_HAS_ELEM_DESC

llvm::function_ref< void(const Twine &Msg)> ErrorHandler

LLVM_ABI bool yaml2wasm(WasmYAML::Object &Doc, raw_ostream &Out, ErrorHandler EH)

Definition WasmEmitter.cpp:697

This is an optimization pass for GlobalISel generic memory operations.

auto enumerate(FirstRange &&First, RestRanges &&...Rest)

Given two or more input ranges, returns a new range whose values are tuples (A, B,...

decltype(auto) dyn_cast(const From &Val)

dyn_cast - Return the argument parameter cast to the specified type.

@ Export

Export information to summary.

@ Import

Import information from summary.

@ Global

Append to llvm.global_dtors.

LLVM_ABI unsigned getULEB128Size(uint64_t Value)

Utility function to get the size of the ULEB128-encoded value.

FunctionAddr VTableAddr uintptr_t uintptr_t Data

unsigned encodeSLEB128(int64_t Value, raw_ostream &OS, unsigned PadTo=0)

Utility function to encode a SLEB128 value to an output stream.

decltype(auto) cast(const From &Val)

cast - Return the argument parameter cast to the specified type.

unsigned encodeULEB128(uint64_t Value, raw_ostream &OS, unsigned PadTo=0)

Utility function to encode a ULEB128 value to an output stream.

wasm::WasmInitExprMVP Inst

std::vector< std::unique_ptr< Section > > Sections

std::vector< Relocation > Relocations

std::vector< ValueType > ReturnTypes

std::vector< ValueType > ParamTypes

union llvm::wasm::WasmInitExprMVP::@021046217255127373215144224227277301132130072341 Value

Common declarations for yaml2obj.