Summary:
This patch enable assembly output of local commons for AIX using .lcomm
directives. Adds a EmitXCOFFLocalCommonSymbol to MCStreamer so we can emit the
AIX version of .lcomm assembly directives which include a csect name. Handle the
case of BSS locals in PPCAIXAsmPrinter by using EmitXCOFFLocalCommonSymbol. Adds
a test for generating .lcomm on AIX Targets.
Reviewers: cebowleratibm, hubert.reinterpretcast, Xiangling_L, jasonliu, sfertile
Reviewed By: sfertile
Subscribers: wuzish, nemanjai, hiraditya, kbarton, MaskRay, jsji, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D64825
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@368306
91177308-0d34-0410-b5e6-
96231b3b80d8
/// \param Symbol - Symbol the image relative relocation should point to.
virtual void EmitCOFFImgRel32(MCSymbol const *Symbol, int64_t Offset);
+ /// Emits an lcomm directive with XCOFF csect information.
+ ///
+ /// \param Symbol - The symbol we are emiting.
+ /// \param Size - The size of the block of storage.
+ /// \param ByteAlignment - The alignment of the symbol in bytes. Must be a power
+ /// of 2.
+ virtual void EmitXCOFFLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
+ unsigned ByteAlignment);
+
/// Emit an ELF .size directive.
///
/// This corresponds to an assembler statement such as:
uint64_t Size = 0, unsigned ByteAlignment = 0,
SMLoc Loc = SMLoc()) override;
void EmitInstToData(const MCInst &Inst, const MCSubtargetInfo &) override;
+ void EmitXCOFFLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
+ unsigned ByteAlign) override;
};
} // end namespace llvm
// Common symbols go into a csect with matching name which will get mapped
// into the .bss section.
- if (Kind.isCommon()) {
+ if (Kind.isBSSLocal() || Kind.isCommon()) {
SmallString<128> Name;
getNameWithPrefix(Name, GO, TM);
- return getContext().getXCOFFSection(Name, XCOFF::XMC_RW, XCOFF::XTY_CM,
- Kind, /* BeginSymbolName */ nullptr);
+ return getContext().getXCOFFSection(
+ Name, Kind.isBSSLocal() ? XCOFF::XMC_BS : XCOFF::XMC_RW, XCOFF::XTY_CM,
+ Kind, /* BeginSymbolName */ nullptr);
}
if (Kind.isText())
IsLittleEndian = false;
HasDotTypeDotSizeDirective = false;
COMMDirectiveAlignmentIsInBytes = false;
+ LCOMMDirectiveAlignmentType = LCOMM::Log2Alignment;
}
void EmitCOFFSectionIndex(MCSymbol const *Symbol) override;
void EmitCOFFSecRel32(MCSymbol const *Symbol, uint64_t Offset) override;
void EmitCOFFImgRel32(MCSymbol const *Symbol, int64_t Offset) override;
+ void EmitXCOFFLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
+ unsigned ByteAlign) override;
void emitELFSize(MCSymbol *Symbol, const MCExpr *Value) override;
void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
unsigned ByteAlignment) override;
EmitEOL();
}
+// We need an XCOFF specific version of this directive as the AIX syntax
+// requires a QualName argument identifying the csect name and storage mapping
+// class to appear before the alignment if we are specifying it.
+void MCAsmStreamer::EmitXCOFFLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
+ unsigned ByteAlignment) {
+ assert(MAI->getLCOMMDirectiveAlignmentType() == LCOMM::Log2Alignment &&
+ "We only support writing log base-2 alignment format with XCOFF");
+ assert(isPowerOf2_32(ByteAlignment) && "alignment must be a power of 2");
+
+ OS << "\t.lcomm\t";
+ Symbol->print(OS, MAI);
+ OS << ',' << Size;
+ OS << ',' << Symbol->getName();
+ OS << ',' << Log2_32(ByteAlignment);
+
+ EmitEOL();
+}
+
void MCAsmStreamer::emitELFSize(MCSymbol *Symbol, const MCExpr *Value) {
assert(MAI->hasDotTypeDotSizeDirective());
OS << "\t.size\t";
return;
}
- if (getKind().isCommon()) {
- if (getMappingClass() != XCOFF::XMC_RW)
- llvm_unreachable("Unsupported storage-mapping class for common csect");
+ if (getKind().isBSSLocal() || getKind().isCommon()) {
+ if (getMappingClass() != XCOFF::XMC_RW &&
+ getMappingClass() != XCOFF::XMC_BS)
+ llvm_unreachable("Generated a storage-mapping class for a common/bss "
+ "csect we don't understand how to switch to.");
if (getCSectType() != XCOFF::XTY_CM)
llvm_unreachable("wrong csect type for .bss csect");
// Don't have to print a directive for switching to section for commons.
void MCStreamer::EmitCOFFSymbolType(int Type) {
llvm_unreachable("this directive only supported on COFF targets");
}
+void MCStreamer::EmitXCOFFLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
+ unsigned ByteAlign) {
+ llvm_unreachable("this directive only supported on XCOFF targets");
+}
void MCStreamer::emitELFSize(MCSymbol *Symbol, const MCExpr *Value) {}
void MCStreamer::emitELFSymverDirective(StringRef AliasName,
const MCSymbol *Aliasee) {}
S->getAssembler().setRelaxAll(true);
return S;
}
+
+void MCXCOFFStreamer::EmitXCOFFLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
+ unsigned ByteAlign) {
+ llvm_unreachable("Not implemented yet.");
+}
\ No newline at end of file
report_fatal_error("COMDAT not yet supported by AIX.");
SectionKind GVKind = getObjFileLowering().getKindForGlobal(GV, TM);
- if (!GVKind.isCommon())
+ if (!GVKind.isCommon() && !GVKind.isBSSLocal())
report_fatal_error("Only common variables are supported on AIX for now.");
// Create the containing csect and switch to it.
unsigned Align =
GV->getAlignment() ? GV->getAlignment() : DL.getPreferredAlignment(GV);
uint64_t Size = DL.getTypeAllocSize(GV->getType()->getElementType());
- OutStreamer->EmitCommonSymbol(XSym, Size, Align);
+
+ if (GVKind.isBSSLocal())
+ OutStreamer->EmitXCOFFLocalCommonSymbol(XSym, Size, Align);
+ else
+ OutStreamer->EmitCommonSymbol(XSym, Size, Align);
}
/// createPPCAsmPrinterPass - Returns a pass that prints the PPC assembly code
--- /dev/null
+; RUN: llc -mtriple powerpc-ibm-aix-xcoff < %s | FileCheck %s
+; RUN: llc -mtriple powerpc64-ibm-aix-xcoff < %s | FileCheck %s
+
+@a = internal global i32 0, align 4
+@b = internal global i64 0, align 8
+@c = internal global i16 0, align 2
+
+; CHECK: .lcomm a,4,a,2
+; CHECK-NEXT: .lcomm b,8,b,3
+; CHECK-NEXT: .lcomm c,2,c,1