[WebAssembly] Emit .param, .result, and .local through MC.

This eliminates one of the main remaining uses of EmitRawText.

llvm-svn: 253878
diff --git a/llvm/lib/Target/WebAssembly/InstPrinter/WebAssemblyInstPrinter.cpp b/llvm/lib/Target/WebAssembly/InstPrinter/WebAssemblyInstPrinter.cpp
index aed722c..a53a7cd 100644
--- a/llvm/lib/Target/WebAssembly/InstPrinter/WebAssemblyInstPrinter.cpp
+++ b/llvm/lib/Target/WebAssembly/InstPrinter/WebAssemblyInstPrinter.cpp
@@ -15,6 +15,7 @@
 #include "InstPrinter/WebAssemblyInstPrinter.h"
 #include "WebAssembly.h"
 #include "WebAssemblyMachineFunctionInfo.h"
+#include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
 #include "llvm/MC/MCExpr.h"
 #include "llvm/MC/MCInst.h"
 #include "llvm/MC/MCInstrInfo.h"
@@ -51,7 +52,8 @@
   if (Desc.isVariadic())
     for (unsigned i = Desc.getNumOperands(), e = MI->getNumOperands(); i < e;
          ++i) {
-      OS << ", ";
+      if (i != 0)
+        OS << ", ";
       printOperand(MI, i, OS);
     }
 
@@ -88,9 +90,24 @@
       O << "$push" << (WAReg & INT32_MAX);
     else
       O << "$discard";
-  } else if (Op.isImm())
-    O << Op.getImm();
-  else if (Op.isFPImm())
+  } else if (Op.isImm()) {
+    switch (MI->getOpcode()) {
+    case WebAssembly::PARAM:
+    case WebAssembly::RESULT:
+    case WebAssembly::LOCAL:
+      switch (Op.getImm()) {
+      case MVT::i32: O << "i32"; break;
+      case MVT::i64: O << "i64"; break;
+      case MVT::f32: O << "f32"; break;
+      case MVT::f64: O << "f64"; break;
+      default: llvm_unreachable("unexpected type");
+      }
+      break;
+    default:
+      O << Op.getImm();
+      break;
+    }
+  } else if (Op.isFPImm())
     O << toString(APFloat(Op.getFPImm()));
   else {
     assert(Op.isExpr() && "unknown operand kind in printOperand");
diff --git a/llvm/lib/Target/WebAssembly/MCTargetDesc/CMakeLists.txt b/llvm/lib/Target/WebAssembly/MCTargetDesc/CMakeLists.txt
index ccc0f0d..dbfa725 100644
--- a/llvm/lib/Target/WebAssembly/MCTargetDesc/CMakeLists.txt
+++ b/llvm/lib/Target/WebAssembly/MCTargetDesc/CMakeLists.txt
@@ -1,4 +1,5 @@
 add_llvm_library(LLVMWebAssemblyDesc
   WebAssemblyMCAsmInfo.cpp
+  WebAssemblyMCCodeEmitter.cpp
   WebAssemblyMCTargetDesc.cpp
 )
diff --git a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.cpp b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.cpp
index fcd4c29..4d92f94 100644
--- a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.cpp
+++ b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.cpp
@@ -65,5 +65,8 @@
 
     // Register the MCInstPrinter.
     TargetRegistry::RegisterMCInstPrinter(*T, createWebAssemblyMCInstPrinter);
+
+    // Register the MC code emitter
+    TargetRegistry::RegisterMCCodeEmitter(*T, createWebAssemblyMCCodeEmitter);
   }
 }
diff --git a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h
index bb788dc..6ef01ff 100644
--- a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h
+++ b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h
@@ -34,13 +34,18 @@
 class Target;
 class Triple;
 class raw_ostream;
+class raw_pwrite_stream;
 
 extern Target TheWebAssemblyTarget32;
 extern Target TheWebAssemblyTarget64;
 
+MCCodeEmitter *createWebAssemblyMCCodeEmitter(const MCInstrInfo &MCII,
+                                              const MCRegisterInfo &MRI,
+                                              MCContext &Ctx);
+
 MCAsmBackend *createWebAssemblyAsmBackend(const Target &T,
                                           const MCRegisterInfo &MRI,
-                                          StringRef TT, StringRef CPU);
+                                          const Triple &TT, StringRef CPU);
 
 } // end namespace llvm
 
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
index 512cdd1..c452e1d 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
@@ -84,7 +84,7 @@
                              unsigned AsmVariant, const char *ExtraCode,
                              raw_ostream &OS) override;
 
-  std::string getRegTypeName(unsigned RegNo) const;
+  MVT getRegType(unsigned RegNo) const;
   const char *toString(MVT VT) const;
   std::string regToString(const MachineOperand &MO);
 };
@@ -95,14 +95,14 @@
 // Helpers.
 //===----------------------------------------------------------------------===//
 
-std::string WebAssemblyAsmPrinter::getRegTypeName(unsigned RegNo) const {
+MVT WebAssemblyAsmPrinter::getRegType(unsigned RegNo) const {
   const TargetRegisterClass *TRC = MRI->getRegClass(RegNo);
   for (MVT T : {MVT::i32, MVT::i64, MVT::f32, MVT::f64})
     if (TRC->hasType(T))
-      return EVT(T).getEVTString();
+      return T;
   DEBUG(errs() << "Unknown type for register number: " << RegNo);
   llvm_unreachable("Unknown register type");
-  return "?";
+  return MVT::Other;
 }
 
 std::string WebAssemblyAsmPrinter::regToString(const MachineOperand &MO) {
@@ -165,21 +165,30 @@
 }
 
 void WebAssemblyAsmPrinter::EmitFunctionBodyStart() {
-  SmallString<128> Str;
-  raw_svector_ostream OS(Str);
+  if (!MFI->getParams().empty()) {
+    MCInst Param;
+    Param.setOpcode(WebAssembly::PARAM);
+    for (MVT VT : MFI->getParams())
+      Param.addOperand(MCOperand::createImm(VT.SimpleTy));
+    EmitToStreamer(*OutStreamer, Param);
+  }
 
-  for (MVT VT : MFI->getParams())
-    OS << "\t" ".param " << toString(VT) << '\n';
 
   SmallVector<MVT, 4> ResultVTs;
   const Function &F(*MF->getFunction());
   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)
-    OS << "\t" ".result " << toString(ResultVTs.front()) << '\n';
+  if (ResultVTs.size() == 1) {
+    MCInst Result;
+    Result.setOpcode(WebAssembly::RESULT);
+    Result.addOperand(MCOperand::createImm(ResultVTs.front().SimpleTy));
+    EmitToStreamer(*OutStreamer, Result);
+  }
 
-  bool FirstWAReg = true;
+  bool AnyWARegs = false;
+  MCInst Local;
+  Local.setOpcode(WebAssembly::LOCAL);
   for (unsigned Idx = 0, IdxE = MRI->getNumVirtRegs(); Idx != IdxE; ++Idx) {
     unsigned VReg = TargetRegisterInfo::index2VirtReg(Idx);
     unsigned WAReg = MFI->getWAReg(VReg);
@@ -192,20 +201,12 @@
     // Don't declare stackified registers.
     if (int(WAReg) < 0)
       continue;
-    if (FirstWAReg)
-      OS << "\t" ".local ";
-    else
-      OS << ", ";
-    OS << getRegTypeName(VReg);
-    FirstWAReg = false;
+    Local.addOperand(MCOperand::createImm(getRegType(VReg).SimpleTy));
+    AnyWARegs = true;
   }
-  if (!FirstWAReg)
-    OS << '\n';
+  if (AnyWARegs)
+    EmitToStreamer(*OutStreamer, Local);
 
-  // EmitRawText appends a newline, so strip off the last newline.
-  StringRef Text = OS.str();
-  if (!Text.empty())
-    OutStreamer->EmitRawText(Text.substr(0, Text.size() - 1));
   AsmPrinter::EmitFunctionBodyStart();
 }
 
@@ -283,6 +284,8 @@
   StringRef Text = OS.str();
   if (!Text.empty())
     OutStreamer->EmitRawText(Text.substr(0, Text.size() - 1));
+
+  AsmPrinter::EmitEndOfAsmFile(M);
 }
 
 bool WebAssemblyAsmPrinter::PrintAsmOperand(const MachineInstr *MI,
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td
index dae9cff..1fa7902 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td
@@ -124,6 +124,11 @@
                    [(set I32:$dst, (WebAssemblywrapper tjumptable:$addr))],
                    "jump_table\t$dst, $addr">;
 
+// Function signature and local variable declaration "instructions".
+def PARAM  : I<(outs), (ins variable_ops), [], ".param  \t">;
+def RESULT : I<(outs), (ins variable_ops), [], ".result \t">;
+def LOCAL  : I<(outs), (ins variable_ops), [], ".local  \t">;
+
 //===----------------------------------------------------------------------===//
 // Additional sets of instructions.
 //===----------------------------------------------------------------------===//
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
index 4c576ec..d60c41a 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
@@ -20,6 +20,7 @@
 #include "llvm/CodeGen/MachineFunctionPass.h"
 #include "llvm/CodeGen/Passes.h"
 #include "llvm/CodeGen/RegAllocRegistry.h"
+#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
 #include "llvm/IR/Function.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/TargetRegistry.h"