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 @@ -1678,22 +1678,31 @@ report_fatal_error("COMDAT not yet supported by AIX."); } -static bool isSpecialLLVMGlobalArrayForStaticInit(const GlobalVariable *GV) { - return StringSwitch(GV->getName()) - .Cases("llvm.global_ctors", "llvm.global_dtors", true) - .Default(false); +static bool isSpecialLLVMGlobalArrayToSkip(const GlobalVariable *GV) { + return GV->hasAppendingLinkage() && + StringSwitch(GV->getName()) + // TODO: Update the handling of global arrays for static init when + // we support the ".ref" directive. + // Otherwise, we can skip these arrays, because the AIX linker + // collects static init functions simply based on their name. + .Cases("llvm.global_ctors", "llvm.global_dtors", true) + // TODO: Linker could still eliminate the GV if we just skip + // handling llvm.used array. Skipping them for now until we or the + // AIX OS team come up with a good solution. + .Case("llvm.used", true) + // It's correct to just skip llvm.compiler.used array here. + .Case("llvm.compiler.used", true) + .Default(false); } void PPCAIXAsmPrinter::emitGlobalVariable(const GlobalVariable *GV) { - ValidateGV(GV); - - // TODO: Update the handling of global arrays for static init when we support - // the ".ref" directive. - // Otherwise, we can skip these arrays, because the AIX linker collects - // static init functions simply based on their name. - if (isSpecialLLVMGlobalArrayForStaticInit(GV)) + if (isSpecialLLVMGlobalArrayToSkip(GV)) return; + assert(!GV->getName().startswith("llvm.") && + "Unhandled intrinsic global variable."); + ValidateGV(GV); + // Create the symbol, set its storage class. MCSymbolXCOFF *GVSym = cast(getSymbol(GV)); GVSym->setStorageClass( @@ -1836,8 +1845,11 @@ // 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()) + for (const auto &G : M.globals()) { + if (isSpecialLLVMGlobalArrayToSkip(&G)) + continue; setCsectAlignment(&G); + } for (const auto &F : M) setCsectAlignment(&F); diff --git a/llvm/test/CodeGen/PowerPC/aix-xcoff-used.ll b/llvm/test/CodeGen/PowerPC/aix-xcoff-used.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/aix-xcoff-used.ll @@ -0,0 +1,26 @@ +;; This test verifies llc on AIX would not crash when llvm.used and +;; llvm.compiler.used is presented in the IR. + +; RUN: llc -verify-machineinstrs -mcpu=pwr4 -mtriple powerpc-ibm-aix-xcoff < %s | \ +; RUN: FileCheck %s + +; RUN: llc -verify-machineinstrs -mcpu=pwr4 -mtriple powerpc64-ibm-aix-xcoff < %s | \ +; RUN: FileCheck %s + +@keep_this = internal global i32 2, align 4 +@keep_this2 = internal global i32 3, align 4 +@llvm.used = appending global [1 x i8*] [i8* bitcast (i32* @keep_this to i8*)], section "llvm.metadata" +@llvm.compiler.used = appending global [1 x i8*] [i8* bitcast (i32* @keep_this2 to i8*)], section "llvm.metadata" + +; CHECK-NOT: llvm.metadata +; CHECK-NOT: llvm.used +; CHECK-NOT: llvm.compiler.used + +; CHECK: .lglobl keep_this +; CHECK: keep_this: +; CHECK: .lglobl keep_this2 +; CHECK: keep_this2: + +; CHECK-NOT: llvm.metadata +; CHECK-NOT: llvm.used +; CHECK-NOT: llvm.compiler.used