llvm-svn: 267229
This commit is contained in:
Sriraman Tallam 2016-04-22 21:41:58 +00:00
parent 6cac934051
commit 3cb773431d
4 changed files with 142 additions and 8 deletions

View File

@ -83,8 +83,12 @@ ClassifyGlobalReference(const GlobalValue *GV, const TargetMachine &TM) const {
} else if (!isTargetWin64()) {
assert(isTargetELF() && "Unknown rip-relative target");
// Extra load is needed for all externally visible globals.
if (!GV->hasLocalLinkage() && GV->hasDefaultVisibility())
// Extra load is needed for all externally visible globals except with
// PIE as the definition of the global in an executable is not
// overridden.
if (!GV->hasLocalLinkage() && GV->hasDefaultVisibility() &&
!isGlobalDefinedInPIE(GV, TM))
return X86II::MO_GOTPCREL;
}
@ -92,8 +96,11 @@ ClassifyGlobalReference(const GlobalValue *GV, const TargetMachine &TM) const {
}
if (isPICStyleGOT()) { // 32-bit ELF targets.
// Extra load is needed for all externally visible.
if (GV->hasLocalLinkage() || GV->hasHiddenVisibility())
// Extra load is needed for all externally visible globals except with
// PIE as the definition of the global in an executable is not overridden.
if (GV->hasLocalLinkage() || GV->hasHiddenVisibility() ||
isGlobalDefinedInPIE(GV, TM))
return X86II::MO_GOTOFF;
return X86II::MO_GOT;
}

View File

@ -548,6 +548,14 @@ public:
}
}
/// Determine if this global is defined in a Position Independent
/// Executable (PIE) where its definition cannot be interposed.
bool isGlobalDefinedInPIE(const GlobalValue *GV,
const TargetMachine &TM) const {
return TM.Options.PositionIndependentExecutable &&
!GV->isDeclarationForLinker();
}
/// ClassifyGlobalReference - Classify a global variable reference for the
/// current subtarget according to how we should reference it in a non-pcrel
/// context.

View File

@ -39,7 +39,7 @@ entry:
define i32 @f1() {
; X32-LABEL: f1:
; X32: movl __emutls_v.i@GOT(%ebx), %eax
; X32: leal __emutls_v.i@GOTOFF(%ebx), %eax
; X32-NEXT: movl %eax, (%esp)
; X32-NEXT: calll __emutls_get_address@PLT
; X32-NEXT: movl (%eax), %eax
@ -47,7 +47,7 @@ define i32 @f1() {
; X32-NEXT: popl %ebx
; X32-NEXT: retl
; X64-LABEL: f1:
; X64: movq __emutls_v.i@GOTPCREL(%rip), %rdi
; X64: leaq __emutls_v.i(%rip), %rdi
; X64-NEXT: callq __emutls_get_address@PLT
; X64-NEXT: movl (%rax), %eax
; X64-NEXT: popq %rcx
@ -60,11 +60,11 @@ entry:
define i32* @f2() {
; X32-LABEL: f2:
; X32: movl __emutls_v.i@GOT(%ebx), %eax
; X32: leal __emutls_v.i@GOTOFF(%ebx), %eax
; X32-NEXT: movl %eax, (%esp)
; X32-NEXT: calll __emutls_get_address@PLT
; X64-LABEL: f2:
; X64: movq __emutls_v.i@GOTPCREL(%rip), %rdi
; X64: leaq __emutls_v.i(%rip), %rdi
; X64-NEXT: callq __emutls_get_address@PLT
entry:

View File

@ -0,0 +1,119 @@
; RUN: llc < %s -march=x86-64 -mcpu=generic -mtriple=x86_64-linux-gnu -relocation-model=pic -enable-pie \
; RUN: | FileCheck -check-prefix=X64 %s
; RUN: llc < %s -emulated-tls -march=x86 -mcpu=generic -mtriple=i386-linux-gnu -relocation-model=pic -enable-pie \
; RUN: | FileCheck -check-prefix=X32 %s
; External Linkage
@a = global i32 0, align 4
define i32 @my_access_global_a() #0 {
; X32-LABEL: my_access_global_a:
; X32: addl $_GLOBAL_OFFSET_TABLE_{{.*}}, %eax
; X32-NEXT: movl a@GOTOFF(%eax), %eax
; X64-LABEL: my_access_global_a:
; X64: movl a(%rip), %eax
entry:
%0 = load i32, i32* @a, align 4
ret i32 %0
}
; WeakAny Linkage
@b = weak global i32 0, align 4
define i32 @my_access_global_b() #0 {
; X32-LABEL: my_access_global_b:
; X32: addl $_GLOBAL_OFFSET_TABLE_{{.*}}, %eax
; X32-NEXT: movl b@GOTOFF(%eax), %eax
; X64-LABEL: my_access_global_b:
; X64: movl b(%rip), %eax
entry:
%0 = load i32, i32* @b, align 4
ret i32 %0
}
; Internal Linkage
@c = internal global i32 0, align 4
define i32 @my_access_global_c() #0 {
; X32-LABEL: my_access_global_c:
; X32: addl $_GLOBAL_OFFSET_TABLE_{{.*}}, %eax
; X32-NEXT: movl c@GOTOFF(%eax), %eax
; X64-LABEL: my_access_global_c:
; X64: movl c(%rip), %eax
entry:
%0 = load i32, i32* @c, align 4
ret i32 %0
}
; External Linkage, only declaration.
@d = external global i32, align 4
define i32 @my_access_global_load_d() #0 {
; X32-LABEL: my_access_global_load_d:
; X32: addl $_GLOBAL_OFFSET_TABLE_{{.*}}, %eax
; X32-NEXT: movl d@GOT(%eax), %eax
; X32-NEXT: movl (%eax), %eax
; X64-LABEL: my_access_global_load_d:
; X64: movq d@GOTPCREL(%rip), %rax
; X64-NEXT: movl (%rax), %eax
entry:
%0 = load i32, i32* @d, align 4
ret i32 %0
}
; External Linkage, only declaration, store a value.
define i32 @my_access_global_store_d() #0 {
; X32-LABEL: my_access_global_store_d:
; X32: addl $_GLOBAL_OFFSET_TABLE_{{.*}}, %eax
; X32-NEXT: movl d@GOT(%eax), %eax
; X32-NEXT: movl $2, (%eax)
; X64-LABEL: my_access_global_store_d:
; X64: movq d@GOTPCREL(%rip), %rax
; X64-NEXT: movl $2, (%rax)
entry:
store i32 2, i32* @d, align 4
ret i32 0
}
; External Linkage, function pointer access.
declare i32 @access_fp(i32 ()*)
declare i32 @foo()
define i32 @my_access_fp_foo() #0 {
; X32-LABEL: my_access_fp_foo:
; X32: addl $_GLOBAL_OFFSET_TABLE_{{.*}}, %ebx
; X32-NEXT: movl foo@GOT(%ebx), %eax
; X64-LABEL: my_access_fp_foo:
; X64: movq foo@GOTPCREL(%rip), %rdi
entry:
%call = call i32 @access_fp(i32 ()* @foo)
ret i32 %call
}
; LinkOnceODR Linkage, function pointer access.
$bar = comdat any
define linkonce_odr i32 @bar() comdat {
entry:
ret i32 0
}
define i32 @my_access_fp_bar() #0 {
; X32-LABEL: my_access_fp_bar:
; X32: addl $_GLOBAL_OFFSET_TABLE_{{.*}}, %ebx
; X32-NEXT: leal bar@GOTOFF(%ebx), %eax
; X64-LABEL: my_access_fp_bar:
; X64: leaq bar(%rip), %rdi
entry:
%call = call i32 @access_fp(i32 ()* @bar)
ret i32 %call
}