Index: llvm/include/llvm/CodeGen/AsmPrinter.h =================================================================== --- llvm/include/llvm/CodeGen/AsmPrinter.h +++ llvm/include/llvm/CodeGen/AsmPrinter.h @@ -635,6 +635,11 @@ /// supported by the target. void EmitLinkage(const GlobalValue *GV, MCSymbol *GVSym) const; + /// Return the alignment in log2 form for the specified \p GV. + static unsigned getGVAlignmentLog2(const GlobalValue *GV, + const DataLayout &DL, + unsigned InBits = 0); + private: /// Private state for PrintSpecial() // Assign a unique ID to this machine instruction. Index: llvm/include/llvm/MC/MCAsmInfo.h =================================================================== --- llvm/include/llvm/MC/MCAsmInfo.h +++ llvm/include/llvm/MC/MCAsmInfo.h @@ -165,6 +165,10 @@ /// instead. bool UseDataRegionDirectives = false; + /// True if .align is to be used for alignment. Only power-of-two + /// alignment is supported. + bool UseDotAlignForAlignment = false; + //===--- Data Emission Directives -------------------------------------===// /// This should be set to the directive used to get some number of zero bytes @@ -520,6 +524,10 @@ return UseDataRegionDirectives; } + bool useDotAlignForAlignment() const { + return UseDotAlignForAlignment; + } + const char *getZeroDirective() const { return ZeroDirective; } const char *getAsciiDirective() const { return AsciiDirective; } const char *getAscizDirective() const { return AscizDirective; } Index: llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp =================================================================== --- llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -162,8 +162,9 @@ /// getGVAlignmentLog2 - Return the alignment to use for the specified global /// value in log2 form. This rounds up to the preferred alignment if possible /// and legal. -static unsigned getGVAlignmentLog2(const GlobalValue *GV, const DataLayout &DL, - unsigned InBits = 0) { +unsigned AsmPrinter::getGVAlignmentLog2(const GlobalValue *GV, + const DataLayout &DL, + unsigned InBits) { unsigned NumBits = 0; if (const GlobalVariable *GVar = dyn_cast(GV)) NumBits = DL.getPreferredAlignmentLog(GVar); Index: llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp =================================================================== --- llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp +++ llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp @@ -1849,6 +1849,9 @@ if (Kind.isText()) return TextSection; + if (Kind.isData()) + return DataSection; + report_fatal_error("XCOFF other section types not yet implemented."); } Index: llvm/lib/MC/MCAsmInfoXCOFF.cpp =================================================================== --- llvm/lib/MC/MCAsmInfoXCOFF.cpp +++ llvm/lib/MC/MCAsmInfoXCOFF.cpp @@ -17,4 +17,8 @@ HasDotTypeDotSizeDirective = false; COMMDirectiveAlignmentIsInBytes = false; LCOMMDirectiveAlignmentType = LCOMM::Log2Alignment; + UseDotAlignForAlignment = true; + AsciiDirective = nullptr; // not supported + AscizDirective = nullptr; // not supported + Data64bitsDirective = "\t.llong\t"; } Index: llvm/lib/MC/MCAsmStreamer.cpp =================================================================== --- llvm/lib/MC/MCAsmStreamer.cpp +++ llvm/lib/MC/MCAsmStreamer.cpp @@ -1119,6 +1119,16 @@ void MCAsmStreamer::EmitValueToAlignment(unsigned ByteAlignment, int64_t Value, unsigned ValueSize, unsigned MaxBytesToEmit) { + if (MAI->useDotAlignForAlignment()) { + if (!isPowerOf2_32(ByteAlignment)) + report_fatal_error("Only power-of-two alignments are supported " + "with .align."); + OS << "\t.align\t"; + OS << Log2_32(ByteAlignment); + EmitEOL(); + return; + } + // Some assemblers don't support non-power of two alignments, so we always // emit alignments as a power of two if possible. if (isPowerOf2_32(ByteAlignment)) { Index: llvm/lib/MC/MCObjectFileInfo.cpp =================================================================== --- llvm/lib/MC/MCObjectFileInfo.cpp +++ llvm/lib/MC/MCObjectFileInfo.cpp @@ -770,6 +770,10 @@ TextSection = Ctx->getXCOFFSection( ".text", XCOFF::StorageMappingClass::XMC_PR, XCOFF::XTY_SD, XCOFF::C_HIDEXT, SectionKind::getText()); + + DataSection = Ctx->getXCOFFSection( + ".data", XCOFF::StorageMappingClass::XMC_RW, XCOFF::XTY_SD, + XCOFF::C_HIDEXT, SectionKind::getData()); } void MCObjectFileInfo::InitMCObjectFileInfo(const Triple &TheTriple, bool PIC, Index: llvm/lib/MC/MCSectionXCOFF.cpp =================================================================== --- llvm/lib/MC/MCSectionXCOFF.cpp +++ llvm/lib/MC/MCSectionXCOFF.cpp @@ -28,6 +28,16 @@ return; } + if (getKind().isData()) { + assert(getMappingClass() == XCOFF::XMC_RW && + "Unhandled storage-mapping class for data section."); + + OS << "\t.csect " << getSectionName() << "[" + << "RW" + << "]" << '\n'; + return; + } + if (getKind().isBSSLocal() || getKind().isCommon()) { assert((getMappingClass() == XCOFF::XMC_RW || getMappingClass() == XCOFF::XMC_BS) && Index: llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp =================================================================== --- llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp +++ llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp @@ -1659,8 +1659,9 @@ report_fatal_error("COMDAT not yet supported by AIX."); SectionKind GVKind = getObjFileLowering().getKindForGlobal(GV, TM); - if (!GVKind.isCommon() && !GVKind.isBSSLocal()) - report_fatal_error("Only common variables are supported on AIX for now."); + if (!GVKind.isCommon() && !GVKind.isBSSLocal() && !GVKind.isData()) + report_fatal_error("Encountered a global variable kind that is " + "not supported yet."); // Create the containing csect and switch to it. MCSectionXCOFF *CSect = cast( @@ -1668,20 +1669,34 @@ OutStreamer->SwitchSection(CSect); // Create the symbol, set its storage class, and emit it. - MCSymbolXCOFF *XSym = cast(getSymbol(GV)); - XSym->setStorageClass( + MCSymbolXCOFF *GVSym = cast(getSymbol(GV)); + GVSym->setStorageClass( TargetLoweringObjectFileXCOFF::getStorageClassForGlobal(GV)); - XSym->setContainingCsect(CSect); + GVSym->setContainingCsect(CSect); const DataLayout &DL = GV->getParent()->getDataLayout(); - unsigned Align = + + // Handle common symbols. + if (GVKind.isCommon() || GVKind.isBSSLocal()) { + unsigned Align = GV->getAlignment() ? GV->getAlignment() : DL.getPreferredAlignment(GV); - uint64_t Size = DL.getTypeAllocSize(GV->getType()->getElementType()); + uint64_t Size = DL.getTypeAllocSize(GV->getType()->getElementType()); + + if (GVKind.isBSSLocal()) + OutStreamer->EmitXCOFFLocalCommonSymbol(GVSym, Size, Align); + else + OutStreamer->EmitCommonSymbol(GVSym, Size, Align); + return; + } + + // Get the alignment in the log2 form. + const unsigned AlignLog = getGVAlignmentLog2(GV, DL); - if (GVKind.isBSSLocal()) - OutStreamer->EmitXCOFFLocalCommonSymbol(XSym, Size, Align); - else - OutStreamer->EmitCommonSymbol(XSym, Size, Align); + MCSymbol *EmittedInitSym = GVSym; + EmitLinkage(GV, EmittedInitSym); + EmitAlignment(AlignLog, GV); + OutStreamer->EmitLabel(EmittedInitSym); + EmitGlobalConstant(GV->getParent()->getDataLayout(), GV->getInitializer()); } /// createPPCAsmPrinterPass - Returns a pass that prints the PPC assembly code Index: llvm/test/CodeGen/PowerPC/aix-xcoff-data.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/PowerPC/aix-xcoff-data.ll @@ -0,0 +1,57 @@ +; RUN: llc -mtriple powerpc-ibm-aix-xcoff < %s | FileCheck %s +; RUN: llc -mtriple powerpc64-ibm-aix-xcoff < %s | FileCheck %s + +@ivar = local_unnamed_addr global i32 35, align 4 +@llvar = local_unnamed_addr global i64 36, align 8 +@svar = local_unnamed_addr global i16 37, align 2 +@fvar = local_unnamed_addr global float 8.000000e+02, align 4 +@dvar = local_unnamed_addr global double 9.000000e+02, align 8 +@over_aligned = local_unnamed_addr global double 9.000000e+02, align 32 +@charr = local_unnamed_addr global [4 x i8] c"abcd", align 1 +@dblarr = local_unnamed_addr global [4 x double] [double 1.000000e+00, double 2.000000e+00, double 3.000000e+00, double 4.000000e+00], align 8 + +; CHECK: .csect .data[RW] +; CHECK-NEXT: .globl ivar +; CHECK-NEXT: .align 2 +; CHECK-NEXT: ivar: +; CHECK-NEXT: .long 35 + +; CHECK: .globl llvar +; CHECK-NEXT: .align 3 +; CHECK-NEXT: llvar: +; CHECK-NEXT: .llong 36 + +; CHECK: .globl svar +; CHECK-NEXT: .align 1 +; CHECK-NEXT: svar: +; CHECK-NEXT: .short 37 + +; CHECK: .globl fvar +; CHECK-NEXT: .align 2 +; CHECK-NEXT: fvar: +; CHECK-NEXT: .long 1145569280 + +; CHECK: .globl dvar +; CHECK-NEXT: .align 3 +; CHECK-NEXT: dvar: +; CHECK-NEXT: .llong 4651127699538968576 + +; CHECK: .globl over_aligned +; CHECK-NEXT: .align 5 +; CHECK-NEXT: over_aligned: +; CHECK-NEXT: .llong 4651127699538968576 + +; CHECK: .globl charr +; CHECK-NEXT: charr: +; CHECK-NEXT: .byte 97 +; CHECK-NEXT: .byte 98 +; CHECK-NEXT: .byte 99 +; CHECK-NEXT: .byte 100 + +; CHECK: .globl dblarr +; CHECK-NEXT: .align 3 +; CHECK-NEXT: dblarr: +; CHECK-NEXT: .llong 4607182418800017408 +; CHECK-NEXT: .llong 4611686018427387904 +; CHECK-NEXT: .llong 4613937818241073152 +; CHECK-NEXT: .llong 4616189618054758400