diff options
author | Rafael Espindola <rafael.espindola@gmail.com> | 2010-09-29 14:52:01 +0000 |
---|---|---|
committer | Rafael Espindola <rafael.espindola@gmail.com> | 2010-09-29 14:52:01 +0000 |
commit | 9e3922e94975b7b3d98da42f0d20a524f3deed53 (patch) | |
tree | af248424afd746cc0220458930a09c0dfde0a052 | |
parent | 9804db13535d524ed88532d161cf265e72249036 (diff) |
Move "local commons" to the end of .bss to match the gnu as behavior.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@115037 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/MC/MCELFStreamer.cpp | 38 | ||||
-rw-r--r-- | test/MC/ELF/common2.s | 21 |
2 files changed, 50 insertions, 9 deletions
diff --git a/lib/MC/MCELFStreamer.cpp b/lib/MC/MCELFStreamer.cpp index 6bf61a194c..465f9ce79c 100644 --- a/lib/MC/MCELFStreamer.cpp +++ b/lib/MC/MCELFStreamer.cpp @@ -111,6 +111,13 @@ public: virtual void Finish(); private: + struct LocalCommon { + MCSymbolData *SD; + uint64_t Size; + unsigned ByteAlignment; + }; + std::vector<LocalCommon> LocalCommons; + SmallPtrSet<MCSymbol *, 16> BindingExplicitlySet; /// @} void SetSection(StringRef Section, unsigned Type, unsigned Flags, @@ -343,17 +350,10 @@ void MCELFStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, MCSectionELF::SHF_WRITE | MCSectionELF::SHF_ALLOC, SectionKind::getBSS()); - - MCSectionData &SectData = getAssembler().getOrCreateSectionData(*Section); - new MCAlignFragment(ByteAlignment, 0, 1, ByteAlignment, &SectData); - - MCFragment *F = new MCFillFragment(0, 0, Size, &SectData); - SD.setFragment(F); Symbol->setSection(*Section); - // Update the maximum alignment of the section if necessary. - if (ByteAlignment > SectData.getAlignment()) - SectData.setAlignment(ByteAlignment); + struct LocalCommon L = {&SD, Size, ByteAlignment}; + LocalCommons.push_back(L); } else { SD.setCommon(Size, ByteAlignment); } @@ -499,6 +499,26 @@ void MCELFStreamer::EmitInstruction(const MCInst &Inst) { } void MCELFStreamer::Finish() { + for (std::vector<LocalCommon>::const_iterator i = LocalCommons.begin(), + e = LocalCommons.end(); + i != e; ++i) { + MCSymbolData *SD = i->SD; + uint64_t Size = i->Size; + unsigned ByteAlignment = i->ByteAlignment; + const MCSymbol &Symbol = SD->getSymbol(); + const MCSection &Section = Symbol.getSection(); + + MCSectionData &SectData = getAssembler().getOrCreateSectionData(Section); + new MCAlignFragment(ByteAlignment, 0, 1, ByteAlignment, &SectData); + + MCFragment *F = new MCFillFragment(0, 0, Size, &SectData); + SD->setFragment(F); + + // Update the maximum alignment of the section if necessary. + if (ByteAlignment > SectData.getAlignment()) + SectData.setAlignment(ByteAlignment); + } + // FIXME: We create more atoms than it is necessary. Some relocations to // merge sections can be implemented with section address + offset, // figure out which ones and why. diff --git a/test/MC/ELF/common2.s b/test/MC/ELF/common2.s new file mode 100644 index 0000000000..a95daa518f --- /dev/null +++ b/test/MC/ELF/common2.s @@ -0,0 +1,21 @@ +// RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu %s -o - | elf-dump | FileCheck %s + +// Test that the common symbols are placed at the end of .bss. In this example +// it causes .bss to have size 9 instead of 8. + + .local vimvardict + .comm vimvardict,1,8 + .bss + .zero 1 + .align 8 + +// CHECK: (('sh_name', 13) # '.bss' +// CHECK-NEXT: ('sh_type', +// CHECK-NEXT: ('sh_flags' +// CHECK-NEXT: ('sh_addr', +// CHECK-NEXT: ('sh_offset', +// CHECK-NEXT: ('sh_size', 9) +// CHECK-NEXT: ('sh_link', +// CHECK-NEXT: ('sh_info', +// CHECK-NEXT: ('sh_addralign', +// CHECK-NEXT: ('sh_entsize', |