From 8b1a705165292328a3db53da273420989b46e443 Mon Sep 17 00:00:00 2001 From: John Porto Date: Wed, 17 Jun 2015 13:20:08 -0700 Subject: [PATCH] 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. --- src/IceCfgNode.cpp | 5 +- src/IceCompiler.cpp | 23 ++++-- src/IceELFObjectWriter.cpp | 34 ++++---- src/IceELFObjectWriter.h | 22 +++-- src/IceGlobalContext.cpp | 132 ++++++++++++++---------------- src/IceGlobalContext.h | 35 ++++++++ src/IceTargetLowering.cpp | 64 ++++++++++----- src/IceTargetLowering.h | 8 +- src/IceTargetLoweringARM32.cpp | 10 +-- src/IceTargetLoweringARM32.h | 3 +- src/IceTargetLoweringMIPS32.cpp | 10 +-- src/IceTargetLoweringMIPS32.h | 3 +- src/IceTargetLoweringX8632.cpp | 19 ++--- src/IceTargetLoweringX8632.h | 3 +- src/IceTranslator.cpp | 10 --- src/IceTranslator.h | 7 -- tests_lit/llvm2ice_tests/elf_container.ll | 3 +- 17 files changed, 219 insertions(+), 172 deletions(-) diff --git a/src/IceCfgNode.cpp b/src/IceCfgNode.cpp index dec40e4d0..aeb54ffd9 100644 --- a/src/IceCfgNode.cpp +++ b/src/IceCfgNode.cpp @@ -1256,7 +1256,10 @@ void CfgNode::profileExecutionCount(VariableDeclaration *Var) { 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 2db7abcda..7619b179b 100644 --- a/src/IceCompiler.cpp +++ b/src/IceCompiler.cpp @@ -141,21 +141,28 @@ void Compiler::run(const Ice::ClFlagsExtra &ExtraFlags, GlobalContext &Ctx, } Ctx.waitForWorkerThreads(); - Translator->transferErrorCode(); - Translator->emitConstants(); - - if (Ctx.getFlags().getOutFileType() == FT_Elf) { - TimerMarker T1(Ice::TimerStack::TT_emit, &Ctx); - Ctx.getObjectWriter()->setUndefinedSyms(Ctx.getConstantExternSyms()); - Ctx.getObjectWriter()->writeNonUserSections(); + 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().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 edb46fae0..44f4adb37 100644 --- a/src/IceELFObjectWriter.cpp +++ b/src/IceELFObjectWriter.cpp @@ -285,7 +285,8 @@ void partitionGlobalsBySection(const VariableDeclarationList &Vars, } // 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 @@ void ELFObjectWriter::writeDataSection(const VariableDeclarationList &Vars, Ctx.getFlags().getTranslateOnly()); size_t I = 0; for (auto &SectionList : VarsBySection) { - writeDataOfType(static_cast(I++), SectionList, RelocationKind); + writeDataOfType(static_cast(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 @@ void ELFObjectWriter::writeDataOfType(SectionType ST, // 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(SectionName, SHT_PROGBITS, ShFlags, ShAddralign, ShEntsize); @@ -329,8 +338,7 @@ void ELFObjectWriter::writeDataOfType(SectionType ST, break; } case Data: { - SectionName = ".data"; - assert(DataSections.empty()); + const IceString SectionName = MangleSectionName(".data", SectionSuffix); const Elf64_Xword ShFlags = SHF_ALLOC | SHF_WRITE; Section = createSection(SectionName, SHT_PROGBITS, ShFlags, ShAddralign, ShEntsize); @@ -341,8 +349,7 @@ void ELFObjectWriter::writeDataOfType(SectionType ST, break; } case BSS: { - SectionName = ".bss"; - assert(BSSSections.empty()); + const IceString SectionName = MangleSectionName(".bss", SectionSuffix); const Elf64_Xword ShFlags = SHF_ALLOC | SHF_WRITE; Section = createSection(SectionName, SHT_NOBITS, ShFlags, ShAddralign, ShEntsize); @@ -383,9 +390,8 @@ void ELFObjectWriter::writeDataOfType(SectionType ST, for (VariableDeclaration::Initializer *Init : Var->getInitializers()) { switch (Init->getKind()) { case VariableDeclaration::Initializer::DataInitializerKind: { - const auto Data = - llvm::cast(Init) - ->getContents(); + const auto Data = llvm::cast( + Init)->getContents(); Section->appendData(Str, llvm::StringRef(Data.data(), Data.size())); break; } diff --git a/src/IceELFObjectWriter.h b/src/IceELFObjectWriter.h index 110384556..a9127ac91 100644 --- a/src/IceELFObjectWriter.h +++ b/src/IceELFObjectWriter.h @@ -30,11 +30,12 @@ namespace Ice { // 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 @@ namespace Ice { // 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 @@ public: // 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 @@ private: // 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 8ed4d7683..b23e75b83 100644 --- a/src/IceGlobalContext.cpp +++ b/src/IceGlobalContext.cpp @@ -222,7 +222,10 @@ GlobalContext::GlobalContext(Ostream *OsDump, Ostream *OsEmit, Ostream *OsError, 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 @@ GlobalContext::GlobalContext(Ostream *OsDump, Ostream *OsEmit, Ostream *OsError, 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 @@ void GlobalContext::translateFunctions() { 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 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 @@ void resizePending(std::vector &Pending, uint32_t Index) { Pending.resize(Index + 1); } -void addAllIfNotNull(std::unique_ptr 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::emitFileHeader() { } } +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 @@ void GlobalContext::emitItems() { // 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 GlobalInits( - new VariableDeclarationList()); std::vector Pending; uint32_t DesiredSequenceNumber = getFirstSequenceNumber(); while (true) { @@ -444,10 +429,12 @@ void GlobalContext::emitItems() { 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 Asm = Item->getAsm(); Asm->alignFunction(); IceString MangledName = mangleName(Asm->getFunctionName()); @@ -469,8 +456,8 @@ void GlobalContext::emitItems() { 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 Func = Item->getCfg(); @@ -485,8 +472,9 @@ void GlobalContext::emitItems() { } } - 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 763a75b48..ff8ff25ed 100644 --- a/src/IceGlobalContext.h +++ b/src/IceGlobalContext.h @@ -303,6 +303,8 @@ public: // Emit file header for output file. void emitFileHeader(); + void lowerConstants(); + void emitQueueBlockingPush(EmitterWorkItem *Item); EmitterWorkItem *emitQueueBlockingPop(); void emitQueueNotifyEnd() { EmitQ.notifyEnd(); } @@ -380,6 +382,13 @@ public: // 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 @@ private: Intrinsics IntrinsicsInfo; const ClFlags &Flags; RandomNumberGenerator RNG; // TODO(stichnot): Move into Cfg. + // TODO(jpp): move to EmitterContext. std::unique_ptr ObjectWriter; BoundedProducerConsumerQueue OptQ; BoundedProducerConsumerQueue 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 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 ProfileBlockInfoVarDecl; LockedPtr> getAllocator() { return LockedPtr>(&Allocator, &AllocLock); @@ -449,6 +471,19 @@ private: return LockedPtr(&Timers, &TimerLock); } + void accumulateGlobals(std::unique_ptr 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 AllThreadContexts; llvm::SmallVector TranslationThreads; llvm::SmallVector EmitterThreads; diff --git a/src/IceTargetLowering.cpp b/src/IceTargetLowering.cpp index 4bb035a80..52017ea09 100644 --- a/src/IceTargetLowering.cpp +++ b/src/IceTargetLowering.cpp @@ -446,40 +446,63 @@ TargetDataLowering::createLowering(GlobalContext *Ctx) { 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 @@ void TargetDataLowering::emitGlobal(const VariableDeclaration &Var) { 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(Init) - ->getContents(); + const auto &Data = llvm::cast( + Init)->getContents(); for (SizeT i = 0; i < Init->getNumBytes(); ++i) { Str << "\t.byte\t" << (((unsigned)Data[i]) & 0xff) << "\n"; } @@ -504,7 +527,7 @@ void TargetDataLowering::emitGlobal(const VariableDeclaration &Var) { Str << "\t.zero\t" << Init->getNumBytes() << "\n"; break; case VariableDeclaration::Initializer::RelocInitializerKind: { - const auto Reloc = + const auto *Reloc = llvm::cast(Init); Str << "\t" << getEmit32Directive() << "\t"; Str << Reloc->getDeclaration()->mangleName(Ctx); @@ -519,12 +542,13 @@ void TargetDataLowering::emitGlobal(const VariableDeclaration &Var) { } } } - } 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 4d9598a24..fa6f5b7e4 100644 --- a/src/IceTargetLowering.h +++ b/src/IceTargetLowering.h @@ -380,16 +380,18 @@ public: static std::unique_ptr createLowering(GlobalContext *Ctx); virtual ~TargetDataLowering(); - virtual void lowerGlobals(std::unique_ptr 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 2d3c5c1f5..9bb2386b3 100644 --- a/src/IceTargetLoweringARM32.cpp +++ b/src/IceTargetLoweringARM32.cpp @@ -2207,20 +2207,20 @@ void TargetARM32::emit(const ConstantUndef *) const { TargetDataARM32::TargetDataARM32(GlobalContext *Ctx) : TargetDataLowering(Ctx) {} -void TargetDataARM32::lowerGlobals( - std::unique_ptr 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 98dd20e3e..1fa3ce242 100644 --- a/src/IceTargetLoweringARM32.h +++ b/src/IceTargetLoweringARM32.h @@ -323,7 +323,8 @@ public: return std::unique_ptr(new TargetDataARM32(Ctx)); } - void lowerGlobals(std::unique_ptr 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 ee2300eb8..3655cb773 100644 --- a/src/IceTargetLoweringMIPS32.cpp +++ b/src/IceTargetLoweringMIPS32.cpp @@ -671,20 +671,20 @@ void ConstantUndef::emit(GlobalContext *) const { TargetDataMIPS32::TargetDataMIPS32(GlobalContext *Ctx) : TargetDataLowering(Ctx) {} -void TargetDataMIPS32::lowerGlobals( - std::unique_ptr 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 9204833a7..cb89ffc24 100644 --- a/src/IceTargetLoweringMIPS32.h +++ b/src/IceTargetLoweringMIPS32.h @@ -137,7 +137,8 @@ public: return std::unique_ptr(new TargetDataMIPS32(Ctx)); } - void lowerGlobals(std::unique_ptr 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 b68657952..c57374b7e 100644 --- a/src/IceTargetLoweringX8632.cpp +++ b/src/IceTargetLoweringX8632.cpp @@ -3296,11 +3296,10 @@ void TargetX8632::lowerIntrinsicCall(const InstIntrinsicCall *Instr) { Func->setError("Unexpected memory ordering for AtomicRMW"); return; } - lowerAtomicRMW( - Instr->getDest(), - static_cast( - llvm::cast(Instr->getArg(0))->getValue()), - Instr->getArg(1), Instr->getArg(2)); + lowerAtomicRMW(Instr->getDest(), + static_cast(llvm::cast( + Instr->getArg(0))->getValue()), + Instr->getArg(1), Instr->getArg(2)); return; case Intrinsics::AtomicStore: { if (!Intrinsics::isMemoryOrderValid( @@ -5021,20 +5020,20 @@ void TargetX8632::emit(const ConstantUndef *) const { TargetDataX8632::TargetDataX8632(GlobalContext *Ctx) : TargetDataLowering(Ctx) {} -void TargetDataX8632::lowerGlobals( - std::unique_ptr 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 0b46e1bde..b9a9e2bf4 100644 --- a/src/IceTargetLoweringX8632.h +++ b/src/IceTargetLoweringX8632.h @@ -587,7 +587,8 @@ public: return std::unique_ptr(new TargetDataX8632(Ctx)); } - void lowerGlobals(std::unique_ptr 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 c78bbcb02..aba71e58f 100644 --- a/src/IceTranslator.cpp +++ b/src/IceTranslator.cpp @@ -57,16 +57,6 @@ void Translator::translateFcn(std::unique_ptr Func) { 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 VariableDeclarations) { EmitterWorkItem *Item = new EmitterWorkItem(getNextSequenceNumber(), diff --git a/src/IceTranslator.h b/src/IceTranslator.h index adddc32c8..0f7f9d7cd 100644 --- a/src/IceTranslator.h +++ b/src/IceTranslator.h @@ -48,13 +48,6 @@ public: /// Takes ownership of Func. void translateFcn(std::unique_ptr 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 diff --git a/tests_lit/llvm2ice_tests/elf_container.ll b/tests_lit/llvm2ice_tests/elf_container.ll index 4c663cf5a..f95ed2a8c 100644 --- a/tests_lit/llvm2ice_tests/elf_container.ll +++ b/tests_lit/llvm2ice_tests/elf_container.ll @@ -270,8 +270,7 @@ define void @_start(i32) { ; CHECK: ] ; CHECK: Address: 0x0 ; CHECK: Offset: 0x{{[1-9A-F][0-9A-F]*}} -; Size is 56 instead of 48 due to __Sz_block_profile_info . -; CHECK: Size: 56 +; CHECK: Size: 48 ; CHECK: Link: 0 ; CHECK: Info: 0 ; CHECK: AddressAlignment: 32 -- 2.11.0