[Issue 14179] New: Posix x86_64 varargs prolog clobbers RDX
via Digitalmars-d-bugs
digitalmars-d-bugs at puremagic.com
Sat Feb 14 14:15:03 PST 2015
https://issues.dlang.org/show_bug.cgi?id=14179
Issue ID: 14179
Summary: Posix x86_64 varargs prolog clobbers RDX
Product: D
Version: D2
Hardware: x86_64
OS: Linux
Status: NEW
Keywords: wrong-code
Severity: blocker
Priority: P1
Component: DMD
Assignee: nobody at puremagic.com
Reporter: yebblies at gmail.com
The compiler generates the required prolog for varargs functions, saving the
registers and filling the __va_argsave structure. When RDX (int reg 3) is used
for a named argument it is not saved into the varargs save space, and is used
as a temp register, discarding the argument value.
================= Prolog description ====================
/* Generate code to move any arguments passed in registers into
* the stack variable __va_argsave,
* so we can reference it via pointers through va_arg().
* struct __va_argsave_t {
* size_t[6] regs;
* real[8] fpregs;
* uint offset_regs;
* uint offset_fpregs;
* void* stack_args;
* void* reg_args;
* }
* The MOVAPS instructions seg fault if data is not aligned on
* 16 bytes, so this gives us a nice check to ensure no mistakes.
MOV voff+0*8[RBP],EDI
MOV voff+1*8[RBP],ESI
MOV voff+2*8[RBP],RDX
MOV voff+3*8[RBP],RCX
MOV voff+4*8[RBP],R8
MOV voff+5*8[RBP],R9
MOVZX EAX,AL // AL = 0..8, # of XMM registers
used
SHL EAX,2 // 4 bytes for each MOVAPS
LEA RDX,offset L2[RIP]
SUB RDX,RAX
LEA RAX,voff+6*8+0x7F[RBP]
JMP EDX
MOVAPS -0x0F[RAX],XMM7 // only save XMM registers if
actually used
MOVAPS -0x1F[RAX],XMM6
MOVAPS -0x2F[RAX],XMM5
MOVAPS -0x3F[RAX],XMM4
MOVAPS -0x4F[RAX],XMM3
MOVAPS -0x5F[RAX],XMM2
MOVAPS -0x6F[RAX],XMM1
MOVAPS -0x7F[RAX],XMM0
L2:
MOV 1[RAX],offset_regs // set __va_argsave.offset_regs
MOV 5[RAX],offset_fpregs // set __va_argsave.offset_fpregs
LEA RDX, Para.size+Para.offset[RBP]
MOV 9[RAX],RDX // set __va_argsave.stack_args
SUB RAX,6*8+0x7F // point to start of __va_argsave
MOV 6*8+8*16+4+4+8[RAX],RAX // set __va_argsave.reg_args
*/
================= Test case ====================
import core.stdc.stdarg;
struct Loc
{
const(char)* filename;
uint linnum;
uint charnum;
}
extern(C++) const(char)* func(Loc loc, const(char)* string, ...)
{
return string;
}
void main()
{
const(char)* s = "hello";
assert(func(Loc(), s) == s);
}
--
More information about the Digitalmars-d-bugs
mailing list