LLVM  8.0.1
WebAssemblyAsmParser.cpp
Go to the documentation of this file.
1 //==- WebAssemblyAsmParser.cpp - Assembler for WebAssembly -*- C++ -*-==//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 ///
10 /// \file
11 /// This file is part of the WebAssembly Assembler.
12 ///
13 /// It contains code to translate a parsed .s file into MCInsts.
14 ///
15 //===----------------------------------------------------------------------===//
16 
19 #include "WebAssembly.h"
20 #include "llvm/MC/MCContext.h"
21 #include "llvm/MC/MCInst.h"
22 #include "llvm/MC/MCInstrInfo.h"
25 #include "llvm/MC/MCStreamer.h"
27 #include "llvm/MC/MCSymbol.h"
28 #include "llvm/MC/MCSymbolWasm.h"
29 #include "llvm/Support/Endian.h"
31 
32 using namespace llvm;
33 
34 #define DEBUG_TYPE "wasm-asm-parser"
35 
36 namespace {
37 
38 /// WebAssemblyOperand - Instances of this class represent the operands in a
39 /// parsed WASM machine instruction.
40 struct WebAssemblyOperand : public MCParsedAsmOperand {
41  enum KindTy { Token, Integer, Float, Symbol, BrList } Kind;
42 
43  SMLoc StartLoc, EndLoc;
44 
45  struct TokOp {
46  StringRef Tok;
47  };
48 
49  struct IntOp {
50  int64_t Val;
51  };
52 
53  struct FltOp {
54  double Val;
55  };
56 
57  struct SymOp {
58  const MCExpr *Exp;
59  };
60 
61  struct BrLOp {
62  std::vector<unsigned> List;
63  };
64 
65  union {
66  struct TokOp Tok;
67  struct IntOp Int;
68  struct FltOp Flt;
69  struct SymOp Sym;
70  struct BrLOp BrL;
71  };
72 
73  WebAssemblyOperand(KindTy K, SMLoc Start, SMLoc End, TokOp T)
74  : Kind(K), StartLoc(Start), EndLoc(End), Tok(T) {}
75  WebAssemblyOperand(KindTy K, SMLoc Start, SMLoc End, IntOp I)
76  : Kind(K), StartLoc(Start), EndLoc(End), Int(I) {}
77  WebAssemblyOperand(KindTy K, SMLoc Start, SMLoc End, FltOp F)
78  : Kind(K), StartLoc(Start), EndLoc(End), Flt(F) {}
79  WebAssemblyOperand(KindTy K, SMLoc Start, SMLoc End, SymOp S)
80  : Kind(K), StartLoc(Start), EndLoc(End), Sym(S) {}
81  WebAssemblyOperand(KindTy K, SMLoc Start, SMLoc End)
82  : Kind(K), StartLoc(Start), EndLoc(End), BrL() {}
83 
84  ~WebAssemblyOperand() {
85  if (isBrList())
86  BrL.~BrLOp();
87  }
88 
89  bool isToken() const override { return Kind == Token; }
90  bool isImm() const override {
91  return Kind == Integer || Kind == Float || Kind == Symbol;
92  }
93  bool isMem() const override { return false; }
94  bool isReg() const override { return false; }
95  bool isBrList() const { return Kind == BrList; }
96 
97  unsigned getReg() const override {
98  llvm_unreachable("Assembly inspects a register operand");
99  return 0;
100  }
101 
102  StringRef getToken() const {
103  assert(isToken());
104  return Tok.Tok;
105  }
106 
107  SMLoc getStartLoc() const override { return StartLoc; }
108  SMLoc getEndLoc() const override { return EndLoc; }
109 
110  void addRegOperands(MCInst &, unsigned) const {
111  // Required by the assembly matcher.
112  llvm_unreachable("Assembly matcher creates register operands");
113  }
114 
115  void addImmOperands(MCInst &Inst, unsigned N) const {
116  assert(N == 1 && "Invalid number of operands!");
117  if (Kind == Integer)
119  else if (Kind == Float)
120  Inst.addOperand(MCOperand::createFPImm(Flt.Val));
121  else if (Kind == Symbol)
122  Inst.addOperand(MCOperand::createExpr(Sym.Exp));
123  else
124  llvm_unreachable("Should be immediate or symbol!");
125  }
126 
127  void addBrListOperands(MCInst &Inst, unsigned N) const {
128  assert(N == 1 && isBrList() && "Invalid BrList!");
129  for (auto Br : BrL.List)
131  }
132 
133  void print(raw_ostream &OS) const override {
134  switch (Kind) {
135  case Token:
136  OS << "Tok:" << Tok.Tok;
137  break;
138  case Integer:
139  OS << "Int:" << Int.Val;
140  break;
141  case Float:
142  OS << "Flt:" << Flt.Val;
143  break;
144  case Symbol:
145  OS << "Sym:" << Sym.Exp;
146  break;
147  case BrList:
148  OS << "BrList:" << BrL.List.size();
149  break;
150  }
151  }
152 };
153 
154 class WebAssemblyAsmParser final : public MCTargetAsmParser {
155  MCAsmParser &Parser;
156  MCAsmLexer &Lexer;
157 
158  // Much like WebAssemblyAsmPrinter in the backend, we have to own these.
159  std::vector<std::unique_ptr<wasm::WasmSignature>> Signatures;
160 
161  // Order of labels, directives and instructions in a .s file have no
162  // syntactical enforcement. This class is a callback from the actual parser,
163  // and yet we have to be feeding data to the streamer in a very particular
164  // order to ensure a correct binary encoding that matches the regular backend
165  // (the streamer does not enforce this). This "state machine" enum helps
166  // guarantee that correct order.
167  enum ParserState {
168  FileStart,
169  Label,
170  FunctionStart,
171  FunctionLocals,
172  Instructions,
173  } CurrentState = FileStart;
174 
175  // For ensuring blocks are properly nested.
176  enum NestingType {
177  Function,
178  Block,
179  Loop,
180  Try,
181  If,
182  Else,
183  Undefined,
184  };
185  std::vector<NestingType> NestingStack;
186 
187  // We track this to see if a .functype following a label is the same,
188  // as this is how we recognize the start of a function.
189  MCSymbol *LastLabel = nullptr;
190 
191 public:
192  WebAssemblyAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
193  const MCInstrInfo &MII, const MCTargetOptions &Options)
194  : MCTargetAsmParser(Options, STI, MII), Parser(Parser),
195  Lexer(Parser.getLexer()) {
196  setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
197  }
198 
199 #define GET_ASSEMBLER_HEADER
200 #include "WebAssemblyGenAsmMatcher.inc"
201 
202  // TODO: This is required to be implemented, but appears unused.
203  bool ParseRegister(unsigned & /*RegNo*/, SMLoc & /*StartLoc*/,
204  SMLoc & /*EndLoc*/) override {
205  llvm_unreachable("ParseRegister is not implemented.");
206  }
207 
208  bool error(const Twine &Msg, const AsmToken &Tok) {
209  return Parser.Error(Tok.getLoc(), Msg + Tok.getString());
210  }
211 
212  bool error(const Twine &Msg) {
213  return Parser.Error(Lexer.getTok().getLoc(), Msg);
214  }
215 
216  void addSignature(std::unique_ptr<wasm::WasmSignature> &&Sig) {
217  Signatures.push_back(std::move(Sig));
218  }
219 
220  std::pair<StringRef, StringRef> nestingString(NestingType NT) {
221  switch (NT) {
222  case Function:
223  return {"function", "end_function"};
224  case Block:
225  return {"block", "end_block"};
226  case Loop:
227  return {"loop", "end_loop"};
228  case Try:
229  return {"try", "end_try"};
230  case If:
231  return {"if", "end_if"};
232  case Else:
233  return {"else", "end_if"};
234  default:
235  llvm_unreachable("unknown NestingType");
236  }
237  }
238 
239  void push(NestingType NT) { NestingStack.push_back(NT); }
240 
241  bool pop(StringRef Ins, NestingType NT1, NestingType NT2 = Undefined) {
242  if (NestingStack.empty())
243  return error(Twine("End of block construct with no start: ") + Ins);
244  auto Top = NestingStack.back();
245  if (Top != NT1 && Top != NT2)
246  return error(Twine("Block construct type mismatch, expected: ") +
247  nestingString(Top).second + ", instead got: " + Ins);
248  NestingStack.pop_back();
249  return false;
250  }
251 
252  bool ensureEmptyNestingStack() {
253  auto err = !NestingStack.empty();
254  while (!NestingStack.empty()) {
255  error(Twine("Unmatched block construct(s) at function end: ") +
256  nestingString(NestingStack.back()).first);
257  NestingStack.pop_back();
258  }
259  return err;
260  }
261 
262  bool isNext(AsmToken::TokenKind Kind) {
263  auto Ok = Lexer.is(Kind);
264  if (Ok)
265  Parser.Lex();
266  return Ok;
267  }
268 
269  bool expect(AsmToken::TokenKind Kind, const char *KindName) {
270  if (!isNext(Kind))
271  return error(std::string("Expected ") + KindName + ", instead got: ",
272  Lexer.getTok());
273  return false;
274  }
275 
276  StringRef expectIdent() {
277  if (!Lexer.is(AsmToken::Identifier)) {
278  error("Expected identifier, got: ", Lexer.getTok());
279  return StringRef();
280  }
281  auto Name = Lexer.getTok().getString();
282  Parser.Lex();
283  return Name;
284  }
285 
287  // FIXME: can't use StringSwitch because wasm::ValType doesn't have a
288  // "invalid" value.
289  if (Type == "i32")
290  return wasm::ValType::I32;
291  if (Type == "i64")
292  return wasm::ValType::I64;
293  if (Type == "f32")
294  return wasm::ValType::F32;
295  if (Type == "f64")
296  return wasm::ValType::F64;
297  if (Type == "v128" || Type == "i8x16" || Type == "i16x8" ||
298  Type == "i32x4" || Type == "i64x2" || Type == "f32x4" ||
299  Type == "f64x2")
300  return wasm::ValType::V128;
301  return Optional<wasm::ValType>();
302  }
303 
304  WebAssembly::ExprType parseBlockType(StringRef ID) {
306  .Case("i32", WebAssembly::ExprType::I32)
311  .Case("except_ref", WebAssembly::ExprType::ExceptRef)
314  }
315 
316  bool parseRegTypeList(SmallVectorImpl<wasm::ValType> &Types) {
317  while (Lexer.is(AsmToken::Identifier)) {
318  auto Type = parseType(Lexer.getTok().getString());
319  if (!Type)
320  return true;
321  Types.push_back(Type.getValue());
322  Parser.Lex();
323  if (!isNext(AsmToken::Comma))
324  break;
325  }
326  return false;
327  }
328 
329  void parseSingleInteger(bool IsNegative, OperandVector &Operands) {
330  auto &Int = Lexer.getTok();
331  int64_t Val = Int.getIntVal();
332  if (IsNegative)
333  Val = -Val;
334  Operands.push_back(make_unique<WebAssemblyOperand>(
335  WebAssemblyOperand::Integer, Int.getLoc(), Int.getEndLoc(),
336  WebAssemblyOperand::IntOp{Val}));
337  Parser.Lex();
338  }
339 
340  bool parseOperandStartingWithInteger(bool IsNegative, OperandVector &Operands,
341  StringRef InstName) {
342  parseSingleInteger(IsNegative, Operands);
343  // FIXME: there is probably a cleaner way to do this.
344  auto IsLoadStore = InstName.startswith("load") ||
345  InstName.startswith("store") ||
346  InstName.startswith("atomic_load") ||
347  InstName.startswith("atomic_store");
348  if (IsLoadStore) {
349  // Parse load/store operands of the form: offset align
350  auto &Offset = Lexer.getTok();
351  if (Offset.is(AsmToken::Integer)) {
352  parseSingleInteger(false, Operands);
353  } else {
354  // Alignment not specified.
355  // FIXME: correctly derive a default from the instruction.
356  // We can't just call WebAssembly::GetDefaultP2Align since we don't have
357  // an opcode until after the assembly matcher.
358  Operands.push_back(make_unique<WebAssemblyOperand>(
359  WebAssemblyOperand::Integer, Offset.getLoc(), Offset.getEndLoc(),
360  WebAssemblyOperand::IntOp{0}));
361  }
362  }
363  return false;
364  }
365 
366  void addBlockTypeOperand(OperandVector &Operands, SMLoc NameLoc,
368  Operands.push_back(make_unique<WebAssemblyOperand>(
369  WebAssemblyOperand::Integer, NameLoc, NameLoc,
370  WebAssemblyOperand::IntOp{static_cast<int64_t>(BT)}));
371  }
372 
373  bool ParseInstruction(ParseInstructionInfo & /*Info*/, StringRef Name,
374  SMLoc NameLoc, OperandVector &Operands) override {
375  // Note: Name does NOT point into the sourcecode, but to a local, so
376  // use NameLoc instead.
377  Name = StringRef(NameLoc.getPointer(), Name.size());
378 
379  // WebAssembly has instructions with / in them, which AsmLexer parses
380  // as seperate tokens, so if we find such tokens immediately adjacent (no
381  // whitespace), expand the name to include them:
382  for (;;) {
383  auto &Sep = Lexer.getTok();
384  if (Sep.getLoc().getPointer() != Name.end() ||
385  Sep.getKind() != AsmToken::Slash)
386  break;
387  // Extend name with /
388  Name = StringRef(Name.begin(), Name.size() + Sep.getString().size());
389  Parser.Lex();
390  // We must now find another identifier, or error.
391  auto &Id = Lexer.getTok();
392  if (Id.getKind() != AsmToken::Identifier ||
393  Id.getLoc().getPointer() != Name.end())
394  return error("Incomplete instruction name: ", Id);
395  Name = StringRef(Name.begin(), Name.size() + Id.getString().size());
396  Parser.Lex();
397  }
398 
399  // Now construct the name as first operand.
400  Operands.push_back(make_unique<WebAssemblyOperand>(
401  WebAssemblyOperand::Token, NameLoc, SMLoc::getFromPointer(Name.end()),
402  WebAssemblyOperand::TokOp{Name}));
403  auto NamePair = Name.split('.');
404  // If no '.', there is no type prefix.
405  auto BaseName = NamePair.second.empty() ? NamePair.first : NamePair.second;
406 
407  // If this instruction is part of a control flow structure, ensure
408  // proper nesting.
409  bool ExpectBlockType = false;
410  if (BaseName == "block") {
411  push(Block);
412  ExpectBlockType = true;
413  } else if (BaseName == "loop") {
414  push(Loop);
415  ExpectBlockType = true;
416  } else if (BaseName == "try") {
417  push(Try);
418  ExpectBlockType = true;
419  } else if (BaseName == "if") {
420  push(If);
421  ExpectBlockType = true;
422  } else if (BaseName == "else") {
423  if (pop(BaseName, If))
424  return true;
425  push(Else);
426  } else if (BaseName == "catch") {
427  if (pop(BaseName, Try))
428  return true;
429  push(Try);
430  } else if (BaseName == "catch_all") {
431  if (pop(BaseName, Try))
432  return true;
433  push(Try);
434  } else if (BaseName == "end_if") {
435  if (pop(BaseName, If, Else))
436  return true;
437  } else if (BaseName == "end_try") {
438  if (pop(BaseName, Try))
439  return true;
440  } else if (BaseName == "end_loop") {
441  if (pop(BaseName, Loop))
442  return true;
443  } else if (BaseName == "end_block") {
444  if (pop(BaseName, Block))
445  return true;
446  } else if (BaseName == "end_function") {
447  if (pop(BaseName, Function) || ensureEmptyNestingStack())
448  return true;
449  }
450 
451  while (Lexer.isNot(AsmToken::EndOfStatement)) {
452  auto &Tok = Lexer.getTok();
453  switch (Tok.getKind()) {
454  case AsmToken::Identifier: {
455  auto &Id = Lexer.getTok();
456  if (ExpectBlockType) {
457  // Assume this identifier is a block_type.
458  auto BT = parseBlockType(Id.getString());
460  return error("Unknown block type: ", Id);
461  addBlockTypeOperand(Operands, NameLoc, BT);
462  Parser.Lex();
463  } else {
464  // Assume this identifier is a label.
465  const MCExpr *Val;
466  SMLoc End;
467  if (Parser.parsePrimaryExpr(Val, End))
468  return error("Cannot parse symbol: ", Lexer.getTok());
469  Operands.push_back(make_unique<WebAssemblyOperand>(
470  WebAssemblyOperand::Symbol, Id.getLoc(), Id.getEndLoc(),
471  WebAssemblyOperand::SymOp{Val}));
472  }
473  break;
474  }
475  case AsmToken::Minus:
476  Parser.Lex();
477  if (Lexer.isNot(AsmToken::Integer))
478  return error("Expected integer instead got: ", Lexer.getTok());
479  if (parseOperandStartingWithInteger(true, Operands, BaseName))
480  return true;
481  break;
482  case AsmToken::Integer:
483  if (parseOperandStartingWithInteger(false, Operands, BaseName))
484  return true;
485  break;
486  case AsmToken::Real: {
487  double Val;
488  if (Tok.getString().getAsDouble(Val, false))
489  return error("Cannot parse real: ", Tok);
490  Operands.push_back(make_unique<WebAssemblyOperand>(
492  WebAssemblyOperand::FltOp{Val}));
493  Parser.Lex();
494  break;
495  }
496  case AsmToken::LCurly: {
497  Parser.Lex();
498  auto Op = make_unique<WebAssemblyOperand>(
499  WebAssemblyOperand::BrList, Tok.getLoc(), Tok.getEndLoc());
500  if (!Lexer.is(AsmToken::RCurly))
501  for (;;) {
502  Op->BrL.List.push_back(Lexer.getTok().getIntVal());
503  expect(AsmToken::Integer, "integer");
504  if (!isNext(AsmToken::Comma))
505  break;
506  }
507  expect(AsmToken::RCurly, "}");
508  Operands.push_back(std::move(Op));
509  break;
510  }
511  default:
512  return error("Unexpected token in operand: ", Tok);
513  }
514  if (Lexer.isNot(AsmToken::EndOfStatement)) {
515  if (expect(AsmToken::Comma, ","))
516  return true;
517  }
518  }
519  if (ExpectBlockType && Operands.size() == 1) {
520  // Support blocks with no operands as default to void.
521  addBlockTypeOperand(Operands, NameLoc, WebAssembly::ExprType::Void);
522  }
523  Parser.Lex();
524  return false;
525  }
526 
527  void onLabelParsed(MCSymbol *Symbol) override {
528  LastLabel = Symbol;
529  CurrentState = Label;
530  }
531 
532  bool parseSignature(wasm::WasmSignature *Signature) {
533  if (expect(AsmToken::LParen, "("))
534  return true;
535  if (parseRegTypeList(Signature->Params))
536  return true;
537  if (expect(AsmToken::RParen, ")"))
538  return true;
539  if (expect(AsmToken::MinusGreater, "->"))
540  return true;
541  if (expect(AsmToken::LParen, "("))
542  return true;
543  if (parseRegTypeList(Signature->Returns))
544  return true;
545  if (expect(AsmToken::RParen, ")"))
546  return true;
547  return false;
548  }
549 
550  // This function processes wasm-specific directives streamed to
551  // WebAssemblyTargetStreamer, all others go to the generic parser
552  // (see WasmAsmParser).
553  bool ParseDirective(AsmToken DirectiveID) override {
554  // This function has a really weird return value behavior that is different
555  // from all the other parsing functions:
556  // - return true && no tokens consumed -> don't know this directive / let
557  // the generic parser handle it.
558  // - return true && tokens consumed -> a parsing error occurred.
559  // - return false -> processed this directive successfully.
560  assert(DirectiveID.getKind() == AsmToken::Identifier);
561  auto &Out = getStreamer();
562  auto &TOut =
563  reinterpret_cast<WebAssemblyTargetStreamer &>(*Out.getTargetStreamer());
564 
565  // TODO: any time we return an error, at least one token must have been
566  // consumed, otherwise this will not signal an error to the caller.
567  if (DirectiveID.getString() == ".globaltype") {
568  auto SymName = expectIdent();
569  if (SymName.empty())
570  return true;
571  if (expect(AsmToken::Comma, ","))
572  return true;
573  auto TypeTok = Lexer.getTok();
574  auto TypeName = expectIdent();
575  if (TypeName.empty())
576  return true;
577  auto Type = parseType(TypeName);
578  if (!Type)
579  return error("Unknown type in .globaltype directive: ", TypeTok);
580  // Now set this symbol with the correct type.
581  auto WasmSym = cast<MCSymbolWasm>(
582  TOut.getStreamer().getContext().getOrCreateSymbol(SymName));
583  WasmSym->setType(wasm::WASM_SYMBOL_TYPE_GLOBAL);
584  WasmSym->setGlobalType(
585  wasm::WasmGlobalType{uint8_t(Type.getValue()), true});
586  // And emit the directive again.
587  TOut.emitGlobalType(WasmSym);
588  return expect(AsmToken::EndOfStatement, "EOL");
589  }
590 
591  if (DirectiveID.getString() == ".functype") {
592  // This code has to send things to the streamer similar to
593  // WebAssemblyAsmPrinter::EmitFunctionBodyStart.
594  // TODO: would be good to factor this into a common function, but the
595  // assembler and backend really don't share any common code, and this code
596  // parses the locals seperately.
597  auto SymName = expectIdent();
598  if (SymName.empty())
599  return true;
600  auto WasmSym = cast<MCSymbolWasm>(
601  TOut.getStreamer().getContext().getOrCreateSymbol(SymName));
602  if (CurrentState == Label && WasmSym == LastLabel) {
603  // This .functype indicates a start of a function.
604  if (ensureEmptyNestingStack())
605  return true;
606  CurrentState = FunctionStart;
607  push(Function);
608  }
609  auto Signature = make_unique<wasm::WasmSignature>();
610  if (parseSignature(Signature.get()))
611  return true;
612  WasmSym->setSignature(Signature.get());
613  addSignature(std::move(Signature));
614  WasmSym->setType(wasm::WASM_SYMBOL_TYPE_FUNCTION);
615  TOut.emitFunctionType(WasmSym);
616  // TODO: backend also calls TOut.emitIndIdx, but that is not implemented.
617  return expect(AsmToken::EndOfStatement, "EOL");
618  }
619 
620  if (DirectiveID.getString() == ".eventtype") {
621  auto SymName = expectIdent();
622  if (SymName.empty())
623  return true;
624  auto WasmSym = cast<MCSymbolWasm>(
625  TOut.getStreamer().getContext().getOrCreateSymbol(SymName));
626  auto Signature = make_unique<wasm::WasmSignature>();
627  if (parseRegTypeList(Signature->Params))
628  return true;
629  WasmSym->setSignature(Signature.get());
630  addSignature(std::move(Signature));
631  WasmSym->setType(wasm::WASM_SYMBOL_TYPE_EVENT);
632  TOut.emitEventType(WasmSym);
633  // TODO: backend also calls TOut.emitIndIdx, but that is not implemented.
634  return expect(AsmToken::EndOfStatement, "EOL");
635  }
636 
637  if (DirectiveID.getString() == ".local") {
638  if (CurrentState != FunctionStart)
639  return error(".local directive should follow the start of a function",
640  Lexer.getTok());
642  if (parseRegTypeList(Locals))
643  return true;
644  TOut.emitLocal(Locals);
645  CurrentState = FunctionLocals;
646  return expect(AsmToken::EndOfStatement, "EOL");
647  }
648 
649  return true; // We didn't process this directive.
650  }
651 
652  bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned & /*Opcode*/,
653  OperandVector &Operands, MCStreamer &Out,
654  uint64_t &ErrorInfo,
655  bool MatchingInlineAsm) override {
656  MCInst Inst;
657  unsigned MatchResult =
658  MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
659  switch (MatchResult) {
660  case Match_Success: {
661  if (CurrentState == FunctionStart) {
662  // This is the first instruction in a function, but we haven't seen
663  // a .local directive yet. The streamer requires locals to be encoded
664  // as a prelude to the instructions, so emit an empty list of locals
665  // here.
666  auto &TOut = reinterpret_cast<WebAssemblyTargetStreamer &>(
667  *Out.getTargetStreamer());
669  }
670  CurrentState = Instructions;
671  Out.EmitInstruction(Inst, getSTI());
672  return false;
673  }
674  case Match_MissingFeature:
675  return Parser.Error(
676  IDLoc, "instruction requires a WASM feature not currently enabled");
677  case Match_MnemonicFail:
678  return Parser.Error(IDLoc, "invalid instruction");
679  case Match_NearMisses:
680  return Parser.Error(IDLoc, "ambiguous instruction");
681  case Match_InvalidTiedOperand:
682  case Match_InvalidOperand: {
683  SMLoc ErrorLoc = IDLoc;
684  if (ErrorInfo != ~0ULL) {
685  if (ErrorInfo >= Operands.size())
686  return Parser.Error(IDLoc, "too few operands for instruction");
687  ErrorLoc = Operands[ErrorInfo]->getStartLoc();
688  if (ErrorLoc == SMLoc())
689  ErrorLoc = IDLoc;
690  }
691  return Parser.Error(ErrorLoc, "invalid operand for instruction");
692  }
693  }
694  llvm_unreachable("Implement any new match types added!");
695  }
696 
697  void onEndOfFile() override { ensureEmptyNestingStack(); }
698 };
699 } // end anonymous namespace
700 
701 // Force static initialization.
705 }
706 
707 #define GET_REGISTER_MATCHER
708 #define GET_MATCHER_IMPLEMENTATION
709 #include "WebAssemblyGenAsmMatcher.inc"
static bool isReg(const MCInst &MI, unsigned OpNo)
const AsmToken & getTok() const
Get the current (last) lexed token.
Definition: MCAsmLexer.h:101
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
StringRef getString() const
Get the string for the current token, this includes all characters (for example, the quotes on string...
Definition: MCAsmMacro.h:111
This class represents lattice values for constants.
Definition: AllocatorList.h:24
bool is(AsmToken::TokenKind K) const
Check if the current token has kind K.
Definition: MCAsmLexer.h:136
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition: MCSymbol.h:42
Generic assembler parser interface, for use by target specific assembly parsers.
Definition: MCAsmParser.h:110
static MCOperand createExpr(const MCExpr *Val)
Definition: MCInst.h:137
MCTargetAsmParser - Generic interface to target specific assembly parsers.
void push_back(const T &Elt)
Definition: SmallVector.h:218
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE size_t size() const
size - Get the string size.
Definition: StringRef.h:138
virtual const AsmToken & Lex()=0
Get the next AsmToken in the stream, possibly handling file inclusion first.
SmallVector< wasm::ValType, 1 > Returns
Definition: Wasm.h:309
unsigned second
#define error(X)
F(f)
This file contains the entry points for global functions defined in the LLVM WebAssembly back-end...
virtual void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI, bool PrintSchedInfo=false)
Emit the given Instruction into the current section.
Definition: MCStreamer.cpp:956
static GCMetadataPrinterRegistry::Add< OcamlGCMetadataPrinter > Y("ocaml", "ocaml 3.10-compatible collector")
amdgpu Simplify well known AMD library false Value Value const Twine & Name
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:81
const FeatureBitset & getFeatureBits() const
Generic assembler lexer interface, for use by target specific assembly lexers.
Definition: MCAsmLexer.h:40
Base class for the full range of assembler expressions which are needed for parsing.
Definition: MCExpr.h:36
Target independent representation for an assembler token.
Definition: MCAsmMacro.h:22
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE R Default(T Value)
Definition: StringSwitch.h:203
static bool isMem(const MachineInstr &MI, unsigned Op)
Definition: X86InstrInfo.h:161
MCParsedAsmOperand - This abstract class represents a source-level assembly instruction operand...
std::pair< StringRef, StringRef > getToken(StringRef Source, StringRef Delimiters=" \\\)
getToken - This function extracts one token from source, ignoring any leading characters that appear ...
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE bool startswith(StringRef Prefix) const
Check if this string starts with the given Prefix.
Definition: StringRef.h:267
RegisterMCAsmParser - Helper template for registering a target specific assembly parser, for use in the target machine initialization function.
SMLoc getLoc() const
Definition: MCAsmLexer.cpp:28
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:161
WebAssembly-specific streamer interface, to implement support WebAssembly-specific assembly directive...
const char * getPointer() const
Definition: SMLoc.h:35
A switch()-like statement whose cases are string literals.
Definition: StringSwitch.h:43
Streaming machine code generation interface.
Definition: MCStreamer.h:189
MCTargetStreamer * getTargetStreamer()
Definition: MCStreamer.h:258
SMLoc getEndLoc() const
Definition: MCAsmLexer.cpp:32
The instances of the Type class are immutable: once they are created, they are never changed...
Definition: Type.h:46
This file provides WebAssembly-specific target descriptions.
virtual bool parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc)=0
Parse a primary expression.
Interface to description of machine instruction set.
Definition: MCInstrInfo.h:24
virtual MCAsmLexer & getLexer()=0
constexpr char TypeName[]
Key for Kernel::Arg::Metadata::mTypeName.
int64_t getIntVal() const
Definition: MCAsmMacro.h:116
static void print(raw_ostream &Out, object::Archive::Kind Kind, T Val)
bool Error(SMLoc L, const Twine &Msg, SMRange Range=None)
Return an error at the location L, with the message Msg.
Definition: MCAsmParser.cpp:88
size_t size() const
Definition: SmallVector.h:53
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned first
This file declares WebAssembly-specific target streamer classes.
LLVM_NODISCARD std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
Definition: StringRef.h:727
bool getAsDouble(double &Result, bool AllowInexact=true) const
Parse the current string as an IEEE double-precision floating point value.
Definition: StringRef.cpp:584
ExprType
This is used to indicate block signatures.
static MCOperand createFPImm(double Val)
Definition: MCInst.h:130
void LLVMInitializeWebAssemblyAsmParser()
static unsigned getReg(const void *D, unsigned RC, unsigned RegNo)
Base class for user error types.
Definition: Error.h:345
LLVM_ATTRIBUTE_ALWAYS_INLINE StringSwitch & Case(StringLiteral S, T Value)
Definition: StringSwitch.h:70
iterator begin() const
Definition: StringRef.h:106
static SMLoc getFromPointer(const char *Ptr)
Definition: SMLoc.h:37
BitTracker BT
Definition: BitTracker.cpp:74
Represents a single loop in the control flow graph.
Definition: LoopInfo.h:465
const NodeList & List
Definition: RDFGraph.cpp:210
#define I(x, y, z)
Definition: MD5.cpp:58
#define N
Generic base class for all target subtargets.
bool isNot(AsmToken::TokenKind K) const
Check if the current token has kind K.
Definition: MCAsmLexer.h:139
const unsigned Kind
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
virtual void emitLocal(ArrayRef< wasm::ValType > Types)=0
.local
This class implements an extremely fast bulk output stream that can only output to a stream...
Definition: raw_ostream.h:46
void addOperand(const MCOperand &Op)
Definition: MCInst.h:186
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:49
Target & getTheWebAssemblyTarget32()
Type * parseType(StringRef Asm, SMDiagnostic &Err, const Module &M, const SlotMapping *Slots=nullptr)
Parse a type in the given string.
Definition: Parser.cpp:160
Represents a location in source code.
Definition: SMLoc.h:24
Target & getTheWebAssemblyTarget64()
iterator end() const
Definition: StringRef.h:108
SmallVector< wasm::ValType, 4 > Params
Definition: Wasm.h:310
static MCOperand createImm(int64_t Val)
Definition: MCInst.h:123
TokenKind getKind() const
Definition: MCAsmMacro.h:82