summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp')
-rw-r--r--llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp117
1 files changed, 64 insertions, 53 deletions
diff --git a/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp b/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp
index 703ea2d7d02..bc2ec11303f 100644
--- a/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp
+++ b/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp
@@ -133,6 +133,9 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser {
MCAsmParser &Parser;
MCAsmLexer &Lexer;
+ // Much like WebAssemblyAsmPrinter in the backend, we have to own these.
+ std::vector<std::unique_ptr<wasm::WasmSignature>> Signatures;
+
public:
WebAssemblyAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
const MCInstrInfo &MII, const MCTargetOptions &Options)
@@ -141,6 +144,10 @@ public:
setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
}
+ void addSignature(std::unique_ptr<wasm::WasmSignature> &&Sig) {
+ Signatures.push_back(std::move(Sig));
+ }
+
#define GET_ASSEMBLER_HEADER
#include "WebAssemblyGenAsmMatcher.inc"
@@ -168,39 +175,40 @@ public:
return false;
}
+ StringRef ExpectIdent() {
+ if (!Lexer.is(AsmToken::Identifier)) {
+ Error("Expected identifier, got: ", Lexer.getTok());
+ return StringRef();
+ }
+ auto Name = Lexer.getTok().getString();
+ Parser.Lex();
+ return Name;
+ }
- std::pair<MVT::SimpleValueType, unsigned>
- ParseRegType(const StringRef &RegType) {
- // Derive type from .param .local decls, or the instruction itself.
- return StringSwitch<std::pair<MVT::SimpleValueType, unsigned>>(RegType)
- .Case("i32", {MVT::i32, wasm::WASM_TYPE_I32})
- .Case("i64", {MVT::i64, wasm::WASM_TYPE_I64})
- .Case("f32", {MVT::f32, wasm::WASM_TYPE_F32})
- .Case("f64", {MVT::f64, wasm::WASM_TYPE_F64})
- .Case("i8x16", {MVT::v16i8, wasm::WASM_TYPE_V128})
- .Case("i16x8", {MVT::v8i16, wasm::WASM_TYPE_V128})
- .Case("i32x4", {MVT::v4i32, wasm::WASM_TYPE_V128})
- .Case("i64x2", {MVT::v2i64, wasm::WASM_TYPE_V128})
- .Case("f32x4", {MVT::v4f32, wasm::WASM_TYPE_V128})
- .Case("f64x2", {MVT::v2f64, wasm::WASM_TYPE_V128})
- // arbitrarily chosen vector type to associate with "v128"
- // FIXME: should these be EVTs to avoid this arbitrary hack? Do we want
- // to accept more specific SIMD register types?
- .Case("v128", {MVT::v16i8, wasm::WASM_TYPE_V128})
- .Default({MVT::INVALID_SIMPLE_VALUE_TYPE, wasm::WASM_TYPE_NORESULT});
+ Optional<wasm::ValType> ParseType(const StringRef &Type) {
+ // FIXME: can't use StringSwitch because wasm::ValType doesn't have a
+ // "invalid" value.
+ if (Type == "i32") return wasm::ValType::I32;
+ if (Type == "i64") return wasm::ValType::I64;
+ if (Type == "f32") return wasm::ValType::F32;
+ if (Type == "f64") return wasm::ValType::F64;
+ if (Type == "v128" || Type == "i8x16" || Type == "i16x8" ||
+ Type == "i32x4" || Type == "i64x2" || Type == "f32x4" ||
+ Type == "f64x2") return wasm::ValType::V128;
+ return Optional<wasm::ValType>();
}
- bool ParseRegTypeList(std::vector<MVT> &Types) {
+ bool ParseRegTypeList(SmallVectorImpl<wasm::ValType> &Types) {
while (Lexer.is(AsmToken::Identifier)) {
- auto RegType = ParseRegType(Lexer.getTok().getString()).first;
- if (RegType == MVT::INVALID_SIMPLE_VALUE_TYPE)
+ auto Type = ParseType(Lexer.getTok().getString());
+ if (!Type)
return true;
- Types.push_back(RegType);
+ Types.push_back(Type.getValue());
Parser.Lex();
if (!IsNext(AsmToken::Comma))
break;
}
- return Expect(AsmToken::EndOfStatement, "EOL");
+ return false;
}
void ParseSingleInteger(bool IsNegative, OperandVector &Operands) {
@@ -343,44 +351,47 @@ public:
// 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() == ".globaltype") {
- if (!Lexer.is(AsmToken::Identifier))
- return Error("Expected symbol name after .globaltype directive, got: ",
- Lexer.getTok());
- auto Name = Lexer.getTok().getString();
- Parser.Lex();
- if (!IsNext(AsmToken::Comma))
- return Error("Expected `,`, got: ", Lexer.getTok());
- if (!Lexer.is(AsmToken::Identifier))
- return Error("Expected type in .globaltype directive, got: ",
- Lexer.getTok());
- auto Type = ParseRegType(Lexer.getTok().getString()).second;
- if (Type == wasm::WASM_TYPE_NORESULT)
- return Error("Unknown type in .globaltype directive: ",
- Lexer.getTok());
- Parser.Lex();
+ auto SymName = ExpectIdent();
+ if (SymName.empty()) return true;
+ if (Expect(AsmToken::Comma, ",")) return true;
+ auto TypeTok = Lexer.getTok();
+ auto TypeName = ExpectIdent();
+ if (TypeName.empty()) return true;
+ auto Type = ParseType(TypeName);
+ if (!Type)
+ return Error("Unknown type in .globaltype directive: ", TypeTok);
// Now set this symbol with the correct type.
auto WasmSym = cast<MCSymbolWasm>(
- TOut.getStreamer().getContext().getOrCreateSymbol(Name));
+ TOut.getStreamer().getContext().getOrCreateSymbol(SymName));
WasmSym->setType(wasm::WASM_SYMBOL_TYPE_GLOBAL);
- WasmSym->setGlobalType(wasm::WasmGlobalType{uint8_t(Type), true});
+ WasmSym->setGlobalType(
+ wasm::WasmGlobalType{uint8_t(Type.getValue()), true});
// And emit the directive again.
TOut.emitGlobalType(WasmSym);
return Expect(AsmToken::EndOfStatement, "EOL");
- } 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() == ".functype") {
+ auto SymName = ExpectIdent();
+ if (SymName.empty()) return true;
+ auto WasmSym = cast<MCSymbolWasm>(
+ TOut.getStreamer().getContext().getOrCreateSymbol(SymName));
+ auto Signature = make_unique<wasm::WasmSignature>();
+ if (Expect(AsmToken::LParen, "(")) return true;
+ if (ParseRegTypeList(Signature->Params)) return true;
+ if (Expect(AsmToken::RParen, ")")) return true;
+ if (Expect(AsmToken::MinusGreater, "->")) return true;
+ if (Expect(AsmToken::LParen, "(")) return true;
+ if (ParseRegTypeList(Signature->Returns)) return true;
+ if (Expect(AsmToken::RParen, ")")) return true;
+ WasmSym->setSignature(Signature.get());
+ addSignature(std::move(Signature));
+ WasmSym->setType(wasm::WASM_SYMBOL_TYPE_FUNCTION);
+ TOut.emitFunctionType(WasmSym);
+ return Expect(AsmToken::EndOfStatement, "EOL");
} else if (DirectiveID.getString() == ".local") {
- std::vector<MVT> Locals;
+ SmallVector<wasm::ValType, 4> Locals;
if (ParseRegTypeList(Locals)) return true;
TOut.emitLocal(Locals);
- return false;
+ return Expect(AsmToken::EndOfStatement, "EOL");
}
return true; // We didn't process this directive.
}
OpenPOWER on IntegriCloud