Fix a bug that would cause subzero to fail when --threads=0.
Creates a single TargetDataLowering.
BUG= None
R=stichnot@chromium.org
Review URL: https://codereview.chromium.org/1179313004.
diff --git a/src/IceCfgNode.cpp b/src/IceCfgNode.cpp
index dec40e4..aeb54ff 100644
--- a/src/IceCfgNode.cpp
+++ b/src/IceCfgNode.cpp
@@ -1256,7 +1256,10 @@
assert(Info != nullptr);
Operand *RMWI64Name = Context->getConstantExternSym(RMW_I64);
- Constant *Counter = Context->getConstantExternSym(Var->getName());
+ constexpr RelocOffsetT Offset = 0;
+ constexpr bool SuppressMangling = true;
+ Constant *Counter =
+ Context->getConstantSym(Offset, Var->getName(), SuppressMangling);
Constant *AtomicRMWOp = Context->getConstantInt32(Intrinsics::AtomicAdd);
Constant *One = Context->getConstantInt64(1);
Constant *OrderAcquireRelease =
diff --git a/src/IceCompiler.cpp b/src/IceCompiler.cpp
index 2db7abc..7619b17 100644
--- a/src/IceCompiler.cpp
+++ b/src/IceCompiler.cpp
@@ -141,21 +141,28 @@
}
Ctx.waitForWorkerThreads();
- Translator->transferErrorCode();
- Translator->emitConstants();
+ if (Translator->getErrorStatus()) {
+ Ctx.getErrorStatus()->assign(Translator->getErrorStatus().value());
+ } else {
+ Ctx.lowerGlobals("last");
+ Ctx.lowerProfileData();
+ Ctx.lowerConstants();
- if (Ctx.getFlags().getOutFileType() == FT_Elf) {
- TimerMarker T1(Ice::TimerStack::TT_emit, &Ctx);
- Ctx.getObjectWriter()->setUndefinedSyms(Ctx.getConstantExternSyms());
- Ctx.getObjectWriter()->writeNonUserSections();
+ if (Ctx.getFlags().getOutFileType() == FT_Elf) {
+ TimerMarker T1(Ice::TimerStack::TT_emit, &Ctx);
+ Ctx.getObjectWriter()->setUndefinedSyms(Ctx.getConstantExternSyms());
+ Ctx.getObjectWriter()->writeNonUserSections();
+ }
}
+
if (Ctx.getFlags().getSubzeroTimingEnabled())
Ctx.dumpTimers();
+
if (Ctx.getFlags().getTimeEachFunction()) {
const bool DumpCumulative = false;
Ctx.dumpTimers(GlobalContext::TSK_Funcs, DumpCumulative);
}
- const bool FinalStats = true;
+ constexpr bool FinalStats = true;
Ctx.dumpStats("_FINAL_", FinalStats);
}
diff --git a/src/IceELFObjectWriter.cpp b/src/IceELFObjectWriter.cpp
index edb46fa..44f4adb 100644
--- a/src/IceELFObjectWriter.cpp
+++ b/src/IceELFObjectWriter.cpp
@@ -285,7 +285,8 @@
} // end of anonymous namespace
void ELFObjectWriter::writeDataSection(const VariableDeclarationList &Vars,
- FixupKind RelocationKind) {
+ FixupKind RelocationKind,
+ const IceString &SectionSuffix) {
assert(!SectionNumbersAssigned);
VariableDeclarationList VarsBySection[ELFObjectWriter::NumSectionTypes];
for (auto &SectionList : VarsBySection)
@@ -294,18 +295,28 @@
Ctx.getFlags().getTranslateOnly());
size_t I = 0;
for (auto &SectionList : VarsBySection) {
- writeDataOfType(static_cast<SectionType>(I++), SectionList, RelocationKind);
+ writeDataOfType(static_cast<SectionType>(I++), SectionList, RelocationKind,
+ SectionSuffix);
}
}
+namespace {
+IceString MangleSectionName(const char Base[], const IceString &Suffix) {
+ if (Suffix.empty())
+ return Base;
+ return Base + ("." + Suffix);
+}
+} // end of anonymous namespace
+
+// TODO(jvoung): Handle fdata-sections.
void ELFObjectWriter::writeDataOfType(SectionType ST,
const VariableDeclarationList &Vars,
- FixupKind RelocationKind) {
+ FixupKind RelocationKind,
+ const IceString &SectionSuffix) {
if (Vars.empty())
return;
ELFDataSection *Section;
ELFRelocationSection *RelSection;
- // TODO(jvoung): Handle fdata-sections.
IceString SectionName;
Elf64_Xword ShAddralign = 1;
for (VariableDeclaration *Var : Vars) {
@@ -316,9 +327,7 @@
// Lift this out, so it can be re-used if we do fdata-sections?
switch (ST) {
case ROData: {
- SectionName = ".rodata";
- // Only expecting to write the data sections all in one shot for now.
- assert(RODataSections.empty());
+ const IceString SectionName = MangleSectionName(".rodata", SectionSuffix);
const Elf64_Xword ShFlags = SHF_ALLOC;
Section = createSection<ELFDataSection>(SectionName, SHT_PROGBITS, ShFlags,
ShAddralign, ShEntsize);
@@ -329,8 +338,7 @@
break;
}
case Data: {
- SectionName = ".data";
- assert(DataSections.empty());
+ const IceString SectionName = MangleSectionName(".data", SectionSuffix);
const Elf64_Xword ShFlags = SHF_ALLOC | SHF_WRITE;
Section = createSection<ELFDataSection>(SectionName, SHT_PROGBITS, ShFlags,
ShAddralign, ShEntsize);
@@ -341,8 +349,7 @@
break;
}
case BSS: {
- SectionName = ".bss";
- assert(BSSSections.empty());
+ const IceString SectionName = MangleSectionName(".bss", SectionSuffix);
const Elf64_Xword ShFlags = SHF_ALLOC | SHF_WRITE;
Section = createSection<ELFDataSection>(SectionName, SHT_NOBITS, ShFlags,
ShAddralign, ShEntsize);
@@ -383,9 +390,8 @@
for (VariableDeclaration::Initializer *Init : Var->getInitializers()) {
switch (Init->getKind()) {
case VariableDeclaration::Initializer::DataInitializerKind: {
- const auto Data =
- llvm::cast<VariableDeclaration::DataInitializer>(Init)
- ->getContents();
+ const auto Data = llvm::cast<VariableDeclaration::DataInitializer>(
+ Init)->getContents();
Section->appendData(Str, llvm::StringRef(Data.data(), Data.size()));
break;
}
diff --git a/src/IceELFObjectWriter.h b/src/IceELFObjectWriter.h
index 1103845..a9127ac 100644
--- a/src/IceELFObjectWriter.h
+++ b/src/IceELFObjectWriter.h
@@ -30,11 +30,12 @@
// sections and write them out. Expected usage:
//
// (1) writeInitialELFHeader (invoke once)
-// (2) writeDataSection (invoke once)
-// (3) writeFunctionCode (must invoke once per function)
-// (4) writeConstantPool (must invoke once per pooled primitive type)
-// (5) setUndefinedSyms (invoke once)
-// (6) writeNonUserSections (invoke once)
+// (2) writeDataSection (may be invoked multiple times, as long as
+// SectionSuffix is unique)
+// (3) writeFunctionCode (must invoke once per function)
+// (4) writeConstantPool (must invoke once per pooled primitive type)
+// (5) setUndefinedSyms (invoke once)
+// (6) 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
@@ -42,11 +43,6 @@
// 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 {
ELFObjectWriter() = delete;
ELFObjectWriter(const ELFObjectWriter &) = delete;
@@ -64,7 +60,8 @@
// 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);
+ FixupKind RelocationKind,
+ const IceString &SectionSuffix);
// Copy data of a function's text section to file and note the offset of the
// symbol's definition in the symbol table.
@@ -151,7 +148,8 @@
// SectionType, given the global variables Vars belonging to that SectionType.
void writeDataOfType(SectionType SectionType,
const VariableDeclarationList &Vars,
- FixupKind RelocationKind);
+ FixupKind RelocationKind,
+ const IceString &SectionSuffix);
// Write the final relocation sections given the final symbol table.
// May also be able to seek around the file and resolve function calls
diff --git a/src/IceGlobalContext.cpp b/src/IceGlobalContext.cpp
index 8ed4d76..b23e75b 100644
--- a/src/IceGlobalContext.cpp
+++ b/src/IceGlobalContext.cpp
@@ -222,7 +222,10 @@
OptQ(/*Sequential=*/Flags.isSequential(),
/*MaxSize=*/Flags.getNumTranslationThreads()),
// EmitQ is allowed unlimited size.
- EmitQ(/*Sequential=*/Flags.isSequential()) {
+ EmitQ(/*Sequential=*/Flags.isSequential()),
+ DataLowering(TargetDataLowering::createLowering(this)),
+ HasSeenCode(false),
+ ProfileBlockInfoVarDecl(VariableDeclaration::create()) {
assert(OsDump && "OsDump is not defined for GlobalContext");
assert(OsEmit && "OsEmit is not defined for GlobalContext");
assert(OsError && "OsError is not defined for GlobalContext");
@@ -254,6 +257,14 @@
case FT_Iasm:
break;
}
+ 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");
+ ProfileBlockInfoVarDecl->setSuppressMangling();
+ ProfileBlockInfoVarDecl->setLinkage(llvm::GlobalValue::ExternalLinkage);
}
void GlobalContext::translateFunctions() {
@@ -322,67 +333,16 @@
namespace {
-// Adds an array of pointers to all the profiler-generated globals. The
-// __Sz_profile_summary function iterates over this array for printing the
-// profiling counters.
-VariableDeclaration *blockProfileInfo(const VariableDeclarationList &Globals) {
- auto *Var = VariableDeclaration::create();
- Var->setAlignment(typeWidthInBytes(IceType_i64));
- Var->setIsConstant(true);
-
- // Note: if you change this symbol, make sure to update
- // runtime/szrt_profiler.c as well.
- Var->setName("__Sz_block_profile_info");
- Var->setSuppressMangling();
- Var->setLinkage(llvm::GlobalValue::ExternalLinkage);
+void addBlockInfoPtrs(const VariableDeclarationList &Globals,
+ VariableDeclaration *ProfileBlockInfo) {
for (const VariableDeclaration *Global : Globals) {
if (Cfg::isProfileGlobal(*Global)) {
constexpr RelocOffsetT BlockExecutionCounterOffset = 0;
- Var->addInitializer(new VariableDeclaration::RelocInitializer(
- Global, BlockExecutionCounterOffset));
+ ProfileBlockInfo->addInitializer(
+ new VariableDeclaration::RelocInitializer(
+ Global, 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);
- Var->addInitializer(
- new VariableDeclaration::ZeroInitializer(Sizeof64BitNullPtr));
-
- return Var;
-}
-
-void addBlockProfileInfoArrayToGlobals(VariableDeclarationList *Globals) {
- // Purposefully create the Var temp to prevent bugs in case the compiler
- // reorders instructions in a way that Globals is extended before the call
- // to profileInfoArray.
- VariableDeclaration *Var = blockProfileInfo(*Globals);
- Globals->push_back(Var);
-}
-
-void lowerGlobals(GlobalContext *Ctx,
- std::unique_ptr<VariableDeclarationList> VariableDeclarations,
- TargetDataLowering *DataLowering) {
- TimerMarker T(TimerStack::TT_emitGlobalInitializers, Ctx);
- const bool DumpGlobalVariables = ALLOW_DUMP && Ctx->getFlags().getVerbose() &&
- Ctx->getFlags().getVerboseFocusOn().empty();
- if (DumpGlobalVariables) {
- OstreamLocker L(Ctx);
- Ostream &Stream = Ctx->getStrDump();
- for (const Ice::VariableDeclaration *Global : *VariableDeclarations) {
- Global->dump(Ctx, Stream);
- }
- }
- if (Ctx->getFlags().getDisableTranslation())
- return;
-
- // There should be no need to emit the block_profile_info array if profiling
- // is disabled. In practice, given that szrt_profiler.o will always be
- // embedded in the application, we need to add it. In a non-profiled build
- // this array will only contain the nullptr terminator.
- addBlockProfileInfoArrayToGlobals(VariableDeclarations.get());
-
- DataLowering->lowerGlobals(std::move(VariableDeclarations));
}
// Ensure Pending is large enough that Pending[Index] is valid.
@@ -391,13 +351,6 @@
Pending.resize(Index + 1);
}
-void addAllIfNotNull(std::unique_ptr<VariableDeclarationList> src,
- VariableDeclarationList *dst) {
- if (src != nullptr) {
- dst->insert(dst->end(), src->begin(), src->end());
- }
-}
-
} // end of anonymous namespace
void GlobalContext::emitFileHeader() {
@@ -411,6 +364,40 @@
}
}
+void GlobalContext::lowerConstants() {
+ DataLowering->lowerConstants();
+}
+
+void GlobalContext::lowerGlobals(const IceString &SectionSuffix) {
+ TimerMarker T(TimerStack::TT_emitGlobalInitializers, this);
+ const bool DumpGlobalVariables =
+ ALLOW_DUMP && Flags.getVerbose() && Flags.getVerboseFocusOn().empty();
+ if (DumpGlobalVariables) {
+ OstreamLocker L(this);
+ Ostream &Stream = getStrDump();
+ for (const Ice::VariableDeclaration *Global : Globals) {
+ Global->dump(this, Stream);
+ }
+ }
+ if (Flags.getDisableTranslation())
+ return;
+
+ addBlockInfoPtrs(Globals, ProfileBlockInfoVarDecl.get());
+ DataLowering->lowerGlobals(Globals, SectionSuffix);
+ Globals.clear();
+}
+
+void GlobalContext::lowerProfileData() {
+ // 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(
+ new VariableDeclaration::ZeroInitializer(Sizeof64BitNullPtr));
+ Globals.push_back(ProfileBlockInfoVarDecl.get());
+ constexpr char ProfileDataSection[] = "$sz_profiler$";
+ lowerGlobals(ProfileDataSection);
+}
+
void GlobalContext::emitItems() {
const bool Threaded = !getFlags().isSequential();
// Pending is a vector containing the reassembled, ordered list of
@@ -419,8 +406,6 @@
// the work queue, and if it's not the item we're waiting for, we
// insert it into Pending and repeat. The work item is deleted
// after it is processed.
- std::unique_ptr<VariableDeclarationList> GlobalInits(
- new VariableDeclarationList());
std::vector<EmitterWorkItem *> Pending;
uint32_t DesiredSequenceNumber = getFirstSequenceNumber();
while (true) {
@@ -444,10 +429,12 @@
case EmitterWorkItem::WI_Nop:
break;
case EmitterWorkItem::WI_GlobalInits: {
- addAllIfNotNull(Item->getGlobalInits(), GlobalInits.get());
+ accumulateGlobals(Item->getGlobalInits());
} break;
case EmitterWorkItem::WI_Asm: {
- addAllIfNotNull(Item->getGlobalInits(), GlobalInits.get());
+ lowerGlobalsIfNoCodeHasBeenSeen();
+ accumulateGlobals(Item->getGlobalInits());
+
std::unique_ptr<Assembler> Asm = Item->getAsm();
Asm->alignFunction();
IceString MangledName = mangleName(Asm->getFunctionName());
@@ -469,8 +456,8 @@
case EmitterWorkItem::WI_Cfg: {
if (!ALLOW_DUMP)
llvm::report_fatal_error("WI_Cfg work item created inappropriately");
-
- addAllIfNotNull(Item->getGlobalInits(), GlobalInits.get());
+ lowerGlobalsIfNoCodeHasBeenSeen();
+ accumulateGlobals(Item->getGlobalInits());
assert(getFlags().getOutFileType() == FT_Asm);
std::unique_ptr<Cfg> Func = Item->getCfg();
@@ -485,8 +472,9 @@
}
}
- lowerGlobals(this, std::move(GlobalInits),
- TargetDataLowering::createLowering(this).get());
+ // In case there are no code to be generated, we invoke the conditional
+ // lowerGlobals again -- this is a no-op if code has been emitted.
+ lowerGlobalsIfNoCodeHasBeenSeen();
}
// Scan a string for S[0-9A-Z]*_ patterns and replace them with
diff --git a/src/IceGlobalContext.h b/src/IceGlobalContext.h
index 763a75b..ff8ff25 100644
--- a/src/IceGlobalContext.h
+++ b/src/IceGlobalContext.h
@@ -303,6 +303,8 @@
// Emit file header for output file.
void emitFileHeader();
+ void lowerConstants();
+
void emitQueueBlockingPush(EmitterWorkItem *Item);
EmitterWorkItem *emitQueueBlockingPop();
void emitQueueNotifyEnd() { EmitQ.notifyEnd(); }
@@ -380,6 +382,13 @@
// until the queue is empty.
void emitItems();
+ // Uses DataLowering to lower Globals. As a side effect, clears the Globals
+ // array.
+ void lowerGlobals(const IceString &SectionSuffix);
+
+ // Lowers the profile information.
+ void lowerProfileData();
+
// Utility function to match a symbol name against a match string.
// This is used in a few cases where we want to take some action on
// a particular function or symbol based on a command-line argument,
@@ -432,9 +441,22 @@
Intrinsics IntrinsicsInfo;
const ClFlags &Flags;
RandomNumberGenerator RNG; // TODO(stichnot): Move into Cfg.
+ // TODO(jpp): move to EmitterContext.
std::unique_ptr<ELFObjectWriter> ObjectWriter;
BoundedProducerConsumerQueue<Cfg> OptQ;
BoundedProducerConsumerQueue<EmitterWorkItem> EmitQ;
+ // DataLowering is only ever used by a single thread at a time (either in
+ // emitItems(), or in IceCompiler::run before the compilation is over.)
+ // TODO(jpp): move to EmitterContext.
+ std::unique_ptr<TargetDataLowering> DataLowering;
+ // If !HasEmittedCode, SubZero will accumulate all Globals (which are "true"
+ // program global variables) until the first code WorkItem is seen.
+ // TODO(jpp): move to EmitterContext.
+ bool HasSeenCode;
+ // TODO(jpp): move to EmitterContext.
+ VariableDeclarationList Globals;
+ // TODO(jpp): move to EmitterContext.
+ std::unique_ptr<VariableDeclaration> ProfileBlockInfoVarDecl;
LockedPtr<ArenaAllocator<>> getAllocator() {
return LockedPtr<ArenaAllocator<>>(&Allocator, &AllocLock);
@@ -449,6 +471,19 @@
return LockedPtr<TimerList>(&Timers, &TimerLock);
}
+ void accumulateGlobals(std::unique_ptr<VariableDeclarationList> Globls) {
+ if (Globls != nullptr)
+ Globals.insert(Globals.end(), Globls->begin(), Globls->end());
+ }
+
+ void lowerGlobalsIfNoCodeHasBeenSeen() {
+ if (HasSeenCode)
+ return;
+ constexpr char NoSuffix[] = "";
+ lowerGlobals(NoSuffix);
+ HasSeenCode = true;
+ }
+
llvm::SmallVector<ThreadContext *, 128> AllThreadContexts;
llvm::SmallVector<std::thread, 128> TranslationThreads;
llvm::SmallVector<std::thread, 128> EmitterThreads;
diff --git a/src/IceTargetLowering.cpp b/src/IceTargetLowering.cpp
index 4bb035a..52017ea 100644
--- a/src/IceTargetLowering.cpp
+++ b/src/IceTargetLowering.cpp
@@ -446,40 +446,63 @@
TargetDataLowering::~TargetDataLowering() {}
-void TargetDataLowering::emitGlobal(const VariableDeclaration &Var) {
+namespace {
+
+// dataSectionSuffix decides whether to use SectionSuffix or MangledVarName as
+// data section suffix. Essentially, when using separate data sections for
+// globals SectionSuffix is not necessary.
+IceString dataSectionSuffix(const IceString &SectionSuffix,
+ const IceString &MangledVarName,
+ const bool DataSections) {
+ if (SectionSuffix.empty() && !DataSections) {
+ return "";
+ }
+
+ if (DataSections) {
+ // With data sections we don't need to use the SectionSuffix.
+ return "." + MangledVarName;
+ }
+
+ assert(!SectionSuffix.empty());
+ return "." + SectionSuffix;
+}
+
+} // end of anonymous namespace
+
+void TargetDataLowering::emitGlobal(const VariableDeclaration &Var,
+ const IceString &SectionSuffix) {
if (!ALLOW_DUMP)
return;
// If external and not initialized, this must be a cross test.
// Don't generate a declaration for such cases.
- bool IsExternal = Var.isExternal() || Ctx->getFlags().getDisableInternal();
+ const bool IsExternal =
+ Var.isExternal() || Ctx->getFlags().getDisableInternal();
if (IsExternal && !Var.hasInitializer())
return;
Ostream &Str = Ctx->getStrEmit();
- const VariableDeclaration::InitializerListType &Initializers =
- Var.getInitializers();
- bool HasNonzeroInitializer = Var.hasNonzeroInitializer();
- bool IsConstant = Var.getIsConstant();
- uint32_t Align = Var.getAlignment();
- SizeT Size = Var.getNumBytes();
- IceString MangledName = Var.mangleName(Ctx);
- IceString SectionSuffix = "";
- if (Ctx->getFlags().getDataSections())
- SectionSuffix = "." + MangledName;
+ const bool HasNonzeroInitializer = Var.hasNonzeroInitializer();
+ const bool IsConstant = Var.getIsConstant();
+ const SizeT Size = Var.getNumBytes();
+ const IceString MangledName = Var.mangleName(Ctx);
Str << "\t.type\t" << MangledName << ",%object\n";
+ const bool UseDataSections = Ctx->getFlags().getDataSections();
+ const IceString Suffix =
+ dataSectionSuffix(SectionSuffix, MangledName, UseDataSections);
if (IsConstant)
- Str << "\t.section\t.rodata" << SectionSuffix << ",\"a\",%progbits\n";
+ Str << "\t.section\t.rodata" << Suffix << ",\"a\",%progbits\n";
else if (HasNonzeroInitializer)
- Str << "\t.section\t.data" << SectionSuffix << ",\"aw\",%progbits\n";
+ Str << "\t.section\t.data" << Suffix << ",\"aw\",%progbits\n";
else
- Str << "\t.section\t.bss" << SectionSuffix << ",\"aw\",%nobits\n";
+ Str << "\t.section\t.bss" << Suffix << ",\"aw\",%nobits\n";
if (IsExternal)
Str << "\t.globl\t" << MangledName << "\n";
+ const uint32_t Align = Var.getAlignment();
if (Align > 1) {
assert(llvm::isPowerOf2_32(Align));
// Use the .p2align directive, since the .align N directive can either
@@ -490,11 +513,11 @@
Str << MangledName << ":\n";
if (HasNonzeroInitializer) {
- for (VariableDeclaration::Initializer *Init : Initializers) {
+ for (VariableDeclaration::Initializer *Init : Var.getInitializers()) {
switch (Init->getKind()) {
case VariableDeclaration::Initializer::DataInitializerKind: {
- const auto Data = llvm::cast<VariableDeclaration::DataInitializer>(Init)
- ->getContents();
+ const auto &Data = llvm::cast<VariableDeclaration::DataInitializer>(
+ Init)->getContents();
for (SizeT i = 0; i < Init->getNumBytes(); ++i) {
Str << "\t.byte\t" << (((unsigned)Data[i]) & 0xff) << "\n";
}
@@ -504,7 +527,7 @@
Str << "\t.zero\t" << Init->getNumBytes() << "\n";
break;
case VariableDeclaration::Initializer::RelocInitializerKind: {
- const auto Reloc =
+ const auto *Reloc =
llvm::cast<VariableDeclaration::RelocInitializer>(Init);
Str << "\t" << getEmit32Directive() << "\t";
Str << Reloc->getDeclaration()->mangleName(Ctx);
@@ -519,12 +542,13 @@
}
}
}
- } else
+ } else {
// NOTE: for non-constant zero initializers, this is BSS (no bits),
// so an ELF writer would not write to the file, and only track
// virtual offsets, but the .s writer still needs this .zero and
// cannot simply use the .size to advance offsets.
Str << "\t.zero\t" << Size << "\n";
+ }
Str << "\t.size\t" << MangledName << ", " << Size << "\n";
}
diff --git a/src/IceTargetLowering.h b/src/IceTargetLowering.h
index 4d9598a..fa6f5b7 100644
--- a/src/IceTargetLowering.h
+++ b/src/IceTargetLowering.h
@@ -380,16 +380,18 @@
static std::unique_ptr<TargetDataLowering> createLowering(GlobalContext *Ctx);
virtual ~TargetDataLowering();
- virtual void lowerGlobals(std::unique_ptr<VariableDeclarationList> Vars) = 0;
+ virtual void lowerGlobals(const VariableDeclarationList &Vars,
+ const IceString &SectionSuffix) = 0;
virtual void lowerConstants() = 0;
protected:
- void emitGlobal(const VariableDeclaration &Var);
+ void emitGlobal(const VariableDeclaration &Var,
+ const IceString &SectionSuffix);
// For now, we assume .long is the right directive for emitting 4 byte
// emit global relocations. However, LLVM MIPS usually uses .4byte instead.
// Perhaps there is some difference when the location is unaligned.
- const char *getEmit32Directive() { return ".long"; }
+ static const char *getEmit32Directive() { return ".long"; }
explicit TargetDataLowering(GlobalContext *Ctx) : Ctx(Ctx) {}
GlobalContext *Ctx;
diff --git a/src/IceTargetLoweringARM32.cpp b/src/IceTargetLoweringARM32.cpp
index 2d3c5c1..9bb2386 100644
--- a/src/IceTargetLoweringARM32.cpp
+++ b/src/IceTargetLoweringARM32.cpp
@@ -2207,20 +2207,20 @@
TargetDataARM32::TargetDataARM32(GlobalContext *Ctx)
: TargetDataLowering(Ctx) {}
-void TargetDataARM32::lowerGlobals(
- std::unique_ptr<VariableDeclarationList> Vars) {
+void TargetDataARM32::lowerGlobals(const VariableDeclarationList &Vars,
+ const IceString &SectionSuffix) {
switch (Ctx->getFlags().getOutFileType()) {
case FT_Elf: {
ELFObjectWriter *Writer = Ctx->getObjectWriter();
- Writer->writeDataSection(*Vars, llvm::ELF::R_ARM_ABS32);
+ Writer->writeDataSection(Vars, llvm::ELF::R_ARM_ABS32, SectionSuffix);
} break;
case FT_Asm:
case FT_Iasm: {
const IceString &TranslateOnly = Ctx->getFlags().getTranslateOnly();
OstreamLocker L(Ctx);
- for (const VariableDeclaration *Var : *Vars) {
+ for (const VariableDeclaration *Var : Vars) {
if (GlobalContext::matchSymbolName(Var->getName(), TranslateOnly)) {
- emitGlobal(*Var);
+ emitGlobal(*Var, SectionSuffix);
}
}
} break;
diff --git a/src/IceTargetLoweringARM32.h b/src/IceTargetLoweringARM32.h
index 98dd20e..1fa3ce2 100644
--- a/src/IceTargetLoweringARM32.h
+++ b/src/IceTargetLoweringARM32.h
@@ -323,7 +323,8 @@
return std::unique_ptr<TargetDataLowering>(new TargetDataARM32(Ctx));
}
- void lowerGlobals(std::unique_ptr<VariableDeclarationList> Vars) override;
+ void lowerGlobals(const VariableDeclarationList &Vars,
+ const IceString &SectionSuffix) override;
void lowerConstants() override;
protected:
diff --git a/src/IceTargetLoweringMIPS32.cpp b/src/IceTargetLoweringMIPS32.cpp
index ee2300e..3655cb7 100644
--- a/src/IceTargetLoweringMIPS32.cpp
+++ b/src/IceTargetLoweringMIPS32.cpp
@@ -671,20 +671,20 @@
TargetDataMIPS32::TargetDataMIPS32(GlobalContext *Ctx)
: TargetDataLowering(Ctx) {}
-void TargetDataMIPS32::lowerGlobals(
- std::unique_ptr<VariableDeclarationList> Vars) {
+void TargetDataMIPS32::lowerGlobals(const VariableDeclarationList &Vars,
+ const IceString &SectionSuffix) {
switch (Ctx->getFlags().getOutFileType()) {
case FT_Elf: {
ELFObjectWriter *Writer = Ctx->getObjectWriter();
- Writer->writeDataSection(*Vars, llvm::ELF::R_MIPS_GLOB_DAT);
+ Writer->writeDataSection(Vars, llvm::ELF::R_MIPS_GLOB_DAT, SectionSuffix);
} break;
case FT_Asm:
case FT_Iasm: {
const IceString &TranslateOnly = Ctx->getFlags().getTranslateOnly();
OstreamLocker L(Ctx);
- for (const VariableDeclaration *Var : *Vars) {
+ for (const VariableDeclaration *Var : Vars) {
if (GlobalContext::matchSymbolName(Var->getName(), TranslateOnly)) {
- emitGlobal(*Var);
+ emitGlobal(*Var, SectionSuffix);
}
}
} break;
diff --git a/src/IceTargetLoweringMIPS32.h b/src/IceTargetLoweringMIPS32.h
index 9204833..cb89ffc 100644
--- a/src/IceTargetLoweringMIPS32.h
+++ b/src/IceTargetLoweringMIPS32.h
@@ -137,7 +137,8 @@
return std::unique_ptr<TargetDataLowering>(new TargetDataMIPS32(Ctx));
}
- void lowerGlobals(std::unique_ptr<VariableDeclarationList> Vars) override;
+ void lowerGlobals(const VariableDeclarationList &Vars,
+ const IceString &SectionSuffix) override;
void lowerConstants() override;
protected:
diff --git a/src/IceTargetLoweringX8632.cpp b/src/IceTargetLoweringX8632.cpp
index b686579..c57374b 100644
--- a/src/IceTargetLoweringX8632.cpp
+++ b/src/IceTargetLoweringX8632.cpp
@@ -3296,11 +3296,10 @@
Func->setError("Unexpected memory ordering for AtomicRMW");
return;
}
- lowerAtomicRMW(
- Instr->getDest(),
- static_cast<uint32_t>(
- llvm::cast<ConstantInteger32>(Instr->getArg(0))->getValue()),
- Instr->getArg(1), Instr->getArg(2));
+ lowerAtomicRMW(Instr->getDest(),
+ static_cast<uint32_t>(llvm::cast<ConstantInteger32>(
+ Instr->getArg(0))->getValue()),
+ Instr->getArg(1), Instr->getArg(2));
return;
case Intrinsics::AtomicStore: {
if (!Intrinsics::isMemoryOrderValid(
@@ -5021,20 +5020,20 @@
TargetDataX8632::TargetDataX8632(GlobalContext *Ctx)
: TargetDataLowering(Ctx) {}
-void TargetDataX8632::lowerGlobals(
- std::unique_ptr<VariableDeclarationList> Vars) {
+void TargetDataX8632::lowerGlobals(const VariableDeclarationList &Vars,
+ const IceString &SectionSuffix) {
switch (Ctx->getFlags().getOutFileType()) {
case FT_Elf: {
ELFObjectWriter *Writer = Ctx->getObjectWriter();
- Writer->writeDataSection(*Vars, llvm::ELF::R_386_32);
+ Writer->writeDataSection(Vars, llvm::ELF::R_386_32, SectionSuffix);
} break;
case FT_Asm:
case FT_Iasm: {
const IceString &TranslateOnly = Ctx->getFlags().getTranslateOnly();
OstreamLocker L(Ctx);
- for (const VariableDeclaration *Var : *Vars) {
+ for (const VariableDeclaration *Var : Vars) {
if (GlobalContext::matchSymbolName(Var->getName(), TranslateOnly)) {
- emitGlobal(*Var);
+ emitGlobal(*Var, SectionSuffix);
}
}
} break;
diff --git a/src/IceTargetLoweringX8632.h b/src/IceTargetLoweringX8632.h
index 0b46e1b..b9a9e2b 100644
--- a/src/IceTargetLoweringX8632.h
+++ b/src/IceTargetLoweringX8632.h
@@ -587,7 +587,8 @@
return std::unique_ptr<TargetDataLowering>(new TargetDataX8632(Ctx));
}
- void lowerGlobals(std::unique_ptr<VariableDeclarationList> Vars) override;
+ void lowerGlobals(const VariableDeclarationList &Vars,
+ const IceString &SectionSuffix) override;
void lowerConstants() override;
protected:
diff --git a/src/IceTranslator.cpp b/src/IceTranslator.cpp
index c78bbcb..aba71e5 100644
--- a/src/IceTranslator.cpp
+++ b/src/IceTranslator.cpp
@@ -57,16 +57,6 @@
Ctx->optQueueBlockingPush(std::move(Func));
}
-void Translator::emitConstants() {
- if (!getErrorStatus())
- TargetDataLowering::createLowering(Ctx)->lowerConstants();
-}
-
-void Translator::transferErrorCode() const {
- if (getErrorStatus())
- Ctx->getErrorStatus()->assign(getErrorStatus().value());
-}
-
void Translator::lowerGlobals(
std::unique_ptr<VariableDeclarationList> VariableDeclarations) {
EmitterWorkItem *Item = new EmitterWorkItem(getNextSequenceNumber(),
diff --git a/src/IceTranslator.h b/src/IceTranslator.h
index adddc32..0f7f9d7 100644
--- a/src/IceTranslator.h
+++ b/src/IceTranslator.h
@@ -48,13 +48,6 @@
/// Takes ownership of Func.
void translateFcn(std::unique_ptr<Cfg> Func);
- /// Emits the constant pool.
- void emitConstants();
-
- /// If there was an error during bitcode reading/parsing, copy the
- /// error code into the GlobalContext.
- void transferErrorCode() const;
-
/// Lowers the given list of global addresses to target. Generates
/// list of corresponding variable declarations.
void