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  DataSection,
176  } CurrentState = FileStart;
177 
178  // For ensuring blocks are properly nested.
179  enum NestingType {
180  Function,
181  Block,
182  Loop,
183  Try,
184  If,
185  Else,
186  Undefined,
187  };
188  std::vector<NestingType> NestingStack;
189 
190  // We track this to see if a .functype following a label is the same,
191  // as this is how we recognize the start of a function.
192  MCSymbol *LastLabel = nullptr;
193  MCSymbol *LastFunctionLabel = nullptr;
194 
195 public:
196  WebAssemblyAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
197  const MCInstrInfo &MII, const MCTargetOptions &Options)
198  : MCTargetAsmParser(Options, STI, MII), Parser(Parser),
199  Lexer(Parser.getLexer()) {
200  setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
201  }
202 
203 #define GET_ASSEMBLER_HEADER
204 #include "WebAssemblyGenAsmMatcher.inc"
205 
206  // TODO: This is required to be implemented, but appears unused.
207  bool ParseRegister(unsigned & /*RegNo*/, SMLoc & /*StartLoc*/,
208  SMLoc & /*EndLoc*/) override {
209  llvm_unreachable("ParseRegister is not implemented.");
210  }
211 
212  bool error(const Twine &Msg, const AsmToken &Tok) {
213  return Parser.Error(Tok.getLoc(), Msg + Tok.getString());
214  }
215 
216  bool error(const Twine &Msg) {
217  return Parser.Error(Lexer.getTok().getLoc(), Msg);
218  }
219 
220  void addSignature(std::unique_ptr<wasm::WasmSignature> &&Sig) {
221  Signatures.push_back(std::move(Sig));
222  }
223 
224  std::pair<StringRef, StringRef> nestingString(NestingType NT) {
225  switch (NT) {
226  case Function:
227  return {"function", "end_function"};
228  case Block:
229  return {"block", "end_block"};
230  case Loop:
231  return {"loop", "end_loop"};
232  case Try:
233  return {"try", "end_try"};
234  case If:
235  return {"if", "end_if"};
236  case Else:
237  return {"else", "end_if"};
238  default:
239  llvm_unreachable("unknown NestingType");
240  }
241  }
242 
243  void push(NestingType NT) { NestingStack.push_back(NT); }
244 
245  bool pop(StringRef Ins, NestingType NT1, NestingType NT2 = Undefined) {
246  if (NestingStack.empty())
247  return error(Twine("End of block construct with no start: ") + Ins);
248  auto Top = NestingStack.back();
249  if (Top != NT1 && Top != NT2)
250  return error(Twine("Block construct type mismatch, expected: ") +
251  nestingString(Top).second + ", instead got: " + Ins);
252  NestingStack.pop_back();
253  return false;
254  }
255 
256  bool ensureEmptyNestingStack() {
257  auto Err = !NestingStack.empty();
258  while (!NestingStack.empty()) {
259  error(Twine("Unmatched block construct(s) at function end: ") +
260  nestingString(NestingStack.back()).first);
261  NestingStack.pop_back();
262  }
263  return Err;
264  }
265 
266  bool isNext(AsmToken::TokenKind Kind) {
267  auto Ok = Lexer.is(Kind);
268  if (Ok)
269  Parser.Lex();
270  return Ok;
271  }
272 
273  bool expect(AsmToken::TokenKind Kind, const char *KindName) {
274  if (!isNext(Kind))
275  return error(std::string("Expected ") + KindName + ", instead got: ",
276  Lexer.getTok());
277  return false;
278  }
279 
280  StringRef expectIdent() {
281  if (!Lexer.is(AsmToken::Identifier)) {
282  error("Expected identifier, got: ", Lexer.getTok());
283  return StringRef();
284  }
285  auto Name = Lexer.getTok().getString();
286  Parser.Lex();
287  return Name;
288  }
289 
291  // FIXME: can't use StringSwitch because wasm::ValType doesn't have a
292  // "invalid" value.
293  if (Type == "i32")
294  return wasm::ValType::I32;
295  if (Type == "i64")
296  return wasm::ValType::I64;
297  if (Type == "f32")
298  return wasm::ValType::F32;
299  if (Type == "f64")
300  return wasm::ValType::F64;
301  if (Type == "v128" || Type == "i8x16" || Type == "i16x8" ||
302  Type == "i32x4" || Type == "i64x2" || Type == "f32x4" ||
303  Type == "f64x2")
304  return wasm::ValType::V128;
305  if (Type == "except_ref")
307  return Optional<wasm::ValType>();
308  }
309 
310  WebAssembly::ExprType parseBlockType(StringRef ID) {
312  .Case("i32", WebAssembly::ExprType::I32)
317  .Case("except_ref", WebAssembly::ExprType::ExceptRef)
320  }
321 
322  bool parseRegTypeList(SmallVectorImpl<wasm::ValType> &Types) {
323  while (Lexer.is(AsmToken::Identifier)) {
324  auto Type = parseType(Lexer.getTok().getString());
325  if (!Type)
326  return error("unknown type: ", Lexer.getTok());
327  Types.push_back(Type.getValue());
328  Parser.Lex();
329  if (!isNext(AsmToken::Comma))
330  break;
331  }
332  return false;
333  }
334 
335  void parseSingleInteger(bool IsNegative, OperandVector &Operands) {
336  auto &Int = Lexer.getTok();
337  int64_t Val = Int.getIntVal();
338  if (IsNegative)
339  Val = -Val;
340  Operands.push_back(make_unique<WebAssemblyOperand>(
341  WebAssemblyOperand::Integer, Int.getLoc(), Int.getEndLoc(),
342  WebAssemblyOperand::IntOp{Val}));
343  Parser.Lex();
344  }
345 
346  bool parseOperandStartingWithInteger(bool IsNegative, OperandVector &Operands,
347  StringRef InstName) {
348  parseSingleInteger(IsNegative, Operands);
349  // FIXME: there is probably a cleaner way to do this.
350  auto IsLoadStore = InstName.startswith("load") ||
351  InstName.startswith("store") ||
352  InstName.startswith("atomic");
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  bool CheckDataSection() {
557  if (CurrentState != DataSection) {
558  auto WS = cast<MCSectionWasm>(getStreamer().getCurrentSection().first);
559  if (WS && WS->getKind().isText())
560  return error("data directive must occur in a data segment: ",
561  Lexer.getTok());
562  }
563  CurrentState = DataSection;
564  return false;
565  }
566 
567  // This function processes wasm-specific directives streamed to
568  // WebAssemblyTargetStreamer, all others go to the generic parser
569  // (see WasmAsmParser).
570  bool ParseDirective(AsmToken DirectiveID) override {
571  // This function has a really weird return value behavior that is different
572  // from all the other parsing functions:
573  // - return true && no tokens consumed -> don't know this directive / let
574  // the generic parser handle it.
575  // - return true && tokens consumed -> a parsing error occurred.
576  // - return false -> processed this directive successfully.
577  assert(DirectiveID.getKind() == AsmToken::Identifier);
578  auto &Out = getStreamer();
579  auto &TOut =
580  reinterpret_cast<WebAssemblyTargetStreamer &>(*Out.getTargetStreamer());
581  auto &Ctx = Out.getContext();
582 
583  // TODO: any time we return an error, at least one token must have been
584  // consumed, otherwise this will not signal an error to the caller.
585  if (DirectiveID.getString() == ".globaltype") {
586  auto SymName = expectIdent();
587  if (SymName.empty())
588  return true;
589  if (expect(AsmToken::Comma, ","))
590  return true;
591  auto TypeTok = Lexer.getTok();
592  auto TypeName = expectIdent();
593  if (TypeName.empty())
594  return true;
595  auto Type = parseType(TypeName);
596  if (!Type)
597  return error("Unknown type in .globaltype directive: ", TypeTok);
598  // Now set this symbol with the correct type.
599  auto WasmSym = cast<MCSymbolWasm>(Ctx.getOrCreateSymbol(SymName));
600  WasmSym->setType(wasm::WASM_SYMBOL_TYPE_GLOBAL);
601  WasmSym->setGlobalType(
602  wasm::WasmGlobalType{uint8_t(Type.getValue()), true});
603  // And emit the directive again.
604  TOut.emitGlobalType(WasmSym);
605  return expect(AsmToken::EndOfStatement, "EOL");
606  }
607 
608  if (DirectiveID.getString() == ".functype") {
609  // This code has to send things to the streamer similar to
610  // WebAssemblyAsmPrinter::EmitFunctionBodyStart.
611  // TODO: would be good to factor this into a common function, but the
612  // assembler and backend really don't share any common code, and this code
613  // parses the locals seperately.
614  auto SymName = expectIdent();
615  if (SymName.empty())
616  return true;
617  auto WasmSym = cast<MCSymbolWasm>(Ctx.getOrCreateSymbol(SymName));
618  if (CurrentState == Label && WasmSym == LastLabel) {
619  // This .functype indicates a start of a function.
620  if (ensureEmptyNestingStack())
621  return true;
622  CurrentState = FunctionStart;
623  LastFunctionLabel = LastLabel;
624  push(Function);
625  }
626  auto Signature = make_unique<wasm::WasmSignature>();
627  if (parseSignature(Signature.get()))
628  return true;
629  WasmSym->setSignature(Signature.get());
630  addSignature(std::move(Signature));
631  WasmSym->setType(wasm::WASM_SYMBOL_TYPE_FUNCTION);
632  TOut.emitFunctionType(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() == ".eventtype") {
638  auto SymName = expectIdent();
639  if (SymName.empty())
640  return true;
641  auto WasmSym = cast<MCSymbolWasm>(Ctx.getOrCreateSymbol(SymName));
642  auto Signature = make_unique<wasm::WasmSignature>();
643  if (parseRegTypeList(Signature->Params))
644  return true;
645  WasmSym->setSignature(Signature.get());
646  addSignature(std::move(Signature));
647  WasmSym->setType(wasm::WASM_SYMBOL_TYPE_EVENT);
648  TOut.emitEventType(WasmSym);
649  // TODO: backend also calls TOut.emitIndIdx, but that is not implemented.
650  return expect(AsmToken::EndOfStatement, "EOL");
651  }
652 
653  if (DirectiveID.getString() == ".local") {
654  if (CurrentState != FunctionStart)
655  return error(".local directive should follow the start of a function",
656  Lexer.getTok());
658  if (parseRegTypeList(Locals))
659  return true;
660  TOut.emitLocal(Locals);
661  CurrentState = FunctionLocals;
662  return expect(AsmToken::EndOfStatement, "EOL");
663  }
664 
665  if (DirectiveID.getString() == ".int8") {
666  if (CheckDataSection()) return true;
667  int64_t V;
668  if (Parser.parseAbsoluteExpression(V))
669  return error("Cannot parse int8 constant: ", Lexer.getTok());
670  // TODO: error if value doesn't fit?
671  Out.EmitIntValue(static_cast<uint64_t>(V), 1);
672  return expect(AsmToken::EndOfStatement, "EOL");
673  }
674 
675  if (DirectiveID.getString() == ".asciz") {
676  if (CheckDataSection()) return true;
677  std::string S;
678  if (Parser.parseEscapedString(S))
679  return error("Cannot parse string constant: ", Lexer.getTok());
680  Out.EmitBytes(StringRef(S.c_str(), S.length() + 1));
681  return expect(AsmToken::EndOfStatement, "EOL");
682  }
683 
684  return true; // We didn't process this directive.
685  }
686 
687  bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned & /*Opcode*/,
688  OperandVector &Operands, MCStreamer &Out,
689  uint64_t &ErrorInfo,
690  bool MatchingInlineAsm) override {
691  MCInst Inst;
692  unsigned MatchResult =
693  MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
694  switch (MatchResult) {
695  case Match_Success: {
696  if (CurrentState == FunctionStart) {
697  // This is the first instruction in a function, but we haven't seen
698  // a .local directive yet. The streamer requires locals to be encoded
699  // as a prelude to the instructions, so emit an empty list of locals
700  // here.
701  auto &TOut = reinterpret_cast<WebAssemblyTargetStreamer &>(
702  *Out.getTargetStreamer());
704  }
705  Out.EmitInstruction(Inst, getSTI());
706  if (CurrentState == EndFunction) {
707  onEndOfFunction();
708  } else {
709  CurrentState = Instructions;
710  }
711  return false;
712  }
713  case Match_MissingFeature:
714  return Parser.Error(
715  IDLoc, "instruction requires a WASM feature not currently enabled");
716  case Match_MnemonicFail:
717  return Parser.Error(IDLoc, "invalid instruction");
718  case Match_NearMisses:
719  return Parser.Error(IDLoc, "ambiguous instruction");
720  case Match_InvalidTiedOperand:
721  case Match_InvalidOperand: {
722  SMLoc ErrorLoc = IDLoc;
723  if (ErrorInfo != ~0ULL) {
724  if (ErrorInfo >= Operands.size())
725  return Parser.Error(IDLoc, "too few operands for instruction");
726  ErrorLoc = Operands[ErrorInfo]->getStartLoc();
727  if (ErrorLoc == SMLoc())
728  ErrorLoc = IDLoc;
729  }
730  return Parser.Error(ErrorLoc, "invalid operand for instruction");
731  }
732  }
733  llvm_unreachable("Implement any new match types added!");
734  }
735 
736  void doBeforeLabelEmit(MCSymbol *Symbol) override {
737  // Start a new section for the next function automatically, since our
738  // object writer expects each function to have its own section. This way
739  // The user can't forget this "convention".
740  auto SymName = Symbol->getName();
741  if (SymName.startswith(".L"))
742  return; // Local Symbol.
743  auto SecName = ".text." + SymName;
744  auto WS = getContext().getWasmSection(SecName, SectionKind::getText());
745  getStreamer().SwitchSection(WS);
746  }
747 
748  void onEndOfFunction() {
749  // Automatically output a .size directive, so it becomes optional for the
750  // user.
751  if (!LastFunctionLabel) return;
752  auto TempSym = getContext().createLinkerPrivateTempSymbol();
753  getStreamer().EmitLabel(TempSym);
754  auto Start = MCSymbolRefExpr::create(LastFunctionLabel, getContext());
755  auto End = MCSymbolRefExpr::create(TempSym, getContext());
756  auto Expr =
757  MCBinaryExpr::create(MCBinaryExpr::Sub, End, Start, getContext());
758  getStreamer().emitELFSize(LastFunctionLabel, Expr);
759  }
760 
761  void onEndOfFile() override { ensureEmptyNestingStack(); }
762 };
763 } // end anonymous namespace
764 
765 // Force static initialization.
769 }
770 
771 #define GET_REGISTER_MATCHER
772 #define GET_MATCHER_IMPLEMENTATION
773 #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:321
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:960
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:336
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:122
MCParsedAsmOperand - This abstract class represents a source-level assembly instruction operand...
SmallVector< ValType, 4 > Params
Definition: Wasm.h:337
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
virtual bool parseEscapedString(std::string &Data)=0
Parse the current token as a string which may include escaped characters and return the string conten...
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:841
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:201
#define I(x, y, z)
Definition: MD5.cpp:58
#define N
Generic base class for all target subtargets.
virtual bool parseAbsoluteExpression(int64_t &Res)=0
Parse an expression which must evaluate to an absolute value.
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
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:439
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