Subzero: Write float/double constant pools directly to the ELF file.

Create the section, write the data and define the symbols in
the symbol table.

BUG=none
R=stichnot@chromium.org

Review URL: https://codereview.chromium.org/837393005
diff --git a/src/IceELFObjectWriter.cpp b/src/IceELFObjectWriter.cpp
index 3ac8a55..4a31a99 100644
--- a/src/IceELFObjectWriter.cpp
+++ b/src/IceELFObjectWriter.cpp
@@ -17,6 +17,7 @@
 #include "IceELFStreamer.h"
 #include "IceGlobalContext.h"
 #include "IceGlobalInits.h"
+#include "IceOperand.h"
 
 using namespace llvm::ELF;
 
@@ -291,6 +292,61 @@
   Str.writeLE16(static_cast<Elf64_Half>(SectHeaderStrIndex)); // e_shstrndx
 }
 
+template <typename ConstType> void ELFObjectWriter::writeConstantPool(Type Ty) {
+  ConstantList Pool = Ctx.getConstantPool(Ty);
+  if (Pool.empty()) {
+    return;
+  }
+  SizeT Align = typeAlignInBytes(Ty);
+  size_t EntSize = typeWidthInBytes(Ty);
+  char Buf[20];
+  SizeT WriteAmt = std::min(EntSize, llvm::array_lengthof(Buf));
+  assert(WriteAmt == EntSize);
+  // Assume that writing WriteAmt bytes at a time allows us to avoid aligning
+  // between entries.
+  assert(WriteAmt % Align == 0);
+  // Check that we write the full PrimType.
+  assert(WriteAmt == sizeof(typename ConstType::PrimType));
+  const Elf64_Xword ShFlags = SHF_ALLOC | SHF_MERGE;
+  std::string SecBuffer;
+  llvm::raw_string_ostream SecStrBuf(SecBuffer);
+  SecStrBuf << ".rodata.cst" << WriteAmt;
+  ELFDataSection *Section = createSection<ELFDataSection>(
+      SecStrBuf.str(), SHT_PROGBITS, ShFlags, Align, WriteAmt);
+  RoDataSections.push_back(Section);
+  SizeT OffsetInSection = 0;
+  // The symbol table entry doesn't need to know the defined symbol's
+  // size since this is in a section with a fixed Entry Size.
+  const SizeT SymbolSize = 0;
+  Section->setFileOffset(alignFileOffset(Align));
+
+  // Write the data.
+  for (Constant *C : Pool) {
+    auto Const = llvm::cast<ConstType>(C);
+    std::string SymBuffer;
+    llvm::raw_string_ostream SymStrBuf(SymBuffer);
+    SymStrBuf << ".L$" << Ty << "$" << Const->getPoolEntryID();
+    std::string &SymName = SymStrBuf.str();
+    SymTab->createDefinedSym(SymName, STT_NOTYPE, STB_LOCAL, Section,
+                             OffsetInSection, SymbolSize);
+    StrTab->add(SymName);
+    typename ConstType::PrimType Value = Const->getValue();
+    memcpy(Buf, &Value, WriteAmt);
+    Str.writeBytes(llvm::StringRef(Buf, WriteAmt));
+    OffsetInSection += WriteAmt;
+  }
+  Section->setSize(OffsetInSection);
+}
+
+// Instantiate known needed versions of the template, since we are
+// defining the function in the .cpp file instead of the .h file.
+// We may need to instantiate constant pools for integers as well
+// if we do constant-pooling of large integers to remove them
+// from the instruction stream (fewer bytes controlled by an attacker).
+template void ELFObjectWriter::writeConstantPool<ConstantFloat>(Type Ty);
+
+template void ELFObjectWriter::writeConstantPool<ConstantDouble>(Type Ty);
+
 void ELFObjectWriter::writeNonUserSections() {
   bool IsELF64 = isELF64(Ctx.getTargetArch());
 
diff --git a/src/IceELFObjectWriter.h b/src/IceELFObjectWriter.h
index 3dbb9f5..039db62 100644
--- a/src/IceELFObjectWriter.h
+++ b/src/IceELFObjectWriter.h
@@ -17,6 +17,7 @@
 #include "IceDefs.h"
 #include "IceELFSection.h"
 #include "IceELFStreamer.h"
+#include "IceTypes.h"
 
 using namespace llvm::ELF;
 
@@ -59,6 +60,8 @@
   void writeDataInitializer(const IceString &VarName,
                             const llvm::StringRef Data);
 
+  template <typename ConstType> void writeConstantPool(Type Ty);
+
   // Do final layout and write out the rest of the object file, then
   // patch up the initial ELF header with the final info.
   void writeNonUserSections();
diff --git a/src/IceOperand.h b/src/IceOperand.h
index ee06499..035dc16 100644
--- a/src/IceOperand.h
+++ b/src/IceOperand.h
@@ -132,14 +132,16 @@
   ConstantPrimitive &operator=(const ConstantPrimitive &) = delete;
 
 public:
-  static ConstantPrimitive *create(GlobalContext *Ctx, Type Ty, T Value,
+  typedef T PrimType;
+
+  static ConstantPrimitive *create(GlobalContext *Ctx, Type Ty, PrimType Value,
                                    uint32_t PoolEntryID) {
     assert(!Ctx->isIRGenerationDisabled() &&
            "Attempt to build primitive constant when IR generation disabled");
     return new (Ctx->allocate<ConstantPrimitive>())
         ConstantPrimitive(Ty, Value, PoolEntryID);
   }
-  T getValue() const { return Value; }
+  PrimType getValue() const { return Value; }
   using Constant::emit;
   // The target needs to implement this for each ConstantPrimitive
   // specialization.
@@ -155,10 +157,10 @@
   }
 
 private:
-  ConstantPrimitive(Type Ty, T Value, uint32_t PoolEntryID)
+  ConstantPrimitive(Type Ty, PrimType Value, uint32_t PoolEntryID)
       : Constant(K, Ty, PoolEntryID), Value(Value) {}
   ~ConstantPrimitive() override {}
-  const T Value;
+  const PrimType Value;
 };
 
 typedef ConstantPrimitive<int32_t, Operand::kConstInteger32> ConstantInteger32;
diff --git a/src/IceTargetLoweringX8632.cpp b/src/IceTargetLoweringX8632.cpp
index 437f941..5a111b8 100644
--- a/src/IceTargetLoweringX8632.cpp
+++ b/src/IceTargetLoweringX8632.cpp
@@ -967,7 +967,6 @@
 template <typename T> struct PoolTypeConverter {};
 
 template <> struct PoolTypeConverter<float> {
-  typedef float PrimitiveFpType;
   typedef uint32_t PrimitiveIntType;
   typedef ConstantFloat IceType;
   static const Type Ty = IceType_f32;
@@ -980,7 +979,6 @@
 const char *PoolTypeConverter<float>::PrintfString = "0x%x";
 
 template <> struct PoolTypeConverter<double> {
-  typedef double PrimitiveFpType;
   typedef uint64_t PrimitiveIntType;
   typedef ConstantDouble IceType;
   static const Type Ty = IceType_f64;
@@ -1004,7 +1002,7 @@
   Str << "\t.align\t" << Align << "\n";
   for (Constant *C : Pool) {
     typename T::IceType *Const = llvm::cast<typename T::IceType>(C);
-    typename T::PrimitiveFpType Value = Const->getValue();
+    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;
@@ -1022,12 +1020,16 @@
 }
 
 void TargetX8632::emitConstants() const {
-  // Note: Still used by emit IAS.
-  emitConstantPool<PoolTypeConverter<float>>();
-  emitConstantPool<PoolTypeConverter<double>>();
-
   // No need to emit constants from the int pool since (for x86) they
-  // are embedded as immediates in the instructions.
+  // 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 {
+    emitConstantPool<PoolTypeConverter<float>>();
+    emitConstantPool<PoolTypeConverter<double>>();
+  }
 }
 
 void TargetX8632::split64(Variable *Var) {
diff --git a/src/IceTranslator.cpp b/src/IceTranslator.cpp
index a6acfb5..2a50a41 100644
--- a/src/IceTranslator.cpp
+++ b/src/IceTranslator.cpp
@@ -97,13 +97,8 @@
 }
 
 void Translator::emitConstants() {
-  if (!Ctx->getFlags().DisableTranslation && Func) {
-    if (Ctx->getFlags().UseELFWriter) {
-      // TODO(jvoung): create the rodata.cst.{4,8} sections for UseELFWriter.
-    } else {
-      Func->getTarget()->emitConstants();
-    }
-  }
+  if (!Ctx->getFlags().DisableTranslation && Func)
+    Func->getTarget()->emitConstants();
 }
 
 void Translator::lowerGlobals(
diff --git a/tests_lit/llvm2ice_tests/elf_container.ll b/tests_lit/llvm2ice_tests/elf_container.ll
index 3b6f700..4f94255 100644
--- a/tests_lit/llvm2ice_tests/elf_container.ll
+++ b/tests_lit/llvm2ice_tests/elf_container.ll
@@ -38,14 +38,15 @@
 ; Use float/double constants to test constant pools.
 define internal float @returnFloatConst() {
 entry:
-  %f = fadd float 0x3FF3AE1480000000, 0x3FF3AE1400000000
+  %f = fadd float -0.0, 0x3FF3AE1400000000
   ret float %f
 }
 
 define internal double @returnDoubleConst() {
 entry:
-  %d = fadd double 1.230000e+00, 3.210000e+00
-  ret double %d
+  %d = fadd double 0x7FFFFFFFFFFFFFFFF, 0xFFF7FFFFFFFFFFFF
+  %d2 = fadd double %d, 0xFFF8000000000003
+  ret double %d2
 }
 
 define internal void @test_memcpy(i32 %iptr_dst, i32 %len) {
@@ -141,6 +142,45 @@
 ; CHECK:   }
 ; CHECK:   Section {
 ; CHECK:     Index: {{[1-9][0-9]*}}
+; CHECK:     Name: .rodata.cst4
+; CHECK:     Type: SHT_PROGBITS
+; CHECK:     Flags [ (0x12)
+; CHECK:       SHF_ALLOC
+; CHECK:       SHF_MERGE
+; CHECK:     ]
+; CHECK:     Address: 0x0
+; CHECK:     Offset: 0x{{[1-9A-F][0-9A-F]*}}
+; CHECK:     Size: 8
+; CHECK:     Link: 0
+; CHECK:     Info: 0
+; CHECK:     AddressAlignment: 4
+; CHECK:     EntrySize: 4
+; CHECK:     SectionData (
+; CHECK:       0000: A0709D3F 00000080
+; CHECK:     )
+; CHECK:   }
+; CHECK:   Section {
+; CHECK:     Index: {{[1-9][0-9]*}}
+; CHECK:     Name: .rodata.cst8
+; CHECK:     Type: SHT_PROGBITS
+; CHECK:     Flags [ (0x12)
+; CHECK:       SHF_ALLOC
+; CHECK:       SHF_MERGE
+; CHECK:     ]
+; CHECK:     Address: 0x0
+; CHECK:     Offset: 0x{{[1-9A-F][0-9A-F]*}}
+; CHECK:     Size: 24
+; CHECK:     Link: 0
+; CHECK:     Info: 0
+; CHECK:     AddressAlignment: 8
+; CHECK:     EntrySize: 8
+; CHECK:     SectionData (
+; CHECK:       0000: 03000000 0000F8FF FFFFFFFF FFFFF7FF
+; CHECK:       0010: FFFFFFFF FFFFFFFF
+; CHECK:     )
+; CHECK:   }
+; CHECK:   Section {
+; CHECK:     Index: {{[1-9][0-9]*}}
 ; CHECK:     Name: .shstrtab
 ; CHECK:     Type: SHT_STRTAB
 ; CHECK:     Flags [ (0x0)
@@ -203,6 +243,42 @@
 ; CHECK-NEXT:   }
 ;  TODO: fill in the data symbols.
 ; CHECK:        Symbol {
+; CHECK:          Name: .L$double$0
+; CHECK-NEXT:     Value: 0x10
+; CHECK-NEXT:     Size: 0
+; CHECK-NEXT:     Binding: Local (0x0)
+; CHECK-NEXT:     Type: None (0x0)
+; CHECK-NEXT:     Other: 0
+; CHECK-NEXT:     Section: .rodata.cst8
+; CHECK-NEXT:   }
+; CHECK:        Symbol {
+; CHECK:          Name: .L$double$2
+; CHECK-NEXT:     Value: 0x0
+; CHECK-NEXT:     Size: 0
+; CHECK-NEXT:     Binding: Local (0x0)
+; CHECK-NEXT:     Type: None (0x0)
+; CHECK-NEXT:     Other: 0
+; CHECK-NEXT:     Section: .rodata.cst8
+; CHECK-NEXT:   }
+; CHECK:        Symbol {
+; CHECK:          Name: .L$float$0
+; CHECK-NEXT:     Value: 0x4
+; CHECK-NEXT:     Size: 0
+; CHECK-NEXT:     Binding: Local (0x0)
+; CHECK-NEXT:     Type: None (0x0)
+; CHECK-NEXT:     Other: 0
+; CHECK-NEXT:     Section: .rodata.cst4
+; CHECK-NEXT:   }
+; CHECK:        Symbol {
+; CHECK:          Name: .L$float$1
+; CHECK-NEXT:     Value: 0x0
+; CHECK-NEXT:     Size: 0
+; CHECK-NEXT:     Binding: Local (0x0)
+; CHECK-NEXT:     Type: None (0x0)
+; CHECK-NEXT:     Other: 0
+; CHECK-NEXT:     Section: .rodata.cst4
+; CHECK-NEXT:   }
+; CHECK:        Symbol {
 ; CHECK:          Name: returnDoubleConst
 ; CHECK-NEXT:     Value: 0x{{[1-9A-F][0-9A-F]*}}
 ; CHECK-NEXT:     Size: 0