summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Kramer <benny.kra@googlemail.com>2011-09-01 23:04:27 +0000
committerBenjamin Kramer <benny.kra@googlemail.com>2011-09-01 23:04:27 +0000
commit36a16015ac108e2f0dd2d6d96a6d364bc74c50d7 (patch)
tree32f8e302aea0fbe6b07b367e256e4f2e01bc19a4
parent7df496d2ad1ecbc86d454a5cea2ae3e0928197ee (diff)
downloadllvm-36a16015ac108e2f0dd2d6d96a6d364bc74c50d7.tar.gz
llvm-36a16015ac108e2f0dd2d6d96a6d364bc74c50d7.tar.bz2
llvm-36a16015ac108e2f0dd2d6d96a6d364bc74c50d7.tar.xz
Don't drop alignment info on local common symbols.
- On COFF the .lcomm directive has an alignment argument. - On ELF we fall back to .local + .comm Based on a patch by NAKAMURA Takumi. Fixes PR9337, PR9483 and PR10128. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@138976 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/llvm/MC/MCAsmInfo.h14
-rw-r--r--include/llvm/MC/MCStreamer.h4
-rw-r--r--lib/CodeGen/AsmPrinter/AsmPrinter.cpp10
-rw-r--r--lib/MC/MCAsmInfo.cpp2
-rw-r--r--lib/MC/MCAsmInfoCOFF.cpp2
-rw-r--r--lib/MC/MCAsmStreamer.cpp15
-rw-r--r--lib/MC/MCELFStreamer.cpp6
-rw-r--r--lib/MC/MCELFStreamer.h3
-rw-r--r--lib/MC/MCLoggingStreamer.cpp5
-rw-r--r--lib/MC/MCMachOStreamer.cpp3
-rw-r--r--lib/MC/MCNullStreamer.cpp4
-rw-r--r--lib/MC/MCPureStreamer.cpp3
-rw-r--r--lib/MC/WinCOFFStreamer.cpp8
-rw-r--r--lib/Target/ARM/MCTargetDesc/ARMMCAsmInfo.cpp2
-rw-r--r--lib/Target/PTX/PTXMCAsmStreamer.cpp7
-rw-r--r--lib/Target/PowerPC/MCTargetDesc/PPCMCAsmInfo.cpp2
-rw-r--r--test/CodeGen/ARM/2010-12-15-elf-lcomm.ll11
-rw-r--r--test/CodeGen/ARM/elf-lcomm-align.ll14
-rw-r--r--tools/lto/LTOModule.cpp3
19 files changed, 80 insertions, 38 deletions
diff --git a/include/llvm/MC/MCAsmInfo.h b/include/llvm/MC/MCAsmInfo.h
index b8a0e02394..96b68c833d 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 { 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 {
@@ -229,9 +233,9 @@ namespace llvm {
/// .long a - b
bool HasAggressiveSymbolFolding; // Defaults to true.
- /// HasLCOMMDirective - This is true if the target supports the .lcomm
- /// directive.
- bool HasLCOMMDirective; // Defaults to false.
+ /// 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
/// alignment is to be specified in bytes instead of log2(n).
@@ -479,7 +483,9 @@ namespace llvm {
bool hasAggressiveSymbolFolding() const {
return HasAggressiveSymbolFolding;
}
- bool hasLCOMMDirective() const { return HasLCOMMDirective; }
+ LCOMM::LCOMMType getLCOMMDirectiveType() const {
+ return LCOMMDirectiveType;
+ }
bool hasDotTypeDotSizeDirective() const {return HasDotTypeDotSizeDirective;}
bool getCOMMDirectiveAlignmentIsInBytes() const {
return COMMDirectiveAlignmentIsInBytes;
diff --git a/include/llvm/MC/MCStreamer.h b/include/llvm/MC/MCStreamer.h
index c5c7583f10..4279ef5091 100644
--- a/include/llvm/MC/MCStreamer.h
+++ b/include/llvm/MC/MCStreamer.h
@@ -304,7 +304,9 @@ namespace llvm {
///
/// @param Symbol - The common symbol to emit.
/// @param Size - The size of the common symbol.
- virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size) = 0;
+ /// @param ByteAlignment - The alignment of the common symbol in bytes.
+ virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
+ unsigned ByteAlignment) = 0;
/// EmitZerofill - Emit the zerofill section and an optional symbol.
///
diff --git a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index f7341fee4b..6084a3c8f5 100644
--- a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -290,10 +290,10 @@ void AsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) {
// Handle common and BSS local symbols (.lcomm).
if (GVKind.isCommon() || GVKind.isBSSLocal()) {
if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it.
+ unsigned Align = 1 << AlignLog;
// Handle common symbols.
if (GVKind.isCommon()) {
- unsigned Align = 1 << AlignLog;
if (!getObjFileLowering().getCommDirectiveSupportsAlignment())
Align = 0;
@@ -307,17 +307,17 @@ void AsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) {
const MCSection *TheSection =
getObjFileLowering().SectionForGlobal(GV, GVKind, Mang, TM);
// .zerofill __DATA, __bss, _foo, 400, 5
- OutStreamer.EmitZerofill(TheSection, GVSym, Size, 1 << AlignLog);
+ OutStreamer.EmitZerofill(TheSection, GVSym, Size, Align);
return;
}
- if (MAI->hasLCOMMDirective()) {
+ if (MAI->getLCOMMDirectiveType() != LCOMM::None &&
+ (MAI->getLCOMMDirectiveType() != LCOMM::NoAlignment || Align == 1)) {
// .lcomm _foo, 42
- OutStreamer.EmitLocalCommonSymbol(GVSym, Size);
+ OutStreamer.EmitLocalCommonSymbol(GVSym, Size, Align);
return;
}
- unsigned Align = 1 << AlignLog;
if (!getObjFileLowering().getCommDirectiveSupportsAlignment())
Align = 0;
diff --git a/lib/MC/MCAsmInfo.cpp b/lib/MC/MCAsmInfo.cpp
index 015ccd4124..a53c474c15 100644
--- a/lib/MC/MCAsmInfo.cpp
+++ b/lib/MC/MCAsmInfo.cpp
@@ -65,7 +65,7 @@ MCAsmInfo::MCAsmInfo() {
GlobalDirective = "\t.globl\t";
HasSetDirective = true;
HasAggressiveSymbolFolding = true;
- HasLCOMMDirective = false;
+ LCOMMDirectiveType = LCOMM::None;
COMMDirectiveAlignmentIsInBytes = true;
HasDotTypeDotSizeDirective = true;
HasSingleParameterDotFile = true;
diff --git a/lib/MC/MCAsmInfoCOFF.cpp b/lib/MC/MCAsmInfoCOFF.cpp
index 7fc7d7abb2..cf6026b4ef 100644
--- a/lib/MC/MCAsmInfoCOFF.cpp
+++ b/lib/MC/MCAsmInfoCOFF.cpp
@@ -19,7 +19,7 @@ using namespace llvm;
MCAsmInfoCOFF::MCAsmInfoCOFF() {
GlobalPrefix = "_";
COMMDirectiveAlignmentIsInBytes = false;
- HasLCOMMDirective = true;
+ LCOMMDirectiveType = LCOMM::ByteAlignment;
HasDotTypeDotSizeDirective = false;
HasSingleParameterDotFile = false;
PrivateGlobalPrefix = "L"; // Prefix for private global symbols
diff --git a/lib/MC/MCAsmStreamer.cpp b/lib/MC/MCAsmStreamer.cpp
index 40eaf979fa..68154345c8 100644
--- a/lib/MC/MCAsmStreamer.cpp
+++ b/lib/MC/MCAsmStreamer.cpp
@@ -158,7 +158,9 @@ public:
///
/// @param Symbol - The common symbol to emit.
/// @param Size - The size of the common symbol.
- virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size);
+ /// @param Size - The alignment of the common symbol in bytes.
+ virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
+ unsigned ByteAlignment);
virtual void EmitZerofill(const MCSection *Section, MCSymbol *Symbol = 0,
unsigned Size = 0, unsigned ByteAlignment = 0);
@@ -484,9 +486,16 @@ void MCAsmStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
///
/// @param Symbol - The common symbol to emit.
/// @param Size - The size of the common symbol.
-void MCAsmStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size) {
- assert(MAI.hasLCOMMDirective() && "Doesn't have .lcomm, can't emit it!");
+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;
+ }
EmitEOL();
}
diff --git a/lib/MC/MCELFStreamer.cpp b/lib/MC/MCELFStreamer.cpp
index 573b3e4887..9ada08ea95 100644
--- a/lib/MC/MCELFStreamer.cpp
+++ b/lib/MC/MCELFStreamer.cpp
@@ -220,14 +220,14 @@ void MCELFStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
SD.setSize(MCConstantExpr::Create(Size, getContext()));
}
-void MCELFStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size) {
+void MCELFStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
+ unsigned ByteAlignment) {
// FIXME: Should this be caught and done earlier?
MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol);
MCELF::SetBinding(SD, ELF::STB_LOCAL);
SD.setExternal(false);
BindingExplicitlySet.insert(Symbol);
- // FIXME: ByteAlignment is not needed here, but is required.
- EmitCommonSymbol(Symbol, Size, 1);
+ EmitCommonSymbol(Symbol, Size, ByteAlignment);
}
void MCELFStreamer::EmitBytes(StringRef Data, unsigned AddrSpace) {
diff --git a/lib/MC/MCELFStreamer.h b/lib/MC/MCELFStreamer.h
index 9b5f3a8bbe..10bf775809 100644
--- a/lib/MC/MCELFStreamer.h
+++ b/lib/MC/MCELFStreamer.h
@@ -74,7 +74,8 @@ public:
SD.setSize(Value);
}
- virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size);
+ virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
+ unsigned ByteAlignment);
virtual void EmitZerofill(const MCSection *Section, MCSymbol *Symbol = 0,
unsigned Size = 0, unsigned ByteAlignment = 0) {
diff --git a/lib/MC/MCLoggingStreamer.cpp b/lib/MC/MCLoggingStreamer.cpp
index 309752ec5f..3fe8ac72c8 100644
--- a/lib/MC/MCLoggingStreamer.cpp
+++ b/lib/MC/MCLoggingStreamer.cpp
@@ -133,9 +133,10 @@ public:
return Child->EmitCommonSymbol(Symbol, Size, ByteAlignment);
}
- virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size) {
+ virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
+ unsigned ByteAlignment) {
LogCall("EmitLocalCommonSymbol");
- return Child->EmitLocalCommonSymbol(Symbol, Size);
+ return Child->EmitLocalCommonSymbol(Symbol, Size, ByteAlignment);
}
virtual void EmitZerofill(const MCSection *Section, MCSymbol *Symbol = 0,
diff --git a/lib/MC/MCMachOStreamer.cpp b/lib/MC/MCMachOStreamer.cpp
index 844793b488..aa35815dd1 100644
--- a/lib/MC/MCMachOStreamer.cpp
+++ b/lib/MC/MCMachOStreamer.cpp
@@ -67,7 +67,8 @@ public:
virtual void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) {
assert(0 && "macho doesn't support this directive");
}
- virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size) {
+ virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
+ unsigned ByteAlignment) {
assert(0 && "macho doesn't support this directive");
}
virtual void EmitZerofill(const MCSection *Section, MCSymbol *Symbol = 0,
diff --git a/lib/MC/MCNullStreamer.cpp b/lib/MC/MCNullStreamer.cpp
index 9577af0102..a6c0adb679 100644
--- a/lib/MC/MCNullStreamer.cpp
+++ b/lib/MC/MCNullStreamer.cpp
@@ -59,8 +59,8 @@ namespace {
virtual void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) {}
virtual void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
unsigned ByteAlignment) {}
- virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size) {}
-
+ virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
+ unsigned ByteAlignment) {}
virtual void EmitZerofill(const MCSection *Section, MCSymbol *Symbol = 0,
unsigned Size = 0, unsigned ByteAlignment = 0) {}
virtual void EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol,
diff --git a/lib/MC/MCPureStreamer.cpp b/lib/MC/MCPureStreamer.cpp
index 0b61c882d4..086c9229bc 100644
--- a/lib/MC/MCPureStreamer.cpp
+++ b/lib/MC/MCPureStreamer.cpp
@@ -86,7 +86,8 @@ public:
virtual void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) {
report_fatal_error("unsupported directive in pure streamer");
}
- virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size) {
+ virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
+ unsigned ByteAlignment) {
report_fatal_error("unsupported directive in pure streamer");
}
virtual void EmitFileDirective(StringRef Filename) {
diff --git a/lib/MC/WinCOFFStreamer.cpp b/lib/MC/WinCOFFStreamer.cpp
index f79ba8e689..7409daf390 100644
--- a/lib/MC/WinCOFFStreamer.cpp
+++ b/lib/MC/WinCOFFStreamer.cpp
@@ -63,7 +63,8 @@ public:
virtual void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value);
virtual void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
unsigned ByteAlignment);
- virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size);
+ virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
+ unsigned ByteAlignment);
virtual void EmitZerofill(const MCSection *Section, MCSymbol *Symbol,
unsigned Size,unsigned ByteAlignment);
virtual void EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol,
@@ -304,11 +305,12 @@ void WinCOFFStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
AddCommonSymbol(Symbol, Size, ByteAlignment, true);
}
-void WinCOFFStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size) {
+void WinCOFFStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
+ unsigned ByteAlignment) {
assert((Symbol->isInSection()
? Symbol->getSection().getVariant() == MCSection::SV_COFF
: true) && "Got non COFF section in the COFF backend!");
- AddCommonSymbol(Symbol, Size, 1, false);
+ AddCommonSymbol(Symbol, Size, ByteAlignment, false);
}
void WinCOFFStreamer::EmitZerofill(const MCSection *Section, MCSymbol *Symbol,
diff --git a/lib/Target/ARM/MCTargetDesc/ARMMCAsmInfo.cpp b/lib/Target/ARM/MCTargetDesc/ARMMCAsmInfo.cpp
index 07e3540e31..1c109e0152 100644
--- a/lib/Target/ARM/MCTargetDesc/ARMMCAsmInfo.cpp
+++ b/lib/Target/ARM/MCTargetDesc/ARMMCAsmInfo.cpp
@@ -72,7 +72,7 @@ ARMELFMCAsmInfo::ARMELFMCAsmInfo() {
Code32Directive = ".code\t32";
WeakRefDirective = "\t.weak\t";
- HasLCOMMDirective = true;
+ LCOMMDirectiveType = LCOMM::NoAlignment;
HasLEB128 = true;
SupportsDebugInformation = true;
diff --git a/lib/Target/PTX/PTXMCAsmStreamer.cpp b/lib/Target/PTX/PTXMCAsmStreamer.cpp
index bac5535693..5003fb5b8f 100644
--- a/lib/Target/PTX/PTXMCAsmStreamer.cpp
+++ b/lib/Target/PTX/PTXMCAsmStreamer.cpp
@@ -132,7 +132,9 @@ public:
///
/// @param Symbol - The common symbol to emit.
/// @param Size - The size of the common symbol.
- virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size);
+ /// @param ByteAlignment - The alignment of the common symbol in bytes.
+ virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
+ unsigned ByteAlignment);
virtual void EmitZerofill(const MCSection *Section, MCSymbol *Symbol = 0,
unsigned Size = 0, unsigned ByteAlignment = 0);
@@ -283,7 +285,8 @@ void PTXMCAsmStreamer::EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) {}
void PTXMCAsmStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
unsigned ByteAlignment) {}
-void PTXMCAsmStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size) {}
+void PTXMCAsmStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
+ unsigned ByteAlignment) {}
void PTXMCAsmStreamer::EmitZerofill(const MCSection *Section, MCSymbol *Symbol,
unsigned Size, unsigned ByteAlignment) {}
diff --git a/lib/Target/PowerPC/MCTargetDesc/PPCMCAsmInfo.cpp b/lib/Target/PowerPC/MCTargetDesc/PPCMCAsmInfo.cpp
index b6d46dd34f..e9424d8415 100644
--- a/lib/Target/PowerPC/MCTargetDesc/PPCMCAsmInfo.cpp
+++ b/lib/Target/PowerPC/MCTargetDesc/PPCMCAsmInfo.cpp
@@ -60,7 +60,7 @@ PPCLinuxMCAsmInfo::PPCLinuxMCAsmInfo(bool is64Bit) {
ZeroDirective = "\t.space\t";
Data64bitsDirective = is64Bit ? "\t.quad\t" : 0;
- HasLCOMMDirective = true;
+ LCOMMDirectiveType = LCOMM::NoAlignment;
AssemblerDialect = 0; // Old-Style mnemonics.
}
diff --git a/test/CodeGen/ARM/2010-12-15-elf-lcomm.ll b/test/CodeGen/ARM/2010-12-15-elf-lcomm.ll
index a4bab85692..5cfbb4f944 100644
--- a/test/CodeGen/ARM/2010-12-15-elf-lcomm.ll
+++ b/test/CodeGen/ARM/2010-12-15-elf-lcomm.ll
@@ -5,7 +5,7 @@
@dummy = internal global i32 666
-@array00 = internal global [20 x i32] zeroinitializer
+@array00 = internal global [80 x i8] zeroinitializer, align 1
@sum = internal global i32 55
@STRIDE = internal global i32 8
@@ -28,8 +28,9 @@
define i32 @main(i32 %argc) nounwind {
%1 = load i32* @sum, align 4
- %2 = getelementptr [20 x i32]* @array00, i32 0, i32 %argc
- %3 = load i32* %2, align 4
- %4 = add i32 %1, %3
- ret i32 %4;
+ %2 = getelementptr [80 x i8]* @array00, i32 0, i32 %argc
+ %3 = load i8* %2
+ %4 = zext i8 %3 to i32
+ %5 = add i32 %1, %4
+ ret i32 %5
}
diff --git a/test/CodeGen/ARM/elf-lcomm-align.ll b/test/CodeGen/ARM/elf-lcomm-align.ll
new file mode 100644
index 0000000000..46792990e5
--- /dev/null
+++ b/test/CodeGen/ARM/elf-lcomm-align.ll
@@ -0,0 +1,14 @@
+; RUN: llc < %s -mtriple=arm-linux-gnueabi -O0 | FileCheck %s
+; run with -O0 to avoid arm global merging.
+
+@c = internal global i8 0, align 1
+@x = internal global i32 0, align 4
+
+; CHECK: .lcomm c,1
+; .lcomm doesn't support alignment.
+; CHECK: .local x
+; CHECK-NEXT: .comm x,4,4
+
+define i32 @foo() nounwind {
+ ret i32 sub (i32 ptrtoint (i8* @c to i32), i32 ptrtoint (i32* @x to i32))
+}
diff --git a/tools/lto/LTOModule.cpp b/tools/lto/LTOModule.cpp
index 7c9489179a..f6dc7d90bc 100644
--- a/tools/lto/LTOModule.cpp
+++ b/tools/lto/LTOModule.cpp
@@ -581,7 +581,8 @@ namespace {
markDefined(*Symbol);
}
virtual void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) {}
- virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size) {}
+ virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
+ unsigned ByteAlignment) {}
virtual void EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol,
uint64_t Size, unsigned ByteAlignment) {}
virtual void EmitBytes(StringRef Data, unsigned AddrSpace) {}