digitalmars.D.bugs - [Issue 14179] New: Posix x86_64 varargs prolog clobbers RDX
- via Digitalmars-d-bugs (80/80) Feb 14 2015 https://issues.dlang.org/show_bug.cgi?id=14179
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 puremagic.com Reporter: yebblies 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 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); } --
Feb 14 2015