diff --git a/llvm/include/llvm/IR/Constant.h b/llvm/include/llvm/IR/Constant.h --- a/llvm/include/llvm/IR/Constant.h +++ b/llvm/include/llvm/IR/Constant.h @@ -130,11 +130,13 @@ bool isConstantUsed() const; /// This method classifies the entry according to whether or not it may - /// generate a relocation entry. This must be conservative, so if it might - /// codegen to a relocatable entry, it should say so. + /// generate a relocation entry (either static or dynamic). This must be + /// conservative, so if it might codegen to a relocatable entry, it should say + /// so. /// /// FIXME: This really should not be in IR. bool needsRelocation() const; + bool needsDynamicRelocation() const; /// For aggregates (struct/array/vector) return the constant that corresponds /// to the specified element if possible, or null if not. This can return null @@ -214,6 +216,24 @@ /// both must either be scalars or vectors with the same element count. If no /// changes are made, the constant C is returned. static Constant *mergeUndefsWith(Constant *C, Constant *Other); + +private: + enum PossibleRelocationsTy { + /// This constant requires no relocations. That is, it holds simple + /// constants (like integrals). + NoRelocation = 0, + + /// This constant holds static relocations that can be resolved by the + /// static linker. + LocalRelocation = 1, + + /// This constant holds dynamic relocations that the dynamic linker will + /// need to resolve. + GlobalRelocation = 2, + }; + + /// Determine what potential relocations may be needed by this constant. + PossibleRelocationsTy getRelocationInfo() const; }; } // end namespace llvm diff --git a/llvm/lib/CodeGen/MachineFunction.cpp b/llvm/lib/CodeGen/MachineFunction.cpp --- a/llvm/lib/CodeGen/MachineFunction.cpp +++ b/llvm/lib/CodeGen/MachineFunction.cpp @@ -1119,7 +1119,7 @@ bool MachineConstantPoolEntry::needsRelocation() const { if (isMachineConstantPoolEntry()) return true; - return Val.ConstVal->needsRelocation(); + return Val.ConstVal->needsDynamicRelocation(); } SectionKind diff --git a/llvm/lib/IR/Constants.cpp b/llvm/lib/IR/Constants.cpp --- a/llvm/lib/IR/Constants.cpp +++ b/llvm/lib/IR/Constants.cpp @@ -652,12 +652,20 @@ return false; } +bool Constant::needsDynamicRelocation() const { + return getRelocationInfo() == GlobalRelocation; +} + bool Constant::needsRelocation() const { + return getRelocationInfo() != NoRelocation; +} + +Constant::PossibleRelocationsTy Constant::getRelocationInfo() const { if (isa(this)) - return true; // Global reference. + return GlobalRelocation; // Global reference. if (const BlockAddress *BA = dyn_cast(this)) - return BA->getFunction()->needsRelocation(); + return BA->getFunction()->getRelocationInfo(); if (const ConstantExpr *CE = dyn_cast(this)) { if (CE->getOpcode() == Instruction::Sub) { @@ -675,7 +683,7 @@ if (isa(LHSOp0) && isa(RHSOp0) && cast(LHSOp0)->getFunction() == cast(RHSOp0)->getFunction()) - return false; + return NoRelocation; // Relative pointers do not need to be dynamically relocated. if (auto *RHSGV = @@ -683,19 +691,20 @@ auto *LHS = LHSOp0->stripInBoundsConstantOffsets(); if (auto *LHSGV = dyn_cast(LHS)) { if (LHSGV->isDSOLocal() && RHSGV->isDSOLocal()) - return false; + return LocalRelocation; } else if (isa(LHS)) { if (RHSGV->isDSOLocal()) - return false; + return LocalRelocation; } } } } } - bool Result = false; + PossibleRelocationsTy Result = NoRelocation; for (unsigned i = 0, e = getNumOperands(); i != e; ++i) - Result |= cast(getOperand(i))->needsRelocation(); + Result = + std::max(cast(getOperand(i))->getRelocationInfo(), Result); return Result; } diff --git a/llvm/lib/Target/ARM/ARMISelLowering.cpp b/llvm/lib/Target/ARM/ARMISelLowering.cpp --- a/llvm/lib/Target/ARM/ARMISelLowering.cpp +++ b/llvm/lib/Target/ARM/ARMISelLowering.cpp @@ -3601,7 +3601,7 @@ // from .data to .text. This is not allowed in position-independent code. auto *Init = GVar->getInitializer(); if ((TLI->isPositionIndependent() || TLI->getSubtarget()->isROPI()) && - Init->needsRelocation()) + Init->needsDynamicRelocation()) return SDValue(); // The constant islands pass can only really deal with alignment requests diff --git a/llvm/lib/Target/ARM/ARMTargetTransformInfo.h b/llvm/lib/Target/ARM/ARMTargetTransformInfo.h --- a/llvm/lib/Target/ARM/ARMTargetTransformInfo.h +++ b/llvm/lib/Target/ARM/ARMTargetTransformInfo.h @@ -275,7 +275,7 @@ // variables or functions in constant data, so don't convert switches to // lookup tables if any of the values would need relocation. if (ST->isROPI() || ST->isRWPI()) - return !C->needsRelocation(); + return !C->needsDynamicRelocation(); return true; } diff --git a/llvm/lib/Target/PowerPC/PPCTargetObjectFile.cpp b/llvm/lib/Target/PowerPC/PPCTargetObjectFile.cpp --- a/llvm/lib/Target/PowerPC/PPCTargetObjectFile.cpp +++ b/llvm/lib/Target/PowerPC/PPCTargetObjectFile.cpp @@ -40,7 +40,8 @@ if (Kind.isReadOnly()) { const auto *GVar = dyn_cast(GO); - if (GVar && GVar->isConstant() && GVar->getInitializer()->needsRelocation()) + if (GVar && GVar->isConstant() && + GVar->getInitializer()->needsDynamicRelocation()) Kind = SectionKind::getReadOnlyWithRel(); } diff --git a/llvm/lib/Target/TargetLoweringObjectFile.cpp b/llvm/lib/Target/TargetLoweringObjectFile.cpp --- a/llvm/lib/Target/TargetLoweringObjectFile.cpp +++ b/llvm/lib/Target/TargetLoweringObjectFile.cpp @@ -290,7 +290,8 @@ // consideration when it tries to merge entries in the section. Reloc::Model ReloModel = TM.getRelocationModel(); if (ReloModel == Reloc::Static || ReloModel == Reloc::ROPI || - ReloModel == Reloc::RWPI || ReloModel == Reloc::ROPI_RWPI) + ReloModel == Reloc::RWPI || ReloModel == Reloc::ROPI_RWPI || + !C->needsDynamicRelocation()) return SectionKind::getReadOnly(); // Otherwise, the dynamic linker needs to fix it up, put it in the diff --git a/llvm/test/CodeGen/X86/relptr-rodata.ll b/llvm/test/CodeGen/X86/relptr-rodata.ll --- a/llvm/test/CodeGen/X86/relptr-rodata.ll +++ b/llvm/test/CodeGen/X86/relptr-rodata.ll @@ -20,7 +20,7 @@ ; CHECK: .long hidden-relro2 @relro2 = constant i32 trunc (i64 sub (i64 ptrtoint (i8* @hidden to i64), i64 ptrtoint (i32* @relro2 to i64)) to i32) -; CHECK: .section .rodata.cst8 +; CHECK: .section .rodata.obj ; CHECK-NEXT: .globl obj ; CHECK: obj: ; CHECK: .long 0