In some circumstances, we use tags to discriminate between functions. A tag is usually an empty struct:
struct Tag { };
Suppose that I have a function, which uses this tag:
void func(Tag, int a);
Now, let's call this function:
func(Tag(), 42);
And check out the resulting x86-64 disassembly, godbolt:
mov edi, 42
jmp func(Tag, int) # TAILCALL
It is fine, the tag gets completely optimized away: there is no register/stack space allocated for it.
But, if I check out other platforms, the tag has some presence.
On ARM, r0
is used as the tag, and it gets zeroed (seems unnecessary):
mov r1, #42
mov r0, #0
b func(Tag, int)
With MSVC,ecx
is used as the tag, and it is "initialized" from the stack (again, seems unnecessary):
movzx ecx, BYTE PTR $T1[rsp]
mov edx, 42 ; 0000002aH
jmp void func(Tag,int) ; func
My question is: is there a tag technique, which is equally optimized on all these platforms?
Note: I don't find where the SysV ABI specifies that empty classes can be optimized away at parameter passing... (and even, the Itanium C++ ABI says: "Empty classes will be passed no differently from ordinary classes".)