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,
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();
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,
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;
}
switch (getMappingClass()) {
case XCOFF::XMC_RW:
case XCOFF::XMC_DS:
- OS << "\t.csect " << QualName->getName() << '\n';
+ printCsectDirective(OS);
break;
case XCOFF::XMC_TC:
break;
#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"
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<MCSymbolXCOFF>(Symbol)->getRepresentedCsect()->setAlignment(
+ Align(ByteAlignment));
+
// Emit the alignment and storage for the variable to the section.
emitValueToAlignment(ByteAlignment);
emitZeros(Size);
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;
}
}
+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<MCSectionXCOFF>(
+ 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.
; 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
; 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
; 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
; 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
; 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
; 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
; 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
; 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
@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:
}
-;CHECK: .csect .data[RW]
+;CHECK: .csect .data[RW], 2
;CHECK-NEXT: .globl foo_ptr
;CHECK-NEXT: .align 2
;CHECK-NEXT: foo_ptr:
;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:
; 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:
; 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
; 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
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
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
@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:
; 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
--- /dev/null
+; 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: }