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