From d6fc7acc50a6a49b0a549f7db9303d6ba736eb26 Mon Sep 17 00:00:00 2001 From: David Green Date: Tue, 4 Nov 2025 08:04:59 +0000 Subject: [PATCH] [ARM] Use TargetMachine over Subtarget in ARMAsmPrinter The subtarget may not be set if no functions are present in the module. Attempt to use the TargetMachine directly in more cases. Fixes #165422 --- llvm/lib/Target/ARM/ARMAsmPrinter.cpp | 23 ++++++++++++----------- llvm/lib/Target/ARM/ARMSubtarget.cpp | 9 +++++++-- llvm/lib/Target/ARM/ARMSubtarget.h | 2 ++ llvm/test/CodeGen/ARM/xxstructor-nodef.ll | 7 +++++++ 4 files changed, 28 insertions(+), 13 deletions(-) create mode 100644 llvm/test/CodeGen/ARM/xxstructor-nodef.ll diff --git a/llvm/lib/Target/ARM/ARMAsmPrinter.cpp b/llvm/lib/Target/ARM/ARMAsmPrinter.cpp index 36b99087e0a32..60f5e9828c284 100644 --- a/llvm/lib/Target/ARM/ARMAsmPrinter.cpp +++ b/llvm/lib/Target/ARM/ARMAsmPrinter.cpp @@ -97,7 +97,8 @@ void ARMAsmPrinter::emitXXStructor(const DataLayout &DL, const Constant *CV) { const MCExpr *E = MCSymbolRefExpr::create( GetARMGVSymbol(GV, ARMII::MO_NO_FLAG), - (Subtarget->isTargetELF() ? ARM::S_TARGET1 : ARM::S_None), OutContext); + (TM.getTargetTriple().isOSBinFormatELF() ? ARM::S_TARGET1 : ARM::S_None), + OutContext); OutStreamer->emitValue(E, Size); } @@ -595,8 +596,7 @@ void ARMAsmPrinter::emitEndOfAsmFile(Module &M) { ARMTargetStreamer &ATS = static_cast(TS); if (OptimizationGoals > 0 && - (Subtarget->isTargetAEABI() || Subtarget->isTargetGNUAEABI() || - Subtarget->isTargetMuslAEABI())) + (TT.isTargetAEABI() || TT.isTargetGNUAEABI() || TT.isTargetMuslAEABI())) ATS.emitAttribute(ARMBuildAttrs::ABI_optimization_goals, OptimizationGoals); OptimizationGoals = -1; @@ -884,9 +884,10 @@ static uint8_t getModifierSpecifier(ARMCP::ARMCPModifier Modifier) { MCSymbol *ARMAsmPrinter::GetARMGVSymbol(const GlobalValue *GV, unsigned char TargetFlags) { - if (Subtarget->isTargetMachO()) { - bool IsIndirect = - (TargetFlags & ARMII::MO_NONLAZY) && Subtarget->isGVIndirectSymbol(GV); + const Triple &TT = TM.getTargetTriple(); + if (TT.isOSBinFormatMachO()) { + bool IsIndirect = (TargetFlags & ARMII::MO_NONLAZY) && + ARMSubtarget::isGVIndirectSymbol(TM, GV); if (!IsIndirect) return getSymbol(GV); @@ -903,9 +904,8 @@ MCSymbol *ARMAsmPrinter::GetARMGVSymbol(const GlobalValue *GV, StubSym = MachineModuleInfoImpl::StubValueTy(getSymbol(GV), !GV->hasInternalLinkage()); return MCSym; - } else if (Subtarget->isTargetCOFF()) { - assert(Subtarget->isTargetWindows() && - "Windows is the only supported COFF target"); + } else if (TT.isOSBinFormatCOFF()) { + assert(TT.isOSWindows() && "Windows is the only supported COFF target"); bool IsIndirect = (TargetFlags & (ARMII::MO_DLLIMPORT | ARMII::MO_COFFSTUB)); @@ -932,7 +932,7 @@ MCSymbol *ARMAsmPrinter::GetARMGVSymbol(const GlobalValue *GV, } return MCSym; - } else if (Subtarget->isTargetELF()) { + } else if (TT.isOSBinFormatELF()) { return getSymbolPreferLocal(*GV); } llvm_unreachable("unexpected target"); @@ -978,7 +978,8 @@ void ARMAsmPrinter::emitMachineConstantPoolValue( // On Darwin, const-pool entries may get the "FOO$non_lazy_ptr" mangling, so // flag the global as MO_NONLAZY. - unsigned char TF = Subtarget->isTargetMachO() ? ARMII::MO_NONLAZY : 0; + unsigned char TF = + TM.getTargetTriple().isOSBinFormatMachO() ? ARMII::MO_NONLAZY : 0; MCSym = GetARMGVSymbol(GV, TF); } else if (ACPV->isMachineBasicBlock()) { const MachineBasicBlock *MBB = cast(ACPV)->getMBB(); diff --git a/llvm/lib/Target/ARM/ARMSubtarget.cpp b/llvm/lib/Target/ARM/ARMSubtarget.cpp index 58bc338b25856..defffd6c9340e 100644 --- a/llvm/lib/Target/ARM/ARMSubtarget.cpp +++ b/llvm/lib/Target/ARM/ARMSubtarget.cpp @@ -317,20 +317,25 @@ bool ARMSubtarget::isRWPI() const { TM.getRelocationModel() == Reloc::ROPI_RWPI; } -bool ARMSubtarget::isGVIndirectSymbol(const GlobalValue *GV) const { +bool ARMSubtarget::isGVIndirectSymbol(const TargetMachine &TM, + const GlobalValue *GV) { if (!TM.shouldAssumeDSOLocal(GV)) return true; // 32 bit macho has no relocation for a-b if a is undefined, even if b is in // the section that is being relocated. This means we have to use o load even // for GVs that are known to be local to the dso. - if (isTargetMachO() && TM.isPositionIndependent() && + if (TM.getTargetTriple().isOSBinFormatMachO() && TM.isPositionIndependent() && (GV->isDeclarationForLinker() || GV->hasCommonLinkage())) return true; return false; } +bool ARMSubtarget::isGVIndirectSymbol(const GlobalValue *GV) const { + return isGVIndirectSymbol(TM, GV); +} + bool ARMSubtarget::isGVInGOT(const GlobalValue *GV) const { return isTargetELF() && TM.isPositionIndependent() && !GV->isDSOLocal(); } diff --git a/llvm/lib/Target/ARM/ARMSubtarget.h b/llvm/lib/Target/ARM/ARMSubtarget.h index 4a0883cc662e7..95fb62da8cf01 100644 --- a/llvm/lib/Target/ARM/ARMSubtarget.h +++ b/llvm/lib/Target/ARM/ARMSubtarget.h @@ -464,6 +464,8 @@ class ARMSubtarget : public ARMGenSubtargetInfo { } /// True if the GV will be accessed via an indirect symbol. + static bool isGVIndirectSymbol(const TargetMachine &TM, + const GlobalValue *GV); bool isGVIndirectSymbol(const GlobalValue *GV) const; /// Returns the constant pool modifier needed to access the GV. diff --git a/llvm/test/CodeGen/ARM/xxstructor-nodef.ll b/llvm/test/CodeGen/ARM/xxstructor-nodef.ll new file mode 100644 index 0000000000000..db17b2b1c21ab --- /dev/null +++ b/llvm/test/CodeGen/ARM/xxstructor-nodef.ll @@ -0,0 +1,7 @@ +; RUN: llc -mtriple=arm-unknown-linux-gnueabihf < %s | FileCheck %s + +; This test contains a llvm.global_ctors with no other definitions. Make sure we do not crash in that case. +; CHECK: .section .init_array,"aw",%init_array + +declare ccc void @ghczmbignum_GHCziNumziBackendziSelected_init__prof_init() +@llvm.global_ctors = appending global [1 x {i32, void ()*, i8* }] [{i32, void ()*, i8* }{i32 65535, void ()* @ghczmbignum_GHCziNumziBackendziSelected_init__prof_init, i8* null } ]