From 73b2f90c135504c969a7994b9e4da4c6a9635cc9 Mon Sep 17 00:00:00 2001 From: Heejin Ahn Date: Tue, 11 Dec 2018 01:11:04 +0000 Subject: [PATCH] [WebAssembly] Add '.eventtype' directive support Summary: This patch supports `.eventtype` directive printing and parsing in the same syntax with `.functype`. Reviewers: aardappel, sbc100 Subscribers: dschuff, sbc100, jgravelle-google, sunfish, llvm-commits Differential Revision: https://reviews.llvm.org/D55353 llvm-svn: 348818 --- .../AsmParser/WebAssemblyAsmParser.cpp | 49 +++++++++++---- .../WebAssemblyTargetStreamer.cpp | 59 +++++++++++-------- .../MCTargetDesc/WebAssemblyTargetStreamer.h | 3 + test/CodeGen/WebAssembly/exception.ll | 2 +- test/MC/WebAssembly/basic-assembly.s | 2 + 5 files changed, 77 insertions(+), 38 deletions(-) diff --git a/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp b/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp index bf7580617c8..9688090cab7 100644 --- a/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp +++ b/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp @@ -367,6 +367,24 @@ public: CurrentState = Label; } + bool parseSignature(wasm::WasmSignature *Signature) { + 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; + return false; + } + // This function processes wasm-specific directives streamed to // WebAssemblyTargetStreamer, all others go to the generic parser // (see WasmAsmParser). @@ -424,19 +442,7 @@ public: CurrentState = FunctionStart; } auto Signature = make_unique(); - 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, ")")) + if (parseSignature(Signature.get())) return true; WasmSym->setSignature(Signature.get()); addSignature(std::move(Signature)); @@ -446,6 +452,23 @@ public: return expect(AsmToken::EndOfStatement, "EOL"); } + if (DirectiveID.getString() == ".eventtype") { + auto SymName = expectIdent(); + if (SymName.empty()) + return true; + auto WasmSym = cast( + TOut.getStreamer().getContext().getOrCreateSymbol(SymName)); + auto Signature = make_unique(); + if (parseRegTypeList(Signature->Params)) + return true; + WasmSym->setSignature(Signature.get()); + addSignature(std::move(Signature)); + WasmSym->setType(wasm::WASM_SYMBOL_TYPE_EVENT); + TOut.emitEventType(WasmSym); + // TODO: backend also calls TOut.emitIndIdx, but that is not implemented. + return expect(AsmToken::EndOfStatement, "EOL"); + } + if (DirectiveID.getString() == ".local") { if (CurrentState != FunctionStart) return error(".local directive should follow the start of a function", diff --git a/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp b/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp index 281c9c0cc69..70ac5027254 100644 --- a/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp +++ b/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp @@ -61,21 +61,40 @@ void WebAssemblyTargetAsmStreamer::emitLocal(ArrayRef Types) { void WebAssemblyTargetAsmStreamer::emitEndFunc() { OS << "\t.endfunc\n"; } +void WebAssemblyTargetAsmStreamer::emitSignature( + const wasm::WasmSignature *Sig) { + OS << "("; + emitParamList(Sig); + OS << ") -> ("; + emitReturnList(Sig); + OS << ")"; +} + +void WebAssemblyTargetAsmStreamer::emitParamList( + const wasm::WasmSignature *Sig) { + auto &Params = Sig->Params; + for (auto &Ty : Params) { + if (&Ty != &Params[0]) + OS << ", "; + OS << WebAssembly::TypeToString(Ty); + } +} + +void WebAssemblyTargetAsmStreamer::emitReturnList( + const wasm::WasmSignature *Sig) { + auto &Returns = Sig->Returns; + for (auto &Ty : Returns) { + if (&Ty != &Returns[0]) + OS << ", "; + OS << WebAssembly::TypeToString(Ty); + } +} + void WebAssemblyTargetAsmStreamer::emitFunctionType(const MCSymbolWasm *Sym) { assert(Sym->isFunction()); - OS << "\t.functype\t" << Sym->getName() << " ("; - auto &Params = Sym->getSignature()->Params; - for (auto &Ty : Params) { - if (&Ty != &Params[0]) OS << ", "; - OS << WebAssembly::TypeToString(Ty); - } - OS << ") -> ("; - auto &Returns = Sym->getSignature()->Returns; - for (auto &Ty : Returns) { - if (&Ty != &Returns[0]) OS << ", "; - OS << WebAssembly::TypeToString(Ty); - } - OS << ")\n"; + OS << "\t.functype\t" << Sym->getName() << " "; + emitSignature(Sym->getSignature()); + OS << "\n"; } void WebAssemblyTargetAsmStreamer::emitGlobalType(const MCSymbolWasm *Sym) { @@ -88,17 +107,9 @@ void WebAssemblyTargetAsmStreamer::emitGlobalType(const MCSymbolWasm *Sym) { void WebAssemblyTargetAsmStreamer::emitEventType(const MCSymbolWasm *Sym) { assert(Sym->isEvent()); - OS << "\t.eventtype\t" << Sym->getName(); - if (Sym->getSignature()->Returns.empty()) - OS << ", void"; - else { - assert(Sym->getSignature()->Returns.size() == 1); - OS << ", " - << WebAssembly::TypeToString(Sym->getSignature()->Returns.front()); - } - for (auto Ty : Sym->getSignature()->Params) - OS << ", " << WebAssembly::TypeToString(Ty); - OS << '\n'; + OS << "\t.eventtype\t" << Sym->getName() << " "; + emitParamList(Sym->getSignature()); + OS << "\n"; } void WebAssemblyTargetAsmStreamer::emitImportModule(const MCSymbolWasm *Sym, diff --git a/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.h b/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.h index 9085dbd1f5f..3073938118b 100644 --- a/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.h +++ b/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.h @@ -54,6 +54,9 @@ protected: /// This part is for ascii assembly output class WebAssemblyTargetAsmStreamer final : public WebAssemblyTargetStreamer { formatted_raw_ostream &OS; + void emitSignature(const wasm::WasmSignature *Sig); + void emitParamList(const wasm::WasmSignature *Sig); + void emitReturnList(const wasm::WasmSignature *Sig); public: WebAssemblyTargetAsmStreamer(MCStreamer &S, formatted_raw_ostream &OS); diff --git a/test/CodeGen/WebAssembly/exception.ll b/test/CodeGen/WebAssembly/exception.ll index b53cd0cb544..b0365fc9d43 100644 --- a/test/CodeGen/WebAssembly/exception.ll +++ b/test/CodeGen/WebAssembly/exception.ll @@ -262,4 +262,4 @@ declare void @_ZSt9terminatev() declare %struct.Cleanup* @_ZN7CleanupD1Ev(%struct.Cleanup* returned) ; CHECK: __cpp_exception: -; CHECK: .eventtype __cpp_exception, void, i32 +; CHECK: .eventtype __cpp_exception i32 diff --git a/test/MC/WebAssembly/basic-assembly.s b/test/MC/WebAssembly/basic-assembly.s index e51e2bc9aab..408d02d1337 100644 --- a/test/MC/WebAssembly/basic-assembly.s +++ b/test/MC/WebAssembly/basic-assembly.s @@ -8,6 +8,7 @@ test0: # Test all types: .functype test0 (i32, i64) -> (i32) + .eventtype __cpp_exception i32 .local f32, f64, v128, v128 # Explicit getlocal/setlocal: get_local 2 @@ -66,6 +67,7 @@ test0: # CHECK: .text # CHECK-LABEL: test0: # CHECK-NEXT: .functype test0 (i32, i64) -> (i32) +# CHECK-NEXT: .eventtype __cpp_exception i32 # CHECK-NEXT: .local f32, f64 # CHECK-NEXT: get_local 2 # CHECK-NEXT: set_local 2