WebAssemblyAsmParser.cpp 41 KB

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