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) {