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/MC/TargetRegistry.h"
35 #include "llvm/Support/Endian.h"
36 #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.contains(".load") ||
435  InstName.contains(".store") ||
436  InstName.contains("prefetch");
437  auto IsAtomic = InstName.contains("atomic.");
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.contains("_lane");
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  std::unique_ptr<WebAssemblyOperand> FunctionTable;
575  if (Name == "block") {
576  push(Block);
577  ExpectBlockType = true;
578  } else if (Name == "loop") {
579  push(Loop);
580  ExpectBlockType = true;
581  } else if (Name == "try") {
582  push(Try);
583  ExpectBlockType = true;
584  } else if (Name == "if") {
585  push(If);
586  ExpectBlockType = true;
587  } else if (Name == "else") {
588  if (pop(Name, If))
589  return true;
590  push(Else);
591  } else if (Name == "catch") {
592  if (pop(Name, Try))
593  return true;
594  push(Try);
595  } else if (Name == "catch_all") {
596  if (pop(Name, Try))
597  return true;
598  push(CatchAll);
599  } else if (Name == "end_if") {
600  if (pop(Name, If, Else))
601  return true;
602  } else if (Name == "end_try") {
603  if (pop(Name, Try, CatchAll))
604  return true;
605  } else if (Name == "delegate") {
606  if (pop(Name, Try))
607  return true;
608  } else if (Name == "end_loop") {
609  if (pop(Name, Loop))
610  return true;
611  } else if (Name == "end_block") {
612  if (pop(Name, Block))
613  return true;
614  } else if (Name == "end_function") {
615  ensureLocals(getStreamer());
616  CurrentState = EndFunction;
617  if (pop(Name, Function) || ensureEmptyNestingStack())
618  return true;
619  } else if (Name == "call_indirect" || Name == "return_call_indirect") {
620  // These instructions have differing operand orders in the text format vs
621  // the binary formats. The MC instructions follow the binary format, so
622  // here we stash away the operand and append it later.
623  if (parseFunctionTableOperand(&FunctionTable))
624  return true;
625  ExpectFuncType = true;
626  }
627 
628  if (ExpectFuncType || (ExpectBlockType && Lexer.is(AsmToken::LParen))) {
629  // This has a special TYPEINDEX operand which in text we
630  // represent as a signature, such that we can re-build this signature,
631  // attach it to an anonymous symbol, which is what WasmObjectWriter
632  // expects to be able to recreate the actual unique-ified type indices.
633  auto Loc = Parser.getTok();
634  auto Signature = std::make_unique<wasm::WasmSignature>();
635  if (parseSignature(Signature.get()))
636  return true;
637  // Got signature as block type, don't need more
638  ExpectBlockType = false;
639  TC.setLastSig(*Signature.get());
640  if (ExpectBlockType)
641  NestingStack.back().Sig = *Signature.get();
642  auto &Ctx = getContext();
643  // The "true" here will cause this to be a nameless symbol.
644  MCSymbol *Sym = Ctx.createTempSymbol("typeindex", true);
645  auto *WasmSym = cast<MCSymbolWasm>(Sym);
646  WasmSym->setSignature(Signature.get());
647  addSignature(std::move(Signature));
648  WasmSym->setType(wasm::WASM_SYMBOL_TYPE_FUNCTION);
649  const MCExpr *Expr = MCSymbolRefExpr::create(
650  WasmSym, MCSymbolRefExpr::VK_WASM_TYPEINDEX, Ctx);
651  Operands.push_back(std::make_unique<WebAssemblyOperand>(
652  WebAssemblyOperand::Symbol, Loc.getLoc(), Loc.getEndLoc(),
653  WebAssemblyOperand::SymOp{Expr}));
654  }
655 
656  while (Lexer.isNot(AsmToken::EndOfStatement)) {
657  auto &Tok = Lexer.getTok();
658  switch (Tok.getKind()) {
659  case AsmToken::Identifier: {
660  if (!parseSpecialFloatMaybe(false, Operands))
661  break;
662  auto &Id = Lexer.getTok();
663  if (ExpectBlockType) {
664  // Assume this identifier is a block_type.
665  auto BT = WebAssembly::parseBlockType(Id.getString());
667  return error("Unknown block type: ", Id);
668  addBlockTypeOperand(Operands, NameLoc, BT);
669  Parser.Lex();
670  } else {
671  // Assume this identifier is a label.
672  const MCExpr *Val;
673  SMLoc End;
674  if (Parser.parseExpression(Val, End))
675  return error("Cannot parse symbol: ", Lexer.getTok());
676  Operands.push_back(std::make_unique<WebAssemblyOperand>(
677  WebAssemblyOperand::Symbol, Id.getLoc(), Id.getEndLoc(),
678  WebAssemblyOperand::SymOp{Val}));
679  if (checkForP2AlignIfLoadStore(Operands, Name))
680  return true;
681  }
682  break;
683  }
684  case AsmToken::Minus:
685  Parser.Lex();
686  if (Lexer.is(AsmToken::Integer)) {
687  parseSingleInteger(true, Operands);
688  if (checkForP2AlignIfLoadStore(Operands, Name))
689  return true;
690  } else if(Lexer.is(AsmToken::Real)) {
691  if (parseSingleFloat(true, Operands))
692  return true;
693  } else if (!parseSpecialFloatMaybe(true, Operands)) {
694  } else {
695  return error("Expected numeric constant instead got: ",
696  Lexer.getTok());
697  }
698  break;
699  case AsmToken::Integer:
700  parseSingleInteger(false, Operands);
701  if (checkForP2AlignIfLoadStore(Operands, Name))
702  return true;
703  break;
704  case AsmToken::Real: {
705  if (parseSingleFloat(false, Operands))
706  return true;
707  break;
708  }
709  case AsmToken::LCurly: {
710  Parser.Lex();
711  auto Op = std::make_unique<WebAssemblyOperand>(
712  WebAssemblyOperand::BrList, Tok.getLoc(), Tok.getEndLoc());
713  if (!Lexer.is(AsmToken::RCurly))
714  for (;;) {
715  Op->BrL.List.push_back(Lexer.getTok().getIntVal());
716  expect(AsmToken::Integer, "integer");
717  if (!isNext(AsmToken::Comma))
718  break;
719  }
720  expect(AsmToken::RCurly, "}");
721  Operands.push_back(std::move(Op));
722  break;
723  }
724  default:
725  return error("Unexpected token in operand: ", Tok);
726  }
727  if (Lexer.isNot(AsmToken::EndOfStatement)) {
728  if (expect(AsmToken::Comma, ","))
729  return true;
730  }
731  }
732  if (ExpectBlockType && Operands.size() == 1) {
733  // Support blocks with no operands as default to void.
734  addBlockTypeOperand(Operands, NameLoc, WebAssembly::BlockType::Void);
735  }
736  if (FunctionTable)
737  Operands.push_back(std::move(FunctionTable));
738  Parser.Lex();
739  return false;
740  }
741 
742  bool parseSignature(wasm::WasmSignature *Signature) {
743  if (expect(AsmToken::LParen, "("))
744  return true;
745  if (parseRegTypeList(Signature->Params))
746  return true;
747  if (expect(AsmToken::RParen, ")"))
748  return true;
749  if (expect(AsmToken::MinusGreater, "->"))
750  return true;
751  if (expect(AsmToken::LParen, "("))
752  return true;
753  if (parseRegTypeList(Signature->Returns))
754  return true;
755  if (expect(AsmToken::RParen, ")"))
756  return true;
757  return false;
758  }
759 
760  bool CheckDataSection() {
761  if (CurrentState != DataSection) {
762  auto WS = cast<MCSectionWasm>(getStreamer().getCurrentSection().first);
763  if (WS && WS->getKind().isText())
764  return error("data directive must occur in a data segment: ",
765  Lexer.getTok());
766  }
767  CurrentState = DataSection;
768  return false;
769  }
770 
771  // This function processes wasm-specific directives streamed to
772  // WebAssemblyTargetStreamer, all others go to the generic parser
773  // (see WasmAsmParser).
774  bool ParseDirective(AsmToken DirectiveID) override {
775  // This function has a really weird return value behavior that is different
776  // from all the other parsing functions:
777  // - return true && no tokens consumed -> don't know this directive / let
778  // the generic parser handle it.
779  // - return true && tokens consumed -> a parsing error occurred.
780  // - return false -> processed this directive successfully.
781  assert(DirectiveID.getKind() == AsmToken::Identifier);
782  auto &Out = getStreamer();
783  auto &TOut =
784  reinterpret_cast<WebAssemblyTargetStreamer &>(*Out.getTargetStreamer());
785  auto &Ctx = Out.getContext();
786 
787  // TODO: any time we return an error, at least one token must have been
788  // consumed, otherwise this will not signal an error to the caller.
789  if (DirectiveID.getString() == ".globaltype") {
790  auto SymName = expectIdent();
791  if (SymName.empty())
792  return true;
793  if (expect(AsmToken::Comma, ","))
794  return true;
795  auto TypeTok = Lexer.getTok();
796  auto TypeName = expectIdent();
797  if (TypeName.empty())
798  return true;
800  if (!Type)
801  return error("Unknown type in .globaltype directive: ", TypeTok);
802  // Optional mutable modifier. Default to mutable for historical reasons.
803  // Ideally we would have gone with immutable as the default and used `mut`
804  // as the modifier to match the `.wat` format.
805  bool Mutable = true;
806  if (isNext(AsmToken::Comma)) {
807  TypeTok = Lexer.getTok();
808  auto Id = expectIdent();
809  if (Id == "immutable")
810  Mutable = false;
811  else
812  // Should we also allow `mutable` and `mut` here for clarity?
813  return error("Unknown type in .globaltype modifier: ", TypeTok);
814  }
815  // Now set this symbol with the correct type.
816  auto WasmSym = cast<MCSymbolWasm>(Ctx.getOrCreateSymbol(SymName));
817  WasmSym->setType(wasm::WASM_SYMBOL_TYPE_GLOBAL);
818  WasmSym->setGlobalType(
819  wasm::WasmGlobalType{uint8_t(Type.getValue()), Mutable});
820  // And emit the directive again.
821  TOut.emitGlobalType(WasmSym);
822  return expect(AsmToken::EndOfStatement, "EOL");
823  }
824 
825  if (DirectiveID.getString() == ".tabletype") {
826  // .tabletype SYM, ELEMTYPE[, MINSIZE[, MAXSIZE]]
827  auto SymName = expectIdent();
828  if (SymName.empty())
829  return true;
830  if (expect(AsmToken::Comma, ","))
831  return true;
832 
833  auto ElemTypeTok = Lexer.getTok();
834  auto ElemTypeName = expectIdent();
835  if (ElemTypeName.empty())
836  return true;
837  Optional<wasm::ValType> ElemType = WebAssembly::parseType(ElemTypeName);
838  if (!ElemType)
839  return error("Unknown type in .tabletype directive: ", ElemTypeTok);
840 
841  wasm::WasmLimits Limits = DefaultLimits();
842  if (isNext(AsmToken::Comma) && parseLimits(&Limits))
843  return true;
844 
845  // Now that we have the name and table type, we can actually create the
846  // symbol
847  auto WasmSym = cast<MCSymbolWasm>(Ctx.getOrCreateSymbol(SymName));
848  WasmSym->setType(wasm::WASM_SYMBOL_TYPE_TABLE);
849  wasm::WasmTableType Type = {uint8_t(ElemType.getValue()), Limits};
850  WasmSym->setTableType(Type);
851  TOut.emitTableType(WasmSym);
852  return expect(AsmToken::EndOfStatement, "EOL");
853  }
854 
855  if (DirectiveID.getString() == ".functype") {
856  // This code has to send things to the streamer similar to
857  // WebAssemblyAsmPrinter::EmitFunctionBodyStart.
858  // TODO: would be good to factor this into a common function, but the
859  // assembler and backend really don't share any common code, and this code
860  // parses the locals separately.
861  auto SymName = expectIdent();
862  if (SymName.empty())
863  return true;
864  auto WasmSym = cast<MCSymbolWasm>(Ctx.getOrCreateSymbol(SymName));
865  if (WasmSym->isDefined()) {
866  // This .functype indicates a start of a function.
867  if (ensureEmptyNestingStack())
868  return true;
869  CurrentState = FunctionStart;
870  LastFunctionLabel = WasmSym;
871  push(Function);
872  }
873  auto Signature = std::make_unique<wasm::WasmSignature>();
874  if (parseSignature(Signature.get()))
875  return true;
876  TC.funcDecl(*Signature);
877  WasmSym->setSignature(Signature.get());
878  addSignature(std::move(Signature));
879  WasmSym->setType(wasm::WASM_SYMBOL_TYPE_FUNCTION);
880  TOut.emitFunctionType(WasmSym);
881  // TODO: backend also calls TOut.emitIndIdx, but that is not implemented.
882  return expect(AsmToken::EndOfStatement, "EOL");
883  }
884 
885  if (DirectiveID.getString() == ".export_name") {
886  auto SymName = expectIdent();
887  if (SymName.empty())
888  return true;
889  if (expect(AsmToken::Comma, ","))
890  return true;
891  auto ExportName = expectIdent();
892  auto WasmSym = cast<MCSymbolWasm>(Ctx.getOrCreateSymbol(SymName));
893  WasmSym->setExportName(storeName(ExportName));
894  TOut.emitExportName(WasmSym, ExportName);
895  }
896 
897  if (DirectiveID.getString() == ".import_module") {
898  auto SymName = expectIdent();
899  if (SymName.empty())
900  return true;
901  if (expect(AsmToken::Comma, ","))
902  return true;
903  auto ImportModule = expectIdent();
904  auto WasmSym = cast<MCSymbolWasm>(Ctx.getOrCreateSymbol(SymName));
905  WasmSym->setImportModule(storeName(ImportModule));
906  TOut.emitImportModule(WasmSym, ImportModule);
907  }
908 
909  if (DirectiveID.getString() == ".import_name") {
910  auto SymName = expectIdent();
911  if (SymName.empty())
912  return true;
913  if (expect(AsmToken::Comma, ","))
914  return true;
915  auto ImportName = expectIdent();
916  auto WasmSym = cast<MCSymbolWasm>(Ctx.getOrCreateSymbol(SymName));
917  WasmSym->setImportName(storeName(ImportName));
918  TOut.emitImportName(WasmSym, ImportName);
919  }
920 
921  if (DirectiveID.getString() == ".tagtype") {
922  auto SymName = expectIdent();
923  if (SymName.empty())
924  return true;
925  auto WasmSym = cast<MCSymbolWasm>(Ctx.getOrCreateSymbol(SymName));
926  auto Signature = std::make_unique<wasm::WasmSignature>();
927  if (parseRegTypeList(Signature->Params))
928  return true;
929  WasmSym->setSignature(Signature.get());
930  addSignature(std::move(Signature));
931  WasmSym->setType(wasm::WASM_SYMBOL_TYPE_TAG);
932  TOut.emitTagType(WasmSym);
933  // TODO: backend also calls TOut.emitIndIdx, but that is not implemented.
934  return expect(AsmToken::EndOfStatement, "EOL");
935  }
936 
937  if (DirectiveID.getString() == ".local") {
938  if (CurrentState != FunctionStart)
939  return error(".local directive should follow the start of a function: ",
940  Lexer.getTok());
942  if (parseRegTypeList(Locals))
943  return true;
944  TC.localDecl(Locals);
945  TOut.emitLocal(Locals);
946  CurrentState = FunctionLocals;
947  return expect(AsmToken::EndOfStatement, "EOL");
948  }
949 
950  if (DirectiveID.getString() == ".int8" ||
951  DirectiveID.getString() == ".int16" ||
952  DirectiveID.getString() == ".int32" ||
953  DirectiveID.getString() == ".int64") {
954  if (CheckDataSection()) return true;
955  const MCExpr *Val;
956  SMLoc End;
957  if (Parser.parseExpression(Val, End))
958  return error("Cannot parse .int expression: ", Lexer.getTok());
959  size_t NumBits = 0;
960  DirectiveID.getString().drop_front(4).getAsInteger(10, NumBits);
961  Out.emitValue(Val, NumBits / 8, End);
962  return expect(AsmToken::EndOfStatement, "EOL");
963  }
964 
965  if (DirectiveID.getString() == ".asciz") {
966  if (CheckDataSection()) return true;
967  std::string S;
968  if (Parser.parseEscapedString(S))
969  return error("Cannot parse string constant: ", Lexer.getTok());
970  Out.emitBytes(StringRef(S.c_str(), S.length() + 1));
971  return expect(AsmToken::EndOfStatement, "EOL");
972  }
973 
974  return true; // We didn't process this directive.
975  }
976 
977  // Called either when the first instruction is parsed of the function ends.
978  void ensureLocals(MCStreamer &Out) {
979  if (CurrentState == FunctionStart) {
980  // We haven't seen a .local directive yet. The streamer requires locals to
981  // be encoded as a prelude to the instructions, so emit an empty list of
982  // locals here.
983  auto &TOut = reinterpret_cast<WebAssemblyTargetStreamer &>(
984  *Out.getTargetStreamer());
986  CurrentState = FunctionLocals;
987  }
988  }
989 
990  bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned & /*Opcode*/,
993  bool MatchingInlineAsm) override {
994  MCInst Inst;
995  Inst.setLoc(IDLoc);
996  FeatureBitset MissingFeatures;
997  unsigned MatchResult = MatchInstructionImpl(
998  Operands, Inst, ErrorInfo, MissingFeatures, MatchingInlineAsm);
999  switch (MatchResult) {
1000  case Match_Success: {
1001  ensureLocals(Out);
1002  // Fix unknown p2align operands.
1004  if (Align != -1U) {
1005  auto &Op0 = Inst.getOperand(0);
1006  if (Op0.getImm() == -1)
1007  Op0.setImm(Align);
1008  }
1009  if (is64) {
1010  // Upgrade 32-bit loads/stores to 64-bit. These mostly differ by having
1011  // an offset64 arg instead of offset32, but to the assembler matcher
1012  // they're both immediates so don't get selected for.
1013  auto Opc64 = WebAssembly::getWasm64Opcode(
1014  static_cast<uint16_t>(Inst.getOpcode()));
1015  if (Opc64 >= 0) {
1016  Inst.setOpcode(Opc64);
1017  }
1018  }
1019  if (!SkipTypeCheck && TC.typeCheck(IDLoc, Inst))
1020  return true;
1021  Out.emitInstruction(Inst, getSTI());
1022  if (CurrentState == EndFunction) {
1023  onEndOfFunction(IDLoc);
1024  } else {
1025  CurrentState = Instructions;
1026  }
1027  return false;
1028  }
1029  case Match_MissingFeature: {
1030  assert(MissingFeatures.count() > 0 && "Expected missing features");
1031  SmallString<128> Message;
1032  raw_svector_ostream OS(Message);
1033  OS << "instruction requires:";
1034  for (unsigned i = 0, e = MissingFeatures.size(); i != e; ++i)
1035  if (MissingFeatures.test(i))
1036  OS << ' ' << getSubtargetFeatureName(i);
1037  return Parser.Error(IDLoc, Message);
1038  }
1039  case Match_MnemonicFail:
1040  return Parser.Error(IDLoc, "invalid instruction");
1041  case Match_NearMisses:
1042  return Parser.Error(IDLoc, "ambiguous instruction");
1043  case Match_InvalidTiedOperand:
1044  case Match_InvalidOperand: {
1045  SMLoc ErrorLoc = IDLoc;
1046  if (ErrorInfo != ~0ULL) {
1047  if (ErrorInfo >= Operands.size())
1048  return Parser.Error(IDLoc, "too few operands for instruction");
1049  ErrorLoc = Operands[ErrorInfo]->getStartLoc();
1050  if (ErrorLoc == SMLoc())
1051  ErrorLoc = IDLoc;
1052  }
1053  return Parser.Error(ErrorLoc, "invalid operand for instruction");
1054  }
1055  }
1056  llvm_unreachable("Implement any new match types added!");
1057  }
1058 
1059  void doBeforeLabelEmit(MCSymbol *Symbol) override {
1060  // Code below only applies to labels in text sections.
1061  auto CWS = cast<MCSectionWasm>(getStreamer().getCurrentSection().first);
1062  if (!CWS || !CWS->getKind().isText())
1063  return;
1064 
1065  auto WasmSym = cast<MCSymbolWasm>(Symbol);
1066  // Unlike other targets, we don't allow data in text sections (labels
1067  // declared with .type @object).
1068  if (WasmSym->getType() == wasm::WASM_SYMBOL_TYPE_DATA) {
1069  Parser.Error(Parser.getTok().getLoc(),
1070  "Wasm doesn\'t support data symbols in text sections");
1071  return;
1072  }
1073 
1074  // Start a new section for the next function automatically, since our
1075  // object writer expects each function to have its own section. This way
1076  // The user can't forget this "convention".
1077  auto SymName = Symbol->getName();
1078  if (SymName.startswith(".L"))
1079  return; // Local Symbol.
1080 
1081  // TODO: If the user explicitly creates a new function section, we ignore
1082  // its name when we create this one. It would be nice to honor their
1083  // choice, while still ensuring that we create one if they forget.
1084  // (that requires coordination with WasmAsmParser::parseSectionDirective)
1085  auto SecName = ".text." + SymName;
1086 
1087  auto *Group = CWS->getGroup();
1088  // If the current section is a COMDAT, also set the flag on the symbol.
1089  // TODO: Currently the only place that the symbols' comdat flag matters is
1090  // for importing comdat functions. But there's no way to specify that in
1091  // assembly currently.
1092  if (Group)
1093  WasmSym->setComdat(true);
1094  auto *WS =
1095  getContext().getWasmSection(SecName, SectionKind::getText(), 0, Group,
1096  MCContext::GenericSectionID, nullptr);
1097  getStreamer().SwitchSection(WS);
1098  // Also generate DWARF for this section if requested.
1099  if (getContext().getGenDwarfForAssembly())
1100  getContext().addGenDwarfSection(WS);
1101  }
1102 
1103  void onEndOfFunction(SMLoc ErrorLoc) {
1104  TC.endOfFunction(ErrorLoc);
1105  // Reset the type checker state.
1106  TC.Clear();
1107 
1108  // Automatically output a .size directive, so it becomes optional for the
1109  // user.
1110  if (!LastFunctionLabel) return;
1111  auto TempSym = getContext().createLinkerPrivateTempSymbol();
1112  getStreamer().emitLabel(TempSym);
1113  auto Start = MCSymbolRefExpr::create(LastFunctionLabel, getContext());
1114  auto End = MCSymbolRefExpr::create(TempSym, getContext());
1115  auto Expr =
1116  MCBinaryExpr::create(MCBinaryExpr::Sub, End, Start, getContext());
1117  getStreamer().emitELFSize(LastFunctionLabel, Expr);
1118  }
1119 
1120  void onEndOfFile() override { ensureEmptyNestingStack(); }
1121 };
1122 } // end anonymous namespace
1123 
1124 // Force static initialization.
1128 }
1129 
1130 #define GET_REGISTER_MATCHER
1131 #define GET_SUBTARGET_FEATURE_NAME
1132 #define GET_MATCHER_IMPLEMENTATION
1133 #include "WebAssemblyGenAsmMatcher.inc"
1134 
1135 StringRef GetMnemonic(unsigned Opc) {
1136  // FIXME: linear search!
1137  for (auto &ME : MatchTable0) {
1138  if (ME.Opcode == Opc) {
1139  return ME.getMnemonic();
1140  }
1141  }
1142  assert(false && "mnemonic not found");
1143  return StringRef();
1144 }
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
This is an optimization pass for GlobalISel generic memory operations.
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::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:148
llvm::MCParsedAsmOperand
MCParsedAsmOperand - This abstract class represents a source-level assembly instruction operand.
Definition: MCParsedAsmOperand.h:25
llvm::getTheWebAssemblyTarget32
Target & getTheWebAssemblyTarget32()
Definition: WebAssemblyTargetInfo.cpp:20
llvm::wasm::WasmLimits::Minimum
uint64_t Minimum
Definition: Wasm.h:79
llvm::WebAssemblyAsmTypeCheck
Definition: WebAssemblyAsmTypeCheck.h:26
T
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:62
llvm::Loop
Represents a single loop in the control flow graph.
Definition: LoopInfo.h:530
llvm::MCSymbolWasm::setOmitFromLinkingSection
void setOmitFromLinkingSection()
Definition: MCSymbolWasm.h:87
llvm::AsmToken::EndOfStatement
@ EndOfStatement
Definition: MCAsmMacro.h:42
llvm::AsmToken::getIntVal
int64_t getIntVal() const
Definition: MCAsmMacro.h:115
llvm::SmallVector< wasm::ValType, 4 >
MCParsedAsmOperand.h
llvm::wasm::WASM_SYMBOL_TYPE_TABLE
@ WASM_SYMBOL_TYPE_TABLE
Definition: Wasm.h:375
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:372
llvm::WebAssemblyAsmTypeCheck::setLastSig
void setLastSig(const wasm::WasmSignature &Sig)
Definition: WebAssemblyAsmTypeCheck.h:53
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
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:1125
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:55
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:198
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::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:77
GetMnemonic
StringRef GetMnemonic(unsigned Opc)
Definition: WebAssemblyAsmParser.cpp:1135
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:105
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
llvm::StringRef::contains
LLVM_NODISCARD bool contains(StringRef Other) const
Return true if the given string is a substring of *this, and false otherwise.
Definition: StringRef.h:461
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:370
llvm::tgtok::If
@ If
Definition: TGLexer.h:51
llvm::wasm::ValType
ValType
Definition: Wasm.h:411
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::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:509
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:78
WebAssemblyTargetStreamer.h
llvm::AsmToken::Equal
@ Equal
Definition: MCAsmMacro.h:49
getSubtargetFeatureName
static const char * getSubtargetFeatureName(uint64_t Val)
llvm::WebAssemblyAsmTypeCheck::Clear
void Clear()
Definition: WebAssemblyAsmTypeCheck.h:57
llvm::ParseInstructionInfo
Definition: MCTargetAsmParser.h:113
uint64_t
LLVM_EXTERNAL_VISIBILITY
#define LLVM_EXTERNAL_VISIBILITY
Definition: Compiler.h:136
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:1090
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:58
WebAssemblyTargetInfo.h
llvm::wasm::WasmSignature::Returns
SmallVector< ValType, 1 > Returns
Definition: Wasm.h:422
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:374
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
llvm::WebAssemblyAsmTypeCheck::endOfFunction
bool endOfFunction(SMLoc ErrorLoc)
Definition: WebAssemblyAsmTypeCheck.cpp:185
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:57
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:80
llvm_unreachable
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Definition: ErrorHandling.h:134
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:199
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::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:113
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:652
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:325
llvm::MCBinaryExpr::Sub
@ Sub
Subtraction.
Definition: MCExpr.h:506
llvm::MCAsmLexer::isNot
bool isNot(AsmToken::TokenKind K) const
Check if the current token has kind K.
Definition: MCAsmLexer.h:146
llvm::wasm::WASM_LIMITS_FLAG_HAS_MAX
@ WASM_LIMITS_FLAG_HAS_MAX
Definition: Wasm.h:312
llvm::MCSymbolRefExpr::VK_WASM_TYPEINDEX
@ VK_WASM_TYPEINDEX
Definition: MCExpr.h:328
llvm::MCInst::getOpcode
unsigned getOpcode() const
Definition: MCInst.h:198
llvm::MCSymbolWasm::setFunctionTable
void setFunctionTable()
Definition: MCSymbolWasm.h:117
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:386
llvm::WebAssembly::parseBlockType
BlockType parseBlockType(StringRef Type)
Definition: WebAssemblyTypeUtilities.cpp:44
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::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:83
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:286
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:661
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::wasm::WASM_LIMITS_FLAG_NONE
@ WASM_LIMITS_FLAG_NONE
Definition: Wasm.h:311
llvm::WebAssembly::getWasm64Opcode
int getWasm64Opcode(unsigned short Opcode)
llvm::AsmToken::RCurly
@ RCurly
Definition: MCAsmMacro.h:48
llvm::AMDGPU::VGPRIndexMode::Id
Id
Definition: SIDefines.h:232
llvm::wasm::WasmTableType
Definition: Wasm.h:83
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:423
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:371
llvm::wasm::WasmSignature
Definition: Wasm.h:421
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:572
MCSectionWasm.h