// Properties to be set by the target writer, used to configure asm printer.
//
- /// ZeroFillDirective - Directive for emitting a global to the ZeroFill
- /// section on this target. Null if this target doesn't support zerofill.
- const char *ZeroFillDirective; // Default is null.
-
/// NonexecutableStackDirective - Directive for declaring to the
/// linker and beyond that the emitted code does not require stack
/// memory to be executable.
const char *NonexecutableStackDirective; // Default is null.
+ /// HasMachoZeroFillDirective - True if this is a MachO target that supports
+ /// the macho-specific .zerofill directive for emitting BSS Symbols.
+ bool HasMachoZeroFillDirective; // Default is false.
+
/// NeedsSet - True if target asm treats expressions in data directives
/// as linktime-relocatable. For assembly-time computation, we need to
/// use a .set. Thus:
// Accessors.
//
- const char *getZeroFillDirective() const {
- return ZeroFillDirective;
- }
- bool hasZeroFillDirective() const { return ZeroFillDirective != 0; }
+ bool hasMachoZeroFillDirective() const { return HasMachoZeroFillDirective; }
const char *getNonexecutableStackDirective() const {
return NonexecutableStackDirective;
const MCSection *ConstDataCoalSection;
const MCSection *ConstDataSection;
const MCSection *DataCoalSection;
+ const MCSection *DataCommonSection;
const MCSection *FourByteConstantSection;
const MCSection *EightByteConstantSection;
const MCSection *SixteenByteConstantSection;
return ConstTextCoalSection;
}
+ /// getDataCommonSection - Return the "__DATA,__common" section we put
+ /// zerofill (aka bss) data into.
+ const MCSection *getDataCommonSection() const {
+ return DataCommonSection;
+ }
+
/// getLazySymbolPointerSection - Return the section corresponding to
/// the .lazy_symbol_pointer directive.
const MCSection *getLazySymbolPointerSection() const {
using namespace llvm;
MCAsmInfo::MCAsmInfo() {
- ZeroFillDirective = 0;
+ HasMachoZeroFillDirective = false;
NonexecutableStackDirective = 0;
NeedsSet = false;
MaxInstLength = 4;
HiddenDirective = "\t.private_extern ";
LCOMMDirective = "\t.lcomm\t";
ZeroDirective = "\t.space\t"; // ".space N" emits N zeros.
- ZeroFillDirective = "\t.zerofill\t"; // Uses .zerofill
+ HasMachoZeroFillDirective = true; // Uses .zerofill
SetDirective = "\t.set";
ProtectedDirective = "\t.globl\t";
HasDotTypeDotSizeDirective = false;
if (Subtarget->isTargetELF())
O << "\t.type " << *GVarSym << ",%object\n";
+ SectionKind GVKind = TargetLoweringObjectFile::getKindForGlobal(GVar, TM);
const MCSection *TheSection =
- getObjFileLowering().SectionForGlobal(GVar, Mang, TM);
+ getObjFileLowering().SectionForGlobal(GVar, GVKind, Mang, TM);
OutStreamer.SwitchSection(TheSection);
+ // Handle the zerofill directive on darwin, which is a special form of BSS
+ // emission.
+ if (GVKind.isBSS() && MAI->hasMachoZeroFillDirective()) {
+ TargetLoweringObjectFileMachO &TLOFMacho =
+ static_cast<TargetLoweringObjectFileMachO &>(getObjFileLowering());
+ if (TheSection == TLOFMacho.getDataCommonSection()) {
+ // .globl _foo
+ OutStreamer.EmitSymbolAttribute(GVarSym, MCStreamer::Global);
+ // .zerofill __DATA, __common, _foo, 400, 5
+ OutStreamer.EmitZerofill(TheSection, GVarSym, Size, 1 << Align);
+ return;
+ }
+ }
+
// FIXME: get this stuff from section kind flags.
if (C->isNullValue() && !GVar->hasSection() && !GVar->isThreadLocal() &&
// Don't put things that should go in the cstring section into "comm".
- !TheSection->getKind().isMergeableCString()) {
- if (GVar->hasExternalLinkage()) {
- if (const char *Directive = MAI->getZeroFillDirective()) {
- O << "\t.globl\t" << *GVarSym << "\n";
- O << Directive << "__DATA, __common, " << *GVarSym
- << ", " << Size << ", " << Align << "\n";
- return;
- }
- }
+ !TheSection->getKind().isMergeableCString() &&
+ (GVar->hasLocalLinkage() || GVar->isWeakForLinker())) {
+ if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it.
- if (GVar->hasLocalLinkage() || GVar->isWeakForLinker()) {
- if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it.
-
- if (isDarwin) {
- if (GVar->hasLocalLinkage()) {
- O << MAI->getLCOMMDirective() << *GVarSym << ',' << Size
- << ',' << Align;
- } else if (GVar->hasCommonLinkage()) {
- O << MAI->getCOMMDirective() << *GVarSym << ',' << Size
- << ',' << Align;
- } else {
- OutStreamer.SwitchSection(TheSection);
- O << "\t.globl " << *GVarSym << '\n' << MAI->getWeakDefDirective();
- O << *GVarSym << '\n';
- EmitAlignment(Align, GVar);
- O << *GVarSym << ":";
- if (VerboseAsm) {
- O.PadToColumn(MAI->getCommentColumn());
- O << MAI->getCommentString() << ' ';
- WriteAsOperand(O, GVar, /*PrintType=*/false, GVar->getParent());
- }
- O << '\n';
- EmitGlobalConstant(C);
- return;
- }
- } else if (MAI->getLCOMMDirective() != NULL) {
- if (GVar->hasLocalLinkage()) {
- O << MAI->getLCOMMDirective() << *GVarSym << "," << Size;
- } else {
- O << MAI->getCOMMDirective() << *GVarSym << "," << Size;
- if (MAI->getCOMMDirectiveTakesAlignment())
- O << ',' << (MAI->getAlignmentIsInBytes() ? (1 << Align) : Align);
+ if (isDarwin) {
+ if (GVar->hasLocalLinkage()) {
+ O << MAI->getLCOMMDirective() << *GVarSym << ',' << Size
+ << ',' << Align;
+ } else if (GVar->hasCommonLinkage()) {
+ O << MAI->getCOMMDirective() << *GVarSym << ',' << Size
+ << ',' << Align;
+ } else {
+ OutStreamer.SwitchSection(TheSection);
+ O << "\t.globl " << *GVarSym << '\n' << MAI->getWeakDefDirective();
+ O << *GVarSym << '\n';
+ EmitAlignment(Align, GVar);
+ O << *GVarSym << ":";
+ if (VerboseAsm) {
+ O.PadToColumn(MAI->getCommentColumn());
+ O << MAI->getCommentString() << ' ';
+ WriteAsOperand(O, GVar, /*PrintType=*/false, GVar->getParent());
}
+ O << '\n';
+ EmitGlobalConstant(C);
+ return;
+ }
+ } else if (MAI->getLCOMMDirective() != NULL) {
+ if (GVar->hasLocalLinkage()) {
+ O << MAI->getLCOMMDirective() << *GVarSym << "," << Size;
} else {
- if (GVar->hasLocalLinkage())
- O << "\t.local\t" << *GVarSym << '\n';
O << MAI->getCOMMDirective() << *GVarSym << "," << Size;
if (MAI->getCOMMDirectiveTakesAlignment())
- O << "," << (MAI->getAlignmentIsInBytes() ? (1 << Align) : Align);
- }
- if (VerboseAsm) {
- O.PadToColumn(MAI->getCommentColumn());
- O << MAI->getCommentString() << ' ';
- WriteAsOperand(O, GVar, /*PrintType=*/false, GVar->getParent());
+ O << ',' << (MAI->getAlignmentIsInBytes() ? (1 << Align) : Align);
}
- O << "\n";
- return;
+ } else {
+ if (GVar->hasLocalLinkage())
+ O << "\t.local\t" << *GVarSym << '\n';
+ O << MAI->getCOMMDirective() << *GVarSym << "," << Size;
+ if (MAI->getCOMMDirectiveTakesAlignment())
+ O << "," << (MAI->getAlignmentIsInBytes() ? (1 << Align) : Align);
+ }
+ if (VerboseAsm) {
+ O.PadToColumn(MAI->getCommentColumn());
+ O << MAI->getCommentString() << ' ';
+ WriteAsOperand(O, GVar, /*PrintType=*/false, GVar->getParent());
}
+ O << "\n";
+ return;
}
switch (GVar->getLinkage()) {
!GVar->hasSection() &&
(GVar->hasLocalLinkage() || GVar->hasExternalLinkage() ||
GVar->isWeakForLinker())) {
- if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it.
-
- if (GVar->hasExternalLinkage()) {
- O << "\t.global " << *GVarSym << '\n';
- O << "\t.type " << *GVarSym << ", @object\n";
- O << *GVarSym << ":\n";
- O << "\t.zero " << Size << '\n';
- } else if (GVar->hasLocalLinkage()) {
- O << MAI->getLCOMMDirective() << *GVarSym << ',' << Size;
- } else {
- O << ".comm " << *GVarSym << ',' << Size;
- }
- if (VerboseAsm) {
- O << "\t\t" << MAI->getCommentString() << " '";
- WriteAsOperand(O, GVar, /*PrintType=*/false, GVar->getParent());
- O << "'";
- }
- O << '\n';
- return;
+ if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it.
+
+ if (GVar->hasExternalLinkage()) {
+ O << "\t.global " << *GVarSym << '\n';
+ O << "\t.type " << *GVarSym << ", @object\n";
+ O << *GVarSym << ":\n";
+ O << "\t.zero " << Size << '\n';
+ } else if (GVar->hasLocalLinkage()) {
+ O << MAI->getLCOMMDirective() << *GVarSym << ',' << Size;
+ } else {
+ O << ".comm " << *GVarSym << ',' << Size;
+ }
+ if (VerboseAsm) {
+ O << "\t\t" << MAI->getCommentString() << " '";
+ WriteAsOperand(O, GVar, /*PrintType=*/false, GVar->getParent());
+ O << "'";
+ }
+ O << '\n';
+ return;
}
switch (GVar->getLinkage()) {
unsigned Size = TD->getTypeAllocSize(Type);
unsigned Align = TD->getPreferredAlignmentLog(GVar);
+ SectionKind GVKind = TargetLoweringObjectFile::getKindForGlobal(GVar, TM);
const MCSection *TheSection =
- getObjFileLowering().SectionForGlobal(GVar, Mang, TM);
+ getObjFileLowering().SectionForGlobal(GVar, GVKind, Mang, TM);
OutStreamer.SwitchSection(TheSection);
+ // Handle the zerofill directive on darwin, which is a special form of BSS
+ // emission.
+ if (GVKind.isBSS() && MAI->hasMachoZeroFillDirective()) {
+ TargetLoweringObjectFileMachO &TLOFMacho =
+ static_cast<TargetLoweringObjectFileMachO &>(getObjFileLowering());
+ if (TheSection == TLOFMacho.getDataCommonSection()) {
+ // .globl _foo
+ OutStreamer.EmitSymbolAttribute(GVarSym, MCStreamer::Global);
+ // .zerofill __DATA, __common, _foo, 400, 5
+ OutStreamer.EmitZerofill(TheSection, GVarSym, Size, 1 << Align);
+ return;
+ }
+ }
+
/// FIXME: Drive this off the section!
if (C->isNullValue() && /* FIXME: Verify correct */
!GVar->hasSection() &&
!TheSection->getKind().isMergeableCString()) {
if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it.
- if (GVar->hasExternalLinkage()) {
- O << "\t.globl " << *GVarSym << '\n';
- O << "\t.zerofill __DATA, __common, " << *GVarSym << ", "
- << Size << ", " << Align;
- } else if (GVar->hasLocalLinkage()) {
+ if (GVar->hasLocalLinkage()) {
O << MAI->getLCOMMDirective() << *GVarSym << ',' << Size << ',' << Align;
} else if (!GVar->hasCommonLinkage()) {
O << "\t.globl " << *GVarSym << '\n' << MAI->getWeakDefDirective();
ConstDataCoalSection
= getMachOSection("__DATA","__const_coal", MCSectionMachO::S_COALESCED,
SectionKind::getText());
+ DataCommonSection
+ = getMachOSection("__DATA","__common", MCSectionMachO::S_ZEROFILL,
+ SectionKind::getBSS());
ConstDataSection // .const_data
= getMachOSection("__DATA", "__const", 0,
SectionKind::getReadOnlyWithRel());
if (Kind.isReadOnlyWithRel())
return ConstDataSection;
+ // Put zero initialized globals with strong external linkage in the
+ // DATA, __common section with the .zerofill directive.
+ if (Kind.isBSS() && GV->hasExternalLinkage())
+ return DataCommonSection;
+
// Otherwise, just drop the variable in the normal data section.
return DataSection;
}
const TargetData *TD = TM.getTargetData();
- MCSymbol *GVSym = GetGlobalValueSymbol(GVar);
+ MCSymbol *GVarSym = GetGlobalValueSymbol(GVar);
Constant *C = GVar->getInitializer();
const Type *Type = C->getType();
unsigned Size = TD->getTypeAllocSize(Type);
unsigned Align = TD->getPreferredAlignmentLog(GVar);
- printVisibility(GVSym, GVar->getVisibility());
+ printVisibility(GVarSym, GVar->getVisibility());
if (Subtarget->isTargetELF())
- O << "\t.type\t" << *GVSym << ",@object\n";
+ O << "\t.type\t" << *GVarSym << ",@object\n";
SectionKind GVKind = TargetLoweringObjectFile::getKindForGlobal(GVar, TM);
const MCSection *TheSection =
getObjFileLowering().SectionForGlobal(GVar, GVKind, Mang, TM);
OutStreamer.SwitchSection(TheSection);
+ // Handle the zerofill directive on darwin, which is a special form of BSS
+ // emission.
+ if (GVKind.isBSS() && MAI->hasMachoZeroFillDirective()) {
+ TargetLoweringObjectFileMachO &TLOFMacho =
+ static_cast<TargetLoweringObjectFileMachO &>(getObjFileLowering());
+ if (TheSection == TLOFMacho.getDataCommonSection()) {
+ // .globl _foo
+ OutStreamer.EmitSymbolAttribute(GVarSym, MCStreamer::Global);
+ // .zerofill __DATA, __common, _foo, 400, 5
+ OutStreamer.EmitZerofill(TheSection, GVarSym, Size, 1 << Align);
+ return;
+ }
+ }
+
// FIXME: get this stuff from section kind flags.
if (C->isNullValue() && !GVar->hasSection() &&
// Don't put things that should go in the cstring section into "comm".
- !TheSection->getKind().isMergeableCString()) {
- if (GVar->hasExternalLinkage()) {
- if (MAI->hasZeroFillDirective()) {
- // .globl _foo
- OutStreamer.EmitSymbolAttribute(GVSym, MCStreamer::Global);
- // .zerofill __DATA, __common, _foo, 400, 5
- TargetLoweringObjectFileMachO &TLOFMacho =
- static_cast<TargetLoweringObjectFileMachO &>(getObjFileLowering());
- // FIXME: This stuff should already be handled by SectionForGlobal!
- const MCSection *TheSection =
- TLOFMacho.getMachOSection("__DATA", "__common",
- MCSectionMachO::S_ZEROFILL,
- SectionKind::getBSS());
-
- OutStreamer.EmitZerofill(TheSection, GVSym, Size, 1 << Align);
- return;
- }
- }
-
- if (!GVar->isThreadLocal() &&
- (GVar->hasLocalLinkage() || GVar->isWeakForLinker())) {
- if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it.
-
- if (MAI->getLCOMMDirective() != NULL) {
- if (GVar->hasLocalLinkage()) {
- O << MAI->getLCOMMDirective() << *GVSym << ',' << Size;
- if (Subtarget->isTargetDarwin())
- O << ',' << Align;
- } else if (Subtarget->isTargetDarwin() && !GVar->hasCommonLinkage()) {
- OutStreamer.EmitSymbolAttribute(GVSym, MCStreamer::Global);
- O << MAI->getWeakDefDirective() << *GVSym << '\n';
- EmitAlignment(Align, GVar);
- O << *GVSym << ":";
- if (VerboseAsm) {
- O.PadToColumn(MAI->getCommentColumn());
- O << MAI->getCommentString() << ' ';
- WriteAsOperand(O, GVar, /*PrintType=*/false, GVar->getParent());
- }
- O << '\n';
- EmitGlobalConstant(C);
- return;
- } else {
- O << MAI->getCOMMDirective() << *GVSym << ',' << Size;
- if (MAI->getCOMMDirectiveTakesAlignment())
- O << ',' << (MAI->getAlignmentIsInBytes() ? (1 << Align) : Align);
+ !TheSection->getKind().isMergeableCString() &&
+ !GVar->isThreadLocal() &&
+ (GVar->hasLocalLinkage() || GVar->isWeakForLinker())) {
+ if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it.
+
+ if (const char *LComm = MAI->getLCOMMDirective()) {
+ if (GVar->hasLocalLinkage()) {
+ O << LComm << *GVarSym << ',' << Size;
+ if (Subtarget->isTargetDarwin())
+ O << ',' << Align;
+ } else if (Subtarget->isTargetDarwin() && !GVar->hasCommonLinkage()) {
+ OutStreamer.EmitSymbolAttribute(GVarSym, MCStreamer::Global);
+ O << MAI->getWeakDefDirective() << *GVarSym << '\n';
+ EmitAlignment(Align, GVar);
+ O << *GVarSym << ":";
+ if (VerboseAsm) {
+ O.PadToColumn(MAI->getCommentColumn());
+ O << MAI->getCommentString() << ' ';
+ WriteAsOperand(O, GVar, /*PrintType=*/false, GVar->getParent());
}
+ O << '\n';
+ EmitGlobalConstant(C);
+ return;
} else {
- if (!Subtarget->isTargetCygMing()) {
- if (GVar->hasLocalLinkage())
- O << "\t.local\t" << *GVSym << '\n';
- }
- O << MAI->getCOMMDirective() << *GVSym << ',' << Size;
+ O << MAI->getCOMMDirective() << *GVarSym << ',' << Size;
if (MAI->getCOMMDirectiveTakesAlignment())
O << ',' << (MAI->getAlignmentIsInBytes() ? (1 << Align) : Align);
}
- if (VerboseAsm) {
- O.PadToColumn(MAI->getCommentColumn());
- O << MAI->getCommentString() << ' ';
- WriteAsOperand(O, GVar, /*PrintType=*/false, GVar->getParent());
+ } else {
+ if (!Subtarget->isTargetCygMing()) {
+ if (GVar->hasLocalLinkage())
+ O << "\t.local\t" << *GVarSym << '\n';
}
- O << '\n';
- return;
+ O << MAI->getCOMMDirective() << *GVarSym << ',' << Size;
+ if (MAI->getCOMMDirectiveTakesAlignment())
+ O << ',' << (MAI->getAlignmentIsInBytes() ? (1 << Align) : Align);
+ }
+ if (VerboseAsm) {
+ O.PadToColumn(MAI->getCommentColumn());
+ O << MAI->getCommentString() << ' ';
+ WriteAsOperand(O, GVar, /*PrintType=*/false, GVar->getParent());
}
+ O << '\n';
+ return;
}
switch (GVar->getLinkage()) {
case GlobalValue::WeakODRLinkage:
case GlobalValue::LinkerPrivateLinkage:
if (Subtarget->isTargetDarwin()) {
- OutStreamer.EmitSymbolAttribute(GVSym, MCStreamer::Global);
- O << MAI->getWeakDefDirective() << *GVSym << '\n';
+ OutStreamer.EmitSymbolAttribute(GVarSym, MCStreamer::Global);
+ O << MAI->getWeakDefDirective() << *GVarSym << '\n';
} else if (Subtarget->isTargetCygMing()) {
- OutStreamer.EmitSymbolAttribute(GVSym, MCStreamer::Global);
+ OutStreamer.EmitSymbolAttribute(GVarSym, MCStreamer::Global);
O << "\t.linkonce same_size\n";
} else
- O << "\t.weak\t" << *GVSym << '\n';
+ O << "\t.weak\t" << *GVarSym << '\n';
break;
case GlobalValue::DLLExportLinkage:
case GlobalValue::AppendingLinkage:
// their name or something. For now, just emit them as external.
case GlobalValue::ExternalLinkage:
// If external or appending, declare as a global symbol
- OutStreamer.EmitSymbolAttribute(GVSym, MCStreamer::Global);
+ OutStreamer.EmitSymbolAttribute(GVarSym, MCStreamer::Global);
break;
case GlobalValue::PrivateLinkage:
case GlobalValue::InternalLinkage:
}
EmitAlignment(Align, GVar);
- O << *GVSym << ":";
+ O << *GVarSym << ":";
if (VerboseAsm){
O.PadToColumn(MAI->getCommentColumn());
O << MAI->getCommentString() << ' ';
EmitGlobalConstant(C);
if (MAI->hasDotTypeDotSizeDirective())
- O << "\t.size\t" << *GVSym << ", " << Size << '\n';
+ O << "\t.size\t" << *GVarSym << ", " << Size << '\n';
}
void X86AsmPrinter::EmitEndOfAsmFile(Module &M) {