Mercurial > pub > dyncall > dyncall
comparison dyncallback/dyncall_args_x64.c @ 557:b36a738c8975
- dyncallback: fix for calling back win/x64 C++ methods returning non-trivial aggregates (thanks Raphael!)
- test/callback_plain_c++:
* added test code for C++ method callbacks returning non-trivial aggregates
* makefile linker command fix (was linking assuming c and not c++)
- test/plain_c++: comments for completeness
author | Tassilo Philipp |
---|---|
date | Sat, 20 Aug 2022 21:04:15 +0200 |
parents | 4d87bd4890b0 |
children | 93ce63d72d59 |
comparison
equal
deleted
inserted
replaced
556:49b60ca068c2 | 557:b36a738c8975 |
---|---|
147 | 147 |
148 return target; | 148 return target; |
149 } | 149 } |
150 | 150 |
151 | 151 |
152 /* A 16 byte struct would be sufficient for System V (because at most two of the four registers can be full). */ | |
153 /* But then it's much more complicated to copy the result to the correct registers in assembly. */ | |
154 typedef struct { | |
155 DClonglong r[2]; /* rax, rdx */ | |
156 DCdouble x[2]; /* xmm0, xmm1 */ | |
157 } DCRetRegs_SysV; | |
158 | |
159 void dcbReturnAggr(DCArgs *args, DCValue *result, DCpointer ret) | 152 void dcbReturnAggr(DCArgs *args, DCValue *result, DCpointer ret) |
160 { | 153 { |
161 int i; | 154 int i; |
162 DCaggr *ag = *(args->aggrs++); | 155 DCaggr *ag = *(args->aggrs++); |
163 | 156 |
164 if(!ag) { | 157 if(args->aggr_return_register >= 0) { |
165 /* non-trivial aggr: all we can do is to provide the ptr to the output space, user has to make copy */ | |
166 result->p = (DCpointer) args->reg_data.i[0]; | |
167 return; | |
168 } | |
169 | |
170 if (args->aggr_return_register >= 0) { | |
171 DCpointer dest = (DCpointer) args->reg_data.i[args->aggr_return_register]; | 158 DCpointer dest = (DCpointer) args->reg_data.i[args->aggr_return_register]; |
172 memcpy(dest, ret, ag->size); | 159 if(ag) |
160 memcpy(dest, ret, ag->size); | |
161 else { | |
162 /* non-trivial aggr: all we can do is to provide the ptr to the output space, user has to make copy */ | |
163 } | |
173 result->p = dest; | 164 result->p = dest; |
174 } else { | 165 } else { |
175 #if defined(DC_UNIX) | 166 #if defined(DC_UNIX) |
167 /* A 16 byte struct would be sufficient for System V (because at most two of the four registers can be full). */ | |
168 /* But then it's much more complicated to copy the result to the correct registers in assembly. */ | |
169 typedef struct { | |
170 DClonglong r[2]; /* rax, rdx */ | |
171 DCdouble x[2]; /* xmm0, xmm1 */ | |
172 } DCRetRegs_SysV; | |
173 | |
176 /* a max of 2 regs are used in this case, out of rax, rdx, xmm0 and xmm1 */ | 174 /* a max of 2 regs are used in this case, out of rax, rdx, xmm0 and xmm1 */ |
177 /* space for 4 qwords is pointed to by (DCRetRegs_SysV*)result */ | 175 /* space for 4 qwords is pointed to by (DCRetRegs_SysV*)result */ |
178 DClonglong *intRegs = ((DCRetRegs_SysV*)result)->r; | 176 DClonglong *intRegs = ((DCRetRegs_SysV*)result)->r; |
179 DCdouble *sseRegs = ((DCRetRegs_SysV*)result)->x; | 177 DCdouble *sseRegs = ((DCRetRegs_SysV*)result)->x; |
180 for(i=0; ag->sysv_classes[i] && i<2/*guaranteed*/; ++i) { | 178 for(i=0; ag->sysv_classes[i] && i<2/*guaranteed*/; ++i) { |