← Back to index
|
Original Bugzilla link
Bug 13957 – 64 bit C ABI not followed for passing structs with floating+integer types
Status
RESOLVED
Resolution
FIXED
Severity
critical
Priority
P1
Component
dmd
Product
D
Version
D2
Platform
x86_64
OS
Linux
Creation time
2015-01-09T08:23:22Z
Last change time
2020-08-31T20:21:22Z
Keywords
backend, betterC, C++, pull, wrong-code
Assigned to
No Owner
Creator
yebblies
See also
https://issues.dlang.org/show_bug.cgi?id=5570
Comments
Comment #0
by yebblies — 2015-01-09T08:23:22Z
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); }
Comment #1
by andrei — 2018-02-22T17:59:42Z
Related:
https://gist.github.com/Laeeth/9a51e12ce7273bf1ded322d5fb12ab18
from Laeeth Isharc. His comment: "Works with gdc 7.3.0 and not LDC 1.7.0 (DMD front end 2.077.1) or DMD v2.078.2"
Comment #2
by dlang-bot — 2019-07-21T00:10:15Z
@SSoulaimane updated dlang/dmd pull request #10200 "Posix x64 ABI fixes 2" fixing this issue: - Fix issues 5570, 13957 - Testsuite: enable asserts on tests
https://github.com/dlang/dmd/pull/10200
Comment #3
by dlang-bot — 2020-08-31T20:21:22Z
dlang/dmd pull request #10200 "Posix x64 ABI fixes 2" was merged into master: - 8a75689be02725741b2af939d63df432ab7c20f2 by سليمان السهمي (Suleyman Sahmi): Fix issues 5570, 13957 - Testsuite: enable asserts on tests
https://github.com/dlang/dmd/pull/10200