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