LLVM  14.0.0git
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 
22 #include "WebAssembly.h"
23 #include "llvm/MC/MCContext.h"
24 #include "llvm/MC/MCExpr.h"
25 #include "llvm/MC/MCInst.h"
26 #include "llvm/MC/MCInstrInfo.h"
29 #include "llvm/MC/MCSectionWasm.h"
30 #include "llvm/MC/MCStreamer.h"
32 #include "llvm/MC/MCSymbol.h"
33 #include "llvm/MC/MCSymbolWasm.h"
34 #include "llvm/Support/Endian.h"
35 #include "llvm/Support/SourceMgr.h"
37 
38 using namespace llvm;
39 
40 #define DEBUG_TYPE "wasm-asm-parser"
41 
42 static const char *getSubtargetFeatureName(uint64_t Val);
43 
44 namespace {
45 
46 /// WebAssemblyOperand - Instances of this class represent the operands in a
47 /// parsed Wasm machine instruction.
48 struct WebAssemblyOperand : public MCParsedAsmOperand {
49  enum KindTy { Token, Integer, Float, Symbol, BrList } Kind;
50 
51  SMLoc StartLoc, EndLoc;
52 
53  struct TokOp {
54  StringRef Tok;
55  };
56 
57  struct IntOp {
58  int64_t Val;
59  };
60 
61  struct FltOp {
62  double Val;
63  };
64 
65  struct SymOp {
66  const MCExpr *Exp;
67  };
68 
69  struct BrLOp {
70  std::vector<unsigned> List;
71  };
72 
73  union {
74  struct TokOp Tok;
75  struct IntOp Int;
76  struct FltOp Flt;
77  struct SymOp Sym;
78  struct BrLOp BrL;
79  };
80 
81  WebAssemblyOperand(KindTy K, SMLoc Start, SMLoc End, TokOp T)
82  : Kind(K), StartLoc(Start), EndLoc(End), Tok(T) {}
83  WebAssemblyOperand(KindTy K, SMLoc Start, SMLoc End, IntOp I)
84  : Kind(K), StartLoc(Start), EndLoc(End), Int(I) {}
85  WebAssemblyOperand(KindTy K, SMLoc Start, SMLoc End, FltOp F)
86  : Kind(K), StartLoc(Start), EndLoc(End), Flt(F) {}
87  WebAssemblyOperand(KindTy K, SMLoc Start, SMLoc End, SymOp S)
88  : Kind(K), StartLoc(Start), EndLoc(End), Sym(S) {}
89  WebAssemblyOperand(KindTy K, SMLoc Start, SMLoc End)
90  : Kind(K), StartLoc(Start), EndLoc(End), BrL() {}
91 
92  ~WebAssemblyOperand() {
93  if (isBrList())
94  BrL.~BrLOp();
95  }
96 
97  bool isToken() const override { return Kind == Token; }
98  bool isImm() const override { return Kind == Integer || Kind == Symbol; }
99  bool isFPImm() const { return Kind == Float; }
100  bool isMem() const override { return false; }
101  bool isReg() const override { return false; }
102  bool isBrList() const { return Kind == BrList; }
103 
104  unsigned getReg() const override {
105  llvm_unreachable("Assembly inspects a register operand");
106  return 0;
107  }
108 
109  StringRef getToken() const {
110  assert(isToken());
111  return Tok.Tok;
112  }
113 
114  SMLoc getStartLoc() const override { return StartLoc; }
115  SMLoc getEndLoc() const override { return EndLoc; }
116 
117  void addRegOperands(MCInst &, unsigned) const {
118  // Required by the assembly matcher.
119  llvm_unreachable("Assembly matcher creates register operands");
120  }
121 
122  void addImmOperands(MCInst &Inst, unsigned N) const {
123  assert(N == 1 && "Invalid number of operands!");
124  if (Kind == Integer)
126  else if (Kind == Symbol)
127  Inst.addOperand(MCOperand::createExpr(Sym.Exp));
128  else
129  llvm_unreachable("Should be integer immediate or symbol!");
130  }
131 
132  void addFPImmf32Operands(MCInst &Inst, unsigned N) const {
133  assert(N == 1 && "Invalid number of operands!");
134  if (Kind == Float)
135  Inst.addOperand(
136  MCOperand::createSFPImm(bit_cast<uint32_t>(float(Flt.Val))));
137  else
138  llvm_unreachable("Should be float immediate!");
139  }
140 
141  void addFPImmf64Operands(MCInst &Inst, unsigned N) const {
142  assert(N == 1 && "Invalid number of operands!");
143  if (Kind == Float)
144  Inst.addOperand(MCOperand::createDFPImm(bit_cast<uint64_t>(Flt.Val)));
145  else
146  llvm_unreachable("Should be float immediate!");
147  }
148 
149  void addBrListOperands(MCInst &Inst, unsigned N) const {
150  assert(N == 1 && isBrList() && "Invalid BrList!");
151  for (auto Br : BrL.List)
153  }
154 
155  void print(raw_ostream &OS) const override {
156  switch (Kind) {
157  case Token:
158  OS << "Tok:" << Tok.Tok;
159  break;
160  case Integer:
161  OS << "Int:" << Int.Val;
162  break;
163  case Float:
164  OS << "Flt:" << Flt.Val;
165  break;
166  case Symbol:
167  OS << "Sym:" << Sym.Exp;
168  break;
169  case BrList:
170  OS << "BrList:" << BrL.List.size();
171  break;
172  }
173  }
174 };
175 
176 // Perhaps this should go somewhere common.
177 static wasm::WasmLimits DefaultLimits() {
178  return {wasm::WASM_LIMITS_FLAG_NONE, 0, 0};
179 }
180 
181 static MCSymbolWasm *GetOrCreateFunctionTableSymbol(MCContext &Ctx,
182  const StringRef &Name) {
183  MCSymbolWasm *Sym = cast_or_null<MCSymbolWasm>(Ctx.lookupSymbol(Name));
184  if (Sym) {
185  if (!Sym->isFunctionTable())
186  Ctx.reportError(SMLoc(), "symbol is not a wasm funcref table");
187  } else {
188  Sym = cast<MCSymbolWasm>(Ctx.getOrCreateSymbol(Name));
189  Sym->setFunctionTable();
190  // The default function table is synthesized by the linker.
191  Sym->setUndefined();
192  }
193  return Sym;
194 }
195 
196 class WebAssemblyAsmParser final : public MCTargetAsmParser {
197  MCAsmParser &Parser;
198  MCAsmLexer &Lexer;
199 
200  // Much like WebAssemblyAsmPrinter in the backend, we have to own these.
201  std::vector<std::unique_ptr<wasm::WasmSignature>> Signatures;
202  std::vector<std::unique_ptr<std::string>> Names;
203 
204  // Order of labels, directives and instructions in a .s file have no
205  // syntactical enforcement. This class is a callback from the actual parser,
206  // and yet we have to be feeding data to the streamer in a very particular
207  // order to ensure a correct binary encoding that matches the regular backend
208  // (the streamer does not enforce this). This "state machine" enum helps
209  // guarantee that correct order.
210  enum ParserState {
211  FileStart,
212  FunctionStart,
213  FunctionLocals,
214  Instructions,
215  EndFunction,
216  DataSection,
217  } CurrentState = FileStart;
218 
219  // For ensuring blocks are properly nested.
220  enum NestingType {
221  Function,
222  Block,
223  Loop,
224  Try,
225  CatchAll,
226  If,
227  Else,
228  Undefined,
229  };
230  struct Nested {
231  NestingType NT;
233  };
234  std::vector<Nested> NestingStack;
235 
236  MCSymbolWasm *DefaultFunctionTable = nullptr;
237  MCSymbol *LastFunctionLabel = nullptr;
238 
239  bool is64;
240 
242  // Don't type check if -no-type-check was set.
243  bool SkipTypeCheck;
244 
245 public:
246  WebAssemblyAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
247  const MCInstrInfo &MII, const MCTargetOptions &Options)
248  : MCTargetAsmParser(Options, STI, MII), Parser(Parser),
249  Lexer(Parser.getLexer()),
250  is64(STI.getTargetTriple().isArch64Bit()),
251  TC(Parser, MII, is64), SkipTypeCheck(Options.MCNoTypeCheck) {
252  setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
253  // Don't type check if this is inline asm, since that is a naked sequence of
254  // instructions without a function/locals decl.
255  auto &SM = Parser.getSourceManager();
256  auto BufferName =
257  SM.getBufferInfo(SM.getMainFileID()).Buffer->getBufferIdentifier();
258  if (BufferName == "<inline asm>")
259  SkipTypeCheck = true;
260  }
261 
262  void Initialize(MCAsmParser &Parser) override {
264 
265  DefaultFunctionTable = GetOrCreateFunctionTableSymbol(
266  getContext(), "__indirect_function_table");
267  if (!STI->checkFeatures("+reference-types"))
268  DefaultFunctionTable->setOmitFromLinkingSection();
269  }
270 
271 #define GET_ASSEMBLER_HEADER
272 #include "WebAssemblyGenAsmMatcher.inc"
273 
274  // TODO: This is required to be implemented, but appears unused.
275  bool ParseRegister(unsigned & /*RegNo*/, SMLoc & /*StartLoc*/,
276  SMLoc & /*EndLoc*/) override {
277  llvm_unreachable("ParseRegister is not implemented.");
278  }
279  OperandMatchResultTy tryParseRegister(unsigned & /*RegNo*/,
280  SMLoc & /*StartLoc*/,
281  SMLoc & /*EndLoc*/) override {
282  llvm_unreachable("tryParseRegister is not implemented.");
283  }
284 
285  bool error(const Twine &Msg, const AsmToken &Tok) {
286  return Parser.Error(Tok.getLoc(), Msg + Tok.getString());
287  }
288 
289  bool error(const Twine &Msg) {
290  return Parser.Error(Lexer.getTok().getLoc(), Msg);
291  }
292 
293  void addSignature(std::unique_ptr<wasm::WasmSignature> &&Sig) {
294  Signatures.push_back(std::move(Sig));
295  }
296 
297  StringRef storeName(StringRef Name) {
298  std::unique_ptr<std::string> N = std::make_unique<std::string>(Name);
299  Names.push_back(std::move(N));
300  return *Names.back();
301  }
302 
303  std::pair<StringRef, StringRef> nestingString(NestingType NT) {
304  switch (NT) {
305  case Function:
306  return {"function", "end_function"};
307  case Block:
308  return {"block", "end_block"};
309  case Loop:
310  return {"loop", "end_loop"};
311  case Try:
312  return {"try", "end_try/delegate"};
313  case CatchAll:
314  return {"catch_all", "end_try"};
315  case If:
316  return {"if", "end_if"};
317  case Else:
318  return {"else", "end_if"};
319  default:
320  llvm_unreachable("unknown NestingType");
321  }
322  }
323 
324  void push(NestingType NT) { NestingStack.push_back({NT, wasm::WasmSignature()}); }
325 
326  bool pop(StringRef Ins, NestingType NT1, NestingType NT2 = Undefined) {
327  if (NestingStack.empty())
328  return error(Twine("End of block construct with no start: ") + Ins);
329  auto Top = NestingStack.back();
330  if (Top.NT != NT1 && Top.NT != NT2)
331  return error(Twine("Block construct type mismatch, expected: ") +
332  nestingString(Top.NT).second + ", instead got: " + Ins);
333  TC.setLastSig(Top.Sig);
334  NestingStack.pop_back();
335  return false;
336  }
337 
338  bool ensureEmptyNestingStack() {
339  auto Err = !NestingStack.empty();
340  while (!NestingStack.empty()) {
341  error(Twine("Unmatched block construct(s) at function end: ") +
342  nestingString(NestingStack.back().NT).first);
343  NestingStack.pop_back();
344  }
345  return Err;
346  }
347 
348  bool isNext(AsmToken::TokenKind Kind) {
349  auto Ok = Lexer.is(Kind);
350  if (Ok)
351  Parser.Lex();
352  return Ok;
353  }
354 
355  bool expect(AsmToken::TokenKind Kind, const char *KindName) {
356  if (!isNext(Kind))
357  return error(std::string("Expected ") + KindName + ", instead got: ",
358  Lexer.getTok());
359  return false;
360  }
361 
362  StringRef expectIdent() {
363  if (!Lexer.is(AsmToken::Identifier)) {
364  error("Expected identifier, got: ", Lexer.getTok());
365  return StringRef();
366  }
367  auto Name = Lexer.getTok().getString();
368  Parser.Lex();
369  return Name;
370  }
371 
372  bool parseRegTypeList(SmallVectorImpl<wasm::ValType> &Types) {
373  while (Lexer.is(AsmToken::Identifier)) {
374  auto Type = WebAssembly::parseType(Lexer.getTok().getString());
375  if (!Type)
376  return error("unknown type: ", Lexer.getTok());
377  Types.push_back(Type.getValue());
378  Parser.Lex();
379  if (!isNext(AsmToken::Comma))
380  break;
381  }
382  return false;
383  }
384 
385  void parseSingleInteger(bool IsNegative, OperandVector &Operands) {
386  auto &Int = Lexer.getTok();
387  int64_t Val = Int.getIntVal();
388  if (IsNegative)
389  Val = -Val;
390  Operands.push_back(std::make_unique<WebAssemblyOperand>(
391  WebAssemblyOperand::Integer, Int.getLoc(), Int.getEndLoc(),
392  WebAssemblyOperand::IntOp{Val}));
393  Parser.Lex();
394  }
395 
396  bool parseSingleFloat(bool IsNegative, OperandVector &Operands) {
397  auto &Flt = Lexer.getTok();
398  double Val;
399  if (Flt.getString().getAsDouble(Val, false))
400  return error("Cannot parse real: ", Flt);
401  if (IsNegative)
402  Val = -Val;
403  Operands.push_back(std::make_unique<WebAssemblyOperand>(
404  WebAssemblyOperand::Float, Flt.getLoc(), Flt.getEndLoc(),
405  WebAssemblyOperand::FltOp{Val}));
406  Parser.Lex();
407  return false;
408  }
409 
410  bool parseSpecialFloatMaybe(bool IsNegative, OperandVector &Operands) {
411  if (Lexer.isNot(AsmToken::Identifier))
412  return true;
413  auto &Flt = Lexer.getTok();
414  auto S = Flt.getString();
415  double Val;
416  if (S.compare_insensitive("infinity") == 0) {
417  Val = std::numeric_limits<double>::infinity();
418  } else if (S.compare_insensitive("nan") == 0) {
419  Val = std::numeric_limits<double>::quiet_NaN();
420  } else {
421  return true;
422  }
423  if (IsNegative)
424  Val = -Val;
425  Operands.push_back(std::make_unique<WebAssemblyOperand>(
426  WebAssemblyOperand::Float, Flt.getLoc(), Flt.getEndLoc(),
427  WebAssemblyOperand::FltOp{Val}));
428  Parser.Lex();
429  return false;
430  }
431 
432  bool checkForP2AlignIfLoadStore(OperandVector &Operands, StringRef InstName) {
433  // FIXME: there is probably a cleaner way to do this.
434  auto IsLoadStore = InstName.find(".load") != StringRef::npos ||
435  InstName.find(".store") != StringRef::npos ||
436  InstName.find("prefetch") != StringRef::npos;
437  auto IsAtomic = InstName.find("atomic.") != StringRef::npos;
438  if (IsLoadStore || IsAtomic) {
439  // Parse load/store operands of the form: offset:p2align=align
440  if (IsLoadStore && isNext(AsmToken::Colon)) {
441  auto Id = expectIdent();
442  if (Id != "p2align")
443  return error("Expected p2align, instead got: " + Id);
444  if (expect(AsmToken::Equal, "="))
445  return true;
446  if (!Lexer.is(AsmToken::Integer))
447  return error("Expected integer constant");
448  parseSingleInteger(false, Operands);
449  } else {
450  // v128.{load,store}{8,16,32,64}_lane has both a memarg and a lane
451  // index. We need to avoid parsing an extra alignment operand for the
452  // lane index.
453  auto IsLoadStoreLane = InstName.find("_lane") != StringRef::npos;
454  if (IsLoadStoreLane && Operands.size() == 4)
455  return false;
456  // Alignment not specified (or atomics, must use default alignment).
457  // We can't just call WebAssembly::GetDefaultP2Align since we don't have
458  // an opcode until after the assembly matcher, so set a default to fix
459  // up later.
460  auto Tok = Lexer.getTok();
461  Operands.push_back(std::make_unique<WebAssemblyOperand>(
463  WebAssemblyOperand::IntOp{-1}));
464  }
465  }
466  return false;
467  }
468 
469  void addBlockTypeOperand(OperandVector &Operands, SMLoc NameLoc,
472  wasm::WasmSignature Sig({static_cast<wasm::ValType>(BT)}, {});
473  TC.setLastSig(Sig);
474  NestingStack.back().Sig = Sig;
475  }
476  Operands.push_back(std::make_unique<WebAssemblyOperand>(
477  WebAssemblyOperand::Integer, NameLoc, NameLoc,
478  WebAssemblyOperand::IntOp{static_cast<int64_t>(BT)}));
479  }
480 
481  bool parseLimits(wasm::WasmLimits *Limits) {
482  auto Tok = Lexer.getTok();
483  if (!Tok.is(AsmToken::Integer))
484  return error("Expected integer constant, instead got: ", Tok);
485  int64_t Val = Tok.getIntVal();
486  assert(Val >= 0);
487  Limits->Minimum = Val;
488  Parser.Lex();
489 
490  if (isNext(AsmToken::Comma)) {
492  auto Tok = Lexer.getTok();
493  if (!Tok.is(AsmToken::Integer))
494  return error("Expected integer constant, instead got: ", Tok);
495  int64_t Val = Tok.getIntVal();
496  assert(Val >= 0);
497  Limits->Maximum = Val;
498  Parser.Lex();
499  }
500  return false;
501  }
502 
503  bool parseFunctionTableOperand(std::unique_ptr<WebAssemblyOperand> *Op) {
504  if (STI->checkFeatures("+reference-types")) {
505  // If the reference-types feature is enabled, there is an explicit table
506  // operand. To allow the same assembly to be compiled with or without
507  // reference types, we allow the operand to be omitted, in which case we
508  // default to __indirect_function_table.
509  auto &Tok = Lexer.getTok();
510  if (Tok.is(AsmToken::Identifier)) {
511  auto *Sym =
512  GetOrCreateFunctionTableSymbol(getContext(), Tok.getString());
513  const auto *Val = MCSymbolRefExpr::create(Sym, getContext());
514  *Op = std::make_unique<WebAssemblyOperand>(
516  WebAssemblyOperand::SymOp{Val});
517  Parser.Lex();
518  return expect(AsmToken::Comma, ",");
519  } else {
520  const auto *Val =
521  MCSymbolRefExpr::create(DefaultFunctionTable, getContext());
522  *Op = std::make_unique<WebAssemblyOperand>(
524  WebAssemblyOperand::SymOp{Val});
525  return false;
526  }
527  } else {
528  // For the MVP there is at most one table whose number is 0, but we can't
529  // write a table symbol or issue relocations. Instead we just ensure the
530  // table is live and write a zero.
531  getStreamer().emitSymbolAttribute(DefaultFunctionTable, MCSA_NoDeadStrip);
532  *Op = std::make_unique<WebAssemblyOperand>(WebAssemblyOperand::Integer,
533  SMLoc(), SMLoc(),
534  WebAssemblyOperand::IntOp{0});
535  return false;
536  }
537  }
538 
539  bool ParseInstruction(ParseInstructionInfo & /*Info*/, StringRef Name,
540  SMLoc NameLoc, OperandVector &Operands) override {
541  // Note: Name does NOT point into the sourcecode, but to a local, so
542  // use NameLoc instead.
543  Name = StringRef(NameLoc.getPointer(), Name.size());
544 
545  // WebAssembly has instructions with / in them, which AsmLexer parses
546  // as separate tokens, so if we find such tokens immediately adjacent (no
547  // whitespace), expand the name to include them:
548  for (;;) {
549  auto &Sep = Lexer.getTok();
550  if (Sep.getLoc().getPointer() != Name.end() ||
551  Sep.getKind() != AsmToken::Slash)
552  break;
553  // Extend name with /
554  Name = StringRef(Name.begin(), Name.size() + Sep.getString().size());
555  Parser.Lex();
556  // We must now find another identifier, or error.
557  auto &Id = Lexer.getTok();
558  if (Id.getKind() != AsmToken::Identifier ||
559  Id.getLoc().getPointer() != Name.end())
560  return error("Incomplete instruction name: ", Id);
561  Name = StringRef(Name.begin(), Name.size() + Id.getString().size());
562  Parser.Lex();
563  }
564 
565  // Now construct the name as first operand.
566  Operands.push_back(std::make_unique<WebAssemblyOperand>(
567  WebAssemblyOperand::Token, NameLoc, SMLoc::getFromPointer(Name.end()),
568  WebAssemblyOperand::TokOp{Name}));
569 
570  // If this instruction is part of a control flow structure, ensure
571  // proper nesting.
572  bool ExpectBlockType = false;
573  bool ExpectFuncType = false;
574  bool ExpectHeapType = false;
575  std::unique_ptr<WebAssemblyOperand> FunctionTable;
576  if (Name == "block") {
577  push(Block);
578  ExpectBlockType = true;
579  } else if (Name == "loop") {
580  push(Loop);
581  ExpectBlockType = true;
582  } else if (Name == "try") {
583  push(Try);
584  ExpectBlockType = true;
585  } else if (Name == "if") {
586  push(If);
587  ExpectBlockType = true;
588  } else if (Name == "else") {
589  if (pop(Name, If))
590  return true;
591  push(Else);
592  } else if (Name == "catch") {
593  if (pop(Name, Try))
594  return true;
595  push(Try);
596  } else if (Name == "catch_all") {
597  if (pop(Name, Try))
598  return true;
599  push(CatchAll);
600  } else if (Name == "end_if") {
601  if (pop(Name, If, Else))
602  return true;
603  } else if (Name == "end_try") {
604  if (pop(Name, Try, CatchAll))
605  return true;
606  } else if (Name == "delegate") {
607  if (pop(Name, Try))
608  return true;
609  } else if (Name == "end_loop") {
610  if (pop(Name, Loop))
611  return true;
612  } else if (Name == "end_block") {
613  if (pop(Name, Block))
614  return true;
615  } else if (Name == "end_function") {
616  ensureLocals(getStreamer());
617  CurrentState = EndFunction;
618  if (pop(Name, Function) || ensureEmptyNestingStack())
619  return true;
620  } else if (Name == "call_indirect" || Name == "return_call_indirect") {
621  // These instructions have differing operand orders in the text format vs
622  // the binary formats. The MC instructions follow the binary format, so
623  // here we stash away the operand and append it later.
624  if (parseFunctionTableOperand(&FunctionTable))
625  return true;
626  ExpectFuncType = true;
627  } else if (Name == "ref.null") {
628  ExpectHeapType = true;
629  }
630 
631  if (ExpectFuncType || (ExpectBlockType && Lexer.is(AsmToken::LParen))) {
632  // This has a special TYPEINDEX operand which in text we
633  // represent as a signature, such that we can re-build this signature,
634  // attach it to an anonymous symbol, which is what WasmObjectWriter
635  // expects to be able to recreate the actual unique-ified type indices.
636  auto Loc = Parser.getTok();
637  auto Signature = std::make_unique<wasm::WasmSignature>();
638  if (parseSignature(Signature.get()))
639  return true;
640  // Got signature as block type, don't need more
641  ExpectBlockType = false;
642  TC.setLastSig(*Signature.get());
643  if (ExpectBlockType)
644  NestingStack.back().Sig = *Signature.get();
645  auto &Ctx = getContext();
646  // The "true" here will cause this to be a nameless symbol.
647  MCSymbol *Sym = Ctx.createTempSymbol("typeindex", true);
648  auto *WasmSym = cast<MCSymbolWasm>(Sym);
649  WasmSym->setSignature(Signature.get());
650  addSignature(std::move(Signature));
651  WasmSym->setType(wasm::WASM_SYMBOL_TYPE_FUNCTION);
652  const MCExpr *Expr = MCSymbolRefExpr::create(
653  WasmSym, MCSymbolRefExpr::VK_WASM_TYPEINDEX, Ctx);
654  Operands.push_back(std::make_unique<WebAssemblyOperand>(
655  WebAssemblyOperand::Symbol, Loc.getLoc(), Loc.getEndLoc(),
656  WebAssemblyOperand::SymOp{Expr}));
657  }
658 
659  while (Lexer.isNot(AsmToken::EndOfStatement)) {
660  auto &Tok = Lexer.getTok();
661  switch (Tok.getKind()) {
662  case AsmToken::Identifier: {
663  if (!parseSpecialFloatMaybe(false, Operands))
664  break;
665  auto &Id = Lexer.getTok();
666  if (ExpectBlockType) {
667  // Assume this identifier is a block_type.
668  auto BT = WebAssembly::parseBlockType(Id.getString());
670  return error("Unknown block type: ", Id);
671  addBlockTypeOperand(Operands, NameLoc, BT);
672  Parser.Lex();
673  } else if (ExpectHeapType) {
674  auto HeapType = WebAssembly::parseHeapType(Id.getString());
676  return error("Expected a heap type: ", Id);
677  }
678  Operands.push_back(std::make_unique<WebAssemblyOperand>(
679  WebAssemblyOperand::Integer, Id.getLoc(), Id.getEndLoc(),
680  WebAssemblyOperand::IntOp{static_cast<int64_t>(HeapType)}));
681  Parser.Lex();
682  } else {
683  // Assume this identifier is a label.
684  const MCExpr *Val;
685  SMLoc End;
686  if (Parser.parseExpression(Val, End))
687  return error("Cannot parse symbol: ", Lexer.getTok());
688  Operands.push_back(std::make_unique<WebAssemblyOperand>(
689  WebAssemblyOperand::Symbol, Id.getLoc(), Id.getEndLoc(),
690  WebAssemblyOperand::SymOp{Val}));
691  if (checkForP2AlignIfLoadStore(Operands, Name))
692  return true;
693  }
694  break;
695  }
696  case AsmToken::Minus:
697  Parser.Lex();
698  if (Lexer.is(AsmToken::Integer)) {
699  parseSingleInteger(true, Operands);
700  if (checkForP2AlignIfLoadStore(Operands, Name))
701  return true;
702  } else if(Lexer.is(AsmToken::Real)) {
703  if (parseSingleFloat(true, Operands))
704  return true;
705  } else if (!parseSpecialFloatMaybe(true, Operands)) {
706  } else {
707  return error("Expected numeric constant instead got: ",
708  Lexer.getTok());
709  }
710  break;
711  case AsmToken::Integer:
712  parseSingleInteger(false, Operands);
713  if (checkForP2AlignIfLoadStore(Operands, Name))
714  return true;
715  break;
716  case AsmToken::Real: {
717  if (parseSingleFloat(false, Operands))
718  return true;
719  break;
720  }
721  case AsmToken::LCurly: {
722  Parser.Lex();
723  auto Op = std::make_unique<WebAssemblyOperand>(
724  WebAssemblyOperand::BrList, Tok.getLoc(), Tok.getEndLoc());
725  if (!Lexer.is(AsmToken::RCurly))
726  for (;;) {
727  Op->BrL.List.push_back(Lexer.getTok().getIntVal());
728  expect(AsmToken::Integer, "integer");
729  if (!isNext(AsmToken::Comma))
730  break;
731  }
732  expect(AsmToken::RCurly, "}");
733  Operands.push_back(std::move(Op));
734  break;
735  }
736  default:
737  return error("Unexpected token in operand: ", Tok);
738  }
739  if (Lexer.isNot(AsmToken::EndOfStatement)) {
740  if (expect(AsmToken::Comma, ","))
741  return true;
742  }
743  }
744  if (ExpectBlockType && Operands.size() == 1) {
745  // Support blocks with no operands as default to void.
746  addBlockTypeOperand(Operands, NameLoc, WebAssembly::BlockType::Void);
747  }
748  if (FunctionTable)
749  Operands.push_back(std::move(FunctionTable));
750  Parser.Lex();
751  return false;
752  }
753 
754  bool parseSignature(wasm::WasmSignature *Signature) {
755  if (expect(AsmToken::LParen, "("))
756  return true;
757  if (parseRegTypeList(Signature->Params))
758  return true;
759  if (expect(AsmToken::RParen, ")"))
760  return true;
761  if (expect(AsmToken::MinusGreater, "->"))
762  return true;
763  if (expect(AsmToken::LParen, "("))
764  return true;
765  if (parseRegTypeList(Signature->Returns))
766  return true;
767  if (expect(AsmToken::RParen, ")"))
768  return true;
769  return false;
770  }
771 
772  bool CheckDataSection() {
773  if (CurrentState != DataSection) {
774  auto WS = cast<MCSectionWasm>(getStreamer().getCurrentSection().first);
775  if (WS && WS->getKind().isText())
776  return error("data directive must occur in a data segment: ",
777  Lexer.getTok());
778  }
779  CurrentState = DataSection;
780  return false;
781  }
782 
783  // This function processes wasm-specific directives streamed to
784  // WebAssemblyTargetStreamer, all others go to the generic parser
785  // (see WasmAsmParser).
786  bool ParseDirective(AsmToken DirectiveID) override {
787  // This function has a really weird return value behavior that is different
788  // from all the other parsing functions:
789  // - return true && no tokens consumed -> don't know this directive / let
790  // the generic parser handle it.
791  // - return true && tokens consumed -> a parsing error occurred.
792  // - return false -> processed this directive successfully.
793  assert(DirectiveID.getKind() == AsmToken::Identifier);
794  auto &Out = getStreamer();
795  auto &TOut =
796  reinterpret_cast<WebAssemblyTargetStreamer &>(*Out.getTargetStreamer());
797  auto &Ctx = Out.getContext();
798 
799  // TODO: any time we return an error, at least one token must have been
800  // consumed, otherwise this will not signal an error to the caller.
801  if (DirectiveID.getString() == ".globaltype") {
802  auto SymName = expectIdent();
803  if (SymName.empty())
804  return true;
805  if (expect(AsmToken::Comma, ","))
806  return true;
807  auto TypeTok = Lexer.getTok();
808  auto TypeName = expectIdent();
809  if (TypeName.empty())
810  return true;
812  if (!Type)
813  return error("Unknown type in .globaltype directive: ", TypeTok);
814  // Optional mutable modifier. Default to mutable for historical reasons.
815  // Ideally we would have gone with immutable as the default and used `mut`
816  // as the modifier to match the `.wat` format.
817  bool Mutable = true;
818  if (isNext(AsmToken::Comma)) {
819  TypeTok = Lexer.getTok();
820  auto Id = expectIdent();
821  if (Id == "immutable")
822  Mutable = false;
823  else
824  // Should we also allow `mutable` and `mut` here for clarity?
825  return error("Unknown type in .globaltype modifier: ", TypeTok);
826  }
827  // Now set this symbol with the correct type.
828  auto WasmSym = cast<MCSymbolWasm>(Ctx.getOrCreateSymbol(SymName));
829  WasmSym->setType(wasm::WASM_SYMBOL_TYPE_GLOBAL);
830  WasmSym->setGlobalType(
831  wasm::WasmGlobalType{uint8_t(Type.getValue()), Mutable});
832  // And emit the directive again.
833  TOut.emitGlobalType(WasmSym);
834  return expect(AsmToken::EndOfStatement, "EOL");
835  }
836 
837  if (DirectiveID.getString() == ".tabletype") {
838  // .tabletype SYM, ELEMTYPE[, MINSIZE[, MAXSIZE]]
839  auto SymName = expectIdent();
840  if (SymName.empty())
841  return true;
842  if (expect(AsmToken::Comma, ","))
843  return true;
844 
845  auto ElemTypeTok = Lexer.getTok();
846  auto ElemTypeName = expectIdent();
847  if (ElemTypeName.empty())
848  return true;
849  Optional<wasm::ValType> ElemType = WebAssembly::parseType(ElemTypeName);
850  if (!ElemType)
851  return error("Unknown type in .tabletype directive: ", ElemTypeTok);
852 
853  wasm::WasmLimits Limits = DefaultLimits();
854  if (isNext(AsmToken::Comma) && parseLimits(&Limits))
855  return true;
856 
857  // Now that we have the name and table type, we can actually create the
858  // symbol
859  auto WasmSym = cast<MCSymbolWasm>(Ctx.getOrCreateSymbol(SymName));
860  WasmSym->setType(wasm::WASM_SYMBOL_TYPE_TABLE);
861  wasm::WasmTableType Type = {uint8_t(ElemType.getValue()), Limits};
862  WasmSym->setTableType(Type);
863  TOut.emitTableType(WasmSym);
864  return expect(AsmToken::EndOfStatement, "EOL");
865  }
866 
867  if (DirectiveID.getString() == ".functype") {
868  // This code has to send things to the streamer similar to
869  // WebAssemblyAsmPrinter::EmitFunctionBodyStart.
870  // TODO: would be good to factor this into a common function, but the
871  // assembler and backend really don't share any common code, and this code
872  // parses the locals separately.
873  auto SymName = expectIdent();
874  if (SymName.empty())
875  return true;
876  auto WasmSym = cast<MCSymbolWasm>(Ctx.getOrCreateSymbol(SymName));
877  if (WasmSym->isDefined()) {
878  // This .functype indicates a start of a function.
879  if (ensureEmptyNestingStack())
880  return true;
881  CurrentState = FunctionStart;
882  LastFunctionLabel = WasmSym;
883  push(Function);
884  }
885  auto Signature = std::make_unique<wasm::WasmSignature>();
886  if (parseSignature(Signature.get()))
887  return true;
888  TC.funcDecl(*Signature);
889  WasmSym->setSignature(Signature.get());
890  addSignature(std::move(Signature));
891  WasmSym->setType(wasm::WASM_SYMBOL_TYPE_FUNCTION);
892  TOut.emitFunctionType(WasmSym);
893  // TODO: backend also calls TOut.emitIndIdx, but that is not implemented.
894  return expect(AsmToken::EndOfStatement, "EOL");
895  }
896 
897  if (DirectiveID.getString() == ".export_name") {
898  auto SymName = expectIdent();
899  if (SymName.empty())
900  return true;
901  if (expect(AsmToken::Comma, ","))
902  return true;
903  auto ExportName = expectIdent();
904  auto WasmSym = cast<MCSymbolWasm>(Ctx.getOrCreateSymbol(SymName));
905  WasmSym->setExportName(storeName(ExportName));
906  TOut.emitExportName(WasmSym, ExportName);
907  }
908 
909  if (DirectiveID.getString() == ".import_module") {
910  auto SymName = expectIdent();
911  if (SymName.empty())
912  return true;
913  if (expect(AsmToken::Comma, ","))
914  return true;
915  auto ImportModule = expectIdent();
916  auto WasmSym = cast<MCSymbolWasm>(Ctx.getOrCreateSymbol(SymName));
917  WasmSym->setImportModule(storeName(ImportModule));
918  TOut.emitImportModule(WasmSym, ImportModule);
919  }
920 
921  if (DirectiveID.getString() == ".import_name") {
922  auto SymName = expectIdent();
923  if (SymName.empty())
924  return true;
925  if (expect(AsmToken::Comma, ","))
926  return true;
927  auto ImportName = expectIdent();
928  auto WasmSym = cast<MCSymbolWasm>(Ctx.getOrCreateSymbol(SymName));
929  WasmSym->setImportName(storeName(ImportName));
930  TOut.emitImportName(WasmSym, ImportName);
931  }
932 
933  if (DirectiveID.getString() == ".tagtype") {
934  auto SymName = expectIdent();
935  if (SymName.empty())
936  return true;
937  auto WasmSym = cast<MCSymbolWasm>(Ctx.getOrCreateSymbol(SymName));
938  auto Signature = std::make_unique<wasm::WasmSignature>();
939  if (parseRegTypeList(Signature->Params))
940  return true;
941  WasmSym->setSignature(Signature.get());
942  addSignature(std::move(Signature));
943  WasmSym->setType(wasm::WASM_SYMBOL_TYPE_TAG);
944  TOut.emitTagType(WasmSym);
945  // TODO: backend also calls TOut.emitIndIdx, but that is not implemented.
946  return expect(AsmToken::EndOfStatement, "EOL");
947  }
948 
949  if (DirectiveID.getString() == ".local") {
950  if (CurrentState != FunctionStart)
951  return error(".local directive should follow the start of a function: ",
952  Lexer.getTok());
954  if (parseRegTypeList(Locals))
955  return true;
956  TC.localDecl(Locals);
957  TOut.emitLocal(Locals);
958  CurrentState = FunctionLocals;
959  return expect(AsmToken::EndOfStatement, "EOL");
960  }
961 
962  if (DirectiveID.getString() == ".int8" ||
963  DirectiveID.getString() == ".int16" ||
964  DirectiveID.getString() == ".int32" ||
965  DirectiveID.getString() == ".int64") {
966  if (CheckDataSection()) return true;
967  const MCExpr *Val;
968  SMLoc End;
969  if (Parser.parseExpression(Val, End))
970  return error("Cannot parse .int expression: ", Lexer.getTok());
971  size_t NumBits = 0;
972  DirectiveID.getString().drop_front(4).getAsInteger(10, NumBits);
973  Out.emitValue(Val, NumBits / 8, End);
974  return expect(AsmToken::EndOfStatement, "EOL");
975  }
976 
977  if (DirectiveID.getString() == ".asciz") {
978  if (CheckDataSection()) return true;
979  std::string S;
980  if (Parser.parseEscapedString(S))
981  return error("Cannot parse string constant: ", Lexer.getTok());
982  Out.emitBytes(StringRef(S.c_str(), S.length() + 1));
983  return expect(AsmToken::EndOfStatement, "EOL");
984  }
985 
986  return true; // We didn't process this directive.
987  }
988 
989  // Called either when the first instruction is parsed of the function ends.
990  void ensureLocals(MCStreamer &Out) {
991  if (CurrentState == FunctionStart) {
992  // We haven't seen a .local directive yet. The streamer requires locals to
993  // be encoded as a prelude to the instructions, so emit an empty list of
994  // locals here.
995  auto &TOut = reinterpret_cast<WebAssemblyTargetStreamer &>(
996  *Out.getTargetStreamer());
998  CurrentState = FunctionLocals;
999  }
1000  }
1001 
1002  bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned & /*Opcode*/,
1004  uint64_t &ErrorInfo,
1005  bool MatchingInlineAsm) override {
1006  MCInst Inst;
1007  Inst.setLoc(IDLoc);
1008  FeatureBitset MissingFeatures;
1009  unsigned MatchResult = MatchInstructionImpl(
1010  Operands, Inst, ErrorInfo, MissingFeatures, MatchingInlineAsm);
1011  switch (MatchResult) {
1012  case Match_Success: {
1013  ensureLocals(Out);
1014  // Fix unknown p2align operands.
1016  if (Align != -1U) {
1017  auto &Op0 = Inst.getOperand(0);
1018  if (Op0.getImm() == -1)
1019  Op0.setImm(Align);
1020  }
1021  if (is64) {
1022  // Upgrade 32-bit loads/stores to 64-bit. These mostly differ by having
1023  // an offset64 arg instead of offset32, but to the assembler matcher
1024  // they're both immediates so don't get selected for.
1025  auto Opc64 = WebAssembly::getWasm64Opcode(
1026  static_cast<uint16_t>(Inst.getOpcode()));
1027  if (Opc64 >= 0) {
1028  Inst.setOpcode(Opc64);
1029  }
1030  }
1031  if (!SkipTypeCheck && TC.typeCheck(IDLoc, Inst))
1032  return true;
1033  Out.emitInstruction(Inst, getSTI());
1034  if (CurrentState == EndFunction) {
1035  onEndOfFunction(IDLoc);
1036  } else {
1037  CurrentState = Instructions;
1038  }
1039  return false;
1040  }
1041  case Match_MissingFeature: {
1042  assert(MissingFeatures.count() > 0 && "Expected missing features");
1043  SmallString<128> Message;
1044  raw_svector_ostream OS(Message);
1045  OS << "instruction requires:";
1046  for (unsigned i = 0, e = MissingFeatures.size(); i != e; ++i)
1047  if (MissingFeatures.test(i))
1048  OS << ' ' << getSubtargetFeatureName(i);
1049  return Parser.Error(IDLoc, Message);
1050  }
1051  case Match_MnemonicFail:
1052  return Parser.Error(IDLoc, "invalid instruction");
1053  case Match_NearMisses:
1054  return Parser.Error(IDLoc, "ambiguous instruction");
1055  case Match_InvalidTiedOperand:
1056  case Match_InvalidOperand: {
1057  SMLoc ErrorLoc = IDLoc;
1058  if (ErrorInfo != ~0ULL) {
1059  if (ErrorInfo >= Operands.size())
1060  return Parser.Error(IDLoc, "too few operands for instruction");
1061  ErrorLoc = Operands[ErrorInfo]->getStartLoc();
1062  if (ErrorLoc == SMLoc())
1063  ErrorLoc = IDLoc;
1064  }
1065  return Parser.Error(ErrorLoc, "invalid operand for instruction");
1066  }
1067  }
1068  llvm_unreachable("Implement any new match types added!");
1069  }
1070 
1071  void doBeforeLabelEmit(MCSymbol *Symbol) override {
1072  // Code below only applies to labels in text sections.
1073  auto CWS = cast<MCSectionWasm>(getStreamer().getCurrentSection().first);
1074  if (!CWS || !CWS->getKind().isText())
1075  return;
1076 
1077  auto WasmSym = cast<MCSymbolWasm>(Symbol);
1078  // Unlike other targets, we don't allow data in text sections (labels
1079  // declared with .type @object).
1080  if (WasmSym->getType() == wasm::WASM_SYMBOL_TYPE_DATA) {
1081  Parser.Error(Parser.getTok().getLoc(),
1082  "Wasm doesn\'t support data symbols in text sections");
1083  return;
1084  }
1085 
1086  // Start a new section for the next function automatically, since our
1087  // object writer expects each function to have its own section. This way
1088  // The user can't forget this "convention".
1089  auto SymName = Symbol->getName();
1090  if (SymName.startswith(".L"))
1091  return; // Local Symbol.
1092 
1093  // TODO: If the user explicitly creates a new function section, we ignore
1094  // its name when we create this one. It would be nice to honor their
1095  // choice, while still ensuring that we create one if they forget.
1096  // (that requires coordination with WasmAsmParser::parseSectionDirective)
1097  auto SecName = ".text." + SymName;
1098 
1099  auto *Group = CWS->getGroup();
1100  // If the current section is a COMDAT, also set the flag on the symbol.
1101  // TODO: Currently the only place that the symbols' comdat flag matters is
1102  // for importing comdat functions. But there's no way to specify that in
1103  // assembly currently.
1104  if (Group)
1105  WasmSym->setComdat(true);
1106  auto *WS =
1107  getContext().getWasmSection(SecName, SectionKind::getText(), 0, Group,
1108  MCContext::GenericSectionID, nullptr);
1109  getStreamer().SwitchSection(WS);
1110  // Also generate DWARF for this section if requested.
1111  if (getContext().getGenDwarfForAssembly())
1112  getContext().addGenDwarfSection(WS);
1113  }
1114 
1115  void onEndOfFunction(SMLoc ErrorLoc) {
1116  TC.endOfFunction(ErrorLoc);
1117 
1118  // Automatically output a .size directive, so it becomes optional for the
1119  // user.
1120  if (!LastFunctionLabel) return;
1121  auto TempSym = getContext().createLinkerPrivateTempSymbol();
1122  getStreamer().emitLabel(TempSym);
1123  auto Start = MCSymbolRefExpr::create(LastFunctionLabel, getContext());
1124  auto End = MCSymbolRefExpr::create(TempSym, getContext());
1125  auto Expr =
1126  MCBinaryExpr::create(MCBinaryExpr::Sub, End, Start, getContext());
1127  getStreamer().emitELFSize(LastFunctionLabel, Expr);
1128  }
1129 
1130  void onEndOfFile() override { ensureEmptyNestingStack(); }
1131 };
1132 } // end anonymous namespace
1133 
1134 // Force static initialization.
1138 }
1139 
1140 #define GET_REGISTER_MATCHER
1141 #define GET_SUBTARGET_FEATURE_NAME
1142 #define GET_MATCHER_IMPLEMENTATION
1143 #include "WebAssemblyGenAsmMatcher.inc"
1144 
1145 StringRef GetMnemonic(unsigned Opc) {
1146  // FIXME: linear search!
1147  for (auto &ME : MatchTable0) {
1148  if (ME.Opcode == Opc) {
1149  return ME.getMnemonic();
1150  }
1151  }
1152  assert(false && "mnemonic not found");
1153  return StringRef();
1154 }
llvm::WebAssemblyTargetStreamer::emitLocal
virtual void emitLocal(ArrayRef< wasm::ValType > Types)=0
.local
i
i
Definition: README.txt:29
llvm::MCAsmParser
Generic assembler parser interface, for use by target specific assembly parsers.
Definition: MCAsmParser.h:124
llvm::MCAsmParser::getSourceManager
virtual SourceMgr & getSourceManager()=0
llvm::MCAsmParser::Error
bool Error(SMLoc L, const Twine &Msg, SMRange Range=None)
Return an error at the location L, with the message Msg.
Definition: MCAsmParser.cpp:99
llvm
---------------------— PointerInfo ------------------------------------—
Definition: AllocatorList.h:23
llvm::WebAssemblyTargetStreamer
WebAssembly-specific streamer interface, to implement support WebAssembly-specific assembly directive...
Definition: WebAssemblyTargetStreamer.h:29
WebAssembly.h
llvm::MCSymbol
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition: MCSymbol.h:41
llvm::AsmToken::is
bool is(TokenKind K) const
Definition: MCAsmMacro.h:82
llvm::wasm::WASM_LIMITS_FLAG_NONE
@ WASM_LIMITS_FLAG_NONE
Definition: Wasm.h:301
llvm::MCOperand::createExpr
static MCOperand createExpr(const MCExpr *Val)
Definition: MCInst.h:162
llvm::MCAsmLexer
Generic assembler lexer interface, for use by target specific assembly lexers.
Definition: MCAsmLexer.h:39
print
static void print(raw_ostream &Out, object::Archive::Kind Kind, T Val)
Definition: ArchiveWriter.cpp:147
llvm::MCParsedAsmOperand
MCParsedAsmOperand - This abstract class represents a source-level assembly instruction operand.
Definition: MCParsedAsmOperand.h:24
llvm::getTheWebAssemblyTarget32
Target & getTheWebAssemblyTarget32()
Definition: WebAssemblyTargetInfo.cpp:20
llvm::wasm::WasmLimits::Minimum
uint64_t Minimum
Definition: Wasm.h:66
llvm::WebAssemblyAsmTypeCheck
Definition: WebAssemblyAsmTypeCheck.h:26
llvm::WebAssembly::HeapType
HeapType
Used as immediate MachineOperands for heap types, e.g. for ref.null.
Definition: WebAssemblyTypeUtilities.h:45
llvm::MCOperand::createImm
static MCOperand createImm(int64_t Val)
Definition: MCInst.h:141
llvm::MCContext
Context object for machine code objects.
Definition: MCContext.h:72
llvm::Function
Definition: Function.h:61
llvm::Loop
Represents a single loop in the control flow graph.
Definition: LoopInfo.h:530
llvm::MCSymbolWasm::setOmitFromLinkingSection
void setOmitFromLinkingSection()
Definition: MCSymbolWasm.h:83
llvm::AsmToken::EndOfStatement
@ EndOfStatement
Definition: MCAsmMacro.h:42
llvm::AsmToken::getIntVal
int64_t getIntVal() const
Definition: MCAsmMacro.h:115
llvm::StringRef::npos
static constexpr size_t npos
Definition: StringRef.h:60
llvm::StringRef::find
LLVM_NODISCARD size_t find(char C, size_t From=0) const
Search for the first character C in the string.
Definition: StringRef.h:315
llvm::SmallVector< wasm::ValType, 4 >
MCParsedAsmOperand.h
llvm::wasm::WASM_SYMBOL_TYPE_TABLE
@ WASM_SYMBOL_TYPE_TABLE
Definition: Wasm.h:357
llvm::MCAsmParser::parseEscapedString
virtual bool parseEscapedString(std::string &Data)=0
Parse the current token as a string which may include escaped characters and return the string conten...
push
static void push(SmallVectorImpl< uint64_t > &R, StringRef Str)
Definition: BitstreamRemarkSerializer.cpp:23
llvm::wasm::WASM_SYMBOL_TYPE_GLOBAL
@ WASM_SYMBOL_TYPE_GLOBAL
Definition: Wasm.h:354
llvm::WebAssemblyAsmTypeCheck::setLastSig
void setLastSig(const wasm::WasmSignature &Sig)
Definition: WebAssemblyAsmTypeCheck.h:59
llvm::MCAsmLexer::getTok
const AsmToken & getTok() const
Get the current (last) lexed token.
Definition: MCAsmLexer.h:108
llvm::MCSymbol::setUndefined
void setUndefined()
Mark the symbol as undefined.
Definition: MCSymbol.h:274
llvm::Type
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
Instructions
Code Generation Notes for reduce the size of the ISel and reduce repetition in the implementation In a small number of this can cause even when no optimisation has taken place Instructions
Definition: MSA.txt:11
llvm::AsmToken::Integer
@ Integer
Definition: MCAsmMacro.h:32
error
#define error(X)
Definition: SymbolRecordMapping.cpp:14
llvm::Optional
Definition: APInt.h:33
llvm::WebAssembly::BlockType::Invalid
@ Invalid
T
#define T
Definition: Mips16ISelLowering.cpp:341
llvm::FeatureBitset
Container class for subtarget features.
Definition: SubtargetFeature.h:40
llvm::MCInst
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:184
LLVMInitializeWebAssemblyAsmParser
LLVM_EXTERNAL_VISIBILITY void LLVMInitializeWebAssemblyAsmParser()
Definition: WebAssemblyAsmParser.cpp:1135
llvm::tgtok::Else
@ Else
Definition: TGLexer.h:75
llvm::MCAsmLexer::is
bool is(AsmToken::TokenKind K) const
Check if the current token has kind K.
Definition: MCAsmLexer.h:143
MCTargetAsmParser.h
llvm::MCContext::lookupSymbol
MCSymbol * lookupSymbol(const Twine &Name) const
Get the symbol for Name, or null.
Definition: MCContext.cpp:344
llvm::AsmToken
Target independent representation for an assembler token.
Definition: MCAsmMacro.h:21
F
#define F(x, y, z)
Definition: MD5.cpp:56
llvm::WebAssembly::BlockType::Void
@ Void
llvm::MCInst::setOpcode
void setOpcode(unsigned Op)
Definition: MCInst.h:197
llvm::AsmToken::Minus
@ Minus
Definition: MCAsmMacro.h:45
llvm::MCSA_NoDeadStrip
@ MCSA_NoDeadStrip
.no_dead_strip (MachO)
Definition: MCDirectives.h:38
llvm::WebAssemblyAsmTypeCheck::localDecl
void localDecl(const SmallVector< wasm::ValType, 4 > &Locals)
Definition: WebAssemblyAsmTypeCheck.cpp:57
WebAssemblyAsmTypeCheck.h
llvm::AsmToken::LParen
@ LParen
Definition: MCAsmMacro.h:48
llvm::MCAsmParser::Lex
virtual const AsmToken & Lex()=0
Get the next AsmToken in the stream, possibly handling file inclusion first.
llvm::MCStreamer
Streaming machine code generation interface.
Definition: MCStreamer.h:197
llvm::WebAssembly::parseType
Optional< wasm::ValType > parseType(StringRef Type)
Definition: WebAssemblyTypeUtilities.cpp:23
llvm::MCAsmParser::parseExpression
virtual bool parseExpression(const MCExpr *&Res, SMLoc &EndLoc)=0
Parse an arbitrary expression.
llvm::MCContext::getOrCreateSymbol
MCSymbol * getOrCreateSymbol(const Twine &Name)
Lookup the symbol inside with the specified Name.
Definition: MCContext.cpp:191
llvm::WebAssemblyAsmTypeCheck::endOfFunction
void endOfFunction(SMLoc ErrorLoc)
Definition: WebAssemblyAsmTypeCheck.cpp:170
llvm::RegisterMCAsmParser
RegisterMCAsmParser - Helper template for registering a target specific assembly parser,...
Definition: TargetRegistry.h:1317
llvm::SMLoc
Represents a location in source code.
Definition: SMLoc.h:23
llvm::wasm::WasmLimits
Definition: Wasm.h:64
GetMnemonic
StringRef GetMnemonic(unsigned Opc)
Definition: WebAssemblyAsmParser.cpp:1145
MCSymbolWasm.h
MCContext.h
llvm::MachO::SymbolFlags::Undefined
@ Undefined
Undefined.
Y
static GCMetadataPrinterRegistry::Add< OcamlGCMetadataPrinter > Y("ocaml", "ocaml 3.10-compatible collector")
MCInstrInfo.h
MCSymbol.h
llvm::BitTracker
Definition: BitTracker.h:35
MCInst.h
llvm::wasm::WasmGlobalType
Definition: Wasm.h:92
Integer
So we should use XX3Form_Rcr to implement instrinsic Convert DP outs ins xscvdpsp No builtin are required Round &Convert QP DP(dword[1] is set to zero) No builtin are required Round to Quad Precision Integer
Definition: README_P9.txt:366
MCSubtargetInfo.h
llvm::MCSubtargetInfo::getFeatureBits
const FeatureBitset & getFeatureBits() const
Definition: MCSubtargetInfo.h:111
WebAssemblyTypeUtilities.h
Options
const char LLVMTargetMachineRef LLVMPassBuilderOptionsRef Options
Definition: PassBuilderBindings.cpp:48
llvm::raw_ostream
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:53
llvm::wasm::WASM_SYMBOL_TYPE_FUNCTION
@ WASM_SYMBOL_TYPE_FUNCTION
Definition: Wasm.h:352
llvm::tgtok::If
@ If
Definition: TGLexer.h:51
llvm::wasm::ValType
ValType
Definition: Wasm.h:392
llvm::AsmToken::getKind
TokenKind getKind() const
Definition: MCAsmMacro.h:81
llvm::AsmToken::MinusGreater
@ MinusGreater
Definition: MCAsmMacro.h:54
llvm::SectionKind::getText
static SectionKind getText()
Definition: SectionKind.h:183
llvm::Align
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition: Alignment.h:39
llvm::wasm::WASM_LIMITS_FLAG_HAS_MAX
@ WASM_LIMITS_FLAG_HAS_MAX
Definition: Wasm.h:302
llvm::StringRef::getAsInteger
std::enable_if_t< std::numeric_limits< T >::is_signed, bool > getAsInteger(unsigned Radix, T &Result) const
Parse the current string as an integer of the specified radix.
Definition: StringRef.h:510
llvm::lltok::Kind
Kind
Definition: LLToken.h:18
SourceMgr.h
X
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
WebAssemblyUtilities.h
llvm::MCInst::addOperand
void addOperand(const MCOperand Op)
Definition: MCInst.h:210
llvm::SmallString< 128 >
WebAssemblyMCTargetDesc.h
Operands
mir Rename Register Operands
Definition: MIRNamerPass.cpp:78
llvm::wasm::WasmLimits::Flags
uint8_t Flags
Definition: Wasm.h:65
WebAssemblyTargetStreamer.h
llvm::AsmToken::Equal
@ Equal
Definition: MCAsmMacro.h:49
getSubtargetFeatureName
static const char * getSubtargetFeatureName(uint64_t Val)
llvm::ParseInstructionInfo
Definition: MCTargetAsmParser.h:113
LLVM_EXTERNAL_VISIBILITY
#define LLVM_EXTERNAL_VISIBILITY
Definition: Compiler.h:132
llvm::tgtok::Int
@ Int
Definition: TGLexer.h:51
llvm::MCSymbolWasm
Definition: MCSymbolWasm.h:16
llvm::MCAsmParserExtension::Initialize
virtual void Initialize(MCAsmParser &Parser)
Initialize the extension for parsing using the given Parser.
Definition: MCAsmParserExtension.cpp:19
move
compiles ldr LCPI1_0 ldr ldr mov lsr tst moveq r1 ldr LCPI1_1 and r0 bx lr It would be better to do something like to fold the shift into the conditional move
Definition: README.txt:546
llvm::numbers::e
constexpr double e
Definition: MathExtras.h:57
llvm::MCStreamer::emitInstruction
virtual void emitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI)
Emit the given Instruction into the current section.
Definition: MCStreamer.cpp:1085
llvm::AsmToken::Colon
@ Colon
Definition: MCAsmMacro.h:43
llvm::NVPTX::PTXLdStInstCode::Float
@ Float
Definition: NVPTX.h:118
I
#define I(x, y, z)
Definition: MD5.cpp:59
WebAssemblyTargetInfo.h
llvm::wasm::WasmSignature::Returns
SmallVector< ValType, 1 > Returns
Definition: Wasm.h:403
llvm::MCBinaryExpr::create
static const MCBinaryExpr * create(Opcode Op, const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition: MCExpr.cpp:183
llvm::wasm::WASM_SYMBOL_TYPE_TAG
@ WASM_SYMBOL_TYPE_TAG
Definition: Wasm.h:356
llvm::AsmToken::Slash
@ Slash
Definition: MCAsmMacro.h:46
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::MCContext::reportError
void reportError(SMLoc L, const Twine &Msg)
Definition: MCContext.cpp:963
llvm::FeatureBitset::count
size_t count() const
Definition: SubtargetFeature.h:98
llvm::FeatureBitset::size
constexpr size_t size() const
Definition: SubtargetFeature.h:92
llvm::MCOperand::setImm
void setImm(int64_t Val)
Definition: MCInst.h:85
llvm::ErrorInfo
Base class for user error types.
Definition: Error.h:349
llvm::MCTargetOptions
Definition: MCTargetOptions.h:36
isReg
static bool isReg(const MCInst &MI, unsigned OpNo)
Definition: MipsInstPrinter.cpp:31
llvm::AsmToken::Comma
@ Comma
Definition: MCAsmMacro.h:49
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:58
llvm::MCAsmParser::getTok
const AsmToken & getTok() const
Get the current AsmToken from the stream.
Definition: MCAsmParser.cpp:38
llvm::wasm::WasmLimits::Maximum
uint64_t Maximum
Definition: Wasm.h:67
llvm_unreachable
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Definition: ErrorHandling.h:136
S
add sub stmia L5 ldr r0 bl L_printf $stub Instead of a and a wouldn t it be better to do three moves *Return an aggregate type is even return S
Definition: README.txt:210
llvm::WebAssemblyAsmTypeCheck::typeCheck
bool typeCheck(SMLoc ErrorLoc, const MCInst &Inst)
Definition: WebAssemblyAsmTypeCheck.cpp:183
llvm::AsmToken::RParen
@ RParen
Definition: MCAsmMacro.h:48
llvm::MCContext::createTempSymbol
MCSymbol * createTempSymbol()
Create a temporary symbol with a unique name.
Definition: MCContext.cpp:303
llvm::MCOperand::createSFPImm
static MCOperand createSFPImm(uint32_t Val)
Definition: MCInst.h:148
llvm::WebAssembly::GetDefaultP2AlignAny
unsigned GetDefaultP2AlignAny(unsigned Opc)
Return the default p2align value for a load or store with the given opcode.
Definition: WebAssemblyMCTargetDesc.h:137
llvm::MCContext::GenericSectionID
@ GenericSectionID
Pass this value as the UniqueID during section creation to get the generic section with the given nam...
Definition: MCContext.h:523
llvm::AsmToken::getString
StringRef getString() const
Get the string for the current token, this includes all characters (for example, the quotes on string...
Definition: MCAsmMacro.h:110
llvm::MCOperand::createDFPImm
static MCOperand createDFPImm(uint64_t Val)
Definition: MCInst.h:155
llvm::getTheWebAssemblyTarget64
Target & getTheWebAssemblyTarget64()
Definition: WebAssemblyTargetInfo.cpp:24
llvm::OperandMatchResultTy
OperandMatchResultTy
Definition: MCTargetAsmParser.h:121
llvm::Twine
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:83
llvm::MCInstrInfo
Interface to description of machine instruction set.
Definition: MCInstrInfo.h:25
llvm::GraphProgram::Name
Name
Definition: GraphWriter.h:52
llvm::MCInst::setLoc
void setLoc(SMLoc loc)
Definition: MCInst.h:203
llvm::AsmToken::Real
@ Real
Definition: MCAsmMacro.h:36
llvm::MCSymbolWasm::isFunctionTable
bool isFunctionTable() const
Definition: MCSymbolWasm.h:109
llvm::AsmToken::Identifier
@ Identifier
Definition: MCAsmMacro.h:28
llvm::StringRef::drop_front
LLVM_NODISCARD StringRef drop_front(size_t N=1) const
Return a StringRef equal to 'this' but with the first N elements dropped.
Definition: StringRef.h:653
uint16_t
llvm::AMDGPU::HSAMD::Kernel::Arg::Key::TypeName
constexpr char TypeName[]
Key for Kernel::Arg::Metadata::mTypeName.
Definition: AMDGPUMetadata.h:170
llvm::SMLoc::getPointer
const char * getPointer() const
Definition: SMLoc.h:34
llvm::AMDGPU::SendMsg::Op
Op
Definition: SIDefines.h:314
llvm::MCBinaryExpr::Sub
@ Sub
Subtraction.
Definition: MCExpr.h:504
llvm::MCAsmLexer::isNot
bool isNot(AsmToken::TokenKind K) const
Check if the current token has kind K.
Definition: MCAsmLexer.h:146
llvm::MCSymbolRefExpr::VK_WASM_TYPEINDEX
@ VK_WASM_TYPEINDEX
Definition: MCExpr.h:327
llvm::MCInst::getOpcode
unsigned getOpcode() const
Definition: MCInst.h:198
llvm::MCSymbolWasm::setFunctionTable
void setFunctionTable()
Definition: MCSymbolWasm.h:113
llvm::MCTargetAsmParser
MCTargetAsmParser - Generic interface to target specific assembly parsers.
Definition: MCTargetAsmParser.h:309
llvm::MCSymbolRefExpr::create
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx)
Definition: MCExpr.h:384
llvm::WebAssembly::parseBlockType
BlockType parseBlockType(StringRef Type)
Definition: WebAssemblyTypeUtilities.cpp:51
llvm::MCSubtargetInfo::checkFeatures
bool checkFeatures(StringRef FS) const
Check whether the subtarget features are enabled/disabled as per the provided string,...
Definition: MCSubtargetInfo.cpp:297
llvm::ARMBuildAttrs::Symbol
@ Symbol
Definition: ARMBuildAttributes.h:79
llvm::FeatureBitset::test
constexpr bool test(unsigned I) const
Definition: SubtargetFeature.h:90
llvm::AsmToken::TokenKind
TokenKind
Definition: MCAsmMacro.h:23
llvm::MCStreamer::getTargetStreamer
MCTargetStreamer * getTargetStreamer()
Definition: MCStreamer.h:285
llvm::WebAssembly::HeapType::Invalid
@ Invalid
List
const NodeList & List
Definition: RDFGraph.cpp:201
BT
BitTracker BT
Definition: BitTracker.cpp:73
N
#define N
MCStreamer.h
llvm::MCInst::getOperand
const MCOperand & getOperand(unsigned i) const
Definition: MCInst.h:206
CmpMode::Int
@ Int
llvm::isMem
static bool isMem(const MachineInstr &MI, unsigned Op)
Definition: X86InstrInfo.h:123
llvm::AsmToken::LCurly
@ LCurly
Definition: MCAsmMacro.h:48
llvm::raw_svector_ostream
A raw_ostream that writes to an SmallVector or SmallString.
Definition: raw_ostream.h:656
llvm::WebAssembly::BlockType
BlockType
Used as immediate MachineOperands for block signatures.
Definition: WebAssemblyTypeUtilities.h:26
llvm::codeview::CompileSym3Flags::Exp
@ Exp
llvm::MipsISD::Ins
@ Ins
Definition: MipsISelLowering.h:157
llvm::SmallVectorImpl< wasm::ValType >
llvm::WebAssemblyAsmTypeCheck::funcDecl
void funcDecl(const wasm::WasmSignature &Sig)
Definition: WebAssemblyAsmTypeCheck.cpp:52
llvm::SMLoc::getFromPointer
static SMLoc getFromPointer(const char *Ptr)
Definition: SMLoc.h:36
llvm::WebAssembly::getWasm64Opcode
int getWasm64Opcode(unsigned short Opcode)
llvm::AsmToken::RCurly
@ RCurly
Definition: MCAsmMacro.h:48
llvm::AMDGPU::VGPRIndexMode::Id
Id
Definition: SIDefines.h:221
llvm::wasm::WasmTableType
Definition: Wasm.h:70
Endian.h
llvm::AsmToken::getLoc
SMLoc getLoc() const
Definition: MCAsmLexer.cpp:27
llvm::AsmToken::getEndLoc
SMLoc getEndLoc() const
Definition: MCAsmLexer.cpp:31
llvm::pdb::PDB_SymType::Block
@ Block
TargetRegistry.h
MCExpr.h
llvm::MCSubtargetInfo
Generic base class for all target subtargets.
Definition: MCSubtargetInfo.h:75
llvm::wasm::WasmSignature::Params
SmallVector< ValType, 4 > Params
Definition: Wasm.h:404
llvm::MCExpr
Base class for the full range of assembler expressions which are needed for parsing.
Definition: MCExpr.h:35
llvm::codeview::ClassOptions::Nested
@ Nested
llvm::wasm::WASM_SYMBOL_TYPE_DATA
@ WASM_SYMBOL_TYPE_DATA
Definition: Wasm.h:353
llvm::wasm::WasmSignature
Definition: Wasm.h:402
llvm::Optional::getValue
constexpr const T & getValue() const LLVM_LVALUE_FUNCTION
Definition: Optional.h:282
llvm::SourceMgr::getBufferInfo
const SrcBuffer & getBufferInfo(unsigned i) const
Definition: SourceMgr.h:117
getReg
static unsigned getReg(const void *D, unsigned RC, unsigned RegNo)
Definition: MipsDisassembler.cpp:580
MCSectionWasm.h
llvm::WebAssembly::parseHeapType
HeapType parseHeapType(StringRef Type)
Definition: WebAssemblyTypeUtilities.cpp:44