Open JoaoBaptMG opened 2 months ago
One workaround that I found after reading how names are translated from C to Swift is, essentially, to declare it as a free function and "name" it using SWIFT_NAME
, aka:
class MyClass final
{
static MyClass instance;
public:
static MyClass* get();
void test() const;
friend MyStruct MyClass_getStruct(const MyClass* self) SWIFT_NAME(MyClass.getStruct(self:));
} SWIFT_IMMORTAL_REFERENCE;
MyStruct MyClass_getStruct(const MyClass* self)
{
MyStruct str = {2, 4, 6, 8, (uintptr_t)self};
printf("self = %p\n", self);
return str;
}
Will correctly return the following value:
instance = 00007FF7A74B41C8
this = 00007FF7A74B41C8
this = 00007FF7A74B41C8
__C.MyStruct(val0: 2, val1: 4, val2: 6, val3: 8, val4: 140701640376776)
Description
I discovered a bug on the code generation when an instance method defined on a C++ class is called from Swift and returns a struct. From the Swift side, it pushes the struct's stack address on
rcx
and thethis
pointer onrdx
, but C++ expectsthis
onrcx
instead, and the returned struct goes onrdx
.Reproduction
There are two targets, a C++ one and a Swift one.
Package.swift:
Sources/CppProj/include/CppProj.hpp:
Sources/CppProj/CppProj.cpp:
Sources/SwiftProj/main.swift:
Expected behavior
The expected behavior would be to print
instance
,this
andthis
, all having the same value.However, a sample run shows this:
Environment
Additional information
I attached a debugger to the program and set breakpoints on line 21 (
printf("this = %p\n", this);
) of CppProj.cpp, and inspected both stack frames.Running
di -f
on theMyClass::getStruct(void) const
stack frame shows:Which clearly shows that
this
is expected onrcx
, and the return value is expected onrdx
.However,
di -f
on themain.swift
stack frame, on the line that sayslet str = instance.getStruct()
, shows:An interesting thing to notice here is that, while it passes
this
onrcx
tovoid MyClass::test(void) const
, it passesthis
onrdx
(which is wrong) toMyStruct MyClass::getStruct(void) const
, and the returned struct's address goes onrcx
.