Subzero: Initial implementation of multithreaded translation.

Provides a single-producer, multiple-consumer translation queue where the number of translation threads is given by the -threads=N argument.  The producer (i.e., bitcode parser) blocks if the queue size is >=N, in order to control the memory footprint.  If N=0 (which is the default), execution is purely single-threaded.  If N=1, there is a single translation thread running in parallel with the parser thread.  "make check" succeeds with the default changed to N=1.

Currently emission is also done by the translation thread, which limits scalability since the emit stream has to be locked.  Also, since the ELF writer stream is not locked, it won't be safe to use N>1 with the ELF writer.  Furthermore, for N>1, emitted function ordering is nondeterministic and needs to be recombobulated.  This will all be fixed in a follow-on CL.

The -timing option is broken for N>0.  This will be fixed in a follow-on CL.

Verbose flags are now managed in the Cfg instead of (or in addition to) the GlobalContext, due to the -verbose-focus option which wants to temporarily change the verbose level for a particular function.

TargetLowering::emitConstants() and related methods are changed to be static, so that a valid TargetLowering object isn't required.  This is because the TargetLowering object wants to hold a valid Cfg, and none really exists after all functions are translated and the constant pool is ready for emission.

The Makefile.standalone now has a TSAN=1 option to enable ThreadSanitizer.

BUG= none
R=jfb@chromium.org

Review URL: https://codereview.chromium.org/870653002
diff --git a/src/IceTargetLoweringX8632.cpp b/src/IceTargetLoweringX8632.cpp
index b092f7f..79c79cc 100644
--- a/src/IceTargetLoweringX8632.cpp
+++ b/src/IceTargetLoweringX8632.cpp
@@ -897,7 +897,7 @@
     Var->setStackOffset(Linked->getStackOffset());
   }
 
-  if (ALLOW_DUMP && Func->getContext()->isVerbose(IceV_Frame)) {
+  if (ALLOW_DUMP && Func->isVerbose(IceV_Frame)) {
     OstreamLocker L(Func->getContext());
     Ostream &Str = Func->getContext()->getStrDump();
 
@@ -966,75 +966,6 @@
   }
 }
 
-template <typename T> struct PoolTypeConverter {};
-
-template <> struct PoolTypeConverter<float> {
-  typedef uint32_t PrimitiveIntType;
-  typedef ConstantFloat IceType;
-  static const Type Ty = IceType_f32;
-  static const char *TypeName;
-  static const char *AsmTag;
-  static const char *PrintfString;
-};
-const char *PoolTypeConverter<float>::TypeName = "float";
-const char *PoolTypeConverter<float>::AsmTag = ".long";
-const char *PoolTypeConverter<float>::PrintfString = "0x%x";
-
-template <> struct PoolTypeConverter<double> {
-  typedef uint64_t PrimitiveIntType;
-  typedef ConstantDouble IceType;
-  static const Type Ty = IceType_f64;
-  static const char *TypeName;
-  static const char *AsmTag;
-  static const char *PrintfString;
-};
-const char *PoolTypeConverter<double>::TypeName = "double";
-const char *PoolTypeConverter<double>::AsmTag = ".quad";
-const char *PoolTypeConverter<double>::PrintfString = "0x%llx";
-
-template <typename T> void TargetX8632::emitConstantPool() const {
-  // Note: Still used by emit IAS.
-  Ostream &Str = Ctx->getStrEmit();
-  Type Ty = T::Ty;
-  SizeT Align = typeAlignInBytes(Ty);
-  ConstantList Pool = Ctx->getConstantPool(Ty);
-
-  Str << "\t.section\t.rodata.cst" << Align << ",\"aM\",@progbits," << Align
-      << "\n";
-  Str << "\t.align\t" << Align << "\n";
-  for (Constant *C : Pool) {
-    typename T::IceType *Const = llvm::cast<typename T::IceType>(C);
-    typename T::IceType::PrimType Value = Const->getValue();
-    // Use memcpy() to copy bits from Value into RawValue in a way
-    // that avoids breaking strict-aliasing rules.
-    typename T::PrimitiveIntType RawValue;
-    memcpy(&RawValue, &Value, sizeof(Value));
-    char buf[30];
-    int CharsPrinted =
-        snprintf(buf, llvm::array_lengthof(buf), T::PrintfString, RawValue);
-    assert(CharsPrinted >= 0 &&
-           (size_t)CharsPrinted < llvm::array_lengthof(buf));
-    (void)CharsPrinted; // avoid warnings if asserts are disabled
-    Const->emitPoolLabel(Str);
-    Str << ":\n\t" << T::AsmTag << "\t" << buf << "\t# " << T::TypeName << " "
-        << Value << "\n";
-  }
-}
-
-void TargetX8632::emitConstants() const {
-  // No need to emit constants from the int pool since (for x86) they
-  // are embedded as immediates in the instructions, just emit float/double.
-  if (Ctx->getFlags().UseELFWriter) {
-    ELFObjectWriter *Writer = Ctx->getObjectWriter();
-    Writer->writeConstantPool<ConstantFloat>(IceType_f32);
-    Writer->writeConstantPool<ConstantDouble>(IceType_f64);
-  } else {
-    OstreamLocker L(Ctx);
-    emitConstantPool<PoolTypeConverter<float>>();
-    emitConstantPool<PoolTypeConverter<double>>();
-  }
-}
-
 void TargetX8632::split64(Variable *Var) {
   switch (Var->getType()) {
   default:
@@ -3567,7 +3498,7 @@
                     const Inst *Reason) {
   if (!ALLOW_DUMP)
     return;
-  if (!Func->getContext()->isVerbose(IceV_AddrOpt))
+  if (!Func->isVerbose(IceV_AddrOpt))
     return;
   OstreamLocker L(Func->getContext());
   Ostream &Str = Func->getContext()->getStrDump();
@@ -3740,7 +3671,7 @@
 void computeAddressOpt(Cfg *Func, const Inst *Instr, Variable *&Base,
                        Variable *&Index, uint16_t &Shift, int32_t &Offset) {
   Func->resetCurrentNode();
-  if (Func->getContext()->isVerbose(IceV_AddrOpt)) {
+  if (Func->isVerbose(IceV_AddrOpt)) {
     OstreamLocker L(Func->getContext());
     Ostream &Str = Func->getContext()->getStrDump();
     Str << "\nStarting computeAddressOpt for instruction:\n  ";
@@ -4582,7 +4513,7 @@
 
   assert(NumShuffled + NumPreserved == RegX8632::Reg_NUM);
 
-  if (Func->getContext()->isVerbose(IceV_Random)) {
+  if (Func->isVerbose(IceV_Random)) {
     OstreamLocker L(Func->getContext());
     Ostream &Str = Func->getContext()->getStrDump();
     Str << "Register equivalence classes:\n";
@@ -4630,10 +4561,10 @@
   llvm_unreachable("undef value encountered by emitter.");
 }
 
-TargetGlobalInitX8632::TargetGlobalInitX8632(GlobalContext *Ctx)
-    : TargetGlobalInitLowering(Ctx) {}
+TargetGlobalX8632::TargetGlobalX8632(GlobalContext *Ctx)
+    : TargetGlobalLowering(Ctx) {}
 
-void TargetGlobalInitX8632::lower(const VariableDeclaration &Var) {
+void TargetGlobalX8632::lowerInit(const VariableDeclaration &Var) const {
   // TODO(jvoung): handle this without text.
   if (Ctx->getFlags().UseELFWriter)
     return;
@@ -4714,4 +4645,76 @@
   Str << "\t.size\t" << MangledName << ", " << Size << "\n";
 }
 
+template <typename T> struct PoolTypeConverter {};
+
+template <> struct PoolTypeConverter<float> {
+  typedef uint32_t PrimitiveIntType;
+  typedef ConstantFloat IceType;
+  static const Type Ty = IceType_f32;
+  static const char *TypeName;
+  static const char *AsmTag;
+  static const char *PrintfString;
+};
+const char *PoolTypeConverter<float>::TypeName = "float";
+const char *PoolTypeConverter<float>::AsmTag = ".long";
+const char *PoolTypeConverter<float>::PrintfString = "0x%x";
+
+template <> struct PoolTypeConverter<double> {
+  typedef uint64_t PrimitiveIntType;
+  typedef ConstantDouble IceType;
+  static const Type Ty = IceType_f64;
+  static const char *TypeName;
+  static const char *AsmTag;
+  static const char *PrintfString;
+};
+const char *PoolTypeConverter<double>::TypeName = "double";
+const char *PoolTypeConverter<double>::AsmTag = ".quad";
+const char *PoolTypeConverter<double>::PrintfString = "0x%llx";
+
+template <typename T>
+void TargetGlobalX8632::emitConstantPool(GlobalContext *Ctx) {
+  // Note: Still used by emit IAS.
+  Ostream &Str = Ctx->getStrEmit();
+  Type Ty = T::Ty;
+  SizeT Align = typeAlignInBytes(Ty);
+  ConstantList Pool = Ctx->getConstantPool(Ty);
+
+  Str << "\t.section\t.rodata.cst" << Align << ",\"aM\",@progbits," << Align
+      << "\n";
+  Str << "\t.align\t" << Align << "\n";
+  for (Constant *C : Pool) {
+    typename T::IceType *Const = llvm::cast<typename T::IceType>(C);
+    typename T::IceType::PrimType Value = Const->getValue();
+    // Use memcpy() to copy bits from Value into RawValue in a way
+    // that avoids breaking strict-aliasing rules.
+    typename T::PrimitiveIntType RawValue;
+    memcpy(&RawValue, &Value, sizeof(Value));
+    char buf[30];
+    int CharsPrinted =
+        snprintf(buf, llvm::array_lengthof(buf), T::PrintfString, RawValue);
+    assert(CharsPrinted >= 0 &&
+           (size_t)CharsPrinted < llvm::array_lengthof(buf));
+    (void)CharsPrinted; // avoid warnings if asserts are disabled
+    Const->emitPoolLabel(Str);
+    Str << ":\n\t" << T::AsmTag << "\t" << buf << "\t# " << T::TypeName << " "
+        << Value << "\n";
+  }
+}
+
+void TargetGlobalX8632::lowerConstants(GlobalContext *Ctx) const {
+  if (Ctx->getFlags().DisableTranslation)
+    return;
+  // No need to emit constants from the int pool since (for x86) they
+  // are embedded as immediates in the instructions, just emit float/double.
+  if (Ctx->getFlags().UseELFWriter) {
+    ELFObjectWriter *Writer = Ctx->getObjectWriter();
+    Writer->writeConstantPool<ConstantFloat>(IceType_f32);
+    Writer->writeConstantPool<ConstantDouble>(IceType_f64);
+  } else {
+    OstreamLocker L(Ctx);
+    emitConstantPool<PoolTypeConverter<float>>(Ctx);
+    emitConstantPool<PoolTypeConverter<double>>(Ctx);
+  }
+}
+
 } // end of namespace Ice