Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue with interfaces and D-style variadic functions #4795

Open
jpiles opened this issue Dec 3, 2024 · 1 comment
Open

Issue with interfaces and D-style variadic functions #4795

jpiles opened this issue Dec 3, 2024 · 1 comment

Comments

@jpiles
Copy link

jpiles commented Dec 3, 2024

The following code segfaults when compiled with LDC, works as expected with DMD:

import std;

interface I {
    void foo(string s1,...);
    void bar(string s1, string s2,...);
}

class C : I {
    override void foo(string s1, ...) {
        writeln("Extra arguments to foo: ",_arguments.length);
        writeln(s1);
    }
    override void bar(string s1, string s2, ...) {
        writeln("Extra arguments to bar: ",_arguments.length);
        writeln(s1, s2);
    }
}

void main() {
    C c = new C();
    c.foo("a", "b"); // This works
    c.bar("a", "b"); // This works
    I i = new C();
    i.foo("a", "b"); // This works
    i.bar("a", "b"); // This segfaults with LDC, works with DMD
    writeln("Done.");
}

As you can see, it's the interface and the number of parameters that it's causing the issues. My guess is that there's some mismatch caused by some hidden parameter due to the interface, but I don't really know the ABI or the internals.

The stack seems pretty much corrupted:

Program received signal SIGSEGV, Segmentation fault.
0x00005555555d24c3 in ?? ()
(gdb) bt
#0  0x00005555555d24c3 in ?? ()
#1  0x0000000000000001 in ?? ()
#2  0x00005555555d24c3 in ?? ()
#3  0x0000000000000021 in ?? ()
#4  0x000055555561d540 in ?? ()
#5  0x00005555556128b0 in ?? ()
#6  0x0000555555612890 in __do_global_dtors_aux_fini_array_entry ()
#7  0x0000000000000001 in ?? ()
#8  0x00005555555d20e4 in ?? ()
#9  0x000055555562e2e0 in ?? ()
#10 0x00005555555d24c3 in ?? ()
#11 0x0000000000000001 in ?? ()
#12 0x00005555555d24c3 in ?? ()
#13 0x0000000000000001 in ?? ()
#14 0x00005555555d24c3 in ?? ()
#15 0x00007ffff7b74030 in ?? ()
#16 0x0000000000000001 in ?? ()
#17 0x00005555555d24c3 in ?? ()
#18 0x0000000000000001 in ?? ()
#19 0x00005555555d24c3 in ?? ()
#20 0x00007ffff7b74000 in ?? ()
#21 0x00007fffffffdb80 in ?? ()
#22 0x00005555555b12dd in rt.dmain2._d_run_main2(char[][], ulong, extern(C) int(char[][]) function).runAll() ()
#23 0x00005555555b11d7 in _d_run_main2 ()
Backtrace stopped: previous frame inner to this frame (corrupt stack?)

LDC config:

LDC - the LLVM D compiler (1.39.0):
  based on DMD v2.109.1 and LLVM 18.1.6
  built with LDC - the LLVM D compiler (1.39.0)
  Default target: x86_64-unknown-linux-gnu
  Host CPU: znver3
  http://dlang.org - http://wiki.dlang.org/LDC
@kinke
Copy link
Member

kinke commented Dec 5, 2024

This is caused by a problem with the interface thunk, which uses musttail, in combination with the byval attribute being applied to s2 for the SysV x86_64 ABI. [The 2 slice components (length and pointer) would be the 6th and 7th low-level words to pass, and to prevent LLVM from passing the length in a register and the pointer on the stack, we use byval to make it pass the entire IR struct (slice) on the stack.] The generated assembly does more than just a straight jump to the actual implementation after offsetting the this pointer (in the first RDI register) though. This is the optimized thunk with v1.38 and LLVM 18; might be an LLVM bug:

_DThn16_9onlineapp1C3barMFAyaQdYv:
	.cfi_startproc
	addq	$-16, %rdi
	movaps	8(%rsp), %xmm8
	movups	%xmm8, (%rsp)
	movaps	%xmm8, 8(%rsp)
	jmp	void onlineapp.C.bar(immutable(char)[], immutable(char)[], ...)@PLT

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants