mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-02-26 10:29:36 +00:00
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
This commit is contained in:
parent
8e70b5506e
commit
39646d96e7
@ -32,10 +32,6 @@ namespace llvm {
|
|||||||
enum ExceptionsType { None, DwarfCFI, SjLj, ARM, Win64 };
|
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
|
/// MCAsmInfo - This class is intended to be used as a base class for asm
|
||||||
/// properties and features specific to the target.
|
/// properties and features specific to the target.
|
||||||
class MCAsmInfo {
|
class MCAsmInfo {
|
||||||
@ -247,14 +243,14 @@ namespace llvm {
|
|||||||
/// .long a - b
|
/// .long a - b
|
||||||
bool HasAggressiveSymbolFolding; // Defaults to true.
|
bool HasAggressiveSymbolFolding; // Defaults to true.
|
||||||
|
|
||||||
/// LCOMMDirectiveType - Describes if the target supports the .lcomm
|
/// COMMDirectiveAlignmentIsInBytes - True is .comm's and .lcomms optional
|
||||||
/// 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).
|
/// alignment is to be specified in bytes instead of log2(n).
|
||||||
bool COMMDirectiveAlignmentIsInBytes; // Defaults to true;
|
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
|
/// HasDotTypeDotSizeDirective - True if the target has .type and .size
|
||||||
/// directives, this is true for most ELF targets.
|
/// directives, this is true for most ELF targets.
|
||||||
bool HasDotTypeDotSizeDirective; // Defaults to true.
|
bool HasDotTypeDotSizeDirective; // Defaults to true.
|
||||||
@ -496,13 +492,13 @@ namespace llvm {
|
|||||||
bool hasAggressiveSymbolFolding() const {
|
bool hasAggressiveSymbolFolding() const {
|
||||||
return HasAggressiveSymbolFolding;
|
return HasAggressiveSymbolFolding;
|
||||||
}
|
}
|
||||||
LCOMM::LCOMMType getLCOMMDirectiveType() const {
|
|
||||||
return LCOMMDirectiveType;
|
|
||||||
}
|
|
||||||
bool hasDotTypeDotSizeDirective() const {return HasDotTypeDotSizeDirective;}
|
|
||||||
bool getCOMMDirectiveAlignmentIsInBytes() const {
|
bool getCOMMDirectiveAlignmentIsInBytes() const {
|
||||||
return COMMDirectiveAlignmentIsInBytes;
|
return COMMDirectiveAlignmentIsInBytes;
|
||||||
}
|
}
|
||||||
|
bool getLCOMMDirectiveSupportsAlignment() const {
|
||||||
|
return LCOMMDirectiveSupportsAlignment;
|
||||||
|
}
|
||||||
|
bool hasDotTypeDotSizeDirective() const {return HasDotTypeDotSizeDirective;}
|
||||||
bool hasSingleParameterDotFile() const { return HasSingleParameterDotFile; }
|
bool hasSingleParameterDotFile() const { return HasSingleParameterDotFile; }
|
||||||
bool hasNoDeadStrip() const { return HasNoDeadStrip; }
|
bool hasNoDeadStrip() const { return HasNoDeadStrip; }
|
||||||
bool hasSymbolResolver() const { return HasSymbolResolver; }
|
bool hasSymbolResolver() const { return HasSymbolResolver; }
|
||||||
|
@ -312,8 +312,7 @@ void AsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (MAI->getLCOMMDirectiveType() != LCOMM::None &&
|
if (Align == 1 || MAI->getLCOMMDirectiveSupportsAlignment()) {
|
||||||
(MAI->getLCOMMDirectiveType() != LCOMM::NoAlignment || Align == 1)) {
|
|
||||||
// .lcomm _foo, 42
|
// .lcomm _foo, 42
|
||||||
OutStreamer.EmitLocalCommonSymbol(GVSym, Size, Align);
|
OutStreamer.EmitLocalCommonSymbol(GVSym, Size, Align);
|
||||||
return;
|
return;
|
||||||
|
@ -68,8 +68,8 @@ MCAsmInfo::MCAsmInfo() {
|
|||||||
GlobalDirective = "\t.globl\t";
|
GlobalDirective = "\t.globl\t";
|
||||||
HasSetDirective = true;
|
HasSetDirective = true;
|
||||||
HasAggressiveSymbolFolding = true;
|
HasAggressiveSymbolFolding = true;
|
||||||
LCOMMDirectiveType = LCOMM::None;
|
|
||||||
COMMDirectiveAlignmentIsInBytes = true;
|
COMMDirectiveAlignmentIsInBytes = true;
|
||||||
|
LCOMMDirectiveSupportsAlignment = false;
|
||||||
HasDotTypeDotSizeDirective = true;
|
HasDotTypeDotSizeDirective = true;
|
||||||
HasSingleParameterDotFile = true;
|
HasSingleParameterDotFile = true;
|
||||||
HasNoDeadStrip = false;
|
HasNoDeadStrip = false;
|
||||||
|
@ -20,7 +20,7 @@ void MCAsmInfoCOFF::anchor() { }
|
|||||||
MCAsmInfoCOFF::MCAsmInfoCOFF() {
|
MCAsmInfoCOFF::MCAsmInfoCOFF() {
|
||||||
GlobalPrefix = "_";
|
GlobalPrefix = "_";
|
||||||
COMMDirectiveAlignmentIsInBytes = false;
|
COMMDirectiveAlignmentIsInBytes = false;
|
||||||
LCOMMDirectiveType = LCOMM::ByteAlignment;
|
LCOMMDirectiveSupportsAlignment = true;
|
||||||
HasDotTypeDotSizeDirective = false;
|
HasDotTypeDotSizeDirective = false;
|
||||||
HasSingleParameterDotFile = false;
|
HasSingleParameterDotFile = false;
|
||||||
PrivateGlobalPrefix = "L"; // Prefix for private global symbols
|
PrivateGlobalPrefix = "L"; // Prefix for private global symbols
|
||||||
|
@ -32,6 +32,7 @@ MCAsmInfoDarwin::MCAsmInfoDarwin() {
|
|||||||
|
|
||||||
AlignmentIsInBytes = false;
|
AlignmentIsInBytes = false;
|
||||||
COMMDirectiveAlignmentIsInBytes = false;
|
COMMDirectiveAlignmentIsInBytes = false;
|
||||||
|
LCOMMDirectiveSupportsAlignment = true;
|
||||||
InlineAsmStart = " InlineAsm Start";
|
InlineAsmStart = " InlineAsm Start";
|
||||||
InlineAsmEnd = " InlineAsm End";
|
InlineAsmEnd = " InlineAsm End";
|
||||||
|
|
||||||
|
@ -517,13 +517,16 @@ void MCAsmStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
|
|||||||
/// @param Size - The size of the common symbol.
|
/// @param Size - The size of the common symbol.
|
||||||
void MCAsmStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
|
void MCAsmStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
|
||||||
unsigned ByteAlign) {
|
unsigned ByteAlign) {
|
||||||
assert(MAI.getLCOMMDirectiveType() != LCOMM::None &&
|
|
||||||
"Doesn't have .lcomm, can't emit it!");
|
|
||||||
OS << "\t.lcomm\t" << *Symbol << ',' << Size;
|
OS << "\t.lcomm\t" << *Symbol << ',' << Size;
|
||||||
if (ByteAlign > 1) {
|
if (ByteAlign > 1) {
|
||||||
assert(MAI.getLCOMMDirectiveType() == LCOMM::ByteAlignment &&
|
assert(MAI.getLCOMMDirectiveSupportsAlignment() &&
|
||||||
"Alignment not supported on .lcomm!");
|
"alignment not supported on .lcomm!");
|
||||||
OS << ',' << ByteAlign;
|
if (MAI.getCOMMDirectiveAlignmentIsInBytes()) {
|
||||||
|
OS << ',' << ByteAlign;
|
||||||
|
} else {
|
||||||
|
assert(isPowerOf2_32(ByteAlign) && "alignment must be a power of 2");
|
||||||
|
OS << ',' << Log2_32(ByteAlign);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
EmitEOL();
|
EmitEOL();
|
||||||
}
|
}
|
||||||
|
@ -70,9 +70,7 @@ public:
|
|||||||
llvm_unreachable("macho doesn't support this directive");
|
llvm_unreachable("macho doesn't support this directive");
|
||||||
}
|
}
|
||||||
virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
|
virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
|
||||||
unsigned ByteAlignment) {
|
unsigned ByteAlignment);
|
||||||
llvm_unreachable("macho doesn't support this directive");
|
|
||||||
}
|
|
||||||
virtual void EmitZerofill(const MCSection *Section, MCSymbol *Symbol = 0,
|
virtual void EmitZerofill(const MCSection *Section, MCSymbol *Symbol = 0,
|
||||||
uint64_t Size = 0, unsigned ByteAlignment = 0);
|
uint64_t Size = 0, unsigned ByteAlignment = 0);
|
||||||
virtual void EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol,
|
virtual void EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol,
|
||||||
@ -325,6 +323,15 @@ void MCMachOStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
|
|||||||
SD.setCommon(Size, ByteAlignment);
|
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,
|
void MCMachOStreamer::EmitZerofill(const MCSection *Section, MCSymbol *Symbol,
|
||||||
uint64_t Size, unsigned ByteAlignment) {
|
uint64_t Size, unsigned ByteAlignment) {
|
||||||
MCSectionData &SectData = getAssembler().getOrCreateSectionData(*Section);
|
MCSectionData &SectData = getAssembler().getOrCreateSectionData(*Section);
|
||||||
|
@ -2280,8 +2280,11 @@ bool AsmParser::ParseDirectiveComm(bool IsLocal) {
|
|||||||
if (ParseAbsoluteExpression(Pow2Alignment))
|
if (ParseAbsoluteExpression(Pow2Alignment))
|
||||||
return true;
|
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 this target takes alignments in bytes (not log) validate and convert.
|
||||||
if (Lexer.getMAI().getAlignmentIsInBytes()) {
|
if (Lexer.getMAI().getCOMMDirectiveAlignmentIsInBytes()) {
|
||||||
if (!isPowerOf2_64(Pow2Alignment))
|
if (!isPowerOf2_64(Pow2Alignment))
|
||||||
return Error(Pow2AlignmentLoc, "alignment must be a power of 2");
|
return Error(Pow2AlignmentLoc, "alignment must be a power of 2");
|
||||||
Pow2Alignment = Log2_64(Pow2Alignment);
|
Pow2Alignment = Log2_64(Pow2Alignment);
|
||||||
@ -2309,13 +2312,9 @@ bool AsmParser::ParseDirectiveComm(bool IsLocal) {
|
|||||||
if (!Sym->isUndefined())
|
if (!Sym->isUndefined())
|
||||||
return Error(IDLoc, "invalid symbol redefinition");
|
return Error(IDLoc, "invalid symbol redefinition");
|
||||||
|
|
||||||
// '.lcomm' is equivalent to '.zerofill'.
|
|
||||||
// Create the Symbol as a common or local common with Size and Pow2Alignment
|
// Create the Symbol as a common or local common with Size and Pow2Alignment
|
||||||
if (IsLocal) {
|
if (IsLocal) {
|
||||||
getStreamer().EmitZerofill(Ctx.getMachOSection(
|
getStreamer().EmitLocalCommonSymbol(Sym, Size, 1 << Pow2Alignment);
|
||||||
"__DATA", "__bss", MCSectionMachO::S_ZEROFILL,
|
|
||||||
0, SectionKind::getBSS()),
|
|
||||||
Sym, Size, 1 << Pow2Alignment);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,7 +50,6 @@ ARMELFMCAsmInfo::ARMELFMCAsmInfo() {
|
|||||||
Code32Directive = ".code\t32";
|
Code32Directive = ".code\t32";
|
||||||
|
|
||||||
WeakRefDirective = "\t.weak\t";
|
WeakRefDirective = "\t.weak\t";
|
||||||
LCOMMDirectiveType = LCOMM::NoAlignment;
|
|
||||||
|
|
||||||
HasLEB128 = true;
|
HasLEB128 = true;
|
||||||
SupportsDebugInformation = true;
|
SupportsDebugInformation = true;
|
||||||
|
@ -24,7 +24,7 @@ HexagonMCAsmInfo::HexagonMCAsmInfo(const Target &T, StringRef TT) {
|
|||||||
HasLEB128 = true;
|
HasLEB128 = true;
|
||||||
|
|
||||||
PrivateGlobalPrefix = ".L";
|
PrivateGlobalPrefix = ".L";
|
||||||
LCOMMDirectiveType = LCOMM::ByteAlignment;
|
LCOMMDirectiveSupportsAlignment = true;
|
||||||
InlineAsmStart = "# InlineAsm Start";
|
InlineAsmStart = "# InlineAsm Start";
|
||||||
InlineAsmEnd = "# InlineAsm End";
|
InlineAsmEnd = "# InlineAsm End";
|
||||||
ZeroDirective = "\t.space\t";
|
ZeroDirective = "\t.space\t";
|
||||||
|
@ -64,7 +64,6 @@ PPCLinuxMCAsmInfo::PPCLinuxMCAsmInfo(bool is64Bit) {
|
|||||||
|
|
||||||
ZeroDirective = "\t.space\t";
|
ZeroDirective = "\t.space\t";
|
||||||
Data64bitsDirective = is64Bit ? "\t.quad\t" : 0;
|
Data64bitsDirective = is64Bit ? "\t.quad\t" : 0;
|
||||||
LCOMMDirectiveType = LCOMM::NoAlignment;
|
|
||||||
AssemblerDialect = 0; // Old-Style mnemonics.
|
AssemblerDialect = 0; // Old-Style mnemonics.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,9 +1,14 @@
|
|||||||
# RUN: llvm-mc -triple i386-apple-darwin10 %s | FileCheck %s
|
# 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: TEST0:
|
||||||
# CHECK: .zerofill __DATA,__bss,a,7,4
|
# CHECK: .lcomm a,7,4
|
||||||
# CHECK: .zerofill __DATA,__bss,b,8
|
# CHECK: .lcomm b,8
|
||||||
# CHECK: .zerofill __DATA,__bss,c,0
|
# CHECK: .lcomm c,0
|
||||||
|
|
||||||
|
# ELF doesn't like alignment on .lcomm.
|
||||||
|
# ERROR: alignment not supported on this target
|
||||||
TEST0:
|
TEST0:
|
||||||
.lcomm a, 8-1, 4
|
.lcomm a, 8-1, 4
|
||||||
.lcomm b,8
|
.lcomm b,8
|
||||||
|
@ -41,7 +41,7 @@ foo:
|
|||||||
// CHECK: .comm "a 6",1
|
// CHECK: .comm "a 6",1
|
||||||
.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
|
.lcomm "a 7", 1
|
||||||
|
|
||||||
// FIXME: We don't bother to support .lsym.
|
// FIXME: We don't bother to support .lsym.
|
||||||
|
21
test/MC/ELF/lcomm.s
Normal file
21
test/MC/ELF/lcomm.s
Normal file
@ -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: ),
|
Loading…
x
Reference in New Issue
Block a user