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