if (const BlockAddress *BA = dyn_cast<BlockAddress>(this))
return BA->getFunction()->needsRelocation();
- // While raw uses of blockaddress need to be relocated, differences between
- // two of them don't when they are for labels in the same function. This is a
- // common idiom when creating a table for the indirect goto extension, so we
- // handle it efficiently here.
- if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(this))
+ if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(this)) {
if (CE->getOpcode() == Instruction::Sub) {
ConstantExpr *LHS = dyn_cast<ConstantExpr>(CE->getOperand(0));
ConstantExpr *RHS = dyn_cast<ConstantExpr>(CE->getOperand(1));
if (LHS && RHS && LHS->getOpcode() == Instruction::PtrToInt &&
- RHS->getOpcode() == Instruction::PtrToInt &&
- isa<BlockAddress>(LHS->getOperand(0)) &&
- isa<BlockAddress>(RHS->getOperand(0)) &&
- cast<BlockAddress>(LHS->getOperand(0))->getFunction() ==
- cast<BlockAddress>(RHS->getOperand(0))->getFunction())
- return false;
+ RHS->getOpcode() == Instruction::PtrToInt) {
+ Constant *LHSOp0 = LHS->getOperand(0);
+ Constant *RHSOp0 = RHS->getOperand(0);
+
+ // While raw uses of blockaddress need to be relocated, differences
+ // between two of them don't when they are for labels in the same
+ // function. This is a common idiom when creating a table for the
+ // indirect goto extension, so we handle it efficiently here.
+ if (isa<BlockAddress>(LHSOp0) && isa<BlockAddress>(LHSOp0) &&
+ cast<BlockAddress>(LHSOp0)->getFunction() ==
+ cast<BlockAddress>(RHSOp0)->getFunction())
+ return false;
+
+ // Relative pointers do not need to be dynamically relocated.
+ if (auto *LHSGV = dyn_cast<GlobalValue>(
+ LHSOp0->stripPointerCastsNoFollowAliases()))
+ if (auto *RHSGV = dyn_cast<GlobalValue>(
+ RHSOp0->stripPointerCastsNoFollowAliases()))
+ if (LHSGV->isDSOLocal() && RHSGV->isDSOLocal())
+ return false;
+ }
}
+ }
bool Result = false;
for (unsigned i = 0, e = getNumOperands(); i != e; ++i)
--- /dev/null
+; RUN: llc -relocation-model=pic -data-sections -o - %s | FileCheck %s
+
+target triple = "x86_64-unknown-linux-gnu"
+
+@hidden = external hidden global i8
+@default = external global i8
+
+; CHECK: .section .rodata.rodata
+; CHECK: rodata:
+; CHECK: .long hidden-rodata
+@rodata = hidden constant i32 trunc (i64 sub (i64 ptrtoint (i8* @hidden to i64), i64 ptrtoint (i32* @rodata to i64)) to i32)
+
+; CHECK: .section .data.rel.ro.relro1
+; CHECK: relro1:
+; CHECK: .long default-relro1
+@relro1 = hidden constant i32 trunc (i64 sub (i64 ptrtoint (i8* @default to i64), i64 ptrtoint (i32* @relro1 to i64)) to i32)
+
+; CHECK: .section .data.rel.ro.relro2
+; CHECK: relro2:
+; CHECK: .long hidden-relro2
+@relro2 = constant i32 trunc (i64 sub (i64 ptrtoint (i8* @hidden to i64), i64 ptrtoint (i32* @relro2 to i64)) to i32)