OSDN Git Service

Fix alignment of .comm and .lcomm on mingw32.
authorBenjamin Kramer <benny.kra@googlemail.com>
Fri, 7 Sep 2012 21:08:01 +0000 (21:08 +0000)
committerBenjamin Kramer <benny.kra@googlemail.com>
Fri, 7 Sep 2012 21:08:01 +0000 (21:08 +0000)
For some reason .lcomm uses byte alignment and .comm log2 alignment so we can't
use the same setting for both. Fix this by reintroducing the LCOMM enum.
I verified this against mingw's gcc.

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

include/llvm/MC/MCAsmInfo.h
lib/CodeGen/AsmPrinter/AsmPrinter.cpp
lib/MC/MCAsmInfo.cpp
lib/MC/MCAsmInfoCOFF.cpp
lib/MC/MCAsmInfoDarwin.cpp
lib/MC/MCAsmStreamer.cpp
lib/MC/MCParser/AsmParser.cpp
lib/Target/Hexagon/MCTargetDesc/HexagonMCAsmInfo.cpp
test/MC/COFF/comm.ll [new file with mode: 0644]

index 7370936..97aad71 100644 (file)
@@ -32,6 +32,10 @@ namespace llvm {
     enum ExceptionsType { None, DwarfCFI, SjLj, ARM, Win64 };
   }
 
+  namespace LCOMM {
+    enum LCOMMType { NoAlignment, ByteAlignment, Log2Alignment };
+  }
+
   /// MCAsmInfo - This class is intended to be used as a base class for asm
   /// properties and features specific to the target.
   class MCAsmInfo {
@@ -247,9 +251,9 @@ namespace llvm {
     /// alignment is to be specified in bytes instead of log2(n).
     bool COMMDirectiveAlignmentIsInBytes;    // Defaults to true;
 
-    /// LCOMMDirectiveSupportsAlignment - True if .lcomm supports an optional
-    /// alignment argument on this target.
-    bool LCOMMDirectiveSupportsAlignment;    // Defaults to false.
+    /// LCOMMDirectiveAlignment - Describes if the .lcomm directive for the
+    /// target supports an alignment argument and how it is interpreted.
+    LCOMM::LCOMMType LCOMMDirectiveAlignmentType; // Defaults to NoAlignment.
 
     /// HasDotTypeDotSizeDirective - True if the target has .type and .size
     /// directives, this is true for most ELF targets.
@@ -495,8 +499,8 @@ namespace llvm {
     bool getCOMMDirectiveAlignmentIsInBytes() const {
       return COMMDirectiveAlignmentIsInBytes;
     }
-    bool getLCOMMDirectiveSupportsAlignment() const {
-      return LCOMMDirectiveSupportsAlignment;
+    LCOMM::LCOMMType getLCOMMDirectiveAlignmentType() const {
+      return LCOMMDirectiveAlignmentType;
     }
     bool hasDotTypeDotSizeDirective() const {return HasDotTypeDotSizeDirective;}
     bool hasSingleParameterDotFile() const { return HasSingleParameterDotFile; }
index 2aae376..d6d4510 100644 (file)
@@ -312,7 +312,8 @@ void AsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) {
       return;
     }
 
-    if (Align == 1 || MAI->getLCOMMDirectiveSupportsAlignment()) {
+    if (Align == 1 ||
+        MAI->getLCOMMDirectiveAlignmentType() != LCOMM::NoAlignment) {
       // .lcomm _foo, 42
       OutStreamer.EmitLocalCommonSymbol(GVSym, Size, Align);
       return;
index 11e368c..7ea0f3b 100644 (file)
@@ -69,7 +69,7 @@ MCAsmInfo::MCAsmInfo() {
   HasSetDirective = true;
   HasAggressiveSymbolFolding = true;
   COMMDirectiveAlignmentIsInBytes = true;
-  LCOMMDirectiveSupportsAlignment = false;
+  LCOMMDirectiveAlignmentType = LCOMM::NoAlignment;
   HasDotTypeDotSizeDirective = true;
   HasSingleParameterDotFile = true;
   HasNoDeadStrip = false;
index 4b426f8..fd79193 100644 (file)
@@ -19,8 +19,10 @@ void MCAsmInfoCOFF::anchor() { }
 
 MCAsmInfoCOFF::MCAsmInfoCOFF() {
   GlobalPrefix = "_";
-  COMMDirectiveAlignmentIsInBytes = true;
-  LCOMMDirectiveSupportsAlignment = true;
+  // MingW 4.5 and later support .comm with log2 alignment, but .lcomm uses byte
+  // alignment.
+  COMMDirectiveAlignmentIsInBytes = false;
+  LCOMMDirectiveAlignmentType = LCOMM::ByteAlignment;
   HasDotTypeDotSizeDirective = false;
   HasSingleParameterDotFile = false;
   PrivateGlobalPrefix = "L";  // Prefix for private global symbols
index 99520d4..a0e3eba 100644 (file)
@@ -32,7 +32,7 @@ MCAsmInfoDarwin::MCAsmInfoDarwin() {
 
   AlignmentIsInBytes = false;
   COMMDirectiveAlignmentIsInBytes = false;
-  LCOMMDirectiveSupportsAlignment = true;
+  LCOMMDirectiveAlignmentType = LCOMM::Log2Alignment;
   InlineAsmStart = " InlineAsm Start";
   InlineAsmEnd = " InlineAsm End";
 
index 804e38e..b0bc290 100644 (file)
@@ -519,13 +519,16 @@ void MCAsmStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
                                           unsigned ByteAlign) {
   OS << "\t.lcomm\t" << *Symbol << ',' << Size;
   if (ByteAlign > 1) {
-    assert(MAI.getLCOMMDirectiveSupportsAlignment() &&
-           "alignment not supported on .lcomm!");
-    if (MAI.getCOMMDirectiveAlignmentIsInBytes()) {
+    switch (MAI.getLCOMMDirectiveAlignmentType()) {
+    case LCOMM::NoAlignment:
+      llvm_unreachable("alignment not supported on .lcomm!");
+    case LCOMM::ByteAlignment:
       OS << ',' << ByteAlign;
-    } else {
+      break;
+    case LCOMM::Log2Alignment:
       assert(isPowerOf2_32(ByteAlign) && "alignment must be a power of 2");
       OS << ',' << Log2_32(ByteAlign);
+      break;
     }
   }
   EmitEOL();
index 271fee0..55ef01c 100644 (file)
@@ -2280,11 +2280,13 @@ bool AsmParser::ParseDirectiveComm(bool IsLocal) {
     if (ParseAbsoluteExpression(Pow2Alignment))
       return true;
 
-    if (IsLocal && !Lexer.getMAI().getLCOMMDirectiveSupportsAlignment())
+    LCOMM::LCOMMType LCOMM = Lexer.getMAI().getLCOMMDirectiveAlignmentType();
+    if (IsLocal && LCOMM == LCOMM::NoAlignment)
       return Error(Pow2AlignmentLoc, "alignment not supported on this target");
 
     // If this target takes alignments in bytes (not log) validate and convert.
-    if (Lexer.getMAI().getCOMMDirectiveAlignmentIsInBytes()) {
+    if ((!IsLocal && Lexer.getMAI().getCOMMDirectiveAlignmentIsInBytes()) ||
+        (IsLocal && LCOMM == LCOMM::ByteAlignment)) {
       if (!isPowerOf2_64(Pow2Alignment))
         return Error(Pow2AlignmentLoc, "alignment must be a power of 2");
       Pow2Alignment = Log2_64(Pow2Alignment);
index ec6b721..86f75d1 100644 (file)
@@ -24,7 +24,7 @@ HexagonMCAsmInfo::HexagonMCAsmInfo(const Target &T, StringRef TT) {
   HasLEB128 = true;
 
   PrivateGlobalPrefix = ".L";
-  LCOMMDirectiveSupportsAlignment = true;
+  LCOMMDirectiveAlignmentType = LCOMM::ByteAlignment;
   InlineAsmStart = "# InlineAsm Start";
   InlineAsmEnd = "# InlineAsm End";
   ZeroDirective = "\t.space\t";
diff --git a/test/MC/COFF/comm.ll b/test/MC/COFF/comm.ll
new file mode 100644 (file)
index 0000000..74da557
--- /dev/null
@@ -0,0 +1,13 @@
+; RUN: llc -mtriple i386-pc-mingw32 < %s | FileCheck %s
+
+@a = internal global i8 0, align 1
+@b = internal global double 0.000000e+00, align 8
+@c = common global i8 0, align 1
+@d = common global double 0.000000e+00, align 8
+
+; .lcomm uses byte alignment
+; CHECK: .lcomm        _a,1
+; CHECK: .lcomm        _b,8,8
+; .comm uses log2 alignment
+; CHECK: .comm _c,1,0
+; CHECK: .comm _d,8,3