Commit 72984d88 by Jan Voung

Write out global initializers and data rel directly to ELF file.

The local symbol relocations are a bit different from llvm-mc, which are section-relative. E.g., instead "bytes", it will be ".data + offsetof(bytes, .data)". So the contents of the text/data/rodata sections can also differ since the offsets written in place are different. Still need to fill the symbol table with undefined symbols (e.g., memset, and szrt lib functions) before trying to link. BUG=none R=kschimpf@google.com, stichnot@chromium.org Review URL: https://codereview.chromium.org/874353006
parent 867684e2
...@@ -643,9 +643,8 @@ public: ...@@ -643,9 +643,8 @@ public:
/// Converts global variables, and their initializers into ICE /// Converts global variables, and their initializers into ICE
/// global variable declarations, for module Mod. Puts corresponding /// global variable declarations, for module Mod. Puts corresponding
/// converted declarations into VariableDeclarations. /// converted declarations into VariableDeclarations.
void convertGlobalsToIce( void convertGlobalsToIce(Module *Mod,
Module *Mod, Ice::VariableDeclarationList &VariableDeclarations);
Ice::Translator::VariableDeclarationListType &VariableDeclarations);
private: private:
// Adds the Initializer to the list of initializers for the Global // Adds the Initializer to the list of initializers for the Global
...@@ -681,8 +680,7 @@ private: ...@@ -681,8 +680,7 @@ private:
}; };
void LLVM2ICEGlobalsConverter::convertGlobalsToIce( void LLVM2ICEGlobalsConverter::convertGlobalsToIce(
Module *Mod, Module *Mod, Ice::VariableDeclarationList &VariableDeclarations) {
Ice::Translator::VariableDeclarationListType &VariableDeclarations) {
for (Module::const_global_iterator I = Mod->global_begin(), for (Module::const_global_iterator I = Mod->global_begin(),
E = Mod->global_end(); E = Mod->global_end();
I != E; ++I) { I != E; ++I) {
...@@ -868,7 +866,7 @@ void Converter::installGlobalDeclarations(Module *Mod) { ...@@ -868,7 +866,7 @@ void Converter::installGlobalDeclarations(Module *Mod) {
void Converter::convertGlobals(Module *Mod) { void Converter::convertGlobals(Module *Mod) {
LLVM2ICEGlobalsConverter GlobalsConverter(*this); LLVM2ICEGlobalsConverter GlobalsConverter(*this);
Translator::VariableDeclarationListType VariableDeclarations; VariableDeclarationList VariableDeclarations;
GlobalsConverter.convertGlobalsToIce(Mod, VariableDeclarations); GlobalsConverter.convertGlobalsToIce(Mod, VariableDeclarations);
lowerGlobals(VariableDeclarations); lowerGlobals(VariableDeclarations);
} }
......
...@@ -60,7 +60,7 @@ class InstTarget; ...@@ -60,7 +60,7 @@ class InstTarget;
class LiveRange; class LiveRange;
class Liveness; class Liveness;
class Operand; class Operand;
class TargetGlobalLowering; class TargetDataLowering;
class TargetLowering; class TargetLowering;
class Variable; class Variable;
class VariableDeclaration; class VariableDeclaration;
...@@ -103,6 +103,8 @@ typedef std::vector<Variable *, CfgLocalAllocator<Variable *>> VarList; ...@@ -103,6 +103,8 @@ typedef std::vector<Variable *, CfgLocalAllocator<Variable *>> VarList;
typedef std::vector<CfgNode *, CfgLocalAllocator<CfgNode *>> NodeList; typedef std::vector<CfgNode *, CfgLocalAllocator<CfgNode *>> NodeList;
typedef std::vector<Constant *> ConstantList; typedef std::vector<Constant *> ConstantList;
typedef std::vector<VariableDeclaration *> VariableDeclarationList;
// SizeT is for holding small-ish limits like number of source // SizeT is for holding small-ish limits like number of source
// operands in an instruction. It is used instead of size_t (which // operands in an instruction. It is used instead of size_t (which
// may be 64-bits wide) when we want to save space. // may be 64-bits wide) when we want to save space.
......
...@@ -29,10 +29,23 @@ namespace Ice { ...@@ -29,10 +29,23 @@ namespace Ice {
// After all definitions are written out, it will finalize the bookkeeping // After all definitions are written out, it will finalize the bookkeeping
// sections and write them out. Expected usage: // sections and write them out. Expected usage:
// //
// (1) writeInitialELFHeader // (1) writeInitialELFHeader (invoke once)
// (2) writeDataInitializer* // (2) writeDataSection (invoke once)
// (3) writeFunctionCode* // (3) writeFunctionCode (must invoke once per function)
// (4) writeNonUserSections // (4) writeConstantPool (must invoke once per pooled primitive type)
// (5) writeNonUserSections (invoke once)
//
// The requirement for writeDataSection to be invoked only once can
// be relaxed if using -fdata-sections. The requirement to invoke only once
// without -fdata-sections is so that variables that belong to each possible
// SectionType are contiguous in the file. With -fdata-sections, each global
// variable is in a separate section and therefore the sections will be
// trivially contiguous.
//
// The motivation for requiring that writeFunctionCode happen after
// writeDataSection: to keep the .text and .data sections contiguous in the
// file. Having both -fdata-sections and -ffunction-sections does allow
// relaxing this requirement.
class ELFObjectWriter { class ELFObjectWriter {
ELFObjectWriter(const ELFObjectWriter &) = delete; ELFObjectWriter(const ELFObjectWriter &) = delete;
ELFObjectWriter &operator=(const ELFObjectWriter &) = delete; ELFObjectWriter &operator=(const ELFObjectWriter &) = delete;
...@@ -45,26 +58,32 @@ public: ...@@ -45,26 +58,32 @@ public:
// and data directly to the file and get the right file offsets. // and data directly to the file and get the right file offsets.
void writeInitialELFHeader(); void writeInitialELFHeader();
// Copy initializer data for globals to file and note the offset and size
// of each global's definition in the symbol table.
// Use the given target's RelocationKind for any relocations.
void writeDataSection(const VariableDeclarationList &Vars,
FixupKind RelocationKind);
// Copy data of a function's text section to file and note the offset of the // Copy data of a function's text section to file and note the offset of the
// symbol's definition in the symbol table. // symbol's definition in the symbol table.
// Copy the text fixups for use after all functions are written. // Copy the text fixups for use after all functions are written.
// The text buffer and fixups are extracted from the Assembler object.
void writeFunctionCode(const IceString &FuncName, bool IsInternal, void writeFunctionCode(const IceString &FuncName, bool IsInternal,
const Assembler *Asm); const Assembler *Asm);
// Copy initializer data for a global to file and note the offset and // Queries the GlobalContext for constant pools of the given type
// size of the global's definition in the symbol table. // and writes out read-only data sections for those constants. This also
// TODO(jvoung): This needs to know which section. This also needs the // fills the symbol table with labels for each constant pool entry.
// relocations to hook them up to the symbol table references. Also
// TODO is handling BSS (which just needs to note the size).
void writeDataInitializer(const IceString &VarName,
const llvm::StringRef Data);
template <typename ConstType> void writeConstantPool(Type Ty); template <typename ConstType> void writeConstantPool(Type Ty);
// Do final layout and write out the rest of the object file, then // Do final layout and write out the rest of the object file.
// patch up the initial ELF header with the final info. // Finally, patch up the initial ELF header with the final info.
void writeNonUserSections(); void writeNonUserSections();
// Which type of ELF section a global variable initializer belongs to.
// This is used as an array index so should start at 0 and be contiguous.
enum SectionType { ROData = 0, Data, BSS, NumSectionTypes };
private: private:
GlobalContext &Ctx; GlobalContext &Ctx;
ELFStreamer &Str; ELFStreamer &Str;
...@@ -79,8 +98,9 @@ private: ...@@ -79,8 +98,9 @@ private:
RelSectionList RelTextSections; RelSectionList RelTextSections;
DataSectionList DataSections; DataSectionList DataSections;
RelSectionList RelDataSections; RelSectionList RelDataSections;
DataSectionList RoDataSections; DataSectionList RODataSections;
RelSectionList RelRoDataSections; RelSectionList RelRODataSections;
DataSectionList BSSSections;
// Handles to special sections that need incremental bookkeeping. // Handles to special sections that need incremental bookkeeping.
ELFSection *NullSection; ELFSection *NullSection;
...@@ -93,6 +113,11 @@ private: ...@@ -93,6 +113,11 @@ private:
Elf64_Xword ShFlags, Elf64_Xword ShAddralign, Elf64_Xword ShFlags, Elf64_Xword ShAddralign,
Elf64_Xword ShEntsize); Elf64_Xword ShEntsize);
// Create a relocation section, given the related section
// (e.g., .text, .data., .rodata).
ELFRelocationSection *
createRelocationSection(bool IsELF64, const ELFSection *RelatedSection);
// Align the file position before writing out a section's data, // Align the file position before writing out a section's data,
// and return the position of the file. // and return the position of the file.
Elf64_Off alignFileOffset(Elf64_Xword Align); Elf64_Off alignFileOffset(Elf64_Xword Align);
...@@ -116,6 +141,12 @@ private: ...@@ -116,6 +141,12 @@ private:
// Link the relocation sections to the symbol table. // Link the relocation sections to the symbol table.
void assignRelLinkNum(SizeT SymTabNumber, RelSectionList &RelSections); void assignRelLinkNum(SizeT SymTabNumber, RelSectionList &RelSections);
// Helper function for writeDataSection. Writes a data section of type
// SectionType, given the global variables Vars belonging to that SectionType.
void writeDataOfType(SectionType SectionType,
const VariableDeclarationList &Vars,
FixupKind RelocationKind, bool IsELF64);
// Write the final relocation sections given the final symbol table. // Write the final relocation sections given the final symbol table.
// May also be able to seek around the file and resolve function calls // May also be able to seek around the file and resolve function calls
// that are for functions within the same section. // that are for functions within the same section.
......
...@@ -11,6 +11,8 @@ ...@@ -11,6 +11,8 @@
// //
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#include "llvm/Support/MathExtras.h"
#include "IceDefs.h" #include "IceDefs.h"
#include "IceELFSection.h" #include "IceELFSection.h"
#include "IceELFStreamer.h" #include "IceELFStreamer.h"
...@@ -35,6 +37,32 @@ void ELFDataSection::appendData(ELFStreamer &Str, ...@@ -35,6 +37,32 @@ void ELFDataSection::appendData(ELFStreamer &Str,
Header.sh_size += MoreData.size(); Header.sh_size += MoreData.size();
} }
void ELFDataSection::appendZeros(ELFStreamer &Str, SizeT NumBytes) {
Str.writeZeroPadding(NumBytes);
Header.sh_size += NumBytes;
}
void ELFDataSection::appendRelocationOffset(ELFStreamer &Str, bool IsRela,
RelocOffsetT RelocOffset) {
if (IsRela) {
appendZeros(Str, RelocAddrSize);
return;
}
static_assert(RelocAddrSize == 4, " writeLE32 assumes RelocAddrSize is 4");
Str.writeLE32(RelocOffset);
Header.sh_size += RelocAddrSize;
}
void ELFDataSection::padToAlignment(ELFStreamer &Str, Elf64_Xword Align) {
assert(llvm::isPowerOf2_32(Align));
Elf64_Xword AlignDiff = Utils::OffsetToAlignment(Header.sh_size, Align);
if (AlignDiff == 0)
return;
if (Header.sh_type != llvm::ELF::SHT_NOBITS)
Str.writeZeroPadding(AlignDiff);
Header.sh_size += AlignDiff;
}
// Relocation sections. // Relocation sections.
void ELFRelocationSection::addRelocations(RelocOffsetT BaseOff, void ELFRelocationSection::addRelocations(RelocOffsetT BaseOff,
...@@ -73,7 +101,7 @@ void ELFSymbolTableSection::createDefinedSym(const IceString &Name, ...@@ -73,7 +101,7 @@ void ELFSymbolTableSection::createDefinedSym(const IceString &Name,
NewSymbol.Section = Section; NewSymbol.Section = Section;
NewSymbol.Number = ELFSym::UnknownNumber; NewSymbol.Number = ELFSym::UnknownNumber;
bool Unique; bool Unique;
if (Type == STB_LOCAL) if (Binding == STB_LOCAL)
Unique = LocalSymbols.insert(std::make_pair(Name, NewSymbol)).second; Unique = LocalSymbols.insert(std::make_pair(Name, NewSymbol)).second;
else else
Unique = GlobalSymbols.insert(std::make_pair(Name, NewSymbol)).second; Unique = GlobalSymbols.insert(std::make_pair(Name, NewSymbol)).second;
......
...@@ -117,6 +117,16 @@ public: ...@@ -117,6 +117,16 @@ public:
using ELFSection::ELFSection; using ELFSection::ELFSection;
void appendData(ELFStreamer &Str, const llvm::StringRef MoreData); void appendData(ELFStreamer &Str, const llvm::StringRef MoreData);
void appendZeros(ELFStreamer &Str, SizeT NumBytes);
void appendRelocationOffset(ELFStreamer &Str, bool IsRela,
RelocOffsetT RelocOffset);
// Pad the next section offset for writing data elements to the requested
// alignment. If the section is NOBITS then do not actually write out
// the padding and only update the section size.
void padToAlignment(ELFStreamer &Str, Elf64_Xword Align);
}; };
// Model of ELF symbol table entries. Besides keeping track of the fields // Model of ELF symbol table entries. Besides keeping track of the fields
...@@ -195,13 +205,18 @@ class ELFRelocationSection : public ELFSection { ...@@ -195,13 +205,18 @@ class ELFRelocationSection : public ELFSection {
public: public:
using ELFSection::ELFSection; using ELFSection::ELFSection;
ELFSection *getRelatedSection() const { return RelatedSection; } const ELFSection *getRelatedSection() const { return RelatedSection; }
void setRelatedSection(ELFSection *Section) { RelatedSection = Section; } void setRelatedSection(const ELFSection *Section) {
RelatedSection = Section;
}
// Track additional relocations which start out relative to offset 0, // Track additional relocations which start out relative to offset 0,
// but should be adjusted to be relative to BaseOff. // but should be adjusted to be relative to BaseOff.
void addRelocations(RelocOffsetT BaseOff, const FixupRefList &FixupRefs); void addRelocations(RelocOffsetT BaseOff, const FixupRefList &FixupRefs);
// Track a single additional relocation.
void addRelocation(const AssemblerFixup &Fixup) { Fixups.push_back(Fixup); }
size_t getSectionDataSize(const GlobalContext &Ctx, size_t getSectionDataSize(const GlobalContext &Ctx,
const ELFSymbolTableSection *SymTab) const; const ELFSymbolTableSection *SymTab) const;
...@@ -209,8 +224,10 @@ public: ...@@ -209,8 +224,10 @@ public:
void writeData(const GlobalContext &Ctx, ELFStreamer &Str, void writeData(const GlobalContext &Ctx, ELFStreamer &Str,
const ELFSymbolTableSection *SymTab); const ELFSymbolTableSection *SymTab);
bool isRela() const { return Header.sh_type == SHT_RELA; }
private: private:
ELFSection *RelatedSection; const ELFSection *RelatedSection;
FixupList Fixups; FixupList Fixups;
}; };
......
...@@ -157,7 +157,7 @@ public: ...@@ -157,7 +157,7 @@ public:
}; };
// Models the data in a data initializer. // Models the data in a data initializer.
typedef std::vector<uint8_t> DataVecType; typedef std::vector<char> DataVecType;
/// Defines a sequence of byte values as a data initializer. /// Defines a sequence of byte values as a data initializer.
class DataInitializer : public Initializer { class DataInitializer : public Initializer {
...@@ -170,14 +170,14 @@ public: ...@@ -170,14 +170,14 @@ public:
: Initializer(DataInitializerKind), Contents(Values.size()) { : Initializer(DataInitializerKind), Contents(Values.size()) {
size_t i = 0; size_t i = 0;
for (auto &V : Values) { for (auto &V : Values) {
Contents[i] = static_cast<uint8_t>(V); Contents[i] = static_cast<int8_t>(V);
++i; ++i;
} }
} }
DataInitializer(const char *Str, size_t StrLen) DataInitializer(const char *Str, size_t StrLen)
: Initializer(DataInitializerKind), Contents(StrLen) { : Initializer(DataInitializerKind), Contents(StrLen) {
for (size_t i = 0; i < StrLen; ++i) for (size_t i = 0; i < StrLen; ++i)
Contents[i] = static_cast<uint8_t>(Str[i]); Contents[i] = Str[i];
} }
~DataInitializer() override {} ~DataInitializer() override {}
const DataVecType &getContents() const { return Contents; } const DataVecType &getContents() const { return Contents; }
......
...@@ -252,24 +252,24 @@ void TargetLowering::regAlloc(RegAllocKind Kind) { ...@@ -252,24 +252,24 @@ void TargetLowering::regAlloc(RegAllocKind Kind) {
LinearScan.scan(RegMask, RandomizeRegisterAllocation); LinearScan.scan(RegMask, RandomizeRegisterAllocation);
} }
TargetGlobalLowering *TargetGlobalLowering::createLowering(GlobalContext *Ctx) { TargetDataLowering *TargetDataLowering::createLowering(GlobalContext *Ctx) {
// These statements can be #ifdef'd to specialize the code generator // These statements can be #ifdef'd to specialize the code generator
// to a subset of the available targets. TODO: use CRTP. // to a subset of the available targets. TODO: use CRTP.
TargetArch Target = Ctx->getTargetArch(); TargetArch Target = Ctx->getTargetArch();
if (Target == Target_X8632) if (Target == Target_X8632)
return TargetGlobalX8632::create(Ctx); return TargetDataX8632::create(Ctx);
#if 0 #if 0
if (Target == Target_X8664) if (Target == Target_X8664)
return TargetGlobalX8664::create(Ctx); return TargetDataX8664::create(Ctx);
if (Target == Target_ARM32) if (Target == Target_ARM32)
return TargetGlobalARM32::create(Ctx); return TargetDataARM32::create(Ctx);
if (Target == Target_ARM64) if (Target == Target_ARM64)
return TargetGlobalARM64::create(Ctx); return TargetDataARM64::create(Ctx);
#endif #endif
llvm_unreachable("Unsupported target"); llvm_unreachable("Unsupported target");
return nullptr; return nullptr;
} }
TargetGlobalLowering::~TargetGlobalLowering() {} TargetDataLowering::~TargetDataLowering() {}
} // end of namespace Ice } // end of namespace Ice
...@@ -238,23 +238,24 @@ protected: ...@@ -238,23 +238,24 @@ protected:
LoweringContext Context; LoweringContext Context;
}; };
// TargetGlobalLowering is used for "lowering" global initializers, // TargetDataLowering is used for "lowering" data including initializers
// including the internal constant pool. It is separated out from // for global variables, and the internal constant pools. It is separated
// TargetLowering because it does not require a Cfg. // out from TargetLowering because it does not require a Cfg.
class TargetGlobalLowering { class TargetDataLowering {
TargetGlobalLowering() = delete; TargetDataLowering() = delete;
TargetGlobalLowering(const TargetGlobalLowering &) = delete; TargetDataLowering(const TargetDataLowering &) = delete;
TargetGlobalLowering &operator=(const TargetGlobalLowering &) = delete; TargetDataLowering &operator=(const TargetDataLowering &) = delete;
public: public:
static TargetGlobalLowering *createLowering(GlobalContext *Ctx); static TargetDataLowering *createLowering(GlobalContext *Ctx);
virtual ~TargetGlobalLowering(); virtual ~TargetDataLowering();
virtual void lowerInit(const VariableDeclaration &Var) const = 0; virtual void lowerGlobal(const VariableDeclaration &Var) const = 0;
virtual void lowerGlobalsELF(const VariableDeclarationList &Vars) const = 0;
virtual void lowerConstants(GlobalContext *Ctx) const = 0; virtual void lowerConstants(GlobalContext *Ctx) const = 0;
protected: protected:
TargetGlobalLowering(GlobalContext *Ctx) : Ctx(Ctx) {} TargetDataLowering(GlobalContext *Ctx) : Ctx(Ctx) {}
GlobalContext *Ctx; GlobalContext *Ctx;
}; };
......
...@@ -4560,25 +4560,19 @@ void ConstantUndef::emit(GlobalContext *) const { ...@@ -4560,25 +4560,19 @@ void ConstantUndef::emit(GlobalContext *) const {
llvm_unreachable("undef value encountered by emitter."); llvm_unreachable("undef value encountered by emitter.");
} }
TargetGlobalX8632::TargetGlobalX8632(GlobalContext *Ctx) TargetDataX8632::TargetDataX8632(GlobalContext *Ctx)
: TargetGlobalLowering(Ctx) {} : TargetDataLowering(Ctx) {}
void TargetGlobalX8632::lowerInit(const VariableDeclaration &Var) const {
// TODO(jvoung): handle this without text.
if (Ctx->getFlags().UseELFWriter)
return;
Ostream &Str = Ctx->getStrEmit();
const VariableDeclaration::InitializerListType &Initializers =
Var.getInitializers();
void TargetDataX8632::lowerGlobal(const VariableDeclaration &Var) const {
// If external and not initialized, this must be a cross test. // If external and not initialized, this must be a cross test.
// Don't generate a declaration for such cases. // Don't generate a declaration for such cases.
bool IsExternal = Var.isExternal() || Ctx->getFlags().DisableInternal; bool IsExternal = Var.isExternal() || Ctx->getFlags().DisableInternal;
if (IsExternal && !Var.hasInitializer()) if (IsExternal && !Var.hasInitializer())
return; return;
Ostream &Str = Ctx->getStrEmit();
const VariableDeclaration::InitializerListType &Initializers =
Var.getInitializers();
bool HasNonzeroInitializer = Var.hasNonzeroInitializer(); bool HasNonzeroInitializer = Var.hasNonzeroInitializer();
bool IsConstant = Var.getIsConstant(); bool IsConstant = Var.getIsConstant();
uint32_t Align = Var.getAlignment(); uint32_t Align = Var.getAlignment();
...@@ -4645,6 +4639,12 @@ void TargetGlobalX8632::lowerInit(const VariableDeclaration &Var) const { ...@@ -4645,6 +4639,12 @@ void TargetGlobalX8632::lowerInit(const VariableDeclaration &Var) const {
Str << "\t.size\t" << MangledName << ", " << Size << "\n"; Str << "\t.size\t" << MangledName << ", " << Size << "\n";
} }
void
TargetDataX8632::lowerGlobalsELF(const VariableDeclarationList &Vars) const {
ELFObjectWriter *Writer = Ctx->getObjectWriter();
Writer->writeDataSection(Vars, llvm::ELF::R_386_32);
}
template <typename T> struct PoolTypeConverter {}; template <typename T> struct PoolTypeConverter {};
template <> struct PoolTypeConverter<float> { template <> struct PoolTypeConverter<float> {
...@@ -4672,7 +4672,7 @@ const char *PoolTypeConverter<double>::AsmTag = ".quad"; ...@@ -4672,7 +4672,7 @@ const char *PoolTypeConverter<double>::AsmTag = ".quad";
const char *PoolTypeConverter<double>::PrintfString = "0x%llx"; const char *PoolTypeConverter<double>::PrintfString = "0x%llx";
template <typename T> template <typename T>
void TargetGlobalX8632::emitConstantPool(GlobalContext *Ctx) { void TargetDataX8632::emitConstantPool(GlobalContext *Ctx) {
// Note: Still used by emit IAS. // Note: Still used by emit IAS.
Ostream &Str = Ctx->getStrEmit(); Ostream &Str = Ctx->getStrEmit();
Type Ty = T::Ty; Type Ty = T::Ty;
...@@ -4701,7 +4701,7 @@ void TargetGlobalX8632::emitConstantPool(GlobalContext *Ctx) { ...@@ -4701,7 +4701,7 @@ void TargetGlobalX8632::emitConstantPool(GlobalContext *Ctx) {
} }
} }
void TargetGlobalX8632::lowerConstants(GlobalContext *Ctx) const { void TargetDataX8632::lowerConstants(GlobalContext *Ctx) const {
if (Ctx->getFlags().DisableTranslation) if (Ctx->getFlags().DisableTranslation)
return; return;
// No need to emit constants from the int pool since (for x86) they // No need to emit constants from the int pool since (for x86) they
......
...@@ -488,24 +488,25 @@ private: ...@@ -488,24 +488,25 @@ private:
~TargetX8632() override {} ~TargetX8632() override {}
}; };
class TargetGlobalX8632 : public TargetGlobalLowering { class TargetDataX8632 : public TargetDataLowering {
TargetGlobalX8632() = delete; TargetDataX8632() = delete;
TargetGlobalX8632(const TargetGlobalX8632 &) = delete; TargetDataX8632(const TargetDataX8632 &) = delete;
TargetGlobalX8632 &operator=(const TargetGlobalX8632 &) = delete; TargetDataX8632 &operator=(const TargetDataX8632 &) = delete;
public: public:
static TargetGlobalLowering *create(GlobalContext *Ctx) { static TargetDataLowering *create(GlobalContext *Ctx) {
return new TargetGlobalX8632(Ctx); return new TargetDataX8632(Ctx);
} }
virtual void lowerInit(const VariableDeclaration &Var) const final; void lowerGlobal(const VariableDeclaration &Var) const final;
virtual void lowerConstants(GlobalContext *Ctx) const final; void lowerGlobalsELF(const VariableDeclarationList &Vars) const final;
void lowerConstants(GlobalContext *Ctx) const final;
protected: protected:
TargetGlobalX8632(GlobalContext *Ctx); TargetDataX8632(GlobalContext *Ctx);
private: private:
~TargetGlobalX8632() override {} ~TargetDataX8632() override {}
template <typename T> static void emitConstantPool(GlobalContext *Ctx); template <typename T> static void emitConstantPool(GlobalContext *Ctx);
}; };
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
X(doBranchOpt) \ X(doBranchOpt) \
X(doNopInsertion) \ X(doNopInsertion) \
X(emit) \ X(emit) \
X(emitGlobalInitializers) \
X(genCode) \ X(genCode) \
X(genFrame) \ X(genFrame) \
X(initUnhandled) \ X(initUnhandled) \
......
...@@ -23,8 +23,7 @@ using namespace Ice; ...@@ -23,8 +23,7 @@ using namespace Ice;
Translator::Translator(GlobalContext *Ctx, const ClFlags &Flags) Translator::Translator(GlobalContext *Ctx, const ClFlags &Flags)
: Ctx(Ctx), Flags(Flags), : Ctx(Ctx), Flags(Flags),
GlobalLowering(TargetGlobalLowering::createLowering(Ctx)), ErrorStatus() { DataLowering(TargetDataLowering::createLowering(Ctx)), ErrorStatus() {}
}
Translator::~Translator() {} Translator::~Translator() {}
...@@ -63,7 +62,7 @@ void Translator::translateFcn(Cfg *Func) { ...@@ -63,7 +62,7 @@ void Translator::translateFcn(Cfg *Func) {
void Translator::emitConstants() { void Translator::emitConstants() {
if (!getErrorStatus()) if (!getErrorStatus())
GlobalLowering->lowerConstants(Ctx); DataLowering->lowerConstants(Ctx);
} }
void Translator::transferErrorCode() const { void Translator::transferErrorCode() const {
...@@ -71,19 +70,33 @@ void Translator::transferErrorCode() const { ...@@ -71,19 +70,33 @@ void Translator::transferErrorCode() const {
Ctx->getErrorStatus()->assign(getErrorStatus().value()); Ctx->getErrorStatus()->assign(getErrorStatus().value());
} }
void Translator::lowerGlobals( void
const VariableDeclarationListType &VariableDeclarations) { Translator::lowerGlobals(const VariableDeclarationList &VariableDeclarations) {
TimerMarker T(TimerStack::TT_emitGlobalInitializers, Ctx);
bool DisableTranslation = Ctx->getFlags().DisableTranslation; bool DisableTranslation = Ctx->getFlags().DisableTranslation;
const bool DumpGlobalVariables = const bool DumpGlobalVariables =
ALLOW_DUMP && Ctx->getVerbose() && Ctx->getFlags().VerboseFocusOn.empty(); ALLOW_DUMP && Ctx->getVerbose() && Ctx->getFlags().VerboseFocusOn.empty();
if (Ctx->getFlags().UseELFWriter) {
// Dump all globals if requested, but don't interleave w/ emission.
if (DumpGlobalVariables) {
OstreamLocker L(Ctx); OstreamLocker L(Ctx);
Ostream &Stream = Ctx->getStrDump(); Ostream &Stream = Ctx->getStrDump();
for (const Ice::VariableDeclaration *Global : VariableDeclarations) {
Global->dump(getContext(), Stream);
}
}
DataLowering->lowerGlobalsELF(VariableDeclarations);
} else {
const IceString &TranslateOnly = Ctx->getFlags().TranslateOnly; const IceString &TranslateOnly = Ctx->getFlags().TranslateOnly;
OstreamLocker L(Ctx);
Ostream &Stream = Ctx->getStrDump();
for (const Ice::VariableDeclaration *Global : VariableDeclarations) { for (const Ice::VariableDeclaration *Global : VariableDeclarations) {
// Interleave dump output w/ emit output.
if (DumpGlobalVariables) if (DumpGlobalVariables)
Global->dump(getContext(), Stream); Global->dump(getContext(), Stream);
if (!DisableTranslation && if (!DisableTranslation &&
GlobalContext::matchSymbolName(Global->getName(), TranslateOnly)) GlobalContext::matchSymbolName(Global->getName(), TranslateOnly))
GlobalLowering->lowerInit(*Global); DataLowering->lowerGlobal(*Global);
}
} }
} }
...@@ -34,9 +34,8 @@ class Translator { ...@@ -34,9 +34,8 @@ class Translator {
Translator &operator=(const Translator &) = delete; Translator &operator=(const Translator &) = delete;
public: public:
typedef std::vector<VariableDeclaration *> VariableDeclarationListType;
Translator(GlobalContext *Ctx, const ClFlags &Flags); Translator(GlobalContext *Ctx, const ClFlags &Flags);
~Translator(); ~Translator();
const ErrorCode &getErrorStatus() const { return ErrorStatus; } const ErrorCode &getErrorStatus() const { return ErrorStatus; }
...@@ -57,7 +56,7 @@ public: ...@@ -57,7 +56,7 @@ public:
/// Lowers the given list of global addresses to target. Generates /// Lowers the given list of global addresses to target. Generates
/// list of corresponding variable declarations. /// list of corresponding variable declarations.
void lowerGlobals(const VariableDeclarationListType &VariableDeclarations); void lowerGlobals(const VariableDeclarationList &VariableDeclarations);
/// Creates a name using the given prefix and corresponding index. /// Creates a name using the given prefix and corresponding index.
std::string createUnnamedName(const IceString &Prefix, SizeT Index); std::string createUnnamedName(const IceString &Prefix, SizeT Index);
...@@ -71,7 +70,7 @@ public: ...@@ -71,7 +70,7 @@ public:
protected: protected:
GlobalContext *Ctx; GlobalContext *Ctx;
const ClFlags &Flags; const ClFlags &Flags;
std::unique_ptr<TargetGlobalLowering> GlobalLowering; std::unique_ptr<TargetDataLowering> DataLowering;
// Exit status of the translation. False is successful. True otherwise. // Exit status of the translation. False is successful. True otherwise.
ErrorCode ErrorStatus; ErrorCode ErrorStatus;
}; };
......
...@@ -53,6 +53,14 @@ public: ...@@ -53,6 +53,14 @@ public:
return ((X > 0 && Y > 0 && (X > std::numeric_limits<T>::max() - Y)) || return ((X > 0 && Y > 0 && (X > std::numeric_limits<T>::max() - Y)) ||
(X < 0 && Y < 0 && (X < std::numeric_limits<T>::min() - Y))); (X < 0 && Y < 0 && (X < std::numeric_limits<T>::min() - Y)));
} }
static inline uint64_t OffsetToAlignment(uint64_t Pos, uint64_t Align) {
assert(llvm::isPowerOf2_64(Align));
uint64_t Mod = Pos & (Align - 1);
if (Mod == 0)
return 0;
return Align - Mod;
}
}; };
// BoundedProducerConsumerQueue is a work queue that allows multiple // BoundedProducerConsumerQueue is a work queue that allows multiple
......
...@@ -351,7 +351,7 @@ public: ...@@ -351,7 +351,7 @@ public:
} }
/// Returns the list of parsed global variable declarations. /// Returns the list of parsed global variable declarations.
const Ice::Translator::VariableDeclarationListType &getGlobalVariables() { const Ice::VariableDeclarationList &getGlobalVariables() {
return VariableDeclarations; return VariableDeclarations;
} }
...@@ -376,7 +376,7 @@ private: ...@@ -376,7 +376,7 @@ private:
// actually-defined function. // actually-defined function.
size_t NextDefiningFunctionID; size_t NextDefiningFunctionID;
// The set of global variables. // The set of global variables.
Ice::Translator::VariableDeclarationListType VariableDeclarations; Ice::VariableDeclarationList VariableDeclarations;
// Relocatable constants associated with global declarations. // Relocatable constants associated with global declarations.
std::vector<Ice::Constant *> ValueIDConstants; std::vector<Ice::Constant *> ValueIDConstants;
// Error recovery value to use when getFuncSigTypeByID fails. // Error recovery value to use when getFuncSigTypeByID fails.
......
...@@ -43,19 +43,13 @@ AssemblerX86::~AssemblerX86() { ...@@ -43,19 +43,13 @@ AssemblerX86::~AssemblerX86() {
} }
void AssemblerX86::alignFunction() { void AssemblerX86::alignFunction() {
intptr_t Pos = buffer_.GetPosition();
SizeT Align = 1 << getBundleAlignLog2Bytes(); SizeT Align = 1 << getBundleAlignLog2Bytes();
intptr_t Mod = Pos & (Align - 1); SizeT BytesNeeded = Utils::OffsetToAlignment(buffer_.GetPosition(), Align);
if (Mod == 0) {
return;
}
SizeT BytesNeeded = Align - Mod;
const SizeT HltSize = 1; const SizeT HltSize = 1;
while (BytesNeeded > 0) { while (BytesNeeded > 0) {
hlt(); hlt();
BytesNeeded -= HltSize; BytesNeeded -= HltSize;
} }
assert((buffer_.GetPosition() & (Align - 1)) == 0);
} }
Label *AssemblerX86::GetOrCreateLabel(SizeT Number, LabelVector &Labels) { Label *AssemblerX86::GetOrCreateLabel(SizeT Number, LabelVector &Labels) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment