mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-06-20 10:24:12 +00:00
WinCOFF: Emit common symbols as specified in the COFF spec
Summary: Local common symbols were properly inserted into the .bss section. However, putting external common symbols in the .bss section would give them a strong definition. Instead, encode them as undefined, external symbols who's symbol value is equivalent to their size. Reviewers: Bigcheese, rafael, rnk CC: llvm-commits Differential Revision: http://reviews.llvm.org/D3324 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@205811 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@ -755,7 +755,7 @@ const MCSection *TargetLoweringObjectFileCOFF::getExplicitSectionGlobal(
|
|||||||
static const char *getCOFFSectionNameForUniqueGlobal(SectionKind Kind) {
|
static const char *getCOFFSectionNameForUniqueGlobal(SectionKind Kind) {
|
||||||
if (Kind.isText())
|
if (Kind.isText())
|
||||||
return ".text";
|
return ".text";
|
||||||
if (Kind.isBSS ())
|
if (Kind.isBSS())
|
||||||
return ".bss";
|
return ".bss";
|
||||||
if (Kind.isThreadLocal())
|
if (Kind.isThreadLocal())
|
||||||
return ".tls$";
|
return ".tls$";
|
||||||
@ -781,7 +781,7 @@ SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind,
|
|||||||
// Section names depend on the name of the symbol which is not feasible if the
|
// Section names depend on the name of the symbol which is not feasible if the
|
||||||
// symbol has private linkage.
|
// symbol has private linkage.
|
||||||
if ((GV->isWeakForLinker() || EmitUniquedSection) &&
|
if ((GV->isWeakForLinker() || EmitUniquedSection) &&
|
||||||
!GV->hasPrivateLinkage()) {
|
!GV->hasPrivateLinkage() && !Kind.isCommon()) {
|
||||||
const char *Name = getCOFFSectionNameForUniqueGlobal(Kind);
|
const char *Name = getCOFFSectionNameForUniqueGlobal(Kind);
|
||||||
unsigned Characteristics = getCOFFSectionFlags(Kind);
|
unsigned Characteristics = getCOFFSectionFlags(Kind);
|
||||||
|
|
||||||
@ -802,7 +802,10 @@ SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind,
|
|||||||
if (Kind.isReadOnly())
|
if (Kind.isReadOnly())
|
||||||
return ReadOnlySection;
|
return ReadOnlySection;
|
||||||
|
|
||||||
if (Kind.isBSS())
|
// Note: we claim that common symbols are put in BSSSection, but they are
|
||||||
|
// really emitted with the magic .comm directive, which creates a symbol table
|
||||||
|
// entry but not a section.
|
||||||
|
if (Kind.isBSS() || Kind.isCommon())
|
||||||
return BSSSection;
|
return BSSSection;
|
||||||
|
|
||||||
return DataSection;
|
return DataSection;
|
||||||
|
@ -548,6 +548,10 @@ void MCObjectFileInfo::InitELFMCObjectFileInfo(Triple T) {
|
|||||||
|
|
||||||
|
|
||||||
void MCObjectFileInfo::InitCOFFMCObjectFileInfo(Triple T) {
|
void MCObjectFileInfo::InitCOFFMCObjectFileInfo(Triple T) {
|
||||||
|
// The object file format cannot represent common symbols with explicit
|
||||||
|
// alignments.
|
||||||
|
CommDirectiveSupportsAlignment = false;
|
||||||
|
|
||||||
// COFF
|
// COFF
|
||||||
BSSSection =
|
BSSSection =
|
||||||
Ctx->getCOFFSection(".bss",
|
Ctx->getCOFFSection(".bss",
|
||||||
|
@ -394,7 +394,7 @@ void WinCOFFObjectWriter::DefineSection(MCSectionData const &SectionData) {
|
|||||||
SectionMap[&SectionData.getSection()] = coff_section;
|
SectionMap[&SectionData.getSection()] = coff_section;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This function takes a section data object from the assembler
|
/// This function takes a symbol data object from the assembler
|
||||||
/// and creates the associated COFF symbol staging object.
|
/// and creates the associated COFF symbol staging object.
|
||||||
void WinCOFFObjectWriter::DefineSymbol(MCSymbolData const &SymbolData,
|
void WinCOFFObjectWriter::DefineSymbol(MCSymbolData const &SymbolData,
|
||||||
MCAssembler &Assembler,
|
MCAssembler &Assembler,
|
||||||
@ -443,6 +443,8 @@ void WinCOFFObjectWriter::DefineSymbol(MCSymbolData const &SymbolData,
|
|||||||
int64_t Addr;
|
int64_t Addr;
|
||||||
if (Symbol.getVariableValue()->EvaluateAsAbsolute(Addr, Layout))
|
if (Symbol.getVariableValue()->EvaluateAsAbsolute(Addr, Layout))
|
||||||
coff_symbol->Data.Value = Addr;
|
coff_symbol->Data.Value = Addr;
|
||||||
|
} else if (SymbolData.isExternal() && SymbolData.isCommon()) {
|
||||||
|
coff_symbol->Data.Value = SymbolData.getCommonSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
coff_symbol->Data.Type = (ResSymData.getFlags() & 0x0000FFFF) >> 0;
|
coff_symbol->Data.Type = (ResSymData.getFlags() & 0x0000FFFF) >> 0;
|
||||||
|
@ -45,9 +45,6 @@ public:
|
|||||||
MCCodeEmitter &CE,
|
MCCodeEmitter &CE,
|
||||||
raw_ostream &OS);
|
raw_ostream &OS);
|
||||||
|
|
||||||
void AddCommonSymbol(MCSymbol *Symbol, uint64_t Size,
|
|
||||||
unsigned ByteAlignment, bool External);
|
|
||||||
|
|
||||||
// MCStreamer interface
|
// MCStreamer interface
|
||||||
|
|
||||||
void InitSections() override;
|
void InitSections() override;
|
||||||
@ -101,26 +98,6 @@ WinCOFFStreamer::WinCOFFStreamer(MCContext &Context, MCAsmBackend &MAB,
|
|||||||
MCCodeEmitter &CE, raw_ostream &OS)
|
MCCodeEmitter &CE, raw_ostream &OS)
|
||||||
: MCObjectStreamer(Context, MAB, OS, &CE), CurSymbol(NULL) {}
|
: MCObjectStreamer(Context, MAB, OS, &CE), CurSymbol(NULL) {}
|
||||||
|
|
||||||
void WinCOFFStreamer::AddCommonSymbol(MCSymbol *Symbol, uint64_t Size,
|
|
||||||
unsigned ByteAlignment, bool External) {
|
|
||||||
assert(!Symbol->isInSection() && "Symbol must not already have a section!");
|
|
||||||
|
|
||||||
const MCSection *Section = getContext().getObjectFileInfo()->getBSSSection();
|
|
||||||
MCSectionData &SectionData = getAssembler().getOrCreateSectionData(*Section);
|
|
||||||
if (SectionData.getAlignment() < ByteAlignment)
|
|
||||||
SectionData.setAlignment(ByteAlignment);
|
|
||||||
|
|
||||||
MCSymbolData &SymbolData = getAssembler().getOrCreateSymbolData(*Symbol);
|
|
||||||
SymbolData.setExternal(External);
|
|
||||||
|
|
||||||
AssignSection(Symbol, Section);
|
|
||||||
|
|
||||||
if (ByteAlignment != 1)
|
|
||||||
new MCAlignFragment(ByteAlignment, 0, 0, ByteAlignment, &SectionData);
|
|
||||||
|
|
||||||
SymbolData.setFragment(new MCFillFragment(0, 0, Size, &SectionData));
|
|
||||||
}
|
|
||||||
|
|
||||||
// MCStreamer interface
|
// MCStreamer interface
|
||||||
|
|
||||||
void WinCOFFStreamer::InitSections() {
|
void WinCOFFStreamer::InitSections() {
|
||||||
@ -244,15 +221,38 @@ void WinCOFFStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
|
|||||||
assert((Symbol->isInSection()
|
assert((Symbol->isInSection()
|
||||||
? Symbol->getSection().getVariant() == MCSection::SV_COFF
|
? Symbol->getSection().getVariant() == MCSection::SV_COFF
|
||||||
: true) && "Got non-COFF section in the COFF backend!");
|
: true) && "Got non-COFF section in the COFF backend!");
|
||||||
AddCommonSymbol(Symbol, Size, ByteAlignment, true);
|
|
||||||
|
if (ByteAlignment > 32)
|
||||||
|
report_fatal_error(
|
||||||
|
"The linker won't align common symbols beyond 32 bytes.");
|
||||||
|
|
||||||
|
AssignSection(Symbol, NULL);
|
||||||
|
|
||||||
|
MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol);
|
||||||
|
SD.setExternal(true);
|
||||||
|
SD.setCommon(Size, ByteAlignment);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WinCOFFStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
|
void WinCOFFStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
|
||||||
unsigned ByteAlignment) {
|
unsigned ByteAlignment) {
|
||||||
assert((Symbol->isInSection()
|
assert(!Symbol->isInSection() && "Symbol must not already have a section!");
|
||||||
? Symbol->getSection().getVariant() == MCSection::SV_COFF
|
|
||||||
: true) && "Got non-COFF section in the COFF backend!");
|
const MCSection *Section = getContext().getObjectFileInfo()->getBSSSection();
|
||||||
AddCommonSymbol(Symbol, Size, ByteAlignment, false);
|
MCSectionData &SectionData = getAssembler().getOrCreateSectionData(*Section);
|
||||||
|
if (SectionData.getAlignment() < ByteAlignment)
|
||||||
|
SectionData.setAlignment(ByteAlignment);
|
||||||
|
|
||||||
|
MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol);
|
||||||
|
SD.setExternal(false);
|
||||||
|
|
||||||
|
AssignSection(Symbol, Section);
|
||||||
|
|
||||||
|
if (ByteAlignment != 1)
|
||||||
|
new MCAlignFragment(ByteAlignment, /*_Value=*/0, /*_ValueSize=*/0,
|
||||||
|
ByteAlignment, &SectionData);
|
||||||
|
|
||||||
|
SD.setFragment(
|
||||||
|
new MCFillFragment(/*_Value=*/0, /*_ValueSize=*/0, Size, &SectionData));
|
||||||
}
|
}
|
||||||
|
|
||||||
void WinCOFFStreamer::EmitZerofill(const MCSection *Section, MCSymbol *Symbol,
|
void WinCOFFStreamer::EmitZerofill(const MCSection *Section, MCSymbol *Symbol,
|
||||||
|
@ -9,5 +9,5 @@
|
|||||||
; CHECK: .lcomm _a,1
|
; CHECK: .lcomm _a,1
|
||||||
; CHECK: .lcomm _b,8,8
|
; CHECK: .lcomm _b,8,8
|
||||||
; .comm uses log2 alignment
|
; .comm uses log2 alignment
|
||||||
; CHECK: .comm _c,1,0
|
; CHECK: .comm _c,1
|
||||||
; CHECK: .comm _d,8,3
|
; CHECK: .comm _d,8
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
// RUN: llvm-mc -filetype=obj -triple i686-pc-win32 %s | llvm-readobj -t | FileCheck %s
|
// RUN: llvm-mc -filetype=obj -triple i686-pc-win32 %s | llvm-readobj -t | FileCheck %s
|
||||||
|
|
||||||
.lcomm _a,4,4
|
.lcomm _a,4,4
|
||||||
.comm _b, 4, 2
|
.comm _b, 4
|
||||||
|
|
||||||
|
|
||||||
// CHECK: Symbol {
|
// CHECK: Symbol {
|
||||||
@ -17,7 +17,7 @@
|
|||||||
// CHECK: Symbol {
|
// CHECK: Symbol {
|
||||||
// CHECK: Name: _b
|
// CHECK: Name: _b
|
||||||
// CHECK-NEXT: Value: 4
|
// CHECK-NEXT: Value: 4
|
||||||
// CHECK-NEXT: Section: .bss
|
// CHECK-NEXT: Section: (0)
|
||||||
// CHECK-NEXT: BaseType: Null
|
// CHECK-NEXT: BaseType: Null
|
||||||
// CHECK-NEXT: ComplexType: Null
|
// CHECK-NEXT: ComplexType: Null
|
||||||
// CHECK-NEXT: StorageClass: External
|
// CHECK-NEXT: StorageClass: External
|
||||||
|
Reference in New Issue
Block a user