]> granicus.if.org Git - llvm/commitdiff
MC: add support for -aligncomm GNU extension
authorSaleem Abdulrasool <compnerd@compnerd.org>
Tue, 7 Oct 2014 19:37:57 +0000 (19:37 +0000)
committerSaleem Abdulrasool <compnerd@compnerd.org>
Tue, 7 Oct 2014 19:37:57 +0000 (19:37 +0000)
The GNU linker supports an -aligncomm directive that allows for power-of-2
alignment of common data.  Add support to emit this directive.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@219229 91177308-0d34-0410-b5e6-96231b3b80d8

lib/MC/WinCOFFStreamer.cpp
test/MC/COFF/comm-align.s [new file with mode: 0644]

index 2829a8ff0b5eb50d9b9afc14e5378b806c33368b..9bae53706a05fa17c68449c98455ca85e560c742 100644 (file)
@@ -29,6 +29,7 @@
 #include "llvm/Support/COFF.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/MathExtras.h"
 #include "llvm/Support/TargetRegistry.h"
 #include "llvm/Support/raw_ostream.h"
 
@@ -184,16 +185,10 @@ void MCWinCOFFStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
          "Got non-COFF section in the COFF backend!");
 
   const Triple &T = getContext().getObjectFileInfo()->getTargetTriple();
-  if (T.isKnownWindowsMSVCEnvironment()) {
+  if (T.isKnownWindowsMSVCEnvironment())
     if (ByteAlignment > 32)
       report_fatal_error("alignment is limited to 32-bytes");
-  } else {
-    // The bfd linker from binutils only supports alignments less than 4 bytes
-    // without inserting -aligncomm arguments into the .drectve section.
-    // TODO: Support inserting -aligncomm into the .drectve section.
-    if (ByteAlignment > 4)
-      report_fatal_error("alignment is limited to 4-bytes");
-  }
+
   // Round size up to alignment so that we will honor the alignment request.
   // TODO: We don't need to do this if we are targeting the bfd linker once we
   // add support for adding -aligncomm into the .drectve section.
@@ -204,6 +199,21 @@ void MCWinCOFFStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
   MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol);
   SD.setExternal(true);
   SD.setCommon(Size, ByteAlignment);
+
+  if (!T.isKnownWindowsMSVCEnvironment() && ByteAlignment > 1) {
+    SmallString<128> Directive;
+    raw_svector_ostream OS(Directive);
+    const MCObjectFileInfo *MFI = getContext().getObjectFileInfo();
+
+    OS << " -aligncomm:\"" << Symbol->getName() << "\","
+       << Log2_32_Ceil(ByteAlignment);
+    OS.flush();
+
+    PushSection();
+    SwitchSection(MFI->getDrectveSection());
+    EmitBytes(Directive);
+    PopSection();
+  }
 }
 
 void MCWinCOFFStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
diff --git a/test/MC/COFF/comm-align.s b/test/MC/COFF/comm-align.s
new file mode 100644 (file)
index 0000000..e658c56
--- /dev/null
@@ -0,0 +1,50 @@
+# RUN: llvm-mc -triple i686-windows-gnu -filetype obj -o - %s \
+# RUN:    | llvm-readobj -coff-directives -symbols | FileCheck %s
+
+# NOTE: this test checks multiple things:
+# - that -aligncomm is not emitted for 1-byte alignment
+# - that -aligncomm is emitted for the various alignments (greater than 1)
+# - that the alignment is represented as a log_2 of the alignment
+# - that the section switching occurs correctly
+# - that functions after the switch also are emitted into the correct section
+
+       .text
+
+       .def _a
+               .scl 3
+               .type 32
+       .endef
+_a:
+       ret
+
+       .data
+
+       .comm _s_1,4,0                  # @s_1
+       .comm _s_2,4,1                  # @s_2
+       .comm _s_4,4,2                  # @s_3
+       .comm _s_8,4,3                  # @s_4
+
+       .text
+
+       .def _b
+               .scl 3
+               .type 32
+       .endef
+_b:
+       ret
+
+# CHECK-NOT: -aligncomm:"_s_1",0
+
+# CHECK: Symbols [
+# CHECK:   Symbol {
+# CHECK:     Name: _a
+# CHECK:     Section: .text (1)
+# CHECK:   }
+# CHECK:   Symbol {
+# CHECK:     Name: _b
+# CHECK:     Section: .text (1)
+# CHECK:   }
+# CHECK: ]
+
+# CHECK: Directive(s): -aligncomm:"_s_2",1 -aligncomm:"_s_4",2 -aligncomm:"_s_8",3
+