Move "local commons" to the end of .bss to match the gnu as behavior.
authorRafael Espindola <rafael.espindola@gmail.com>
Wed, 29 Sep 2010 14:52:01 +0000 (14:52 +0000)
committerRafael Espindola <rafael.espindola@gmail.com>
Wed, 29 Sep 2010 14:52:01 +0000 (14:52 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@115037 91177308-0d34-0410-b5e6-96231b3b80d8

lib/MC/MCELFStreamer.cpp
test/MC/ELF/common2.s [new file with mode: 0644]

index 6bf61a194c60ef4345d87dbdf38495a7e28f4b8a..465f9ce79cbd2815d7e3aa9662145e0758b99020 100644 (file)
@@ -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 (file)
index 0000000..a95daa5
--- /dev/null
@@ -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',