diff --git a/llvm/include/llvm/MC/MCSectionXCOFF.h b/llvm/include/llvm/MC/MCSectionXCOFF.h --- a/llvm/include/llvm/MC/MCSectionXCOFF.h +++ b/llvm/include/llvm/MC/MCSectionXCOFF.h @@ -36,6 +36,7 @@ XCOFF::SymbolType Type; XCOFF::StorageClass StorageClass; MCSymbolXCOFF *const QualName; + static constexpr unsigned DefaultAlignVal = 4; MCSectionXCOFF(StringRef Name, XCOFF::StorageMappingClass SMC, XCOFF::SymbolType ST, XCOFF::StorageClass SC, SectionKind K, @@ -47,8 +48,13 @@ assert(QualName != nullptr && "QualName is needed."); QualName->setStorageClass(SC); QualName->setRepresentedCsect(this); + // A csect is 4 byte aligned by default, except for undefined symbol csects. + if (Type != XCOFF::XTY_ER) + setAlignment(Align(DefaultAlignVal)); } + void printCsectDirective(raw_ostream &OS) const; + public: ~MCSectionXCOFF(); diff --git a/llvm/lib/MC/MCSectionXCOFF.cpp b/llvm/lib/MC/MCSectionXCOFF.cpp --- a/llvm/lib/MC/MCSectionXCOFF.cpp +++ b/llvm/lib/MC/MCSectionXCOFF.cpp @@ -15,6 +15,10 @@ MCSectionXCOFF::~MCSectionXCOFF() = default; +void MCSectionXCOFF::printCsectDirective(raw_ostream &OS) const { + OS << "\t.csect " << QualName->getName() << ", " << Log2_32(getAlignment()) + << '\n'; +} void MCSectionXCOFF::PrintSwitchToSection(const MCAsmInfo &MAI, const Triple &T, raw_ostream &OS, @@ -23,14 +27,14 @@ if (getMappingClass() != XCOFF::XMC_PR) report_fatal_error("Unhandled storage-mapping class for .text csect"); - OS << "\t.csect " << QualName->getName() << '\n'; + printCsectDirective(OS); return; } if (getKind().isReadOnly()) { if (getMappingClass() != XCOFF::XMC_RO) report_fatal_error("Unhandled storage-mapping class for .rodata csect."); - OS << "\t.csect " << QualName->getName() << '\n'; + printCsectDirective(OS); return; } @@ -38,7 +42,7 @@ switch (getMappingClass()) { case XCOFF::XMC_RW: case XCOFF::XMC_DS: - OS << "\t.csect " << QualName->getName() << '\n'; + printCsectDirective(OS); break; case XCOFF::XMC_TC: break; diff --git a/llvm/lib/MC/MCXCOFFStreamer.cpp b/llvm/lib/MC/MCXCOFFStreamer.cpp --- a/llvm/lib/MC/MCXCOFFStreamer.cpp +++ b/llvm/lib/MC/MCXCOFFStreamer.cpp @@ -16,6 +16,7 @@ #include "llvm/MC/MCCodeEmitter.h" #include "llvm/MC/MCDirectives.h" #include "llvm/MC/MCObjectWriter.h" +#include "llvm/MC/MCSectionXCOFF.h" #include "llvm/MC/MCSymbolXCOFF.h" #include "llvm/Support/TargetRegistry.h" @@ -60,6 +61,11 @@ XCOFF::C_HIDEXT); Symbol->setCommon(Size, ByteAlignment); + // Default csect align is 4, but common symbols have explicit alignment values + // and we should honor it. + cast(Symbol)->getRepresentedCsect()->setAlignment( + Align(ByteAlignment)); + // Emit the alignment and storage for the variable to the section. emitValueToAlignment(ByteAlignment); emitZeros(Size); diff --git a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp --- a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp +++ b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp @@ -159,13 +159,7 @@ StringRef getPassName() const override { return "AIX PPC Assembly Printer"; } - bool doInitialization(Module &M) override { - if (M.alias_size() > 0u) - report_fatal_error( - "module has aliases, which LLVM does not yet support for AIX"); - - return PPCAsmPrinter::doInitialization(M); - } + bool doInitialization(Module &M) override; void SetupMachineFunction(MachineFunction &MF) override; @@ -1725,6 +1719,39 @@ } } +bool PPCAIXAsmPrinter::doInitialization(Module &M) { + if (M.alias_size() > 0u) + report_fatal_error( + "module has aliases, which LLVM does not yet support for AIX"); + + const bool Result = PPCAsmPrinter::doInitialization(M); + + auto setCsectAlignment = [this](const GlobalObject *GO) { + // Declarations have 0 alignment which is set by default. + if (GO->isDeclaration()) + return; + + SectionKind GOKind = getObjFileLowering().getKindForGlobal(GO, TM); + MCSectionXCOFF *Csect = cast( + getObjFileLowering().SectionForGlobal(GO, GOKind, TM)); + + Align GOAlign = getGVAlignment(GO, GO->getParent()->getDataLayout()); + if (GOAlign > Csect->getAlignment()) + Csect->setAlignment(GOAlign); + }; + + // We need to know, up front, the alignment of csects for the assembly path, + // because once a .csect directive gets emitted, we could not change the + // alignment value on it. + for (const auto &G : M.globals()) + setCsectAlignment(&G); + + for (const auto &F : M) + setCsectAlignment(&F); + + return Result; +} + /// createPPCAsmPrinterPass - Returns a pass that prints the PPC assembly code /// for a MachineFunction to the given output stream, in a format that the /// Darwin assembler can deal with. diff --git a/llvm/test/CodeGen/PowerPC/aix-lower-constant-pool-index.ll b/llvm/test/CodeGen/PowerPC/aix-lower-constant-pool-index.ll --- a/llvm/test/CodeGen/PowerPC/aix-lower-constant-pool-index.ll +++ b/llvm/test/CodeGen/PowerPC/aix-lower-constant-pool-index.ll @@ -45,7 +45,7 @@ ; 64LARGE-MIR: renamable $x[[REG2:[0-9]+]] = LDtocL %const.0, killed renamable $x[[REG1]], implicit $x2 :: (load 8 from got) ; 64LARGE-MIR: renamable $f[[REG3:[0-9]+]] = LFS 0, killed renamable $x[[REG2]] :: (load 4 from constant-pool) -; 32SMALL-ASM: .csect .rodata[RO] +; 32SMALL-ASM: .csect .rodata[RO], 2 ; 32SMALL-ASM: .align 2 ; 32SMALL-ASM: .LCPI0_0: ; 32SMALL-ASM: .long 0x40b00000 @@ -54,7 +54,7 @@ ; 32SMALL-ASM: lfs 1, 0([[REG1]]) ; 32SMALL-ASM: blr -; 32LARGE-ASM: .csect .rodata[RO] +; 32LARGE-ASM: .csect .rodata[RO], 2 ; 32LARGE-ASM: .align 2 ; 32LARGE-ASM: .LCPI0_0: ; 32LARGE-ASM: .long 0x40b00000 @@ -64,7 +64,7 @@ ; 32LARGE-ASM: lfs 1, 0([[REG2]]) ; 32LARGE-ASM: blr -; 64SMALL-ASM: .csect .rodata[RO] +; 64SMALL-ASM: .csect .rodata[RO], 2 ; 64SMALL-ASM: .align 2 ; 64SMALL-ASM: .LCPI0_0: ; 64SMALL-ASM: .long 0x40b00000 @@ -73,7 +73,7 @@ ; 64SMALL-ASM: lfs 1, 0([[REG1]]) ; 64SMALL-ASM: blr -; 64LARGE-ASM: .csect .rodata[RO] +; 64LARGE-ASM: .csect .rodata[RO], 2 ; 64LARGE-ASM: .align 2 ; 64LARGE-ASM: .LCPI0_0: ; 64LARGE-ASM: .long 0x40b00000 diff --git a/llvm/test/CodeGen/PowerPC/aix-lower-jump-table.ll b/llvm/test/CodeGen/PowerPC/aix-lower-jump-table.ll --- a/llvm/test/CodeGen/PowerPC/aix-lower-jump-table.ll +++ b/llvm/test/CodeGen/PowerPC/aix-lower-jump-table.ll @@ -96,7 +96,7 @@ ; 32SMALL-ASM: LBB0_6: ; 32SMALL-ASM: li 3, 0 ; 32SMALL-ASM: blr -; 32SMALL-ASM: .csect .rodata[RO] +; 32SMALL-ASM: .csect .rodata[RO], 2 ; 32SMALL-ASM: .align 2 ; 32SMALL-ASM: .LJTI0_0: ; 32SMALL-ASM: .long LBB0_2-.LJTI0_0 @@ -123,7 +123,7 @@ ; 32LARGE-ASM: LBB0_6: ; 32LARGE-ASM: li 3, 0 ; 32LARGE-ASM: blr -; 32LARGE-ASM: .csect .rodata[RO] +; 32LARGE-ASM: .csect .rodata[RO], 2 ; 32LARGE-ASM: .align 2 ; 32LARGE-ASM: .LJTI0_0: ; 32LARGE-ASM: .long LBB0_2-.LJTI0_0 @@ -149,7 +149,7 @@ ; 64SMALL-ASM: LBB0_6: ; 64SMALL-ASM: li 3, 0 ; 64SMALL-ASM: blr -; 64SMALL-ASM: .csect .rodata[RO] +; 64SMALL-ASM: .csect .rodata[RO], 2 ; 64SMALL-ASM: .align 2 ; 64SMALL-ASM: .LJTI0_0: ; 64SMALL-ASM: .long LBB0_2-.LJTI0_0 @@ -176,7 +176,7 @@ ; 64LARGE-ASM: LBB0_6: ; 64LARGE-ASM: li 3, 0 ; 64LARGE-ASM: blr -; 64LARGE-ASM: .csect .rodata[RO] +; 64LARGE-ASM: .csect .rodata[RO], 2 ; 64LARGE-ASM: .align 2 ; 64LARGE-ASM: .LJTI0_0: ; 64LARGE-ASM: .long LBB0_2-.LJTI0_0 diff --git a/llvm/test/CodeGen/PowerPC/aix-readonly-with-relocation.ll b/llvm/test/CodeGen/PowerPC/aix-readonly-with-relocation.ll --- a/llvm/test/CodeGen/PowerPC/aix-readonly-with-relocation.ll +++ b/llvm/test/CodeGen/PowerPC/aix-readonly-with-relocation.ll @@ -5,14 +5,14 @@ @b = constant i32* @a ;CHECK: .comm a[RW],4,2 -;CHECK-NEXT: .csect .data[RW] +;CHECK-NEXT: .csect .data[RW], 2 ;CHECK-NEXT: .globl b ;CHECK-NEXT: .align 2 ;CHECK-NEXT: b: ;CHECK-NEXT: .long a ;CHECK64: .comm a[RW],4,2 -;CHECK64-NEXT: .csect .data[RW] +;CHECK64-NEXT: .csect .data[RW], 3 ;CHECK64-NEXT: .globl b ;CHECK64-NEXT: .align 3 ;CHECK64-NEXT: b: diff --git a/llvm/test/CodeGen/PowerPC/aix-reference-func-addr-const.ll b/llvm/test/CodeGen/PowerPC/aix-reference-func-addr-const.ll --- a/llvm/test/CodeGen/PowerPC/aix-reference-func-addr-const.ll +++ b/llvm/test/CodeGen/PowerPC/aix-reference-func-addr-const.ll @@ -11,7 +11,7 @@ } -;CHECK: .csect .data[RW] +;CHECK: .csect .data[RW], 2 ;CHECK-NEXT: .globl foo_ptr ;CHECK-NEXT: .align 2 ;CHECK-NEXT: foo_ptr: @@ -22,7 +22,7 @@ ;CHECK-NEXT: .long bar[DS] ;CHECK-NEXT: .extern foo[DS] -;CHECK64: .csect .data[RW] +;CHECK64: .csect .data[RW], 3 ;CHECK64-NEXT: .globl foo_ptr ;CHECK64-NEXT: .align 3 ;CHECK64-NEXT: foo_ptr: diff --git a/llvm/test/CodeGen/PowerPC/aix-xcoff-data.ll b/llvm/test/CodeGen/PowerPC/aix-xcoff-data.ll --- a/llvm/test/CodeGen/PowerPC/aix-xcoff-data.ll +++ b/llvm/test/CodeGen/PowerPC/aix-xcoff-data.ll @@ -38,10 +38,10 @@ ; CHECK-NOT: .toc -; CHECK: .csect .text[PR] +; CHECK: .csect .text[PR], 2 ; CHECK-NEXT: .file -; CHECK: .csect .data[RW] +; CHECK: .csect .data[RW], 5 ; CHECK-NEXT: .globl ivar ; CHECK-NEXT: .align 2 ; CHECK-NEXT: ivar: @@ -186,7 +186,7 @@ ; SYMS-NEXT: SectionLen: 0 ; SYMS-NEXT: ParameterHashIndex: 0x0 ; SYMS-NEXT: TypeChkSectNum: 0x0 -; SYMS-NEXT: SymbolAlignmentLog2: 0 +; SYMS-NEXT: SymbolAlignmentLog2: 2 ; SYMS-NEXT: SymbolType: XTY_SD (0x1) ; SYMS-NEXT: StorageMappingClass: XMC_PR (0x0) ; SYMS-NEXT: StabInfoIndex: 0x0 diff --git a/llvm/test/CodeGen/PowerPC/aix-xcoff-lower-comm.ll b/llvm/test/CodeGen/PowerPC/aix-xcoff-lower-comm.ll --- a/llvm/test/CodeGen/PowerPC/aix-xcoff-lower-comm.ll +++ b/llvm/test/CodeGen/PowerPC/aix-xcoff-lower-comm.ll @@ -13,7 +13,8 @@ ; CHECK: .comm common[RW],4,2 -; CHECK-NEXT: .csect .data[RW] +; ASM32-NEXT: .csect .data[RW], 2 +; ASM64-NEXT: .csect .data[RW], 3 ; CHECK-NEXT: .globl pointer ; ASM32-NEXT: .align 2 ; ASM64-NEXT: .align 3 diff --git a/llvm/test/CodeGen/PowerPC/aix-xcoff-mergeable-const.ll b/llvm/test/CodeGen/PowerPC/aix-xcoff-mergeable-const.ll --- a/llvm/test/CodeGen/PowerPC/aix-xcoff-mergeable-const.ll +++ b/llvm/test/CodeGen/PowerPC/aix-xcoff-mergeable-const.ll @@ -22,7 +22,7 @@ ret i32 0 } -;CHECK: .csect .rodata[RO] +;CHECK: .csect .rodata[RO], 4 ;CHECK-NEXT: .align 4 ;CHECK-NEXT: .L__const.main.cnst32: ;CHECK-NEXT: .llong 4611686018427387954 diff --git a/llvm/test/CodeGen/PowerPC/aix-xcoff-mergeable-str.ll b/llvm/test/CodeGen/PowerPC/aix-xcoff-mergeable-str.ll --- a/llvm/test/CodeGen/PowerPC/aix-xcoff-mergeable-str.ll +++ b/llvm/test/CodeGen/PowerPC/aix-xcoff-mergeable-str.ll @@ -25,21 +25,21 @@ ret i8 %1 } -; CHECK: .csect .rodata.str2.2[RO] +; CHECK: .csect .rodata.str2.2[RO], 2 ; CHECK-NEXT: .align 1 ; CHECK-NEXT: .Lmagic16: ; CHECK-NEXT: .short 264 # 0x108 ; CHECK-NEXT: .short 272 # 0x110 ; CHECK-NEXT: .short 213 # 0xd5 ; CHECK-NEXT: .short 0 # 0x0 -; CHECK-NEXT: .csect .rodata.str4.4[RO] +; CHECK-NEXT: .csect .rodata.str4.4[RO], 2 ; CHECK-NEXT: .align 2 ; CHECK-NEXT: .Lmagic32: ; CHECK-NEXT: .long 464 # 0x1d0 ; CHECK-NEXT: .long 472 # 0x1d8 ; CHECK-NEXT: .long 413 # 0x19d ; CHECK-NEXT: .long 0 # 0x0 -; CHECK-NEXT: .csect .rodata.str1.1[RO] +; CHECK-NEXT: .csect .rodata.str1.1[RO], 2 ; CHECK-NEXT: .LstrA: ; CHECK-NEXT: .byte 104 ; CHECK-NEXT: .byte 101 diff --git a/llvm/test/CodeGen/PowerPC/aix-xcoff-rodata.ll b/llvm/test/CodeGen/PowerPC/aix-xcoff-rodata.ll --- a/llvm/test/CodeGen/PowerPC/aix-xcoff-rodata.ll +++ b/llvm/test/CodeGen/PowerPC/aix-xcoff-rodata.ll @@ -20,7 +20,7 @@ @const_chrarray = constant [4 x i8] c"abcd", align 1 @const_dblarr = constant [4 x double] [double 1.000000e+00, double 2.000000e+00, double 3.000000e+00, double 4.000000e+00], align 8 -; CHECK: .csect .rodata[RO] +; CHECK: .csect .rodata[RO], 5 ; CHECK-NEXT: .globl const_ivar ; CHECK-NEXT: .align 2 ; CHECK-NEXT: const_ivar: diff --git a/llvm/test/CodeGen/PowerPC/test_func_desc.ll b/llvm/test/CodeGen/PowerPC/test_func_desc.ll --- a/llvm/test/CodeGen/PowerPC/test_func_desc.ll +++ b/llvm/test/CodeGen/PowerPC/test_func_desc.ll @@ -29,40 +29,43 @@ ; CHECK: .globl foo[DS] ; CHECK: .globl .foo -; CHECK: .csect foo[DS] -; 32BIT: .long .foo +; 32BIT: .csect foo[DS], 2 +; 32BIT-NEXT: .long .foo ; 32BIT-NEXT: .long TOC[TC0] ; 32BIT-NEXT: .long 0 -; 64BIT: .llong .foo +; 64BIT: .csect foo[DS], 3 +; 64BIT-NEXT: .llong .foo ; 64BIT-NEXT: .llong TOC[TC0] ; 64BIT-NEXT: .llong 0 -; CHECK-NEXT: .csect .text[PR] +; CHECK-NEXT: .csect .text[PR], 2 ; CHECK-LABEL: .foo: ; CHECK: .globl main[DS] ; CHECK: .globl .main -; CHECK: .csect main[DS] -; 32BIT: .long .main +; 32BIT: .csect main[DS], 2 +; 32BIT-NEXT: .long .main ; 32BIT-NEXT: .long TOC[TC0] ; 32BIT-NEXT: .long 0 -; 64BIT: .llong .main +; 64BIT: .csect main[DS], 3 +; 64BIT-NEXT: .llong .main ; 64BIT-NEXT: .llong TOC[TC0] ; 64BIT-NEXT: .llong 0 -; CHECK-NEXT: .csect .text[PR] +; CHECK-NEXT: .csect .text[PR], 2 ; CHECK-LABEL: .main: ; CHECK: bl .foo ; CHECK: bl .extern_foo ; CHECK: bl .static_foo ; CHECK: .lglobl .static_foo -; CHECK: .csect static_foo[DS] -; 32BIT: .long .static_foo +; 32BIT: .csect static_foo[DS], 2 +; 32BIT-NEXT: .long .static_foo ; 32BIT-NEXT: .long TOC[TC0] ; 32BIT-NEXT: .long 0 -; 64BIT: .llong .static_foo +; 64BIT: .csect static_foo[DS], 3 +; 64BIT-NEXT: .llong .static_foo ; 64BIT-NEXT: .llong TOC[TC0] ; 64BIT-NEXT: .llong 0 -; CHECK-NEXT: .csect .text[PR] +; CHECK-NEXT: .csect .text[PR], 2 ; CHECK-LABEL: .static_foo: ; CHECK-NOT: .csect extern_foo diff --git a/llvm/test/CodeGen/aix-func-align.ll b/llvm/test/CodeGen/aix-func-align.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/aix-func-align.ll @@ -0,0 +1,46 @@ +; This test tries to verify if a csect containing code would have the correct alignment. + +; RUN: llc -verify-machineinstrs -mcpu=pwr4 -mtriple powerpc-ibm-aix-xcoff < %s | FileCheck %s +; RUN: llc -verify-machineinstrs -mcpu=pwr4 -mtriple powerpc64-ibm-aix-xcoff < %s | FileCheck %s + +; RUN: llc -verify-machineinstrs -mcpu=pwr4 -mtriple powerpc-ibm-aix-xcoff -filetype=obj -o %t.o < %s +; RUN: llvm-readobj --syms %t.o | FileCheck --check-prefix=SYMS %s + +; RUN: not --crash llc -mtriple powerpc64-ibm-aix-xcoff -filetype=obj < %s 2>&1 | \ +; RUN: FileCheck --check-prefix=XCOFF64 %s +; XCOFF64: LLVM ERROR: 64-bit XCOFF object files are not supported yet. + +define i32 @foo() align 32 { +entry: + ret i32 0 +} + +define i32 @bar() align 64 { +entry: + ret i32 0 +} + +; CHECK: .csect .text[PR], 6 +; CHECK-NEXT: .foo: + +; CHECK: .csect .text[PR], 6 +; CHECK-NEXT: .bar: + +; SYMS: Symbol {{[{][[:space:]] *}}Index: [[#INDX:]]{{[[:space:]] *}}Name: .text +; SYMS-NEXT: Value (RelocatableAddress): 0x0 +; SYMS-NEXT: Section: .text +; SYMS-NEXT: Type: 0x0 +; SYMS-NEXT: StorageClass: C_HIDEXT (0x6B) +; SYMS-NEXT: NumberOfAuxEntries: 1 +; SYMS-NEXT: CSECT Auxiliary Entry { +; SYMS-NEXT: Index: [[#INDX+1]] +; SYMS-NEXT: SectionLen: 72 +; SYMS-NEXT: ParameterHashIndex: 0x0 +; SYMS-NEXT: TypeChkSectNum: 0x0 +; SYMS-NEXT: SymbolAlignmentLog2: 6 +; SYMS-NEXT: SymbolType: XTY_SD (0x1) +; SYMS-NEXT: StorageMappingClass: XMC_PR (0x0) +; SYMS-NEXT: StabInfoIndex: 0x0 +; SYMS-NEXT: StabSectNum: 0x0 +; SYMS-NEXT: } +; SYMS-NEXT: }