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,26 +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,7 @@ return static_cast(TS); } + //===----------------------------------------------------------------------===// // WebAssemblyAsmPrinter Implementation. //===----------------------------------------------------------------------===// @@ -83,16 +84,25 @@ if (F.isDeclarationForLinker() && !F.isIntrinsic()) { SmallVector Results; SmallVector Params; - ComputeSignatureVTs(F, TM, Params, Results); - MCSymbol *Sym = getSymbol(&F); - getTargetStreamer()->emitIndirectFunctionType(Sym, Params, Results); + ComputeSignatureVTs(F.getFunctionType(), F, TM, Params, Results); + auto *Sym = cast(getSymbol(&F)); + if (!Sym->getSignature()) { + auto Signature = SignatureFromMVTs(Results, Params); + Sym->setSignature(Signature.get()); + addSignature(std::move(Signature)); + } + // FIXME: this was originally intended for post-linking and was only used + // for imports that were only called indirectly (i.e. s2wasm could not + // 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); 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 +147,18 @@ } void WebAssemblyAsmPrinter::EmitFunctionBodyStart() { - getTargetStreamer()->emitParam(CurrentFnSym, MFI->getParams()); - - SmallVector ResultVTs; const Function &F = MF->getFunction(); + SmallVector ResultVTs; + SmallVector ParamVTs; + ComputeSignatureVTs(F.getFunctionType(), F, TM, ParamVTs, ResultVTs); + auto Signature = SignatureFromMVTs(ResultVTs, ParamVTs); + auto *WasmSym = cast(CurrentFnSym); + //assert(WasmSym->getSignature() == nullptr); + WasmSym->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,15 +168,7 @@ 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) - getTargetStreamer()->emitResult(CurrentFnSym, ResultVTs); - else - getTargetStreamer()->emitResult(CurrentFnSym, ArrayRef()); - + getTargetStreamer()->emitResult(CurrentFnSym, ResultVTs); getTargetStreamer()->emitLocal(MFI->getLocals()); AsmPrinter::EmitFunctionBodyStart(); Index: lib/Target/WebAssembly/WebAssemblyISelLowering.cpp =================================================================== --- lib/Target/WebAssembly/WebAssemblyISelLowering.cpp +++ lib/Target/WebAssembly/WebAssemblyISelLowering.cpp @@ -769,12 +769,17 @@ MFI->addParam(PtrVT); } - // Record the number and types of results. + // Record the number and types of arguments and results. SmallVector Params; SmallVector Results; - ComputeSignatureVTs(MF.getFunction(), DAG.getTarget(), Params, Results); + ComputeSignatureVTs(MF.getFunction().getFunctionType(), MF.getFunction(), DAG.getTarget(), Params, Results); for (MVT VT : Results) MFI->addResult(VT); + // TODO: Use signatures in WebAssemblyMachineFunctionInfo too and unify + // the param logic here with ComputeSignatureVTs + assert(MFI->getParams().size() == Params.size() && + std::equal(MFI->getParams().begin(), MFI->getParams().end(), + Params.begin())); return Chain; } Index: lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp =================================================================== --- lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp +++ lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp @@ -51,34 +51,13 @@ const TargetMachine &TM = MF.getTarget(); const Function &CurrentFunc = MF.getFunction(); - SmallVector Returns; - SmallVector Params; + SmallVector ResultMVTs; + SmallVector ParamMVTs; + ComputeSignatureVTs(FuncTy, CurrentFunc, TM, ParamMVTs, ResultMVTs); - wasm::ValType iPTR = MF.getSubtarget().hasAddr64() - ? wasm::ValType::I64 - : wasm::ValType::I32; - - SmallVector ResultMVTs; - ComputeLegalValueVTs(CurrentFunc, TM, FuncTy->getReturnType(), ResultMVTs); - // WebAssembly can't currently handle returning tuples. - if (ResultMVTs.size() <= 1) - for (MVT ResultMVT : ResultMVTs) - Returns.push_back(WebAssembly::toValType(ResultMVT)); - else - Params.push_back(iPTR); - - for (Type *Ty : FuncTy->params()) { - SmallVector ParamMVTs; - ComputeLegalValueVTs(CurrentFunc, TM, Ty, ParamMVTs); - for (MVT ParamMVT : ParamMVTs) - Params.push_back(WebAssembly::toValType(ParamMVT)); - } - - if (FuncTy->isVarArg()) - Params.push_back(iPTR); - - WasmSym->setReturns(std::move(Returns)); - WasmSym->setParams(std::move(Params)); + auto Signature = SignatureFromMVTs(ResultMVTs, ParamMVTs); + WasmSym->setSignature(Signature.get()); + Printer.addSignature(std::move(Signature)); WasmSym->setType(wasm::WASM_SYMBOL_TYPE_FUNCTION); } @@ -108,9 +87,10 @@ SmallVector Returns; SmallVector Params; GetLibcallSignature(Subtarget, Name, Returns, Params); - - 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); return WasmSym; @@ -203,8 +183,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 @@ -17,7 +17,9 @@ #define LLVM_LIB_TARGET_WEBASSEMBLY_WEBASSEMBLYMACHINEFUNCTIONINFO_H #include "MCTargetDesc/WebAssemblyMCTargetDesc.h" +#include "llvm/BinaryFormat/Wasm.h" #include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/MC/MCSymbolWasm.h" namespace llvm { @@ -121,10 +123,16 @@ void ComputeLegalValueVTs(const Function &F, const TargetMachine &TM, Type *Ty, SmallVectorImpl &ValueVTs); -void ComputeSignatureVTs(const Function &F, const TargetMachine &TM, +// Compute the signature for a given FunctionType (Ty). Note that it's not the +// signature for F (F is just used to get varous context) +void ComputeSignatureVTs(const FunctionType *Ty, const Function &F, const TargetMachine &TM, SmallVectorImpl &Params, SmallVectorImpl &Results); +std::unique_ptr +SignatureFromMVTs(const SmallVectorImpl &Results, + const SmallVectorImpl &Params); + } // end namespace llvm #endif Index: lib/Target/WebAssembly/WebAssemblyMachineFunctionInfo.cpp =================================================================== --- lib/Target/WebAssembly/WebAssemblyMachineFunctionInfo.cpp +++ lib/Target/WebAssembly/WebAssemblyMachineFunctionInfo.cpp @@ -43,20 +43,35 @@ } } -void llvm::ComputeSignatureVTs(const Function &F, const TargetMachine &TM, +void llvm::ComputeSignatureVTs(const FunctionType *Ty, + const Function &F, + const TargetMachine &TM, SmallVectorImpl &Params, SmallVectorImpl &Results) { - ComputeLegalValueVTs(F, TM, F.getReturnType(), Results); + ComputeLegalValueVTs(F, TM, Ty->getReturnType(), Results); + MVT PtrVT = MVT::getIntegerVT(TM.createDataLayout().getPointerSizeInBits()); if (Results.size() > 1) { // WebAssembly currently can't lower returns of multiple values without // demoting to sret (see WebAssemblyTargetLowering::CanLowerReturn). So // replace multiple return values with a pointer parameter. Results.clear(); - Params.push_back( - MVT::getIntegerVT(TM.createDataLayout().getPointerSizeInBits())); + Params.push_back(PtrVT); } - for (auto &Arg : F.args()) - ComputeLegalValueVTs(F, TM, Arg.getType(), Params); + for (auto *Param : Ty->params()) + ComputeLegalValueVTs(F, TM, Param, Params); + if (Ty->isVarArg()) + Params.push_back(PtrVT); +} + +std::unique_ptr +llvm::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; } Index: test/MC/WebAssembly/external-func-address.ll =================================================================== --- test/MC/WebAssembly/external-func-address.ll +++ test/MC/WebAssembly/external-func-address.ll @@ -3,7 +3,7 @@ target triple = "wasm32-unknown-unknown" ; Verify that addresses of external functions generate correctly typed -; imports and relocations or type R_TABLE_INDEX_I32. +; imports and relocations of type R_TABLE_INDEX_I32. declare void @f0(i32) #0 @ptr_to_f0 = hidden global void (i32)* @f0, align 4 @@ -13,6 +13,13 @@ declare void @f1(i32) #1 @ptr_to_f1 = hidden global void (i32)* @f1, align 4 +; Check that varargs functions have correctly typed imports +declare i32 @varargs(i32, i32, ...) +define void @call(i32) { + %a = call i32 (i32, i32, ...) @varargs(i32 0, i32 0) + ret void +} + ; CHECK: --- !WASM ; CHECK-NEXT: FileHeader: ; CHECK-NEXT: Version: 0x00000001 @@ -21,7 +28,13 @@ ; CHECK-NEXT: Signatures: ; CHECK-NEXT: - Index: 0 ; CHECK-NEXT: ReturnType: NORESULT -; CHECK-NEXT: ParamTypes: +; CHECK-NEXT: ParamTypes: +; CHECK-NEXT: - I32 +; CHECK-NEXT: - Index: 1 +; CHECK-NEXT: ReturnType: I32 +; CHECK-NEXT: ParamTypes: +; CHECK-NEXT: - I32 +; CHECK-NEXT: - I32 ; CHECK-NEXT: - I32 ; CHECK: - Type: IMPORT ; CHECK-NEXT: Imports: @@ -29,6 +42,10 @@ ; CHECK-NEXT: Field: __linear_memory ; CHECK: - Module: env ; CHECK-NEXT: Field: __indirect_function_table +; CHECK: - Module: env +; CHECK-NEXT: Field: varargs +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: SigIndex: 1 ; CHECK: - Module: somewhere ; CHECK-NEXT: Field: f0 ; CHECK: - Module: env @@ -40,9 +57,9 @@ ; CHECK-NEXT: - Offset: ; CHECK-NEXT: Opcode: I32_CONST ; CHECK-NEXT: Value: 1 -; CHECK-NEXT: Functions: [ 0, 1 ] +; CHECK-NEXT: Functions: [ 1, 2 ] ; CHECK: - Type: DATA ; CHECK-NEXT: Relocations: ; CHECK-NEXT: - Type: R_WEBASSEMBLY_TABLE_INDEX_I32 -; CHECK-NEXT: Index: 1 +; CHECK-NEXT: Index: 3 ; CHECK-NEXT: Offset: 0x00000006 Index: test/MC/WebAssembly/types.ll =================================================================== --- test/MC/WebAssembly/types.ll +++ test/MC/WebAssembly/types.ll @@ -12,6 +12,7 @@ declare <2 x i64> @v2i64() declare <4 x float> @v4f32() declare <2 x double> @v2f64() +declare { i32, i32, i32 } @structret() define void @f1() { entry: @@ -25,6 +26,11 @@ %tmp8 = call <2 x i64> @v2i64() %tmp9 = call <4 x float> @v4f32() %tmp10 = call <2 x double> @v2f64() + %tmp11 = call {i32, i32, i32} @structret() + ret void +} + +define void @vararg(i32, i32, ...) { ret void } @@ -48,5 +54,15 @@ ; CHECK-NEXT: - Index: 5 ; CHECK-NEXT: ReturnType: V128 ; CHECK-NEXT: ParamTypes: +; CHECK-NEXT: - Index: 6 +; CHECK-NEXT: ReturnType: NORESULT +; CHECK-NEXT: ParamTypes: +; CHECK-NEXT: - I32 +; CHECK-NEXT: - Index: 7 +; CHECK-NEXT: ReturnType: NORESULT +; CHECK-NEXT: ParamTypes: +; CHECK-NEXT: - I32 +; CHECK-NEXT: - I32 +; CHECK-NEXT: - I32 ; should be no additional types ; CHECK-NOT: ReturnType Index: tools/obj2yaml/wasm2yaml.cpp =================================================================== --- tools/obj2yaml/wasm2yaml.cpp +++ tools/obj2yaml/wasm2yaml.cpp @@ -155,9 +155,13 @@ 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; + assert(FunctionSig.Returns.size() <= 1 && + "Functions with multiple returns are not supported"); + 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);