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)> 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: 47 WasmAsmParser() : Parser(nullptr), Lexer(nullptr) { 48 BracketExpressionsSupported = true; 49 } 50 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 63 bool Error(const StringRef &msg, const AsmToken &tok) { 64 return Parser->Error(tok.getLoc(), msg + tok.getString()); 65 } 66 67 bool IsNext(AsmToken::TokenKind Kind) { 68 auto ok = Lexer->is(Kind); 69 if (ok) Lex(); 70 return ok; 71 } 72 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 80 bool parseSectionDirectiveText(StringRef, SMLoc) { 81 // FIXME: .text currently no-op. 82 return false; 83 } 84 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. 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 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 141 MCAsmParserExtension *createWasmAsmParser() { 142 return new WasmAsmParser; 143 } 144 145 } // end namespace llvm 146