diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index 1d24fa44a5cea..030d0e1c82ab7 100644 --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -3849,6 +3849,8 @@ static void emitGlobalConstantImpl(const DataLayout &DL, const Constant *CV, AsmPrinter &AP, const Constant *BaseCV, uint64_t Offset, AsmPrinter::AliasMapTy *AliasList) { + assert(!AliasList || AP.TM.getTargetTriple().isOSBinFormatXCOFF() && + "AliasList only expected for XCOFF"); emitGlobalAliasInline(AP, Offset, AliasList); uint64_t Size = DL.getTypeAllocSize(CV->getType()); @@ -3858,7 +3860,27 @@ static void emitGlobalConstantImpl(const DataLayout &DL, const Constant *CV, if (!BaseCV && CV->hasOneUse()) BaseCV = dyn_cast(CV->user_back()); - if (isa(CV) || isa(CV)) + if (isa(CV)) { + StructType *structType; + if (AliasList && (structType = llvm::dyn_cast(CV->getType()))) { + // Handle cases of aliases to direct struct elements + const StructLayout *Layout = DL.getStructLayout(structType); + uint64_t SizeSoFar = 0; + for (unsigned int i = 0, n = structType->getNumElements(); i < n - 1; + ++i) { + uint64_t GapToNext = Layout->getElementOffset(i + 1) - SizeSoFar; + AP.OutStreamer->emitZeros(GapToNext); + SizeSoFar += GapToNext; + emitGlobalAliasInline(AP, Offset + SizeSoFar, AliasList); + } + AP.OutStreamer->emitZeros(Size - SizeSoFar); + return; + } else { + return AP.OutStreamer->emitZeros(Size); + } + } + + if (isa(CV)) return AP.OutStreamer->emitZeros(Size); if (const ConstantInt *CI = dyn_cast(CV)) { diff --git a/llvm/test/CodeGen/PowerPC/global-merge-aix-sections.ll b/llvm/test/CodeGen/PowerPC/global-merge-aix-sections.ll new file mode 100644 index 0000000000000..0fb313b572677 --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/global-merge-aix-sections.ll @@ -0,0 +1,52 @@ +; RUN: rm -rf %t +; RUN: mkdir -p %t + +; RUN: llc -verify-machineinstrs -mtriple powerpc64-ibm-aix-xcoff -mcpu=pwr8 < %s | FileCheck %s + +; RUN: llc -verify-machineinstrs -mtriple powerpc64-ibm-aix-xcoff -mcpu=pwr8 --filetype=obj -o %t/global-merge-aix-sections.o < %s +; RUN; llvm-objdump --syms %t/global-merge-aix-sections.o | FileCheck %s --check-prefix=DATA + +%struct.Example = type { i32, i8 } + +@y = internal global i32 0, section "mycsect", align 4 +@z = internal global i32 0, section "mycsect", align 4 +@l = internal global i32 0, align 4 +@u = internal global i16 0, section "mycsect", align 2 +@myStruct1 = internal global %struct.Example zeroinitializer, section "mycsect", align 4 + +; Function Attrs: nounwind +define void @g() { +entry: + tail call void @f(ptr noundef nonnull @y, ptr noundef nonnull @z) + tail call void @f(ptr noundef nonnull @l, ptr noundef nonnull @z) + tail call void @h(ptr noundef nonnull @u) + tail call void @s(ptr noundef nonnull @myStruct1) + ret void +} + +declare void @f(ptr noundef, ptr noundef) +declare void @h(ptr noundef) +declare void @s(ptr noundef) + +; CHECK: .csect mycsect[RW],2 +; CHECK-NEXT: .lglobl u # @_MergedGlobals +; CHECK-NEXT: .lglobl y +; CHECK-NEXT: .lglobl z +; CHECK-NEXT: .lglobl myStruct1 +; CHECK-NEXT: .align 2 +; CHECK-NEXT: L.._MergedGlobals: +; CHECK-NEXT: u: +; CHECK-NEXT: .space 2 +; CHECK-NEXT: .space 2 +; CHECK-NEXT: y: +; CHECK-NEXT: .space 4 +; CHECK-NEXT: z: +; CHECK-NEXT: .space 4 +; CHECK-NEXT: myStruct1: +; CHECK-NEXT: .space 8 + +; DATA: 00000078 l O .data 00000014 mycsect +; DATA-NEXT: 00000078 l O .data (csect: mycsect) 00000000 u +; DATA-NEXT: 0000007c l O .data (csect: mycsect) 00000000 y +; DATA-NEXT: 00000080 l O .data (csect: mycsect) 00000000 z +; DATA-NEXT: 00000084 l O .data (csect: mycsect) 00000000 myStruct1