digitalmars.D.bugs - [Issue 13957] New: 64 bit C ABI not followed for passing structs
- via Digitalmars-d-bugs (106/106) Jan 09 2015 https://issues.dlang.org/show_bug.cgi?id=13957
https://issues.dlang.org/show_bug.cgi?id=13957 Issue ID: 13957 Summary: 64 bit C ABI not followed for passing structs with floating+integer types Product: D Version: D2 Hardware: x86_64 OS: Linux Status: NEW Keywords: wrong-code Severity: critical Priority: P1 Component: DMD Assignee: nobody puremagic.com Reporter: yebblies gmail.com I tried, but I can't work out how to fix this. argtypes.c explicitly ruins passing of this type of struct by passing by memory if one but not both types are floating, but disabling that leads to more problems. There is a bunch of code in elstruct that tries to combine structs into TYcdouble or TYucent, which obviously results in invalid register allocation when trying to pass one of these structs. Disabling that leads to loaddata calling cdrelconst, which somehow manages to load the double value below correctly then load the address of the struct into rdx instead of ulong member. ======================================================== import core.stdc.stdarg; struct S69 { double val_0; ulong val_1; } extern(C++) void cppvararg(char arg0, real arg1, char arg2, S69 arg3, double arg4, int arg5, char arg6); extern(C++) void dvararg(char arg0, real arg1, char arg2, S69 arg3, double arg4, int arg5, char arg6) { checkValues(arg0, arg1, arg2, arg3, arg4, arg5, arg6); } extern(C++) void checkValues(char arg0, real arg1, char arg2, S69 arg3, double arg4, int arg5, char arg6) { import core.stdc.stdio; printf("%d\n", arg0); printf("%Lf\n", arg1); printf("%d\n", arg2); printf("%f\n", arg3.val_0); printf("%lu\n", arg3.val_1); printf("%f\n", arg4); printf("%d\n", arg5); printf("%d\n", arg6); assert(arg0 == 90); assert(arg1 == 2); assert(arg2 == 91); assert(arg3 == S69(4, 92)); assert(arg4 == 8); assert(arg5 == 93); assert(arg6 == 94); } extern(C++) void cppcall(); void main() { char arg0 = 90; real arg1 = 2; char arg2 = 91; S69 arg3 = S69(4, 92); double arg4 = 8; int arg5 = 93; char arg6 = 94; // dvararg(arg0, arg1, arg2, arg3, arg4, arg5, arg6); cppvararg(arg0, arg1, arg2, arg3, arg4, arg5, arg6); // cppcall(); } ============================================================== #include <stdarg.h> #include <stdio.h> struct S69 { double val_0; unsigned long val_1; }; void checkValues(char arg0, long double arg1, char arg2, S69 arg3, double arg4, int arg5, char arg6); void cppvararg(char arg0, long double arg1, char arg2, S69 arg3, double arg4, int arg5, char arg6) { printf("%d\n", arg0); printf("%Lf\n", arg1); printf("%d\n", arg2); printf("%f\n", arg3.val_0); printf("%lu\n", arg3.val_1); printf("%f\n", arg4); printf("%d\n", arg5); printf("%d\n", arg6); checkValues(arg0, arg1, arg2, arg3, arg4, arg5, arg6); } void cppcall() { char arg0 = 90; long double arg1 = 2; char arg2 = 91; S69 arg3 = {4, 92}; double arg4 = 8; int arg5 = 93; char arg6 = 94; // dvararg(arg0, arg1, arg2, arg3, arg4, arg5, arg6); cppvararg(arg0, arg1, arg2, arg3, arg4, arg5, arg6); } --
Jan 09 2015