[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
diff --git a/llvm/lib/MC/MCParser/AsmLexer.cpp b/llvm/lib/MC/MCParser/AsmLexer.cpp
index c8d48f0..2b0d20f 100644
--- a/llvm/lib/MC/MCParser/AsmLexer.cpp
+++ b/llvm/lib/MC/MCParser/AsmLexer.cpp
@@ -627,7 +627,6 @@
     return AsmToken(AsmToken::EndOfStatement, StringRef(TokStart, 1));
   case ':': return AsmToken(AsmToken::Colon, StringRef(TokStart, 1));
   case '+': return AsmToken(AsmToken::Plus, StringRef(TokStart, 1));
-  case '-': return AsmToken(AsmToken::Minus, StringRef(TokStart, 1));
   case '~': return AsmToken(AsmToken::Tilde, StringRef(TokStart, 1));
   case '(': return AsmToken(AsmToken::LParen, StringRef(TokStart, 1));
   case ')': return AsmToken(AsmToken::RParen, StringRef(TokStart, 1));
@@ -646,6 +645,12 @@
       return AsmToken(AsmToken::EqualEqual, StringRef(TokStart, 2));
     }
     return AsmToken(AsmToken::Equal, StringRef(TokStart, 1));
+  case '-':
+    if (*CurPtr == '>') {
+      ++CurPtr;
+      return AsmToken(AsmToken::MinusGreater, StringRef(TokStart, 2));
+    }
+    return AsmToken(AsmToken::Minus, StringRef(TokStart, 1));
   case '|':
     if (*CurPtr == '|') {
       ++CurPtr;
diff --git a/llvm/lib/MC/MCParser/MCAsmLexer.cpp b/llvm/lib/MC/MCParser/MCAsmLexer.cpp
index 1ed0568..10960fc 100644
--- a/llvm/lib/MC/MCParser/MCAsmLexer.cpp
+++ b/llvm/lib/MC/MCParser/MCAsmLexer.cpp
@@ -85,6 +85,7 @@
   case AsmToken::LessGreater:        OS << "LessGreater"; break;
   case AsmToken::LessLess:           OS << "LessLess"; break;
   case AsmToken::Minus:              OS << "Minus"; break;
+  case AsmToken::MinusGreater:       OS << "MinusGreater"; break;
   case AsmToken::Percent:            OS << "Percent"; break;
   case AsmToken::Pipe:               OS << "Pipe"; break;
   case AsmToken::PipePipe:           OS << "PipePipe"; break;
diff --git a/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp b/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp
index 703ea2d..bc2ec11 100644
--- a/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp
+++ b/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp
@@ -133,6 +133,9 @@
   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 @@
     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 @@
     return false;
   }
 
-
-  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});
+  StringRef ExpectIdent() {
+    if (!Lexer.is(AsmToken::Identifier)) {
+      Error("Expected identifier, got: ", Lexer.getTok());
+      return StringRef();
+    }
+    auto Name = Lexer.getTok().getString();
+    Parser.Lex();
+    return Name;
   }
 
-  bool ParseRegTypeList(std::vector<MVT> &Types) {
+  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(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 @@
     // 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 ada687e..5f06da8 100644
--- a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp
+++ b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp
@@ -39,43 +39,19 @@
 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::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 @@
   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 @@
   Streamer.EmitULEB128IntValue(Grouped.size());
   for (auto Pair : Grouped) {
     Streamer.EmitULEB128IntValue(Pair.second);
-    emitValueType(WebAssembly::toValType(Pair.first));
+    emitValueType(Pair.first);
   }
 }
 
@@ -165,8 +132,7 @@
   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 3f1c6e1..0416aa4 100644
--- a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.h
+++ b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.h
@@ -31,16 +31,12 @@
 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 @@
 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 @@
 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 @@
   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 66fa91b..afe975a 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
@@ -104,7 +104,7 @@
       // 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 @@
   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 @@
         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 073706e..0157af0 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyMachineFunctionInfo.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyMachineFunctionInfo.cpp
@@ -64,13 +64,17 @@
     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 cde44d2..4be4beb 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyMachineFunctionInfo.h
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyMachineFunctionInfo.h
@@ -129,6 +129,9 @@
                          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);