[llvm-dev] PIC and mcmodel=large on x86 doesn't use any relocations

John Reagan via llvm-dev llvm-dev at lists.llvm.org
Thu Oct 27 11:42:54 PDT 2016


We're at the point in our port of OpenVMS to x86 using LLVM to make choices
on mcmodel.  Given OpenVMS's history, our linker will allocate static data
(ie, .data, .bss, .plt, GOT, etc.) in the bottom 32-bits of address space
(ie, 00000000.xxxxxxxx).  However, we support code anywhere in the 64-bit
address space as PIC code (we do this on Itanium today using our own
code-generator and linker).  Given this requirement, I'm looking at the
support for -fPIC and -mcmodel=large.  Either I'm missing something or there
is something broken (and has been for quite a while).

Using the code samples in the AMD64 ABI document, I wrote a little abi.c
program to look at the generated code.  The code from gcc matches almost
exactly what is listed in the ABI document.  However, LLVM seems very
different.  I don't see -fPIC has having any impact with mcmodel=large.

Thanks

John

For example, 

static int src;     // Lsrc: .long
static int dst;     // Ldst: .long
extern int *dptr;   //       .extern dptr
void DataLoadAndStore() {

  // Large Memory Model code sequences from AMD64 abi

  // Figure 3.22: Position-Independent Global Data Load and Store
  //
  // Assume that %r15 has been loaded with GOT address by
  // function prologue.

  // movabs $Lsrc at GOTOFF,%rax  ; R_X86_64_GOTOFF64
  // movabs $Ldst at GOTOFF,%rdx  ; R_X86_64_GOTOFF64
  // movl   (%rax,%r15),%ecx
  // movl   %ecx,(%rdx,%r15)
  dst = src;

  // movabs $dptr at GOT,%rax     ; R_X86_64_GOT64
  // movabs $Ldst at GOTOFF,%rdx  ; R_X86_64_GOTOFF64
  // movq   (%rax,%r15),%rax
  // leaq   (%rdx,%r15),%rcx
  // movq   %rcx,(%rax)
  dptr = &dst;

  // movabs $Lsrc at GOTOFF,%rax  ; R_X86_64_GOTOFF64
  // movabs $dptr at GOT,%rdx     ; R_X86_64_GOT64
  // movl   (%rax,%r15),%ecx
  // movq   (%rdx,%r15),%rdx
  // movl   %ecx,(%rdx)
  *dptr = src;

generates (using 'clang -c -S -fPIC -mcmodel=large'):

DataLoadAndStore:                       # @DataLoadAndStore
        .cfi_startproc
# BB#0:
        pushq   %rbp
.Ltmp0:
        .cfi_def_cfa_offset 16
.Ltmp1:
        .cfi_offset %rbp, -16
        movq    %rsp, %rbp
.Ltmp2:
        .cfi_def_cfa_register %rbp
        movabsq $src, %rax
        movl    (%rax), %ecx
        movabsq $dst, %rdx
        movl    %ecx, (%rdx)
        movabsq $dptr, %rsi
        movq    %rdx, (%rsi)
        movl    (%rax), %ecx
        movl    %ecx, (%rdx)
        movl    (%rax), %ecx
        movq    (%rsi), %rax
        movl    %ecx, (%rax)
        popq    %rbp
        retq

Where are the GOT accesses?  

Where is the computation of the GOT address?  Since it is more than 2GB away
from the code,
the ABI says to generate:

  // ABI document suggests:
  //
  // pushq  %r15
  // leaq   1f(%rip),%r11
  // 1:
  // movabs $_GLOBAL_OFFSET_TABLE_,%r15
  // leaq   (%r11,%r15),%r15
  //
  // gcc generates:
  //
  // .L2:
  // leaq    .L2(%rip), %rax
  // movabsq $_GLOBAL_OFFSET_TABLE_-.L2, %r11
  // addq    %r11, %rax
  //






More information about the llvm-dev mailing list