1 //===- WasmAsmParser.cpp - Wasm Assembly Parser -----------------------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 // --
9 //
10 // Note, this is for wasm, the binary format (analogous to ELF), not wasm,
11 // the instruction set (analogous to x86), for which parsing code lives in
12 // WebAssemblyAsmParser.
13 //
14 // This file contains processing for generic directives implemented using
15 // MCTargetStreamer, the ones that depend on WebAssemblyTargetStreamer are in
16 // WebAssemblyAsmParser.
17 //
18 //===----------------------------------------------------------------------===//
19
20 #include "llvm/BinaryFormat/Wasm.h"
21 #include "llvm/MC/MCContext.h"
22 #include "llvm/MC/MCParser/MCAsmLexer.h"
23 #include "llvm/MC/MCParser/MCAsmParser.h"
24 #include "llvm/MC/MCParser/MCAsmParserExtension.h"
25 #include "llvm/MC/MCStreamer.h"
26 #include "llvm/MC/MCSymbol.h"
27 #include "llvm/MC/MCSymbolWasm.h"
28 #include "llvm/Support/MachineValueType.h"
29
30 using namespace llvm;
31
32 namespace {
33
34 class WasmAsmParser : public MCAsmParserExtension {
35 MCAsmParser *Parser;
36 MCAsmLexer *Lexer;
37
38 template<bool (WasmAsmParser::*HandlerMethod)(StringRef, SMLoc)>
addDirectiveHandler(StringRef Directive)39 void addDirectiveHandler(StringRef Directive) {
40 MCAsmParser::ExtensionDirectiveHandler Handler = std::make_pair(
41 this, HandleDirective<WasmAsmParser, HandlerMethod>);
42
43 getParser().addDirectiveHandler(Directive, Handler);
44 }
45
46 public:
WasmAsmParser()47 WasmAsmParser() : Parser(nullptr), Lexer(nullptr) {
48 BracketExpressionsSupported = true;
49 }
50
Initialize(MCAsmParser & P)51 void Initialize(MCAsmParser &P) override {
52 Parser = &P;
53 Lexer = &Parser->getLexer();
54 // Call the base implementation.
55 this->MCAsmParserExtension::Initialize(*Parser);
56
57 addDirectiveHandler<&WasmAsmParser::parseSectionDirectiveText>(".text");
58 addDirectiveHandler<&WasmAsmParser::parseSectionDirective>(".section");
59 addDirectiveHandler<&WasmAsmParser::parseDirectiveSize>(".size");
60 addDirectiveHandler<&WasmAsmParser::parseDirectiveType>(".type");
61 }
62
Error(const StringRef & msg,const AsmToken & tok)63 bool Error(const StringRef &msg, const AsmToken &tok) {
64 return Parser->Error(tok.getLoc(), msg + tok.getString());
65 }
66
IsNext(AsmToken::TokenKind Kind)67 bool IsNext(AsmToken::TokenKind Kind) {
68 auto ok = Lexer->is(Kind);
69 if (ok) Lex();
70 return ok;
71 }
72
Expect(AsmToken::TokenKind Kind,const char * KindName)73 bool Expect(AsmToken::TokenKind Kind, const char *KindName) {
74 if (!IsNext(Kind))
75 return Error(std::string("Expected ") + KindName + ", instead got: ",
76 Lexer->getTok());
77 return false;
78 }
79
parseSectionDirectiveText(StringRef,SMLoc)80 bool parseSectionDirectiveText(StringRef, SMLoc) {
81 // FIXME: .text currently no-op.
82 return false;
83 }
84
parseSectionDirective(StringRef,SMLoc)85 bool parseSectionDirective(StringRef, SMLoc) {
86 // FIXME: .section currently no-op.
87 while (Lexer->isNot(AsmToken::EndOfStatement)) Parser->Lex();
88 return false;
89 }
90
91 // TODO: This function is almost the same as ELFAsmParser::ParseDirectiveSize
92 // so maybe could be shared somehow.
parseDirectiveSize(StringRef,SMLoc)93 bool parseDirectiveSize(StringRef, SMLoc) {
94 StringRef Name;
95 if (Parser->parseIdentifier(Name))
96 return TokError("expected identifier in directive");
97 auto Sym = getContext().getOrCreateSymbol(Name);
98 if (Lexer->isNot(AsmToken::Comma))
99 return TokError("unexpected token in directive");
100 Lex();
101 const MCExpr *Expr;
102 if (Parser->parseExpression(Expr))
103 return true;
104 if (Lexer->isNot(AsmToken::EndOfStatement))
105 return TokError("unexpected token in directive");
106 Lex();
107 // MCWasmStreamer implements this.
108 getStreamer().emitELFSize(Sym, Expr);
109 return false;
110 }
111
parseDirectiveType(StringRef,SMLoc)112 bool parseDirectiveType(StringRef, SMLoc) {
113 // This could be the start of a function, check if followed by
114 // "label,@function"
115 if (!Lexer->is(AsmToken::Identifier))
116 return Error("Expected label after .type directive, got: ",
117 Lexer->getTok());
118 auto WasmSym = cast<MCSymbolWasm>(
119 getStreamer().getContext().getOrCreateSymbol(
120 Lexer->getTok().getString()));
121 Lex();
122 if (!(IsNext(AsmToken::Comma) && IsNext(AsmToken::At) &&
123 Lexer->is(AsmToken::Identifier)))
124 return Error("Expected label,@type declaration, got: ", Lexer->getTok());
125 auto TypeName = Lexer->getTok().getString();
126 if (TypeName == "function")
127 WasmSym->setType(wasm::WASM_SYMBOL_TYPE_FUNCTION);
128 else if (TypeName == "global")
129 WasmSym->setType(wasm::WASM_SYMBOL_TYPE_GLOBAL);
130 else
131 return Error("Unknown WASM symbol type: ", Lexer->getTok());
132 Lex();
133 return Expect(AsmToken::EndOfStatement, "EOL");
134 }
135 };
136
137 } // end anonymous namespace
138
139 namespace llvm {
140
createWasmAsmParser()141 MCAsmParserExtension *createWasmAsmParser() {
142 return new WasmAsmParser;
143 }
144
145 } // end namespace llvm
146