diff options
author | Mike Pall <mike> | 2011-01-12 18:24:29 +0100 |
---|---|---|
committer | Mike Pall <mike> | 2011-01-12 20:01:35 +0100 |
commit | 2363399b10cf79196df4dde1554027db2b50faf9 (patch) | |
tree | 86592eb1da49cd7485bf885bb280aff2c7d301f3 /src | |
parent | 1548383dbe3d66cc30d58dbfe47afb181702a145 (diff) | |
download | luajit-2363399b10cf79196df4dde1554027db2b50faf9.tar.gz luajit-2363399b10cf79196df4dde1554027db2b50faf9.tar.bz2 luajit-2363399b10cf79196df4dde1554027db2b50faf9.zip |
FFI: Untangle and fix calling convention definitions.
Diffstat (limited to 'src')
-rw-r--r-- | src/lj_ccall.c | 198 | ||||
-rw-r--r-- | src/lj_ccall.h | 23 |
2 files changed, 129 insertions, 92 deletions
diff --git a/src/lj_ccall.c b/src/lj_ccall.c index 57afb57e..6234a05a 100644 --- a/src/lj_ccall.c +++ b/src/lj_ccall.c | |||
@@ -18,11 +18,52 @@ | |||
18 | 18 | ||
19 | /* Target-specific handling of register arguments. */ | 19 | /* Target-specific handling of register arguments. */ |
20 | #if LJ_TARGET_X86 | 20 | #if LJ_TARGET_X86 |
21 | /* -- x86 calling conventions --------------------------------------------- */ | ||
22 | |||
23 | #if LJ_ABI_WIN | ||
24 | |||
25 | #define CCALL_HANDLE_STRUCTRET \ | ||
26 | /* Return structs bigger than 8 by reference (on stack only). */ \ | ||
27 | cc->retref = (sz > 8); \ | ||
28 | if (cc->retref) cc->stack[nsp++] = (GPRArg)dp; | ||
29 | |||
30 | #define CCALL_HANDLE_COMPLEXRET CCALL_HANDLE_STRUCTRET | ||
31 | |||
32 | #else | ||
33 | |||
34 | #define CCALL_HANDLE_STRUCTRET \ | ||
35 | cc->retref = 1; /* Return all structs by reference (in reg or on stack). */ \ | ||
36 | if (ngpr < maxgpr) \ | ||
37 | cc->gpr[ngpr++] = (GPRArg)dp; \ | ||
38 | else \ | ||
39 | cc->stack[nsp++] = (GPRArg)dp; | ||
40 | |||
41 | #define CCALL_HANDLE_COMPLEXRET \ | ||
42 | /* Return complex float in GPRs and complex double by reference. */ \ | ||
43 | cc->retref = (sz > 8); \ | ||
44 | if (cc->retref) { \ | ||
45 | if (ngpr < maxgpr) \ | ||
46 | cc->gpr[ngpr++] = (GPRArg)dp; \ | ||
47 | else \ | ||
48 | cc->stack[nsp++] = (GPRArg)dp; \ | ||
49 | } | ||
50 | |||
51 | #endif | ||
52 | |||
53 | #define CCALL_HANDLE_COMPLEXRET2 \ | ||
54 | if (!cc->retref) \ | ||
55 | *(int64_t *)dp = *(int64_t *)sp; /* Copy complex float from GPRs. */ | ||
56 | |||
57 | #define CCALL_HANDLE_STRUCTARG \ | ||
58 | ngpr = maxgpr; /* Pass all structs by value on the stack. */ | ||
59 | |||
60 | #define CCALL_HANDLE_COMPLEXARG \ | ||
61 | isfp = 1; /* Pass complex by value on stack. */ | ||
21 | 62 | ||
22 | #define CCALL_HANDLE_REGARG \ | 63 | #define CCALL_HANDLE_REGARG \ |
23 | if (!isfp) { /* Only non-FP values may be passed in registers. */ \ | 64 | if (!isfp) { /* Only non-FP values may be passed in registers. */ \ |
24 | if (n > 1) { /* Anything > 32 bit is passed on the stack. */ \ | 65 | if (n > 1) { /* Anything > 32 bit is passed on the stack. */ \ |
25 | ngpr = maxgpr; /* Prevent reordering. */ \ | 66 | if (!LJ_ABI_WIN) ngpr = maxgpr; /* Prevent reordering. */ \ |
26 | } else if (ngpr + 1 <= maxgpr) { \ | 67 | } else if (ngpr + 1 <= maxgpr) { \ |
27 | dp = &cc->gpr[ngpr]; \ | 68 | dp = &cc->gpr[ngpr]; \ |
28 | ngpr += n; \ | 69 | ngpr += n; \ |
@@ -31,6 +72,32 @@ | |||
31 | } | 72 | } |
32 | 73 | ||
33 | #elif LJ_TARGET_X64 && LJ_ABI_WIN | 74 | #elif LJ_TARGET_X64 && LJ_ABI_WIN |
75 | /* -- Windows/x64 calling conventions ------------------------------------- */ | ||
76 | |||
77 | #define CCALL_HANDLE_STRUCTRET \ | ||
78 | /* Return structs of size 1, 2, 4 or 8 in a GPR. */ \ | ||
79 | cc->retref = !(sz == 1 || sz == 2 || sz == 4 || sz == 8); \ | ||
80 | if (cc->retref) cc->gpr[ngpr++] = (GPRArg)dp; | ||
81 | |||
82 | #define CCALL_HANDLE_COMPLEXRET CCALL_HANDLE_STRUCTRET | ||
83 | |||
84 | #define CCALL_HANDLE_COMPLEXRET2 \ | ||
85 | if (!cc->retref) \ | ||
86 | *(int64_t *)dp = *(int64_t *)sp; /* Copy complex float from GPRs. */ | ||
87 | |||
88 | #define CCALL_HANDLE_STRUCTARG \ | ||
89 | /* Pass structs of size 1, 2, 4 or 8 in a GPR by value. */ \ | ||
90 | if (!(sz == 1 || sz == 2 || sz == 4 || sz == 8)) { \ | ||
91 | rp = cdataptr(lj_cdata_new(cts, did, sz)); \ | ||
92 | sz = CTSIZE_PTR; /* Pass all other structs by reference. */ \ | ||
93 | } | ||
94 | |||
95 | #define CCALL_HANDLE_COMPLEXARG \ | ||
96 | /* Pass complex float in a GPR and complex double by reference. */ \ | ||
97 | if (sz != 2*sizeof(float)) { \ | ||
98 | rp = cdataptr(lj_cdata_new(cts, did, sz)); \ | ||
99 | sz = CTSIZE_PTR; \ | ||
100 | } | ||
34 | 101 | ||
35 | /* Windows/x64 argument registers are strictly positional (use ngpr). */ | 102 | /* Windows/x64 argument registers are strictly positional (use ngpr). */ |
36 | #define CCALL_HANDLE_REGARG \ | 103 | #define CCALL_HANDLE_REGARG \ |
@@ -41,6 +108,36 @@ | |||
41 | } | 108 | } |
42 | 109 | ||
43 | #elif LJ_TARGET_X64 | 110 | #elif LJ_TARGET_X64 |
111 | /* -- POSIX/x64 calling conventions --------------------------------------- */ | ||
112 | |||
113 | #define CCALL_HANDLE_STRUCTRET \ | ||
114 | if (sz <= 16) { \ | ||
115 | cc->retref = 0; \ | ||
116 | goto err_nyi; /* NYI: crazy x64 rules for small structs. */ \ | ||
117 | } else { \ | ||
118 | cc->retref = 1; /* Return all bigger structs by reference. */ \ | ||
119 | cc->gpr[ngpr++] = (GPRArg)dp; \ | ||
120 | } | ||
121 | |||
122 | #define CCALL_HANDLE_COMPLEXRET \ | ||
123 | /* Complex values are returned in one or two FPRs. */ \ | ||
124 | cc->retref = 0; | ||
125 | |||
126 | #define CCALL_HANDLE_COMPLEXRET2 \ | ||
127 | if (ctr->size == 2*sizeof(float)) { /* Copy complex float from FPR. */ \ | ||
128 | *(int64_t *)dp = cc->fpr[0].l[0]; \ | ||
129 | } else { /* Copy non-contiguous complex double from FPRs. */ \ | ||
130 | ((int64_t *)dp)[0] = cc->fpr[0].l[0]; \ | ||
131 | ((int64_t *)dp)[1] = cc->fpr[1].l[0]; \ | ||
132 | } | ||
133 | |||
134 | #define CCALL_HANDLE_STRUCTARG \ | ||
135 | if (sz <= 16) { \ | ||
136 | goto err_nyi; /* NYI: crazy x64 rules for small structs. */ \ | ||
137 | } /* Pass all other structs by value on stack. */ | ||
138 | |||
139 | #define CCALL_HANDLE_COMPLEXARG \ | ||
140 | isfp = 2; /* Pass complex in FPRs or on stack. Needs postprocessing. */ | ||
44 | 141 | ||
45 | #define CCALL_HANDLE_REGARG \ | 142 | #define CCALL_HANDLE_REGARG \ |
46 | if (isfp) { /* Try to pass argument in FPRs. */ \ | 143 | if (isfp) { /* Try to pass argument in FPRs. */ \ |
@@ -59,6 +156,25 @@ | |||
59 | } | 156 | } |
60 | 157 | ||
61 | #elif LJ_TARGET_PPCSPE | 158 | #elif LJ_TARGET_PPCSPE |
159 | /* -- PPC/SPE calling conventions ----------------------------------------- */ | ||
160 | |||
161 | #define CCALL_HANDLE_STRUCTRET \ | ||
162 | cc->retref = 1; /* Return all structs by reference. */ \ | ||
163 | cc->gpr[ngpr++] = (GPRArg)dp; | ||
164 | |||
165 | #define CCALL_HANDLE_COMPLEXRET \ | ||
166 | /* Complex values are returned in 2 or 4 GPRs. */ \ | ||
167 | cc->retref = 0; | ||
168 | |||
169 | #define CCALL_HANDLE_COMPLEXRET2 \ | ||
170 | memcpy(dp, sp, ctr->size); /* Copy complex from GPRs. */ | ||
171 | |||
172 | #define CCALL_HANDLE_STRUCTARG \ | ||
173 | rp = cdataptr(lj_cdata_new(cts, did, sz)); \ | ||
174 | sz = CTSIZE_PTR; /* Pass all structs by reference. */ | ||
175 | |||
176 | #define CCALL_HANDLE_COMPLEXARG \ | ||
177 | /* Pass complex by value in 2 or 4 GPRs. */ | ||
62 | 178 | ||
63 | /* PPC/SPE has a softfp ABI. */ | 179 | /* PPC/SPE has a softfp ABI. */ |
64 | #define CCALL_HANDLE_REGARG \ | 180 | #define CCALL_HANDLE_REGARG \ |
@@ -76,7 +192,7 @@ | |||
76 | } | 192 | } |
77 | 193 | ||
78 | #else | 194 | #else |
79 | #error "missing definition for handling of register arguments" | 195 | #error "missing calling convention definitions for this architecture" |
80 | #endif | 196 | #endif |
81 | 197 | ||
82 | /* Infer the destination CTypeID for a vararg argument. */ | 198 | /* Infer the destination CTypeID for a vararg argument. */ |
@@ -146,31 +262,12 @@ static int ccall_set_args(lua_State *L, CTState *cts, CType *ct, | |||
146 | /* Preallocate cdata object and anchor it after arguments. */ | 262 | /* Preallocate cdata object and anchor it after arguments. */ |
147 | CTSize sz = ctr->size; | 263 | CTSize sz = ctr->size; |
148 | GCcdata *cd = lj_cdata_new(cts, ctype_cid(ct->info), sz); | 264 | GCcdata *cd = lj_cdata_new(cts, ctype_cid(ct->info), sz); |
265 | void *dp = cdataptr(cd); | ||
149 | setcdataV(L, L->top++, cd); | 266 | setcdataV(L, L->top++, cd); |
150 | if (ctype_iscomplex(ctr->info)) { | 267 | if (ctype_isstruct(ctr->info)) { |
151 | cc->retref = (sz == 2*sizeof(float)) ? CCALL_COMPLEXF_RETREF : | 268 | CCALL_HANDLE_STRUCTRET |
152 | CCALL_COMPLEX_RETREF; | ||
153 | } else { | 269 | } else { |
154 | #if CCALL_STRUCT_RETREF | 270 | CCALL_HANDLE_COMPLEXRET |
155 | cc->retref = 1; /* Return all structs by reference. */ | ||
156 | #elif LJ_TARGET_X64 | ||
157 | #if LJ_ABI_WIN | ||
158 | /* Return structs of size 1, 2, 4 or 8 in a GPR. */ | ||
159 | cc->retref = !(sz == 1 || sz == 2 || sz == 4 || sz == 8); | ||
160 | #else | ||
161 | if (sz <= 16) goto err_nyi; /* NYI: crazy x64 rules for structs. */ | ||
162 | cc->retref = 1; /* Return all bigger structs by reference. */ | ||
163 | #endif | ||
164 | #else | ||
165 | #error "missing definition for handling of struct return values" | ||
166 | #endif | ||
167 | } | ||
168 | /* Pass reference to returned aggregate in first argument. */ | ||
169 | if (cc->retref) { | ||
170 | if (ngpr < maxgpr) | ||
171 | cc->gpr[ngpr++] = (GPRArg)cdataptr(cd); | ||
172 | else | ||
173 | cc->stack[nsp++] = (GPRArg)cdataptr(cd); | ||
174 | } | 271 | } |
175 | #if LJ_TARGET_X86 | 272 | #if LJ_TARGET_X86 |
176 | } else if (ctype_isfp(ctr->info)) { | 273 | } else if (ctype_isfp(ctr->info)) { |
@@ -213,30 +310,10 @@ static int ccall_set_args(lua_State *L, CTState *cts, CType *ct, | |||
213 | isfp = 1; | 310 | isfp = 1; |
214 | else | 311 | else |
215 | goto err_nyi; | 312 | goto err_nyi; |
216 | } else if (ctype_iscomplex(d->info)) { | ||
217 | #if CCALL_COMPLEX_ARGREF | ||
218 | rp = cdataptr(lj_cdata_new(cts, did, sz)); | ||
219 | sz = CTSIZE_PTR; | ||
220 | #else | ||
221 | isfp = 2; | ||
222 | #endif | ||
223 | } else if (ctype_isstruct(d->info)) { | 313 | } else if (ctype_isstruct(d->info)) { |
224 | int sref = CCALL_STRUCT_ARGREF; | 314 | CCALL_HANDLE_STRUCTARG |
225 | #if LJ_TARGET_X86 | 315 | } else if (ctype_iscomplex(d->info)) { |
226 | ngpr = maxgpr; /* Pass all structs by value on the stack. */ | 316 | CCALL_HANDLE_COMPLEXARG |
227 | #elif LJ_TARGET_X64 | ||
228 | #if LJ_ABI_WIN | ||
229 | /* Pass structs of size 1, 2, 4 or 8 in a GPR by value. */ | ||
230 | sref = !(sz == 1 || sz == 2 || sz == 4 || sz == 8); | ||
231 | #else | ||
232 | if (sz <= 16) goto err_nyi; /* NYI: crazy x64 rules for structs. */ | ||
233 | /* Pass all bigger structs by value on the stack. */ | ||
234 | #endif | ||
235 | #endif | ||
236 | if (sref) { /* Pass struct by reference. */ | ||
237 | rp = cdataptr(lj_cdata_new(cts, did, sz)); | ||
238 | sz = CTSIZE_PTR; /* Pass all other structs by reference. */ | ||
239 | } | ||
240 | } else { | 317 | } else { |
241 | sz = CTSIZE_PTR; | 318 | sz = CTSIZE_PTR; |
242 | } | 319 | } |
@@ -274,9 +351,8 @@ static int ccall_set_args(lua_State *L, CTState *cts, CType *ct, | |||
274 | } | 351 | } |
275 | #endif | 352 | #endif |
276 | #if LJ_TARGET_X64 && !LJ_ABI_WIN | 353 | #if LJ_TARGET_X64 && !LJ_ABI_WIN |
277 | if (isfp == 2 && n == 2 && | 354 | if (isfp == 2 && n == 2 && (uint8_t *)dp == (uint8_t *)&cc->fpr[nfpr-2]) { |
278 | (uint8_t *)dp == (uint8_t *)&cc->fpr[nfpr-2]) { | 355 | cc->fpr[nfpr-1].d[0] = cc->fpr[nfpr-2].d[1]; /* Split complex double. */ |
279 | cc->fpr[nfpr-1].d[0] = cc->fpr[nfpr-2].d[1]; | ||
280 | cc->fpr[nfpr-2].d[1] = 0; | 356 | cc->fpr[nfpr-2].d[1] = 0; |
281 | } | 357 | } |
282 | #endif | 358 | #endif |
@@ -306,7 +382,7 @@ static int ccall_get_results(lua_State *L, CTState *cts, CType *ct, | |||
306 | *ret = 1; /* One result. */ | 382 | *ret = 1; /* One result. */ |
307 | if (ctype_isstruct(ctr->info)) { | 383 | if (ctype_isstruct(ctr->info)) { |
308 | /* Return cdata object which is already on top of stack. */ | 384 | /* Return cdata object which is already on top of stack. */ |
309 | if (!CCALL_STRUCT_RETREF && !cc->retref) { | 385 | if (!cc->retref) { |
310 | void *dp = cdataptr(cdataV(L->top-1)); /* Use preallocated object. */ | 386 | void *dp = cdataptr(cdataV(L->top-1)); /* Use preallocated object. */ |
311 | memcpy(dp, sp, ctr->size); /* Copy struct return value from GPRs. */ | 387 | memcpy(dp, sp, ctr->size); /* Copy struct return value from GPRs. */ |
312 | } | 388 | } |
@@ -314,24 +390,8 @@ static int ccall_get_results(lua_State *L, CTState *cts, CType *ct, | |||
314 | } | 390 | } |
315 | if (ctype_iscomplex(ctr->info)) { | 391 | if (ctype_iscomplex(ctr->info)) { |
316 | /* Return cdata object which is already on top of stack. */ | 392 | /* Return cdata object which is already on top of stack. */ |
317 | #if !CCALL_COMPLEX_RETREF || !CCALL_COMPLEXF_RETREF | ||
318 | void *dp = cdataptr(cdataV(L->top-1)); /* Use preallocated object. */ | 393 | void *dp = cdataptr(cdataV(L->top-1)); /* Use preallocated object. */ |
319 | #if !CCALL_NUM_FPR | 394 | CCALL_HANDLE_COMPLEXRET2 |
320 | memcpy(dp, sp, ctr->size); /* Copy complex from GPRs. */ | ||
321 | #elif CCALL_COMPLEX_RETREF && !CCALL_COMPLEXF_RETREF | ||
322 | if (ctr->size == 2*sizeof(float)) | ||
323 | *(int64_t *)dp = *(int64_t *)sp; /* Copy complex float from GPRs. */ | ||
324 | #elif LJ_TARGET_X64 | ||
325 | if (ctr->size == 2*sizeof(float)) { /* Copy complex float from FPR. */ | ||
326 | *(int64_t *)dp = cc->fpr[0].l[0]; | ||
327 | } else { /* Copy non-contiguous complex double from FPRs. */ | ||
328 | ((int64_t *)dp)[0] = cc->fpr[0].l[0]; | ||
329 | ((int64_t *)dp)[1] = cc->fpr[1].l[0]; | ||
330 | } | ||
331 | #else | ||
332 | #error "missing definition for handling of complex return values" | ||
333 | #endif | ||
334 | #endif | ||
335 | return 1; /* One GC step. */ | 395 | return 1; /* One GC step. */ |
336 | } | 396 | } |
337 | #if CCALL_NUM_FPR | 397 | #if CCALL_NUM_FPR |
diff --git a/src/lj_ccall.h b/src/lj_ccall.h index 17ed56c7..6f9c58e5 100644 --- a/src/lj_ccall.h +++ b/src/lj_ccall.h | |||
@@ -19,9 +19,6 @@ | |||
19 | #define CCALL_NARG_FPR 0 | 19 | #define CCALL_NARG_FPR 0 |
20 | #define CCALL_NRET_GPR 2 | 20 | #define CCALL_NRET_GPR 2 |
21 | #define CCALL_NRET_FPR 1 /* For FP results on x87 stack. */ | 21 | #define CCALL_NRET_FPR 1 /* For FP results on x87 stack. */ |
22 | #define CCALL_STRUCT_RETREF 1 /* Return structs by reference. */ | ||
23 | #define CCALL_COMPLEX_RETREF 1 /* Return complex by reference. */ | ||
24 | #define CCALL_COMPLEXF_RETREF 0 /* Return complex float by value. */ | ||
25 | #define CCALL_ALIGN_STACKARG 0 /* Don't align argument on stack. */ | 22 | #define CCALL_ALIGN_STACKARG 0 /* Don't align argument on stack. */ |
26 | #elif LJ_ABI_WIN | 23 | #elif LJ_ABI_WIN |
27 | #define CCALL_NARG_GPR 4 | 24 | #define CCALL_NARG_GPR 4 |
@@ -29,9 +26,6 @@ | |||
29 | #define CCALL_NRET_GPR 1 | 26 | #define CCALL_NRET_GPR 1 |
30 | #define CCALL_NRET_FPR 1 | 27 | #define CCALL_NRET_FPR 1 |
31 | #define CCALL_SPS_EXTRA 4 | 28 | #define CCALL_SPS_EXTRA 4 |
32 | #define CCALL_COMPLEX_ARGREF 1 /* Pass complex by reference. */ | ||
33 | #define CCALL_COMPLEX_RETREF 1 /* Return complex by reference. */ | ||
34 | #define CCALL_COMPLEXF_RETREF 0 /* Return complex float by value. */ | ||
35 | #else | 29 | #else |
36 | #define CCALL_NARG_GPR 6 | 30 | #define CCALL_NARG_GPR 6 |
37 | #define CCALL_NARG_FPR 8 | 31 | #define CCALL_NARG_FPR 8 |
@@ -60,8 +54,6 @@ typedef intptr_t GPRArg; | |||
60 | #define CCALL_NRET_GPR 4 /* For softfp complex double. */ | 54 | #define CCALL_NRET_GPR 4 /* For softfp complex double. */ |
61 | #define CCALL_NRET_FPR 0 | 55 | #define CCALL_NRET_FPR 0 |
62 | #define CCALL_SPS_FREE 0 /* NYI */ | 56 | #define CCALL_SPS_FREE 0 /* NYI */ |
63 | #define CCALL_STRUCT_ARGREF 1 /* Pass structs by reference. */ | ||
64 | #define CCALL_STRUCT_RETREF 1 /* Return structs by reference. */ | ||
65 | 57 | ||
66 | typedef intptr_t GPRArg; | 58 | typedef intptr_t GPRArg; |
67 | 59 | ||
@@ -72,21 +64,6 @@ typedef intptr_t GPRArg; | |||
72 | #ifndef CCALL_SPS_EXTRA | 64 | #ifndef CCALL_SPS_EXTRA |
73 | #define CCALL_SPS_EXTRA 0 | 65 | #define CCALL_SPS_EXTRA 0 |
74 | #endif | 66 | #endif |
75 | #ifndef CCALL_STRUCT_ARGREF | ||
76 | #define CCALL_STRUCT_ARGREF 0 | ||
77 | #endif | ||
78 | #ifndef CCALL_STRUCT_RETREF | ||
79 | #define CCALL_STRUCT_RETREF 0 | ||
80 | #endif | ||
81 | #ifndef CCALL_COMPLEX_ARGREF | ||
82 | #define CCALL_COMPLEX_ARGREF 0 | ||
83 | #endif | ||
84 | #ifndef CCALL_COMPLEX_RETREF | ||
85 | #define CCALL_COMPLEX_RETREF 0 | ||
86 | #endif | ||
87 | #ifndef CCALL_COMPLEXF_RETREF | ||
88 | #define CCALL_COMPLEXF_RETREF CCALL_COMPLEX_RETREF | ||
89 | #endif | ||
90 | #ifndef CCALL_VECTOR_REG | 67 | #ifndef CCALL_VECTOR_REG |
91 | #define CCALL_VECTOR_REG 0 | 68 | #define CCALL_VECTOR_REG 0 |
92 | #endif | 69 | #endif |