2

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.

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
Erik Eidt
  • 23,049
  • 2
  • 29
  • 53

1 Answers1

0

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.)

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
  • Wow, great info, thanks! I had wondered if it might be a "textual" problem; wasn't really but something like that (operator (me) error.. ;) – Erik Eidt Jan 12 '22 at 04:01
  • And Linux ABI for MIPS 64 is close enough for me, thanks. – Erik Eidt Jan 12 '22 at 04:02
  • @ErikEidt: I didn't actually check the ABI doc; the incoming $25 is just what I'm inferring from *this* code reading $25 without writing it, and calling another function that way. But I have read before about Linux MIPS using position-independent code. [Is all MIPS code on Linux supposed to be PIC?](https://stackoverflow.com/q/20413290) on SO, and https://www.linux-mips.org/wiki/PIC_code (ah, that says "It is currently not possible to mix non-PIC object files and PIC object files when linking." - presumably that's because the PIC ABI includes passing PC in $25, which non-PIC wouldn't.) – Peter Cordes Jan 12 '22 at 04:04