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.
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
before the
nop(which is indeed in the branch delay slot), which was a target of a.reloc 1f,R_MIPS_JALR,gon 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
$25and jumping through it.Apparently with
$25as 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 forADDIUPC.)