aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMike Pall <mike>2011-01-12 18:24:29 +0100
committerMike Pall <mike>2011-01-12 20:01:35 +0100
commit2363399b10cf79196df4dde1554027db2b50faf9 (patch)
tree86592eb1da49cd7485bf885bb280aff2c7d301f3 /src
parent1548383dbe3d66cc30d58dbfe47afb181702a145 (diff)
downloadluajit-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.c198
-rw-r--r--src/lj_ccall.h23
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
66typedef intptr_t GPRArg; 58typedef 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