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