aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Majnemer <david.majnemer@gmail.com>2014-09-21 09:18:07 +0000
committerDavid Majnemer <david.majnemer@gmail.com>2014-09-21 09:18:07 +0000
commit48227a37592f31bd8c9410f36fb0ee5246a2e2bf (patch)
treea3f7ea909628af70d28eaeb14f98c4ef6fe9e0e6
parent8ff73c01704991fdbe0b23a67925defdcb988d64 (diff)
downloadllvm-48227a37592f31bd8c9410f36fb0ee5246a2e2bf.zip
llvm-48227a37592f31bd8c9410f36fb0ee5246a2e2bf.tar.gz
llvm-48227a37592f31bd8c9410f36fb0ee5246a2e2bf.tar.bz2
MC: Support aligned COMMON symbols for COFF
link.exe: Fuzz testing has shown that COMMON symbols with size > 32 will always have an alignment of at least 32 and all symbols with size < 32 will have an alignment of at least the largest power of 2 less than the size of the symbol. binutils: The BFD linker essentially work like the link.exe behavior but with alignment 4 instead of 32. The BFD linker also supports an extension to COFF which adds an -aligncomm argument to the .drectve section which permits specifying a precise alignment for a variable but MC currently doesn't support editing .drectve in this way. With all of this in mind, we decide to play a little trick: we can ensure that the alignment will be respected by bumping the size of the global to it's alignment. llvm-svn: 218201
-rw-r--r--llvm/lib/MC/MCObjectFileInfo.cpp4
-rw-r--r--llvm/lib/MC/WinCOFFStreamer.cpp17
-rw-r--r--llvm/test/MC/COFF/comm.ll4
-rw-r--r--llvm/test/MC/COFF/comm.s14
4 files changed, 31 insertions, 8 deletions
diff --git a/llvm/lib/MC/MCObjectFileInfo.cpp b/llvm/lib/MC/MCObjectFileInfo.cpp
index da707d8..547630e 100644
--- a/llvm/lib/MC/MCObjectFileInfo.cpp
+++ b/llvm/lib/MC/MCObjectFileInfo.cpp
@@ -595,9 +595,7 @@ void MCObjectFileInfo::InitELFMCObjectFileInfo(Triple T) {
void MCObjectFileInfo::InitCOFFMCObjectFileInfo(Triple T) {
bool IsWoA = T.getArch() == Triple::arm || T.getArch() == Triple::thumb;
- // The object file format cannot represent common symbols with explicit
- // alignments.
- CommDirectiveSupportsAlignment = false;
+ CommDirectiveSupportsAlignment = true;
// COFF
BSSSection =
diff --git a/llvm/lib/MC/WinCOFFStreamer.cpp b/llvm/lib/MC/WinCOFFStreamer.cpp
index 1d03e2d7..2829a8f 100644
--- a/llvm/lib/MC/WinCOFFStreamer.cpp
+++ b/llvm/lib/MC/WinCOFFStreamer.cpp
@@ -183,8 +183,21 @@ void MCWinCOFFStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
Symbol->getSection().getVariant() == MCSection::SV_COFF) &&
"Got non-COFF section in the COFF backend!");
- if (ByteAlignment > 32)
- report_fatal_error("alignment is limited to 32-bytes");
+ const Triple &T = getContext().getObjectFileInfo()->getTargetTriple();
+ 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.
+ Size = std::max(Size, static_cast<uint64_t>(ByteAlignment));
AssignSection(Symbol, nullptr);
diff --git a/llvm/test/MC/COFF/comm.ll b/llvm/test/MC/COFF/comm.ll
index 6fe122e..74da557 100644
--- a/llvm/test/MC/COFF/comm.ll
+++ b/llvm/test/MC/COFF/comm.ll
@@ -9,5 +9,5 @@
; CHECK: .lcomm _a,1
; CHECK: .lcomm _b,8,8
; .comm uses log2 alignment
-; CHECK: .comm _c,1
-; CHECK: .comm _d,8
+; CHECK: .comm _c,1,0
+; CHECK: .comm _d,8,3
diff --git a/llvm/test/MC/COFF/comm.s b/llvm/test/MC/COFF/comm.s
index 28d9726..773ebde 100644
--- a/llvm/test/MC/COFF/comm.s
+++ b/llvm/test/MC/COFF/comm.s
@@ -1,7 +1,9 @@
// RUN: llvm-mc -filetype=obj -triple i686-pc-win32 %s | llvm-readobj -t | FileCheck %s
.lcomm _a,4,4
-.comm _b, 4
+.comm _b, 4, 2
+// _c has size 1 but align 32, the value field is the max of size and align.
+.comm _c, 1, 5
// CHECK: Symbol {
@@ -23,3 +25,13 @@
// CHECK-NEXT: StorageClass: External
// CHECK-NEXT: AuxSymbolCount: 0
// CHECK-NEXT: }
+
+// CHECK: Symbol {
+// CHECK: Name: _c
+// CHECK-NEXT: Value: 32
+// CHECK-NEXT: Section: IMAGE_SYM_UNDEFINED (0)
+// CHECK-NEXT: BaseType: Null
+// CHECK-NEXT: ComplexType: Null
+// CHECK-NEXT: StorageClass: External
+// CHECK-NEXT: AuxSymbolCount: 0
+// CHECK-NEXT: }