[Issue 13957] New: 64 bit C ABI not followed for passing structs with floating+integer types
via Digitalmars-d-bugs
digitalmars-d-bugs at puremagic.com
Fri Jan 9 00:23:22 PST 2015
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 at puremagic.com
Reporter: yebblies at 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);
}
--
More information about the Digitalmars-d-bugs
mailing list