Convert Constant->emit() definitions to allow multiple targets to define them.

Wasn't sure how to allow TargetX8632 and TargetARM32
to both define "ConstantInteger32::emit(GlobalContext *)",
and define them differently if both targets happen to be
ifdef'ed into the code. Rearranged things so that it's now
"TargetFoo::emit(ConstantInteger32 *)", so that each
TargetFoo can have a separate definition.

Some targets may allow emitting some types of constants
while other targets do not (64-bit int for x86-64?).
Also they emit constants with a different style.
E.g., the prefix for x86 is "$" while the prefix for ARM
is "#" and there isn't a prefix for mips(?).
Renamed emitWithoutDollar to emitWithoutPrefix.

Did this sort of multi-method dispatch via a visitor
pattern, which is a bit verbose though.

We may be able to remove the emitWithoutDollar/Prefix for
ConstantPrimitive by just inlining that into the few places
that need it (only needed for ConstantInteger32). This
undoes the unreachable methods added by: https://codereview.chromium.org/1017373002/diff/60001/src/IceTargetLoweringX8632.cpp
The only place extra was for emitting calls to constants.
There was already an inlined instance for OperandX8632Mem.

BUG= https://code.google.com/p/nativeclient/issues/detail?id=4076
R=stichnot@chromium.org

Review URL: https://codereview.chromium.org/1129263005
diff --git a/src/IceInstX8632.cpp b/src/IceInstX8632.cpp
index b253278..2ac95db 100644
--- a/src/IceInstX8632.cpp
+++ b/src/IceInstX8632.cpp
@@ -526,8 +526,12 @@
   Ostream &Str = Func->getContext()->getStrEmit();
   assert(getSrcSize() == 1);
   Str << "\tcall\t";
-  if (const auto CallTarget = llvm::dyn_cast<Constant>(getCallTarget())) {
-    CallTarget->emitWithoutDollar(Func->getContext());
+  if (const auto CI = llvm::dyn_cast<ConstantInteger32>(getCallTarget())) {
+    // Emit without a leading '$'.
+    Str << CI->getValue();
+  } else if (const auto CallTarget =
+                 llvm::dyn_cast<ConstantRelocatable>(getCallTarget())) {
+    CallTarget->emitWithoutPrefix(Func->getTarget());
   } else {
     Str << "*";
     getCallTarget()->emit(Func);
@@ -2848,7 +2852,7 @@
       // Emit a non-zero offset without a leading '$'.
       Str << CI->getValue();
   } else if (const auto CR = llvm::dyn_cast<ConstantRelocatable>(Offset)) {
-    CR->emitWithoutDollar(Func->getContext());
+    CR->emitWithoutPrefix(Func->getTarget());
   } else {
     llvm_unreachable("Invalid offset type for x86 mem operand");
   }
diff --git a/src/IceOperand.cpp b/src/IceOperand.cpp
index 9338bdc..2d2c8cf 100644
--- a/src/IceOperand.cpp
+++ b/src/IceOperand.cpp
@@ -422,27 +422,28 @@
   }
 }
 
-void ConstantRelocatable::emitWithoutDollar(GlobalContext *Ctx) const {
-  if (!ALLOW_DUMP)
-    return;
-  Ostream &Str = Ctx->getStrEmit();
-  if (SuppressMangling)
-    Str << Name;
-  else
-    Str << Ctx->mangleName(Name);
-  if (Offset) {
-    if (Offset > 0)
-      Str << "+";
-    Str << Offset;
-  }
+template <> void ConstantInteger32::emit(TargetLowering *Target) const {
+  Target->emit(this);
 }
 
-void ConstantRelocatable::emit(GlobalContext *Ctx) const {
-  if (!ALLOW_DUMP)
-    return;
-  Ostream &Str = Ctx->getStrEmit();
-  Str << "$";
-  emitWithoutDollar(Ctx);
+template <> void ConstantInteger64::emit(TargetLowering *Target) const {
+  Target->emit(this);
+}
+
+template <> void ConstantFloat::emit(TargetLowering *Target) const {
+  Target->emit(this);
+}
+
+template <> void ConstantDouble::emit(TargetLowering *Target) const {
+  Target->emit(this);
+}
+
+void ConstantRelocatable::emit(TargetLowering *Target) const {
+  Target->emit(this);
+}
+
+void ConstantRelocatable::emitWithoutPrefix(TargetLowering *Target) const {
+  Target->emitWithoutPrefix(this);
 }
 
 void ConstantRelocatable::dump(const Cfg *Func, Ostream &Str) const {
@@ -458,6 +459,8 @@
     Str << "+" << Offset;
 }
 
+void ConstantUndef::emit(TargetLowering *Target) const { Target->emit(this); }
+
 void LiveRange::dump(Ostream &Str) const {
   if (!ALLOW_DUMP)
     return;
diff --git a/src/IceOperand.h b/src/IceOperand.h
index 3bbd02c..430a565 100644
--- a/src/IceOperand.h
+++ b/src/IceOperand.h
@@ -106,9 +106,8 @@
   void emitPoolLabel(Ostream &Str) const {
     Str << ".L$" << getType() << "$" << PoolEntryID;
   }
-  void emit(const Cfg *Func) const override { emit(Func->getContext()); }
-  virtual void emit(GlobalContext *Ctx) const = 0;
-  virtual void emitWithoutDollar(GlobalContext *Ctx) const = 0;
+  void emit(const Cfg *Func) const override { emit(Func->getTarget()); }
+  virtual void emit(TargetLowering *Target) const = 0;
 
   static bool classof(const Operand *Operand) {
     OperandKind Kind = Operand->getKind();
@@ -147,10 +146,7 @@
   }
   PrimType getValue() const { return Value; }
   using Constant::emit;
-  // The target needs to implement this for each ConstantPrimitive
-  // specialization.
-  void emit(GlobalContext *Ctx) const override;
-  void emitWithoutDollar(GlobalContext *Ctx) const override;
+  void emit(TargetLowering *Target) const final;
   using Constant::dump;
   void dump(const Cfg *, Ostream &Str) const override {
     if (ALLOW_DUMP)
@@ -234,9 +230,9 @@
   void setSuppressMangling(bool Value) { SuppressMangling = Value; }
   bool getSuppressMangling() const { return SuppressMangling; }
   using Constant::emit;
+  void emit(TargetLowering *Target) const final;
+  void emitWithoutPrefix(TargetLowering *Target) const;
   using Constant::dump;
-  void emit(GlobalContext *Ctx) const override;
-  void emitWithoutDollar(GlobalContext *Ctx) const override;
   void dump(const Cfg *Func, Ostream &Str) const override;
 
   static bool classof(const Operand *Operand) {
@@ -272,10 +268,8 @@
   }
 
   using Constant::emit;
+  void emit(TargetLowering *Target) const final;
   using Constant::dump;
-  // The target needs to implement this.
-  void emit(GlobalContext *Ctx) const override;
-  void emitWithoutDollar(GlobalContext *Ctx) const override;
   void dump(const Cfg *, Ostream &Str) const override {
     if (ALLOW_DUMP)
       Str << "undef";
diff --git a/src/IceTargetLowering.cpp b/src/IceTargetLowering.cpp
index 22f698a..d0929a0 100644
--- a/src/IceTargetLowering.cpp
+++ b/src/IceTargetLowering.cpp
@@ -234,6 +234,30 @@
   return Call;
 }
 
+void TargetLowering::emitWithoutPrefix(const ConstantRelocatable *C) const {
+  if (!ALLOW_DUMP)
+    return;
+  Ostream &Str = Ctx->getStrEmit();
+  if (C->getSuppressMangling())
+    Str << C->getName();
+  else
+    Str << Ctx->mangleName(C->getName());
+  RelocOffsetT Offset = C->getOffset();
+  if (Offset) {
+    if (Offset > 0)
+      Str << "+";
+    Str << Offset;
+  }
+}
+
+void TargetLowering::emit(const ConstantRelocatable *C) const {
+  if (!ALLOW_DUMP)
+    return;
+  Ostream &Str = Ctx->getStrEmit();
+  Str << getConstantPrefix();
+  emitWithoutPrefix(C);
+}
+
 std::unique_ptr<TargetDataLowering>
 TargetDataLowering::createLowering(GlobalContext *Ctx) {
   TargetArch Target = Ctx->getFlags().getTargetArch();
diff --git a/src/IceTargetLowering.h b/src/IceTargetLowering.h
index baa569f..5003574 100644
--- a/src/IceTargetLowering.h
+++ b/src/IceTargetLowering.h
@@ -23,6 +23,7 @@
 
 #include "IceDefs.h"
 #include "IceInst.h" // for the names of the Inst subtypes
+#include "IceOperand.h"
 #include "IceTypes.h"
 
 namespace Ice {
@@ -207,6 +208,16 @@
 
   virtual void emitVariable(const Variable *Var) const = 0;
 
+  void emitWithoutPrefix(const ConstantRelocatable *CR) const;
+  void emit(const ConstantRelocatable *CR) const;
+  virtual const char *getConstantPrefix() const = 0;
+
+  virtual void emit(const ConstantUndef *C) const = 0;
+  virtual void emit(const ConstantInteger32 *C) const = 0;
+  virtual void emit(const ConstantInteger64 *C) const = 0;
+  virtual void emit(const ConstantFloat *C) const = 0;
+  virtual void emit(const ConstantDouble *C) const = 0;
+
   // Performs target-specific argument lowering.
   virtual void lowerArguments() = 0;
 
diff --git a/src/IceTargetLoweringARM32.cpp b/src/IceTargetLoweringARM32.cpp
index 287e42d..7e96d04 100644
--- a/src/IceTargetLoweringARM32.cpp
+++ b/src/IceTargetLoweringARM32.cpp
@@ -702,15 +702,28 @@
   UnimplementedError(Func->getContext()->getFlags());
 }
 
-/* TODO(jvoung): avoid duplicate symbols with multiple targets.
-void ConstantUndef::emitWithoutDollar(GlobalContext *) const {
-  llvm_unreachable("Not expecting to emitWithoutDollar undef");
+void TargetARM32::emit(const ConstantInteger32 *C) const {
+  if (!ALLOW_DUMP)
+    return;
+  Ostream &Str = Ctx->getStrEmit();
+  Str << getConstantPrefix() << C->getValue();
 }
 
-void ConstantUndef::emit(GlobalContext *) const {
-  llvm_unreachable("undef value encountered by emitter.");
+void TargetARM32::emit(const ConstantInteger64 *) const {
+  llvm::report_fatal_error("Not expecting to emit 64-bit integers");
 }
-*/
+
+void TargetARM32::emit(const ConstantFloat *C) const {
+  UnimplementedError(Ctx->getFlags());
+}
+
+void TargetARM32::emit(const ConstantDouble *C) const {
+  UnimplementedError(Ctx->getFlags());
+}
+
+void TargetARM32::emit(const ConstantUndef *) const {
+  llvm::report_fatal_error("undef value encountered by emitter.");
+}
 
 TargetDataARM32::TargetDataARM32(GlobalContext *Ctx)
     : TargetDataLowering(Ctx) {}
diff --git a/src/IceTargetLoweringARM32.h b/src/IceTargetLoweringARM32.h
index c1862d5..99909a3 100644
--- a/src/IceTargetLoweringARM32.h
+++ b/src/IceTargetLoweringARM32.h
@@ -53,6 +53,14 @@
     return (typeWidthInBytes(Ty) + 3) & ~3;
   }
   void emitVariable(const Variable *Var) const override;
+
+  const char *getConstantPrefix() const final { return "#"; }
+  void emit(const ConstantUndef *C) const final;
+  void emit(const ConstantInteger32 *C) const final;
+  void emit(const ConstantInteger64 *C) const final;
+  void emit(const ConstantFloat *C) const final;
+  void emit(const ConstantDouble *C) const final;
+
   void lowerArguments() override;
   void addProlog(CfgNode *Node) override;
   void addEpilog(CfgNode *Node) override;
diff --git a/src/IceTargetLoweringX8632.cpp b/src/IceTargetLoweringX8632.cpp
index dd75168..5f83bae 100644
--- a/src/IceTargetLoweringX8632.cpp
+++ b/src/IceTargetLoweringX8632.cpp
@@ -4650,58 +4650,33 @@
   }
 }
 
-template <>
-void ConstantInteger32::emitWithoutDollar(GlobalContext *Ctx) const {
+void TargetX8632::emit(const ConstantInteger32 *C) const {
   if (!ALLOW_DUMP)
     return;
   Ostream &Str = Ctx->getStrEmit();
-  Str << (int32_t)getValue();
+  Str << getConstantPrefix() << C->getValue();
 }
 
-template <> void ConstantInteger32::emit(GlobalContext *Ctx) const {
+void TargetX8632::emit(const ConstantInteger64 *) const {
+  llvm::report_fatal_error("Not expecting to emit 64-bit integers");
+}
+
+void TargetX8632::emit(const ConstantFloat *C) const {
   if (!ALLOW_DUMP)
     return;
   Ostream &Str = Ctx->getStrEmit();
-  Str << "$";
-  emitWithoutDollar(Ctx);
+  C->emitPoolLabel(Str);
 }
 
-template <> void ConstantInteger64::emitWithoutDollar(GlobalContext *) const {
-  llvm_unreachable("Not expecting to emitWithoutDollar 64-bit integers");
-}
-
-template <> void ConstantInteger64::emit(GlobalContext *) const {
-  llvm_unreachable("Not expecting to emit 64-bit integers");
-}
-
-template <> void ConstantFloat::emitWithoutDollar(GlobalContext *) const {
-  llvm_unreachable("Not expecting to emitWithoutDollar floats");
-}
-
-template <> void ConstantFloat::emit(GlobalContext *Ctx) const {
+void TargetX8632::emit(const ConstantDouble *C) const {
   if (!ALLOW_DUMP)
     return;
   Ostream &Str = Ctx->getStrEmit();
-  emitPoolLabel(Str);
+  C->emitPoolLabel(Str);
 }
 
-template <> void ConstantDouble::emitWithoutDollar(GlobalContext *) const {
-  llvm_unreachable("Not expecting to emitWithoutDollar doubles");
-}
-
-template <> void ConstantDouble::emit(GlobalContext *Ctx) const {
-  if (!ALLOW_DUMP)
-    return;
-  Ostream &Str = Ctx->getStrEmit();
-  emitPoolLabel(Str);
-}
-
-void ConstantUndef::emitWithoutDollar(GlobalContext *) const {
-  llvm_unreachable("Not expecting to emitWithoutDollar undef");
-}
-
-void ConstantUndef::emit(GlobalContext *) const {
-  llvm_unreachable("undef value encountered by emitter.");
+void TargetX8632::emit(const ConstantUndef *) const {
+  llvm::report_fatal_error("undef value encountered by emitter.");
 }
 
 TargetDataX8632::TargetDataX8632(GlobalContext *Ctx)
diff --git a/src/IceTargetLoweringX8632.h b/src/IceTargetLoweringX8632.h
index 8a3c36e..f114dba 100644
--- a/src/IceTargetLoweringX8632.h
+++ b/src/IceTargetLoweringX8632.h
@@ -54,6 +54,14 @@
     return (typeWidthInBytes(Ty) + 3) & ~3;
   }
   void emitVariable(const Variable *Var) const override;
+
+  const char *getConstantPrefix() const final { return "$"; }
+  void emit(const ConstantUndef *C) const final;
+  void emit(const ConstantInteger32 *C) const final;
+  void emit(const ConstantInteger64 *C) const final;
+  void emit(const ConstantFloat *C) const final;
+  void emit(const ConstantDouble *C) const final;
+
   void lowerArguments() override;
   void addProlog(CfgNode *Node) override;
   void addEpilog(CfgNode *Node) override;
@@ -523,11 +531,6 @@
   template <typename T> static void emitConstantPool(GlobalContext *Ctx);
 };
 
-template <> void ConstantInteger32::emit(GlobalContext *Ctx) const;
-template <> void ConstantInteger64::emit(GlobalContext *Ctx) const;
-template <> void ConstantFloat::emit(GlobalContext *Ctx) const;
-template <> void ConstantDouble::emit(GlobalContext *Ctx) const;
-
 } // end of namespace Ice
 
 #endif // SUBZERO_SRC_ICETARGETLOWERINGX8632_H