June 18, 2022
https://issues.dlang.org/show_bug.cgi?id=23195

          Issue ID: 23195
           Summary: codegen/calling convention bug causes small non-POD
                    arguments to be broken for extern(C++) functions
           Product: D
           Version: D2
          Hardware: x86_64
                OS: Windows
            Status: NEW
          Severity: major
          Priority: P1
         Component: dmd
          Assignee: nobody@puremagic.com
          Reporter: simon.vanbernem@yahoo.de

Microsoft states in their C++ x64 calling convention that structs with a maximum size of 8 bytes should be passed by value through registers (POD or not doesn't matter). Dmd gets this wrong, and passes them by reference instead, when calling a function marked with extern(C++) that has non-POD arguments of size 8. The called C++ function will then interpret the pointers in the registers as values and compute nosense.

Ldc doesn't have this bug and does the right thing.


For example, for the following definitions:



void imgui_draw_rectangle(ImVec2 min, ImVec2 max);

struct ImVec2{
    float x, y;

    ~this(){}
}



calling imgui_draw_rectangle will load the addresses of min and max into rdx and rcx, instead of loading their values into rdx and rcx.


(https://docs.microsoft.com/en-us/cpp/build/x64-calling-convention?view=msvc-170#parameter-passing)

--