forked from OSchip/llvm-project
parent
6cac934051
commit
3cb773431d
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
}
|
Loading…
Reference in New Issue