Skip to content

Commit

Permalink
[X86] Emit RIP-relative access to local function in PIC medium code m…
Browse files Browse the repository at this point in the history
…odel

Currently, the medium code model for x86_64 emits position-dependent relocations (R_X86_64_64) for local functions, regardless of PIC or no-PIC mode. (This means generically that code compiled with the medium model cannot be linked into a position-independent executable.)

Example:

```
static int g(int n) {
  return 2 * n + 3;
}

void f(int(**p)(int)) {
  *p = g;
}
```

This results in:

```
Disassembly of section .text:

0000000000000000 <f>:
       0: 48 b8 00 00 00 00 00 00 00 00	movabs	rax, 0x0
       a: 48 89 07                     	mov	qword ptr [rdi], rax
       d: c3                           	ret
```

```
Relocation section '.rela.text' at offset 0xf0 contains 1 entries:
    Offset             Info             Type               Symbol's Value  Symbol's Name + Addend
0000000000000002  0000000200000001 R_X86_64_64            0000000000000000 .text + 10
```

This patch changes the behaviour to unconditionally emit a RIP-relative access, both in PIC and non-PIC mode. This fixes PIC mode, and is perhaps an improvement in non-PIC mode, too, since it results in a shorter instruction. A 32-bit relocation should suffice since the medium memory model demands that all code fit within 2GiB.

Reviewed By: MaskRay

Differential Revision: https://reviews.llvm.org/D140593
  • Loading branch information
tkoeppe authored and MaskRay committed Dec 28, 2022
1 parent 935a652 commit 82be8a1
Show file tree
Hide file tree
Showing 2 changed files with 10 additions and 4 deletions.
6 changes: 6 additions & 0 deletions llvm/lib/Target/X86/X86ISelLowering.cpp
Expand Up @@ -20493,6 +20493,12 @@ unsigned X86TargetLowering::getGlobalWrapperKind(
(M == CodeModel::Small || M == CodeModel::Kernel))
return X86ISD::WrapperRIP;

// In the medium model, functions can always be referenced RIP-relatively,
// since they must be within 2GiB. This is also possible in non-PIC mode, and
// shorter than the 64-bit absolute immediate that would otherwise be emitted.
if (M == CodeModel::Medium && isa_and_nonnull<Function>(GV))
return X86ISD::WrapperRIP;

// GOTPCREL references must always use RIP.
if (OpFlags == X86II::MO_GOTPCREL || OpFlags == X86II::MO_GOTPCREL_NORELAX)
return X86ISD::WrapperRIP;
Expand Down
8 changes: 4 additions & 4 deletions llvm/test/CodeGen/X86/code-model-elf.ll
Expand Up @@ -270,7 +270,7 @@ define dso_local ptr @lea_static_fn() #0 {
;
; MEDIUM-STATIC-LABEL: lea_static_fn:
; MEDIUM-STATIC: # %bb.0:
; MEDIUM-STATIC-NEXT: movabsq $static_fn, %rax
; MEDIUM-STATIC-NEXT: leaq static_fn(%rip), %rax
; MEDIUM-STATIC-NEXT: retq
;
; LARGE-STATIC-LABEL: lea_static_fn:
Expand All @@ -285,7 +285,7 @@ define dso_local ptr @lea_static_fn() #0 {
;
; MEDIUM-PIC-LABEL: lea_static_fn:
; MEDIUM-PIC: # %bb.0:
; MEDIUM-PIC-NEXT: movabsq $static_fn, %rax
; MEDIUM-PIC-NEXT: leaq static_fn(%rip), %rax
; MEDIUM-PIC-NEXT: retq
;
; LARGE-PIC-LABEL: lea_static_fn:
Expand All @@ -308,7 +308,7 @@ define dso_local ptr @lea_global_fn() #0 {
;
; MEDIUM-STATIC-LABEL: lea_global_fn:
; MEDIUM-STATIC: # %bb.0:
; MEDIUM-STATIC-NEXT: movabsq $global_fn, %rax
; MEDIUM-STATIC-NEXT: leaq global_fn(%rip), %rax
; MEDIUM-STATIC-NEXT: retq
;
; LARGE-STATIC-LABEL: lea_global_fn:
Expand All @@ -323,7 +323,7 @@ define dso_local ptr @lea_global_fn() #0 {
;
; MEDIUM-PIC-LABEL: lea_global_fn:
; MEDIUM-PIC: # %bb.0:
; MEDIUM-PIC-NEXT: movabsq $global_fn, %rax
; MEDIUM-PIC-NEXT: leaq global_fn(%rip), %rax
; MEDIUM-PIC-NEXT: retq
;
; LARGE-PIC-LABEL: lea_global_fn:
Expand Down

0 comments on commit 82be8a1

Please sign in to comment.