Commit a78e4baa by John Porto

Subzero. Allocate global initializers from a dedicated arena.

This allows Subzero to release the global initializers once they've been lowered. This CL also modifies the global initializer types to ensure they are trivially destructible -- therefore not requiring destructors to run. BUG= https://bugs.chromium.org/p/nativeclient/issues/detail?id=4360 R=stichnot@chromium.org Review URL: https://codereview.chromium.org/1776473007 .
parent 76719b4a
......@@ -122,46 +122,43 @@ bool Cfg::hasComputedFrame() const { return getTarget()->hasComputedFrame(); }
namespace {
constexpr char BlockNameGlobalPrefix[] = ".L$profiler$block_name$";
constexpr char BlockStatsGlobalPrefix[] = ".L$profiler$block_info$";
} // end of anonymous namespace
VariableDeclaration *nodeNameDeclaration(GlobalContext *Ctx,
const IceString &NodeAsmName) {
auto *Var = VariableDeclaration::create(Ctx);
void Cfg::createNodeNameDeclaration(const IceString &NodeAsmName) {
auto *Var = VariableDeclaration::create(GlobalInits.get());
Var->setName(BlockNameGlobalPrefix + NodeAsmName);
Var->setIsConstant(true);
Var->addInitializer(VariableDeclaration::DataInitializer::create(
NodeAsmName.data(), NodeAsmName.size() + 1));
GlobalInits.get(), NodeAsmName.data(), NodeAsmName.size() + 1));
const SizeT Int64ByteSize = typeWidthInBytes(IceType_i64);
Var->setAlignment(Int64ByteSize); // Wasteful, 32-bit could use 4 bytes.
return Var;
GlobalInits->push_back(Var);
}
VariableDeclaration *
blockProfilingInfoDeclaration(GlobalContext *Ctx, const IceString &NodeAsmName,
VariableDeclaration *NodeNameDeclaration) {
auto *Var = VariableDeclaration::create(Ctx);
void Cfg::createBlockProfilingInfoDeclaration(
const IceString &NodeAsmName, VariableDeclaration *NodeNameDeclaration) {
auto *Var = VariableDeclaration::create(GlobalInits.get());
Var->setName(BlockStatsGlobalPrefix + NodeAsmName);
const SizeT Int64ByteSize = typeWidthInBytes(IceType_i64);
Var->addInitializer(
VariableDeclaration::ZeroInitializer::create(Int64ByteSize));
Var->addInitializer(VariableDeclaration::ZeroInitializer::create(
GlobalInits.get(), Int64ByteSize));
const RelocOffsetT NodeNameDeclarationOffset = 0;
Var->addInitializer(VariableDeclaration::RelocInitializer::create(
NodeNameDeclaration,
GlobalInits.get(), NodeNameDeclaration,
{RelocOffset::create(Ctx, NodeNameDeclarationOffset)}));
Var->setAlignment(Int64ByteSize);
return Var;
GlobalInits->push_back(Var);
}
} // end of anonymous namespace
void Cfg::profileBlocks() {
if (GlobalInits == nullptr)
GlobalInits.reset(new VariableDeclarationList());
for (CfgNode *Node : Nodes) {
IceString NodeAsmName = Node->getAsmName();
GlobalInits->push_back(nodeNameDeclaration(Ctx, NodeAsmName));
GlobalInits->push_back(
blockProfilingInfoDeclaration(Ctx, NodeAsmName, GlobalInits->back()));
const IceString NodeAsmName = Node->getAsmName();
createNodeNameDeclaration(NodeAsmName);
createBlockProfilingInfoDeclaration(NodeAsmName, GlobalInits->back());
Node->profileExecutionCount(GlobalInits->back());
}
}
......
......@@ -158,6 +158,12 @@ public:
}
GlobalInits->push_back(Global);
}
VariableDeclarationList *getGlobalPool() {
if (GlobalInits == nullptr) {
GlobalInits.reset(new VariableDeclarationList);
}
return GlobalInits.get();
}
/// @}
/// \name Miscellaneous accessors.
......@@ -269,6 +275,11 @@ private:
/// code needs to be defined.
void profileBlocks();
void createNodeNameDeclaration(const IceString &NodeAsmName);
void
createBlockProfilingInfoDeclaration(const IceString &NodeAsmName,
VariableDeclaration *NodeNameDeclaration);
/// Delete registered jump table placeholder instructions. This should only be
/// called once all repointing has taken place.
void deleteJumpTableInsts();
......
......@@ -93,6 +93,9 @@ void Compiler::run(const Ice::ClFlagsExtra &ExtraFlags, GlobalContext &Ctx,
Ctx.getErrorStatus()->assign(EC_Args);
return;
}
// Globals must be kept alive after lowering when converting from LLVM to
// Ice.
Ctx.setDisposeGlobalVariablesAfterLowering(false);
// Parse the input LLVM IR file into a module.
llvm::SMDiagnostic Err;
TimerMarker T1(Ice::TimerStack::TT_parse, &Ctx);
......
......@@ -659,13 +659,13 @@ class LLVM2ICEGlobalsConverter : public LLVM2ICEConverter {
operator=(const LLVM2ICEGlobalsConverter &) = delete;
public:
explicit LLVM2ICEGlobalsConverter(Ice::Converter &Converter)
: LLVM2ICEConverter(Converter) {}
explicit LLVM2ICEGlobalsConverter(Ice::Converter &Converter,
Ice::VariableDeclarationList *G)
: LLVM2ICEConverter(Converter), GlobalPool(G) {}
/// Converts global variables, and their initializers into ICE global variable
/// declarations, for module Mod. Returns the set of converted declarations.
std::unique_ptr<Ice::VariableDeclarationList>
convertGlobalsToIce(Module *Mod);
void convertGlobalsToIce(Module *Mod);
private:
// Adds the Initializer to the list of initializers for the Global variable
......@@ -697,12 +697,11 @@ private:
report_fatal_error(StrBuf.str());
return 0;
}
Ice::VariableDeclarationList *GlobalPool;
};
std::unique_ptr<Ice::VariableDeclarationList>
LLVM2ICEGlobalsConverter::convertGlobalsToIce(Module *Mod) {
std::unique_ptr<Ice::VariableDeclarationList> VariableDeclarations(
new Ice::VariableDeclarationList);
void LLVM2ICEGlobalsConverter::convertGlobalsToIce(Module *Mod) {
for (Module::const_global_iterator I = Mod->global_begin(),
E = Mod->global_end();
I != E; ++I) {
......@@ -711,7 +710,7 @@ LLVM2ICEGlobalsConverter::convertGlobalsToIce(Module *Mod) {
Ice::GlobalDeclaration *Var = getConverter().getGlobalDeclaration(GV);
auto *VarDecl = cast<Ice::VariableDeclaration>(Var);
VariableDeclarations->push_back(VarDecl);
GlobalPool->push_back(VarDecl);
if (!GV->hasInternalLinkage() && GV->hasInitializer()) {
std::string Buffer;
......@@ -744,7 +743,6 @@ LLVM2ICEGlobalsConverter::convertGlobalsToIce(Module *Mod) {
addGlobalInitializer(*VarDecl, Initializer);
}
}
return VariableDeclarations;
}
void LLVM2ICEGlobalsConverter::addGlobalInitializer(
......@@ -757,7 +755,7 @@ void LLVM2ICEGlobalsConverter::addGlobalInitializer(
assert(!HasOffset && isa<IntegerType>(CDA->getElementType()) &&
(cast<IntegerType>(CDA->getElementType())->getBitWidth() == 8));
Global.addInitializer(Ice::VariableDeclaration::DataInitializer::create(
CDA->getRawDataValues().data(), CDA->getNumElements()));
GlobalPool, CDA->getRawDataValues().data(), CDA->getNumElements()));
return;
}
......@@ -766,7 +764,7 @@ void LLVM2ICEGlobalsConverter::addGlobalInitializer(
assert(!HasOffset && isa<IntegerType>(AT->getElementType()) &&
(cast<IntegerType>(AT->getElementType())->getBitWidth() == 8));
Global.addInitializer(Ice::VariableDeclaration::ZeroInitializer::create(
AT->getNumElements()));
GlobalPool, AT->getNumElements()));
} else {
llvm_unreachable("Unhandled constant aggregate zero type");
}
......@@ -788,7 +786,7 @@ void LLVM2ICEGlobalsConverter::addGlobalInitializer(
const Ice::GlobalDeclaration *Addr =
getConverter().getGlobalDeclaration(GV);
Global.addInitializer(Ice::VariableDeclaration::RelocInitializer::create(
Addr, {Ice::RelocOffset::create(Ctx, Offset)}));
GlobalPool, Addr, {Ice::RelocOffset::create(Ctx, Offset)}));
return;
}
default:
......@@ -890,8 +888,8 @@ void Converter::installGlobalDeclarations(Module *Mod) {
I != E; ++I) {
const GlobalVariable *GV = I;
constexpr bool NoSuppressMangling = false;
auto *Var =
VariableDeclaration::create(Ctx, NoSuppressMangling, GV->getLinkage());
auto *Var = VariableDeclaration::create(
GlobalDeclarationsPool.get(), NoSuppressMangling, GV->getLinkage());
Var->setAlignment(GV->getAlignment());
Var->setIsConstant(GV->isConstant());
Var->setName(GV->getName());
......@@ -909,7 +907,9 @@ void Converter::installGlobalDeclarations(Module *Mod) {
}
void Converter::convertGlobals(Module *Mod) {
lowerGlobals(LLVM2ICEGlobalsConverter(*this).convertGlobalsToIce(Mod));
LLVM2ICEGlobalsConverter(*this, GlobalDeclarationsPool.get())
.convertGlobalsToIce(Mod);
lowerGlobals(std::move(GlobalDeclarationsPool));
}
void Converter::convertFunctions() {
......
......@@ -32,7 +32,8 @@ class Converter : public Translator {
public:
Converter(llvm::Module *Mod, GlobalContext *Ctx)
: Translator(Ctx), Mod(Mod) {}
: Translator(Ctx), Mod(Mod),
GlobalDeclarationsPool(new VariableDeclarationList()) {}
~Converter() override = default;
......@@ -52,6 +53,8 @@ private:
std::map<const llvm::GlobalValue *, GlobalDeclaration *>;
GlobalDeclarationMapType GlobalDeclarationMap;
std::unique_ptr<VariableDeclarationList> GlobalDeclarationsPool;
/// Walks module and generates names for unnamed globals using prefix
/// getFlags().DefaultGlobalPrefix, if the prefix is non-empty.
void nameUnnamedGlobalVariables(llvm::Module *Mod);
......
......@@ -73,6 +73,11 @@ class Variable;
class VariableDeclaration;
class VariablesMetadata;
/// SizeT is for holding small-ish limits like number of source operands in an
/// instruction. It is used instead of size_t (which may be 64-bits wide) when
/// we want to save space.
using SizeT = uint32_t;
constexpr char GlobalOffsetTable[] = "_GLOBAL_OFFSET_TABLE_";
// makeUnique should be used when memory is expected to be allocated from the
// heap (as opposed to allocated from some Allocator.) It is intended to be
......@@ -139,12 +144,127 @@ using NodeList = CfgVector<CfgNode *>;
// Containers that use the default (global) allocator.
using ConstantList = std::vector<Constant *>;
using FunctionDeclarationList = std::vector<FunctionDeclaration *>;
using VariableDeclarationList = std::vector<VariableDeclaration *>;
/// SizeT is for holding small-ish limits like number of source operands in an
/// instruction. It is used instead of size_t (which may be 64-bits wide) when
/// we want to save space.
using SizeT = uint32_t;
/// VariableDeclarationList is a container for holding VariableDeclarations --
/// i.e., Global Variables. It is also used to create said variables, and their
/// initializers in an arena.
class VariableDeclarationList {
VariableDeclarationList(const VariableDeclarationList &) = delete;
VariableDeclarationList &operator=(const VariableDeclarationList &) = delete;
VariableDeclarationList(VariableDeclarationList &&) = delete;
VariableDeclarationList &operator=(VariableDeclarationList &&) = delete;
public:
using VariableDeclarationArray = std::vector<VariableDeclaration *>;
VariableDeclarationList() : Arena(new ArenaAllocator()) {}
~VariableDeclarationList() { clearAndPurge(); }
template <typename T> T *allocate_initializer(SizeT Count = 1) {
static_assert(
std::is_trivially_destructible<T>::value,
"allocate_initializer can only allocate trivially destructible types.");
return Arena->Allocate<T>(Count);
}
template <typename T> T *allocate_variable_declaration() {
static_assert(!std::is_trivially_destructible<T>::value,
"allocate_variable_declaration expects non-trivially "
"destructible types.");
T *Ret = Arena->Allocate<T>();
Dtors.emplace_back([Ret]() { Ret->~T(); });
return Ret;
}
// This do nothing method is invoked when a global variable is created, but it
// will not be emitted. If we ever need to track the created variabled, having
// this hook is handy.
void willNotBeEmitted(VariableDeclaration *) {}
/// Merges Other with this, effectively resetting Other to an empty state.
void merge(VariableDeclarationList *Other) {
assert(Other != nullptr);
addArena(std::move(Other->Arena));
for (std::size_t i = 0; i < Other->MergedArenas.size(); ++i) {
addArena(std::move(Other->MergedArenas[i]));
}
Other->MergedArenas.clear();
Dtors.insert(Dtors.end(), Other->Dtors.begin(), Other->Dtors.end());
Other->Dtors.clear();
Globals.insert(Globals.end(), Other->Globals.begin(), Other->Globals.end());
Other->Globals.clear();
}
/// Destroys all GlobalVariables and initializers that this knows about
/// (including those merged with it), and releases memory.
void clearAndPurge() {
if (Arena == nullptr) {
// Arena is only null if this was merged, so we ensure there's no state
// being held by this.
assert(Dtors.empty());
assert(Globals.empty());
assert(MergedArenas.empty());
return;
}
// Invokes destructors in reverse creation order.
for (auto Dtor = Dtors.rbegin(); Dtor != Dtors.rend(); ++Dtor) {
(*Dtor)();
}
Dtors.clear();
Globals.clear();
MergedArenas.clear();
Arena->Reset();
}
/// Adapt the relevant parts of the std::vector<VariableDeclaration *>
/// interface.
/// @{
VariableDeclarationArray::iterator begin() { return Globals.begin(); }
VariableDeclarationArray::iterator end() { return Globals.end(); }
VariableDeclarationArray::const_iterator begin() const {
return Globals.begin();
}
VariableDeclarationArray::const_iterator end() const { return Globals.end(); }
bool empty() const { return Globals.empty(); }
VariableDeclarationArray::size_type size() const { return Globals.size(); }
VariableDeclarationArray::reference
at(VariableDeclarationArray::size_type Pos) {
return Globals.at(Pos);
}
void push_back(VariableDeclaration *Global) { Globals.push_back(Global); }
void reserve(VariableDeclarationArray::size_type Capacity) {
Globals.reserve(Capacity);
}
void clear() { Globals.clear(); }
VariableDeclarationArray::reference back() { return Globals.back(); }
/// @}
private:
using ArenaPtr = std::unique_ptr<ArenaAllocator>;
using DestructorsArray = std::vector<std::function<void()>>;
void addArena(ArenaPtr NewArena) {
MergedArenas.emplace_back(std::move(NewArena));
}
ArenaPtr Arena;
VariableDeclarationArray Globals;
DestructorsArray Dtors;
std::vector<ArenaPtr> MergedArenas;
};
/// InstNumberT is for holding an instruction number. Instruction numbers are
/// used for representing Variable live ranges.
......
......@@ -288,7 +288,7 @@ classifyGlobalSection(const VariableDeclaration *Var) {
// Partition the Vars list by SectionType into VarsBySection. If TranslateOnly
// is non-empty, then only the TranslateOnly variable is kept for emission.
void partitionGlobalsBySection(const VariableDeclarationList &Vars,
VariableDeclarationList VarsBySection[],
VariableDeclarationPartition VarsBySection[],
const IceString &TranslateOnly) {
for (VariableDeclaration *Var : Vars) {
if (GlobalContext::matchSymbolName(Var->getName(), TranslateOnly)) {
......@@ -307,7 +307,7 @@ void ELFObjectWriter::writeDataSection(const VariableDeclarationList &Vars,
bool IsPIC) {
TimerMarker Timer(TimerStack::TT_writeELF, &Ctx);
assert(!SectionNumbersAssigned);
VariableDeclarationList VarsBySection[ELFObjectWriter::NumSectionTypes];
VariableDeclarationPartition VarsBySection[ELFObjectWriter::NumSectionTypes];
for (auto &SectionList : VarsBySection)
SectionList.reserve(Vars.size());
partitionGlobalsBySection(Vars, VarsBySection,
......@@ -329,7 +329,7 @@ IceString MangleSectionName(const char Base[], const IceString &Suffix) {
// TODO(jvoung): Handle fdata-sections.
void ELFObjectWriter::writeDataOfType(SectionType ST,
const VariableDeclarationList &Vars,
const VariableDeclarationPartition &Vars,
FixupKind RelocationKind,
const IceString &SectionSuffix,
bool IsPIC) {
......@@ -407,12 +407,11 @@ void ELFObjectWriter::writeDataOfType(SectionType ST,
Section->setSize(Section->getCurrentSize() + SymbolSize);
} else {
assert(ST != BSS);
for (const std::unique_ptr<VariableDeclaration::Initializer> &Init :
Var->getInitializers()) {
for (const auto *Init : Var->getInitializers()) {
switch (Init->getKind()) {
case VariableDeclaration::Initializer::DataInitializerKind: {
const auto &Data =
llvm::cast<VariableDeclaration::DataInitializer>(Init.get())
llvm::cast<VariableDeclaration::DataInitializer>(Init)
->getContents();
Section->appendData(Str, llvm::StringRef(Data.data(), Data.size()));
break;
......@@ -422,7 +421,7 @@ void ELFObjectWriter::writeDataOfType(SectionType ST,
break;
case VariableDeclaration::Initializer::RelocInitializerKind: {
const auto *Reloc =
llvm::cast<VariableDeclaration::RelocInitializer>(Init.get());
llvm::cast<VariableDeclaration::RelocInitializer>(Init);
AssemblerFixup NewFixup;
NewFixup.set_position(Section->getCurrentSize());
NewFixup.set_kind(Reloc->hasFixup() ? Reloc->getFixup()
......
......@@ -24,6 +24,8 @@ using namespace llvm::ELF;
namespace Ice {
using VariableDeclarationPartition = std::vector<VariableDeclaration *>;
/// Higher level ELF object writer. Manages section information and writes the
/// final ELF object. The object writer will write to file the code and data as
/// it is being defined (rather than keep a copy). After all definitions are
......@@ -153,7 +155,7 @@ private:
/// SectionType, given the global variables Vars belonging to that
/// SectionType.
void writeDataOfType(SectionType SectionType,
const VariableDeclarationList &Vars,
const VariableDeclarationPartition &Vars,
FixupKind RelocationKind, const IceString &SectionSuffix,
bool IsPIC);
......
......@@ -292,17 +292,6 @@ GlobalContext::GlobalContext(Ostream *OsDump, Ostream *OsEmit, Ostream *OsError,
break;
}
// ProfileBlockInfoVarDecl is initialized here because it takes this as a
// parameter -- we want to
// ensure that at least this' member variables are initialized.
ProfileBlockInfoVarDecl = VariableDeclaration::createExternal(this);
ProfileBlockInfoVarDecl->setAlignment(typeWidthInBytes(IceType_i64));
ProfileBlockInfoVarDecl->setIsConstant(true);
// Note: if you change this symbol, make sure to update
// runtime/szrt_profiler.c as well.
ProfileBlockInfoVarDecl->setName("__Sz_block_profile_info");
TargetLowering::staticInit(this);
}
......@@ -397,14 +386,10 @@ void GlobalContext::lowerConstants() { DataLowering->lowerConstants(); }
void GlobalContext::lowerJumpTables() { DataLowering->lowerJumpTables(); }
void GlobalContext::addBlockInfoPtrs(VariableDeclaration *ProfileBlockInfo) {
for (const VariableDeclaration *Global : Globals) {
void GlobalContext::saveBlockInfoPtrs() {
for (VariableDeclaration *Global : Globals) {
if (Cfg::isProfileGlobal(*Global)) {
constexpr RelocOffsetT BlockExecutionCounterOffset = 0;
ProfileBlockInfo->addInitializer(
VariableDeclaration::RelocInitializer::create(
Global,
{RelocOffset::create(this, BlockExecutionCounterOffset)}));
ProfileBlockInfos.push_back(Global);
}
}
}
......@@ -424,7 +409,7 @@ void GlobalContext::lowerGlobals(const IceString &SectionSuffix) {
if (Flags.getDisableTranslation())
return;
addBlockInfoPtrs(ProfileBlockInfoVarDecl);
saveBlockInfoPtrs();
// If we need to shuffle the layout of global variables, shuffle them now.
if (getFlags().shouldReorderGlobalVariables()) {
// Create a random number generator for global variable reordering.
......@@ -434,26 +419,48 @@ void GlobalContext::lowerGlobals(const IceString &SectionSuffix) {
[&RNG](int N) { return (uint32_t)RNG.next(N); });
}
DataLowering->lowerGlobals(Globals, SectionSuffix);
for (VariableDeclaration *Var : Globals) {
Var->discardInitializers();
if (ProfileBlockInfos.empty() && DisposeGlobalVariablesAfterLowering) {
Globals.clearAndPurge();
} else {
Globals.clear();
}
Globals.clear();
}
void GlobalContext::lowerProfileData() {
// ProfileBlockInfoVarDecl is initialized in the constructor, and will only
// ever be nullptr after this method completes. This assertion is a convoluted
// way of ensuring lowerProfileData is invoked a single time.
assert(ProfileBlockInfoVarDecl != nullptr);
assert(ProfileBlockInfoVarDecl == nullptr);
auto GlobalVariablePool = getInitializerAllocator();
ProfileBlockInfoVarDecl =
VariableDeclaration::createExternal(GlobalVariablePool.get());
ProfileBlockInfoVarDecl->setAlignment(typeWidthInBytes(IceType_i64));
ProfileBlockInfoVarDecl->setIsConstant(true);
// Note: if you change this symbol, make sure to update
// runtime/szrt_profiler.c as well.
ProfileBlockInfoVarDecl->setName("__Sz_block_profile_info");
for (const VariableDeclaration *PBI : ProfileBlockInfos) {
if (Cfg::isProfileGlobal(*PBI)) {
constexpr RelocOffsetT BlockExecutionCounterOffset = 0;
ProfileBlockInfoVarDecl->addInitializer(
VariableDeclaration::RelocInitializer::create(
GlobalVariablePool.get(), PBI,
{RelocOffset::create(this, BlockExecutionCounterOffset)}));
}
}
// This adds a 64-bit sentinel entry to the end of our array. For 32-bit
// architectures this will waste 4 bytes.
const SizeT Sizeof64BitNullPtr = typeWidthInBytes(IceType_i64);
ProfileBlockInfoVarDecl->addInitializer(
VariableDeclaration::ZeroInitializer::create(Sizeof64BitNullPtr));
VariableDeclaration::ZeroInitializer::create(GlobalVariablePool.get(),
Sizeof64BitNullPtr));
Globals.push_back(ProfileBlockInfoVarDecl);
constexpr char ProfileDataSection[] = "$sz_profiler$";
lowerGlobals(ProfileDataSection);
ProfileBlockInfoVarDecl = nullptr;
}
void GlobalContext::emitItems() {
......
......@@ -57,6 +57,7 @@ public:
~LockedPtr() { Lock->unlock(); }
T *operator->() const { return Value; }
T &operator*() const { return *Value; }
T *get() { return Value; }
private:
T *Value;
......@@ -435,6 +436,18 @@ public:
static ClFlags Flags;
static ClFlagsExtra ExtraFlags;
/// DisposeGlobalVariablesAfterLowering controls whether the memory used by
/// GlobaleVariables can be reclaimed right after they have been lowered.
/// @{
bool getDisposeGlobalVariablesAfterLowering() const {
return DisposeGlobalVariablesAfterLowering;
}
void setDisposeGlobalVariablesAfterLowering(bool Value) {
DisposeGlobalVariablesAfterLowering = Value;
}
/// @}
private:
// Try to ensure mutexes are allocated on separate cache lines.
......@@ -445,6 +458,11 @@ private:
ArenaAllocator Allocator;
ICE_CACHELINE_BOUNDARY;
// Managed by getInitializerAllocator()
GlobalLockType InitAllocLock;
VariableDeclarationList Globals;
ICE_CACHELINE_BOUNDARY;
// Managed by getDestructors()
using DestructorArray = std::vector<std::function<void()>>;
GlobalLockType DestructorsLock;
......@@ -499,13 +517,18 @@ private:
// TODO(jpp): move to EmitterContext.
bool HasSeenCode = false;
// TODO(jpp): move to EmitterContext.
VariableDeclarationList Globals;
// TODO(jpp): move to EmitterContext.
VariableDeclaration *ProfileBlockInfoVarDecl;
VariableDeclaration *ProfileBlockInfoVarDecl = nullptr;
std::vector<VariableDeclaration *> ProfileBlockInfos;
/// Indicates if global variable declarations can be disposed of right after
/// lowering.
bool DisposeGlobalVariablesAfterLowering = true;
LockedPtr<ArenaAllocator> getAllocator() {
return LockedPtr<ArenaAllocator>(&Allocator, &AllocLock);
}
LockedPtr<VariableDeclarationList> getInitializerAllocator() {
return LockedPtr<VariableDeclarationList>(&Globals, &InitAllocLock);
}
LockedPtr<ConstantPool> getConstPool() {
return LockedPtr<ConstantPool>(ConstPool.get(), &ConstPoolLock);
}
......@@ -523,8 +546,10 @@ private:
}
void accumulateGlobals(std::unique_ptr<VariableDeclarationList> Globls) {
if (Globls != nullptr)
Globals.insert(Globals.end(), Globls->begin(), Globls->end());
LockedPtr<VariableDeclarationList> _(&Globals, &InitAllocLock);
if (Globls != nullptr) {
Globals.merge(Globls.get());
}
}
void lowerGlobalsIfNoCodeHasBeenSeen() {
......@@ -535,7 +560,7 @@ private:
HasSeenCode = true;
}
void addBlockInfoPtrs(VariableDeclaration *ProfileBlockInfo);
void saveBlockInfoPtrs();
llvm::SmallVector<ThreadContext *, 128> AllThreadContexts;
llvm::SmallVector<std::thread, 128> TranslationThreads;
......
......@@ -138,12 +138,12 @@ void FunctionDeclaration::dump(Ostream &Stream) const {
void VariableDeclaration::dumpType(Ostream &Stream) const {
if (!Ice::BuildDefs::dump())
return;
if (Initializers->size() == 1) {
Initializers->front()->dumpType(Stream);
if (Initializers.size() == 1) {
Initializers.front()->dumpType(Stream);
} else {
Stream << "<{ ";
bool IsFirst = true;
for (const std::unique_ptr<Initializer> &Init : *Initializers) {
for (const auto *Init : Initializers) {
if (IsFirst) {
IsFirst = false;
} else {
......@@ -163,13 +163,13 @@ void VariableDeclaration::dump(Ostream &Stream) const {
Stream << " " << (IsConstant ? "constant" : "global") << " ";
// Add initializer.
if (Initializers->size() == 1) {
Initializers->front()->dump(Stream);
if (Initializers.size() == 1) {
Initializers.front()->dump(Stream);
} else {
dumpType(Stream);
Stream << " <{ ";
bool IsFirst = true;
for (const std::unique_ptr<Initializer> &Init : *Initializers) {
for (const auto *Init : Initializers) {
if (IsFirst) {
IsFirst = false;
} else {
......@@ -199,7 +199,8 @@ void VariableDeclaration::DataInitializer::dump(Ostream &Stream) const {
Stream << " c\"";
// Code taken from PrintEscapedString() in AsmWriter.cpp. Keep the strings in
// the same format as the .ll file for practical diffing.
for (uint8_t C : Contents) {
for (SizeT i = 0; i < ContentsSize; ++i) {
uint8_t C = Contents[i];
if (isprint(C) && C != '\\' && C != '"')
Stream << C;
else
......
......@@ -826,12 +826,11 @@ void TargetDataLowering::emitGlobal(const VariableDeclaration &Var,
Str << Name << ":\n";
if (HasNonzeroInitializer) {
for (const std::unique_ptr<VariableDeclaration::Initializer> &Init :
Var.getInitializers()) {
for (const auto *Init : Var.getInitializers()) {
switch (Init->getKind()) {
case VariableDeclaration::Initializer::DataInitializerKind: {
const auto &Data =
llvm::cast<VariableDeclaration::DataInitializer>(Init.get())
llvm::cast<VariableDeclaration::DataInitializer>(Init)
->getContents();
for (SizeT i = 0; i < Init->getNumBytes(); ++i) {
Str << "\t.byte\t" << (((unsigned)Data[i]) & 0xff) << "\n";
......@@ -843,7 +842,7 @@ void TargetDataLowering::emitGlobal(const VariableDeclaration &Var,
break;
case VariableDeclaration::Initializer::RelocInitializerKind: {
const auto *Reloc =
llvm::cast<VariableDeclaration::RelocInitializer>(Init.get());
llvm::cast<VariableDeclaration::RelocInitializer>(Init);
Str << "\t" << getEmit32Directive() << "\t";
Str << Reloc->getDeclaration()->getName();
if (Reloc->hasFixup()) {
......
......@@ -908,15 +908,19 @@ IceString TargetARM32::createGotoffRelocation(const ConstantRelocatable *CR) {
"GOTOFF$" + Func->getFunctionName() + "$" + CRName;
if (KnownGotoffs.count(CRGotoffName) == 0) {
constexpr bool SuppressMangling = true;
auto *Global = VariableDeclaration::create(Ctx, SuppressMangling);
auto *Global =
VariableDeclaration::create(Func->getGlobalPool(), SuppressMangling);
Global->setIsConstant(true);
Global->setName(CRName);
Func->getGlobalPool()->willNotBeEmitted(Global);
auto *Gotoff = VariableDeclaration::create(Ctx, SuppressMangling);
auto *Gotoff =
VariableDeclaration::create(Func->getGlobalPool(), SuppressMangling);
constexpr auto GotFixup = R_ARM_GOTOFF32;
Gotoff->setIsConstant(true);
Gotoff->addInitializer(VariableDeclaration::RelocInitializer::create(
Global, {RelocOffset::create(Ctx, 0)}, GotFixup));
Func->getGlobalPool(), Global, {RelocOffset::create(Ctx, 0)},
GotFixup));
Gotoff->setName(CRGotoffName);
Func->addGlobal(Gotoff);
KnownGotoffs.emplace(CRGotoffName);
......
......@@ -257,6 +257,11 @@ public:
size_t getNumTypeIDValues() const { return TypeIDValues.size(); }
/// Returns a pointer to the pool where globals are allocated.
Ice::VariableDeclarationList *getGlobalVariablesPool() {
return VariableDeclarations.get();
}
/// Returns the undefined type associated with type ID. Note: Returns extended
/// type ready to be defined.
ExtendedType *getTypeByIDForDefining(NaClBcIndexSize_t ID) {
......@@ -1021,9 +1026,11 @@ public:
: BlockParserBaseClass(BlockID, EnclosingParser),
Timer(Ice::TimerStack::TT_parseGlobals, getTranslator().getContext()),
NumFunctionIDs(Context->getNumFunctionIDs()),
DummyGlobalVar(
Ice::VariableDeclaration::create(getTranslator().getContext())),
CurGlobalVar(DummyGlobalVar) {}
DummyGlobalVar(Ice::VariableDeclaration::create(
Context->getGlobalVariablesPool())),
CurGlobalVar(DummyGlobalVar) {
Context->getGlobalVariablesPool()->willNotBeEmitted(DummyGlobalVar);
}
~GlobalsParser() final = default;
......@@ -1063,7 +1070,8 @@ private:
Ice::VariableDeclaration *getGlobalVarByID(NaClBcIndexSize_t Index) {
Ice::VariableDeclaration *&Decl = GlobalVarsMap[Index];
if (Decl == nullptr)
Decl = Ice::VariableDeclaration::create(getTranslator().getContext());
Decl =
Ice::VariableDeclaration::create(Context->getGlobalVariablesPool());
return Decl;
}
......@@ -1173,16 +1181,18 @@ void GlobalsParser::ProcessRecord() {
// ZEROFILL: [size]
if (!isValidRecordSize(1, "zerofill"))
return;
auto *Pool = Context->getGlobalVariablesPool();
CurGlobalVar->addInitializer(
Ice::VariableDeclaration::ZeroInitializer::create(Values[0]));
Ice::VariableDeclaration::ZeroInitializer::create(Pool, Values[0]));
return;
}
case naclbitc::GLOBALVAR_DATA: {
// DATA: [b0, b1, ...]
if (!isValidRecordSizeAtLeast(1, "data"))
return;
auto *Pool = Context->getGlobalVariablesPool();
CurGlobalVar->addInitializer(
Ice::VariableDeclaration::DataInitializer::create(Values));
Ice::VariableDeclaration::DataInitializer::create(Pool, Values));
return;
}
case naclbitc::GLOBALVAR_RELOC: {
......@@ -1208,10 +1218,12 @@ void GlobalsParser::ProcessRecord() {
Error(StrBuf.str());
}
}
auto *Pool = Context->getGlobalVariablesPool();
Ice::GlobalContext *Ctx = getTranslator().getContext();
CurGlobalVar->addInitializer(
Ice::VariableDeclaration::RelocInitializer::create(
getGlobalDeclByID(Index), {Ice::RelocOffset::create(Ctx, Offset)}));
Pool, getGlobalDeclByID(Index),
{Ice::RelocOffset::create(Ctx, Offset)}));
return;
}
default:
......
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