[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