diff options
author | Benjamin Kramer <benny.kra@googlemail.com> | 2012-09-07 17:25:13 +0000 |
---|---|---|
committer | Benjamin Kramer <benny.kra@googlemail.com> | 2012-09-07 17:25:13 +0000 |
commit | 39646d96e76aea5d20bffb386233a0dbb5932a21 (patch) | |
tree | 5de73a0fc45310a16dab5a01751ba4302b33a75a | |
parent | 8e70b5506ec0d7a6c2740bc89cd1b8f12a78b24f (diff) |
MC: Overhaul handling of .lcomm
- Darwin lied about not supporting .lcomm and turned it into zerofill in the
asm parser. Push the zerofill-conversion down into macho-specific code.
- This makes the tri-state LCOMMType enum superfluous, there are no targets
without .lcomm.
- Do proper error reporting when trying to use .lcomm with alignment on a target
that doesn't support it.
- .comm and .lcomm alignment was parsed in bytes on COFF, should be power of 2.
- Fixes PR13755 (.lcomm crashes on ELF).
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@163395 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/llvm/MC/MCAsmInfo.h | 22 | ||||
-rw-r--r-- | lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 3 | ||||
-rw-r--r-- | lib/MC/MCAsmInfo.cpp | 2 | ||||
-rw-r--r-- | lib/MC/MCAsmInfoCOFF.cpp | 2 | ||||
-rw-r--r-- | lib/MC/MCAsmInfoDarwin.cpp | 1 | ||||
-rw-r--r-- | lib/MC/MCAsmStreamer.cpp | 13 | ||||
-rw-r--r-- | lib/MC/MCMachOStreamer.cpp | 13 | ||||
-rw-r--r-- | lib/MC/MCParser/AsmParser.cpp | 11 | ||||
-rw-r--r-- | lib/Target/ARM/MCTargetDesc/ARMMCAsmInfo.cpp | 1 | ||||
-rw-r--r-- | lib/Target/Hexagon/MCTargetDesc/HexagonMCAsmInfo.cpp | 2 | ||||
-rw-r--r-- | lib/Target/PowerPC/MCTargetDesc/PPCMCAsmInfo.cpp | 1 | ||||
-rw-r--r-- | test/MC/AsmParser/directive_lcomm.s | 11 | ||||
-rw-r--r-- | test/MC/AsmParser/labels.s | 2 | ||||
-rw-r--r-- | test/MC/ELF/lcomm.s | 21 |
14 files changed, 67 insertions, 38 deletions
diff --git a/include/llvm/MC/MCAsmInfo.h b/include/llvm/MC/MCAsmInfo.h index 9f5230b9c8..73709364fe 100644 --- a/include/llvm/MC/MCAsmInfo.h +++ b/include/llvm/MC/MCAsmInfo.h @@ -32,10 +32,6 @@ namespace llvm { enum ExceptionsType { None, DwarfCFI, SjLj, ARM, Win64 }; } - namespace LCOMM { - enum LCOMMType { None, NoAlignment, ByteAlignment }; - } - /// MCAsmInfo - This class is intended to be used as a base class for asm /// properties and features specific to the target. class MCAsmInfo { @@ -247,14 +243,14 @@ namespace llvm { /// .long a - b bool HasAggressiveSymbolFolding; // Defaults to true. - /// LCOMMDirectiveType - Describes if the target supports the .lcomm - /// directive and whether it has an alignment parameter. - LCOMM::LCOMMType LCOMMDirectiveType; // Defaults to LCOMM::None. - - /// COMMDirectiveAlignmentIsInBytes - True is COMMDirective's optional + /// COMMDirectiveAlignmentIsInBytes - True is .comm's and .lcomms optional /// 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. + /// HasDotTypeDotSizeDirective - True if the target has .type and .size /// directives, this is true for most ELF targets. bool HasDotTypeDotSizeDirective; // Defaults to true. @@ -496,13 +492,13 @@ namespace llvm { bool hasAggressiveSymbolFolding() const { return HasAggressiveSymbolFolding; } - LCOMM::LCOMMType getLCOMMDirectiveType() const { - return LCOMMDirectiveType; - } - bool hasDotTypeDotSizeDirective() const {return HasDotTypeDotSizeDirective;} bool getCOMMDirectiveAlignmentIsInBytes() const { return COMMDirectiveAlignmentIsInBytes; } + bool getLCOMMDirectiveSupportsAlignment() const { + return LCOMMDirectiveSupportsAlignment; + } + bool hasDotTypeDotSizeDirective() const {return HasDotTypeDotSizeDirective;} bool hasSingleParameterDotFile() const { return HasSingleParameterDotFile; } bool hasNoDeadStrip() const { return HasNoDeadStrip; } bool hasSymbolResolver() const { return HasSymbolResolver; } diff --git a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index aa5d140e9f..80017c514d 100644 --- a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -312,8 +312,7 @@ void AsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) { return; } - if (MAI->getLCOMMDirectiveType() != LCOMM::None && - (MAI->getLCOMMDirectiveType() != LCOMM::NoAlignment || Align == 1)) { + if (Align == 1 || MAI->getLCOMMDirectiveSupportsAlignment()) { // .lcomm _foo, 42 OutStreamer.EmitLocalCommonSymbol(GVSym, Size, Align); return; diff --git a/lib/MC/MCAsmInfo.cpp b/lib/MC/MCAsmInfo.cpp index 8da2e0e583..11e368c81a 100644 --- a/lib/MC/MCAsmInfo.cpp +++ b/lib/MC/MCAsmInfo.cpp @@ -68,8 +68,8 @@ MCAsmInfo::MCAsmInfo() { GlobalDirective = "\t.globl\t"; HasSetDirective = true; HasAggressiveSymbolFolding = true; - LCOMMDirectiveType = LCOMM::None; COMMDirectiveAlignmentIsInBytes = true; + LCOMMDirectiveSupportsAlignment = false; HasDotTypeDotSizeDirective = true; HasSingleParameterDotFile = true; HasNoDeadStrip = false; diff --git a/lib/MC/MCAsmInfoCOFF.cpp b/lib/MC/MCAsmInfoCOFF.cpp index 678e75af5d..2637be7978 100644 --- a/lib/MC/MCAsmInfoCOFF.cpp +++ b/lib/MC/MCAsmInfoCOFF.cpp @@ -20,7 +20,7 @@ void MCAsmInfoCOFF::anchor() { } MCAsmInfoCOFF::MCAsmInfoCOFF() { GlobalPrefix = "_"; COMMDirectiveAlignmentIsInBytes = false; - LCOMMDirectiveType = LCOMM::ByteAlignment; + LCOMMDirectiveSupportsAlignment = true; HasDotTypeDotSizeDirective = false; HasSingleParameterDotFile = false; PrivateGlobalPrefix = "L"; // Prefix for private global symbols diff --git a/lib/MC/MCAsmInfoDarwin.cpp b/lib/MC/MCAsmInfoDarwin.cpp index 8e0ac23efc..99520d4bf9 100644 --- a/lib/MC/MCAsmInfoDarwin.cpp +++ b/lib/MC/MCAsmInfoDarwin.cpp @@ -32,6 +32,7 @@ MCAsmInfoDarwin::MCAsmInfoDarwin() { AlignmentIsInBytes = false; COMMDirectiveAlignmentIsInBytes = false; + LCOMMDirectiveSupportsAlignment = true; InlineAsmStart = " InlineAsm Start"; InlineAsmEnd = " InlineAsm End"; diff --git a/lib/MC/MCAsmStreamer.cpp b/lib/MC/MCAsmStreamer.cpp index 394f049ca4..804e38ead0 100644 --- a/lib/MC/MCAsmStreamer.cpp +++ b/lib/MC/MCAsmStreamer.cpp @@ -517,13 +517,16 @@ void MCAsmStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, /// @param Size - The size of the common symbol. void MCAsmStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, unsigned ByteAlign) { - assert(MAI.getLCOMMDirectiveType() != LCOMM::None && - "Doesn't have .lcomm, can't emit it!"); OS << "\t.lcomm\t" << *Symbol << ',' << Size; if (ByteAlign > 1) { - assert(MAI.getLCOMMDirectiveType() == LCOMM::ByteAlignment && - "Alignment not supported on .lcomm!"); - OS << ',' << ByteAlign; + assert(MAI.getLCOMMDirectiveSupportsAlignment() && + "alignment not supported on .lcomm!"); + if (MAI.getCOMMDirectiveAlignmentIsInBytes()) { + OS << ',' << ByteAlign; + } else { + assert(isPowerOf2_32(ByteAlign) && "alignment must be a power of 2"); + OS << ',' << Log2_32(ByteAlign); + } } EmitEOL(); } diff --git a/lib/MC/MCMachOStreamer.cpp b/lib/MC/MCMachOStreamer.cpp index b75fe2c3a7..74f6dc62e1 100644 --- a/lib/MC/MCMachOStreamer.cpp +++ b/lib/MC/MCMachOStreamer.cpp @@ -70,9 +70,7 @@ public: llvm_unreachable("macho doesn't support this directive"); } virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, - unsigned ByteAlignment) { - llvm_unreachable("macho doesn't support this directive"); - } + unsigned ByteAlignment); virtual void EmitZerofill(const MCSection *Section, MCSymbol *Symbol = 0, uint64_t Size = 0, unsigned ByteAlignment = 0); virtual void EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol, @@ -325,6 +323,15 @@ void MCMachOStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, SD.setCommon(Size, ByteAlignment); } +void MCMachOStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment) { + // '.lcomm' is equivalent to '.zerofill'. + return EmitZerofill(getContext().getMachOSection("__DATA", "__bss", + MCSectionMachO::S_ZEROFILL, + 0, SectionKind::getBSS()), + Symbol, Size, ByteAlignment); +} + void MCMachOStreamer::EmitZerofill(const MCSection *Section, MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment) { MCSectionData &SectData = getAssembler().getOrCreateSectionData(*Section); diff --git a/lib/MC/MCParser/AsmParser.cpp b/lib/MC/MCParser/AsmParser.cpp index d60a270190..271fee02ad 100644 --- a/lib/MC/MCParser/AsmParser.cpp +++ b/lib/MC/MCParser/AsmParser.cpp @@ -2280,8 +2280,11 @@ bool AsmParser::ParseDirectiveComm(bool IsLocal) { if (ParseAbsoluteExpression(Pow2Alignment)) return true; + if (IsLocal && !Lexer.getMAI().getLCOMMDirectiveSupportsAlignment()) + return Error(Pow2AlignmentLoc, "alignment not supported on this target"); + // If this target takes alignments in bytes (not log) validate and convert. - if (Lexer.getMAI().getAlignmentIsInBytes()) { + if (Lexer.getMAI().getCOMMDirectiveAlignmentIsInBytes()) { if (!isPowerOf2_64(Pow2Alignment)) return Error(Pow2AlignmentLoc, "alignment must be a power of 2"); Pow2Alignment = Log2_64(Pow2Alignment); @@ -2309,13 +2312,9 @@ bool AsmParser::ParseDirectiveComm(bool IsLocal) { if (!Sym->isUndefined()) return Error(IDLoc, "invalid symbol redefinition"); - // '.lcomm' is equivalent to '.zerofill'. // Create the Symbol as a common or local common with Size and Pow2Alignment if (IsLocal) { - getStreamer().EmitZerofill(Ctx.getMachOSection( - "__DATA", "__bss", MCSectionMachO::S_ZEROFILL, - 0, SectionKind::getBSS()), - Sym, Size, 1 << Pow2Alignment); + getStreamer().EmitLocalCommonSymbol(Sym, Size, 1 << Pow2Alignment); return false; } diff --git a/lib/Target/ARM/MCTargetDesc/ARMMCAsmInfo.cpp b/lib/Target/ARM/MCTargetDesc/ARMMCAsmInfo.cpp index d32805e522..c1aab9c72c 100644 --- a/lib/Target/ARM/MCTargetDesc/ARMMCAsmInfo.cpp +++ b/lib/Target/ARM/MCTargetDesc/ARMMCAsmInfo.cpp @@ -50,7 +50,6 @@ ARMELFMCAsmInfo::ARMELFMCAsmInfo() { Code32Directive = ".code\t32"; WeakRefDirective = "\t.weak\t"; - LCOMMDirectiveType = LCOMM::NoAlignment; HasLEB128 = true; SupportsDebugInformation = true; diff --git a/lib/Target/Hexagon/MCTargetDesc/HexagonMCAsmInfo.cpp b/lib/Target/Hexagon/MCTargetDesc/HexagonMCAsmInfo.cpp index d6e6c36af5..ec6b721f12 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"; - LCOMMDirectiveType = LCOMM::ByteAlignment; + LCOMMDirectiveSupportsAlignment = true; InlineAsmStart = "# InlineAsm Start"; InlineAsmEnd = "# InlineAsm End"; ZeroDirective = "\t.space\t"; diff --git a/lib/Target/PowerPC/MCTargetDesc/PPCMCAsmInfo.cpp b/lib/Target/PowerPC/MCTargetDesc/PPCMCAsmInfo.cpp index 245b4578bf..b9ea8b5562 100644 --- a/lib/Target/PowerPC/MCTargetDesc/PPCMCAsmInfo.cpp +++ b/lib/Target/PowerPC/MCTargetDesc/PPCMCAsmInfo.cpp @@ -64,7 +64,6 @@ PPCLinuxMCAsmInfo::PPCLinuxMCAsmInfo(bool is64Bit) { ZeroDirective = "\t.space\t"; Data64bitsDirective = is64Bit ? "\t.quad\t" : 0; - LCOMMDirectiveType = LCOMM::NoAlignment; AssemblerDialect = 0; // Old-Style mnemonics. } diff --git a/test/MC/AsmParser/directive_lcomm.s b/test/MC/AsmParser/directive_lcomm.s index 0a0add513f..37a350c82e 100644 --- a/test/MC/AsmParser/directive_lcomm.s +++ b/test/MC/AsmParser/directive_lcomm.s @@ -1,9 +1,14 @@ # RUN: llvm-mc -triple i386-apple-darwin10 %s | FileCheck %s +# RUN: llvm-mc -triple i386-pc-mingw32 %s | FileCheck %s +# RUN: not llvm-mc -triple i386-linux-gnu %s 2>&1 | FileCheck %s -check-prefix=ERROR # CHECK: TEST0: -# CHECK: .zerofill __DATA,__bss,a,7,4 -# CHECK: .zerofill __DATA,__bss,b,8 -# CHECK: .zerofill __DATA,__bss,c,0 +# CHECK: .lcomm a,7,4 +# CHECK: .lcomm b,8 +# CHECK: .lcomm c,0 + +# ELF doesn't like alignment on .lcomm. +# ERROR: alignment not supported on this target TEST0: .lcomm a, 8-1, 4 .lcomm b,8 diff --git a/test/MC/AsmParser/labels.s b/test/MC/AsmParser/labels.s index 56091755d9..6a9870b655 100644 --- a/test/MC/AsmParser/labels.s +++ b/test/MC/AsmParser/labels.s @@ -41,7 +41,7 @@ foo: // CHECK: .comm "a 6",1 .comm "a 6", 1 -// CHECK: .zerofill __DATA,__bss,"a 7",1,0 +// CHECK: .lcomm "a 7",1 .lcomm "a 7", 1 // FIXME: We don't bother to support .lsym. diff --git a/test/MC/ELF/lcomm.s b/test/MC/ELF/lcomm.s new file mode 100644 index 0000000000..ae8d0baa33 --- /dev/null +++ b/test/MC/ELF/lcomm.s @@ -0,0 +1,21 @@ +// RUN: llvm-mc -triple i386-pc-linux-gnu %s -filetype=obj -o - | elf-dump | FileCheck %s + +.lcomm A, 5 +.lcomm B, 32 << 20 + +// CHECK: (('st_name', 0x00000001) # 'A' +// CHECK: ('st_value', 0x00000000) +// CHECK: ('st_size', 0x00000005) +// CHECK: ('st_bind', 0x0) +// CHECK: ('st_type', 0x1) +// CHECK: ('st_other', 0x00) +// CHECK: ('st_shndx', 0x0003) +// CHECK: ), +// CHECK: (('st_name', 0x00000003) # 'B' +// CHECK: ('st_value', 0x00000005) +// CHECK: ('st_size', 0x02000000) +// CHECK: ('st_bind', 0x0) +// CHECK: ('st_type', 0x1) +// CHECK: ('st_other', 0x00) +// CHECK: ('st_shndx', 0x0003) +// CHECK: ), |