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