diff --git a/include/llvm/MC/MCAsmInfo.h b/include/llvm/MC/MCAsmInfo.h index 73709364fef..97aad71fd95 100644 --- a/include/llvm/MC/MCAsmInfo.h +++ b/include/llvm/MC/MCAsmInfo.h @@ -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; } diff --git a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index 2aae37696ba..d6d45104098 100644 --- a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -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; diff --git a/lib/MC/MCAsmInfo.cpp b/lib/MC/MCAsmInfo.cpp index 11e368c81a3..7ea0f3b85a5 100644 --- a/lib/MC/MCAsmInfo.cpp +++ b/lib/MC/MCAsmInfo.cpp @@ -69,7 +69,7 @@ MCAsmInfo::MCAsmInfo() { HasSetDirective = true; HasAggressiveSymbolFolding = true; COMMDirectiveAlignmentIsInBytes = true; - LCOMMDirectiveSupportsAlignment = false; + LCOMMDirectiveAlignmentType = LCOMM::NoAlignment; HasDotTypeDotSizeDirective = true; HasSingleParameterDotFile = true; HasNoDeadStrip = false; diff --git a/lib/MC/MCAsmInfoCOFF.cpp b/lib/MC/MCAsmInfoCOFF.cpp index 4b426f8a731..fd79193073d 100644 --- a/lib/MC/MCAsmInfoCOFF.cpp +++ b/lib/MC/MCAsmInfoCOFF.cpp @@ -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 diff --git a/lib/MC/MCAsmInfoDarwin.cpp b/lib/MC/MCAsmInfoDarwin.cpp index 99520d4bf9a..a0e3ebad5e2 100644 --- a/lib/MC/MCAsmInfoDarwin.cpp +++ b/lib/MC/MCAsmInfoDarwin.cpp @@ -32,7 +32,7 @@ MCAsmInfoDarwin::MCAsmInfoDarwin() { AlignmentIsInBytes = false; COMMDirectiveAlignmentIsInBytes = false; - LCOMMDirectiveSupportsAlignment = true; + LCOMMDirectiveAlignmentType = LCOMM::Log2Alignment; InlineAsmStart = " InlineAsm Start"; InlineAsmEnd = " InlineAsm End"; diff --git a/lib/MC/MCAsmStreamer.cpp b/lib/MC/MCAsmStreamer.cpp index 804e38ead08..b0bc2900ecb 100644 --- a/lib/MC/MCAsmStreamer.cpp +++ b/lib/MC/MCAsmStreamer.cpp @@ -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(); diff --git a/lib/MC/MCParser/AsmParser.cpp b/lib/MC/MCParser/AsmParser.cpp index 271fee02ada..55ef01c7961 100644 --- a/lib/MC/MCParser/AsmParser.cpp +++ b/lib/MC/MCParser/AsmParser.cpp @@ -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); diff --git a/lib/Target/Hexagon/MCTargetDesc/HexagonMCAsmInfo.cpp b/lib/Target/Hexagon/MCTargetDesc/HexagonMCAsmInfo.cpp index ec6b721f127..86f75d1c2d7 100644 --- a/lib/Target/Hexagon/MCTargetDesc/HexagonMCAsmInfo.cpp +++ b/lib/Target/Hexagon/MCTargetDesc/HexagonMCAsmInfo.cpp @@ -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 index 00000000000..74da557fb5c --- /dev/null +++ b/test/MC/COFF/comm.ll @@ -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