1 | /* |
2 | ** C type management. |
3 | ** Copyright (C) 2005-2014 Mike Pall. See Copyright Notice in luajit.h |
4 | */ |
5 | |
6 | #include "lj_obj.h" |
7 | |
8 | #if LJ_HASFFI |
9 | |
10 | #include "lj_gc.h" |
11 | #include "lj_err.h" |
12 | #include "lj_str.h" |
13 | #include "lj_tab.h" |
14 | #include "lj_ctype.h" |
15 | #include "lj_ccallback.h" |
16 | |
17 | /* -- C type definitions -------------------------------------------------- */ |
18 | |
19 | /* Predefined typedefs. */ |
20 | #define CTTDDEF(_) \ |
21 | /* Vararg handling. */ \ |
22 | _("va_list", P_VOID) \ |
23 | _("__builtin_va_list", P_VOID) \ |
24 | _("__gnuc_va_list", P_VOID) \ |
25 | /* From stddef.h. */ \ |
26 | _("ptrdiff_t", INT_PSZ) \ |
27 | _("size_t", UINT_PSZ) \ |
28 | _("wchar_t", WCHAR) \ |
29 | /* Subset of stdint.h. */ \ |
30 | _("int8_t", INT8) \ |
31 | _("int16_t", INT16) \ |
32 | _("int32_t", INT32) \ |
33 | _("int64_t", INT64) \ |
34 | _("uint8_t", UINT8) \ |
35 | _("uint16_t", UINT16) \ |
36 | _("uint32_t", UINT32) \ |
37 | _("uint64_t", UINT64) \ |
38 | _("intptr_t", INT_PSZ) \ |
39 | _("uintptr_t", UINT_PSZ) \ |
40 | /* End of typedef list. */ |
41 | |
42 | /* Keywords (only the ones we actually care for). */ |
43 | #define CTKWDEF(_) \ |
44 | /* Type specifiers. */ \ |
45 | _("void", -1, CTOK_VOID) \ |
46 | _("_Bool", 0, CTOK_BOOL) \ |
47 | _("bool", 1, CTOK_BOOL) \ |
48 | _("char", 1, CTOK_CHAR) \ |
49 | _("int", 4, CTOK_INT) \ |
50 | _("__int8", 1, CTOK_INT) \ |
51 | _("__int16", 2, CTOK_INT) \ |
52 | _("__int32", 4, CTOK_INT) \ |
53 | _("__int64", 8, CTOK_INT) \ |
54 | _("float", 4, CTOK_FP) \ |
55 | _("double", 8, CTOK_FP) \ |
56 | _("long", 0, CTOK_LONG) \ |
57 | _("short", 0, CTOK_SHORT) \ |
58 | _("_Complex", 0, CTOK_COMPLEX) \ |
59 | _("complex", 0, CTOK_COMPLEX) \ |
60 | _("__complex", 0, CTOK_COMPLEX) \ |
61 | _("__complex__", 0, CTOK_COMPLEX) \ |
62 | _("signed", 0, CTOK_SIGNED) \ |
63 | _("__signed", 0, CTOK_SIGNED) \ |
64 | _("__signed__", 0, CTOK_SIGNED) \ |
65 | _("unsigned", 0, CTOK_UNSIGNED) \ |
66 | /* Type qualifiers. */ \ |
67 | _("const", 0, CTOK_CONST) \ |
68 | _("__const", 0, CTOK_CONST) \ |
69 | _("__const__", 0, CTOK_CONST) \ |
70 | _("volatile", 0, CTOK_VOLATILE) \ |
71 | _("__volatile", 0, CTOK_VOLATILE) \ |
72 | _("__volatile__", 0, CTOK_VOLATILE) \ |
73 | _("restrict", 0, CTOK_RESTRICT) \ |
74 | _("__restrict", 0, CTOK_RESTRICT) \ |
75 | _("__restrict__", 0, CTOK_RESTRICT) \ |
76 | _("inline", 0, CTOK_INLINE) \ |
77 | _("__inline", 0, CTOK_INLINE) \ |
78 | _("__inline__", 0, CTOK_INLINE) \ |
79 | /* Storage class specifiers. */ \ |
80 | _("typedef", 0, CTOK_TYPEDEF) \ |
81 | _("extern", 0, CTOK_EXTERN) \ |
82 | _("static", 0, CTOK_STATIC) \ |
83 | _("auto", 0, CTOK_AUTO) \ |
84 | _("register", 0, CTOK_REGISTER) \ |
85 | /* GCC Attributes. */ \ |
86 | _("__extension__", 0, CTOK_EXTENSION) \ |
87 | _("__attribute", 0, CTOK_ATTRIBUTE) \ |
88 | _("__attribute__", 0, CTOK_ATTRIBUTE) \ |
89 | _("asm", 0, CTOK_ASM) \ |
90 | _("__asm", 0, CTOK_ASM) \ |
91 | _("__asm__", 0, CTOK_ASM) \ |
92 | /* MSVC Attributes. */ \ |
93 | _("__declspec", 0, CTOK_DECLSPEC) \ |
94 | _("__cdecl", CTCC_CDECL, CTOK_CCDECL) \ |
95 | _("__thiscall", CTCC_THISCALL, CTOK_CCDECL) \ |
96 | _("__fastcall", CTCC_FASTCALL, CTOK_CCDECL) \ |
97 | _("__stdcall", CTCC_STDCALL, CTOK_CCDECL) \ |
98 | _("__ptr32", 4, CTOK_PTRSZ) \ |
99 | _("__ptr64", 8, CTOK_PTRSZ) \ |
100 | /* Other type specifiers. */ \ |
101 | _("struct", 0, CTOK_STRUCT) \ |
102 | _("union", 0, CTOK_UNION) \ |
103 | _("enum", 0, CTOK_ENUM) \ |
104 | /* Operators. */ \ |
105 | _("sizeof", 0, CTOK_SIZEOF) \ |
106 | _("__alignof", 0, CTOK_ALIGNOF) \ |
107 | _("__alignof__", 0, CTOK_ALIGNOF) \ |
108 | /* End of keyword list. */ |
109 | |
110 | /* Type info for predefined types. Size merged in. */ |
111 | static CTInfo lj_ctype_typeinfo[] = { |
112 | #define CTTYINFODEF(id, sz, ct, info) CTINFO((ct),(((sz)&0x3fu)<<10)+(info)), |
113 | #define CTTDINFODEF(name, id) CTINFO(CT_TYPEDEF, CTID_##id), |
114 | #define CTKWINFODEF(name, sz, kw) CTINFO(CT_KW,(((sz)&0x3fu)<<10)+(kw)), |
115 | CTTYDEF(CTTYINFODEF) |
116 | CTTDDEF(CTTDINFODEF) |
117 | CTKWDEF(CTKWINFODEF) |
118 | #undef CTTYINFODEF |
119 | #undef CTTDINFODEF |
120 | #undef CTKWINFODEF |
121 | 0 |
122 | }; |
123 | |
124 | /* Predefined type names collected in a single string. */ |
125 | static const char * const lj_ctype_typenames = |
126 | #define CTTDNAMEDEF(name, id) name "\0" |
127 | #define CTKWNAMEDEF(name, sz, cds) name "\0" |
128 | CTTDDEF(CTTDNAMEDEF) |
129 | CTKWDEF(CTKWNAMEDEF) |
130 | #undef CTTDNAMEDEF |
131 | #undef CTKWNAMEDEF |
132 | ; |
133 | |
134 | #define CTTYPEINFO_NUM (sizeof(lj_ctype_typeinfo)/sizeof(CTInfo)-1) |
135 | #ifdef LUAJIT_CTYPE_CHECK_ANCHOR |
136 | #define CTTYPETAB_MIN CTTYPEINFO_NUM |
137 | #else |
138 | #define CTTYPETAB_MIN 128 |
139 | #endif |
140 | |
141 | /* -- C type interning ---------------------------------------------------- */ |
142 | |
143 | #define ct_hashtype(info, size) (hashrot(info, size) & CTHASH_MASK) |
144 | #define ct_hashname(name) \ |
145 | (hashrot(u32ptr(name), u32ptr(name) + HASH_BIAS) & CTHASH_MASK) |
146 | |
147 | /* Create new type element. */ |
148 | CTypeID lj_ctype_new(CTState *cts, CType **ctp) |
149 | { |
150 | CTypeID id = cts->top; |
151 | CType *ct; |
152 | lua_assert(cts->L); |
153 | if (LJ_UNLIKELY(id >= cts->sizetab)) { |
154 | if (id >= CTID_MAX) lj_err_msg(cts->L, LJ_ERR_TABOV); |
155 | #ifdef LUAJIT_CTYPE_CHECK_ANCHOR |
156 | ct = lj_mem_newvec(cts->L, id+1, CType); |
157 | memcpy(ct, cts->tab, id*sizeof(CType)); |
158 | memset(cts->tab, 0, id*sizeof(CType)); |
159 | lj_mem_freevec(cts->g, cts->tab, cts->sizetab, CType); |
160 | cts->tab = ct; |
161 | cts->sizetab = id+1; |
162 | #else |
163 | lj_mem_growvec(cts->L, cts->tab, cts->sizetab, CTID_MAX, CType); |
164 | #endif |
165 | } |
166 | cts->top = id+1; |
167 | *ctp = ct = &cts->tab[id]; |
168 | ct->info = 0; |
169 | ct->size = 0; |
170 | ct->sib = 0; |
171 | ct->next = 0; |
172 | setgcrefnull(ct->name); |
173 | return id; |
174 | } |
175 | |
176 | /* Intern a type element. */ |
177 | CTypeID lj_ctype_intern(CTState *cts, CTInfo info, CTSize size) |
178 | { |
179 | uint32_t h = ct_hashtype(info, size); |
180 | CTypeID id = cts->hash[h]; |
181 | lua_assert(cts->L); |
182 | while (id) { |
183 | CType *ct = ctype_get(cts, id); |
184 | if (ct->info == info && ct->size == size) |
185 | return id; |
186 | id = ct->next; |
187 | } |
188 | id = cts->top; |
189 | if (LJ_UNLIKELY(id >= cts->sizetab)) { |
190 | if (id >= CTID_MAX) lj_err_msg(cts->L, LJ_ERR_TABOV); |
191 | lj_mem_growvec(cts->L, cts->tab, cts->sizetab, CTID_MAX, CType); |
192 | } |
193 | cts->top = id+1; |
194 | cts->tab[id].info = info; |
195 | cts->tab[id].size = size; |
196 | cts->tab[id].sib = 0; |
197 | cts->tab[id].next = cts->hash[h]; |
198 | setgcrefnull(cts->tab[id].name); |
199 | cts->hash[h] = (CTypeID1)id; |
200 | return id; |
201 | } |
202 | |
203 | /* Add type element to hash table. */ |
204 | static void ctype_addtype(CTState *cts, CType *ct, CTypeID id) |
205 | { |
206 | uint32_t h = ct_hashtype(ct->info, ct->size); |
207 | ct->next = cts->hash[h]; |
208 | cts->hash[h] = (CTypeID1)id; |
209 | } |
210 | |
211 | /* Add named element to hash table. */ |
212 | void lj_ctype_addname(CTState *cts, CType *ct, CTypeID id) |
213 | { |
214 | uint32_t h = ct_hashname(gcref(ct->name)); |
215 | ct->next = cts->hash[h]; |
216 | cts->hash[h] = (CTypeID1)id; |
217 | } |
218 | |
219 | /* Get a C type by name, matching the type mask. */ |
220 | CTypeID lj_ctype_getname(CTState *cts, CType **ctp, GCstr *name, uint32_t tmask) |
221 | { |
222 | CTypeID id = cts->hash[ct_hashname(name)]; |
223 | while (id) { |
224 | CType *ct = ctype_get(cts, id); |
225 | if (gcref(ct->name) == obj2gco(name) && |
226 | ((tmask >> ctype_type(ct->info)) & 1)) { |
227 | *ctp = ct; |
228 | return id; |
229 | } |
230 | id = ct->next; |
231 | } |
232 | *ctp = &cts->tab[0]; /* Simplify caller logic. ctype_get() would assert. */ |
233 | return 0; |
234 | } |
235 | |
236 | /* Get a struct/union/enum/function field by name. */ |
237 | CType *lj_ctype_getfieldq(CTState *cts, CType *ct, GCstr *name, CTSize *ofs, |
238 | CTInfo *qual) |
239 | { |
240 | while (ct->sib) { |
241 | ct = ctype_get(cts, ct->sib); |
242 | if (gcref(ct->name) == obj2gco(name)) { |
243 | *ofs = ct->size; |
244 | return ct; |
245 | } |
246 | if (ctype_isxattrib(ct->info, CTA_SUBTYPE)) { |
247 | CType *fct, *cct = ctype_child(cts, ct); |
248 | CTInfo q = 0; |
249 | while (ctype_isattrib(cct->info)) { |
250 | if (ctype_attrib(cct->info) == CTA_QUAL) q |= cct->size; |
251 | cct = ctype_child(cts, cct); |
252 | } |
253 | fct = lj_ctype_getfieldq(cts, cct, name, ofs, qual); |
254 | if (fct) { |
255 | if (qual) *qual |= q; |
256 | *ofs += ct->size; |
257 | return fct; |
258 | } |
259 | } |
260 | } |
261 | return NULL; /* Not found. */ |
262 | } |
263 | |
264 | /* -- C type information -------------------------------------------------- */ |
265 | |
266 | /* Follow references and get raw type for a C type ID. */ |
267 | CType *lj_ctype_rawref(CTState *cts, CTypeID id) |
268 | { |
269 | CType *ct = ctype_get(cts, id); |
270 | while (ctype_isattrib(ct->info) || ctype_isref(ct->info)) |
271 | ct = ctype_child(cts, ct); |
272 | return ct; |
273 | } |
274 | |
275 | /* Get size for a C type ID. Does NOT support VLA/VLS. */ |
276 | CTSize lj_ctype_size(CTState *cts, CTypeID id) |
277 | { |
278 | CType *ct = ctype_raw(cts, id); |
279 | return ctype_hassize(ct->info) ? ct->size : CTSIZE_INVALID; |
280 | } |
281 | |
282 | /* Get size for a variable-length C type. Does NOT support other C types. */ |
283 | CTSize lj_ctype_vlsize(CTState *cts, CType *ct, CTSize nelem) |
284 | { |
285 | uint64_t xsz = 0; |
286 | if (ctype_isstruct(ct->info)) { |
287 | CTypeID arrid = 0, fid = ct->sib; |
288 | xsz = ct->size; /* Add the struct size. */ |
289 | while (fid) { |
290 | CType *ctf = ctype_get(cts, fid); |
291 | if (ctype_type(ctf->info) == CT_FIELD) |
292 | arrid = ctype_cid(ctf->info); /* Remember last field of VLS. */ |
293 | fid = ctf->sib; |
294 | } |
295 | ct = ctype_raw(cts, arrid); |
296 | } |
297 | lua_assert(ctype_isvlarray(ct->info)); /* Must be a VLA. */ |
298 | ct = ctype_rawchild(cts, ct); /* Get array element. */ |
299 | lua_assert(ctype_hassize(ct->info)); |
300 | /* Calculate actual size of VLA and check for overflow. */ |
301 | xsz += (uint64_t)ct->size * nelem; |
302 | return xsz < 0x80000000u ? (CTSize)xsz : CTSIZE_INVALID; |
303 | } |
304 | |
305 | /* Get type, qualifiers, size and alignment for a C type ID. */ |
306 | CTInfo lj_ctype_info(CTState *cts, CTypeID id, CTSize *szp) |
307 | { |
308 | CTInfo qual = 0; |
309 | CType *ct = ctype_get(cts, id); |
310 | for (;;) { |
311 | CTInfo info = ct->info; |
312 | if (ctype_isenum(info)) { |
313 | /* Follow child. Need to look at its attributes, too. */ |
314 | } else if (ctype_isattrib(info)) { |
315 | if (ctype_isxattrib(info, CTA_QUAL)) |
316 | qual |= ct->size; |
317 | else if (ctype_isxattrib(info, CTA_ALIGN) && !(qual & CTFP_ALIGNED)) |
318 | qual |= CTFP_ALIGNED + CTALIGN(ct->size); |
319 | } else { |
320 | if (!(qual & CTFP_ALIGNED)) qual |= (info & CTF_ALIGN); |
321 | qual |= (info & ~(CTF_ALIGN|CTMASK_CID)); |
322 | lua_assert(ctype_hassize(info) || ctype_isfunc(info)); |
323 | *szp = ctype_isfunc(info) ? CTSIZE_INVALID : ct->size; |
324 | break; |
325 | } |
326 | ct = ctype_get(cts, ctype_cid(info)); |
327 | } |
328 | return qual; |
329 | } |
330 | |
331 | /* Get ctype metamethod. */ |
332 | cTValue *lj_ctype_meta(CTState *cts, CTypeID id, MMS mm) |
333 | { |
334 | CType *ct = ctype_get(cts, id); |
335 | cTValue *tv; |
336 | while (ctype_isattrib(ct->info) || ctype_isref(ct->info)) { |
337 | id = ctype_cid(ct->info); |
338 | ct = ctype_get(cts, id); |
339 | } |
340 | if (ctype_isptr(ct->info) && |
341 | ctype_isfunc(ctype_get(cts, ctype_cid(ct->info))->info)) |
342 | tv = lj_tab_getstr(cts->miscmap, &cts->g->strempty); |
343 | else |
344 | tv = lj_tab_getinth(cts->miscmap, -(int32_t)id); |
345 | if (tv && tvistab(tv) && |
346 | (tv = lj_tab_getstr(tabV(tv), mmname_str(cts->g, mm))) && !tvisnil(tv)) |
347 | return tv; |
348 | return NULL; |
349 | } |
350 | |
351 | /* -- C type representation ----------------------------------------------- */ |
352 | |
353 | /* Fixed max. length of a C type representation. */ |
354 | #define CTREPR_MAX 512 |
355 | |
356 | typedef struct CTRepr { |
357 | char *pb, *pe; |
358 | CTState *cts; |
359 | lua_State *L; |
360 | int needsp; |
361 | int ok; |
362 | char buf[CTREPR_MAX]; |
363 | } CTRepr; |
364 | |
365 | /* Prepend string. */ |
366 | static void ctype_prepstr(CTRepr *ctr, const char *str, MSize len) |
367 | { |
368 | char *p = ctr->pb; |
369 | if (ctr->buf + len+1 > p) { ctr->ok = 0; return; } |
370 | if (ctr->needsp) *--p = ' '; |
371 | ctr->needsp = 1; |
372 | p -= len; |
373 | while (len-- > 0) p[len] = str[len]; |
374 | ctr->pb = p; |
375 | } |
376 | |
377 | #define ctype_preplit(ctr, str) ctype_prepstr((ctr), "" str, sizeof(str)-1) |
378 | |
379 | /* Prepend char. */ |
380 | static void ctype_prepc(CTRepr *ctr, int c) |
381 | { |
382 | if (ctr->buf >= ctr->pb) { ctr->ok = 0; return; } |
383 | *--ctr->pb = c; |
384 | } |
385 | |
386 | /* Prepend number. */ |
387 | static void ctype_prepnum(CTRepr *ctr, uint32_t n) |
388 | { |
389 | char *p = ctr->pb; |
390 | if (ctr->buf + 10+1 > p) { ctr->ok = 0; return; } |
391 | do { *--p = (char)('0' + n % 10); } while (n /= 10); |
392 | ctr->pb = p; |
393 | ctr->needsp = 0; |
394 | } |
395 | |
396 | /* Append char. */ |
397 | static void ctype_appc(CTRepr *ctr, int c) |
398 | { |
399 | if (ctr->pe >= ctr->buf + CTREPR_MAX) { ctr->ok = 0; return; } |
400 | *ctr->pe++ = c; |
401 | } |
402 | |
403 | /* Append number. */ |
404 | static void ctype_appnum(CTRepr *ctr, uint32_t n) |
405 | { |
406 | char buf[10]; |
407 | char *p = buf+sizeof(buf); |
408 | char *q = ctr->pe; |
409 | if (q > ctr->buf + CTREPR_MAX - 10) { ctr->ok = 0; return; } |
410 | do { *--p = (char)('0' + n % 10); } while (n /= 10); |
411 | do { *q++ = *p++; } while (p < buf+sizeof(buf)); |
412 | ctr->pe = q; |
413 | } |
414 | |
415 | /* Prepend qualifiers. */ |
416 | static void ctype_prepqual(CTRepr *ctr, CTInfo info) |
417 | { |
418 | if ((info & CTF_VOLATILE)) ctype_preplit(ctr, "volatile" ); |
419 | if ((info & CTF_CONST)) ctype_preplit(ctr, "const" ); |
420 | } |
421 | |
422 | /* Prepend named type. */ |
423 | static void ctype_preptype(CTRepr *ctr, CType *ct, CTInfo qual, const char *t) |
424 | { |
425 | if (gcref(ct->name)) { |
426 | GCstr *str = gco2str(gcref(ct->name)); |
427 | ctype_prepstr(ctr, strdata(str), str->len); |
428 | } else { |
429 | if (ctr->needsp) ctype_prepc(ctr, ' '); |
430 | ctype_prepnum(ctr, ctype_typeid(ctr->cts, ct)); |
431 | ctr->needsp = 1; |
432 | } |
433 | ctype_prepstr(ctr, t, (MSize)strlen(t)); |
434 | ctype_prepqual(ctr, qual); |
435 | } |
436 | |
437 | static void ctype_repr(CTRepr *ctr, CTypeID id) |
438 | { |
439 | CType *ct = ctype_get(ctr->cts, id); |
440 | CTInfo qual = 0; |
441 | int ptrto = 0; |
442 | for (;;) { |
443 | CTInfo info = ct->info; |
444 | CTSize size = ct->size; |
445 | switch (ctype_type(info)) { |
446 | case CT_NUM: |
447 | if ((info & CTF_BOOL)) { |
448 | ctype_preplit(ctr, "bool" ); |
449 | } else if ((info & CTF_FP)) { |
450 | if (size == sizeof(double)) ctype_preplit(ctr, "double" ); |
451 | else if (size == sizeof(float)) ctype_preplit(ctr, "float" ); |
452 | else ctype_preplit(ctr, "long double" ); |
453 | } else if (size == 1) { |
454 | if (!((info ^ CTF_UCHAR) & CTF_UNSIGNED)) ctype_preplit(ctr, "char" ); |
455 | else if (CTF_UCHAR) ctype_preplit(ctr, "signed char" ); |
456 | else ctype_preplit(ctr, "unsigned char" ); |
457 | } else if (size < 8) { |
458 | if (size == 4) ctype_preplit(ctr, "int" ); |
459 | else ctype_preplit(ctr, "short" ); |
460 | if ((info & CTF_UNSIGNED)) ctype_preplit(ctr, "unsigned" ); |
461 | } else { |
462 | ctype_preplit(ctr, "_t" ); |
463 | ctype_prepnum(ctr, size*8); |
464 | ctype_preplit(ctr, "int" ); |
465 | if ((info & CTF_UNSIGNED)) ctype_prepc(ctr, 'u'); |
466 | } |
467 | ctype_prepqual(ctr, (qual|info)); |
468 | return; |
469 | case CT_VOID: |
470 | ctype_preplit(ctr, "void" ); |
471 | ctype_prepqual(ctr, (qual|info)); |
472 | return; |
473 | case CT_STRUCT: |
474 | ctype_preptype(ctr, ct, qual, (info & CTF_UNION) ? "union" : "struct" ); |
475 | return; |
476 | case CT_ENUM: |
477 | if (id == CTID_CTYPEID) { |
478 | ctype_preplit(ctr, "ctype" ); |
479 | return; |
480 | } |
481 | ctype_preptype(ctr, ct, qual, "enum" ); |
482 | return; |
483 | case CT_ATTRIB: |
484 | if (ctype_attrib(info) == CTA_QUAL) qual |= size; |
485 | break; |
486 | case CT_PTR: |
487 | if ((info & CTF_REF)) { |
488 | ctype_prepc(ctr, '&'); |
489 | } else { |
490 | ctype_prepqual(ctr, (qual|info)); |
491 | if (LJ_64 && size == 4) ctype_preplit(ctr, "__ptr32" ); |
492 | ctype_prepc(ctr, '*'); |
493 | } |
494 | qual = 0; |
495 | ptrto = 1; |
496 | ctr->needsp = 1; |
497 | break; |
498 | case CT_ARRAY: |
499 | if (ctype_isrefarray(info)) { |
500 | ctr->needsp = 1; |
501 | if (ptrto) { ptrto = 0; ctype_prepc(ctr, '('); ctype_appc(ctr, ')'); } |
502 | ctype_appc(ctr, '['); |
503 | if (size != CTSIZE_INVALID) { |
504 | CTSize csize = ctype_child(ctr->cts, ct)->size; |
505 | ctype_appnum(ctr, csize ? size/csize : 0); |
506 | } else if ((info & CTF_VLA)) { |
507 | ctype_appc(ctr, '?'); |
508 | } |
509 | ctype_appc(ctr, ']'); |
510 | } else if ((info & CTF_COMPLEX)) { |
511 | if (size == 2*sizeof(float)) ctype_preplit(ctr, "float" ); |
512 | ctype_preplit(ctr, "complex" ); |
513 | return; |
514 | } else { |
515 | ctype_preplit(ctr, ")))" ); |
516 | ctype_prepnum(ctr, size); |
517 | ctype_preplit(ctr, "__attribute__((vector_size(" ); |
518 | } |
519 | break; |
520 | case CT_FUNC: |
521 | ctr->needsp = 1; |
522 | if (ptrto) { ptrto = 0; ctype_prepc(ctr, '('); ctype_appc(ctr, ')'); } |
523 | ctype_appc(ctr, '('); |
524 | ctype_appc(ctr, ')'); |
525 | break; |
526 | default: |
527 | lua_assert(0); |
528 | break; |
529 | } |
530 | ct = ctype_get(ctr->cts, ctype_cid(info)); |
531 | } |
532 | } |
533 | |
534 | /* Return a printable representation of a C type. */ |
535 | GCstr *lj_ctype_repr(lua_State *L, CTypeID id, GCstr *name) |
536 | { |
537 | global_State *g = G(L); |
538 | CTRepr ctr; |
539 | ctr.pb = ctr.pe = &ctr.buf[CTREPR_MAX/2]; |
540 | ctr.cts = ctype_ctsG(g); |
541 | ctr.L = L; |
542 | ctr.ok = 1; |
543 | ctr.needsp = 0; |
544 | if (name) ctype_prepstr(&ctr, strdata(name), name->len); |
545 | ctype_repr(&ctr, id); |
546 | if (LJ_UNLIKELY(!ctr.ok)) return lj_str_newlit(L, "?" ); |
547 | return lj_str_new(L, ctr.pb, ctr.pe - ctr.pb); |
548 | } |
549 | |
550 | /* Convert int64_t/uint64_t to string with 'LL' or 'ULL' suffix. */ |
551 | GCstr *lj_ctype_repr_int64(lua_State *L, uint64_t n, int isunsigned) |
552 | { |
553 | char buf[1+20+3]; |
554 | char *p = buf+sizeof(buf); |
555 | int sign = 0; |
556 | *--p = 'L'; *--p = 'L'; |
557 | if (isunsigned) { |
558 | *--p = 'U'; |
559 | } else if ((int64_t)n < 0) { |
560 | n = (uint64_t)-(int64_t)n; |
561 | sign = 1; |
562 | } |
563 | do { *--p = (char)('0' + n % 10); } while (n /= 10); |
564 | if (sign) *--p = '-'; |
565 | return lj_str_new(L, p, (size_t)(buf+sizeof(buf)-p)); |
566 | } |
567 | |
568 | /* Convert complex to string with 'i' or 'I' suffix. */ |
569 | GCstr *lj_ctype_repr_complex(lua_State *L, void *sp, CTSize size) |
570 | { |
571 | char buf[2*LJ_STR_NUMBUF+2+1]; |
572 | TValue re, im; |
573 | size_t len; |
574 | if (size == 2*sizeof(double)) { |
575 | re.n = *(double *)sp; im.n = ((double *)sp)[1]; |
576 | } else { |
577 | re.n = (double)*(float *)sp; im.n = (double)((float *)sp)[1]; |
578 | } |
579 | len = lj_str_bufnum(buf, &re); |
580 | if (!(im.u32.hi & 0x80000000u) || im.n != im.n) buf[len++] = '+'; |
581 | len += lj_str_bufnum(buf+len, &im); |
582 | buf[len] = buf[len-1] >= 'a' ? 'I' : 'i'; |
583 | return lj_str_new(L, buf, len+1); |
584 | } |
585 | |
586 | /* -- C type state -------------------------------------------------------- */ |
587 | |
588 | /* Initialize C type table and state. */ |
589 | CTState *lj_ctype_init(lua_State *L) |
590 | { |
591 | CTState *cts = lj_mem_newt(L, sizeof(CTState), CTState); |
592 | CType *ct = lj_mem_newvec(L, CTTYPETAB_MIN, CType); |
593 | const char *name = lj_ctype_typenames; |
594 | CTypeID id; |
595 | memset(cts, 0, sizeof(CTState)); |
596 | cts->tab = ct; |
597 | cts->sizetab = CTTYPETAB_MIN; |
598 | cts->top = CTTYPEINFO_NUM; |
599 | cts->L = NULL; |
600 | cts->g = G(L); |
601 | for (id = 0; id < CTTYPEINFO_NUM; id++, ct++) { |
602 | CTInfo info = lj_ctype_typeinfo[id]; |
603 | ct->size = (CTSize)((int32_t)(info << 16) >> 26); |
604 | ct->info = info & 0xffff03ffu; |
605 | ct->sib = 0; |
606 | if (ctype_type(info) == CT_KW || ctype_istypedef(info)) { |
607 | size_t len = strlen(name); |
608 | GCstr *str = lj_str_new(L, name, len); |
609 | ctype_setname(ct, str); |
610 | name += len+1; |
611 | lj_ctype_addname(cts, ct, id); |
612 | } else { |
613 | setgcrefnull(ct->name); |
614 | ct->next = 0; |
615 | if (!ctype_isenum(info)) ctype_addtype(cts, ct, id); |
616 | } |
617 | } |
618 | setmref(G(L)->ctype_state, cts); |
619 | return cts; |
620 | } |
621 | |
622 | /* Free C type table and state. */ |
623 | void lj_ctype_freestate(global_State *g) |
624 | { |
625 | CTState *cts = ctype_ctsG(g); |
626 | if (cts) { |
627 | lj_ccallback_mcode_free(cts); |
628 | lj_mem_freevec(g, cts->tab, cts->sizetab, CType); |
629 | lj_mem_freevec(g, cts->cb.cbid, cts->cb.sizeid, CTypeID1); |
630 | lj_mem_freet(g, cts); |
631 | } |
632 | } |
633 | |
634 | #endif |
635 | |