diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -1790,6 +1790,9 @@ if (TM.getTargetTriple().isOSBinFormatXCOFF()) { assert(MAI->hasVisibilityOnlyWithLinkage() && "Visibility should be handled with emitLinkage() on AIX."); + // Linkage for alias of global variable has been emitted. + if (isa(GA.getAliaseeObject())) + return; emitLinkage(&GA, Name); // If it's a function, also emit linkage for aliases of function entry // point. 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 @@ -230,6 +230,9 @@ void emitGlobalVariableHelper(const GlobalVariable *); + // Get the offset of an alias based on its AliaseeObject. + uint64_t getAliasOffset(const Constant *C); + public: PPCAIXAsmPrinter(TargetMachine &TM, std::unique_ptr Streamer) : PPCAsmPrinter(TM, std::move(Streamer)) { @@ -2367,6 +2370,21 @@ emitGlobalVariableHelper(GV); } +uint64_t PPCAIXAsmPrinter::getAliasOffset(const Constant *C) { + if (auto *GA = dyn_cast(C)) + return getAliasOffset(GA->getAliasee()); + if (auto *CE = dyn_cast(C)) { + const MCExpr *LowC = lowerConstant(CE); + const MCBinaryExpr *CBE = dyn_cast(LowC); + // Currently only the case of adding an offset is considered. + if (!CBE || CBE->getOpcode() != MCBinaryExpr::Add) + return 0; + if (auto *RHS = dyn_cast(CBE->getRHS())) + return RHS->getValue(); + } + return 0; +} + void PPCAIXAsmPrinter::emitGlobalVariableHelper(const GlobalVariable *GV) { assert(!GV->getName().startswith("llvm.") && "Unhandled intrinsic global variable."); @@ -2427,16 +2445,44 @@ // When -fdata-sections is enabled, every GlobalVariable will // be put into its own csect; therefore, label is not necessary here. - if (!TM.getDataSections() || GV->hasSection()) { + bool LabelForGV = (!TM.getDataSections() || GV->hasSection()); + if (LabelForGV) OutStreamer->emitLabel(EmittedInitSym); - } - // Emit aliasing label for global variable. - llvm::for_each(GOAliasMap[GV], [this](const GlobalAlias *Alias) { - OutStreamer->emitLabel(getSymbol(Alias)); - }); + // No need to consider label alignment for GlobalVariable and GlobalAlias. + if (!LabelForGV || !GOAliasMap[GV].size()) + emitGlobalConstant(DL, GV->getInitializer()); - emitGlobalConstant(GV->getParent()->getDataLayout(), GV->getInitializer()); + // No alias to emit. + if (!GOAliasMap[GV].size()) + return; + + // Aliases with the same offset should be aligned. Record the list of aliases + // associated with the offset. + DenseMap> AliasList; + for (const GlobalAlias *GA : GOAliasMap[GV]) + AliasList[getAliasOffset(GA->getAliasee())].push_back(GA); + + // Emit the value of GlobalVariable before aliases if it is not aligned with + // the first set of aliases. + if (LabelForGV && AliasList.begin()->first != 0) + emitGlobalConstant(DL, GV->getInitializer()); + + for (auto I = AliasList.begin(); I != AliasList.end(); ++I) { + // Emit label for alias. + for (const GlobalAlias *GA : I->second) + OutStreamer->emitLabel(getSymbol(GA)); + + // Emit the value. + if (LabelForGV && I->first == 0) + emitGlobalConstant(DL, GV->getInitializer()); + else + emitGlobalConstant(DL, I->second[0]->getAliasee()); + + // Emit linkage for alias. + for (const GlobalAlias *Alias : I->second) + emitLinkage(Alias, getSymbol(Alias)); + } } void PPCAIXAsmPrinter::emitFunctionDescriptor() { diff --git a/llvm/test/CodeGen/PowerPC/aix-alias-alignment.ll b/llvm/test/CodeGen/PowerPC/aix-alias-alignment.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/aix-alias-alignment.ll @@ -0,0 +1,100 @@ +; RUN: llc -verify-machineinstrs -mtriple powerpc-ibm-aix-xcoff -mcpu=pwr4 \ +; RUN: -data-sections=false < %s | FileCheck --check-prefix=ASM %s + +; RUN: llc -verify-machineinstrs -mtriple powerpc-ibm-aix-xcoff -mcpu=pwr4 < %s |\ +; RUN: FileCheck --check-prefix=NOGVLABEL %s + +; RUN: llc -verify-machineinstrs -mtriple powerpc-ibm-aix-xcoff -mcpu=pwr4 \ +; RUN: -data-sections=false -filetype=obj -o %t.o < %s +; RUN: llvm-objdump -dr %t.o | FileCheck --check-prefix=OBJ %s +; RUN: llvm-objdump --syms %t.o | FileCheck --check-prefix=SYM %s + +@_MergedGlobals = private global <{ i32, i32 }> <{ i32 1, i32 2 }>, align 4 +@var1 = internal alias i32, getelementptr inbounds (<{ i32, i32 }>, <{ i32, i32 }>* @_MergedGlobals, i32 0, i32 0) +@var2 = internal alias i32, getelementptr inbounds (<{ i32, i32 }>, <{ i32, i32 }>* @_MergedGlobals, i32 0, i32 1) +@var3 = alias i32, i32* @var2 + +; Test the case where the first set of aliases isn't aligned with the base variable. +@base = private global <{ i32, i32 }> <{ i32 1, i32 2 }>, align 4 +@var4 = internal alias i32, getelementptr inbounds (<{ i32, i32 }>, <{ i32, i32 }>* @base, i32 0, i32 1) +@var5 = alias i32, i32* @var4 + +define void @foo(i32 %a1, i32 %a2, i32 %a3) { + store i32 %a1, i32* getelementptr inbounds (<{ i32, i32 }>, <{ i32, i32 }>* @_MergedGlobals, i32 0, i32 0), align 4 + store i32 %a2, i32* getelementptr inbounds (<{ i32, i32 }>, <{ i32, i32 }>* @_MergedGlobals, i32 0, i32 1), align 4 + store i32 %a3, i32* getelementptr inbounds (<{ i32, i32 }>, <{ i32, i32 }>* @base, i32 0, i32 1), align 4 + ret void +} + +; ASM: # -- End function +; ASM-NEXT: .csect .data[RW],2 +; ASM-NEXT: .align 2 # @_MergedGlobals +; ASM-NEXT: L.._MergedGlobals: +; ASM-NEXT: var1: +; ASM-NEXT: .vbyte 4, 1 # 0x1 +; ASM-NEXT: .vbyte 4, 2 # 0x2 +; ASM-NEXT: .lglobl var1 +; ASM-NEXT: var2: +; ASM-NEXT: var3: +; ASM-NEXT: .vbyte 4, L.._MergedGlobals+4 +; ASM-NEXT: .lglobl var2 +; ASM-NEXT: .globl var3 + +; ASM: .align 2 # @base +; ASM-NEXT: L..base: +; ASM-NEXT: .vbyte 4, 1 # 0x1 +; ASM-NEXT: .vbyte 4, 2 # 0x2 +; ASM-NEXT: var4: +; ASM-NEXT: var5: +; ASM-NEXT: .vbyte 4, L..base+4 +; ASM-NEXT: .lglobl var4 +; ASM-NEXT: .globl var5 + +; NOGVLABEL: # -- End function +; NOGVLABEL-NEXT: .csect L.._MergedGlobals[RW],2 +; NOGVLABEL-NEXT: .align 2 # @_MergedGlobals +; NOGVLABEL-NEXT: .vbyte 4, 1 # 0x1 +; NOGVLABEL-NEXT: .vbyte 4, 2 # 0x2 +; NOGVLABEL-NEXT: var1: +; NOGVLABEL-NEXT: .vbyte 4, L.._MergedGlobals[RW] +; NOGVLABEL-NEXT: .lglobl var1 +; NOGVLABEL-NEXT: var2: +; NOGVLABEL-NEXT: var3: +; NOGVLABEL-NEXT: .vbyte 4, L.._MergedGlobals[RW]+4 +; NOGVLABEL-NEXT: .lglobl var2 +; NOGVLABEL-NEXT: .globl var3 + +; NOGVLABEL: .csect L..base[RW],2 +; NOGVLABEL-NEXT: .align 2 # @base +; NOGVLABEL-NEXT: .vbyte 4, 1 # 0x1 +; NOGVLABEL-NEXT: .vbyte 4, 2 # 0x2 +; NOGVLABEL-NEXT: var4: +; NOGVLABEL-NEXT: var5: +; NOGVLABEL-NEXT: .vbyte 4, L..base[RW]+4 +; NOGVLABEL-NEXT: .lglobl var4 +; NOGVLABEL-NEXT: .globl var5 + +; OBJ: 00000000 <.foo>: +; OBJ-NEXT: 0: 80 c2 00 00 lwz 6, 0(2) +; OBJ-NEXT: 00000002: R_TOC L.._MergedGlobals +; OBJ-NEXT: 4: 90 66 00 00 stw 3, 0(6) +; OBJ-NEXT: 8: 80 62 00 04 lwz 3, 4(2) +; OBJ-NEXT: 0000000a: R_TOC L..base +; OBJ-NEXT: c: 90 86 00 04 stw 4, 4(6) +; OBJ-NEXT: 10: 90 a3 00 04 stw 5, 4(3) +; OBJ-NEXT: 14: 4e 80 00 20 blr + +; SYM: SYMBOL TABLE: +; SYM-NEXT: 00000000 df *DEBUG* 00000000 .file +; SYM-NEXT: 00000000 l .text 00000031 .text +; SYM-NEXT: 00000000 g F .text (csect: .text) 00000000 .foo +; SYM-NEXT: 00000034 l .data 00000018 .data +; SYM-NEXT: 00000034 l O .data (csect: .data) 00000000 var1 +; SYM-NEXT: 0000003c l O .data (csect: .data) 00000000 var2 +; SYM-NEXT: 0000003c g O .data (csect: .data) 00000000 var3 +; SYM-NEXT: 00000048 l O .data (csect: .data) 00000000 var4 +; SYM-NEXT: 00000048 g O .data (csect: .data) 00000000 var5 +; SYM-NEXT: 0000004c g O .data 0000000c foo +; SYM-NEXT: 00000058 l .data 00000000 TOC +; SYM-NEXT: 00000058 l O .data 00000004 L.._MergedGlobals +; SYM-NEXT: 0000005c l O .data 00000004 L..base diff --git a/llvm/test/CodeGen/PowerPC/aix-alias.ll b/llvm/test/CodeGen/PowerPC/aix-alias.ll --- a/llvm/test/CodeGen/PowerPC/aix-alias.ll +++ b/llvm/test/CodeGen/PowerPC/aix-alias.ll @@ -83,7 +83,13 @@ ; ASM-NEXT: var_h: ; ASM-NEXT: var_p: ; ASM-NEXT: .vbyte 4, 42 -; ASM-NEXT: .globl array +; ASM-NEXT: .globl var1 +; ASM-NEXT: .globl var2 +; ASM-NEXT: .weak var_l +; ASM-NEXT: .lglobl var_i +; ASM-NEXT: .globl var_h,hidden +; ASM-NEXT: .globl var_p,protected +; ASM-NEXT: .globl array ; ASM: array: ; ASM-NEXT: .vbyte 4, 1 # 0x1 ; ASM-NEXT: .vbyte 4, 2 # 0x2 @@ -91,18 +97,12 @@ ; ASM: x: ; ASM-NEXT: bitcast_alias: ; ASM-NEXT: .vbyte {{[0-9]+}}, array+4 +; ASM-NEXT: .globl bitcast_alias ; ASM-NEXT: .globl fun_ptr ; ASM: fun_ptr: ; ASM-NEXT: .vbyte {{[0-9]+}}, fun_weak -; ASM-NEXT: .globl var1 -; ASM-NEXT: .globl var2 -; ASM-NEXT: .weak var_l -; ASM-NEXT: .lglobl var_i -; ASM-NEXT: .globl var_h,hidden -; ASM-NEXT: .globl var_p,protected -; ASM-NEXT: .globl bitcast_alias -; ASM-NEXT: .weak fun_weak -; ASM-NEXT: .weak .fun_weak +; ASM-NEXT: .weak fun_weak +; ASM-NEXT: .weak .fun_weak ; ASM-NEXT: .globl fun_hidden,hidden ; ASM-NEXT: .globl .fun_hidden,hidden ; ASM-NEXT: .toc diff --git a/llvm/test/CodeGen/PowerPC/aix-tls-xcoff-variables.ll b/llvm/test/CodeGen/PowerPC/aix-tls-xcoff-variables.ll --- a/llvm/test/CodeGen/PowerPC/aix-tls-xcoff-variables.ll +++ b/llvm/test/CodeGen/PowerPC/aix-tls-xcoff-variables.ll @@ -1,12 +1,12 @@ ; This file tests the codegen of tls variables in AIX XCOFF object files ; RUN: llc -mtriple powerpc-ibm-aix-xcoff -filetype=obj -o %t.o < %s -; RUN: llvm-readobj --section-headers %t.o | FileCheck --check-prefix=SECTION %s +; RUN: llvm-readobj --section-headers %t.o | FileCheck --check-prefixes=SECTION,SECT-DATASET %s ; RUN: llvm-readobj --syms %t.o | FileCheck --check-prefixes=SYMS,SYMS-DATASECT %s ; RUN: llvm-objdump -D --symbol-description %t.o | FileCheck --check-prefixes=OBJDUMP-DATASECT %s ; RUN: llc -mtriple powerpc-ibm-aix-xcoff -data-sections=false -filetype=obj -o %t.o < %s -; RUN: llvm-readobj --section-headers %t.o | FileCheck --check-prefix=SECTION %s +; RUN: llvm-readobj --section-headers %t.o | FileCheck --check-prefixes=SECTION,SECT-NODATASECT %s ; RUN: llvm-readobj --syms %t.o | FileCheck --check-prefixes=SYMS,SYMS-NODATASECT %s ; RUN: llvm-objdump -D --symbol-description %t.o | FileCheck --check-prefixes=OBJDUMP-NODATASECT %s @@ -37,10 +37,12 @@ ; SECTION-NEXT: VirtualAddress: 0x0 ; SECTION-NEXT: Size: 0x30 ; SECTION-NEXT: RawDataOffset: 0x90 -; SECTION-NEXT: RelocationPointer: 0x0 -; SECTION-NEXT: LineNumberPointer: 0x0 -; SECTION-NEXT: NumberOfRelocations: 0 -; SECTION-NEXT: NumberOfLineNumbers: 0 +; SECT-DATASET: RelocationPointer: 0xC0 +; SECT-NODATASECT: RelocationPointer: 0x0 +; SECTION: LineNumberPointer: 0x0 +; SECT-DATASET: NumberOfRelocations: 1 +; SECT-NODATASECT: NumberOfRelocations: 0 +; SECTION: NumberOfLineNumbers: 0 ; SECTION-NEXT: Type: STYP_TDATA (0x400) ; SECTION-NEXT: } ; SECTION-NEXT: Section { @@ -215,7 +217,7 @@ ; SYMS-NEXT: NumberOfAuxEntries: 1 ; SYMS-NEXT: CSECT Auxiliary Entry { ; SYMS-DATASECT: Index: [[#INDX+9]] -; SYMS-DATASECT-NEXT: SectionLen: 4 +; SYMS-DATASECT-NEXT: SectionLen: 8 ; SYMS-NODATASECT: Index: [[#INDX+13]] ; SYMS-NODATASECT-NEXT: ContainingCsectSymbolIndex: [[#INDX+10]] ; SYMS: ParameterHashIndex: 0x0 @@ -234,7 +236,8 @@ ; SYMS-DATASECT: Index: [[#INDX+10]] ; SYMS-NODATASECT: Index: [[#INDX+14]] ; SYMS: Name: tls_global_alias_int_external_val_initialized -; SYMS-NEXT: Value (RelocatableAddress): 0x0 +; SYMS-DATASECT: Value (RelocatableAddress): 0x4 +; SYMS-NODATASECT: Value (RelocatableAddress): 0x0 ; SYMS-NEXT: Section: .tdata ; SYMS-NEXT: Type: 0x0 ; SYMS-NEXT: StorageClass: C_EXT (0x2) @@ -258,8 +261,9 @@ ; SYMS-DATASECT: Index: [[#INDX+12]] ; SYMS-NODATASECT: Index: [[#INDX+16]] ; SYMS: Name: tls_global_int_external_zero_initialized -; SYMS-NEXT: Value (RelocatableAddress): 0x4 -; SYMS-NEXT: Section: .tdata +; SYMS-DATASECT: Value (RelocatableAddress): 0x8 +; SYMS-NODATASECT: Value (RelocatableAddress): 0x4 +; SYMS: Section: .tdata ; SYMS-NEXT: Type: 0x0 ; SYMS-NEXT: StorageClass: C_EXT (0x2) ; SYMS-NEXT: NumberOfAuxEntries: 1 @@ -284,8 +288,9 @@ ; SYMS-DATASECT: Index: [[#INDX+14]] ; SYMS-NODATASECT: Index: [[#INDX+18]] ; SYMS: Name: tls_global_int_local_val_initialized -; SYMS-NEXT: Value (RelocatableAddress): 0x8 -; SYMS-NEXT: Section: .tdata +; SYMS-DATASECT: Value (RelocatableAddress): 0xC +; SYMS-NODATASECT: Value (RelocatableAddress): 0x8 +; SYMS: Section: .tdata ; SYMS-NEXT: Type: 0x0 ; SYMS-NEXT: StorageClass: C_HIDEXT (0x6B) ; SYMS-NEXT: NumberOfAuxEntries: 1 @@ -310,8 +315,9 @@ ; SYMS-DATASECT: Index: [[#INDX+16]] ; SYMS-NODATASECT: Index: [[#INDX+20]] ; SYMS: Name: tls_global_int_weak_zero_initialized -; SYMS-NEXT: Value (RelocatableAddress): 0xC -; SYMS-NEXT: Section: .tdata +; SYMS-DATASECT: Value (RelocatableAddress): 0x10 +; SYMS-NODATASECT: Value (RelocatableAddress): 0xC +; SYMS: Section: .tdata ; SYMS-NEXT: Type: 0x0 ; SYMS-NEXT: StorageClass: C_WEAKEXT (0x6F) ; SYMS-NEXT: NumberOfAuxEntries: 1 @@ -336,8 +342,9 @@ ; SYMS-DATASECT: Index: [[#INDX+18]] ; SYMS-NODATASECT: Index: [[#INDX+22]] ; SYMS: Name: tls_global_int_weak_val_initialized -; SYMS-NEXT: Value (RelocatableAddress): 0x10 -; SYMS-NEXT: Section: .tdata +; SYMS-DATASECT: Value (RelocatableAddress): 0x14 +; SYMS-NODATASECT: Value (RelocatableAddress): 0x10 +; SYMS: Section: .tdata ; SYMS-NEXT: Type: 0x0 ; SYMS-NEXT: StorageClass: C_WEAKEXT (0x6F) ; SYMS-NEXT: NumberOfAuxEntries: 1 @@ -536,21 +543,23 @@ ; OBJDUMP-DATASECT-EMPTY: ; OBJDUMP-DATASECT-NEXT: Disassembly of section .tdata: ; OBJDUMP-DATASECT-EMPTY: -; OBJDUMP-DATASECT-NEXT: 00000000 (idx: 11) tls_global_alias_int_external_val_initialized: +; OBJDUMP-DATASECT-NEXT: 00000000 (idx: 9) tls_global_int_external_val_initialized[TL]: ; OBJDUMP-DATASECT-NEXT: 0: 00 00 00 01 ; OBJDUMP-DATASECT-EMPTY: -; OBJDUMP-DATASECT-NEXT: 00000004 (idx: 13) tls_global_int_external_zero_initialized[TL]: +; OBJDUMP-DATASECT-NEXT: 00000004 (idx: 11) tls_global_alias_int_external_val_initialized: ; OBJDUMP-DATASECT-NEXT: 4: 00 00 00 00 ; OBJDUMP-DATASECT-EMPTY: -; OBJDUMP-DATASECT-NEXT: 00000008 (idx: 15) tls_global_int_local_val_initialized[TL]: -; OBJDUMP-DATASECT-NEXT: 8: 00 00 00 02 +; OBJDUMP-DATASECT-NEXT: 00000008 (idx: 13) tls_global_int_external_zero_initialized[TL]: +; OBJDUMP-DATASECT-NEXT: 8: 00 00 00 00 +; OBJDUMP-DATASECT-EMPTY: +; OBJDUMP-DATASECT-NEXT: 0000000c (idx: 15) tls_global_int_local_val_initialized[TL]: +; OBJDUMP-DATASECT-NEXT: c: 00 00 00 02 ; OBJDUMP-DATASECT-EMPTY: -; OBJDUMP-DATASECT-NEXT: 0000000c (idx: 17) tls_global_int_weak_zero_initialized[TL]: -; OBJDUMP-DATASECT-NEXT: c: 00 00 00 00 +; OBJDUMP-DATASECT-NEXT: 00000010 (idx: 17) tls_global_int_weak_zero_initialized[TL]: +; OBJDUMP-DATASECT-NEXT: 10: 00 00 00 00 ; OBJDUMP-DATASECT-EMPTY: -; OBJDUMP-DATASECT-NEXT: 00000010 (idx: 19) tls_global_int_weak_val_initialized[TL]: -; OBJDUMP-DATASECT-NEXT: 10: 00 00 00 01 -; OBJDUMP-DATASECT-NEXT: 14: 00 00 00 00 +; OBJDUMP-DATASECT-NEXT: 00000014 (idx: 19) tls_global_int_weak_val_initialized[TL]: +; OBJDUMP-DATASECT-NEXT: 14: 00 00 00 01 ; OBJDUMP-DATASECT-EMPTY: ; OBJDUMP-DATASECT-NEXT: 00000018 (idx: 21) tls_global_long_long_internal_val_initialized[TL]: ; OBJDUMP-DATASECT-NEXT: 18: 00 00 00 00