assemblygccmipsmips64compiler-explorer

What is the name of the default code model used by gcc for MIPS 64?


gcc for MIPS 64 is using a complex method to locate and invoke a function not present in the compilation unit.  What is the name of this code model (and where is it documented)?  I searched but did not find it forthcoming.  It involves $28/$gp and $25/$t9 as some kind of parameter to pass to the called function.

And, is there a bug in this translation (either in code gen or the textual output)?

The following code sequence:

extern int g(int);

int f(int x)
{
    return g(x) + 2;
}

generates this output:

        daddiu  $sp,$sp,-16
        sd      $28,0($sp)
        lui     $28,%hi(%neg(%gp_rel(f(int))))
        daddu   $28,$28,$25                             <--- sourcing $25/$t9 
        daddiu  $28,$28,%lo(%neg(%gp_rel(f(int))))
        ld      $25,%call16(_Z1gi)($28)
        sd      $31,8($sp)
        nop                       <--- where is the function call??

        ld      $31,8($sp)
        ld      $28,0($sp)
        addiu   $2,$2,2
        j       $31
        daddiu  $sp,$sp,16

At my 2nd <-- marker in the above, I would expect to see an indirect function call, but all that's there is a nop (which might have been intended for the delay slot of a call instruction, and is otherwise not explainable).

(At my first marker, it sources $25, so that must be a parameter of some kind provided to f; f appears to also setup $25 maybe for g as well.)


https://godbolt.org/z/11n9nxs63

Adding -msym32 to command line options for the above (which tells it to assume all symbols have a 32-bit address), the code uses direct function call via jal.


Solution

  • Partial answer, to the "is there a bug" part, not the name of the code-model in the MIPS64 ABI.

    Turns out the [compiler-explorer] tag was relevant after all: It was hiding a

    1:   jalr   $25
    

    before the nop (which is indeed in the branch delay slot), which was a target of a .reloc 1f,R_MIPS_JALR,g on the previous line. Uncheck "hide unused labels"; I guess the filtering incorrectly assumes that labels won't be on the same line as instructions, which isn't the case for MIPS.

    So yes, indeed, the this is loading a pointer from the GOT into $25 and jumping through it.

    Apparently with $25 as the function's own address as part of the ABI/calling convention, to enable position-independent code (which apparently Linux MIPS always requires, even though I thought MIPS couldn't do that very efficiently until very recent MIPS revisions for ADDIUPC.)