2.1 KiB
§218 — A NARROW TYPE AT THE ABI BOUNDARY COSTS AN IN-PLACE sll/sra PAIR — on the RETURN as well as on the PARAMETER (P31 S58)
Extends §43, whose tell is stated in the negative ("absence of in-place sll/sra proves 32-bit
params"). This is the cost direction, and it applies to the return type too, which §43 does not
cover.
1. A NARROW RETURN TYPE IN THE PROTOTYPE COSTS A SIGN-EXTENSION AT EVERY CALL SITE.
func_80183258 (ov_SC04_011, 23 ins): the TU's authoritative prototype is
extern s16 func_80174774(void); (atlas tu=('s16',())). Calling it directly forces an
sll v0,v0,0x10 / sra pair the target does not have — even though the result feeds only a
zero-test. The atlas row is byte-true for the SYMBOL but must not be allowed to reach the call site
uncast. Fix, which is the TU's own house style: a cast-at-call through an s32-returning function
pointer, ((s32 (*)(void))func_80174774)().
2. A NARROW ARG CAST EMITS THE PAIR IN PLACE ON THE ARGUMENT REGISTER — AND PERTURBS HEAD
ALLOCATION. func_8017EAC0 (ov_SC02_011, 16 ins) is the clean A/B: without the (s16)a1
narrowing of arg4 the head is the naive move $a3,$a1 shape, 15 ins; with it, the sll/sra
pair displaces the allocator into routing $a0 through $v0, producing the target's odd
addu $v0,$a0 / addu $a1,$v0 head — 16 ins, MATCH. func_8017C624 shows the same 2-insn
pre-call form (§18484). So a strange-looking head copy chain is a tell for a narrowed argument,
not a scheduling artefact.
3. WHEN THE TU'S DECLARATION IS THE NARROW ONE AND THE TARGET IS 32-BIT, USE §202's DEF-SIDE
ALIAS. func_80185C6C (ov_SC06_029, 7 ins): the TU carries
extern void *func_80185C6C(s16, s32); at four sites, but the target has no sll/sra on $a0
at all — both args are 32-bit. Adopting s16 costs a sign-extension from instruction #1, and a
K&R (int,int)-promoted definition conflicts with the s16 prototype. The definition was banked as
aF80185C6C __asm__("func_80185C6C") with the TU's declarations untouched and callers unaffected.