[llvm] r374933 - [WebAssembly] Allow multivalue types in block signature operands

Thomas Lively via llvm-commits llvm-commits at lists.llvm.org
Tue Oct 15 11:28:22 PDT 2019


Author: tlively
Date: Tue Oct 15 11:28:22 2019
New Revision: 374933

URL: http://llvm.org/viewvc/llvm-project?rev=374933&view=rev
Log:
[WebAssembly] Allow multivalue types in block signature operands

Summary:
Renames `ExprType` to the more apt `BlockType` and adds a variant for
multivalue blocks. Currently non-void blocks are only generated at the
end of functions where the block return type needs to agree with the
function return type, and that remains true for multivalue
blocks. That invariant means that the actual signature does not need
to be stored in the block signature `MachineOperand` because it can be
inferred by `WebAssemblyMCInstLower` from the return type of the
parent function. `WebAssemblyMCInstLower` continues to lower block
signature operands to immediates when possible but lowers multivalue
signatures to function type symbols. The AsmParser and Disassembler
are updated to handle multivalue block types as well.

Reviewers: aheejin, dschuff, aardappel

Subscribers: sbc100, jgravelle-google, hiraditya, sunfish, llvm-commits

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D68889

Modified:
    llvm/trunk/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp
    llvm/trunk/lib/Target/WebAssembly/Disassembler/LLVMBuild.txt
    llvm/trunk/lib/Target/WebAssembly/Disassembler/WebAssemblyDisassembler.cpp
    llvm/trunk/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyInstPrinter.cpp
    llvm/trunk/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCCodeEmitter.cpp
    llvm/trunk/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h
    llvm/trunk/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp
    llvm/trunk/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp
    llvm/trunk/lib/Target/WebAssembly/WebAssemblyMCInstLower.h
    llvm/trunk/test/CodeGen/WebAssembly/multivalue.ll
    llvm/trunk/test/MC/Disassembler/WebAssembly/wasm-error.txt
    llvm/trunk/test/MC/WebAssembly/basic-assembly.s
    llvm/trunk/tools/llvm-mc/Disassembler.cpp
    llvm/trunk/tools/llvm-mc/Disassembler.h
    llvm/trunk/tools/llvm-mc/llvm-mc.cpp

Modified: llvm/trunk/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp?rev=374933&r1=374932&r2=374933&view=diff
==============================================================================
--- llvm/trunk/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp (original)
+++ llvm/trunk/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp Tue Oct 15 11:28:22 2019
@@ -313,16 +313,17 @@ public:
     return Optional<wasm::ValType>();
   }
 
-  WebAssembly::ExprType parseBlockType(StringRef ID) {
-    return StringSwitch<WebAssembly::ExprType>(ID)
-        .Case("i32", WebAssembly::ExprType::I32)
-        .Case("i64", WebAssembly::ExprType::I64)
-        .Case("f32", WebAssembly::ExprType::F32)
-        .Case("f64", WebAssembly::ExprType::F64)
-        .Case("v128", WebAssembly::ExprType::V128)
-        .Case("exnref", WebAssembly::ExprType::Exnref)
-        .Case("void", WebAssembly::ExprType::Void)
-        .Default(WebAssembly::ExprType::Invalid);
+  WebAssembly::BlockType parseBlockType(StringRef ID) {
+    // Multivalue block types are handled separately in parseSignature
+    return StringSwitch<WebAssembly::BlockType>(ID)
+        .Case("i32", WebAssembly::BlockType::I32)
+        .Case("i64", WebAssembly::BlockType::I64)
+        .Case("f32", WebAssembly::BlockType::F32)
+        .Case("f64", WebAssembly::BlockType::F64)
+        .Case("v128", WebAssembly::BlockType::V128)
+        .Case("exnref", WebAssembly::BlockType::Exnref)
+        .Case("void", WebAssembly::BlockType::Void)
+        .Default(WebAssembly::BlockType::Invalid);
   }
 
   bool parseRegTypeList(SmallVectorImpl<wasm::ValType> &Types) {
@@ -416,7 +417,7 @@ public:
   }
 
   void addBlockTypeOperand(OperandVector &Operands, SMLoc NameLoc,
-                           WebAssembly::ExprType BT) {
+                           WebAssembly::BlockType BT) {
     Operands.push_back(std::make_unique<WebAssemblyOperand>(
         WebAssemblyOperand::Integer, NameLoc, NameLoc,
         WebAssemblyOperand::IntOp{static_cast<int64_t>(BT)}));
@@ -456,6 +457,7 @@ public:
     // If this instruction is part of a control flow structure, ensure
     // proper nesting.
     bool ExpectBlockType = false;
+    bool ExpectFuncType = false;
     if (Name == "block") {
       push(Block);
       ExpectBlockType = true;
@@ -494,6 +496,10 @@ public:
       if (pop(Name, Function) || ensureEmptyNestingStack())
         return true;
     } else if (Name == "call_indirect" || Name == "return_call_indirect") {
+      ExpectFuncType = true;
+    }
+
+    if (ExpectFuncType || (ExpectBlockType && Lexer.is(AsmToken::LParen))) {
       // This has a special TYPEINDEX operand which in text we
       // represent as a signature, such that we can re-build this signature,
       // attach it to an anonymous symbol, which is what WasmObjectWriter
@@ -502,6 +508,8 @@ public:
       auto Signature = std::make_unique<wasm::WasmSignature>();
       if (parseSignature(Signature.get()))
         return true;
+      // Got signature as block type, don't need more
+      ExpectBlockType = false;
       auto &Ctx = getStreamer().getContext();
       // The "true" here will cause this to be a nameless symbol.
       MCSymbol *Sym = Ctx.createTempSymbol("typeindex", true);
@@ -526,7 +534,7 @@ public:
         if (ExpectBlockType) {
           // Assume this identifier is a block_type.
           auto BT = parseBlockType(Id.getString());
-          if (BT == WebAssembly::ExprType::Invalid)
+          if (BT == WebAssembly::BlockType::Invalid)
             return error("Unknown block type: ", Id);
           addBlockTypeOperand(Operands, NameLoc, BT);
           Parser.Lex();
@@ -594,7 +602,7 @@ public:
     }
     if (ExpectBlockType && Operands.size() == 1) {
       // Support blocks with no operands as default to void.
-      addBlockTypeOperand(Operands, NameLoc, WebAssembly::ExprType::Void);
+      addBlockTypeOperand(Operands, NameLoc, WebAssembly::BlockType::Void);
     }
     Parser.Lex();
     return false;

Modified: llvm/trunk/lib/Target/WebAssembly/Disassembler/LLVMBuild.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/WebAssembly/Disassembler/LLVMBuild.txt?rev=374933&r1=374932&r2=374933&view=diff
==============================================================================
--- llvm/trunk/lib/Target/WebAssembly/Disassembler/LLVMBuild.txt (original)
+++ llvm/trunk/lib/Target/WebAssembly/Disassembler/LLVMBuild.txt Tue Oct 15 11:28:22 2019
@@ -18,5 +18,5 @@
 type = Library
 name = WebAssemblyDisassembler
 parent = WebAssembly
-required_libraries = WebAssemblyDesc MCDisassembler WebAssemblyInfo Support
+required_libraries = WebAssemblyDesc MCDisassembler WebAssemblyInfo Support MC
 add_to_library_groups = WebAssembly

Modified: llvm/trunk/lib/Target/WebAssembly/Disassembler/WebAssemblyDisassembler.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/WebAssembly/Disassembler/WebAssemblyDisassembler.cpp?rev=374933&r1=374932&r2=374933&view=diff
==============================================================================
--- llvm/trunk/lib/Target/WebAssembly/Disassembler/WebAssemblyDisassembler.cpp (original)
+++ llvm/trunk/lib/Target/WebAssembly/Disassembler/WebAssemblyDisassembler.cpp Tue Oct 15 11:28:22 2019
@@ -24,6 +24,7 @@
 #include "llvm/MC/MCInstrInfo.h"
 #include "llvm/MC/MCSubtargetInfo.h"
 #include "llvm/MC/MCSymbol.h"
+#include "llvm/MC/MCSymbolWasm.h"
 #include "llvm/Support/Endian.h"
 #include "llvm/Support/LEB128.h"
 #include "llvm/Support/TargetRegistry.h"
@@ -213,10 +214,29 @@ MCDisassembler::DecodeStatus WebAssembly
         return MCDisassembler::Fail;
       break;
     }
-    // block_type operands (uint8_t).
+    // block_type operands:
     case WebAssembly::OPERAND_SIGNATURE: {
-      if (!parseImmediate<uint8_t>(MI, Size, Bytes))
+      int64_t Val;
+      uint64_t PrevSize = Size;
+      if (!nextLEB(Val, Bytes, Size, true))
         return MCDisassembler::Fail;
+      if (Val < 0) {
+        // Negative values are single septet value types or empty types
+        if (Size != PrevSize + 1) {
+          MI.addOperand(
+              MCOperand::createImm(int64_t(WebAssembly::BlockType::Invalid)));
+        } else {
+          MI.addOperand(MCOperand::createImm(Val & 0x7f));
+        }
+      } else {
+        // We don't have access to the signature, so create a symbol without one
+        MCSymbol *Sym = getContext().createTempSymbol("typeindex", true);
+        auto *WasmSym = cast<MCSymbolWasm>(Sym);
+        WasmSym->setType(wasm::WASM_SYMBOL_TYPE_FUNCTION);
+        const MCExpr *Expr = MCSymbolRefExpr::create(
+            WasmSym, MCSymbolRefExpr::VK_WASM_TYPEINDEX, getContext());
+        MI.addOperand(MCOperand::createExpr(Expr));
+      }
       break;
     }
     // FP operands.

Modified: llvm/trunk/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyInstPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyInstPrinter.cpp?rev=374933&r1=374932&r2=374933&view=diff
==============================================================================
--- llvm/trunk/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyInstPrinter.cpp (original)
+++ llvm/trunk/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyInstPrinter.cpp Tue Oct 15 11:28:22 2019
@@ -272,9 +272,21 @@ void WebAssemblyInstPrinter::printWebAss
 void WebAssemblyInstPrinter::printWebAssemblySignatureOperand(const MCInst *MI,
                                                               unsigned OpNo,
                                                               raw_ostream &O) {
-  auto Imm = static_cast<unsigned>(MI->getOperand(OpNo).getImm());
-  if (Imm != wasm::WASM_TYPE_NORESULT)
-    O << WebAssembly::anyTypeToString(Imm);
+  const MCOperand &Op = MI->getOperand(OpNo);
+  if (Op.isImm()) {
+    auto Imm = static_cast<unsigned>(Op.getImm());
+    if (Imm != wasm::WASM_TYPE_NORESULT)
+      O << WebAssembly::anyTypeToString(Imm);
+  } else {
+    auto Expr = cast<MCSymbolRefExpr>(Op.getExpr());
+    auto *Sym = cast<MCSymbolWasm>(&Expr->getSymbol());
+    if (Sym->getSignature()) {
+      O << WebAssembly::signatureToString(Sym->getSignature());
+    } else {
+      // Disassembler does not currently produce a signature
+      O << "unknown_type";
+    }
+  }
 }
 
 // We have various enums representing a subset of these types, use this

Modified: llvm/trunk/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCCodeEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCCodeEmitter.cpp?rev=374933&r1=374932&r2=374933&view=diff
==============================================================================
--- llvm/trunk/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCCodeEmitter.cpp (original)
+++ llvm/trunk/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCCodeEmitter.cpp Tue Oct 15 11:28:22 2019
@@ -152,6 +152,7 @@ void WebAssemblyMCCodeEmitter::encodeIns
         break;
       case WebAssembly::OPERAND_FUNCTION32:
       case WebAssembly::OPERAND_OFFSET32:
+      case WebAssembly::OPERAND_SIGNATURE:
       case WebAssembly::OPERAND_TYPEINDEX:
       case WebAssembly::OPERAND_GLOBAL:
       case WebAssembly::OPERAND_EVENT:

Modified: llvm/trunk/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h?rev=374933&r1=374932&r2=374933&view=diff
==============================================================================
--- llvm/trunk/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h (original)
+++ llvm/trunk/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h Tue Oct 15 11:28:22 2019
@@ -122,16 +122,22 @@ enum TOF {
 namespace llvm {
 namespace WebAssembly {
 
-/// This is used to indicate block signatures.
-enum class ExprType : unsigned {
+/// Used as immediate MachineOperands for block signatures
+enum class BlockType : unsigned {
+  Invalid = 0x00,
   Void = 0x40,
-  I32 = 0x7F,
-  I64 = 0x7E,
-  F32 = 0x7D,
-  F64 = 0x7C,
-  V128 = 0x7B,
-  Exnref = 0x68,
-  Invalid = 0x00
+  I32 = unsigned(wasm::ValType::I32),
+  I64 = unsigned(wasm::ValType::I64),
+  F32 = unsigned(wasm::ValType::F32),
+  F64 = unsigned(wasm::ValType::F64),
+  V128 = unsigned(wasm::ValType::V128),
+  Exnref = unsigned(wasm::ValType::EXNREF),
+  // Multivalue blocks (and other non-void blocks) are only emitted when the
+  // blocks will never be exited and are at the ends of functions (see
+  // WebAssemblyCFGStackify::fixEndsAtEndOfFunction). They also are never made
+  // to pop values off the stack, so the exact multivalue signature can always
+  // be inferred from the return type of the parent function in MCInstLower.
+  Multivalue = 0xffff,
 };
 
 /// Instruction opcodes emitted via means other than CodeGen.

Modified: llvm/trunk/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp?rev=374933&r1=374932&r2=374933&view=diff
==============================================================================
--- llvm/trunk/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp (original)
+++ llvm/trunk/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp Tue Oct 15 11:28:22 2019
@@ -315,12 +315,12 @@ void WebAssemblyCFGStackify::placeBlockM
   //   br_on_exn 0, $__cpp_exception
   //   rethrow
   // end_block
-  WebAssembly::ExprType ReturnType = WebAssembly::ExprType::Void;
+  WebAssembly::BlockType ReturnType = WebAssembly::BlockType::Void;
   if (IsBrOnExn) {
     const char *TagName = BrOnExn->getOperand(1).getSymbolName();
     if (std::strcmp(TagName, "__cpp_exception") != 0)
       llvm_unreachable("Only C++ exception is supported");
-    ReturnType = WebAssembly::ExprType::I32;
+    ReturnType = WebAssembly::BlockType::I32;
   }
 
   auto InsertPos = getLatestInsertPos(Header, BeforeSet, AfterSet);
@@ -406,7 +406,7 @@ void WebAssemblyCFGStackify::placeLoopMa
   auto InsertPos = getEarliestInsertPos(&MBB, BeforeSet, AfterSet);
   MachineInstr *Begin = BuildMI(MBB, InsertPos, MBB.findDebugLoc(InsertPos),
                                 TII.get(WebAssembly::LOOP))
-                            .addImm(int64_t(WebAssembly::ExprType::Void));
+                            .addImm(int64_t(WebAssembly::BlockType::Void));
 
   // Decide where in Header to put the END_LOOP.
   BeforeSet.clear();
@@ -575,7 +575,7 @@ void WebAssemblyCFGStackify::placeTryMar
   MachineInstr *Begin =
       BuildMI(*Header, InsertPos, Header->findDebugLoc(InsertPos),
               TII.get(WebAssembly::TRY))
-          .addImm(int64_t(WebAssembly::ExprType::Void));
+          .addImm(int64_t(WebAssembly::BlockType::Void));
 
   // Decide where in Header to put the END_TRY.
   BeforeSet.clear();
@@ -1129,7 +1129,7 @@ bool WebAssemblyCFGStackify::fixUnwindMi
       MachineInstr *NestedTry =
           BuildMI(*MBB, *RangeBegin, RangeBegin->getDebugLoc(),
                   TII.get(WebAssembly::TRY))
-              .addImm(int64_t(WebAssembly::ExprType::Void));
+              .addImm(int64_t(WebAssembly::BlockType::Void));
 
       // Create the nested EH pad and fill instructions in.
       MachineBasicBlock *NestedEHPad = MF.CreateMachineBasicBlock();
@@ -1231,54 +1231,28 @@ void WebAssemblyCFGStackify::fixEndsAtEn
   if (MFI.getResults().empty())
     return;
 
-  // TODO: Generalize from value types to function types for multivalue
-  WebAssembly::ExprType RetType;
-  switch (MFI.getResults().front().SimpleTy) {
-  case MVT::i32:
-    RetType = WebAssembly::ExprType::I32;
-    break;
-  case MVT::i64:
-    RetType = WebAssembly::ExprType::I64;
-    break;
-  case MVT::f32:
-    RetType = WebAssembly::ExprType::F32;
-    break;
-  case MVT::f64:
-    RetType = WebAssembly::ExprType::F64;
-    break;
-  case MVT::v16i8:
-  case MVT::v8i16:
-  case MVT::v4i32:
-  case MVT::v2i64:
-  case MVT::v4f32:
-  case MVT::v2f64:
-    RetType = WebAssembly::ExprType::V128;
-    break;
-  case MVT::exnref:
-    RetType = WebAssembly::ExprType::Exnref;
-    break;
-  default:
-    llvm_unreachable("unexpected return type");
-  }
+  // MCInstLower will add the proper types to multivalue signatures based on the
+  // function return type
+  WebAssembly::BlockType RetType =
+      MFI.getResults().size() > 1
+          ? WebAssembly::BlockType::Multivalue
+          : WebAssembly::BlockType(
+                WebAssembly::toValType(MFI.getResults().front()));
 
   for (MachineBasicBlock &MBB : reverse(MF)) {
     for (MachineInstr &MI : reverse(MBB)) {
       if (MI.isPosition() || MI.isDebugInstr())
         continue;
-      if (MI.getOpcode() == WebAssembly::END_BLOCK) {
-        if (MFI.getResults().size() > 1)
-          report_fatal_error("Multivalue block signatures not implemented yet");
-        EndToBegin[&MI]->getOperand(0).setImm(int32_t(RetType));
-        continue;
-      }
-      if (MI.getOpcode() == WebAssembly::END_LOOP) {
-        if (MFI.getResults().size() > 1)
-          report_fatal_error("Multivalue loop signatures not implemented yet");
+      switch (MI.getOpcode()) {
+      case WebAssembly::END_BLOCK:
+      case WebAssembly::END_LOOP:
+      case WebAssembly::END_TRY:
         EndToBegin[&MI]->getOperand(0).setImm(int32_t(RetType));
         continue;
+      default:
+        // Something other than an `end`. We're done.
+        return;
       }
-      // Something other than an `end`. We're done.
-      return;
     }
   }
 }

Modified: llvm/trunk/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp?rev=374933&r1=374932&r2=374933&view=diff
==============================================================================
--- llvm/trunk/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp (original)
+++ llvm/trunk/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp Tue Oct 15 11:28:22 2019
@@ -163,6 +163,21 @@ MCOperand WebAssemblyMCInstLower::lowerS
   return MCOperand::createExpr(Expr);
 }
 
+MCOperand WebAssemblyMCInstLower::lowerTypeIndexOperand(
+    SmallVector<wasm::ValType, 1> &&Returns,
+    SmallVector<wasm::ValType, 4> &&Params) const {
+  auto Signature = std::make_unique<wasm::WasmSignature>(std::move(Returns),
+                                                         std::move(Params));
+  MCSymbol *Sym = Printer.createTempSymbol("typeindex");
+  auto *WasmSym = cast<MCSymbolWasm>(Sym);
+  WasmSym->setSignature(Signature.get());
+  Printer.addSignature(std::move(Signature));
+  WasmSym->setType(wasm::WASM_SYMBOL_TYPE_FUNCTION);
+  const MCExpr *Expr =
+      MCSymbolRefExpr::create(WasmSym, MCSymbolRefExpr::VK_WASM_TYPEINDEX, Ctx);
+  return MCOperand::createExpr(Expr);
+}
+
 // Return the WebAssembly type associated with the given register class.
 static wasm::ValType getType(const TargetRegisterClass *RC) {
   if (RC == &WebAssembly::I32RegClass)
@@ -178,6 +193,16 @@ static wasm::ValType getType(const Targe
   llvm_unreachable("Unexpected register class");
 }
 
+static void getFunctionReturns(const MachineInstr *MI,
+                               SmallVectorImpl<wasm::ValType> &Returns) {
+  const Function &F = MI->getMF()->getFunction();
+  const TargetMachine &TM = MI->getMF()->getTarget();
+  Type *RetTy = F.getReturnType();
+  SmallVector<MVT, 4> CallerRetTys;
+  computeLegalValueVTs(F, TM, RetTy, CallerRetTys);
+  valTypesFromMVTs(CallerRetTys, Returns);
+}
+
 void WebAssemblyMCInstLower::lower(const MachineInstr *MI,
                                    MCInst &OutMI) const {
   OutMI.setOpcode(MI->getOpcode());
@@ -208,8 +233,6 @@ void WebAssemblyMCInstLower::lower(const
       if (I < Desc.NumOperands) {
         const MCOperandInfo &Info = Desc.OpInfo[I];
         if (Info.OperandType == WebAssembly::OPERAND_TYPEINDEX) {
-          MCSymbol *Sym = Printer.createTempSymbol("typeindex");
-
           SmallVector<wasm::ValType, 4> Returns;
           SmallVector<wasm::ValType, 4> Params;
 
@@ -228,26 +251,21 @@ void WebAssemblyMCInstLower::lower(const
 
           // return_call_indirect instructions have the return type of the
           // caller
-          if (MI->getOpcode() == WebAssembly::RET_CALL_INDIRECT) {
-            const Function &F = MI->getMF()->getFunction();
-            const TargetMachine &TM = MI->getMF()->getTarget();
-            Type *RetTy = F.getReturnType();
-            SmallVector<MVT, 4> CallerRetTys;
-            computeLegalValueVTs(F, TM, RetTy, CallerRetTys);
-            valTypesFromMVTs(CallerRetTys, Returns);
-          }
+          if (MI->getOpcode() == WebAssembly::RET_CALL_INDIRECT)
+            getFunctionReturns(MI, Returns);
 
-          auto *WasmSym = cast<MCSymbolWasm>(Sym);
-          auto Signature = std::make_unique<wasm::WasmSignature>(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(
-              WasmSym, MCSymbolRefExpr::VK_WASM_TYPEINDEX, Ctx);
-          MCOp = MCOperand::createExpr(Expr);
+          MCOp = lowerTypeIndexOperand(std::move(Returns), std::move(Params));
           break;
+        } else if (Info.OperandType == WebAssembly::OPERAND_SIGNATURE) {
+          auto BT = static_cast<WebAssembly::BlockType>(MO.getImm());
+          assert(BT != WebAssembly::BlockType::Invalid);
+          if (BT == WebAssembly::BlockType::Multivalue) {
+            SmallVector<wasm::ValType, 1> Returns;
+            getFunctionReturns(MI, Returns);
+            MCOp = lowerTypeIndexOperand(std::move(Returns),
+                                         SmallVector<wasm::ValType, 4>());
+            break;
+          }
         }
       }
       MCOp = MCOperand::createImm(MO.getImm());

Modified: llvm/trunk/lib/Target/WebAssembly/WebAssemblyMCInstLower.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/WebAssembly/WebAssemblyMCInstLower.h?rev=374933&r1=374932&r2=374933&view=diff
==============================================================================
--- llvm/trunk/lib/Target/WebAssembly/WebAssemblyMCInstLower.h (original)
+++ llvm/trunk/lib/Target/WebAssembly/WebAssemblyMCInstLower.h Tue Oct 15 11:28:22 2019
@@ -15,6 +15,7 @@
 #ifndef LLVM_LIB_TARGET_WEBASSEMBLY_WEBASSEMBLYMCINSTLOWER_H
 #define LLVM_LIB_TARGET_WEBASSEMBLY_WEBASSEMBLYMCINSTLOWER_H
 
+#include "llvm/BinaryFormat/Wasm.h"
 #include "llvm/MC/MCInst.h"
 #include "llvm/Support/Compiler.h"
 
@@ -33,6 +34,8 @@ class LLVM_LIBRARY_VISIBILITY WebAssembl
   MCSymbol *GetGlobalAddressSymbol(const MachineOperand &MO) const;
   MCSymbol *GetExternalSymbolSymbol(const MachineOperand &MO) const;
   MCOperand lowerSymbolOperand(const MachineOperand &MO, MCSymbol *Sym) const;
+  MCOperand lowerTypeIndexOperand(SmallVector<wasm::ValType, 1> &&,
+                                  SmallVector<wasm::ValType, 4> &&) const;
 
 public:
   WebAssemblyMCInstLower(MCContext &ctx, WebAssemblyAsmPrinter &printer)

Modified: llvm/trunk/test/CodeGen/WebAssembly/multivalue.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/WebAssembly/multivalue.ll?rev=374933&r1=374932&r2=374933&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/WebAssembly/multivalue.ll (original)
+++ llvm/trunk/test/CodeGen/WebAssembly/multivalue.ll Tue Oct 15 11:28:22 2019
@@ -1,7 +1,7 @@
 ; RUN: llc < %s -asm-verbose=false -verify-machineinstrs -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -mattr=+multivalue | FileCheck %s
 
-; Test that the multivalue attribute is accepted
-; TODO(tlively): implement multivalue
+; Test that the multivalue returns, function types, and block types
+; work as expected.
 
 target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
 target triple = "wasm32-unknown-unknown"
@@ -10,19 +10,33 @@ target triple = "wasm32-unknown-unknown"
 %packed_pair = type <{ i32, i32 }>
 
 ; CHECK-LABEL: pair_ident:
-; CHECK-NEXT: pair_ident (i32, i32) -> (i32, i32)
+; CHECK-NEXT: .functype pair_ident (i32, i32) -> (i32, i32)
 ; CHECK-NEXT: return $0, $1{{$}}
 define %pair @pair_ident(%pair %p) {
   ret %pair %p
 }
 
 ; CHECK-LABEL: packed_pair_ident:
-; CHECK-NEXT: packed_pair_ident (i32, i32) -> (i32, i32)
-; CHECK-nEXT: return $0, $1{{$}}
+; CHECK-NEXT: .functype packed_pair_ident (i32, i32) -> (i32, i32)
+; CHECK-NEXT: return $0, $1{{$}}
 define %packed_pair @packed_pair_ident(%packed_pair %p) {
   ret %packed_pair %p
 }
 
+; CHECK-LABEL: minimal_loop:
+; CHECK-NEXT: .functype minimal_loop (i32) -> (i32, i64)
+; CHECK-NEXT: .LBB{{[0-9]+}}_1:
+; CHECK-NEXT: loop () -> (i32, i64)
+; CHECK-NEXT: br 0{{$}}
+; CHECK-NEXT: .LBB{{[0-9]+}}_2:
+; CHECK-NEXT: end_loop{{$}}
+define {i32, i64} @minimal_loop(i32* %p) {
+entry:
+  br label %loop
+loop:
+  br label %loop
+}
+
 ; CHECK-LABEL: .section .custom_section.target_features
 ; CHECK-NEXT: .int8 1
 ; CHECK-NEXT: .int8 43

Modified: llvm/trunk/test/MC/Disassembler/WebAssembly/wasm-error.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/WebAssembly/wasm-error.txt?rev=374933&r1=374932&r2=374933&view=diff
==============================================================================
--- llvm/trunk/test/MC/Disassembler/WebAssembly/wasm-error.txt (original)
+++ llvm/trunk/test/MC/Disassembler/WebAssembly/wasm-error.txt Tue Oct 15 11:28:22 2019
@@ -2,8 +2,11 @@
 
 # CHECK: .text
 
-# CHECK: block invalid_type
+# CHECK: block unknown_type
 0x02 0x00
 
+# CHECK: block invalid_type
+0x02 0xff 0x42
+
 # CHECK: br 16 # Invalid depth argument!
 0x0C 0x10

Modified: llvm/trunk/test/MC/WebAssembly/basic-assembly.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/WebAssembly/basic-assembly.s?rev=374933&r1=374932&r2=374933&view=diff
==============================================================================
--- llvm/trunk/test/MC/WebAssembly/basic-assembly.s (original)
+++ llvm/trunk/test/MC/WebAssembly/basic-assembly.s Tue Oct 15 11:28:22 2019
@@ -55,6 +55,12 @@ test0:
     block       i64
     block       f32
     block       f64
+    block       () -> (i32, i32)
+    i32.const   1
+    i32.const   2
+    end_block
+    drop
+    drop
     br_table {0, 1, 2}   # 2 entries, default
     end_block            # first entry jumps here.
     i32.const   1
@@ -162,6 +168,12 @@ test0:
 # CHECK-NEXT:      block       i64
 # CHECK-NEXT:      block       f32
 # CHECK-NEXT:      block       f64
+# CHECK-NEXT:      block       () -> (i32, i32)
+# CHECK-NEXT:      i32.const   1
+# CHECK-NEXT:      i32.const   2
+# CHECK-NEXT:      end_block
+# CHECK-NEXT:      drop
+# CHECK-NEXT:      drop
 # CHECK-NEXT:      br_table {0, 1, 2}  # 1: down to label4
 # CHECK-NEXT:                          # 2: down to label3
 # CHECK-NEXT:      end_block           # label5:

Modified: llvm/trunk/tools/llvm-mc/Disassembler.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-mc/Disassembler.cpp?rev=374933&r1=374932&r2=374933&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-mc/Disassembler.cpp (original)
+++ llvm/trunk/tools/llvm-mc/Disassembler.cpp Tue Oct 15 11:28:22 2019
@@ -17,6 +17,7 @@
 #include "llvm/MC/MCContext.h"
 #include "llvm/MC/MCDisassembler/MCDisassembler.h"
 #include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCObjectFileInfo.h"
 #include "llvm/MC/MCRegisterInfo.h"
 #include "llvm/MC/MCStreamer.h"
 #include "llvm/MC/MCSubtargetInfo.h"
@@ -129,13 +130,10 @@ static bool ByteArrayFromString(ByteArra
   return false;
 }
 
-int Disassembler::disassemble(const Target &T,
-                              const std::string &Triple,
-                              MCSubtargetInfo &STI,
-                              MCStreamer &Streamer,
-                              MemoryBuffer &Buffer,
-                              SourceMgr &SM,
-                              raw_ostream &Out) {
+int Disassembler::disassemble(const Target &T, const std::string &Triple,
+                              MCSubtargetInfo &STI, MCStreamer &Streamer,
+                              MemoryBuffer &Buffer, SourceMgr &SM,
+                              MCContext &Ctx, raw_ostream &Out) {
 
   std::unique_ptr<const MCRegisterInfo> MRI(T.createMCRegInfo(Triple));
   if (!MRI) {
@@ -149,9 +147,6 @@ int Disassembler::disassemble(const Targ
     return -1;
   }
 
-  // Set up the MCContext for creating symbols and MCExpr's.
-  MCContext Ctx(MAI.get(), MRI.get(), nullptr);
-
   std::unique_ptr<const MCDisassembler> DisAsm(
     T.createMCDisassembler(STI, Ctx));
   if (!DisAsm) {

Modified: llvm/trunk/tools/llvm-mc/Disassembler.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-mc/Disassembler.h?rev=374933&r1=374932&r2=374933&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-mc/Disassembler.h (original)
+++ llvm/trunk/tools/llvm-mc/Disassembler.h Tue Oct 15 11:28:22 2019
@@ -22,17 +22,15 @@ class MemoryBuffer;
 class Target;
 class raw_ostream;
 class SourceMgr;
+class MCContext;
 class MCSubtargetInfo;
 class MCStreamer;
 
 class Disassembler {
 public:
-  static int disassemble(const Target &T,
-                         const std::string &Triple,
-                         MCSubtargetInfo &STI,
-                         MCStreamer &Streamer,
-                         MemoryBuffer &Buffer,
-                         SourceMgr &SM,
+  static int disassemble(const Target &T, const std::string &Triple,
+                         MCSubtargetInfo &STI, MCStreamer &Streamer,
+                         MemoryBuffer &Buffer, SourceMgr &SM, MCContext &Ctx,
                          raw_ostream &Out);
 };
 

Modified: llvm/trunk/tools/llvm-mc/llvm-mc.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-mc/llvm-mc.cpp?rev=374933&r1=374932&r2=374933&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-mc/llvm-mc.cpp (original)
+++ llvm/trunk/tools/llvm-mc/llvm-mc.cpp Tue Oct 15 11:28:22 2019
@@ -517,8 +517,8 @@ int main(int argc, char **argv) {
     break;
   }
   if (disassemble)
-    Res = Disassembler::disassemble(*TheTarget, TripleName, *STI, *Str,
-                                    *Buffer, SrcMgr, Out->os());
+    Res = Disassembler::disassemble(*TheTarget, TripleName, *STI, *Str, *Buffer,
+                                    SrcMgr, Ctx, Out->os());
 
   // Keep output if no errors.
   if (Res == 0) {




More information about the llvm-commits mailing list