OSDN Git Service

Merge x86 data and header lowering
authorDavid Sehr <sehr@chromium.org>
Fri, 22 Jan 2016 07:16:58 +0000 (23:16 -0800)
committerDavid Sehr <sehr@chromium.org>
Fri, 22 Jan 2016 07:16:58 +0000 (23:16 -0800)
BUG=
R=stichnot@chromium.org

Review URL: https://codereview.chromium.org/1616673004 .

Makefile.standalone
src/IceTargetLoweringX86.cpp [new file with mode: 0644]
src/IceTargetLoweringX8632.cpp
src/IceTargetLoweringX8632.h
src/IceTargetLoweringX8664.cpp
src/IceTargetLoweringX8664.h
src/IceTargetLoweringX86Base.h
src/IceTargetLoweringX86BaseImpl.h

index 4549618..98ba05e 100644 (file)
@@ -250,6 +250,7 @@ SRCS = \
   IceTargetLowering.cpp \
   IceTargetLoweringARM32.cpp \
   IceTargetLoweringMIPS32.cpp \
+  IceTargetLoweringX86.cpp \
   IceTargetLoweringX8632.cpp \
   IceTargetLoweringX8664.cpp \
   IceAssembler.cpp \
diff --git a/src/IceTargetLoweringX86.cpp b/src/IceTargetLoweringX86.cpp
new file mode 100644 (file)
index 0000000..8fbd075
--- /dev/null
@@ -0,0 +1,50 @@
+//===---- subzero/src/IceTargetLoweringX86.cpp - x86 lowering -*- C++ -*---===//
+//
+//                        The Subzero Code Generator
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Implements portions of the TargetLoweringX86Base class, and related
+/// classes.
+///
+//===----------------------------------------------------------------------===//
+
+// Choose one namespace, since including this file should not cause the
+// templates to be instantiated.  This avoids duplicating the PoolTypeConverter
+// data items, but is ugly as code common to all of x86 is including code
+// specific to one of 32 or 64.
+// TODO(jpp): replace this ugliness with the beauty of extern template.
+
+#define X86NAMESPACE X8632
+#include "IceTargetLoweringX86Base.h"
+#undef X86NAMESPACE
+
+namespace Ice {
+namespace X86 {
+
+const char *PoolTypeConverter<float>::TypeName = "float";
+const char *PoolTypeConverter<float>::AsmTag = ".long";
+const char *PoolTypeConverter<float>::PrintfString = "0x%x";
+
+const char *PoolTypeConverter<double>::TypeName = "double";
+const char *PoolTypeConverter<double>::AsmTag = ".quad";
+const char *PoolTypeConverter<double>::PrintfString = "0x%llx";
+
+const char *PoolTypeConverter<uint32_t>::TypeName = "i32";
+const char *PoolTypeConverter<uint32_t>::AsmTag = ".long";
+const char *PoolTypeConverter<uint32_t>::PrintfString = "0x%x";
+
+const char *PoolTypeConverter<uint16_t>::TypeName = "i16";
+const char *PoolTypeConverter<uint16_t>::AsmTag = ".short";
+const char *PoolTypeConverter<uint16_t>::PrintfString = "0x%x";
+
+const char *PoolTypeConverter<uint8_t>::TypeName = "i8";
+const char *PoolTypeConverter<uint8_t>::AsmTag = ".byte";
+const char *PoolTypeConverter<uint8_t>::PrintfString = "0x%x";
+
+} // end of namespace X86
+} // end of namespace Ice
index e9164f6..0460222 100644 (file)
@@ -24,12 +24,13 @@ std::unique_ptr<::Ice::TargetLowering> createTargetLowering(::Ice::Cfg *Func) {
 
 std::unique_ptr<::Ice::TargetDataLowering>
 createTargetDataLowering(::Ice::GlobalContext *Ctx) {
-  return ::Ice::X8632::TargetDataX8632::create(Ctx);
+  return ::Ice::X8632::TargetDataX86<::Ice::X8632::TargetX8632Traits>::create(
+      Ctx);
 }
 
 std::unique_ptr<::Ice::TargetHeaderLowering>
 createTargetHeaderLowering(::Ice::GlobalContext *Ctx) {
-  return ::Ice::X8632::TargetHeaderX8632::create(Ctx);
+  return ::Ice::X8632::TargetHeaderX86::create(Ctx);
 }
 
 void staticInit(::Ice::GlobalContext *Ctx) {
@@ -269,228 +270,6 @@ void TargetX8632::emitSandboxedReturn() {
   lowerIndirectJump(T_ecx);
 }
 
-void TargetX8632::emitJumpTable(const Cfg *Func,
-                                const InstJumpTable *JumpTable) const {
-  if (!BuildDefs::dump())
-    return;
-  Ostream &Str = Ctx->getStrEmit();
-  const bool UseNonsfi = Ctx->getFlags().getUseNonsfi();
-  const IceString MangledName = Ctx->mangleName(Func->getFunctionName());
-  const IceString Prefix = UseNonsfi ? ".data.rel.ro." : ".rodata.";
-  Str << "\t.section\t" << Prefix << MangledName
-      << "$jumptable,\"a\",@progbits\n";
-  Str << "\t.align\t" << typeWidthInBytes(getPointerType()) << "\n";
-  Str << InstJumpTable::makeName(MangledName, JumpTable->getId()) << ":";
-
-  // On X8632 pointers are 32-bit hence the use of .long
-  for (SizeT I = 0; I < JumpTable->getNumTargets(); ++I)
-    Str << "\n\t.long\t" << JumpTable->getTarget(I)->getAsmName();
-  Str << "\n";
-}
-
-TargetDataX8632::TargetDataX8632(GlobalContext *Ctx)
-    : TargetDataLowering(Ctx) {}
-
-namespace {
-template <typename T> struct PoolTypeConverter {};
-
-template <> struct PoolTypeConverter<float> {
-  using PrimitiveIntType = uint32_t;
-  using IceType = ConstantFloat;
-  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> {
-  using PrimitiveIntType = uint64_t;
-  using IceType = ConstantDouble;
-  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";
-
-// Add converter for int type constant pooling
-template <> struct PoolTypeConverter<uint32_t> {
-  using PrimitiveIntType = uint32_t;
-  using IceType = ConstantInteger32;
-  static const Type Ty = IceType_i32;
-  static const char *TypeName;
-  static const char *AsmTag;
-  static const char *PrintfString;
-};
-const char *PoolTypeConverter<uint32_t>::TypeName = "i32";
-const char *PoolTypeConverter<uint32_t>::AsmTag = ".long";
-const char *PoolTypeConverter<uint32_t>::PrintfString = "0x%x";
-
-// Add converter for int type constant pooling
-template <> struct PoolTypeConverter<uint16_t> {
-  using PrimitiveIntType = uint32_t;
-  using IceType = ConstantInteger32;
-  static const Type Ty = IceType_i16;
-  static const char *TypeName;
-  static const char *AsmTag;
-  static const char *PrintfString;
-};
-const char *PoolTypeConverter<uint16_t>::TypeName = "i16";
-const char *PoolTypeConverter<uint16_t>::AsmTag = ".short";
-const char *PoolTypeConverter<uint16_t>::PrintfString = "0x%x";
-
-// Add converter for int type constant pooling
-template <> struct PoolTypeConverter<uint8_t> {
-  using PrimitiveIntType = uint32_t;
-  using IceType = ConstantInteger32;
-  static const Type Ty = IceType_i8;
-  static const char *TypeName;
-  static const char *AsmTag;
-  static const char *PrintfString;
-};
-const char *PoolTypeConverter<uint8_t>::TypeName = "i8";
-const char *PoolTypeConverter<uint8_t>::AsmTag = ".byte";
-const char *PoolTypeConverter<uint8_t>::PrintfString = "0x%x";
-} // end of anonymous namespace
-
-template <typename T>
-void TargetDataX8632::emitConstantPool(GlobalContext *Ctx) {
-  if (!BuildDefs::dump())
-    return;
-  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";
-
-  // If reorder-pooled-constants option is set to true, we need to shuffle the
-  // constant pool before emitting it.
-  if (Ctx->getFlags().shouldReorderPooledConstants() && !Pool.empty()) {
-    // Use the constant's kind value as the salt for creating random number
-    // generator.
-    Operand::OperandKind K = (*Pool.begin())->getKind();
-
-    RandomNumberGenerator RNG(Ctx->getFlags().getRandomSeed(),
-                              RPE_PooledConstantReordering, K);
-    RandomShuffle(Pool.begin(), Pool.end(),
-                  [&RNG](uint64_t N) { return (uint32_t)RNG.next(N); });
-  }
-
-  for (Constant *C : Pool) {
-    if (!C->getShouldBePooled())
-      continue;
-    auto *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, Ctx);
-    Str << ":\n\t" << T::AsmTag << "\t" << buf << "\t/* " << T::TypeName << " "
-        << Value << " */\n";
-  }
-}
-
-void TargetDataX8632::lowerConstants() {
-  if (Ctx->getFlags().getDisableTranslation())
-    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.
-  switch (Ctx->getFlags().getOutFileType()) {
-  case FT_Elf: {
-    ELFObjectWriter *Writer = Ctx->getObjectWriter();
-
-    Writer->writeConstantPool<ConstantInteger32>(IceType_i8);
-    Writer->writeConstantPool<ConstantInteger32>(IceType_i16);
-    Writer->writeConstantPool<ConstantInteger32>(IceType_i32);
-
-    Writer->writeConstantPool<ConstantFloat>(IceType_f32);
-    Writer->writeConstantPool<ConstantDouble>(IceType_f64);
-  } break;
-  case FT_Asm:
-  case FT_Iasm: {
-    OstreamLocker L(Ctx);
-
-    emitConstantPool<PoolTypeConverter<uint8_t>>(Ctx);
-    emitConstantPool<PoolTypeConverter<uint16_t>>(Ctx);
-    emitConstantPool<PoolTypeConverter<uint32_t>>(Ctx);
-
-    emitConstantPool<PoolTypeConverter<float>>(Ctx);
-    emitConstantPool<PoolTypeConverter<double>>(Ctx);
-  } break;
-  }
-}
-
-void TargetDataX8632::lowerJumpTables() {
-  const bool IsPIC = Ctx->getFlags().getUseNonsfi();
-  switch (Ctx->getFlags().getOutFileType()) {
-  case FT_Elf: {
-    ELFObjectWriter *Writer = Ctx->getObjectWriter();
-    for (const JumpTableData &JT : Ctx->getJumpTables())
-      Writer->writeJumpTable(JT, TargetX8632::Traits::FK_Abs, IsPIC);
-  } break;
-  case FT_Asm:
-    // Already emitted from Cfg
-    break;
-  case FT_Iasm: {
-    if (!BuildDefs::dump())
-      return;
-    Ostream &Str = Ctx->getStrEmit();
-    const IceString Prefix = IsPIC ? ".data.rel.ro." : ".rodata.";
-    for (const JumpTableData &JT : Ctx->getJumpTables()) {
-      Str << "\t.section\t" << Prefix << JT.getFunctionName()
-          << "$jumptable,\"a\",@progbits\n";
-      Str << "\t.align\t" << typeWidthInBytes(getPointerType()) << "\n";
-      Str << InstJumpTable::makeName(JT.getFunctionName(), JT.getId()) << ":";
-
-      // On X8632 pointers are 32-bit hence the use of .long
-      for (intptr_t TargetOffset : JT.getTargetOffsets())
-        Str << "\n\t.long\t" << JT.getFunctionName() << "+" << TargetOffset;
-      Str << "\n";
-    }
-  } break;
-  }
-}
-
-void TargetDataX8632::lowerGlobals(const VariableDeclarationList &Vars,
-                                   const IceString &SectionSuffix) {
-  const bool IsPIC = Ctx->getFlags().getUseNonsfi();
-  switch (Ctx->getFlags().getOutFileType()) {
-  case FT_Elf: {
-    ELFObjectWriter *Writer = Ctx->getObjectWriter();
-    Writer->writeDataSection(Vars, TargetX8632::Traits::FK_Abs, SectionSuffix,
-                             IsPIC);
-  } break;
-  case FT_Asm:
-  case FT_Iasm: {
-    const IceString &TranslateOnly = Ctx->getFlags().getTranslateOnly();
-    OstreamLocker L(Ctx);
-    for (const VariableDeclaration *Var : Vars) {
-      if (GlobalContext::matchSymbolName(Var->getName(), TranslateOnly)) {
-        emitGlobal(*Var, SectionSuffix);
-      }
-    }
-  } break;
-  }
-}
-
-TargetHeaderX8632::TargetHeaderX8632(GlobalContext *Ctx)
-    : TargetHeaderLowering(Ctx) {}
-
 // In some cases, there are x-macros tables for both high-level and low-level
 // instructions/operands that use the same enum key value. The tables are kept
 // separate to maintain a proper separation between abstraction layers. There
index 5b2d6b0..96f1e2c 100644 (file)
@@ -34,9 +34,6 @@ class TargetX8632 final : public ::Ice::X8632::TargetX86Base<X8632::Traits> {
   TargetX8632(const TargetX8632 &) = delete;
   TargetX8632 &operator=(const TargetX8632 &) = delete;
 
-  void emitJumpTable(const Cfg *Func,
-                     const InstJumpTable *JumpTable) const override;
-
 public:
   ~TargetX8632() = default;
 
@@ -70,55 +67,14 @@ private:
   ENABLE_MAKE_UNIQUE;
   friend class X8632::TargetX86Base<X8632::Traits>;
 
+  explicit TargetX8632(Cfg *Func) : TargetX86Base(Func) {}
+
   Operand *createNaClReadTPSrcOperand() {
     Constant *Zero = Ctx->getConstantZero(IceType_i32);
     return Traits::X86OperandMem::create(Func, IceType_i32, nullptr, Zero,
                                          nullptr, 0,
                                          Traits::X86OperandMem::SegReg_GS);
   }
-
-  explicit TargetX8632(Cfg *Func) : TargetX86Base(Func) {}
-};
-
-class TargetDataX8632 final : public TargetDataLowering {
-  TargetDataX8632() = delete;
-  TargetDataX8632(const TargetDataX8632 &) = delete;
-  TargetDataX8632 &operator=(const TargetDataX8632 &) = delete;
-
-public:
-  ~TargetDataX8632() override = default;
-
-  static std::unique_ptr<TargetDataLowering> create(GlobalContext *Ctx) {
-    return makeUnique<TargetDataX8632>(Ctx);
-  }
-
-  void lowerGlobals(const VariableDeclarationList &Vars,
-                    const IceString &SectionSuffix) override;
-  void lowerConstants() override;
-  void lowerJumpTables() override;
-
-private:
-  ENABLE_MAKE_UNIQUE;
-
-  explicit TargetDataX8632(GlobalContext *Ctx);
-  template <typename T> static void emitConstantPool(GlobalContext *Ctx);
-};
-
-class TargetHeaderX8632 final : public TargetHeaderLowering {
-  TargetHeaderX8632() = delete;
-  TargetHeaderX8632(const TargetHeaderX8632 &) = delete;
-  TargetHeaderX8632 &operator=(const TargetHeaderX8632 &) = delete;
-
-public:
-  static std::unique_ptr<TargetHeaderLowering> create(GlobalContext *Ctx) {
-    return std::unique_ptr<TargetHeaderLowering>(new TargetHeaderX8632(Ctx));
-  }
-
-protected:
-  explicit TargetHeaderX8632(GlobalContext *Ctx);
-
-private:
-  ~TargetHeaderX8632() = default;
 };
 
 } // end of namespace X8632
index c023949..49a35ad 100644 (file)
@@ -24,12 +24,13 @@ std::unique_ptr<::Ice::TargetLowering> createTargetLowering(::Ice::Cfg *Func) {
 
 std::unique_ptr<::Ice::TargetDataLowering>
 createTargetDataLowering(::Ice::GlobalContext *Ctx) {
-  return ::Ice::X8664::TargetDataX8664::create(Ctx);
+  return ::Ice::X8664::TargetDataX86<::Ice::X8664::TargetX8664Traits>::create(
+      Ctx);
 }
 
 std::unique_ptr<::Ice::TargetHeaderLowering>
 createTargetHeaderLowering(::Ice::GlobalContext *Ctx) {
-  return ::Ice::X8664::TargetHeaderX8664::create(Ctx);
+  return ::Ice::X8664::TargetHeaderX86::create(Ctx);
 }
 
 void staticInit(::Ice::GlobalContext *Ctx) {
@@ -547,218 +548,6 @@ void TargetX8664::emitSandboxedReturn() {
   }
 }
 
-void TargetX8664::emitJumpTable(const Cfg *Func,
-                                const InstJumpTable *JumpTable) const {
-  if (!BuildDefs::dump())
-    return;
-  Ostream &Str = Ctx->getStrEmit();
-  IceString MangledName = Ctx->mangleName(Func->getFunctionName());
-  Str << "\t.section\t.rodata." << MangledName
-      << "$jumptable,\"a\",@progbits\n";
-  Str << "\t.align\t" << typeWidthInBytes(getPointerType()) << "\n";
-  Str << InstJumpTable::makeName(MangledName, JumpTable->getId()) << ":";
-
-  // On X8664 ILP32 pointers are 32-bit hence the use of .long
-  for (SizeT I = 0; I < JumpTable->getNumTargets(); ++I)
-    Str << "\n\t.long\t" << JumpTable->getTarget(I)->getAsmName();
-  Str << "\n";
-}
-
-namespace {
-template <typename T> struct PoolTypeConverter {};
-
-template <> struct PoolTypeConverter<float> {
-  using PrimitiveIntType = uint32_t;
-  using IceType = ConstantFloat;
-  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> {
-  using PrimitiveIntType = uint64_t;
-  using IceType = ConstantDouble;
-  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";
-
-// Add converter for int type constant pooling
-template <> struct PoolTypeConverter<uint32_t> {
-  using PrimitiveIntType = uint32_t;
-  using IceType = ConstantInteger32;
-  static const Type Ty = IceType_i32;
-  static const char *TypeName;
-  static const char *AsmTag;
-  static const char *PrintfString;
-};
-const char *PoolTypeConverter<uint32_t>::TypeName = "i32";
-const char *PoolTypeConverter<uint32_t>::AsmTag = ".long";
-const char *PoolTypeConverter<uint32_t>::PrintfString = "0x%x";
-
-// Add converter for int type constant pooling
-template <> struct PoolTypeConverter<uint16_t> {
-  using PrimitiveIntType = uint32_t;
-  using IceType = ConstantInteger32;
-  static const Type Ty = IceType_i16;
-  static const char *TypeName;
-  static const char *AsmTag;
-  static const char *PrintfString;
-};
-const char *PoolTypeConverter<uint16_t>::TypeName = "i16";
-const char *PoolTypeConverter<uint16_t>::AsmTag = ".short";
-const char *PoolTypeConverter<uint16_t>::PrintfString = "0x%x";
-
-// Add converter for int type constant pooling
-template <> struct PoolTypeConverter<uint8_t> {
-  using PrimitiveIntType = uint32_t;
-  using IceType = ConstantInteger32;
-  static const Type Ty = IceType_i8;
-  static const char *TypeName;
-  static const char *AsmTag;
-  static const char *PrintfString;
-};
-const char *PoolTypeConverter<uint8_t>::TypeName = "i8";
-const char *PoolTypeConverter<uint8_t>::AsmTag = ".byte";
-const char *PoolTypeConverter<uint8_t>::PrintfString = "0x%x";
-} // end of anonymous namespace
-
-template <typename T>
-void TargetDataX8664::emitConstantPool(GlobalContext *Ctx) {
-  if (!BuildDefs::dump())
-    return;
-  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";
-
-  // If reorder-pooled-constants option is set to true, we need to shuffle the
-  // constant pool before emitting it.
-  if (Ctx->getFlags().shouldReorderPooledConstants()) {
-    // Use the constant's kind value as the salt for creating random number
-    // generator.
-    Operand::OperandKind K = (*Pool.begin())->getKind();
-    RandomNumberGenerator RNG(Ctx->getFlags().getRandomSeed(),
-                              RPE_PooledConstantReordering, K);
-    RandomShuffle(Pool.begin(), Pool.end(),
-                  [&RNG](uint64_t N) { return (uint32_t)RNG.next(N); });
-  }
-
-  for (Constant *C : Pool) {
-    if (!C->getShouldBePooled())
-      continue;
-    auto *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, Ctx);
-    Str << ":\n\t" << T::AsmTag << "\t" << buf << "\t/* " << T::TypeName << " "
-        << Value << " */\n";
-  }
-}
-
-void TargetDataX8664::lowerConstants() {
-  if (Ctx->getFlags().getDisableTranslation())
-    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.
-  switch (Ctx->getFlags().getOutFileType()) {
-  case FT_Elf: {
-    ELFObjectWriter *Writer = Ctx->getObjectWriter();
-
-    Writer->writeConstantPool<ConstantInteger32>(IceType_i8);
-    Writer->writeConstantPool<ConstantInteger32>(IceType_i16);
-    Writer->writeConstantPool<ConstantInteger32>(IceType_i32);
-
-    Writer->writeConstantPool<ConstantFloat>(IceType_f32);
-    Writer->writeConstantPool<ConstantDouble>(IceType_f64);
-  } break;
-  case FT_Asm:
-  case FT_Iasm: {
-    OstreamLocker L(Ctx);
-
-    emitConstantPool<PoolTypeConverter<uint8_t>>(Ctx);
-    emitConstantPool<PoolTypeConverter<uint16_t>>(Ctx);
-    emitConstantPool<PoolTypeConverter<uint32_t>>(Ctx);
-
-    emitConstantPool<PoolTypeConverter<float>>(Ctx);
-    emitConstantPool<PoolTypeConverter<double>>(Ctx);
-  } break;
-  }
-}
-
-void TargetDataX8664::lowerJumpTables() {
-  const bool IsPIC = Ctx->getFlags().getUseNonsfi();
-  switch (Ctx->getFlags().getOutFileType()) {
-  case FT_Elf: {
-    ELFObjectWriter *Writer = Ctx->getObjectWriter();
-    for (const JumpTableData &JumpTable : Ctx->getJumpTables())
-      Writer->writeJumpTable(JumpTable, TargetX8664::Traits::FK_Abs, IsPIC);
-  } break;
-  case FT_Asm:
-    // Already emitted from Cfg
-    break;
-  case FT_Iasm: {
-    if (!BuildDefs::dump())
-      return;
-    Ostream &Str = Ctx->getStrEmit();
-    for (const JumpTableData &JT : Ctx->getJumpTables()) {
-      Str << "\t.section\t.rodata." << JT.getFunctionName()
-          << "$jumptable,\"a\",@progbits\n";
-      Str << "\t.align\t" << typeWidthInBytes(getPointerType()) << "\n";
-      Str << InstJumpTable::makeName(JT.getFunctionName(), JT.getId()) << ":";
-
-      // On X8664 ILP32 pointers are 32-bit hence the use of .long
-      for (intptr_t TargetOffset : JT.getTargetOffsets())
-        Str << "\n\t.long\t" << JT.getFunctionName() << "+" << TargetOffset;
-      Str << "\n";
-    }
-  } break;
-  }
-}
-
-void TargetDataX8664::lowerGlobals(const VariableDeclarationList &Vars,
-                                   const IceString &SectionSuffix) {
-  const bool IsPIC = Ctx->getFlags().getUseNonsfi();
-  switch (Ctx->getFlags().getOutFileType()) {
-  case FT_Elf: {
-    ELFObjectWriter *Writer = Ctx->getObjectWriter();
-    Writer->writeDataSection(Vars, TargetX8664::Traits::FK_Abs, SectionSuffix,
-                             IsPIC);
-  } break;
-  case FT_Asm:
-  case FT_Iasm: {
-    const IceString &TranslateOnly = Ctx->getFlags().getTranslateOnly();
-    OstreamLocker L(Ctx);
-    for (const VariableDeclaration *Var : Vars) {
-      if (GlobalContext::matchSymbolName(Var->getName(), TranslateOnly)) {
-        emitGlobal(*Var, SectionSuffix);
-      }
-    }
-  } break;
-  }
-}
-
 // In some cases, there are x-macros tables for both high-level and low-level
 // instructions/operands that use the same enum key value. The tables are kept
 // separate to maintain a proper separation between abstraction layers. There
index 0a3cdef..7ab3025 100644 (file)
@@ -34,9 +34,6 @@ class TargetX8664 final : public X8664::TargetX86Base<X8664::Traits> {
   TargetX8664(const TargetX8664 &) = delete;
   TargetX8664 &operator=(const TargetX8664 &) = delete;
 
-  void emitJumpTable(const Cfg *Func,
-                     const InstJumpTable *JumpTable) const override;
-
 public:
   ~TargetX8664() = default;
 
@@ -49,12 +46,9 @@ public:
     return makeUnique<X8664::AssemblerX8664>(EmitAddrSizeOverridePrefix);
   }
 
-  bool needSandboxing() const { return NeedSandboxing; }
-
 protected:
   void _add_sp(Operand *Adjustment);
   void _mov_sp(Operand *NewValue);
-  void _push_rbp();
   Traits::X86OperandMem *_sandbox_mem_reference(X86OperandMem *Mem);
   void _sub_sp(Operand *Adjustment);
   void _link_bp();
@@ -72,8 +66,9 @@ private:
   ENABLE_MAKE_UNIQUE;
   friend class X8664::TargetX86Base<X8664::Traits>;
 
-  explicit TargetX8664(Cfg *Func)
-      : ::Ice::X8664::TargetX86Base<X8664::Traits>(Func) {}
+  explicit TargetX8664(Cfg *Func) : TargetX86Base(Func) {}
+
+  void _push_rbp();
 
   Operand *createNaClReadTPSrcOperand() {
     Variable *TDB = makeReg(IceType_i32);
@@ -83,49 +78,6 @@ private:
   }
 };
 
-class TargetDataX8664 : public TargetDataLowering {
-  TargetDataX8664() = delete;
-  TargetDataX8664(const TargetDataX8664 &) = delete;
-  TargetDataX8664 &operator=(const TargetDataX8664 &) = delete;
-
-public:
-  ~TargetDataX8664() override = default;
-
-  static std::unique_ptr<TargetDataLowering> create(GlobalContext *Ctx) {
-    return makeUnique<TargetDataX8664>(Ctx);
-  }
-
-  void lowerGlobals(const VariableDeclarationList &Vars,
-                    const IceString &SectionSuffix) override;
-
-  void lowerConstants() override;
-  void lowerJumpTables() override;
-
-private:
-  ENABLE_MAKE_UNIQUE;
-
-  explicit TargetDataX8664(GlobalContext *Ctx) : TargetDataLowering(Ctx) {}
-  template <typename T> static void emitConstantPool(GlobalContext *Ctx);
-};
-
-class TargetHeaderX8664 : public TargetHeaderLowering {
-  TargetHeaderX8664() = delete;
-  TargetHeaderX8664(const TargetHeaderX8664 &) = delete;
-  TargetHeaderX8664 &operator=(const TargetHeaderX8664 &) = delete;
-
-public:
-  ~TargetHeaderX8664() = default;
-
-  static std::unique_ptr<TargetHeaderLowering> create(GlobalContext *Ctx) {
-    return makeUnique<TargetHeaderX8664>(Ctx);
-  }
-
-private:
-  ENABLE_MAKE_UNIQUE;
-
-  explicit TargetHeaderX8664(GlobalContext *Ctx) : TargetHeaderLowering(Ctx) {}
-};
-
 } // end of namespace X8664
 } // end of namespace Ice
 
index 2a4a728..e3e67a0 100644 (file)
@@ -298,6 +298,10 @@ protected:
   virtual Variable *moveReturnValueToRegister(Operand *Value,
                                               Type ReturnType) = 0;
 
+  /// Emit a jump table to the constant pool.
+  void emitJumpTable(const Cfg *Func,
+                     const InstJumpTable *JumpTable) const override;
+
   /// Emit a fake use of esp to make sure esp stays alive for the entire
   /// function. Otherwise some esp adjustments get dead-code eliminated.
   void keepEspLiveAtExit() {
@@ -1020,6 +1024,51 @@ private:
   static FixupKind PcRelFixup;
   static FixupKind AbsFixup;
 };
+
+template <typename TraitsType>
+class TargetDataX86 final : public TargetDataLowering {
+  using Traits = TraitsType;
+  TargetDataX86() = delete;
+  TargetDataX86(const TargetDataX86 &) = delete;
+  TargetDataX86 &operator=(const TargetDataX86 &) = delete;
+
+public:
+  ~TargetDataX86() override = default;
+
+  static std::unique_ptr<TargetDataLowering> create(GlobalContext *Ctx) {
+    return makeUnique<TargetDataX86>(Ctx);
+  }
+
+  void lowerGlobals(const VariableDeclarationList &Vars,
+                    const IceString &SectionSuffix) override;
+  void lowerConstants() override;
+  void lowerJumpTables() override;
+
+private:
+  ENABLE_MAKE_UNIQUE;
+
+  explicit TargetDataX86(GlobalContext *Ctx) : TargetDataLowering(Ctx){};
+  template <typename T> static void emitConstantPool(GlobalContext *Ctx);
+};
+
+class TargetHeaderX86 : public TargetHeaderLowering {
+  TargetHeaderX86() = delete;
+  TargetHeaderX86(const TargetHeaderX86 &) = delete;
+  TargetHeaderX86 &operator=(const TargetHeaderX86 &) = delete;
+
+public:
+  ~TargetHeaderX86() = default;
+
+  static std::unique_ptr<TargetHeaderLowering> create(GlobalContext *Ctx) {
+    return makeUnique<TargetHeaderX86>(Ctx);
+  }
+
+private:
+  ENABLE_MAKE_UNIQUE;
+
+  explicit TargetHeaderX86(GlobalContext *Ctx) : TargetHeaderLowering(Ctx) {}
+};
+
 } // end of namespace X86NAMESPACE
 } // end of namespace Ice
 
index e70c757..4d54236 100644 (file)
 #include <stack>
 
 namespace Ice {
+namespace X86 {
+template <typename T> struct PoolTypeConverter {};
+
+template <> struct PoolTypeConverter<float> {
+  using PrimitiveIntType = uint32_t;
+  using IceType = ConstantFloat;
+  static const Type Ty = IceType_f32;
+  static const char *TypeName;
+  static const char *AsmTag;
+  static const char *PrintfString;
+};
+
+template <> struct PoolTypeConverter<double> {
+  using PrimitiveIntType = uint64_t;
+  using IceType = ConstantDouble;
+  static const Type Ty = IceType_f64;
+  static const char *TypeName;
+  static const char *AsmTag;
+  static const char *PrintfString;
+};
+
+// Add converter for int type constant pooling
+template <> struct PoolTypeConverter<uint32_t> {
+  using PrimitiveIntType = uint32_t;
+  using IceType = ConstantInteger32;
+  static const Type Ty = IceType_i32;
+  static const char *TypeName;
+  static const char *AsmTag;
+  static const char *PrintfString;
+};
+
+// Add converter for int type constant pooling
+template <> struct PoolTypeConverter<uint16_t> {
+  using PrimitiveIntType = uint32_t;
+  using IceType = ConstantInteger32;
+  static const Type Ty = IceType_i16;
+  static const char *TypeName;
+  static const char *AsmTag;
+  static const char *PrintfString;
+};
+
+// Add converter for int type constant pooling
+template <> struct PoolTypeConverter<uint8_t> {
+  using PrimitiveIntType = uint32_t;
+  using IceType = ConstantInteger32;
+  static const Type Ty = IceType_i8;
+  static const char *TypeName;
+  static const char *AsmTag;
+  static const char *PrintfString;
+};
+} // end of namespace X86
+
 namespace X86NAMESPACE {
 
 /// A helper class to ease the settings of RandomizationPoolingPause to disable
@@ -7229,6 +7281,156 @@ TargetX86Base<TraitsType>::randomizeOrPoolImmediate(X86OperandMem *MemOperand,
   }
   }
 }
+
+template <typename TraitsType>
+void TargetX86Base<TraitsType>::emitJumpTable(
+    const Cfg *Func, const InstJumpTable *JumpTable) const {
+  if (!BuildDefs::dump())
+    return;
+  Ostream &Str = Ctx->getStrEmit();
+  const bool UseNonsfi = Ctx->getFlags().getUseNonsfi();
+  const IceString MangledName = Ctx->mangleName(Func->getFunctionName());
+  const IceString Prefix = UseNonsfi ? ".data.rel.ro." : ".rodata.";
+  Str << "\t.section\t" << Prefix << MangledName
+      << "$jumptable,\"a\",@progbits\n";
+  Str << "\t.align\t" << typeWidthInBytes(getPointerType()) << "\n";
+  Str << InstJumpTable::makeName(MangledName, JumpTable->getId()) << ":";
+
+  // On X86 ILP32 pointers are 32-bit hence the use of .long
+  for (SizeT I = 0; I < JumpTable->getNumTargets(); ++I)
+    Str << "\n\t.long\t" << JumpTable->getTarget(I)->getAsmName();
+  Str << "\n";
+}
+
+template <typename TraitsType>
+template <typename T>
+void TargetDataX86<TraitsType>::emitConstantPool(GlobalContext *Ctx) {
+  if (!BuildDefs::dump())
+    return;
+  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";
+
+  // If reorder-pooled-constants option is set to true, we need to shuffle the
+  // constant pool before emitting it.
+  if (Ctx->getFlags().shouldReorderPooledConstants() && !Pool.empty()) {
+    // Use the constant's kind value as the salt for creating random number
+    // generator.
+    Operand::OperandKind K = (*Pool.begin())->getKind();
+    RandomNumberGenerator RNG(Ctx->getFlags().getRandomSeed(),
+                              RPE_PooledConstantReordering, K);
+    RandomShuffle(Pool.begin(), Pool.end(),
+                  [&RNG](uint64_t N) { return (uint32_t)RNG.next(N); });
+  }
+
+  for (Constant *C : Pool) {
+    if (!C->getShouldBePooled())
+      continue;
+    auto *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);
+    assert((size_t)CharsPrinted < llvm::array_lengthof(buf));
+    (void)CharsPrinted; // avoid warnings if asserts are disabled
+    Const->emitPoolLabel(Str, Ctx);
+    Str << ":\n\t" << T::AsmTag << "\t" << buf << "\t/* " << T::TypeName << " "
+        << Value << " */\n";
+  }
+}
+
+template <typename TraitsType>
+void TargetDataX86<TraitsType>::lowerConstants() {
+  if (Ctx->getFlags().getDisableTranslation())
+    return;
+  switch (Ctx->getFlags().getOutFileType()) {
+  case FT_Elf: {
+    ELFObjectWriter *Writer = Ctx->getObjectWriter();
+
+    Writer->writeConstantPool<ConstantInteger32>(IceType_i8);
+    Writer->writeConstantPool<ConstantInteger32>(IceType_i16);
+    Writer->writeConstantPool<ConstantInteger32>(IceType_i32);
+
+    Writer->writeConstantPool<ConstantFloat>(IceType_f32);
+    Writer->writeConstantPool<ConstantDouble>(IceType_f64);
+  } break;
+  case FT_Asm:
+  case FT_Iasm: {
+    OstreamLocker L(Ctx);
+
+    emitConstantPool<PoolTypeConverter<uint8_t>>(Ctx);
+    emitConstantPool<PoolTypeConverter<uint16_t>>(Ctx);
+    emitConstantPool<PoolTypeConverter<uint32_t>>(Ctx);
+
+    emitConstantPool<PoolTypeConverter<float>>(Ctx);
+    emitConstantPool<PoolTypeConverter<double>>(Ctx);
+  } break;
+  }
+}
+
+template <typename TraitsType>
+void TargetDataX86<TraitsType>::lowerJumpTables() {
+  const bool IsPIC = Ctx->getFlags().getUseNonsfi();
+  switch (Ctx->getFlags().getOutFileType()) {
+  case FT_Elf: {
+    ELFObjectWriter *Writer = Ctx->getObjectWriter();
+    for (const JumpTableData &JT : Ctx->getJumpTables())
+      Writer->writeJumpTable(JT, Traits::FK_Abs, IsPIC);
+  } break;
+  case FT_Asm:
+    // Already emitted from Cfg
+    break;
+  case FT_Iasm: {
+    if (!BuildDefs::dump())
+      return;
+    Ostream &Str = Ctx->getStrEmit();
+    const IceString Prefix = IsPIC ? ".data.rel.ro." : ".rodata.";
+    for (const JumpTableData &JT : Ctx->getJumpTables()) {
+      Str << "\t.section\t" << Prefix << JT.getFunctionName()
+          << "$jumptable,\"a\",@progbits\n";
+      Str << "\t.align\t" << typeWidthInBytes(getPointerType()) << "\n";
+      Str << InstJumpTable::makeName(JT.getFunctionName(), JT.getId()) << ":";
+
+      // On X8664 ILP32 pointers are 32-bit hence the use of .long
+      for (intptr_t TargetOffset : JT.getTargetOffsets())
+        Str << "\n\t.long\t" << JT.getFunctionName() << "+" << TargetOffset;
+      Str << "\n";
+    }
+  } break;
+  }
+}
+
+template <typename TraitsType>
+void TargetDataX86<TraitsType>::lowerGlobals(
+    const VariableDeclarationList &Vars, const IceString &SectionSuffix) {
+  const bool IsPIC = Ctx->getFlags().getUseNonsfi();
+  switch (Ctx->getFlags().getOutFileType()) {
+  case FT_Elf: {
+    ELFObjectWriter *Writer = Ctx->getObjectWriter();
+    Writer->writeDataSection(Vars, Traits::FK_Abs, SectionSuffix, IsPIC);
+  } break;
+  case FT_Asm:
+  case FT_Iasm: {
+    const IceString &TranslateOnly = Ctx->getFlags().getTranslateOnly();
+    OstreamLocker L(Ctx);
+    for (const VariableDeclaration *Var : Vars) {
+      if (GlobalContext::matchSymbolName(Var->getName(), TranslateOnly)) {
+        emitGlobal(*Var, SectionSuffix);
+      }
+    }
+  } break;
+  }
+}
 } // end of namespace X86NAMESPACE
 } // end of namespace Ice