[llvm] r285040 - [WebAssembly] Implement more WebAssembly binary encoding.

Dan Gohman via llvm-commits llvm-commits at lists.llvm.org
Mon Oct 24 16:27:50 PDT 2016


Author: djg
Date: Mon Oct 24 18:27:49 2016
New Revision: 285040

URL: http://llvm.org/viewvc/llvm-project?rev=285040&view=rev
Log:
[WebAssembly] Implement more WebAssembly binary encoding.

This changes locals from being declared by the emitLocal hook in
WebAssemblyTargetStreamer, rather than with an instruction. After exploring
the infastructure in LLVM more, this seems to make more sense since
declaring locals doesn't use an encoded opcode.

This also adds more 0xd opcodes, type encodings, and miscellaneous
binary encoding bits.

Modified:
    llvm/trunk/lib/Target/WebAssembly/InstPrinter/WebAssemblyInstPrinter.cpp
    llvm/trunk/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyAsmBackend.cpp
    llvm/trunk/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCCodeEmitter.cpp
    llvm/trunk/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.cpp
    llvm/trunk/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h
    llvm/trunk/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp
    llvm/trunk/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.h
    llvm/trunk/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
    llvm/trunk/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp
    llvm/trunk/lib/Target/WebAssembly/WebAssemblyExplicitLocals.cpp
    llvm/trunk/lib/Target/WebAssembly/WebAssemblyInstrCall.td
    llvm/trunk/lib/Target/WebAssembly/WebAssemblyInstrControl.td
    llvm/trunk/lib/Target/WebAssembly/WebAssemblyInstrFloat.td
    llvm/trunk/lib/Target/WebAssembly/WebAssemblyInstrInfo.td
    llvm/trunk/lib/Target/WebAssembly/WebAssemblyInstrInteger.td
    llvm/trunk/lib/Target/WebAssembly/WebAssemblyMachineFunctionInfo.h

Modified: llvm/trunk/lib/Target/WebAssembly/InstPrinter/WebAssemblyInstPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/WebAssembly/InstPrinter/WebAssemblyInstPrinter.cpp?rev=285040&r1=285039&r2=285040&view=diff
==============================================================================
--- llvm/trunk/lib/Target/WebAssembly/InstPrinter/WebAssemblyInstPrinter.cpp (original)
+++ llvm/trunk/lib/Target/WebAssembly/InstPrinter/WebAssemblyInstPrinter.cpp Mon Oct 24 18:27:49 2016
@@ -154,22 +154,11 @@ void WebAssemblyInstPrinter::printOperan
             (Desc.TSFlags & WebAssemblyII::VariableOpIsImmediate)) &&
            "WebAssemblyII::VariableOpIsImmediate should be set for "
            "variable_ops immediate ops");
-
-    if (Desc.TSFlags & WebAssemblyII::VariableOpImmediateIsType) {
-      switch (Op.getImm()) {
-      case int64_t(WebAssembly::ValType::I32): O << "i32"; break;
-      case int64_t(WebAssembly::ValType::I64): O << "i64"; break;
-      case int64_t(WebAssembly::ValType::F32): O << "f32"; break;
-      case int64_t(WebAssembly::ValType::F64): O << "f64"; break;
-      default: llvm_unreachable("unknown local type");
-      }
-    } else {
-      // TODO: (MII.get(MI->getOpcode()).TSFlags &
-      //        WebAssemblyII::VariableOpImmediateIsLabel)
-      // can tell us whether this is an immediate referencing a label in the
-      // control flow stack, and it may be nice to pretty-print.
-      O << Op.getImm();
-    }
+    // TODO: (MII.get(MI->getOpcode()).TSFlags &
+    //        WebAssemblyII::VariableOpImmediateIsLabel)
+    // can tell us whether this is an immediate referencing a label in the
+    // control flow stack, and it may be nice to pretty-print.
+    O << Op.getImm();
   } else if (Op.isFPImm()) {
     const MCInstrDesc &Desc = MII.get(MI->getOpcode());
     assert(OpNo < Desc.getNumOperands() &&
@@ -220,9 +209,10 @@ WebAssemblyInstPrinter::printWebAssembly
   case WebAssembly::ExprType::I8x16: O << "i8x16"; break;
   case WebAssembly::ExprType::I16x8: O << "i16x8"; break;
   case WebAssembly::ExprType::I32x4: O << "i32x4"; break;
-  case WebAssembly::ExprType::I64x2: O << "i32x4"; break;
   case WebAssembly::ExprType::F32x4: O << "f32x4"; break;
-  case WebAssembly::ExprType::F64x2: O << "f64x2"; break;
+  case WebAssembly::ExprType::B8x16: O << "b8x16"; break;
+  case WebAssembly::ExprType::B16x8: O << "b16x8"; break;
+  case WebAssembly::ExprType::B32x4: O << "b32x4"; break;
   }
 }
 

Modified: llvm/trunk/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyAsmBackend.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyAsmBackend.cpp?rev=285040&r1=285039&r2=285040&view=diff
==============================================================================
--- llvm/trunk/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyAsmBackend.cpp (original)
+++ llvm/trunk/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyAsmBackend.cpp Mon Oct 24 18:27:49 2016
@@ -66,8 +66,10 @@ bool WebAssemblyAsmBackend::writeNopData
   if (Count == 0)
     return true;
 
-  // FIXME: Do something.
-  return false;
+  for (uint64_t i = 0; i < Count; ++i)
+    OW->write8(WebAssembly::Nop);
+
+  return true;
 }
 
 void WebAssemblyAsmBackend::applyFixup(const MCFixup &Fixup, char *Data,

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=285040&r1=285039&r2=285040&view=diff
==============================================================================
--- llvm/trunk/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCCodeEmitter.cpp (original)
+++ llvm/trunk/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCCodeEmitter.cpp Mon Oct 24 18:27:49 2016
@@ -60,7 +60,8 @@ void WebAssemblyMCCodeEmitter::encodeIns
   uint64_t Start = OS.tell();
 
   uint64_t Binary = getBinaryCodeForInstr(MI, Fixups, STI);
-  encodeULEB128(Binary, OS);
+  assert(Binary < UINT8_MAX && "Multi-byte opcodes not supported yet");
+  OS << uint8_t(Binary);
 
   const MCInstrDesc &Desc = MCII.get(MI.getOpcode());
   for (unsigned i = 0, e = MI.getNumOperands(); i < e; ++i) {
@@ -68,16 +69,20 @@ void WebAssemblyMCCodeEmitter::encodeIns
     if (MO.isReg()) {
       /* nothing to encode */
     } else if (MO.isImm()) {
-      assert(i < Desc.getNumOperands() &&
-             "Unexpected integer immediate as a non-fixed operand");
-      assert(Desc.TSFlags == 0 &&
-             "WebAssembly variable_ops integer ops don't use TSFlags");
-      const MCOperandInfo &Info = Desc.OpInfo[i];
-      if (Info.OperandType == WebAssembly::OPERAND_I32IMM) {
-        encodeSLEB128(int32_t(MO.getImm()), OS);
-      } else if (Info.OperandType == WebAssembly::OPERAND_I64IMM) {
-        encodeSLEB128(int64_t(MO.getImm()), OS);
+      if (i < Desc.getNumOperands()) {
+        assert(Desc.TSFlags == 0 &&
+               "WebAssembly non-variable_ops don't use TSFlags");
+        const MCOperandInfo &Info = Desc.OpInfo[i];
+        if (Info.OperandType == WebAssembly::OPERAND_I32IMM) {
+          encodeSLEB128(int32_t(MO.getImm()), OS);
+        } else if (Info.OperandType == WebAssembly::OPERAND_I64IMM) {
+          encodeSLEB128(int64_t(MO.getImm()), OS);
+        } else {
+          encodeULEB128(uint64_t(MO.getImm()), OS);
+        }
       } else {
+        assert(Desc.TSFlags == (WebAssemblyII::VariableOpIsImmediate |
+                                WebAssemblyII::VariableOpImmediateIsLabel));
         encodeULEB128(uint64_t(MO.getImm()), OS);
       }
     } else if (MO.isFPImm()) {

Modified: llvm/trunk/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.cpp?rev=285040&r1=285039&r2=285040&view=diff
==============================================================================
--- llvm/trunk/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.cpp (original)
+++ llvm/trunk/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.cpp Mon Oct 24 18:27:49 2016
@@ -134,3 +134,13 @@ extern "C" void LLVMInitializeWebAssembl
     TargetRegistry::RegisterAsmTargetStreamer(*T, createAsmTargetStreamer);
   }
 }
+
+WebAssembly::ValType WebAssembly::toValType(const MVT &Ty) {
+  switch (Ty.SimpleTy) {
+  case MVT::i32: return WebAssembly::ValType::I32;
+  case MVT::i64: return WebAssembly::ValType::I64;
+  case MVT::f32: return WebAssembly::ValType::F32;
+  case MVT::f64: return WebAssembly::ValType::F64;
+  default: llvm_unreachable("unexpected type");
+  }
+}

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=285040&r1=285039&r2=285040&view=diff
==============================================================================
--- llvm/trunk/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h (original)
+++ llvm/trunk/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h Mon Oct 24 18:27:49 2016
@@ -26,6 +26,7 @@ class MCContext;
 class MCInstrInfo;
 class MCObjectWriter;
 class MCSubtargetInfo;
+class MVT;
 class Target;
 class Triple;
 class raw_pwrite_stream;
@@ -59,17 +60,6 @@ enum OperandType {
   /// signature immediate for block/loop.
   OPERAND_SIGNATURE
 };
-
-/// WebAssembly-specific directive identifiers.
-enum Directive {
-  // FIXME: This is not the real binary encoding.
-  DotParam = UINT64_MAX - 0,   ///< .param
-  DotResult = UINT64_MAX - 1,  ///< .result
-  DotLocal = UINT64_MAX - 2,   ///< .local
-  DotEndFunc = UINT64_MAX - 3, ///< .endfunc
-  DotIndIdx = UINT64_MAX - 4,  ///< .indidx
-};
-
 } // end namespace WebAssembly
 
 namespace WebAssemblyII {
@@ -79,10 +69,7 @@ enum {
   VariableOpIsImmediate = (1 << 0),
   // For immediate values in the variable_ops range, this flag indicates
   // whether the value represents a control-flow label.
-  VariableOpImmediateIsLabel = (1 << 1),
-  // For immediate values in the variable_ops range, this flag indicates
-  // whether the value represents a ValType.
-  VariableOpImmediateIsType = (1 << 2),
+  VariableOpImmediateIsLabel = (1 << 1)
 };
 } // end namespace WebAssemblyII
 
@@ -150,33 +137,41 @@ static const unsigned StoreP2AlignOperan
 
 /// This is used to indicate block signatures.
 enum class ExprType {
-  Void = 0,
-  I32  = 1,
-  I64  = 2,
-  F32  = 3,
-  F64  = 4,
-  I8x16 = 5,
-  I16x8 = 6,
-  I32x4 = 7,
-  I64x2 = 8,
-  F32x4 = 9,
-  F64x2 = 10
+  Void    = 0x40,
+  I32     = 0x7f,
+  I64     = 0x7e,
+  F32     = 0x7d,
+  F64     = 0x7c,
+  I8x16   = 0x7b,
+  I16x8   = 0x7a,
+  I32x4   = 0x79,
+  F32x4   = 0x78,
+  B8x16   = 0x77,
+  B16x8   = 0x76,
+  B32x4   = 0x75
 };
 
 /// This is used to indicate local types.
 enum class ValType {
-  I32  = 1,
-  I64  = 2,
-  F32  = 3,
-  F64  = 4,
-  I8x16 = 5,
-  I16x8 = 6,
-  I32x4 = 7,
-  I64x2 = 8,
-  F32x4 = 9,
-  F64x2 = 10
+  I32     = 0x7f,
+  I64     = 0x7e,
+  F32     = 0x7d,
+  F64     = 0x7c,
+  I8x16   = 0x7b,
+  I16x8   = 0x7a,
+  I32x4   = 0x79,
+  F32x4   = 0x78,
+  B8x16   = 0x77,
+  B16x8   = 0x76,
+  B32x4   = 0x75
 };
 
+/// Instruction opcodes emitted via means other than CodeGen.
+static const unsigned Nop = 0x01;
+static const unsigned End = 0x0b;
+
+ValType toValType(const MVT &Ty);
+
 } // end namespace WebAssembly
 } // end namespace llvm
 

Modified: llvm/trunk/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp?rev=285040&r1=285039&r2=285040&view=diff
==============================================================================
--- llvm/trunk/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp (original)
+++ llvm/trunk/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp Mon Oct 24 18:27:49 2016
@@ -58,8 +58,10 @@ void WebAssemblyTargetAsmStreamer::emitR
 }
 
 void WebAssemblyTargetAsmStreamer::emitLocal(ArrayRef<MVT> Types) {
-  OS << "\t.local  \t";
-  PrintTypes(OS, Types);
+  if (!Types.empty()) {
+    OS << "\t.local  \t";
+    PrintTypes(OS, Types);
+  }
 }
 
 void WebAssemblyTargetAsmStreamer::emitEndFunc() { OS << "\t.endfunc\n"; }
@@ -82,34 +84,30 @@ void WebAssemblyTargetAsmStreamer::emitI
   OS << "\t.indidx  \t" << *Value << '\n';
 }
 
-// FIXME: What follows is not the real binary encoding.
-
-static void EncodeTypes(MCStreamer &Streamer, ArrayRef<MVT> Types) {
-  Streamer.EmitIntValue(Types.size(), sizeof(uint64_t));
-  for (MVT Type : Types)
-    Streamer.EmitIntValue(Type.SimpleTy, sizeof(uint64_t));
-}
-
 void WebAssemblyTargetELFStreamer::emitParam(ArrayRef<MVT> Types) {
-  Streamer.EmitIntValue(WebAssembly::DotParam, sizeof(uint64_t));
-  EncodeTypes(Streamer, Types);
+  // Nothing to emit; params are declared as part of the function signature.
 }
 
 void WebAssemblyTargetELFStreamer::emitResult(ArrayRef<MVT> Types) {
-  Streamer.EmitIntValue(WebAssembly::DotResult, sizeof(uint64_t));
-  EncodeTypes(Streamer, Types);
+  // Nothing to emit; results are declared as part of the function signature.
 }
 
 void WebAssemblyTargetELFStreamer::emitLocal(ArrayRef<MVT> Types) {
-  Streamer.EmitIntValue(WebAssembly::DotLocal, sizeof(uint64_t));
-  EncodeTypes(Streamer, Types);
+  Streamer.EmitULEB128IntValue(Types.size());
+  for (MVT Type : Types)
+    Streamer.EmitIntValue(int64_t(WebAssembly::toValType(Type)), 1);
 }
 
 void WebAssemblyTargetELFStreamer::emitEndFunc() {
-  Streamer.EmitIntValue(WebAssembly::DotEndFunc, sizeof(uint64_t));
+  Streamer.EmitIntValue(WebAssembly::End, 1);
 }
 
 void WebAssemblyTargetELFStreamer::emitIndIdx(const MCExpr *Value) {
-  Streamer.EmitIntValue(WebAssembly::DotIndIdx, sizeof(uint64_t));
-  Streamer.EmitValue(Value, sizeof(uint64_t));
+  llvm_unreachable(".indidx encoding not yet implemented");
+}
+
+void WebAssemblyTargetELFStreamer::emitIndirectFunctionType(
+    StringRef name, SmallVectorImpl<MVT> &Params, SmallVectorImpl<MVT> &Results) {
+  // Nothing to emit here. TODO: Re-design how linking works and re-evaluate
+  // whether it's necessary for .o files to declare indirect function types.
 }

Modified: llvm/trunk/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.h?rev=285040&r1=285039&r2=285040&view=diff
==============================================================================
--- llvm/trunk/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.h (original)
+++ llvm/trunk/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.h Mon Oct 24 18:27:49 2016
@@ -73,6 +73,9 @@ public:
   void emitResult(ArrayRef<MVT> Types) override;
   void emitLocal(ArrayRef<MVT> Types) override;
   void emitEndFunc() override;
+  void emitIndirectFunctionType(StringRef name,
+                                SmallVectorImpl<MVT> &Params,
+                                SmallVectorImpl<MVT> &Results) override;
   void emitIndIdx(const MCExpr *Value) override;
 };
 

Modified: llvm/trunk/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp?rev=285040&r1=285039&r2=285040&view=diff
==============================================================================
--- llvm/trunk/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp (original)
+++ llvm/trunk/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp Mon Oct 24 18:27:49 2016
@@ -42,7 +42,7 @@ namespace {
 
 class WebAssemblyAsmPrinter final : public AsmPrinter {
   const MachineRegisterInfo *MRI;
-  const WebAssemblyFunctionInfo *MFI;
+  WebAssemblyFunctionInfo *MFI;
 
 public:
   WebAssemblyAsmPrinter(TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer)
@@ -166,8 +166,8 @@ void WebAssemblyAsmPrinter::EmitFunction
   if (ResultVTs.size() == 1)
     getTargetStreamer()->emitResult(ResultVTs);
 
-  bool AnyWARegs = false;
-  SmallVector<MVT, 16> LocalTypes;
+  // FIXME: When ExplicitLocals is enabled by default, we won't need
+  // to define the locals here (and MFI can go back to being pointer-to-const).
   for (unsigned Idx = 0, IdxE = MRI->getNumVirtRegs(); Idx != IdxE; ++Idx) {
     unsigned VReg = TargetRegisterInfo::index2VirtReg(Idx);
     unsigned WAReg = MFI->getWAReg(VReg);
@@ -180,11 +180,10 @@ void WebAssemblyAsmPrinter::EmitFunction
     // Don't declare stackified registers.
     if (int(WAReg) < 0)
       continue;
-    LocalTypes.push_back(getRegType(VReg));
-    AnyWARegs = true;
+    MFI->addLocal(getRegType(VReg));
   }
-  if (AnyWARegs)
-    getTargetStreamer()->emitLocal(LocalTypes);
+
+  getTargetStreamer()->emitLocal(MFI->getLocals());
 
   AsmPrinter::EmitFunctionBodyStart();
 }

Modified: llvm/trunk/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp?rev=285040&r1=285039&r2=285040&view=diff
==============================================================================
--- llvm/trunk/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp (original)
+++ llvm/trunk/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp Mon Oct 24 18:27:49 2016
@@ -466,9 +466,7 @@ static void FixEndsAtEndOfFunction(
   case MVT::v16i8: retType = WebAssembly::ExprType::I8x16; break;
   case MVT::v8i16: retType = WebAssembly::ExprType::I16x8; break;
   case MVT::v4i32: retType = WebAssembly::ExprType::I32x4; break;
-  case MVT::v2i64: retType = WebAssembly::ExprType::I64x2; break;
   case MVT::v4f32: retType = WebAssembly::ExprType::F32x4; break;
-  case MVT::v2f64: retType = WebAssembly::ExprType::F64x2; break;
   default: llvm_unreachable("unexpected return type");
   }
 

Modified: llvm/trunk/lib/Target/WebAssembly/WebAssemblyExplicitLocals.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/WebAssembly/WebAssemblyExplicitLocals.cpp?rev=285040&r1=285039&r2=285040&view=diff
==============================================================================
--- llvm/trunk/lib/Target/WebAssembly/WebAssemblyExplicitLocals.cpp (original)
+++ llvm/trunk/lib/Target/WebAssembly/WebAssemblyExplicitLocals.cpp Mon Oct 24 18:27:49 2016
@@ -109,15 +109,15 @@ static unsigned getTeeLocalOpcode(const
 }
 
 /// Get the type associated with the given register class.
-static WebAssembly::ValType typeForRegClass(const TargetRegisterClass *RC) {
+static MVT typeForRegClass(const TargetRegisterClass *RC) {
   if (RC == &WebAssembly::I32RegClass)
-    return WebAssembly::ValType::I32;
+    return MVT::i32;
   if (RC == &WebAssembly::I64RegClass)
-    return WebAssembly::ValType::I64;
+    return MVT::i64;
   if (RC == &WebAssembly::F32RegClass)
-    return WebAssembly::ValType::F32;
+    return MVT::f32;
   if (RC == &WebAssembly::F64RegClass)
-    return WebAssembly::ValType::F64;
+    return MVT::f64;
   llvm_unreachable("unrecognized register class");
 }
 
@@ -272,21 +272,15 @@ bool WebAssemblyExplicitLocals::runOnMac
     }
   }
 
-  // Insert a .locals directive to declare the locals.
-  MachineInstrBuilder DeclareLocals;
+  // Define the locals.
   for (size_t i = 0, e = MRI.getNumVirtRegs(); i < e; ++i) {
     unsigned Reg = TargetRegisterInfo::index2VirtReg(i);
     auto I = Reg2Local.find(Reg);
     if (I == Reg2Local.end() || I->second < MFI.getParams().size())
       continue;
 
-    if (!DeclareLocals) {
-      DeclareLocals = BuildMI(*MF.begin(), MF.begin()->begin(), DebugLoc(),
-                              TII->get(WebAssembly::DECLARE_LOCALS));
-      Changed = true;
-    }
-
-    DeclareLocals.addImm(int64_t(typeForRegClass(MRI.getRegClass(Reg))));
+    MFI.addLocal(typeForRegClass(MRI.getRegClass(Reg)));
+    Changed = true;
   }
 
 #ifndef NDEBUG

Modified: llvm/trunk/lib/Target/WebAssembly/WebAssemblyInstrCall.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/WebAssembly/WebAssemblyInstrCall.td?rev=285040&r1=285039&r2=285040&view=diff
==============================================================================
--- llvm/trunk/lib/Target/WebAssembly/WebAssemblyInstrCall.td (original)
+++ llvm/trunk/lib/Target/WebAssembly/WebAssemblyInstrCall.td Mon Oct 24 18:27:49 2016
@@ -28,7 +28,8 @@ def ADJCALLSTACKUP : I<(outs), (ins i32i
 multiclass CALL<WebAssemblyRegClass vt, string prefix> {
   def CALL_#vt : I<(outs vt:$dst), (ins i32imm:$callee, variable_ops),
                    [(set vt:$dst, (WebAssemblycall1 (i32 imm:$callee)))],
-                   !strconcat(prefix, "call\t$dst, $callee")>;
+                   !strconcat(prefix, "call\t$dst, $callee"),
+                   0x10>;
   let isCodeGenOnly = 1 in {
     def PCALL_INDIRECT_#vt : I<(outs vt:$dst), (ins I32:$callee, variable_ops),
                               [(set vt:$dst, (WebAssemblycall1 I32:$callee))],
@@ -36,14 +37,16 @@ multiclass CALL<WebAssemblyRegClass vt,
   } // isCodeGenOnly = 1
   def CALL_INDIRECT_#vt : I<(outs vt:$dst), (ins variable_ops),
                             [],
-                            !strconcat(prefix, "call_indirect\t$dst")>;
+                            !strconcat(prefix, "call_indirect\t$dst"),
+                            0x11>;
 }
 
 multiclass SIMD_CALL<ValueType vt, string prefix> {
   def CALL_#vt : SIMD_I<(outs V128:$dst), (ins i32imm:$callee, variable_ops),
                          [(set (vt V128:$dst),
                                (WebAssemblycall1 (i32 imm:$callee)))],
-                         !strconcat(prefix, "call\t$dst, $callee")>;
+                         !strconcat(prefix, "call\t$dst, $callee"),
+                         0x10>;
   let isCodeGenOnly = 1 in {
     def PCALL_INDIRECT_#vt : SIMD_I<(outs V128:$dst),
                                     (ins I32:$callee, variable_ops),
@@ -54,7 +57,8 @@ multiclass SIMD_CALL<ValueType vt, strin
   def CALL_INDIRECT_#vt : SIMD_I<(outs V128:$dst),
                                   (ins variable_ops),
                                   [],
-                                  !strconcat(prefix, "call_indirect\t$dst")>;
+                                  !strconcat(prefix, "call_indirect\t$dst"),
+                                  0x11>;
 }
 
 let Uses = [SP32, SP64], isCall = 1 in {
@@ -69,7 +73,7 @@ let Uses = [SP32, SP64], isCall = 1 in {
 
   def CALL_VOID : I<(outs), (ins i32imm:$callee, variable_ops),
                     [(WebAssemblycall0 (i32 imm:$callee))],
-                    "call    \t$callee">;
+                    "call    \t$callee", 0x10>;
   let isCodeGenOnly = 1 in {
     def PCALL_INDIRECT_VOID : I<(outs), (ins I32:$callee, variable_ops),
                       [(WebAssemblycall0 I32:$callee)],
@@ -77,7 +81,7 @@ let Uses = [SP32, SP64], isCall = 1 in {
   } // isCodeGenOnly = 1
   def CALL_INDIRECT_VOID : I<(outs), (ins variable_ops),
                              [],
-                             "call_indirect\t">;
+                             "call_indirect\t", 0x11>;
 } // Uses = [SP32,SP64], isCall = 1
 
 } // Defs = [ARGUMENTS]

Modified: llvm/trunk/lib/Target/WebAssembly/WebAssemblyInstrControl.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/WebAssembly/WebAssemblyInstrControl.td?rev=285040&r1=285039&r2=285040&view=diff
==============================================================================
--- llvm/trunk/lib/Target/WebAssembly/WebAssemblyInstrControl.td (original)
+++ llvm/trunk/lib/Target/WebAssembly/WebAssemblyInstrControl.td Mon Oct 24 18:27:49 2016
@@ -65,13 +65,13 @@ def BLOCK     : I<(outs), (ins Signature
 def LOOP      : I<(outs), (ins Signature:$sig), [], "loop    \t$sig", 0x03>;
 
 // END_BLOCK and END_LOOP are represented with the same opcode in wasm.
-def END_BLOCK : I<(outs), (ins), [], "end_block", 0x0f>;
-def END_LOOP  : I<(outs), (ins), [], "end_loop", 0x0f>;
+def END_BLOCK : I<(outs), (ins), [], "end_block", 0x0b>;
+def END_LOOP  : I<(outs), (ins), [], "end_loop", 0x0b>;
 } // Uses = [VALUE_STACK], Defs = [VALUE_STACK]
 
 multiclass RETURN<WebAssemblyRegClass vt> {
   def RETURN_#vt : I<(outs), (ins vt:$val), [(WebAssemblyreturn vt:$val)],
-                     "return  \t$val">;
+                     "return  \t$val", 0x0f>;
   // Equivalent to RETURN_#vt, for use at the end of a function when wasm
   // semantics return by falling off the end of the block.
   let isCodeGenOnly = 1 in
@@ -81,7 +81,7 @@ multiclass RETURN<WebAssemblyRegClass vt
 multiclass SIMD_RETURN<ValueType vt> {
   def RETURN_#vt : SIMD_I<(outs), (ins V128:$val),
                           [(WebAssemblyreturn (vt V128:$val))],
-                          "return  \t$val">;
+                          "return  \t$val", 0x0f>;
   // Equivalent to RETURN_#vt, for use at the end of a function when wasm
   // semantics return by falling off the end of the block.
   let isCodeGenOnly = 1 in
@@ -100,14 +100,14 @@ let isReturn = 1 in {
   defm : SIMD_RETURN<v4i32>;
   defm : SIMD_RETURN<v4f32>;
 
-  def RETURN_VOID : I<(outs), (ins), [(WebAssemblyreturn)], "return">;
+  def RETURN_VOID : I<(outs), (ins), [(WebAssemblyreturn)], "return", 0x0f>;
 
   // This is to RETURN_VOID what FALLTHROUGH_RETURN_#vt is to RETURN_#vt.
   let isCodeGenOnly = 1 in
   def FALLTHROUGH_RETURN_VOID : I<(outs), (ins), []>;
 } // isReturn = 1
 
-def UNREACHABLE : I<(outs), (ins), [(trap)], "unreachable">;
+def UNREACHABLE : I<(outs), (ins), [(trap)], "unreachable", 0x00>;
 
 } // isTerminator = 1, hasCtrlDep = 1, isBarrier = 1
 

Modified: llvm/trunk/lib/Target/WebAssembly/WebAssemblyInstrFloat.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/WebAssembly/WebAssemblyInstrFloat.td?rev=285040&r1=285039&r2=285040&view=diff
==============================================================================
--- llvm/trunk/lib/Target/WebAssembly/WebAssemblyInstrFloat.td (original)
+++ llvm/trunk/lib/Target/WebAssembly/WebAssemblyInstrFloat.td Mon Oct 24 18:27:49 2016
@@ -79,10 +79,10 @@ let Defs = [ARGUMENTS] in {
 
 def SELECT_F32 : I<(outs F32:$dst), (ins F32:$lhs, F32:$rhs, I32:$cond),
                    [(set F32:$dst, (select I32:$cond, F32:$lhs, F32:$rhs))],
-                   "f32.select\t$dst, $lhs, $rhs, $cond">;
+                   "f32.select\t$dst, $lhs, $rhs, $cond", 0x1b>;
 def SELECT_F64 : I<(outs F64:$dst), (ins F64:$lhs, F64:$rhs, I32:$cond),
                    [(set F64:$dst, (select I32:$cond, F64:$lhs, F64:$rhs))],
-                   "f64.select\t$dst, $lhs, $rhs, $cond">;
+                   "f64.select\t$dst, $lhs, $rhs, $cond", 0x1b>;
 
 } // Defs = [ARGUMENTS]
 

Modified: llvm/trunk/lib/Target/WebAssembly/WebAssemblyInstrInfo.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/WebAssembly/WebAssemblyInstrInfo.td?rev=285040&r1=285039&r2=285040&view=diff
==============================================================================
--- llvm/trunk/lib/Target/WebAssembly/WebAssemblyInstrInfo.td (original)
+++ llvm/trunk/lib/Target/WebAssembly/WebAssemblyInstrInfo.td Mon Oct 24 18:27:49 2016
@@ -180,13 +180,6 @@ defm : LOCAL<F32>;
 defm : LOCAL<F64>;
 defm : LOCAL<V128>, Requires<[HasSIMD128]>;
 
-// Set TSFlags{0} to 1 to indicate that the variable_ops are immediates.
-// Set TSFlags{2} to 1 to indicate that the immediates are ValTypes.
-def DECLARE_LOCALS : I<(outs), (ins variable_ops), [], ".local  \t"> {
-  let TSFlags{0} = 1;
-  let TSFlags{2} = 1;
-}
-
 let isMoveImm = 1, isAsCheapAsAMove = 1, isReMaterializable = 1 in {
 def CONST_I32 : I<(outs I32:$res), (ins i32imm_op:$imm),
                   [(set I32:$res, imm:$imm)],

Modified: llvm/trunk/lib/Target/WebAssembly/WebAssemblyInstrInteger.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/WebAssembly/WebAssemblyInstrInteger.td?rev=285040&r1=285039&r2=285040&view=diff
==============================================================================
--- llvm/trunk/lib/Target/WebAssembly/WebAssemblyInstrInteger.td (original)
+++ llvm/trunk/lib/Target/WebAssembly/WebAssemblyInstrInteger.td Mon Oct 24 18:27:49 2016
@@ -75,10 +75,10 @@ let Defs = [ARGUMENTS] in {
 
 def SELECT_I32 : I<(outs I32:$dst), (ins I32:$lhs, I32:$rhs, I32:$cond),
                    [(set I32:$dst, (select I32:$cond, I32:$lhs, I32:$rhs))],
-                   "i32.select\t$dst, $lhs, $rhs, $cond">;
+                   "i32.select\t$dst, $lhs, $rhs, $cond", 0x1b>;
 def SELECT_I64 : I<(outs I64:$dst), (ins I64:$lhs, I64:$rhs, I32:$cond),
                    [(set I64:$dst, (select I32:$cond, I64:$lhs, I64:$rhs))],
-                   "i64.select\t$dst, $lhs, $rhs, $cond">;
+                   "i64.select\t$dst, $lhs, $rhs, $cond", 0x1b>;
 
 } // Defs = [ARGUMENTS]
 

Modified: llvm/trunk/lib/Target/WebAssembly/WebAssemblyMachineFunctionInfo.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/WebAssembly/WebAssemblyMachineFunctionInfo.h?rev=285040&r1=285039&r2=285040&view=diff
==============================================================================
--- llvm/trunk/lib/Target/WebAssembly/WebAssemblyMachineFunctionInfo.h (original)
+++ llvm/trunk/lib/Target/WebAssembly/WebAssemblyMachineFunctionInfo.h Mon Oct 24 18:27:49 2016
@@ -28,6 +28,7 @@ class WebAssemblyFunctionInfo final : pu
 
   std::vector<MVT> Params;
   std::vector<MVT> Results;
+  std::vector<MVT> Locals;
 
   /// A mapping from CodeGen vreg index to WebAssembly register number.
   std::vector<unsigned> WARegs;
@@ -55,6 +56,9 @@ class WebAssemblyFunctionInfo final : pu
   void addResult(MVT VT) { Results.push_back(VT); }
   const std::vector<MVT> &getResults() const { return Results; }
 
+  void addLocal(MVT VT) { Locals.push_back(VT); }
+  const std::vector<MVT> &getLocals() const { return Locals; }
+
   unsigned getVarargBufferVreg() const {
     assert(VarargVreg != -1U && "Vararg vreg hasn't been set");
     return VarargVreg;




More information about the llvm-commits mailing list