LLVM: lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

37

38using namespace llvm;

39

40#define DEBUG_TYPE "wasm-asm-parser"

41

43

44namespace {

45

46

47

49 enum KindTy { Token, Integer, Float, Symbol, BrList, CatchList } Kind;

50

51 SMLoc StartLoc, EndLoc;

52

53 struct TokOp {

54 StringRef Tok;

55 };

56

57 struct IntOp {

58 int64_t Val;

59 };

60

61 struct FltOp {

62 double Val;

63 };

64

65 struct SymOp {

66 const MCExpr *Exp;

67 };

68

69 struct BrLOp {

70 std::vector List;

71 };

72

73 struct CaLOpElem {

74 uint8_t Opcode;

75 const MCExpr *Tag;

76 unsigned Dest;

77 };

78

79 struct CaLOp {

80 std::vector List;

81 };

82

83 union {

84 struct TokOp Tok;

85 struct IntOp Int;

86 struct FltOp Flt;

87 struct SymOp Sym;

88 struct BrLOp BrL;

89 struct CaLOp CaL;

90 };

91

92 WebAssemblyOperand(SMLoc Start, SMLoc End, TokOp T)

93 : Kind(Token), StartLoc(Start), EndLoc(End), Tok(T) {}

94 WebAssemblyOperand(SMLoc Start, SMLoc End, IntOp I)

95 : Kind(Integer), StartLoc(Start), EndLoc(End), Int(I) {}

96 WebAssemblyOperand(SMLoc Start, SMLoc End, FltOp F)

97 : Kind(Float), StartLoc(Start), EndLoc(End), Flt(F) {}

98 WebAssemblyOperand(SMLoc Start, SMLoc End, SymOp S)

99 : Kind(Symbol), StartLoc(Start), EndLoc(End), Sym(S) {}

100 WebAssemblyOperand(SMLoc Start, SMLoc End, BrLOp B)

101 : Kind(BrList), StartLoc(Start), EndLoc(End), BrL(B) {}

102 WebAssemblyOperand(SMLoc Start, SMLoc End, CaLOp C)

103 : Kind(CatchList), StartLoc(Start), EndLoc(End), CaL(C) {}

104

105 ~WebAssemblyOperand() override {

106 if (isBrList())

107 BrL.~BrLOp();

108 if (isCatchList())

109 CaL.~CaLOp();

110 }

111

112 bool isToken() const override { return Kind == Token; }

113 bool isImm() const override { return Kind == Integer || Kind == Symbol; }

114 bool isFPImm() const { return Kind == Float; }

115 bool isMem() const override { return false; }

116 bool isReg() const override { return false; }

117 bool isBrList() const { return Kind == BrList; }

118 bool isCatchList() const { return Kind == CatchList; }

119

120 MCRegister getReg() const override {

122 return 0;

123 }

124

127 return Tok.Tok;

128 }

129

130 SMLoc getStartLoc() const override { return StartLoc; }

131 SMLoc getEndLoc() const override { return EndLoc; }

132

133 void addRegOperands(MCInst &, unsigned) const {

134

135 llvm_unreachable("Assembly matcher creates register operands");

136 }

137

138 void addImmOperands(MCInst &Inst, unsigned N) const {

139 assert(N == 1 && "Invalid number of operands!");

140 if (Kind == Integer)

142 else if (Kind == Symbol)

144 else

146 }

147

148 void addFPImmf32Operands(MCInst &Inst, unsigned N) const {

149 assert(N == 1 && "Invalid number of operands!");

150 if (Kind == Float)

153 else

155 }

156

157 void addFPImmf64Operands(MCInst &Inst, unsigned N) const {

158 assert(N == 1 && "Invalid number of operands!");

159 if (Kind == Float)

161 else

163 }

164

165 void addBrListOperands(MCInst &Inst, unsigned N) const {

166 assert(N == 1 && isBrList() && "Invalid BrList!");

167 for (auto Br : BrL.List)

169 }

170

171 void addCatchListOperands(MCInst &Inst, unsigned N) const {

172 assert(N == 1 && isCatchList() && "Invalid CatchList!");

174 for (auto Ca : CaL.List) {

180 }

181 }

182

183 void print(raw_ostream &OS, const MCAsmInfo &MAI) const override {

184 switch (Kind) {

185 case Token:

186 OS << "Tok:" << Tok.Tok;

187 break;

188 case Integer:

189 OS << "Int:" << Int.Val;

190 break;

191 case Float:

192 OS << "Flt:" << Flt.Val;

193 break;

194 case Symbol:

195 OS << "Sym:" << Sym.Exp;

196 break;

197 case BrList:

198 OS << "BrList:" << BrL.List.size();

199 break;

200 case CatchList:

201 OS << "CaList:" << CaL.List.size();

202 break;

203 }

204 }

205};

206

207

210}

211

214 bool Is64) {

215 auto *Sym = static_cast<MCSymbolWasm *>(Ctx.lookupSymbol(Name));

216 if (Sym) {

217 if (!Sym->isFunctionTable())

218 Ctx.reportError(SMLoc(), "symbol is not a wasm funcref table");

219 } else {

220 Sym = static_cast<MCSymbolWasm *>(Ctx.getOrCreateSymbol(Name));

222

223 }

224 return Sym;

225}

226

228 MCAsmParser &Parser;

229 AsmLexer &Lexer;

230

231

232

233

234

235

236

237 enum ParserState {

238 FileStart,

239 FunctionLabel,

240 FunctionStart,

241 FunctionLocals,

242 Instructions,

243 EndFunction,

244 DataSection,

245 } CurrentState = FileStart;

246

247

248 enum NestingType {

249 Function,

250 Block,

251 Loop,

252 Try,

253 CatchAll,

254 TryTable,

255 If,

256 Else,

257 Undefined,

258 };

259 struct Nested {

260 NestingType NT;

261 wasm::WasmSignature Sig;

262 };

263 std::vector NestingStack;

264

265 MCSymbolWasm *DefaultFunctionTable = nullptr;

266 MCSymbol *LastFunctionLabel = nullptr;

267

268 bool Is64;

269

270 WebAssemblyAsmTypeCheck TC;

271

272 bool SkipTypeCheck;

273

274public:

275 WebAssemblyAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,

276 const MCInstrInfo &MII, const MCTargetOptions &Options)

277 : MCTargetAsmParser(Options, STI, MII), Parser(Parser),

278 Lexer(Parser.getLexer()), Is64(STI.getTargetTriple().isArch64Bit()),

279 TC(Parser, MII, Is64), SkipTypeCheck(Options.MCNoTypeCheck) {

280 FeatureBitset FBS = ComputeAvailableFeatures(STI.getFeatureBits());

281

282

283 if (FBS.test(WebAssembly::FeatureBulkMemory)) {

284 FBS.set(WebAssembly::FeatureBulkMemoryOpt);

285 }

286

287 if (FBS.test(WebAssembly::FeatureReferenceTypes)) {

288 FBS.set(WebAssembly::FeatureCallIndirectOverlong);

289 }

290

291 setAvailableFeatures(FBS);

292

293

294 auto &SM = Parser.getSourceManager();

295 auto BufferName =

296 SM.getBufferInfo(SM.getMainFileID()).Buffer->getBufferIdentifier();

297 if (BufferName == "")

298 SkipTypeCheck = true;

299 }

300

301 void Initialize(MCAsmParser &Parser) override {

303

305 getContext(), "__indirect_function_table", Is64);

306 if (!STI->checkFeatures("+call-indirect-overlong") &&

308 DefaultFunctionTable->setOmitFromLinkingSection();

309 }

310

311#define GET_ASSEMBLER_HEADER

312#include "WebAssemblyGenAsmMatcher.inc"

313

314

317 }

318 ParseStatus tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,

319 SMLoc &EndLoc) override {

321 }

322

323 bool error(const Twine &Msg, const AsmToken &Tok) {

324 return Parser.Error(Tok.getLoc(), Msg + Tok.getString());

325 }

326

327 bool error(const Twine &Msg, SMLoc Loc = SMLoc()) {

328 return Parser.Error(Loc.isValid() ? Loc : Lexer.getTok().getLoc(), Msg);

329 }

330

331 std::pair<StringRef, StringRef> nestingString(NestingType NT) {

332 switch (NT) {

333 case Function:

334 return {"function", "end_function"};

335 case Block:

336 return {"block", "end_block"};

337 case Loop:

338 return {"loop", "end_loop"};

339 case Try:

340 return {"try", "end_try/delegate"};

341 case CatchAll:

342 return {"catch_all", "end_try"};

343 case TryTable:

344 return {"try_table", "end_try_table"};

345 case If:

346 return {"if", "end_if"};

347 case Else:

348 return {"else", "end_if"};

349 default:

351 }

352 }

353

354 void push(NestingType NT, wasm::WasmSignature Sig = wasm::WasmSignature()) {

355 NestingStack.push_back({NT, Sig});

356 }

357

358 bool pop(StringRef Ins, NestingType NT1, NestingType NT2 = Undefined) {

359 if (NestingStack.empty())

360 return error(Twine("End of block construct with no start: ") + Ins);

361 auto Top = NestingStack.back();

362 if (Top.NT != NT1 && Top.NT != NT2)

363 return error(Twine("Block construct type mismatch, expected: ") +

364 nestingString(Top.NT).second + ", instead got: " + Ins);

365 TC.setLastSig(Top.Sig);

366 NestingStack.pop_back();

367 return false;

368 }

369

370

371

372 bool popAndPushWithSameSignature(StringRef Ins, NestingType PopNT,

373 NestingType PushNT) {

374 if (NestingStack.empty())

375 return error(Twine("End of block construct with no start: ") + Ins);

376 auto Sig = NestingStack.back().Sig;

377 if (pop(Ins, PopNT))

378 return true;

379 push(PushNT, Sig);

380 return false;

381 }

382

383 bool ensureEmptyNestingStack(SMLoc Loc = SMLoc()) {

384 auto Err = !NestingStack.empty();

385 while (!NestingStack.empty()) {

386 error(Twine("Unmatched block construct(s) at function end: ") +

387 nestingString(NestingStack.back().NT).first,

388 Loc);

389 NestingStack.pop_back();

390 }

391 return Err;

392 }

393

395 auto Ok = Lexer.is(Kind);

396 if (Ok)

397 Parser.Lex();

398 return Ok;

399 }

400

402 if (!isNext(Kind))

403 return error(std::string("Expected ") + KindName + ", instead got: ",

404 Lexer.getTok());

405 return false;

406 }

407

408 StringRef expectIdent() {

410 error("Expected identifier, got: ", Lexer.getTok());

411 return StringRef();

412 }

413 auto Name = Lexer.getTok().getString();

414 Parser.Lex();

416 }

417

418 bool parseRegTypeList(SmallVectorImplwasm::ValType &Types) {

422 return error("unknown type: ", Lexer.getTok());

424 Parser.Lex();

426 break;

427 }

428 return false;

429 }

430

431 void parseSingleInteger(bool IsNegative, OperandVector &Operands) {

432 auto &Int = Lexer.getTok();

433 int64_t Val = Int.getIntVal();

434 if (IsNegative)

435 Val = -Val;

436 Operands.push_back(std::make_unique(

437 Int.getLoc(), Int.getEndLoc(), WebAssemblyOperand::IntOp{Val}));

438 Parser.Lex();

439 }

440

441 bool parseSingleFloat(bool IsNegative, OperandVector &Operands) {

442 auto &Flt = Lexer.getTok();

443 double Val;

444 if (Flt.getString().getAsDouble(Val, false))

445 return error("Cannot parse real: ", Flt);

446 if (IsNegative)

447 Val = -Val;

448 Operands.push_back(std::make_unique(

449 Flt.getLoc(), Flt.getEndLoc(), WebAssemblyOperand::FltOp{Val}));

450 Parser.Lex();

451 return false;

452 }

453

454 bool parseSpecialFloatMaybe(bool IsNegative, OperandVector &Operands) {

456 return true;

457 auto &Flt = Lexer.getTok();

458 auto S = Flt.getString();

459 double Val;

460 if (S.compare_insensitive("infinity") == 0) {

461 Val = std::numeric_limits::infinity();

462 } else if (S.compare_insensitive("nan") == 0) {

463 Val = std::numeric_limits::quiet_NaN();

464 } else {

465 return true;

466 }

467 if (IsNegative)

468 Val = -Val;

469 Operands.push_back(std::make_unique(

470 Flt.getLoc(), Flt.getEndLoc(), WebAssemblyOperand::FltOp{Val}));

471 Parser.Lex();

472 return false;

473 }

474

475 bool checkForP2AlignIfLoadStore(OperandVector &Operands, StringRef InstName) {

476

477 auto IsLoadStore = InstName.contains(".load") ||

478 InstName.contains(".store") ||

479 InstName.contains("prefetch");

480 auto IsAtomic = InstName.contains("atomic.");

481 if (IsLoadStore || IsAtomic) {

482

484 auto Id = expectIdent();

485 if (Id != "p2align")

486 return error("Expected p2align, instead got: " + Id);

488 return true;

490 return error("Expected integer constant");

491 parseSingleInteger(false, Operands);

492 } else {

493

494

495

496 auto IsLoadStoreLane = InstName.contains("_lane");

497 if (IsLoadStoreLane && Operands.size() == 4)

498 return false;

499

500

501

502

503 auto Tok = Lexer.getTok();

504 Operands.push_back(std::make_unique(

505 Tok.getLoc(), Tok.getEndLoc(), WebAssemblyOperand::IntOp{-1}));

506 }

507 }

508 return false;

509 }

510

511 void addBlockTypeOperand(OperandVector &Operands, SMLoc NameLoc,

513 if (BT == WebAssembly::BlockType::Void) {

514 TC.setLastSig(wasm::WasmSignature{});

515 } else {

516 wasm::WasmSignature Sig({static_cast<wasm::ValType>(BT)}, {});

517 TC.setLastSig(Sig);

518 NestingStack.back().Sig = Sig;

519 }

520 Operands.push_back(std::make_unique(

521 NameLoc, NameLoc, WebAssemblyOperand::IntOp{static_cast<int64_t>(BT)}));

522 }

523

524 bool parseLimits(wasm::WasmLimits *Limits) {

525 auto Tok = Lexer.getTok();

527 return error("Expected integer constant, instead got: ", Tok);

531 Parser.Lex();

532

535 auto Tok = Lexer.getTok();

537 return error("Expected integer constant, instead got: ", Tok);

541 Parser.Lex();

542 }

543 return false;

544 }

545

546 bool parseFunctionTableOperand(std::unique_ptr *Op) {

547 if (STI->checkFeatures("+call-indirect-overlong") ||

549

550

551

552

553

554 auto &Tok = Lexer.getTok();

556 auto *Sym =

559 *Op = std::make_unique(

560 Tok.getLoc(), Tok.getEndLoc(), WebAssemblyOperand::SymOp{Val});

561 Parser.Lex();

563 }

564 const auto *Val =

566 *Op = std::make_unique(

567 SMLoc(), SMLoc(), WebAssemblyOperand::SymOp{Val});

568 return false;

569 }

570

571

572

573 getStreamer().emitSymbolAttribute(DefaultFunctionTable, MCSA_NoDeadStrip);

574 *Op = std::make_unique(SMLoc(), SMLoc(),

575 WebAssemblyOperand::IntOp{0});

576 return false;

577 }

578

579 bool parseInstruction(ParseInstructionInfo & , StringRef Name,

580 SMLoc NameLoc, OperandVector &Operands) override {

581

582

584

585

586

587

588 for (;;) {

589 auto &Sep = Lexer.getTok();

590 if (Sep.getLoc().getPointer() != Name.end() ||

592 break;

593

594 Name = StringRef(Name.begin(), Name.size() + Sep.getString().size());

595 Parser.Lex();

596

597 auto &Id = Lexer.getTok();

599 Id.getLoc().getPointer() != Name.end())

600 return error("Incomplete instruction name: ", Id);

601 Name = StringRef(Name.begin(), Name.size() + Id.getString().size());

602 Parser.Lex();

603 }

604

605

606 Operands.push_back(std::make_unique(

608 WebAssemblyOperand::TokOp{Name}));

609

610

611

612 bool ExpectBlockType = false;

613 bool ExpectFuncType = false;

614 bool ExpectCatchList = false;

615 std::unique_ptr FunctionTable;

616 if (Name == "block") {

617 push(Block);

618 ExpectBlockType = true;

619 } else if (Name == "loop") {

620 push(Loop);

621 ExpectBlockType = true;

622 } else if (Name == "try") {

623 push(Try);

624 ExpectBlockType = true;

625 } else if (Name == "if") {

626 push(If);

627 ExpectBlockType = true;

628 } else if (Name == "else") {

629 if (popAndPushWithSameSignature(Name, If, Else))

630 return true;

631 } else if (Name == "catch") {

632 if (popAndPushWithSameSignature(Name, Try, Try))

633 return true;

634 } else if (Name == "catch_all") {

635 if (popAndPushWithSameSignature(Name, Try, CatchAll))

636 return true;

637 } else if (Name == "try_table") {

638 push(TryTable);

639 ExpectBlockType = true;

640 ExpectCatchList = true;

641 } else if (Name == "end_if") {

642 if (pop(Name, If, Else))

643 return true;

644 } else if (Name == "end_try") {

645 if (pop(Name, Try, CatchAll))

646 return true;

647 } else if (Name == "end_try_table") {

648 if (pop(Name, TryTable))

649 return true;

650 } else if (Name == "delegate") {

651 if (pop(Name, Try))

652 return true;

653 } else if (Name == "end_loop") {

654 if (pop(Name, Loop))

655 return true;

656 } else if (Name == "end_block") {

657 if (pop(Name, Block))

658 return true;

659 } else if (Name == "end_function") {

660 ensureLocals(getStreamer());

661 CurrentState = EndFunction;

662 if (pop(Name, Function) || ensureEmptyNestingStack())

663 return true;

664 } else if (Name == "call_indirect" || Name == "return_call_indirect") {

665

666

667

668 if (parseFunctionTableOperand(&FunctionTable))

669 return true;

670 ExpectFuncType = true;

671 } else if (Name == "ref.test") {

672

673

674 ExpectFuncType = true;

675 }

676

677

678 auto PeekCatchList = [&]() {

680 return false;

681 AsmToken NextTok = Lexer.peekTok();

684 };

685

686

687 if (ExpectFuncType ||

688 (Lexer.is(AsmToken::LParen) && ExpectBlockType && !PeekCatchList())) {

689

690

691

692

694 auto Loc = Parser.getTok();

696 if (parseSignature(Signature))

697 return true;

698

699 TC.setLastSig(*Signature);

700 if (ExpectBlockType)

701 NestingStack.back().Sig = *Signature;

702 ExpectBlockType = false;

703

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

706 WasmSym->setSignature(Signature);

708 const MCExpr *Expr =

710 Operands.push_back(std::make_unique(

711 Loc.getLoc(), Loc.getEndLoc(), WebAssemblyOperand::SymOp{Expr}));

712 }

713

714

715

716

717

718

719

720

721 if (ExpectCatchList && PeekCatchList()) {

722 if (ExpectBlockType) {

723 ExpectBlockType = false;

724 addBlockTypeOperand(Operands, NameLoc, WebAssembly::BlockType::Void);

725 }

726 if (parseCatchList(Operands))

727 return true;

728 ExpectCatchList = false;

729 }

730

732 auto &Tok = Lexer.getTok();

735 if (!parseSpecialFloatMaybe(false, Operands))

736 break;

737 auto &Id = Lexer.getTok();

738 if (ExpectBlockType) {

739

741 if (BT == WebAssembly::BlockType::Invalid)

742 return error("Unknown block type: ", Id);

743 addBlockTypeOperand(Operands, NameLoc, BT);

744 ExpectBlockType = false;

745 Parser.Lex();

746

747

748 if (ExpectCatchList && PeekCatchList()) {

749 if (parseCatchList(Operands))

750 return true;

751 ExpectCatchList = false;

752 }

753 } else {

754

755 const MCExpr *Val;

756 SMLoc Start = Id.getLoc();

757 SMLoc End;

758 if (Parser.parseExpression(Val, End))

759 return error("Cannot parse symbol: ", Lexer.getTok());

760 Operands.push_back(std::make_unique(

761 Start, End, WebAssemblyOperand::SymOp{Val}));

762 if (checkForP2AlignIfLoadStore(Operands, Name))

763 return true;

764 }

765 break;

766 }

768 Parser.Lex();

770 parseSingleInteger(true, Operands);

771 if (checkForP2AlignIfLoadStore(Operands, Name))

772 return true;

774 if (parseSingleFloat(true, Operands))

775 return true;

776 } else if (!parseSpecialFloatMaybe(true, Operands)) {

777 } else {

778 return error("Expected numeric constant instead got: ",

779 Lexer.getTok());

780 }

781 break;

783 parseSingleInteger(false, Operands);

784 if (checkForP2AlignIfLoadStore(Operands, Name))

785 return true;

786 break;

788 if (parseSingleFloat(false, Operands))

789 return true;

790 break;

791 }

793 Parser.Lex();

794 auto Op = std::make_unique(

795 Tok.getLoc(), Tok.getEndLoc(), WebAssemblyOperand::BrLOp{});

797 for (;;) {

798 Op->BrL.List.push_back(Lexer.getTok().getIntVal());

801 break;

802 }

805 break;

806 }

807 default:

808 return error("Unexpected token in operand: ", Tok);

809 }

812 return true;

813 }

814 }

815

816

817

818

819

820 if (ExpectBlockType)

821 addBlockTypeOperand(Operands, NameLoc, WebAssembly::BlockType::Void);

822

823 if (ExpectCatchList)

824 Operands.push_back(std::make_unique(

825 NameLoc, NameLoc, WebAssemblyOperand::CaLOp{}));

826

827 if (FunctionTable)

828 Operands.push_back(std::move(FunctionTable));

829 Parser.Lex();

830 return false;

831 }

832

833 bool parseSignature(wasm::WasmSignature *Signature) {

835 return true;

836 if (parseRegTypeList(Signature->Params))

837 return true;

839 return true;

841 return true;

843 return true;

844 if (parseRegTypeList(Signature->Returns))

845 return true;

847 return true;

848 return false;

849 }

850

852 auto Op = std::make_unique(

853 Lexer.getTok().getLoc(), SMLoc(), WebAssemblyOperand::CaLOp{});

854 SMLoc EndLoc;

855

858 return true;

859

860 auto CatchStr = expectIdent();

861 if (CatchStr.empty())

862 return true;

863 uint8_t CatchOpcode =

864 StringSwitch<uint8_t>(CatchStr)

869 .Default(0xff);

870 if (CatchOpcode == 0xff)

872 "Expected catch/catch_ref/catch_all/catch_all_ref, instead got: " +

873 CatchStr);

874

875 const MCExpr *Tag = nullptr;

878 if (Parser.parseExpression(Tag))

879 return error("Cannot parse symbol: ", Lexer.getTok());

880 }

881

882 auto &DestTok = Lexer.getTok();

884 return error("Expected integer constant, instead got: ", DestTok);

885 unsigned Dest = DestTok.getIntVal();

886 Parser.Lex();

887

888 EndLoc = Lexer.getTok().getEndLoc();

890 return true;

891

892 Op->CaL.List.push_back({CatchOpcode, Tag, Dest});

893 }

894

895 Op->EndLoc = EndLoc;

897 return false;

898 }

899

900 bool checkDataSection() {

901 if (CurrentState != DataSection) {

902 auto *WS = static_cast<const MCSectionWasm *>(

903 getStreamer().getCurrentSectionOnly());

904 if (WS && WS->isText())

905 return error("data directive must occur in a data segment: ",

906 Lexer.getTok());

907 }

908 CurrentState = DataSection;

909 return false;

910 }

911

912

913

914

915 ParseStatus parseDirective(AsmToken DirectiveID) override {

917 auto &Out = getStreamer();

918 auto &TOut =

919 reinterpret_cast<WebAssemblyTargetStreamer &>(*Out.getTargetStreamer());

920 auto &Ctx = Out.getContext();

921

922 if (DirectiveID.getString() == ".globaltype") {

923 auto SymName = expectIdent();

924 if (SymName.empty())

928 auto TypeTok = Lexer.getTok();

929 auto TypeName = expectIdent();

934 return error("Unknown type in .globaltype directive: ", TypeTok);

935

936

937

938 bool Mutable = true;

940 TypeTok = Lexer.getTok();

941 auto Id = expectIdent();

942 if (Id.empty())

944 if (Id == "immutable")

945 Mutable = false;

946 else

947

948 return error("Unknown type in .globaltype modifier: ", TypeTok);

949 }

950

951 auto *WasmSym =

954 WasmSym->setGlobalType(wasm::WasmGlobalType{uint8_t(*Type), Mutable});

955

956 TOut.emitGlobalType(WasmSym);

958 }

959

960 if (DirectiveID.getString() == ".tabletype") {

961

962 auto SymName = expectIdent();

963 if (SymName.empty())

967

968 auto ElemTypeTok = Lexer.getTok();

969 auto ElemTypeName = expectIdent();

970 if (ElemTypeName.empty())

972 std::optionalwasm::ValType ElemType =

974 if (!ElemType)

975 return error("Unknown type in .tabletype directive: ", ElemTypeTok);

976

977 wasm::WasmLimits Limits = defaultLimits();

980

981

982

983 auto *WasmSym =

986 if (Is64) {

988 }

989 wasm::WasmTableType Type = {*ElemType, Limits};

990 WasmSym->setTableType(Type);

991 TOut.emitTableType(WasmSym);

993 }

994

995 if (DirectiveID.getString() == ".functype") {

996

997

998

999

1000

1001 auto SymName = expectIdent();

1002 if (SymName.empty())

1004 auto *WasmSym =

1006 if (WasmSym->isDefined()) {

1007

1008

1009

1010

1011

1012

1013

1014

1015

1016

1017 if (CurrentState != FunctionLabel) {

1018

1019 if (ensureEmptyNestingStack())

1021 push(Function);

1022 }

1023 CurrentState = FunctionStart;

1024 LastFunctionLabel = WasmSym;

1025 }

1027 if (parseSignature(Signature))

1029 if (CurrentState == FunctionStart)

1030 TC.funcDecl(*Signature);

1031 WasmSym->setSignature(Signature);

1033 TOut.emitFunctionType(WasmSym);

1034

1036 }

1037

1038 if (DirectiveID.getString() == ".export_name") {

1039 auto SymName = expectIdent();

1040 if (SymName.empty())

1044 auto ExportName = expectIdent();

1045 if (ExportName.empty())

1047 auto *WasmSym =

1049 WasmSym->setExportName(Ctx.allocateString(ExportName));

1050 TOut.emitExportName(WasmSym, ExportName);

1052 }

1053

1054 if (DirectiveID.getString() == ".import_module") {

1055 auto SymName = expectIdent();

1056 if (SymName.empty())

1060 auto ImportModule = expectIdent();

1061 if (ImportModule.empty())

1063 auto *WasmSym =

1065 WasmSym->setImportModule(Ctx.allocateString(ImportModule));

1066 TOut.emitImportModule(WasmSym, ImportModule);

1068 }

1069

1070 if (DirectiveID.getString() == ".import_name") {

1071 auto SymName = expectIdent();

1072 if (SymName.empty())

1076 auto ImportName = expectIdent();

1077 if (ImportName.empty())

1079 auto *WasmSym =

1081 WasmSym->setImportName(Ctx.allocateString(ImportName));

1082 TOut.emitImportName(WasmSym, ImportName);

1084 }

1085

1086 if (DirectiveID.getString() == ".tagtype") {

1087 auto SymName = expectIdent();

1088 if (SymName.empty())

1090 auto *WasmSym =

1093 if (parseRegTypeList(Signature->Params))

1095 WasmSym->setSignature(Signature);

1097 TOut.emitTagType(WasmSym);

1098

1100 }

1101

1102 if (DirectiveID.getString() == ".local") {

1103 if (CurrentState != FunctionStart)

1104 return error(".local directive should follow the start of a function: ",

1105 Lexer.getTok());

1107 if (parseRegTypeList(Locals))

1109 TC.localDecl(Locals);

1110 TOut.emitLocal(Locals);

1111 CurrentState = FunctionLocals;

1113 }

1114

1115 if (DirectiveID.getString() == ".int8" ||

1116 DirectiveID.getString() == ".int16" ||

1117 DirectiveID.getString() == ".int32" ||

1118 DirectiveID.getString() == ".int64") {

1119 if (checkDataSection())

1121 const MCExpr *Val;

1122 SMLoc End;

1123 if (Parser.parseExpression(Val, End))

1124 return error("Cannot parse .int expression: ", Lexer.getTok());

1125 size_t NumBits = 0;

1127 Out.emitValue(Val, NumBits / 8, End);

1129 }

1130

1131 if (DirectiveID.getString() == ".asciz") {

1132 if (checkDataSection())

1134 std::string S;

1135 if (Parser.parseEscapedString(S))

1136 return error("Cannot parse string constant: ", Lexer.getTok());

1137 Out.emitBytes(StringRef(S.c_str(), S.length() + 1));

1139 }

1140

1142 }

1143

1144

1145 void ensureLocals(MCStreamer &Out) {

1146 if (CurrentState == FunctionStart) {

1147

1148

1149

1150 auto &TOut = reinterpret_cast<WebAssemblyTargetStreamer &>(

1153 CurrentState = FunctionLocals;

1154 }

1155 }

1156

1157 bool matchAndEmitInstruction(SMLoc IDLoc, unsigned & ,

1159 uint64_t &ErrorInfo,

1160 bool MatchingInlineAsm) override {

1161 MCInst Inst;

1163 FeatureBitset MissingFeatures;

1164 unsigned MatchResult = MatchInstructionImpl(

1165 Operands, Inst, ErrorInfo, MissingFeatures, MatchingInlineAsm);

1166 switch (MatchResult) {

1167 case Match_Success: {

1168 ensureLocals(Out);

1169

1171 if (Align != -1U) {

1173 if (Op0.getImm() == -1)

1175 }

1176 if (Is64) {

1177

1178

1179

1181 static_cast<uint16_t>(Inst.getOpcode()));

1182 if (Opc64 >= 0) {

1184 }

1185 }

1186 if (!SkipTypeCheck)

1187 TC.typeCheck(IDLoc, Inst, Operands);

1189 if (CurrentState == EndFunction) {

1190 onEndOfFunction(IDLoc);

1191 } else {

1192 CurrentState = Instructions;

1193 }

1194 return false;

1195 }

1196 case Match_MissingFeature: {

1197 assert(MissingFeatures.count() > 0 && "Expected missing features");

1198 SmallString<128> Message;

1199 raw_svector_ostream OS(Message);

1200 OS << "instruction requires:";

1201 for (unsigned I = 0, E = MissingFeatures.size(); I != E; ++I)

1202 if (MissingFeatures.test(I))

1204 return Parser.Error(IDLoc, Message);

1205 }

1206 case Match_MnemonicFail:

1207 return Parser.Error(IDLoc, "invalid instruction");

1208 case Match_NearMisses:

1209 return Parser.Error(IDLoc, "ambiguous instruction");

1210 case Match_InvalidTiedOperand:

1211 case Match_InvalidOperand: {

1212 SMLoc ErrorLoc = IDLoc;

1213 if (ErrorInfo != ~0ULL) {

1214 if (ErrorInfo >= Operands.size())

1215 return Parser.Error(IDLoc, "too few operands for instruction");

1216 ErrorLoc = Operands[ErrorInfo]->getStartLoc();

1217 if (ErrorLoc == SMLoc())

1218 ErrorLoc = IDLoc;

1219 }

1220 return Parser.Error(ErrorLoc, "invalid operand for instruction");

1221 }

1222 }

1224 }

1225

1226 void doBeforeLabelEmit(MCSymbol *Symbol, SMLoc IDLoc) override {

1227

1228 auto *CWS = static_cast<const MCSectionWasm *>(

1229 getStreamer().getCurrentSectionOnly());

1230 if (!CWS->isText())

1231 return;

1232

1233 auto *WasmSym = static_cast<MCSymbolWasm *>(Symbol);

1234

1235

1237 Parser.Error(IDLoc,

1238 "Wasm doesn\'t support data symbols in text sections");

1239 return;

1240 }

1241

1242

1243

1244

1245 auto SymName = Symbol->getName();

1246 if (SymName.starts_with(".L"))

1247 return;

1248

1249

1250

1251

1252

1253 std::string SecName = (".text." + SymName).str();

1254

1255 auto *Group = CWS->getGroup();

1256

1257

1258

1259

1260 if (Group)

1261 WasmSym->setComdat(true);

1264 getStreamer().switchSection(WS);

1265

1266 if (getContext().getGenDwarfForAssembly())

1267 getContext().addGenDwarfSection(WS);

1268

1269 if (WasmSym->isFunction()) {

1270

1271

1272

1273

1274

1275

1276

1277

1278

1279 ensureEmptyNestingStack(IDLoc);

1280 CurrentState = FunctionLabel;

1281 LastFunctionLabel = Symbol;

1282 push(Function);

1283 }

1284 }

1285

1286 void onEndOfFunction(SMLoc ErrorLoc) {

1287 if (!SkipTypeCheck)

1288 TC.endOfFunction(ErrorLoc, true);

1289

1291 }

1292

1293 void onEndOfFile() override { ensureEmptyNestingStack(); }

1294};

1295}

1296

1297

1303

1304#define GET_REGISTER_MATCHER

1305#define GET_SUBTARGET_FEATURE_NAME

1306#define GET_MATCHER_IMPLEMENTATION

1307#include "WebAssemblyGenAsmMatcher.inc"

1308

1310

1311 for (auto &ME : MatchTable0) {

1312 if (ME.Opcode == Opc) {

1313 return ME.getMnemonic();

1314 }

1315 }

1316 assert(false && "mnemonic not found");

1318}

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

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

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

#define LLVM_EXTERNAL_VISIBILITY

static MCRegister getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)

static bool isReg(const MCInst &MI, unsigned OpNo)

static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")

static TableGen::Emitter::OptClass< SkeletonEmitter > X("gen-skeleton-class", "Generate example skeleton class")

LLVM_ABI LLVM_EXTERNAL_VISIBILITY void LLVMInitializeWebAssemblyAsmParser()

Definition WebAssemblyAsmParser.cpp:1299

StringRef getMnemonic(unsigned Opc)

Definition WebAssemblyAsmParser.cpp:1309

static const char * getSubtargetFeatureName(uint64_t Val)

This file is part of the WebAssembly Assembler.

This file contains the declaration of the WebAssemblyMCAsmInfo class.

This file provides WebAssembly-specific target descriptions.

This file contains the declaration of the WebAssembly-specific type parsing utility functions.

This file registers the WebAssembly target.

This file declares WebAssembly-specific target streamer classes.

LLVM_ABI SMLoc getLoc() const

int64_t getIntVal() const

StringRef getString() const

Get the string for the current token, this includes all characters (for example, the quotes on string...

bool is(TokenKind K) const

TokenKind getKind() const

LLVM_ABI SMLoc getEndLoc() const

StringRef getIdentifier() const

Get the identifier string for the current token, which should be an identifier or a string.

constexpr bool test(unsigned I) const

constexpr size_t size() const

virtual void Initialize(MCAsmParser &Parser)

Initialize the extension for parsing using the given Parser.

Context object for machine code objects.

LLVM_ABI MCSymbol * createTempSymbol()

Create a temporary symbol with a unique name.

LLVM_ABI wasm::WasmSignature * createWasmSignature()

Allocates and returns a new WasmSignature instance (with empty parameter and return type lists).

StringRef allocateString(StringRef s)

Allocates a copy of the given string on the allocator managed by this context and returns the result.

LLVM_ABI MCSymbol * getOrCreateSymbol(const Twine &Name)

Lookup the symbol inside with the specified Name.

unsigned getOpcode() const

void addOperand(const MCOperand Op)

void setOpcode(unsigned Op)

const MCOperand & getOperand(unsigned i) const

static MCOperand createExpr(const MCExpr *Val)

static MCOperand createSFPImm(uint32_t Val)

static MCOperand createImm(int64_t Val)

static MCOperand createDFPImm(uint64_t Val)

MCParsedAsmOperand - This abstract class represents a source-level assembly instruction operand.

Wrapper class representing physical registers. Should be passed by value.

static constexpr unsigned NonUniqueID

virtual void emitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI)

Emit the given Instruction into the current section.

MCTargetStreamer * getTargetStreamer()

bool checkFeatures(StringRef FS) const

Check whether the subtarget features are enabled/disabled as per the provided string,...

const FeatureBitset & getFeatureBits() const

static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx, SMLoc Loc=SMLoc())

void setFunctionTable(bool is64)

MCTargetAsmParser - Generic interface to target specific assembly parsers.

static constexpr StatusTy Failure

static constexpr StatusTy NoMatch

Represents a location in source code.

static SMLoc getFromPointer(const char *Ptr)

constexpr const char * getPointer() const

static SectionKind getText()

void push_back(const T &Elt)

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

bool getAsInteger(unsigned Radix, T &Result) const

Parse the current string as an integer of the specified radix.

bool starts_with(StringRef Prefix) const

Check if this string starts with the given Prefix.

StringRef drop_front(size_t N=1) const

Return a StringRef equal to 'this' but with the first N elements dropped.

bool contains(StringRef Other) const

Return true if the given string is a substring of *this, and false otherwise.

LLVM_ABI void clear()

Clears function-level state.

#define llvm_unreachable(msg)

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

constexpr char Align[]

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

constexpr char TypeName[]

Key for Kernel::Arg::Metadata::mTypeName.

@ C

The default llvm calling convention, compatible with C.

int getWasm64Opcode(unsigned short Opcode)

MCSymbolWasm * getOrCreateFunctionTableSymbol(MCContext &Ctx, const WebAssemblySubtarget *Subtarget)

Returns the __indirect_function_table, for use in call_indirect and in function bitcasts.

BlockType parseBlockType(StringRef Type)

BlockType

Used as immediate MachineOperands for block signatures.

unsigned GetDefaultP2AlignAny(unsigned Opc)

Return the default p2align value for a load or store with the given opcode.

std::optional< wasm::ValType > parseType(StringRef Type)

Context & getContext() const

@ WASM_OPCODE_CATCH_ALL_REF

@ WASM_LIMITS_FLAG_HAS_MAX

@ WASM_SYMBOL_TYPE_GLOBAL

@ WASM_SYMBOL_TYPE_FUNCTION

This is an optimization pass for GlobalISel generic memory operations.

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

static bool isMem(const MachineInstr &MI, unsigned Op)

LLVM_ABI std::pair< StringRef, StringRef > getToken(StringRef Source, StringRef Delimiters=" \t\n\v\f\r")

getToken - This function extracts one token from source, ignoring any leading characters that appear ...

SmallVectorImpl< std::unique_ptr< MCParsedAsmOperand > > OperandVector

Target & getTheWebAssemblyTarget32()

class LLVM_GSL_OWNER SmallVector

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

Target & getTheWebAssemblyTarget64()

To bit_cast(const From &from) noexcept

DWARFExpression::Operation Op

@ MCSA_NoDeadStrip

.no_dead_strip (MachO)

RegisterMCAsmParser - Helper template for registering a target specific assembly parser,...

SmallVector< ValType, 1 > Returns

SmallVector< ValType, 4 > Params