WebAssembly: assert that there aren't any constant pools
[oota-llvm.git] / lib / Target / WebAssembly / WebAssemblyAsmPrinter.cpp
index a1c3350ed73051c2ed854a51acdc73ef9c4eb8f7..aa7734118a60cfd3d6fa7781841cb9597345336b 100644 (file)
 
 #include "llvm/ADT/SmallString.h"
 #include "llvm/CodeGen/AsmPrinter.h"
+#include "llvm/CodeGen/MachineConstantPool.h"
 #include "llvm/CodeGen/MachineInstr.h"
 #include "llvm/IR/DataLayout.h"
 #include "llvm/IR/DebugInfo.h"
 #include "llvm/MC/MCStreamer.h"
+#include "llvm/MC/MCSymbol.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/TargetRegistry.h"
 #include "llvm/Support/raw_ostream.h"
@@ -58,8 +60,7 @@ private:
   }
 
   bool runOnMachineFunction(MachineFunction &MF) override {
-    TII = static_cast<const WebAssemblyInstrInfo *>(
-        MF.getSubtarget().getInstrInfo());
+    TII = MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo();
     return AsmPrinter::runOnMachineFunction(MF);
   }
 
@@ -67,6 +68,11 @@ private:
   // AsmPrinter Implementation.
   //===------------------------------------------------------------------===//
 
+  void EmitConstantPool() override;
+  void EmitFunctionEntryLabel() override;
+  void EmitFunctionBodyStart() override;
+  void EmitFunctionBodyEnd() override;
+
   void EmitInstruction(const MachineInstr *MI) override;
 };
 
@@ -80,12 +86,76 @@ private:
 static SmallString<32> Name(const WebAssemblyInstrInfo *TII,
                             const MachineInstr *MI) {
   std::string N(StringRef(TII->getName(MI->getOpcode())).lower());
-  std::string::size_type End = N.find('_');
+  std::string::size_type End = N.rfind('_');
   End = std::string::npos == End ? N.length() : End;
   return SmallString<32>(&N[0], &N[End]);
 }
 
+static std::string toSymbol(StringRef S) { return ("$" + S).str(); }
+
+static const char *toType(const Type *Ty) {
+  switch (Ty->getTypeID()) {
+  default: break;
+  case Type::FloatTyID:  return "f32";
+  case Type::DoubleTyID: return "f64";
+  case Type::IntegerTyID:
+    switch (Ty->getIntegerBitWidth()) {
+    case 32: return "i32";
+    case 64: return "i64";
+    default: break;
+    }
+  }
+  DEBUG(dbgs() << "Invalid type "; Ty->print(dbgs()); dbgs() << '\n');
+  llvm_unreachable("invalid type");
+  return "<invalid>";
+}
+
+void WebAssemblyAsmPrinter::EmitConstantPool() {
+  assert(MF->getConstantPool()->getConstants().empty() &&
+         "WebAssembly disables constant pools");
+}
+
+void WebAssemblyAsmPrinter::EmitFunctionEntryLabel() {
+  SmallString<128> Str;
+  raw_svector_ostream OS(Str);
+
+  CurrentFnSym->redefineIfPossible();
+
+  // The function label could have already been emitted if two symbols end up
+  // conflicting due to asm renaming.  Detect this and emit an error.
+  if (CurrentFnSym->isVariable())
+    report_fatal_error("'" + Twine(CurrentFnSym->getName()) +
+                       "' is a protected alias");
+  if (CurrentFnSym->isDefined())
+    report_fatal_error("'" + Twine(CurrentFnSym->getName()) +
+                       "' label emitted multiple times to assembly file");
+
+  OS << "(func " << toSymbol(CurrentFnSym->getName());
+  OutStreamer->EmitRawText(OS.str());
+}
+
+void WebAssemblyAsmPrinter::EmitFunctionBodyStart() {
+  SmallString<128> Str;
+  raw_svector_ostream OS(Str);
+  const Function *F = MF->getFunction();
+  for (const Argument &A : F->args())
+    OS << " (param " << toType(A.getType()) << ')';
+  const Type *Rt = F->getReturnType();
+  if (!Rt->isVoidTy())
+    OS << " (result " << toType(Rt) << ')';
+  OS << '\n';
+  OutStreamer->EmitRawText(OS.str());
+}
+
+void WebAssemblyAsmPrinter::EmitFunctionBodyEnd() {
+  SmallString<128> Str;
+  raw_svector_ostream OS(Str);
+  OS << ") ;; end func " << toSymbol(CurrentFnSym->getName()) << '\n';
+  OutStreamer->EmitRawText(OS.str());
+}
+
 void WebAssemblyAsmPrinter::EmitInstruction(const MachineInstr *MI) {
+  DEBUG(dbgs() << "EmitInstruction: " << *MI << '\n');
   SmallString<128> Str;
   raw_svector_ostream OS(Str);
 
@@ -93,6 +163,8 @@ void WebAssemblyAsmPrinter::EmitInstruction(const MachineInstr *MI) {
   assert(NumDefs <= 1 &&
          "Instructions with multiple result values not implemented");
 
+  OS << '\t';
+
   if (NumDefs != 0) {
     const MachineOperand &MO = MI->getOperand(0);
     unsigned Reg = MO.getReg();
@@ -131,6 +203,9 @@ void WebAssemblyAsmPrinter::EmitInstruction(const MachineInstr *MI) {
       assert(Written < BufBytes);
       OS << ' ' << buf;
     } break;
+    case MachineOperand::MO_GlobalAddress: {
+      OS << ' ' << toSymbol(MO.getGlobal()->getName());
+    } break;
     }
   OS << ')';