Skip to content

ABI transformations are never applied for variadic arguments #172

Closed
klickverbot opened this Issue Sep 29, 2012 · 4 comments

3 participants

@klickverbot
LDC member

There is a big problem with the current ABI code: ABI rewrites (such as for turning a struct into an integer so it gets passed in a single register by LLVM) are only ever applied for formal parameters, but not for variadic parameters. This is a problem on x86_64, where there is no difference between variadic and formal paremeters with regard to the calling convention.

The classification scheme needs to happen at least partly at per-call, not per-declaration basis.

For an example of this, see DMD testcase test12.

@smolt
LDC member
smolt commented Apr 9, 2014

Is this the same issue? This is ARM now. I noticed while writing for iOS that structs passed into the variadic part of a extern C function are being passed by ref instead of by value. C library calls end up not working correctly. Below, apple is passed by value, banana is passed by ref.

struct foo
{
    float a;
    float b;
}

extern (C) void bar(foo a, ...);

__gshared foo apple = {1,2};
__gshared foo banana = {3,4};

void main()
{
    bar(apple, banana);
}

results in this thumb2 assembly

    .thumb_func __Dmain
__Dmain:
    push    {r7, lr}
    movw    r0, :lower16:(__D9vastructd5appleOS9vastructd3foo-(LPC1_0+4))
    mov r7, sp
    movt    r0, :upper16:(__D9vastructd5appleOS9vastructd3foo-(LPC1_0+4))
    movw    r2, :lower16:(__D9vastructd6bananaOS9vastructd3foo-(LPC1_1+4))
LPC1_0:
    add r0, pc
    movt    r2, :upper16:(__D9vastructd6bananaOS9vastructd3foo-(LPC1_1+4))
    ldrd    r0, r1, [r0]
LPC1_1:
    add r2, pc
    blx _bar
    movs    r0, #0
    pop {r7, pc}
@klickverbot
LDC member

It certainly sounds like a good guess, though I'm not quite sure what IR parameter attributes the assembly corresponds to. As I don't have an ARM build of LLVM on this machine, I can't easily double-check this right now, but if it's a question of the byval attribute not being set correctly, UnknownTargetABI::passByVal would be the function responsible for that (and I don't think it is taken into consideration for variadic arguments due to this bug).

@smolt
LDC member
smolt commented May 5, 2014

This seems to work for me. I have it in the iOS fork and now structs are passed by value to extern (C) funcs(…). Didn't make any druntime or phobos unit tests fail either.

smolt@c66fbbe

@kinke
LDC member
kinke commented Feb 25, 2015

Fixed by #768.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.