Index: include/llvm/BinaryFormat/Wasm.h =================================================================== --- include/llvm/BinaryFormat/Wasm.h +++ include/llvm/BinaryFormat/Wasm.h @@ -16,6 +16,7 @@ #define LLVM_BINARYFORMAT_WASM_H #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/SmallVector.h" namespace llvm { namespace wasm { @@ -34,11 +35,6 @@ uint32_t Version; }; -struct WasmSignature { - std::vector ParamTypes; - uint8_t ReturnType; -}; - struct WasmExport { StringRef Name; uint8_t Kind; @@ -220,16 +216,6 @@ WASM_LIMITS_FLAG_HAS_MAX = 0x1, }; -// Subset of types that a value can have -enum class ValType { - I32 = WASM_TYPE_I32, - I64 = WASM_TYPE_I64, - F32 = WASM_TYPE_F32, - F64 = WASM_TYPE_F64, - V128 = WASM_TYPE_V128, - EXCEPT_REF = WASM_TYPE_EXCEPT_REF, -}; - // Kind codes used in the custom "name" section enum : unsigned { WASM_NAMES_FUNCTION = 0x1, @@ -276,9 +262,32 @@ #undef WASM_RELOC +// Subset of types that a value can have +enum class ValType { + I32 = WASM_TYPE_I32, + I64 = WASM_TYPE_I64, + F32 = WASM_TYPE_F32, + F64 = WASM_TYPE_F64, + V128 = WASM_TYPE_V128, + EXCEPT_REF = WASM_TYPE_EXCEPT_REF, +}; + +struct WasmSignature { + SmallVector Returns; + SmallVector Params; + // Support empty and tombstone instances, needed by DenseMap. + enum { Plain, Empty, Tombstone } State = Plain; + + WasmSignature(SmallVector &&InReturns, + SmallVector &&InParams) + : Returns(InReturns), Params(InParams) {} + WasmSignature() = default; +}; + // Useful comparison operators inline bool operator==(const WasmSignature &LHS, const WasmSignature &RHS) { - return LHS.ReturnType == RHS.ReturnType && LHS.ParamTypes == RHS.ParamTypes; + return LHS.State == RHS.State && LHS.Returns == RHS.Returns && + LHS.Params == RHS.Params; } inline bool operator!=(const WasmSignature &LHS, const WasmSignature &RHS) { Index: include/llvm/MC/MCSymbolWasm.h =================================================================== --- include/llvm/MC/MCSymbolWasm.h +++ include/llvm/MC/MCSymbolWasm.h @@ -20,11 +20,8 @@ bool IsHidden = false; bool IsComdat = false; std::string ModuleName; - SmallVector Returns; - SmallVector Params; + wasm::WasmSignature *Signature = nullptr; wasm::WasmGlobalType GlobalType; - bool ParamsSet = false; - bool ReturnsSet = false; bool GlobalTypeSet = false; /// An expression describing how to calculate the size of a symbol. If a @@ -60,25 +57,8 @@ const StringRef getModuleName() const { return ModuleName; } void setModuleName(StringRef Name) { ModuleName = Name; } - const SmallVector &getReturns() const { - assert(ReturnsSet); - return Returns; - } - - void setReturns(SmallVectorImpl &&Rets) { - ReturnsSet = true; - Returns = std::move(Rets); - } - - const SmallVector &getParams() const { - assert(ParamsSet); - return Params; - } - - void setParams(SmallVectorImpl &&Pars) { - ParamsSet = true; - Params = std::move(Pars); - } + const wasm::WasmSignature *getSignature() const { return Signature; } + void setSignature(wasm::WasmSignature *Sig) { Signature = Sig; } const wasm::WasmGlobalType &getGlobalType() const { assert(GlobalTypeSet); Index: include/llvm/Object/Wasm.h =================================================================== --- include/llvm/Object/Wasm.h +++ include/llvm/Object/Wasm.h @@ -22,6 +22,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/BinaryFormat/Wasm.h" #include "llvm/Config/llvm-config.h" +#include "llvm/MC/MCSymbolWasm.h" #include "llvm/Object/Binary.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Support/Error.h" Index: include/llvm/Object/WasmTraits.h =================================================================== --- include/llvm/Object/WasmTraits.h +++ include/llvm/Object/WasmTraits.h @@ -24,14 +24,20 @@ // Traits for using WasmSignature in a DenseMap. template <> struct DenseMapInfo { static wasm::WasmSignature getEmptyKey() { - return wasm::WasmSignature{{}, 1}; + wasm::WasmSignature Sig; + Sig.State = wasm::WasmSignature::Empty; + return Sig; } static wasm::WasmSignature getTombstoneKey() { - return wasm::WasmSignature{{}, 2}; + wasm::WasmSignature Sig; + Sig.State = wasm::WasmSignature::Tombstone; + return Sig; } static unsigned getHashValue(const wasm::WasmSignature &Sig) { - unsigned H = hash_value(Sig.ReturnType); - for (int32_t Param : Sig.ParamTypes) + uintptr_t H = hash_value(Sig.State); + for (auto Ret : Sig.Returns) + H = hash_combine(H, Ret); + for (auto Param : Sig.Params) H = hash_combine(H, Param); return H; } Index: lib/MC/WasmObjectWriter.cpp =================================================================== --- lib/MC/WasmObjectWriter.cpp +++ lib/MC/WasmObjectWriter.cpp @@ -58,6 +58,7 @@ // The signature of a wasm function, in a struct capable of being used as a // DenseMap key. +// TODO: Consider using WasmSignature directly instead. struct WasmFunctionType { // Support empty and tombstone instances, needed by DenseMap. enum { Plain, Empty, Tombstone } State; @@ -1049,8 +1050,10 @@ WasmFunctionType F; const MCSymbolWasm *ResolvedSym = ResolveSymbol(Symbol); - F.Returns = ResolvedSym->getReturns(); - F.Params = ResolvedSym->getParams(); + if (auto *Sig = ResolvedSym->getSignature()) { + F.Returns = Sig->Returns; + F.Params = Sig->Params; + } auto Pair = FunctionTypeIndices.insert(std::make_pair(F, FunctionTypes.size())); Index: lib/Object/WasmObjectFile.cpp =================================================================== --- lib/Object/WasmObjectFile.cpp +++ lib/Object/WasmObjectFile.cpp @@ -701,17 +701,16 @@ Signatures.reserve(Count); while (Count--) { wasm::WasmSignature Sig; - Sig.ReturnType = wasm::WASM_TYPE_NORESULT; uint8_t Form = readUint8(Ctx); if (Form != wasm::WASM_TYPE_FUNC) { return make_error("Invalid signature type", object_error::parse_failed); } uint32_t ParamCount = readVaruint32(Ctx); - Sig.ParamTypes.reserve(ParamCount); + Sig.Params.reserve(ParamCount); while (ParamCount--) { uint32_t ParamType = readUint8(Ctx); - Sig.ParamTypes.push_back(ParamType); + Sig.Params.push_back(wasm::ValType(ParamType)); } uint32_t ReturnCount = readVaruint32(Ctx); if (ReturnCount) { @@ -719,9 +718,9 @@ return make_error( "Multiple return types not supported", object_error::parse_failed); } - Sig.ReturnType = readUint8(Ctx); + Sig.Returns.push_back(wasm::ValType(readUint8(Ctx))); } - Signatures.push_back(Sig); + Signatures.push_back(std::move(Sig)); } if (Ctx.Ptr != Ctx.End) return make_error("Type section ended prematurely", Index: lib/Target/WebAssembly/InstPrinter/WebAssemblyInstPrinter.h =================================================================== --- lib/Target/WebAssembly/InstPrinter/WebAssemblyInstPrinter.h +++ lib/Target/WebAssembly/InstPrinter/WebAssemblyInstPrinter.h @@ -50,7 +50,7 @@ namespace WebAssembly { -const char *TypeToString(MVT Ty); +const char *TypeToString(wasm::ValType Ty); } // end namespace WebAssembly Index: lib/Target/WebAssembly/InstPrinter/WebAssemblyInstPrinter.cpp =================================================================== --- lib/Target/WebAssembly/InstPrinter/WebAssemblyInstPrinter.cpp +++ lib/Target/WebAssembly/InstPrinter/WebAssemblyInstPrinter.cpp @@ -235,24 +235,19 @@ } } -const char *llvm::WebAssembly::TypeToString(MVT Ty) { - switch (Ty.SimpleTy) { - case MVT::i32: +const char *llvm::WebAssembly::TypeToString(wasm::ValType Ty) { + switch (Ty) { + case wasm::ValType::I32: return "i32"; - case MVT::i64: + case wasm::ValType::I64: return "i64"; - case MVT::f32: + case wasm::ValType::F32: return "f32"; - case MVT::f64: + case wasm::ValType::F64: return "f64"; - case MVT::v16i8: - case MVT::v8i16: - case MVT::v4i32: - case MVT::v2i64: - case MVT::v4f32: - case MVT::v2f64: + case wasm::ValType::V128: return "v128"; - case MVT::ExceptRef: + case wasm::ValType::EXCEPT_REF: return "except_ref"; default: llvm_unreachable("unsupported type"); Index: lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.h =================================================================== --- lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.h +++ lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.h @@ -40,9 +40,7 @@ /// .endfunc virtual void emitEndFunc() = 0; /// .functype - virtual void emitIndirectFunctionType(MCSymbol *Symbol, - SmallVectorImpl &Params, - SmallVectorImpl &Results) = 0; + virtual void emitIndirectFunctionType(MCSymbolWasm *Symbol) = 0; /// .indidx virtual void emitIndIdx(const MCExpr *Value) = 0; /// .import_global @@ -65,8 +63,7 @@ void emitResult(MCSymbol *Symbol, ArrayRef Types) override; void emitLocal(ArrayRef Types) override; void emitEndFunc() override; - void emitIndirectFunctionType(MCSymbol *Symbol, SmallVectorImpl &Params, - SmallVectorImpl &Results) override; + void emitIndirectFunctionType(MCSymbolWasm *Symbol) override; void emitIndIdx(const MCExpr *Value) override; void emitGlobalImport(StringRef name) override; void emitImportModule(MCSymbolWasm *Sym, StringRef ModuleName) override; @@ -81,8 +78,7 @@ void emitResult(MCSymbol *Symbol, ArrayRef Types) override; void emitLocal(ArrayRef Types) override; void emitEndFunc() override; - void emitIndirectFunctionType(MCSymbol *Symbol, SmallVectorImpl &Params, - SmallVectorImpl &Results) override; + void emitIndirectFunctionType(MCSymbolWasm *Symbol) override; void emitIndIdx(const MCExpr *Value) override; void emitGlobalImport(StringRef name) override; void emitImportModule(MCSymbolWasm *Sym, StringRef ModuleName) override; Index: lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp =================================================================== --- lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp +++ lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp @@ -46,7 +46,7 @@ First = false; else OS << ", "; - OS << WebAssembly::TypeToString(Type); + OS << WebAssembly::TypeToString(WebAssembly::toValType(Type)); } OS << '\n'; } @@ -85,16 +85,16 @@ void WebAssemblyTargetAsmStreamer::emitEndFunc() { OS << "\t.endfunc\n"; } void WebAssemblyTargetAsmStreamer::emitIndirectFunctionType( - MCSymbol *Symbol, SmallVectorImpl &Params, - SmallVectorImpl &Results) { + MCSymbolWasm *Symbol) { OS << "\t.functype\t" << Symbol->getName(); - if (Results.empty()) + if (Symbol->getSignature()->Returns.empty()) OS << ", void"; else { - assert(Results.size() == 1); - OS << ", " << WebAssembly::TypeToString(Results.front()); + assert(Symbol->getSignature()->Returns.size() == 1); + OS << ", " + << WebAssembly::TypeToString(Symbol->getSignature()->Returns.front()); } - for (auto Ty : Params) + for (auto Ty : Symbol->getSignature()->Params) OS << ", " << WebAssembly::TypeToString(Ty); OS << '\n'; } @@ -114,20 +114,12 @@ void WebAssemblyTargetWasmStreamer::emitParam(MCSymbol *Symbol, ArrayRef Types) { - SmallVector Params; - for (MVT Ty : Types) - Params.push_back(WebAssembly::toValType(Ty)); - - cast(Symbol)->setParams(std::move(Params)); + // The Symbol already has its signature } void WebAssemblyTargetWasmStreamer::emitResult(MCSymbol *Symbol, ArrayRef Types) { - SmallVector Returns; - for (MVT Ty : Types) - Returns.push_back(WebAssembly::toValType(Ty)); - - cast(Symbol)->setReturns(std::move(Returns)); + // The Symbol already has its signature } void WebAssemblyTargetWasmStreamer::emitLocal(ArrayRef Types) { @@ -155,25 +147,9 @@ } void WebAssemblyTargetWasmStreamer::emitIndirectFunctionType( - MCSymbol *Symbol, SmallVectorImpl &Params, - SmallVectorImpl &Results) { - MCSymbolWasm *WasmSym = cast(Symbol); - if (WasmSym->isFunction()) { + MCSymbolWasm *Symbol) { // Symbol already has its arguments and result set. - return; - } - - SmallVector ValParams; - for (MVT Ty : Params) - ValParams.push_back(WebAssembly::toValType(Ty)); - - SmallVector ValResults; - for (MVT Ty : Results) - ValResults.push_back(WebAssembly::toValType(Ty)); - - WasmSym->setParams(std::move(ValParams)); - WasmSym->setReturns(std::move(ValResults)); - WasmSym->setType(wasm::WASM_SYMBOL_TYPE_FUNCTION); + Symbol->setType(wasm::WASM_SYMBOL_TYPE_FUNCTION); } void WebAssemblyTargetWasmStreamer::emitGlobalImport(StringRef name) { Index: lib/Target/WebAssembly/WebAssemblyAsmPrinter.h =================================================================== --- lib/Target/WebAssembly/WebAssemblyAsmPrinter.h +++ lib/Target/WebAssembly/WebAssemblyAsmPrinter.h @@ -25,6 +25,8 @@ const WebAssemblySubtarget *Subtarget; const MachineRegisterInfo *MRI; WebAssemblyFunctionInfo *MFI; + // TODO: Do the uniquing of Signatures here instead of ObjectFileWriter? + std::vector> Signatures; public: explicit WebAssemblyAsmPrinter(TargetMachine &TM, @@ -37,6 +39,9 @@ } const WebAssemblySubtarget &getSubtarget() const { return *Subtarget; } + void addSignature(std::unique_ptr &&Sig) { + Signatures.push_back(std::move(Sig)); + } //===------------------------------------------------------------------===// // MachineFunctionPass Implementation. Index: lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp =================================================================== --- lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp +++ lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp @@ -73,6 +73,19 @@ return static_cast(TS); } +// TODO: Clean up how and where we compute legal param/return VTs, and which +// signatures and param values have been legalized. +std::unique_ptr +SignatureFromMVTs(const SmallVectorImpl &Results, + const SmallVectorImpl &Params) { + auto Sig = make_unique(); + for (MVT Ty : Results) + Sig->Returns.push_back(WebAssembly::toValType(Ty)); + for (MVT Ty : Params) + Sig->Params.push_back(WebAssembly::toValType(Ty)); + return Sig; +} + //===----------------------------------------------------------------------===// // WebAssemblyAsmPrinter Implementation. //===----------------------------------------------------------------------===// @@ -84,15 +97,18 @@ SmallVector Results; SmallVector Params; ComputeSignatureVTs(F, TM, Params, Results); - MCSymbol *Sym = getSymbol(&F); - getTargetStreamer()->emitIndirectFunctionType(Sym, Params, Results); + auto *Sym = cast(getSymbol(&F)); + auto Signature = SignatureFromMVTs(Results, Params); + Sym->setSignature(Signature.get()); + addSignature(std::move(Signature)); + + getTargetStreamer()->emitIndirectFunctionType(Sym); if (TM.getTargetTriple().isOSBinFormatWasm() && F.hasFnAttribute("wasm-import-module")) { - MCSymbolWasm *WasmSym = cast(Sym); StringRef Name = F.getFnAttribute("wasm-import-module").getValueAsString(); - getTargetStreamer()->emitImportModule(WasmSym, Name); + getTargetStreamer()->emitImportModule(Sym, Name); } } } @@ -137,10 +153,18 @@ } void WebAssemblyAsmPrinter::EmitFunctionBodyStart() { - getTargetStreamer()->emitParam(CurrentFnSym, MFI->getParams()); - - SmallVector ResultVTs; const Function &F = MF->getFunction(); + SmallVector ResultVTs; + SmallVector ParamVTs; + ParamVTs.resize(MFI->getParams().size()); + std::copy(MFI->getParams().begin(), MFI->getParams().end(), ParamVTs.begin()); + ComputeLegalValueVTs(F, TM, F.getReturnType(), ResultVTs); + auto Signature = SignatureFromMVTs(ResultVTs, ParamVTs); + cast(CurrentFnSym)->setSignature(Signature.get()); + addSignature(std::move(Signature)); + + // FIXME: clean up how params and results are emitted (use signatures) + getTargetStreamer()->emitParam(CurrentFnSym, ParamVTs); // Emit the function index. if (MDNode *Idx = F.getMetadata("wasm.index")) { @@ -150,8 +174,6 @@ cast(Idx->getOperand(0))->getValue())); } - ComputeLegalValueVTs(F, TM, F.getReturnType(), ResultVTs); - // If the return type needs to be legalized it will get converted into // passing a pointer. if (ResultVTs.size() == 1) Index: lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp =================================================================== --- lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp +++ lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp @@ -51,7 +51,7 @@ const TargetMachine &TM = MF.getTarget(); const Function &CurrentFunc = MF.getFunction(); - SmallVector Returns; + SmallVector Returns; SmallVector Params; wasm::ValType iPTR = MF.getSubtarget().hasAddr64() @@ -77,8 +77,10 @@ if (FuncTy->isVarArg()) Params.push_back(iPTR); - WasmSym->setReturns(std::move(Returns)); - WasmSym->setParams(std::move(Params)); + auto Signature = + make_unique(std::move(Returns), std::move(Params)); + WasmSym->setSignature(Signature.get()); + Printer.addSignature(std::move(Signature)); WasmSym->setType(wasm::WASM_SYMBOL_TYPE_FUNCTION); } @@ -107,10 +109,11 @@ SmallVector Returns; SmallVector Params; - GetSignature(Subtarget, Name, Returns, Params); - - WasmSym->setReturns(std::move(Returns)); - WasmSym->setParams(std::move(Params)); + GetLibcallSignature(Subtarget, Name, Returns, Params); + auto Signature = + make_unique(std::move(Returns), std::move(Params)); + WasmSym->setSignature(Signature.get()); + Printer.addSignature(std::move(Signature)); WasmSym->setType(wasm::WASM_SYMBOL_TYPE_FUNCTION); return WasmSym; @@ -203,8 +206,10 @@ Params.pop_back(); MCSymbolWasm *WasmSym = cast(Sym); - WasmSym->setReturns(std::move(Returns)); - WasmSym->setParams(std::move(Params)); + auto Signature = make_unique(std::move(Returns), + std::move(Params)); + WasmSym->setSignature(Signature.get()); + Printer.addSignature(std::move(Signature)); WasmSym->setType(wasm::WASM_SYMBOL_TYPE_FUNCTION); const MCExpr *Expr = MCSymbolRefExpr::create( Index: lib/Target/WebAssembly/WebAssemblyMachineFunctionInfo.h =================================================================== --- lib/Target/WebAssembly/WebAssemblyMachineFunctionInfo.h +++ lib/Target/WebAssembly/WebAssemblyMachineFunctionInfo.h @@ -18,6 +18,7 @@ #include "MCTargetDesc/WebAssemblyMCTargetDesc.h" #include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/MC/MCSymbolWasm.h" namespace llvm { Index: lib/Target/WebAssembly/WebAssemblyRuntimeLibcallSignatures.h =================================================================== --- lib/Target/WebAssembly/WebAssemblyRuntimeLibcallSignatures.h +++ lib/Target/WebAssembly/WebAssemblyRuntimeLibcallSignatures.h @@ -23,14 +23,15 @@ class WebAssemblySubtarget; -extern void GetSignature(const WebAssemblySubtarget &Subtarget, - RTLIB::Libcall LC, - SmallVectorImpl &Rets, - SmallVectorImpl &Params); - -extern void GetSignature(const WebAssemblySubtarget &Subtarget, - const char *Name, SmallVectorImpl &Rets, - SmallVectorImpl &Params); +extern void GetLibcallSignature(const WebAssemblySubtarget &Subtarget, + RTLIB::Libcall LC, + SmallVectorImpl &Rets, + SmallVectorImpl &Params); + +extern void GetLibcallSignature(const WebAssemblySubtarget &Subtarget, + const char *Name, + SmallVectorImpl &Rets, + SmallVectorImpl &Params); } // end namespace llvm Index: lib/Target/WebAssembly/WebAssemblyRuntimeLibcallSignatures.cpp =================================================================== --- lib/Target/WebAssembly/WebAssemblyRuntimeLibcallSignatures.cpp +++ lib/Target/WebAssembly/WebAssemblyRuntimeLibcallSignatures.cpp @@ -485,9 +485,10 @@ } // end anonymous namespace -void llvm::GetSignature(const WebAssemblySubtarget &Subtarget, - RTLIB::Libcall LC, SmallVectorImpl &Rets, - SmallVectorImpl &Params) { +void llvm::GetLibcallSignature(const WebAssemblySubtarget &Subtarget, + RTLIB::Libcall LC, + SmallVectorImpl &Rets, + SmallVectorImpl &Params) { assert(Rets.empty()); assert(Params.empty()); @@ -831,11 +832,12 @@ static ManagedStatic LibcallNameMap; // TODO: If the RTLIB::Libcall-taking flavor of GetSignature remains unsed // other than here, just roll its logic into this version. -void llvm::GetSignature(const WebAssemblySubtarget &Subtarget, const char *Name, - SmallVectorImpl &Rets, - SmallVectorImpl &Params) { +void llvm::GetLibcallSignature(const WebAssemblySubtarget &Subtarget, + const char *Name, + SmallVectorImpl &Rets, + SmallVectorImpl &Params) { auto &Map = LibcallNameMap->Map; auto val = Map.find(Name); assert(val != Map.end() && "unexpected runtime library name"); - return GetSignature(Subtarget, val->second, Rets, Params); + return GetLibcallSignature(Subtarget, val->second, Rets, Params); } Index: tools/obj2yaml/wasm2yaml.cpp =================================================================== --- tools/obj2yaml/wasm2yaml.cpp +++ tools/obj2yaml/wasm2yaml.cpp @@ -155,9 +155,11 @@ for (const auto &FunctionSig : Obj.types()) { WasmYAML::Signature Sig; Sig.Index = Index++; - Sig.ReturnType = FunctionSig.ReturnType; - for (const auto &ParamType : FunctionSig.ParamTypes) - Sig.ParamTypes.push_back(ParamType); + Sig.ReturnType = wasm::WASM_TYPE_NORESULT; + if (FunctionSig.Returns.size()) + Sig.ReturnType = static_cast(FunctionSig.Returns[0]); + for (const auto &ParamType : FunctionSig.Params) + Sig.ParamTypes.push_back(static_cast(ParamType)); TypeSec->Signatures.push_back(Sig); } S = std::move(TypeSec);