HiPE calling convention

Hi all

I saw presentation http://www.softlab.ntua.gr/~gtsiour/files/erllvm_pres-20111107.pdf
and I have couple question to the HiPE calling convention. I am trying to enable HiPE call for Rust compiler.

That presentation mentioned that:
Virtual registers with “special” use, pinned to hardware registers
(unallocatable).
VM Register AMD64 Register
Native stack pointer %nsp
Heap pointer %r15
Process pointer %rbp

Reading that I am under impression that both r15 and rbp should not be
used in functions marked using "HiPE" calling convention. That's it
looks like r15 and rbp are reserved some purpose (like addressing
dynamic language argument/locals).
However when trying to enable this calling convention I see quite the opposite.

e.g.

0000000000005e30 <hipe_test::test1>:
    5e30: 49 01 ef add %rbp,%r15
<========== RBP and R15 contain arguments and RBP is clobbered
    5e33: c3 retq
    5e34: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1)
    5e3b: 00 00 00
    5e3e: 66 90 xchg %ax,%ax

0000000000005e40 <hipe_test::test2>:
    5e40: e9 eb ff ff ff jmpq 5e30 <hipe_test::test1>
    5e45: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1)
    5e4c: 00 00 00
    5e4f: 90 nop

0000000000005e50 <hipe_test::main>:
    5e50: 55 push %rbp
    5e51: 41 57 push %r15
    5e53: 41 56 push %r14
    5e55: 41 55 push %r13
    5e57: 41 54 push %r12
    5e59: 53 push %rbx
    5e5a: 48 83 ec 58 sub $0x58,%rsp
    5e5e: 31 db xor %ebx,%ebx
    5e60: 45 31 f6 xor %r14d,%r14d
    5e63: 66 66 66 66 2e 0f 1f data16 data16 data16 nopw
%cs:0x0(%rax,%rax,1)
    5e6a: 84 00 00 00 00 00
    5e70: 4c 89 34 24 mov %r14,(%rsp)
    5e74: 48 89 5c 24 08 mov %rbx,0x8(%rsp)
    5e79: 4c 8b 3c 24 mov (%rsp),%r15
    5e7d: 48 8b 04 24 mov (%rsp),%rax
    5e81: 48 8d 40 01 lea 0x1(%rax),%rax
    5e85: 48 89 04 24 mov %rax,(%rsp)
    5e89: 48 8b 6c 24 08 mov 0x8(%rsp),%rbp
    5e8e: e8 ad ff ff ff callq 5e40 <hipe_test::test2>
    5e93: 48 8b 5c 24 08 mov 0x8(%rsp),%rbx

I am getting that code for following Rust code.
#[inline(never)]
extern "hipe" fn test1(a1:i64, a2:i64) -> i64 {
    a1+a2
}
#[inline(never)]
extern "hipe" fn test2(a1:i64, a2:i64) -> i64 {
    test1(a1, a2)
}
fn main() {
    for i in 0..100 {
        let r=test2(i, i*3);
        println!("{}", r);
    }
}

Could it be that LLVM is wrong here or I am missing something obvious?

Calling conventions should be just that: conventions on how to perfrom calls, I hope we don't have code in LLVM that changes which registers are reserved based on the calling convention.

I assume they used a modified version of LLVM that also reserved those registers, at least I don't see any code in X86RegisterInfo::getReservedRegs() that would result in a heap or process pointer thing getting reserved.

- Matthias

Thanks Matthias.
That definitely makes sense.

BR,
Denis