LLVM: lib/MC/WasmObjectWriter.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

16#include "llvm/Config/llvm-config.h"

31#include

32

33using namespace llvm;

34

35#define DEBUG_TYPE "mc"

36

37namespace {

38

39

40

41static const uint32_t InitialTableOffset = 1;

42

43

44

45

46struct SectionBookkeeping {

47

49

51

54};

55

56

57

58

59

60struct WasmDataSegment {

68};

69

70

71struct WasmFunction {

74};

75

76

77struct WasmGlobal {

80};

81

82

83

84

85struct WasmComdatEntry {

86 unsigned Kind;

88};

89

90

91struct WasmRelocationEntry {

93 const MCSymbolWasm *Symbol;

94 int64_t Addend;

95 unsigned Type;

96 const MCSectionWasm *FixupSection;

97

99 int64_t Addend, unsigned Type,

102 FixupSection(FixupSection) {}

103

105

108 << ", Sym=" << *Symbol << ", Addend=" << Addend

109 << ", FixupSection=" << FixupSection->getName();

110 }

111

112#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)

114#endif

115};

116

118

119struct WasmCustomSection {

120

123

124 uint32_t OutputContentsOffset = 0;

126

128 : Name(Name), Section(Section) {}

129};

130

131#if !defined(NDEBUG)

133 Rel.print(OS);

134 return OS;

135}

136#endif

137

138

139

140template <typename T, int W>

144 assert(SizeLen == W);

145 Stream.pwrite((char *)Buffer, SizeLen, Offset);

146}

147

148

149

150template <typename T, int W>

154 assert(SizeLen == W);

155 Stream.pwrite((char *)Buffer, SizeLen, Offset);

156}

157

160 writePatchableULEB<uint32_t, 5>(Stream, Value, Offset);

161}

162

165 writePatchableSLEB<int32_t, 5>(Stream, Value, Offset);

166}

167

170 writePatchableSLEB<uint64_t, 10>(Stream, Value, Offset);

171}

172

175 writePatchableSLEB<int64_t, 10>(Stream, Value, Offset);

176}

177

178

183 Stream.pwrite((char *)Buffer, sizeof(Buffer), Offset);

184}

185

190 Stream.pwrite((char *)Buffer, sizeof(Buffer), Offset);

191}

192

195}

196

199

200

201 std::unique_ptr TargetObjectWriter;

202

203

204 std::vector CodeRelocations;

205

206 std::vector DataRelocations;

207

208

209

211

212

214

215

218

220

221

222

223 std::vector CustomSections;

224 std::unique_ptr ProducersSection;

225 std::unique_ptr TargetFeaturesSection;

226

228 CustomSectionsRelocations;

229

230

232

236 unsigned NumFunctionImports = 0;

237 unsigned NumGlobalImports = 0;

238 unsigned NumTableImports = 0;

239 unsigned NumTagImports = 0;

241

242 enum class DwoMode {

243 AllSections,

244 NonDwoOnly,

245 DwoOnly,

246 };

247 bool IsSplitDwarf = false;

250

251

252 bool is64Bit() const { return TargetObjectWriter->is64Bit(); }

253 bool isEmscripten() const { return TargetObjectWriter->isEmscripten(); }

254

255 void startSection(SectionBookkeeping &Section, unsigned SectionId);

256 void startCustomSection(SectionBookkeeping &Section, StringRef Name);

257 void endSection(SectionBookkeeping &Section);

258

259public:

260 WasmObjectWriter(std::unique_ptr MOTW,

262 : TargetObjectWriter(std::move(MOTW)), OS(&OS_) {}

263

264 WasmObjectWriter(std::unique_ptr MOTW,

266 : TargetObjectWriter(std::move(MOTW)), IsSplitDwarf(true), OS(&OS_),

267 DwoOS(&DwoOS_) {}

268

269private:

270 void reset() override {

271 CodeRelocations.clear();

272 DataRelocations.clear();

273 TypeIndices.clear();

274 WasmIndices.clear();

275 GOTIndices.clear();

276 TableIndices.clear();

277 DataLocations.clear();

278 CustomSections.clear();

279 ProducersSection.reset();

280 TargetFeaturesSection.reset();

281 CustomSectionsRelocations.clear();

282 SignatureIndices.clear();

283 Signatures.clear();

284 DataSegments.clear();

285 SectionFunctions.clear();

286 NumFunctionImports = 0;

287 NumGlobalImports = 0;

288 NumTableImports = 0;

290 }

291

292 void writeHeader(const MCAssembler &Asm);

293

296

297 void executePostLayoutBinding() override;

300 uint64_t writeObject() override;

301

303

304 void writeString(const StringRef Str) {

306 W->OS << Str;

307 }

308

309 void writeStringWithAlignment(const StringRef Str, unsigned Alignment);

310

311 void writeI32(int32_t val) {

312 char Buffer[4];

314 W->OS.write(Buffer, sizeof(Buffer));

315 }

316

317 void writeI64(int64_t val) {

318 char Buffer[8];

320 W->OS.write(Buffer, sizeof(Buffer));

321 }

322

323 void writeValueType(wasm::ValType Ty) { W->OS << static_cast<char>(Ty); }

324

330 void writeElemSection(const MCSymbolWasm *IndirectFunctionTable,

332 void writeDataCountSection();

340 std::vector &Relocations);

341 void writeLinkingMetaDataSection(

343 ArrayRef<std::pair<uint16_t, uint32_t>> InitFuncs,

344 const std::map<StringRef, std::vector> &Comdats);

345 void writeCustomSection(WasmCustomSection &CustomSection,

347 void writeCustomRelocSections();

348

350 const WasmRelocationEntry &RelEntry);

353

354 uint32_t getRelocationIndexValue(const WasmRelocationEntry &RelEntry);

357 void registerFunctionType(const MCSymbolWasm &Symbol);

358 void registerTagType(const MCSymbolWasm &Symbol);

359};

360

361}

362

363

364void WasmObjectWriter::startSection(SectionBookkeeping &Section,

365 unsigned SectionId) {

366 LLVM_DEBUG(dbgs() << "startSection " << SectionId << "\n");

367 W->OS << char(SectionId);

368

370

371

372

374

375

378 Section.Index = SectionCount++;

379}

380

381

382

383void WasmObjectWriter::writeStringWithAlignment(const StringRef Str,

384 unsigned Alignment) {

385

386

387

388 raw_null_ostream NullOS;

389 uint64_t StrSizeLength = encodeULEB128(Str.size(), NullOS);

390 uint64_t Offset = W->OS.tell() + StrSizeLength + Str.size();

393

394

395 assert((StrSizeLength + Paddings) <= 5 && "too long string to align");

396

397 encodeSLEB128(Str.size(), W->OS, StrSizeLength + Paddings);

398 W->OS << Str;

399

401}

402

403void WasmObjectWriter::startCustomSection(SectionBookkeeping &Section,

404 StringRef Name) {

405 LLVM_DEBUG(dbgs() << "startCustomSection " << Name << "\n");

407

408

410

411

412 if (Name != "__clangast") {

413 writeString(Name);

414 } else {

415

416 writeStringWithAlignment(Name, 4);

417 }

418

419

421}

422

423

424

425void WasmObjectWriter::endSection(SectionBookkeeping &Section) {

427

428

430 return;

431

435

437

438

439

440 writePatchableU32(static_cast<raw_pwrite_stream &>(W->OS), Size,

442}

443

444

445void WasmObjectWriter::writeHeader(const MCAssembler &Asm) {

448}

449

450void WasmObjectWriter::executePostLayoutBinding() {

451

452

453

454

455

456

457 if (auto *Sym = Asm->getContext().lookupSymbol("__indirect_function_table")) {

458 const auto *WasmSym = static_cast<const MCSymbolWasm *>(Sym);

459 if (WasmSym->isNoStrip())

460 Asm->registerSymbol(*Sym);

461 }

462

463

464

465 for (const MCSymbol &S : Asm->symbols()) {

466 const auto &WS = static_cast<const MCSymbolWasm &>(S);

467 if (WS.isDefined() && WS.isFunction() && !WS.isVariable()) {

468 const auto &Sec = static_cast<const MCSectionWasm &>(S.getSection());

469 auto Pair = SectionFunctions.insert(std::make_pair(&Sec, &S));

470 if (!Pair.second)

472 Sec.getName());

473 }

474 }

475}

476

477void WasmObjectWriter::recordRelocation(const MCFragment &F,

478 const MCFixup &Fixup, MCValue Target,

479 uint64_t &FixedValue) {

480

482

483 const auto &FixupSection = static_cast<MCSectionWasm &>(*F.getParent());

484 uint64_t C = Target.getConstant();

485 uint64_t FixupOffset = Asm->getFragmentOffset(F) + Fixup.getOffset();

487 bool IsLocRel = false;

488

489 if (const auto *RefB = Target.getSubSym()) {

490 auto &SymB = static_cast<const MCSymbolWasm &>(*RefB);

491

492 if (FixupSection.isText()) {

494 Twine("symbol '") + SymB.getName() +

495 "' unsupported subtraction expression used in "

496 "relocation in code section.");

497 return;

498 }

499

500 if (SymB.isUndefined()) {

502 Twine("symbol '") + SymB.getName() +

503 "' can not be undefined in a subtraction expression");

504 return;

505 }

506 const MCSection &SecB = SymB.getSection();

507 if (&SecB != &FixupSection) {

509 Twine("symbol '") + SymB.getName() +

510 "' can not be placed in a different section");

511 return;

512 }

513 IsLocRel = true;

514 C += FixupOffset - Asm->getSymbolOffset(SymB);

515 }

516

517

518 auto *SymA = static_cast<const MCSymbolWasm *>(Target.getAddSym());

519

520

521 if (FixupSection.getName().starts_with(".init_array")) {

522 SymA->setUsedInInitArray();

523 return;

524 }

525

526

527

528

529 FixedValue = 0;

530

531 unsigned Type;

534 else

536 TargetObjectWriter->getRelocType(Target, Fixup, FixupSection, IsLocRel);

537

538

539

540

541 if ((Type == wasm::R_WASM_FUNCTION_OFFSET_I32 ||

542 Type == wasm::R_WASM_FUNCTION_OFFSET_I64 ||

543 Type == wasm::R_WASM_SECTION_OFFSET_I32) &&

544 SymA->isDefined()) {

545

546

547

548

549

550 if (!FixupSection.isMetadata())

551 report_fatal_error("relocations for function or section offsets are "

552 "only supported in metadata sections");

553

554 const MCSymbol *SectionSymbol = nullptr;

555 const MCSection &SecA = SymA->getSection();

557 auto SecSymIt = SectionFunctions.find(&SecA);

558 if (SecSymIt == SectionFunctions.end())

560 SectionSymbol = SecSymIt->second;

561 } else {

563 }

564 if (!SectionSymbol)

566

567 C += Asm->getSymbolOffset(*SymA);

568 SymA = static_cast<const MCSymbolWasm *>(SectionSymbol);

569 }

570

571 if (Type == wasm::R_WASM_TABLE_INDEX_REL_SLEB ||

572 Type == wasm::R_WASM_TABLE_INDEX_REL_SLEB64 ||

573 Type == wasm::R_WASM_TABLE_INDEX_SLEB ||

574 Type == wasm::R_WASM_TABLE_INDEX_SLEB64 ||

575 Type == wasm::R_WASM_TABLE_INDEX_I32 ||

576 Type == wasm::R_WASM_TABLE_INDEX_I64) {

577

578

579 auto TableName = "__indirect_function_table";

580 auto *Sym = static_cast<MCSymbolWasm *>(Ctx.lookupSymbol(TableName));

581 if (!Sym) {

583 } else {

584 if (!Sym->isFunctionTable())

585 report_fatal_error("__indirect_function_table symbol has wrong type");

586

587 Sym->setNoStrip();

588 Asm->registerSymbol(*Sym);

589 }

590 }

591

592

593

594 if (Type != wasm::R_WASM_TYPE_INDEX_LEB) {

595 if (SymA->getName().empty())

596 report_fatal_error("relocations against un-named temporaries are not yet "

597 "supported by wasm");

598

599 SymA->setUsedInReloc();

600 }

601

602 WasmRelocationEntry Rec(FixupOffset, SymA, C, Type, &FixupSection);

604

605 if (FixupSection.isWasmData()) {

606 DataRelocations.push_back(Rec);

607 } else if (FixupSection.isText()) {

608 CodeRelocations.push_back(Rec);

609 } else if (FixupSection.isMetadata()) {

610 CustomSectionsRelocations[&FixupSection].push_back(Rec);

611 } else {

613 }

614}

615

616

617

618

619

620uint64_t

621WasmObjectWriter::getProvisionalValue(const MCAssembler &Asm,

622 const WasmRelocationEntry &RelEntry) {

623 if ((RelEntry.Type == wasm::R_WASM_GLOBAL_INDEX_LEB ||

624 RelEntry.Type == wasm::R_WASM_GLOBAL_INDEX_I32) &&

625 !RelEntry.Symbol->isGlobal()) {

626 assert(GOTIndices.count(RelEntry.Symbol) > 0 && "symbol not found in GOT index space");

627 return GOTIndices[RelEntry.Symbol];

628 }

629

630 switch (RelEntry.Type) {

631 case wasm::R_WASM_TABLE_INDEX_REL_SLEB:

632 case wasm::R_WASM_TABLE_INDEX_REL_SLEB64:

633 case wasm::R_WASM_TABLE_INDEX_SLEB:

634 case wasm::R_WASM_TABLE_INDEX_SLEB64:

635 case wasm::R_WASM_TABLE_INDEX_I32:

636 case wasm::R_WASM_TABLE_INDEX_I64: {

637

639 static_cast<const MCSymbolWasm *>(Asm.getBaseSymbol(*RelEntry.Symbol));

641 if (RelEntry.Type == wasm::R_WASM_TABLE_INDEX_REL_SLEB ||

642 RelEntry.Type == wasm::R_WASM_TABLE_INDEX_REL_SLEB64)

643 return TableIndices[Base] - InitialTableOffset;

644 else

645 return TableIndices[Base];

646 }

647 case wasm::R_WASM_TYPE_INDEX_LEB:

648

649 return getRelocationIndexValue(RelEntry);

650 case wasm::R_WASM_FUNCTION_INDEX_LEB:

651 case wasm::R_WASM_FUNCTION_INDEX_I32:

652 case wasm::R_WASM_GLOBAL_INDEX_LEB:

653 case wasm::R_WASM_GLOBAL_INDEX_I32:

654 case wasm::R_WASM_TAG_INDEX_LEB:

655 case wasm::R_WASM_TABLE_NUMBER_LEB:

656

657 assert(WasmIndices.count(RelEntry.Symbol) > 0 && "symbol not found in wasm index space");

658 return WasmIndices[RelEntry.Symbol];

659 case wasm::R_WASM_FUNCTION_OFFSET_I32:

660 case wasm::R_WASM_FUNCTION_OFFSET_I64:

661 case wasm::R_WASM_SECTION_OFFSET_I32: {

662 if (!RelEntry.Symbol->isDefined())

663 return 0;

665 static_cast<const MCSectionWasm &>(RelEntry.Symbol->getSection());

666 return Section.getSectionOffset() + RelEntry.Addend;

667 }

668 case wasm::R_WASM_MEMORY_ADDR_LEB:

669 case wasm::R_WASM_MEMORY_ADDR_LEB64:

670 case wasm::R_WASM_MEMORY_ADDR_SLEB:

671 case wasm::R_WASM_MEMORY_ADDR_SLEB64:

672 case wasm::R_WASM_MEMORY_ADDR_REL_SLEB:

673 case wasm::R_WASM_MEMORY_ADDR_REL_SLEB64:

674 case wasm::R_WASM_MEMORY_ADDR_I32:

675 case wasm::R_WASM_MEMORY_ADDR_I64:

676 case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB:

677 case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB64:

678 case wasm::R_WASM_MEMORY_ADDR_LOCREL_I32: {

679

680

681 if (!RelEntry.Symbol->isDefined())

682 return 0;

683 const wasm::WasmDataReference &SymRef = DataLocations[RelEntry.Symbol];

684 const WasmDataSegment &Segment = DataSegments[SymRef.Segment];

685

686 return Segment.Offset + SymRef.Offset + RelEntry.Addend;

687 }

688 default:

690 }

691}

692

696

698

699 for (const MCFragment &Frag : DataSection) {

700 if (Frag.hasInstructions())

702

705 if (Frag.getAlignFillLen() != 1)

707

708 uint8_t Value = Frag.hasAlignEmitNops() ? 0 : Frag.getAlignFill();

710 std::min<uint64_t>(alignTo(DataBytes.size(), Frag.getAlignment()),

711 DataBytes.size() + Frag.getAlignMaxBytesToEmit());

714 int64_t NumValues;

715 if (!Fill->getNumValues().evaluateAsAbsolute(NumValues))

716 llvm_unreachable("The fill should be an assembler constant");

717 DataBytes.insert(DataBytes.end(), Fill->getValueSize() * NumValues,

718 Fill->getValue());

721 } else {

723 }

724 }

725

727}

728

729uint32_t

730WasmObjectWriter::getRelocationIndexValue(const WasmRelocationEntry &RelEntry) {

731 if (RelEntry.Type == wasm::R_WASM_TYPE_INDEX_LEB) {

732 auto It = TypeIndices.find(RelEntry.Symbol);

733 if (It == TypeIndices.end())

735 RelEntry.Symbol->getName());

736 return It->second;

737 }

738

739 return RelEntry.Symbol->getIndex();

740}

741

742

743

744void WasmObjectWriter::applyRelocations(

746 const MCAssembler &Asm) {

747 auto &Stream = static_cast<raw_pwrite_stream &>(W->OS);

748 for (const WasmRelocationEntry &RelEntry : Relocations) {

749 uint64_t Offset = ContentsOffset +

751 RelEntry.Offset;

752

753 LLVM_DEBUG(dbgs() << "applyRelocation: " << RelEntry << "\n");

754 uint64_t Value = getProvisionalValue(Asm, RelEntry);

755

756 switch (RelEntry.Type) {

757 case wasm::R_WASM_FUNCTION_INDEX_LEB:

758 case wasm::R_WASM_TYPE_INDEX_LEB:

759 case wasm::R_WASM_GLOBAL_INDEX_LEB:

760 case wasm::R_WASM_MEMORY_ADDR_LEB:

761 case wasm::R_WASM_TAG_INDEX_LEB:

762 case wasm::R_WASM_TABLE_NUMBER_LEB:

763 writePatchableU32(Stream, Value, Offset);

764 break;

765 case wasm::R_WASM_MEMORY_ADDR_LEB64:

766 writePatchableU64(Stream, Value, Offset);

767 break;

768 case wasm::R_WASM_TABLE_INDEX_I32:

769 case wasm::R_WASM_MEMORY_ADDR_I32:

770 case wasm::R_WASM_FUNCTION_OFFSET_I32:

771 case wasm::R_WASM_FUNCTION_INDEX_I32:

772 case wasm::R_WASM_SECTION_OFFSET_I32:

773 case wasm::R_WASM_GLOBAL_INDEX_I32:

774 case wasm::R_WASM_MEMORY_ADDR_LOCREL_I32:

776 break;

777 case wasm::R_WASM_TABLE_INDEX_I64:

778 case wasm::R_WASM_MEMORY_ADDR_I64:

779 case wasm::R_WASM_FUNCTION_OFFSET_I64:

781 break;

782 case wasm::R_WASM_TABLE_INDEX_SLEB:

783 case wasm::R_WASM_TABLE_INDEX_REL_SLEB:

784 case wasm::R_WASM_MEMORY_ADDR_SLEB:

785 case wasm::R_WASM_MEMORY_ADDR_REL_SLEB:

786 case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB:

787 writePatchableS32(Stream, Value, Offset);

788 break;

789 case wasm::R_WASM_TABLE_INDEX_SLEB64:

790 case wasm::R_WASM_TABLE_INDEX_REL_SLEB64:

791 case wasm::R_WASM_MEMORY_ADDR_SLEB64:

792 case wasm::R_WASM_MEMORY_ADDR_REL_SLEB64:

793 case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB64:

794 writePatchableS64(Stream, Value, Offset);

795 break;

796 default:

798 }

799 }

800}

801

802void WasmObjectWriter::writeTypeSection(

804 if (Signatures.empty())

805 return;

806

807 SectionBookkeeping Section;

809

811

812 for (const wasm::WasmSignature &Sig : Signatures) {

816 writeValueType(Ty);

819 writeValueType(Ty);

820 }

821

822 endSection(Section);

823}

824

827 uint32_t NumElements) {

828 if (Imports.empty())

829 return;

830

831 uint64_t NumPages =

833

834 SectionBookkeeping Section;

836

838 for (const wasm::WasmImport &Import : Imports) {

839 writeString(Import.Module);

840 writeString(Import.Field);

842

843 switch (Import.Kind) {

846 break;

848 W->OS << char(Import.Global.Type);

849 W->OS << char(Import.Global.Mutable ? 1 : 0);

850 break;

854 break;

856 W->OS << char(Import.Table.ElemType);

859 break;

861 W->OS << char(0);

863 break;

864 default:

866 }

867 }

868

869 endSection(Section);

870}

871

873 if (Functions.empty())

874 return;

875

876 SectionBookkeeping Section;

878

880 for (const WasmFunction &Func : Functions)

882

883 endSection(Section);

884}

885

886void WasmObjectWriter::writeTagSection(ArrayRef<uint32_t> TagTypes) {

887 if (TagTypes.empty())

888 return;

889

890 SectionBookkeeping Section;

892

894 for (uint32_t Index : TagTypes) {

895 W->OS << char(0);

897 }

898

899 endSection(Section);

900}

901

903 if (Globals.empty())

904 return;

905

906 SectionBookkeeping Section;

908

910 for (const wasm::WasmGlobal &Global : Globals) {

912 W->OS << char(Global.Type.Mutable);

913 if (Global.InitExpr.Extended) {

915 } else {

916 W->OS << char(Global.InitExpr.Inst.Opcode);

917 switch (Global.Type.Type) {

920 break;

923 break;

925 writeI32(0);

926 break;

928 writeI64(0);

929 break;

931 writeValueType(wasm::ValType::EXTERNREF);

932 break;

933 default:

935 }

936 }

938 }

939

940 endSection(Section);

941}

942

944 if (Tables.empty())

945 return;

946

947 SectionBookkeeping Section;

949

951 for (const wasm::WasmTable &Table : Tables) {

952 assert(Table.Type.ElemType != wasm::ValType::OTHERREF &&

953 "Cannot encode general ref-typed tables");

959 }

960 endSection(Section);

961}

962

964 if (Exports.empty())

965 return;

966

967 SectionBookkeeping Section;

969

971 for (const wasm::WasmExport &Export : Exports) {

972 writeString(Export.Name);

975 }

976

977 endSection(Section);

978}

979

980void WasmObjectWriter::writeElemSection(

981 const MCSymbolWasm *IndirectFunctionTable, ArrayRef<uint32_t> TableElems) {

982 if (TableElems.empty())

983 return;

984

985 assert(IndirectFunctionTable);

986

987 SectionBookkeeping Section;

989

991

992 assert(WasmIndices.count(IndirectFunctionTable));

993 uint32_t TableNumber = WasmIndices.find(IndirectFunctionTable)->second;

994 uint32_t Flags = 0;

995 if (TableNumber)

1000

1001

1006

1008

1009

1010 const uint8_t ElemKind = 0;

1011 W->OS << ElemKind;

1012 }

1013

1015 for (uint32_t Elem : TableElems)

1017

1018 endSection(Section);

1019}

1020

1021void WasmObjectWriter::writeDataCountSection() {

1022 if (DataSegments.empty())

1023 return;

1024

1025 SectionBookkeeping Section;

1028 endSection(Section);

1029}

1030

1031uint32_t WasmObjectWriter::writeCodeSection(const MCAssembler &Asm,

1033 if (Functions.empty())

1034 return 0;

1035

1036 SectionBookkeeping Section;

1038

1040

1041 for (const WasmFunction &Func : Functions) {

1042 auto *FuncSection = static_cast<MCSectionWasm *>(Func.Section);

1043

1044 int64_t Size = Asm.getSectionAddressSize(*FuncSection);

1046 FuncSection->setSectionOffset(W->OS.tell() - Section.ContentsOffset);

1047 Asm.writeSectionData(W->OS, FuncSection);

1048 }

1049

1050

1051 applyRelocations(CodeRelocations, Section.ContentsOffset, Asm);

1052

1053 endSection(Section);

1055}

1056

1057uint32_t WasmObjectWriter::writeDataSection(const MCAssembler &Asm) {

1058 if (DataSegments.empty())

1059 return 0;

1060

1061 SectionBookkeeping Section;

1063

1065

1066 for (const WasmDataSegment &Segment : DataSegments) {

1075 }

1077 Segment.Section->setSectionOffset(W->OS.tell() - Section.ContentsOffset);

1078 W->OS << Segment.Data;

1079 }

1080

1081

1082 applyRelocations(DataRelocations, Section.ContentsOffset, Asm);

1083

1084 endSection(Section);

1086}

1087

1088void WasmObjectWriter::writeRelocSection(

1089 uint32_t SectionIndex, StringRef Name,

1090 std::vector &Relocs) {

1091

1092

1093

1094 if (Relocs.empty())

1095 return;

1096

1097

1098

1099

1100

1101

1103 Relocs, [](const WasmRelocationEntry &A, const WasmRelocationEntry &B) {

1104 return (A.Offset + A.FixupSection->getSectionOffset()) <

1105 (B.Offset + B.FixupSection->getSectionOffset());

1106 });

1107

1108 SectionBookkeeping Section;

1109 startCustomSection(Section, std::string("reloc.") + Name.str());

1110

1113 for (const WasmRelocationEntry &RelEntry : Relocs) {

1115 RelEntry.Offset + RelEntry.FixupSection->getSectionOffset();

1116 uint32_t Index = getRelocationIndexValue(RelEntry);

1117

1118 W->OS << char(RelEntry.Type);

1121 if (RelEntry.hasAddend())

1123 }

1124

1125 endSection(Section);

1126}

1127

1128void WasmObjectWriter::writeCustomRelocSections() {

1129 for (const auto &Sec : CustomSections) {

1130 auto &Relocations = CustomSectionsRelocations[Sec.Section];

1131 writeRelocSection(Sec.OutputIndex, Sec.Name, Relocations);

1132 }

1133}

1134

1135void WasmObjectWriter::writeLinkingMetaDataSection(

1137 ArrayRef<std::pair<uint16_t, uint32_t>> InitFuncs,

1138 const std::map<StringRef, std::vector> &Comdats) {

1139 SectionBookkeeping Section;

1140 startCustomSection(Section, "linking");

1142

1143 SectionBookkeeping SubSection;

1144 if (SymbolInfos.size() != 0) {

1147 for (const wasm::WasmSymbolInfo &Sym : SymbolInfos) {

1150 switch (Sym.Kind) {

1158 writeString(Sym.Name);

1159 break;

1161 writeString(Sym.Name);

1166 }

1167 break;

1169 const uint32_t SectionIndex =

1170 CustomSections[Sym.ElementIndex].OutputIndex;

1172 break;

1173 }

1174 default:

1176 }

1177 }

1178 endSection(SubSection);

1179 }

1180

1181 if (DataSegments.size()) {

1184 for (const WasmDataSegment &Segment : DataSegments) {

1185 writeString(Segment.Name);

1188 }

1189 endSection(SubSection);

1190 }

1191

1192 if (!InitFuncs.empty()) {

1195 for (auto &StartFunc : InitFuncs) {

1197 encodeULEB128(StartFunc.second, W->OS);

1198 }

1199 endSection(SubSection);

1200 }

1201

1202 if (Comdats.size()) {

1205 for (const auto &C : Comdats) {

1206 writeString(C.first);

1209 for (const WasmComdatEntry &Entry : C.second) {

1212 }

1213 }

1214 endSection(SubSection);

1215 }

1216

1217 endSection(Section);

1218}

1219

1220void WasmObjectWriter::writeCustomSection(WasmCustomSection &CustomSection,

1221 const MCAssembler &Asm) {

1222 SectionBookkeeping Section;

1223 auto *Sec = CustomSection.Section;

1224 startCustomSection(Section, CustomSection.Name);

1225

1226 Sec->setSectionOffset(W->OS.tell() - Section.ContentsOffset);

1227 Asm.writeSectionData(W->OS, Sec);

1228

1229 CustomSection.OutputContentsOffset = Section.ContentsOffset;

1230 CustomSection.OutputIndex = Section.Index;

1231

1232 endSection(Section);

1233

1234

1235 auto &Relocations = CustomSectionsRelocations[CustomSection.Section];

1236 applyRelocations(Relocations, CustomSection.OutputContentsOffset, Asm);

1237}

1238

1239uint32_t WasmObjectWriter::getFunctionType(const MCSymbolWasm &Symbol) {

1241 assert(TypeIndices.count(&Symbol));

1242 return TypeIndices[&Symbol];

1243}

1244

1245uint32_t WasmObjectWriter::getTagType(const MCSymbolWasm &Symbol) {

1247 assert(TypeIndices.count(&Symbol));

1248 return TypeIndices[&Symbol];

1249}

1250

1251void WasmObjectWriter::registerFunctionType(const MCSymbolWasm &Symbol) {

1253

1254 wasm::WasmSignature S;

1255

1256 if (auto *Sig = Symbol.getSignature()) {

1257 S.Returns = Sig->Returns;

1258 S.Params = Sig->Params;

1259 }

1260

1261 auto Pair = SignatureIndices.insert(std::make_pair(S, Signatures.size()));

1262 if (Pair.second)

1263 Signatures.push_back(S);

1264 TypeIndices[&Symbol] = Pair.first->second;

1265

1266 LLVM_DEBUG(dbgs() << "registerFunctionType: " << Symbol

1267 << " new:" << Pair.second << "\n");

1268 LLVM_DEBUG(dbgs() << " -> type index: " << Pair.first->second << "\n");

1269}

1270

1271void WasmObjectWriter::registerTagType(const MCSymbolWasm &Symbol) {

1273

1274

1275

1276 wasm::WasmSignature S;

1277 if (auto *Sig = Symbol.getSignature()) {

1278 S.Returns = Sig->Returns;

1279 S.Params = Sig->Params;

1280 }

1281

1282 auto Pair = SignatureIndices.insert(std::make_pair(S, Signatures.size()));

1283 if (Pair.second)

1284 Signatures.push_back(S);

1285 TypeIndices[&Symbol] = Pair.first->second;

1286

1287 LLVM_DEBUG(dbgs() << "registerTagType: " << Symbol << " new:" << Pair.second

1288 << "\n");

1289 LLVM_DEBUG(dbgs() << " -> type index: " << Pair.first->second << "\n");

1290}

1291

1294 return true;

1295

1297 return false;

1298

1300 return false;

1301

1303 return false;

1304

1306 return false;

1307

1308 return true;

1309}

1310

1313

1314 for (const MCSymbol &S : Asm.symbols()) {

1315 const auto &WS = static_cast<const MCSymbolWasm &>(S);

1316 if (WS.isData() && WS.isInSection()) {

1317 auto &RefSection = static_cast<MCSectionWasm &>(WS.getSection());

1318 if (RefSection.getName() == SectionName) {

1319 return true;

1320 }

1321 }

1322 }

1323

1324 return false;

1325}

1326

1327void WasmObjectWriter::prepareImports(

1328 SmallVectorImplwasm::WasmImport &Imports, MCAssembler &Asm) {

1329

1330

1331

1332 wasm::WasmImport MemImport;

1333 MemImport.Module = "env";

1334 MemImport.Field = "__linear_memory";

1339

1340

1341

1342

1343 for (const MCSymbol &S : Asm.symbols()) {

1344 const auto &WS = static_cast<const MCSymbolWasm &>(S);

1345

1346

1347

1348 if (WS.isFunction()) {

1349 auto *BS = static_cast<const MCSymbolWasm *>(Asm.getBaseSymbol(S));

1350 if (!BS)

1352 ": absolute addressing not supported!");

1353 registerFunctionType(*BS);

1354 }

1355

1356 if (WS.isTag())

1357 registerTagType(WS);

1358

1359 if (WS.isTemporary())

1360 continue;

1361

1362

1363 if (!WS.isDefined() && !WS.isComdat()) {

1364 if (WS.isFunction()) {

1365 wasm::WasmImport Import;

1366 Import.Module = WS.getImportModule();

1367 Import.Field = WS.getImportName();

1369 Import.SigIndex = getFunctionType(WS);

1371 assert(WasmIndices.count(&WS) == 0);

1372 WasmIndices[&WS] = NumFunctionImports++;

1373 } else if (WS.isGlobal()) {

1374 if (WS.isWeak())

1376

1377 wasm::WasmImport Import;

1378 Import.Field = WS.getImportName();

1380 Import.Module = WS.getImportModule();

1381 Import.Global = WS.getGlobalType();

1383 assert(WasmIndices.count(&WS) == 0);

1384 WasmIndices[&WS] = NumGlobalImports++;

1385 } else if (WS.isTag()) {

1386 if (WS.isWeak())

1388

1389 wasm::WasmImport Import;

1390 Import.Module = WS.getImportModule();

1391 Import.Field = WS.getImportName();

1393 Import.SigIndex = getTagType(WS);

1395 assert(WasmIndices.count(&WS) == 0);

1396 WasmIndices[&WS] = NumTagImports++;

1397 } else if (WS.isTable()) {

1398 if (WS.isWeak())

1400

1401 wasm::WasmImport Import;

1402 Import.Module = WS.getImportModule();

1403 Import.Field = WS.getImportName();

1405 Import.Table = WS.getTableType();

1407 assert(WasmIndices.count(&WS) == 0);

1408 WasmIndices[&WS] = NumTableImports++;

1409 }

1410 }

1411 }

1412

1413

1414 for (const MCSymbol &S : Asm.symbols()) {

1415 const auto &WS = static_cast<const MCSymbolWasm &>(S);

1416 if (WS.isUsedInGOT()) {

1417 wasm::WasmImport Import;

1418 if (WS.isFunction())

1419 Import.Module = "GOT.func";

1420 else

1421 Import.Module = "GOT.mem";

1422 Import.Field = WS.getName();

1426 assert(GOTIndices.count(&WS) == 0);

1427 GOTIndices[&WS] = NumGlobalImports++;

1428 }

1429 }

1430}

1431

1432uint64_t WasmObjectWriter::writeObject() {

1434 W = &MainWriter;

1435 if (IsSplitDwarf) {

1436 uint64_t TotalSize = writeOneObject(*Asm, DwoMode::NonDwoOnly);

1439 W = &DwoWriter;

1440 return TotalSize + writeOneObject(*Asm, DwoMode::DwoOnly);

1441 } else {

1442 return writeOneObject(*Asm, DwoMode::AllSections);

1443 }

1444}

1445

1446uint64_t WasmObjectWriter::writeOneObject(MCAssembler &Asm,

1447 DwoMode Mode) {

1448 uint64_t StartOffset = W->OS.tell();

1449 SectionCount = 0;

1450 CustomSections.clear();

1451

1452 LLVM_DEBUG(dbgs() << "WasmObjectWriter::writeObject\n");

1453

1454

1456 SmallVector<uint32_t, 4> TableElems;

1464 std::map<StringRef, std::vector> Comdats;

1466 if (Mode != DwoMode::DwoOnly)

1467 prepareImports(Imports, Asm);

1468

1469

1470

1471 for (MCSection &Sec : Asm) {

1472 auto &Section = static_cast<MCSectionWasm &>(Sec);

1474

1476 continue;

1478 continue;

1479

1480 LLVM_DEBUG(dbgs() << "Processing Section " << SectionName << " group "

1481 << Section.getGroup() << "\n";);

1482

1483

1484

1485 if (SectionName.starts_with(".init_array") &&

1487 continue;

1488

1489

1491 continue;

1492

1493 if (Section.isWasmData()) {

1494 uint32_t SegmentIndex = DataSegments.size();

1496 DataSegments.emplace_back();

1497 WasmDataSegment &Segment = DataSegments.back();

1499 Segment.InitFlags = Section.getPassive()

1501 : 0;

1503 Segment.Section = &Section;

1504 addData(Segment.Data, Section);

1505 Segment.Alignment = Log2(Section.getAlign());

1506 Segment.LinkingFlags = Section.getSegmentFlags();

1507 DataSize += Segment.Data.size();

1508 Section.setSegmentIndex(SegmentIndex);

1509

1510 if (const MCSymbolWasm *C = Section.getGroup()) {

1511 Comdats[C->getName()].emplace_back(

1513 }

1514 } else {

1515

1517

1519

1520

1521 Name.consume_front(".custom_section.");

1522

1523 auto *Begin = static_cast<MCSymbolWasm *>(Sec.getBeginSymbol());

1524 if (Begin) {

1525 assert(WasmIndices.count(Begin) == 0);

1526 WasmIndices[Begin] = CustomSections.size();

1527 }

1528

1529

1530 if (Name == "producers") {

1531 ProducersSection = std::make_unique(Name, &Section);

1532 continue;

1533 }

1534 if (Name == "target_features") {

1535 TargetFeaturesSection =

1536 std::make_unique(Name, &Section);

1537 continue;

1538 }

1539

1540

1541

1542

1543

1544 if (const MCSymbolWasm *C = Section.getGroup()) {

1545 Comdats[C->getName()].emplace_back(

1547 static_cast<uint32_t>(CustomSections.size())});

1548 }

1549

1550 CustomSections.emplace_back(Name, &Section);

1551 }

1552 }

1553

1554 if (Mode != DwoMode::DwoOnly) {

1555

1556 for (const MCSymbol &S : Asm.symbols()) {

1557

1558

1559 if (S.isTemporary() && S.getName().empty())

1560 continue;

1561

1562 const auto &WS = static_cast<const MCSymbolWasm &>(S);

1564 dbgs() << "MCSymbol: "

1566 << " '" << S << "'"

1567 << " isDefined=" << S.isDefined() << " isExternal="

1568 << WS.isExternal() << " isTemporary=" << S.isTemporary()

1569 << " isWeak=" << WS.isWeak() << " isHidden=" << WS.isHidden()

1570 << " isVariable=" << WS.isVariable() << "\n");

1571

1572 if (WS.isVariable())

1573 continue;

1574 if (WS.isComdat() && !WS.isDefined())

1575 continue;

1576

1577 if (WS.isFunction()) {

1579 if (WS.isDefined()) {

1580 if (WS.getOffset() != 0)

1582 "function sections must contain one function each");

1583

1584

1585 Index = NumFunctionImports + Functions.size();

1586 WasmFunction Func;

1587 Func.SigIndex = getFunctionType(WS);

1588 Func.Section = &WS.getSection();

1589 assert(WasmIndices.count(&WS) == 0);

1590 WasmIndices[&WS] = Index;

1592

1593 auto &Section = static_cast<MCSectionWasm &>(WS.getSection());

1594 if (const MCSymbolWasm *C = Section.getGroup()) {

1595 Comdats[C->getName()].emplace_back(

1597 }

1598

1599 if (WS.hasExportName()) {

1600 wasm::WasmExport Export;

1601 Export.Name = WS.getExportName();

1605 }

1606 } else {

1607

1608 Index = WasmIndices.find(&WS)->second;

1609 }

1610

1611 LLVM_DEBUG(dbgs() << " -> function index: " << Index << "\n");

1612

1613 } else if (WS.isData()) {

1615 continue;

1616

1617 if (!WS.isDefined()) {

1619 << "\n");

1620 continue;

1621 }

1622

1623 if (!WS.getSize())

1624 report_fatal_error("data symbols must have a size set with .size: " +

1625 WS.getName());

1626

1627 int64_t Size = 0;

1628 if (!WS.getSize()->evaluateAsAbsolute(Size, Asm))

1630

1631 auto &DataSection = static_cast<MCSectionWasm &>(WS.getSection());

1632 if (!DataSection.isWasmData())

1634 WS.getName());

1635

1636

1637

1638 wasm::WasmDataReference Ref = wasm::WasmDataReference{

1639 DataSection.getSegmentIndex(), Asm.getSymbolOffset(WS),

1640 static_cast<uint64_t>(Size)};

1641 assert(DataLocations.count(&WS) == 0);

1642 DataLocations[&WS] = Ref;

1643 LLVM_DEBUG(dbgs() << " -> segment index: " << Ref.Segment << "\n");

1644

1645 } else if (WS.isGlobal()) {

1646

1647 if (WS.isDefined()) {

1648 wasm::WasmGlobal Global;

1649 Global.Type = WS.getGlobalType();

1650 Global.Index = NumGlobalImports + Globals.size();

1651 Global.InitExpr.Extended = false;

1652 switch (Global.Type.Type) {

1655 break;

1658 break;

1661 break;

1664 break;

1667 break;

1668 default:

1670 }

1671 assert(WasmIndices.count(&WS) == 0);

1672 WasmIndices[&WS] = Global.Index;

1674 } else {

1675

1677 << WasmIndices.find(&WS)->second << "\n");

1678 }

1679 } else if (WS.isTable()) {

1680 if (WS.isDefined()) {

1681 wasm::WasmTable Table;

1682 Table.Index = NumTableImports + Tables.size();

1683 Table.Type = WS.getTableType();

1684 assert(WasmIndices.count(&WS) == 0);

1685 WasmIndices[&WS] = Table.Index;

1687 }

1689 << WasmIndices.find(&WS)->second << "\n");

1690 } else if (WS.isTag()) {

1691

1692

1694 if (WS.isDefined()) {

1695 Index = NumTagImports + TagTypes.size();

1696 uint32_t SigIndex = getTagType(WS);

1697 assert(WasmIndices.count(&WS) == 0);

1698 WasmIndices[&WS] = Index;

1700 } else {

1701

1702 assert(WasmIndices.count(&WS) > 0);

1703 }

1704 LLVM_DEBUG(dbgs() << " -> tag index: " << WasmIndices.find(&WS)->second

1705 << "\n");

1706

1707 } else {

1708 assert(WS.isSection());

1709 }

1710 }

1711

1712

1713

1714

1715

1716 for (const MCSymbol &S : Asm.symbols()) {

1717 if (!S.isVariable())

1718 continue;

1719

1720 assert(S.isDefined());

1721

1722 const auto *BS = Asm.getBaseSymbol(S);

1723 if (!BS)

1725 ": absolute addressing not supported!");

1726 const MCSymbolWasm *Base = static_cast<const MCSymbolWasm *>(BS);

1727

1728

1729 const auto &WS = static_cast<const MCSymbolWasm &>(S);

1731 << "'\n");

1732

1733 if (Base->isFunction()) {

1734 assert(WasmIndices.count(Base) > 0);

1735 uint32_t WasmIndex = WasmIndices.find(Base)->second;

1736 assert(WasmIndices.count(&WS) == 0);

1737 WasmIndices[&WS] = WasmIndex;

1738 LLVM_DEBUG(dbgs() << " -> index:" << WasmIndex << "\n");

1739 } else if (Base->isData()) {

1740 auto &DataSection = static_cast<MCSectionWasm &>(WS.getSection());

1741 uint64_t Offset = Asm.getSymbolOffset(S);

1742 int64_t Size = 0;

1743

1744

1745

1746

1747 if (Base->getSize()->evaluateAsAbsolute(Size, Asm))

1749 const WasmDataSegment &Segment =

1750 DataSegments[DataSection.getSegmentIndex()];

1752 std::min(static_cast<uint64_t>(Size), Segment.Data.size() - Offset);

1753 wasm::WasmDataReference Ref = wasm::WasmDataReference{

1754 DataSection.getSegmentIndex(),

1755 static_cast<uint32_t>(Asm.getSymbolOffset(S)),

1756 static_cast<uint32_t>(Size)};

1757 DataLocations[&WS] = Ref;

1759 } else {

1761 }

1762 }

1763 }

1764

1765

1766 for (const MCSymbol &S : Asm.symbols()) {

1767 const auto &WS = static_cast<const MCSymbolWasm &>(S);

1770 continue;

1771 }

1772

1773

1774

1775

1776

1777

1778

1779

1780

1781

1782 if (WS.isData() && WS.isDefined() && !DataLocations.count(&WS))

1783 continue;

1784 LLVM_DEBUG(dbgs() << "adding to symtab: " << WS << "\n");

1785

1786 uint32_t Flags = 0;

1787 if (WS.isWeak())

1789 if (WS.isHidden())

1791 if (!WS.isExternal() && WS.isDefined())

1793 if (WS.isUndefined())

1795 if (WS.isNoStrip()) {

1797 if (isEmscripten()) {

1799 }

1800 }

1801 if (WS.hasImportName())

1803 if (WS.hasExportName())

1805 if (WS.isTLS())

1807

1808 wasm::WasmSymbolInfo Info;

1809 Info.Name = WS.getName();

1812 if (!WS.isData()) {

1813 assert(WasmIndices.count(&WS) > 0);

1814 Info.ElementIndex = WasmIndices.find(&WS)->second;

1815 } else if (WS.isDefined()) {

1816 assert(DataLocations.count(&WS) > 0);

1817 Info.DataRef = DataLocations.find(&WS)->second;

1818 }

1819 WS.setIndex(SymbolInfos.size());

1821 }

1822

1823 {

1824 auto HandleReloc = [&](const WasmRelocationEntry &Rel) {

1825

1826

1827

1828 if (Rel.Type != wasm::R_WASM_TABLE_INDEX_I32 &&

1829 Rel.Type != wasm::R_WASM_TABLE_INDEX_I64 &&

1830 Rel.Type != wasm::R_WASM_TABLE_INDEX_SLEB &&

1831 Rel.Type != wasm::R_WASM_TABLE_INDEX_SLEB64 &&

1832 Rel.Type != wasm::R_WASM_TABLE_INDEX_REL_SLEB &&

1833 Rel.Type != wasm::R_WASM_TABLE_INDEX_REL_SLEB64)

1834 return;

1835 assert(Rel.Symbol->isFunction());

1836 auto *Base =

1837 static_cast<const MCSymbolWasm *>(Asm.getBaseSymbol(*Rel.Symbol));

1838 uint32_t FunctionIndex = WasmIndices.find(Base)->second;

1839 uint32_t TableIndex = TableElems.size() + InitialTableOffset;

1840 if (TableIndices.try_emplace(Base, TableIndex).second) {

1842 << " to table: " << TableIndex << "\n");

1843 TableElems.push_back(FunctionIndex);

1844 registerFunctionType(*Base);

1845 }

1846 };

1847

1848 for (const WasmRelocationEntry &RelEntry : CodeRelocations)

1849 HandleReloc(RelEntry);

1850 for (const WasmRelocationEntry &RelEntry : DataRelocations)

1851 HandleReloc(RelEntry);

1852 }

1853

1854

1855 for (const MCSection &S : Asm) {

1856 const auto &WS = static_cast<const MCSectionWasm &>(S);

1857 if (WS.getName().starts_with(".fini_array"))

1859 if (!WS.getName().starts_with(".init_array"))

1860 continue;

1861 auto IT = WS.begin();

1862 if (IT == WS.end())

1863 continue;

1864 for (auto *Frag = &*IT; Frag; Frag = Frag->getNext()) {

1868

1869 uint16_t Priority = UINT16_MAX;

1870 unsigned PrefixLength = strlen(".init_array");

1871 if (WS.getName().size() > PrefixLength) {

1872 if (WS.getName()[PrefixLength] != '.')

1874 ".init_array section priority should start with '.'");

1875 if (WS.getName().substr(PrefixLength + 1).getAsInteger(10, Priority))

1877 }

1879 for (const MCFixup &Fixup : Frag->getFixups()) {

1882 const MCExpr *Expr = Fixup.getValue();

1884 if (!SymRef)

1886 "fixups in .init_array should be symbol references");

1887 auto &TargetSym =

1888 static_cast<const MCSymbolWasm &>(SymRef->getSymbol());

1890 report_fatal_error("symbols in .init_array should exist in symtab");

1891 if (!TargetSym.isFunction())

1892 report_fatal_error("symbols in .init_array should be for functions");

1893 InitFuncs.push_back(std::make_pair(Priority, TargetSym.getIndex()));

1894 }

1895 }

1896 }

1897

1898

1899 writeHeader(Asm);

1900

1901 uint32_t CodeSectionIndex, DataSectionIndex;

1902 if (Mode != DwoMode::DwoOnly) {

1903 writeTypeSection(Signatures);

1904 writeImportSection(Imports, DataSize, TableElems.size());

1905 writeFunctionSection(Functions);

1906 writeTableSection(Tables);

1907

1908 writeTagSection(TagTypes);

1909 writeGlobalSection(Globals);

1910 writeExportSection(Exports);

1911 const MCSymbol *IndirectFunctionTable =

1912 getContext().lookupSymbol("__indirect_function_table");

1913 writeElemSection(static_cast<const MCSymbolWasm *>(IndirectFunctionTable),

1914 TableElems);

1915 writeDataCountSection();

1916

1917 CodeSectionIndex = writeCodeSection(Asm, Functions);

1918 DataSectionIndex = writeDataSection(Asm);

1919 }

1920

1921

1922

1923 for (auto &Group : Comdats) {

1924 for (auto &Entry : Group.second) {

1926 Entry.Index += SectionCount;

1927 }

1928 }

1929 }

1930 for (auto &CustomSection : CustomSections)

1931 writeCustomSection(CustomSection, Asm);

1932

1933 if (Mode != DwoMode::DwoOnly) {

1934 writeLinkingMetaDataSection(SymbolInfos, InitFuncs, Comdats);

1935

1936 writeRelocSection(CodeSectionIndex, "CODE", CodeRelocations);

1937 writeRelocSection(DataSectionIndex, "DATA", DataRelocations);

1938 }

1939 writeCustomRelocSections();

1940 if (ProducersSection)

1941 writeCustomSection(*ProducersSection, Asm);

1942 if (TargetFeaturesSection)

1943 writeCustomSection(*TargetFeaturesSection, Asm);

1944

1945

1946 return W->OS.tell() - StartOffset;

1947}

1948

1949std::unique_ptr

1952 return std::make_unique(std::move(MOTW), OS);

1953}

1954

1955std::unique_ptr

1959 return std::make_unique(std::move(MOTW), OS, DwoOS);

1960}

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

static cl::opt< ITMode > IT(cl::desc("IT block support"), cl::Hidden, cl::init(DefaultIT), cl::values(clEnumValN(DefaultIT, "arm-default-it", "Generate any type of IT block"), clEnumValN(RestrictedIT, "arm-restrict-it", "Disallow complex IT blocks")))

static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")

static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")

Analysis containing CSE Info

#define LLVM_DUMP_METHOD

Mark debug helper function definitions like dump() that should not be stripped from debug builds.

PowerPC TLS Dynamic Call Fixup

static cl::opt< RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode > Mode("regalloc-enable-advisor", cl::Hidden, cl::init(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default), cl::desc("Enable regalloc advisor mode"), cl::values(clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default, "default", "Default"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Release, "release", "precompiled"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Development, "development", "for training")))

static const unsigned InvalidIndex

static bool isSectionReferenced(MCAssembler &Asm, MCSectionWasm &Section)

Definition WasmObjectWriter.cpp:1311

static void addData(SmallVectorImpl< char > &DataBytes, MCSectionWasm &DataSection)

Definition WasmObjectWriter.cpp:693

static bool isInSymtab(const MCSymbolWasm &Sym)

Definition WasmObjectWriter.cpp:1292

static bool isDwoSection(const MCSection &Sec)

static bool is64Bit(const char *name)

ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...

size_t size() const

size - Get the array size.

bool empty() const

empty - Check if the array is empty.

LLVM_ABI MCSymbol * lookupSymbol(const Twine &Name) const

Get the symbol for Name, or null.

LLVM_ABI void reportError(SMLoc L, const Twine &Msg)

Encode information on a single operation to perform on a byte sequence (e.g., an encoded instruction)...

static MCFixupKind getDataKindForSize(unsigned Size)

Return the generic fixup kind for a value with the given size.

Defines the object file and target independent interfaces used by the assembler backend to write nati...

virtual void reset()

lifetime management

This represents a section on wasm.

uint64_t getSectionOffset() const

Instances of this class represent a uniqued identifier for a section in the current translation unit.

StringRef getName() const

MCSymbol * getBeginSymbol()

bool omitFromLinkingSection() const

bool isUsedInInitArray() const

MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...

bool isDefined() const

isDefined - Check if this symbol is defined (i.e., it has an address).

StringRef getName() const

getName - Get the symbol name.

uint32_t getIndex() const

Get the (implementation defined) index.

MCSection & getSection() const

Get the section associated with a defined, non-absolute symbol.

bool isTemporary() const

isTemporary - Check if this is an assembler temporary symbol.

bool isUsedInReloc() const

This class consists of common code factored out of the SmallVector class to reduce code duplication b...

reference emplace_back(ArgTypes &&... Args)

iterator insert(iterator I, T &&Elt)

void push_back(const T &Elt)

This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.

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

bool ends_with(StringRef Suffix) const

Check if this string ends with the given Suffix.

Target - Wrapper for Target specific information.

The instances of the Type class are immutable: once they are created, they are never changed.

LLVM Value Representation.

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

uint64_t tell() const

tell - Return the current offset with the file.

raw_ostream & write(unsigned char C)

An abstract base class for streams implementations that also support a pwrite operation.

void pwrite(const char *Ptr, size_t Size, uint64_t Offset)

#define llvm_unreachable(msg)

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

constexpr char Align[]

Key for Kernel::Arg::Metadata::mAlign.

@ C

The default llvm calling convention, compatible with C.

bool isRelocRelocation(MCFixupKind FixupKind)

NodeAddr< FuncNode * > Func

Context & getContext() const

void write64le(void *P, uint64_t V)

void write32le(void *P, uint32_t V)

const unsigned WASM_SYMBOL_UNDEFINED

const unsigned WASM_SYMBOL_NO_STRIP

const unsigned WASM_SYMBOL_TLS

const uint32_t WasmMetadataVersion

const unsigned WASM_SYMBOL_BINDING_WEAK

const unsigned WASM_SYMBOL_BINDING_LOCAL

@ 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

const uint32_t WasmVersion

const unsigned WASM_SYMBOL_EXPORTED

@ WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER

LLVM_ABI bool relocTypeHasAddend(uint32_t type)

const uint32_t WasmDefaultPageSize

const unsigned WASM_SYMBOL_EXPLICIT_NAME

const unsigned WASM_SYMBOL_VISIBILITY_HIDDEN

const unsigned WASM_ELEM_SEGMENT_MASK_HAS_ELEM_DESC

LLVM_ABI llvm::StringRef relocTypetoString(uint32_t type)

This is an optimization pass for GlobalISel generic memory operations.

void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)

FunctionAddr VTableAddr Value

void stable_sort(R &&Range)

bool all_of(R &&range, UnaryPredicate P)

Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.

Printable print(const GCNRegPressure &RP, const GCNSubtarget *ST=nullptr, unsigned DynamicVGPRBlockSize=0)

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.

void append_range(Container &C, Range &&R)

Wrapper function to append range R to container C.

FunctionAddr VTableAddr uintptr_t uintptr_t DataSize

std::unique_ptr< MCObjectWriter > createWasmObjectWriter(std::unique_ptr< MCWasmObjectTargetWriter > MOTW, raw_pwrite_stream &OS)

Construct a new Wasm writer instance.

Definition WasmObjectWriter.cpp:1950

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)

class LLVM_GSL_OWNER SmallVector

Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...

uint64_t offsetToAlignment(uint64_t Value, Align Alignment)

Returns the offset to the next integer (mod 2**64) that is greater than or equal to Value and is a mu...

LLVM_ABI raw_fd_ostream & errs()

This returns a reference to a raw_ostream for standard error.

@ Global

Append to llvm.global_dtors.

@ Ref

The access may reference the value stored in memory.

@ FirstLiteralRelocationKind

FunctionAddr VTableAddr uintptr_t uintptr_t Data

uint64_t alignTo(uint64_t Size, Align A)

Returns a multiple of A needed to store Size bytes.

raw_ostream & operator<<(raw_ostream &OS, const APFixedPoint &FX)

ArrayRef(const T &OneElt) -> ArrayRef< T >

std::string toString(const APInt &I, unsigned Radix, bool Signed, bool formatAsCLiteral=false, bool UpperCase=true, bool InsertSeparators=false)

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

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

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

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

unsigned Log2(Align A)

Returns the log2 of the alignment.

std::unique_ptr< MCObjectWriter > createWasmDwoObjectWriter(std::unique_ptr< MCWasmObjectTargetWriter > MOTW, raw_pwrite_stream &OS, raw_pwrite_stream &DwoOS)

Definition WasmObjectWriter.cpp:1956

Adapter to write values to a stream in a particular byte order.

void write(ArrayRef< value_type > Val)

SmallVector< ValType, 1 > Returns

SmallVector< ValType, 4 > Params