diff options
| author | Wouter van Oortmerssen <aardappel@gmail.com> | 2018-11-19 17:10:36 +0000 |
|---|---|---|
| committer | Wouter van Oortmerssen <aardappel@gmail.com> | 2018-11-19 17:10:36 +0000 |
| commit | 49482f824a0d92f8f97121aaa6e82f409ff23d58 (patch) | |
| tree | b6619cb3dddaca091bf225cbeadfc1fa224c0904 /llvm/lib/Target/WebAssembly | |
| parent | b25adf5edba0bfb487828600f4294702e695fdba (diff) | |
| download | bcm5719-llvm-49482f824a0d92f8f97121aaa6e82f409ff23d58.tar.gz bcm5719-llvm-49482f824a0d92f8f97121aaa6e82f409ff23d58.zip | |
[WebAssembly] replaced .param/.result by .functype
Summary:
This makes it easier/cleaner to generate a single signature from
this directive. Also:
- Adds the symbol name, such that we don't depend on the location
of this directive anymore.
- Actually constructs the signature in the assembler, and make the
assembler own it.
- Refactor the use of MVT vs ValType in the streamer and assembler
to require less conversions overall.
- Changed 700 or so tests to use it.
Reviewers: sbc100, dschuff
Subscribers: jgravelle-google, eraman, aheejin, sunfish, jfb, llvm-commits
Differential Revision: https://reviews.llvm.org/D54652
llvm-svn: 347228
Diffstat (limited to 'llvm/lib/Target/WebAssembly')
6 files changed, 114 insertions, 139 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. } diff --git a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp index ada687e20e1..5f06da8d25f 100644 --- a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp +++ b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp @@ -39,43 +39,19 @@ WebAssemblyTargetAsmStreamer::WebAssemblyTargetAsmStreamer( WebAssemblyTargetWasmStreamer::WebAssemblyTargetWasmStreamer(MCStreamer &S) : WebAssemblyTargetStreamer(S) {} -static void PrintTypes(formatted_raw_ostream &OS, ArrayRef<MVT> Types) { +static void PrintTypes(formatted_raw_ostream &OS, ArrayRef<wasm::ValType> Types) { bool First = true; - for (MVT Type : Types) { + for (auto Type : Types) { if (First) First = false; else OS << ", "; - OS << WebAssembly::TypeToString(WebAssembly::toValType(Type)); + OS << WebAssembly::TypeToString(Type); } OS << '\n'; } -void WebAssemblyTargetAsmStreamer::emitParam(MCSymbol *Symbol, - ArrayRef<MVT> Types) { - if (!Types.empty()) { - OS << "\t.param \t"; - - // FIXME: Currently this applies to the "current" function; it may - // be cleaner to specify an explicit symbol as part of the directive. - - PrintTypes(OS, Types); - } -} - -void WebAssemblyTargetAsmStreamer::emitResult(MCSymbol *Symbol, - ArrayRef<MVT> Types) { - if (!Types.empty()) { - OS << "\t.result \t"; - - // FIXME: Currently this applies to the "current" function; it may - // be cleaner to specify an explicit symbol as part of the directive. - - PrintTypes(OS, Types); - } -} - -void WebAssemblyTargetAsmStreamer::emitLocal(ArrayRef<MVT> Types) { +void WebAssemblyTargetAsmStreamer::emitLocal(ArrayRef<wasm::ValType> Types) { if (!Types.empty()) { OS << "\t.local \t"; PrintTypes(OS, Types); @@ -84,19 +60,20 @@ void WebAssemblyTargetAsmStreamer::emitLocal(ArrayRef<MVT> Types) { void WebAssemblyTargetAsmStreamer::emitEndFunc() { OS << "\t.endfunc\n"; } -void WebAssemblyTargetAsmStreamer::emitIndirectFunctionType( - MCSymbolWasm *Symbol) { - OS << "\t.functype\t" << Symbol->getName(); - if (Symbol->getSignature()->Returns.empty()) - OS << ", void"; - else { - assert(Symbol->getSignature()->Returns.size() == 1); - OS << ", " - << WebAssembly::TypeToString(Symbol->getSignature()->Returns.front()); +void WebAssemblyTargetAsmStreamer::emitFunctionType(MCSymbolWasm *Symbol) { + OS << "\t.functype\t" << Symbol->getName() << " ("; + auto &Params = Symbol->getSignature()->Params; + for (auto &Ty : Params) { + if (&Ty != &Params[0]) OS << ", "; + OS << WebAssembly::TypeToString(Ty); } - for (auto Ty : Symbol->getSignature()->Params) - OS << ", " << WebAssembly::TypeToString(Ty); - OS << '\n'; + OS << ") -> ("; + auto &Returns = Symbol->getSignature()->Returns; + for (auto &Ty : Returns) { + if (&Ty != &Returns[0]) OS << ", "; + OS << WebAssembly::TypeToString(Ty); + } + OS << ")\n"; } void WebAssemblyTargetAsmStreamer::emitGlobalType(MCSymbolWasm *Sym) { @@ -131,19 +108,9 @@ void WebAssemblyTargetAsmStreamer::emitIndIdx(const MCExpr *Value) { OS << "\t.indidx \t" << *Value << '\n'; } -void WebAssemblyTargetWasmStreamer::emitParam(MCSymbol *Symbol, - ArrayRef<MVT> Types) { - // The Symbol already has its signature -} - -void WebAssemblyTargetWasmStreamer::emitResult(MCSymbol *Symbol, - ArrayRef<MVT> Types) { - // The Symbol already has its signature -} - -void WebAssemblyTargetWasmStreamer::emitLocal(ArrayRef<MVT> Types) { - SmallVector<std::pair<MVT, uint32_t>, 4> Grouped; - for (MVT Type : Types) { +void WebAssemblyTargetWasmStreamer::emitLocal(ArrayRef<wasm::ValType> Types) { + SmallVector<std::pair<wasm::ValType, uint32_t>, 4> Grouped; + for (auto Type : Types) { if (Grouped.empty() || Grouped.back().first != Type) Grouped.push_back(std::make_pair(Type, 1)); else @@ -153,7 +120,7 @@ void WebAssemblyTargetWasmStreamer::emitLocal(ArrayRef<MVT> Types) { Streamer.EmitULEB128IntValue(Grouped.size()); for (auto Pair : Grouped) { Streamer.EmitULEB128IntValue(Pair.second); - emitValueType(WebAssembly::toValType(Pair.first)); + emitValueType(Pair.first); } } @@ -165,8 +132,7 @@ void WebAssemblyTargetWasmStreamer::emitIndIdx(const MCExpr *Value) { llvm_unreachable(".indidx encoding not yet implemented"); } -void WebAssemblyTargetWasmStreamer::emitIndirectFunctionType( - MCSymbolWasm *Symbol) { +void WebAssemblyTargetWasmStreamer::emitFunctionType(MCSymbolWasm *Symbol) { // Symbol already has its arguments and result set. Symbol->setType(wasm::WASM_SYMBOL_TYPE_FUNCTION); } diff --git a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.h b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.h index 3f1c6e158b2..0416aa434d9 100644 --- a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.h +++ b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.h @@ -31,16 +31,12 @@ class WebAssemblyTargetStreamer : public MCTargetStreamer { public: explicit WebAssemblyTargetStreamer(MCStreamer &S); - /// .param - virtual void emitParam(MCSymbol *Symbol, ArrayRef<MVT> Types) = 0; - /// .result - virtual void emitResult(MCSymbol *Symbol, ArrayRef<MVT> Types) = 0; /// .local - virtual void emitLocal(ArrayRef<MVT> Types) = 0; + virtual void emitLocal(ArrayRef<wasm::ValType> Types) = 0; /// .endfunc virtual void emitEndFunc() = 0; /// .functype - virtual void emitIndirectFunctionType(MCSymbolWasm *Symbol) = 0; + virtual void emitFunctionType(MCSymbolWasm *Symbol) = 0; /// .indidx virtual void emitIndIdx(const MCExpr *Value) = 0; /// .globaltype @@ -61,11 +57,9 @@ class WebAssemblyTargetAsmStreamer final : public WebAssemblyTargetStreamer { public: WebAssemblyTargetAsmStreamer(MCStreamer &S, formatted_raw_ostream &OS); - void emitParam(MCSymbol *Symbol, ArrayRef<MVT> Types) override; - void emitResult(MCSymbol *Symbol, ArrayRef<MVT> Types) override; - void emitLocal(ArrayRef<MVT> Types) override; + void emitLocal(ArrayRef<wasm::ValType> Types) override; void emitEndFunc() override; - void emitIndirectFunctionType(MCSymbolWasm *Symbol) override; + void emitFunctionType(MCSymbolWasm *Symbol) override; void emitIndIdx(const MCExpr *Value) override; void emitGlobalType(MCSymbolWasm *Sym) override; void emitEventType(MCSymbolWasm *Sym) override; @@ -77,11 +71,9 @@ class WebAssemblyTargetWasmStreamer final : public WebAssemblyTargetStreamer { public: explicit WebAssemblyTargetWasmStreamer(MCStreamer &S); - void emitParam(MCSymbol *Symbol, ArrayRef<MVT> Types) override; - void emitResult(MCSymbol *Symbol, ArrayRef<MVT> Types) override; - void emitLocal(ArrayRef<MVT> Types) override; + void emitLocal(ArrayRef<wasm::ValType> Types) override; void emitEndFunc() override; - void emitIndirectFunctionType(MCSymbolWasm *Symbol) override; + void emitFunctionType(MCSymbolWasm *Symbol) override; void emitIndIdx(const MCExpr *Value) override; void emitGlobalType(MCSymbolWasm *Sym) override; void emitEventType(MCSymbolWasm *Sym) override; @@ -94,15 +86,13 @@ public: explicit WebAssemblyTargetNullStreamer(MCStreamer &S) : WebAssemblyTargetStreamer(S) {} - void emitParam(MCSymbol *Symbol, ArrayRef<MVT> Types) override {} - void emitResult(MCSymbol *Symbol, ArrayRef<MVT> Types) override {} - void emitLocal(ArrayRef<MVT> Types) override {} + void emitLocal(ArrayRef<wasm::ValType>) override {} void emitEndFunc() override {} - void emitIndirectFunctionType(MCSymbolWasm *Symbol) override {} - void emitIndIdx(const MCExpr *Value) override {} - void emitGlobalType(MCSymbolWasm *Sym) override {} - void emitEventType(MCSymbolWasm *Sym) override {} - void emitImportModule(MCSymbolWasm *Sym, StringRef ModuleName) override {} + void emitFunctionType(MCSymbolWasm *) override {} + void emitIndIdx(const MCExpr *) override {} + void emitGlobalType(MCSymbolWasm *) override {} + void emitEventType(MCSymbolWasm *) override {} + void emitImportModule(MCSymbolWasm *, StringRef) override {} }; } // end namespace llvm diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp index 66fa91bd4d9..afe975a7046 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp @@ -104,7 +104,7 @@ void WebAssemblyAsmPrinter::EmitEndOfAsmFile(Module &M) { // infer the type from a call). With object files it applies to all // imports. so fix the names and the tests, or rethink how import // delcarations work in asm files. - getTargetStreamer()->emitIndirectFunctionType(Sym); + getTargetStreamer()->emitFunctionType(Sym); if (TM.getTargetTriple().isOSBinFormatWasm() && F.hasFnAttribute("wasm-import-module")) { @@ -166,7 +166,7 @@ void WebAssemblyAsmPrinter::EmitFunctionBodyStart() { addSignature(std::move(Signature)); // FIXME: clean up how params and results are emitted (use signatures) - getTargetStreamer()->emitParam(CurrentFnSym, ParamVTs); + getTargetStreamer()->emitFunctionType(WasmSym); // Emit the function index. if (MDNode *Idx = F.getMetadata("wasm.index")) { @@ -176,8 +176,9 @@ void WebAssemblyAsmPrinter::EmitFunctionBodyStart() { cast<ConstantAsMetadata>(Idx->getOperand(0))->getValue())); } - getTargetStreamer()->emitResult(CurrentFnSym, ResultVTs); - getTargetStreamer()->emitLocal(MFI->getLocals()); + SmallVector<wasm::ValType, 16> Locals; + ValTypesFromMVTs(MFI->getLocals(), Locals); + getTargetStreamer()->emitLocal(Locals); AsmPrinter::EmitFunctionBodyStart(); } diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyMachineFunctionInfo.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyMachineFunctionInfo.cpp index 073706e567e..0157af0f851 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyMachineFunctionInfo.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyMachineFunctionInfo.cpp @@ -64,13 +64,17 @@ void llvm::ComputeSignatureVTs(const FunctionType *Ty, const Function &F, Params.push_back(PtrVT); } +void llvm::ValTypesFromMVTs(const ArrayRef<MVT> &In, + SmallVectorImpl<wasm::ValType> &Out) { + for (MVT Ty : In) + Out.push_back(WebAssembly::toValType(Ty)); +} + std::unique_ptr<wasm::WasmSignature> llvm::SignatureFromMVTs(const SmallVectorImpl<MVT> &Results, const SmallVectorImpl<MVT> &Params) { auto Sig = make_unique<wasm::WasmSignature>(); - for (MVT Ty : Results) - Sig->Returns.push_back(WebAssembly::toValType(Ty)); - for (MVT Ty : Params) - Sig->Params.push_back(WebAssembly::toValType(Ty)); + ValTypesFromMVTs(Results, Sig->Returns); + ValTypesFromMVTs(Params, Sig->Params); return Sig; } diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyMachineFunctionInfo.h b/llvm/lib/Target/WebAssembly/WebAssemblyMachineFunctionInfo.h index cde44d24599..4be4beb85d0 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyMachineFunctionInfo.h +++ b/llvm/lib/Target/WebAssembly/WebAssemblyMachineFunctionInfo.h @@ -129,6 +129,9 @@ void ComputeSignatureVTs(const FunctionType *Ty, const Function &F, const TargetMachine &TM, SmallVectorImpl<MVT> &Params, SmallVectorImpl<MVT> &Results); +void ValTypesFromMVTs(const ArrayRef<MVT> &In, + SmallVectorImpl<wasm::ValType> &Out); + std::unique_ptr<wasm::WasmSignature> SignatureFromMVTs(const SmallVectorImpl<MVT> &Results, const SmallVectorImpl<MVT> &Params); |

