Issue
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
.)
Answered By - Peter Cordes Answer Checked By - Marie Seifert (WPSolving Admin)