summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/MC/MCParser/AsmParser.cpp8
-rw-r--r--llvm/lib/MC/MCParser/CMakeLists.txt1
-rw-r--r--llvm/lib/MC/MCParser/WasmAsmParser.cpp145
-rw-r--r--llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp105
4 files changed, 180 insertions, 79 deletions
diff --git a/llvm/lib/MC/MCParser/AsmParser.cpp b/llvm/lib/MC/MCParser/AsmParser.cpp
index 3f7b507791e..7299ed29e4b 100644
--- a/llvm/lib/MC/MCParser/AsmParser.cpp
+++ b/llvm/lib/MC/MCParser/AsmParser.cpp
@@ -675,6 +675,7 @@ namespace llvm {
extern MCAsmParserExtension *createDarwinAsmParser();
extern MCAsmParserExtension *createELFAsmParser();
extern MCAsmParserExtension *createCOFFAsmParser();
+extern MCAsmParserExtension *createWasmAsmParser();
} // end namespace llvm
@@ -705,10 +706,7 @@ AsmParser::AsmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out,
PlatformParser.reset(createELFAsmParser());
break;
case MCObjectFileInfo::IsWasm:
- // TODO: WASM will need its own MCAsmParserExtension implementation, but
- // for now we can re-use the ELF one, since the directives can be the
- // same for now.
- PlatformParser.reset(createELFAsmParser());
+ PlatformParser.reset(createWasmAsmParser());
break;
}
@@ -3921,7 +3919,7 @@ bool AsmParser::parseDirectiveCFIStartProc() {
parseToken(AsmToken::EndOfStatement))
return addErrorSuffix(" in '.cfi_startproc' directive");
}
-
+
// TODO(kristina): Deal with a corner case of incorrect diagnostic context
// being produced if this directive is emitted as part of preprocessor macro
// expansion which can *ONLY* happen if Clang's cc1as is the API consumer.
diff --git a/llvm/lib/MC/MCParser/CMakeLists.txt b/llvm/lib/MC/MCParser/CMakeLists.txt
index 99fdd016799..0c54e8e9019 100644
--- a/llvm/lib/MC/MCParser/CMakeLists.txt
+++ b/llvm/lib/MC/MCParser/CMakeLists.txt
@@ -8,6 +8,7 @@ add_llvm_library(LLVMMCParser
MCAsmParser.cpp
MCAsmParserExtension.cpp
MCTargetAsmParser.cpp
+ WasmAsmParser.cpp
ADDITIONAL_HEADER_DIRS
${LLVM_MAIN_INCLUDE_DIR}/llvm/MC/MCParser
diff --git a/llvm/lib/MC/MCParser/WasmAsmParser.cpp b/llvm/lib/MC/MCParser/WasmAsmParser.cpp
new file mode 100644
index 00000000000..93bb0cb3c72
--- /dev/null
+++ b/llvm/lib/MC/MCParser/WasmAsmParser.cpp
@@ -0,0 +1,145 @@
+//===- WasmAsmParser.cpp - Wasm Assembly Parser -----------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+// --
+//
+// Note, this is for wasm, the binary format (analogous to ELF), not wasm,
+// the instruction set (analogous to x86), for which parsing code lives in
+// WebAssemblyAsmParser.
+//
+// This file contains processing for generic directives implemented using
+// MCTargetStreamer, the ones that depend on WebAssemblyTargetStreamer are in
+// WebAssemblyAsmParser.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/BinaryFormat/Wasm.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCParser/MCAsmLexer.h"
+#include "llvm/MC/MCParser/MCAsmParser.h"
+#include "llvm/MC/MCParser/MCAsmParserExtension.h"
+#include "llvm/MC/MCStreamer.h"
+#include "llvm/MC/MCSymbol.h"
+#include "llvm/MC/MCSymbolWasm.h"
+#include "llvm/Support/MachineValueType.h"
+
+using namespace llvm;
+
+namespace {
+
+class WasmAsmParser : public MCAsmParserExtension {
+ MCAsmParser *Parser;
+ MCAsmLexer *Lexer;
+
+ template<bool (WasmAsmParser::*HandlerMethod)(StringRef, SMLoc)>
+ void addDirectiveHandler(StringRef Directive) {
+ MCAsmParser::ExtensionDirectiveHandler Handler = std::make_pair(
+ this, HandleDirective<WasmAsmParser, HandlerMethod>);
+
+ getParser().addDirectiveHandler(Directive, Handler);
+ }
+
+public:
+ WasmAsmParser() : Parser(nullptr), Lexer(nullptr) {
+ BracketExpressionsSupported = true;
+ }
+
+ void Initialize(MCAsmParser &P) override {
+ Parser = &P;
+ Lexer = &Parser->getLexer();
+ // Call the base implementation.
+ this->MCAsmParserExtension::Initialize(*Parser);
+
+ addDirectiveHandler<&WasmAsmParser::parseSectionDirectiveText>(".text");
+ addDirectiveHandler<&WasmAsmParser::parseSectionDirective>(".section");
+ addDirectiveHandler<&WasmAsmParser::parseDirectiveSize>(".size");
+ addDirectiveHandler<&WasmAsmParser::parseDirectiveType>(".type");
+ }
+
+ bool Error(const StringRef &msg, const AsmToken &tok) {
+ return Parser->Error(tok.getLoc(), msg + tok.getString());
+ }
+
+ bool IsNext(AsmToken::TokenKind Kind) {
+ auto ok = Lexer->is(Kind);
+ if (ok) Lex();
+ return ok;
+ }
+
+ bool Expect(AsmToken::TokenKind Kind, const char *KindName) {
+ if (!IsNext(Kind))
+ return Error(std::string("Expected ") + KindName + ", instead got: ",
+ Lexer->getTok());
+ return false;
+ }
+
+ bool parseSectionDirectiveText(StringRef, SMLoc) {
+ // FIXME: .text currently no-op.
+ return false;
+ }
+
+ bool parseSectionDirective(StringRef, SMLoc) {
+ // FIXME: .section currently no-op.
+ while (Lexer->isNot(AsmToken::EndOfStatement)) Parser->Lex();
+ return false;
+ }
+
+ // TODO: This function is almost the same as ELFAsmParser::ParseDirectiveSize
+ // so maybe could be shared somehow.
+ bool parseDirectiveSize(StringRef, SMLoc) {
+ StringRef Name;
+ if (Parser->parseIdentifier(Name))
+ return TokError("expected identifier in directive");
+ auto Sym = getContext().getOrCreateSymbol(Name);
+ if (Lexer->isNot(AsmToken::Comma))
+ return TokError("unexpected token in directive");
+ Lex();
+ const MCExpr *Expr;
+ if (Parser->parseExpression(Expr))
+ return true;
+ if (Lexer->isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in directive");
+ Lex();
+ // MCWasmStreamer implements this.
+ getStreamer().emitELFSize(Sym, Expr);
+ return false;
+ }
+
+ bool parseDirectiveType(StringRef, SMLoc) {
+ // This could be the start of a function, check if followed by
+ // "label,@function"
+ if (!Lexer->is(AsmToken::Identifier))
+ return Error("Expected label after .type directive, got: ",
+ Lexer->getTok());
+ auto WasmSym = cast<MCSymbolWasm>(
+ getStreamer().getContext().getOrCreateSymbol(
+ Lexer->getTok().getString()));
+ Lex();
+ if (!(IsNext(AsmToken::Comma) && IsNext(AsmToken::At) &&
+ Lexer->is(AsmToken::Identifier)))
+ return Error("Expected label,@type declaration, got: ", Lexer->getTok());
+ auto TypeName = Lexer->getTok().getString();
+ if (TypeName == "function")
+ WasmSym->setType(wasm::WASM_SYMBOL_TYPE_FUNCTION);
+ else if (TypeName == "global")
+ WasmSym->setType(wasm::WASM_SYMBOL_TYPE_GLOBAL);
+ else
+ return Error("Unknown WASM symbol type: ", Lexer->getTok());
+ Lex();
+ return Expect(AsmToken::EndOfStatement, "EOL");
+ }
+};
+
+} // end anonymous namespace
+
+namespace llvm {
+
+MCAsmParserExtension *createWasmAsmParser() {
+ return new WasmAsmParser;
+}
+
+} // end namespace llvm
diff --git a/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp b/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp
index efa6793cff2..703ea2d7d02 100644
--- a/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp
+++ b/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp
@@ -132,13 +132,12 @@ struct WebAssemblyOperand : public MCParsedAsmOperand {
class WebAssemblyAsmParser final : public MCTargetAsmParser {
MCAsmParser &Parser;
MCAsmLexer &Lexer;
- MCSymbolWasm *LastSymbol;
public:
WebAssemblyAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
const MCInstrInfo &MII, const MCTargetOptions &Options)
: MCTargetAsmParser(Options, STI, MII), Parser(Parser),
- Lexer(Parser.getLexer()), LastSymbol(nullptr) {
+ Lexer(Parser.getLexer()) {
setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
}
@@ -191,6 +190,19 @@ public:
.Default({MVT::INVALID_SIMPLE_VALUE_TYPE, wasm::WASM_TYPE_NORESULT});
}
+ bool ParseRegTypeList(std::vector<MVT> &Types) {
+ while (Lexer.is(AsmToken::Identifier)) {
+ auto RegType = ParseRegType(Lexer.getTok().getString()).first;
+ if (RegType == MVT::INVALID_SIMPLE_VALUE_TYPE)
+ return true;
+ Types.push_back(RegType);
+ Parser.Lex();
+ if (!IsNext(AsmToken::Comma))
+ break;
+ }
+ return Expect(AsmToken::EndOfStatement, "EOL");
+ }
+
void ParseSingleInteger(bool IsNegative, OperandVector &Operands) {
auto &Int = Lexer.getTok();
int64_t Val = Int.getIntVal();
@@ -314,10 +326,9 @@ public:
return false;
}
- void onLabelParsed(MCSymbol *Symbol) override {
- LastSymbol = cast<MCSymbolWasm>(Symbol);
- }
-
+ // This function processes wasm-specific directives streamed to
+ // WebAssemblyTargetStreamer, all others go to the generic parser
+ // (see WasmAsmParser).
bool ParseDirective(AsmToken DirectiveID) override {
// This function has a really weird return value behavior that is different
// from all the other parsing functions:
@@ -331,44 +342,7 @@ public:
reinterpret_cast<WebAssemblyTargetStreamer &>(*Out.getTargetStreamer());
// TODO: any time we return an error, at least one token must have been
// consumed, otherwise this will not signal an error to the caller.
- if (DirectiveID.getString() == ".type") {
- // This could be the start of a function, check if followed by
- // "label,@function"
- if (!Lexer.is(AsmToken::Identifier))
- return Error("Expected label after .type directive, got: ",
- Lexer.getTok());
- auto WasmSym = cast<MCSymbolWasm>(
- TOut.getStreamer().getContext().getOrCreateSymbol(
- Lexer.getTok().getString()));
- Parser.Lex();
- if (!(IsNext(AsmToken::Comma) && IsNext(AsmToken::At) &&
- Lexer.is(AsmToken::Identifier)))
- return Error("Expected label,@type declaration, got: ", Lexer.getTok());
- auto TypeName = Lexer.getTok().getString();
- if (TypeName == "function")
- WasmSym->setType(wasm::WASM_SYMBOL_TYPE_FUNCTION);
- else if (TypeName == "global")
- WasmSym->setType(wasm::WASM_SYMBOL_TYPE_GLOBAL);
- else
- return Error("Unknown WASM symbol type: ", Lexer.getTok());
- Parser.Lex();
- return Expect(AsmToken::EndOfStatement, "EOL");
- } else if (DirectiveID.getString() == ".size") {
- if (!Lexer.is(AsmToken::Identifier))
- return Error("Expected label after .size directive, got: ",
- Lexer.getTok());
- auto WasmSym = cast<MCSymbolWasm>(
- TOut.getStreamer().getContext().getOrCreateSymbol(
- Lexer.getTok().getString()));
- Parser.Lex();
- if (!IsNext(AsmToken::Comma))
- return Error("Expected `,`, got: ", Lexer.getTok());
- const MCExpr *Exp;
- if (Parser.parseExpression(Exp))
- return Error("Cannot parse .size expression: ", Lexer.getTok());
- WasmSym->setSize(Exp);
- return Expect(AsmToken::EndOfStatement, "EOL");
- } else if (DirectiveID.getString() == ".globaltype") {
+ if (DirectiveID.getString() == ".globaltype") {
if (!Lexer.is(AsmToken::Identifier))
return Error("Expected symbol name after .globaltype directive, got: ",
Lexer.getTok());
@@ -392,40 +366,23 @@ public:
// And emit the directive again.
TOut.emitGlobalType(WasmSym);
return Expect(AsmToken::EndOfStatement, "EOL");
- } else if (DirectiveID.getString() == ".param" ||
- DirectiveID.getString() == ".local") {
- // Track the number of locals, needed for correct virtual register
- // assignment elsewhere.
- // Also output a directive to the streamer.
+ } else if (DirectiveID.getString() == ".param") {
std::vector<MVT> Params;
+ if (ParseRegTypeList(Params)) return true;
+ TOut.emitParam(nullptr /* unused */, Params);
+ return false;
+ } else if (DirectiveID.getString() == ".result") {
+ std::vector<MVT> Results;
+ if (ParseRegTypeList(Results)) return true;
+ TOut.emitResult(nullptr /* unused */, Results);
+ return false;
+ } else if (DirectiveID.getString() == ".local") {
std::vector<MVT> Locals;
- while (Lexer.is(AsmToken::Identifier)) {
- auto RegType = ParseRegType(Lexer.getTok().getString()).first;
- if (RegType == MVT::INVALID_SIMPLE_VALUE_TYPE)
- return true;
- if (DirectiveID.getString() == ".param") {
- Params.push_back(RegType);
- } else {
- Locals.push_back(RegType);
- }
- Parser.Lex();
- if (!IsNext(AsmToken::Comma))
- break;
- }
- assert(LastSymbol);
- // TODO: LastSymbol isn't even used by emitParam, so could be removed.
- TOut.emitParam(LastSymbol, Params);
+ if (ParseRegTypeList(Locals)) return true;
TOut.emitLocal(Locals);
- return Expect(AsmToken::EndOfStatement, "EOL");
- } else {
- // TODO: remove.
- while (Lexer.isNot(AsmToken::EndOfStatement))
- Parser.Lex();
- return Expect(AsmToken::EndOfStatement, "EOL");
+ return false;
}
- // TODO: current ELF directive parsing is broken, fix this is a followup.
- //return true; // We didn't process this directive.
- return false;
+ return true; // We didn't process this directive.
}
bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned & /*Opcode*/,
OpenPOWER on IntegriCloud