• source navigation  • diff markup  • identifier search  • freetext search  • 

Sources/ucode/lib/ffi/uc_ctype.c

  1 /*
  2 ** C type management.
  3 ** Copyright (C) 2005-2025 Mike Pall. See Copyright Notice below.
  4 **
  5 ** This file contains derived work from LuaJIT's FFI type system (lj_ctype.c).
  6 **
  7 ** Modifications:
  8 ** - Adapted VM interactions to use ucode's API (uc_vm_t, uc_value_t, etc.)
  9 ** - Adapted type registration and lookup for ucode resource system
 10 ** - Removed JIT-specific code and dependencies
 11 **
 12 ** See NOTICE and ATTRIBUTION.md for complete attribution details.
 13 */
 14 
 15 
 16 #include <stdio.h>
 17 #include <assert.h>
 18 
 19 #include "ucode/util.h"
 20 
 21 #include "uc_ctype.h"
 22 
 23 /* Hash constants from lj_tab.h - inlined since lj_tab.h removed */
 24 #define HASH_ROT1       14
 25 #define HASH_ROT2       5
 26 #define HASH_ROT3       13
 27 
 28 static UC_AINLINE uint32_t hashrot(uint32_t lo, uint32_t hi)
 29 {
 30 #if UC_TARGET_X86ORX64
 31   lo ^= hi; hi = uc_rol(hi, HASH_ROT1);
 32   lo -= hi; hi = uc_rol(hi, HASH_ROT2);
 33   hi ^= lo; hi -= uc_rol(lo, HASH_ROT3);
 34 #else
 35   lo ^= hi;
 36   lo = lo - uc_rol(hi, HASH_ROT1);
 37   hi = lo ^ uc_rol(hi, HASH_ROT1 + HASH_ROT2);
 38   hi = hi - uc_rol(lo, HASH_ROT3);
 39 #endif
 40   return hi;
 41 }
 42 
 43 /* -- C type definitions -------------------------------------------------- */
 44 
 45 /* Predefined typedefs. */
 46 #define CTTDDEF(_)                 \
 47         /* Vararg handling. */         \
 48         _("va_list", P_VOID)           \
 49         _("__builtin_va_list", P_VOID) \
 50         _("__gnuc_va_list", P_VOID)    \
 51         /* From stddef.h. */           \
 52         _("ptrdiff_t", INT_PSZ)        \
 53         _("size_t", UINT_PSZ)          \
 54         _("wchar_t", WCHAR)            \
 55         /* Subset of stdint.h. */      \
 56         _("int8_t", INT8)              \
 57         _("int16_t", INT16)            \
 58         _("int32_t", INT32)            \
 59         _("int64_t", INT64)            \
 60         _("uint8_t", UINT8)            \
 61         _("uint16_t", UINT16)          \
 62         _("uint32_t", UINT32)          \
 63         _("uint64_t", UINT64)          \
 64         _("intptr_t", INT_PSZ)         \
 65         _("uintptr_t", UINT_PSZ)       \
 66         /* From POSIX. */              \
 67         _("ssize_t", INT_PSZ)          \
 68         /* End of typedef list. */
 69 
 70 /* Keywords (only the ones we actually care for). */
 71 #define CTKWDEF(_)                              \
 72         /* Type specifiers. */                      \
 73         _("void", -1, CTOK_VOID)                    \
 74         _("_Bool", 0, CTOK_BOOL)                    \
 75         _("bool", 1, CTOK_BOOL)                     \
 76         _("char", 1, CTOK_CHAR)                     \
 77         _("int", 4, CTOK_INT)                       \
 78         _("__int8", 1, CTOK_INT)                    \
 79         _("__int16", 2, CTOK_INT)                   \
 80         _("__int32", 4, CTOK_INT)                   \
 81         _("__int64", 8, CTOK_INT)                   \
 82         _("float", 4, CTOK_FP)                      \
 83         _("double", 8, CTOK_FP)                     \
 84         _("long", 0, CTOK_LONG)                     \
 85         _("short", 0, CTOK_SHORT)                   \
 86         _("_Complex", 0, CTOK_COMPLEX)              \
 87         _("complex", 0, CTOK_COMPLEX)               \
 88         _("__complex", 0, CTOK_COMPLEX)             \
 89         _("__complex__", 0, CTOK_COMPLEX)           \
 90         _("signed", 0, CTOK_SIGNED)                 \
 91         _("__signed", 0, CTOK_SIGNED)               \
 92         _("__signed__", 0, CTOK_SIGNED)             \
 93         _("unsigned", 0, CTOK_UNSIGNED)             \
 94         /* Type qualifiers. */                      \
 95         _("const", 0, CTOK_CONST)                   \
 96         _("__const", 0, CTOK_CONST)                 \
 97         _("__const__", 0, CTOK_CONST)               \
 98         _("volatile", 0, CTOK_VOLATILE)             \
 99         _("__volatile", 0, CTOK_VOLATILE)           \
100         _("__volatile__", 0, CTOK_VOLATILE)         \
101         _("restrict", 0, CTOK_RESTRICT)             \
102         _("__restrict", 0, CTOK_RESTRICT)           \
103         _("__restrict__", 0, CTOK_RESTRICT)         \
104         _("inline", 0, CTOK_INLINE)                 \
105         _("__inline", 0, CTOK_INLINE)               \
106         _("__inline__", 0, CTOK_INLINE)             \
107         /* Storage class specifiers. */             \
108         _("typedef", 0, CTOK_TYPEDEF)               \
109         _("extern", 0, CTOK_EXTERN)                 \
110         _("static", 0, CTOK_STATIC)                 \
111         _("auto", 0, CTOK_AUTO)                     \
112         _("register", 0, CTOK_REGISTER)             \
113         /* GCC Attributes. */                       \
114         _("__extension__", 0, CTOK_EXTENSION)       \
115         _("__attribute", 0, CTOK_ATTRIBUTE)         \
116         _("__attribute__", 0, CTOK_ATTRIBUTE)       \
117         _("asm", 0, CTOK_ASM)                       \
118         _("__asm", 0, CTOK_ASM)                     \
119         _("__asm__", 0, CTOK_ASM)                   \
120         /* MSVC Attributes. */                      \
121         _("__declspec", 0, CTOK_DECLSPEC)           \
122         _("__cdecl", CTCC_CDECL, CTOK_CCDECL)       \
123         _("__thiscall", CTCC_THISCALL, CTOK_CCDECL) \
124         _("__fastcall", CTCC_FASTCALL, CTOK_CCDECL) \
125         _("__stdcall", CTCC_STDCALL, CTOK_CCDECL)   \
126         _("__ptr32", 4, CTOK_PTRSZ)                 \
127         _("__ptr64", 8, CTOK_PTRSZ)                 \
128         /* Other type specifiers. */                \
129         _("struct", 0, CTOK_STRUCT)                 \
130         _("union", 0, CTOK_UNION)                   \
131         _("enum", 0, CTOK_ENUM)                     \
132         /* Operators. */                            \
133         _("sizeof", 0, CTOK_SIZEOF)                 \
134         _("__alignof", 0, CTOK_ALIGNOF)             \
135         _("__alignof__", 0, CTOK_ALIGNOF)           \
136         /* End of keyword list. */
137 
138 /* Type info for predefined types. Size merged in. */
139 static CTInfo uc_ctype_typeinfo[] = {
140 #define CTTYINFODEF(id, sz, ct, info) CTINFO((ct), (((sz) & 0x3fu) << 10) + (info)),
141 #define CTTDINFODEF(name, id) CTINFO(CT_TYPEDEF, CTID_##id),
142 #define CTKWINFODEF(name, sz, kw) CTINFO(CT_KW, (((sz) & 0x3fu) << 10) + (kw)),
143         CTTYDEF(CTTYINFODEF)
144                 CTTDDEF(CTTDINFODEF)
145                         CTKWDEF(CTKWINFODEF)
146 #undef CTTYINFODEF
147 #undef CTTDINFODEF
148 #undef CTKWINFODEF
149                                 0};
150 
151 /* Predefined type names collected in a single string. */
152 static const char *const uc_ctype_typenames =
153 #define CTTDNAMEDEF(name, id) name "\0"
154 #define CTKWNAMEDEF(name, sz, cds) name "\0"
155         CTTDDEF(CTTDNAMEDEF)
156                 CTKWDEF(CTKWNAMEDEF)
157 #undef CTTDNAMEDEF
158 #undef CTKWNAMEDEF
159         ;
160 
161 #define CTTYPEINFO_NUM (sizeof(uc_ctype_typeinfo) / sizeof(CTInfo) - 1)
162 #ifdef LUAJIT_CTYPE_CHECK_ANCHOR
163 #define CTTYPETAB_MIN CTTYPEINFO_NUM
164 #else
165 #define CTTYPETAB_MIN 128
166 #endif
167 
168 /* -- C type interning ---------------------------------------------------- */
169 
170 #define ct_hashtype(info, size) (hashrot(info, size) & CTHASH_MASK)
171 
172 static inline uint32_t
173 ct_hashname(uc_value_t *uv)
174 {
175         uint8_t *u8 = NULL;
176         size_t len = 0;
177         uint32_t h;
178 
179         h = ucv_type(uv);
180 
181         switch (h)
182         {
183         case UC_STRING:
184                 u8 = (uint8_t *)ucv_string_get(uv);
185                 len = ucv_string_length(uv);
186                 break;
187 
188         default:
189                 assert(0);
190         }
191 
192         while (len > 0)
193         {
194                 h = h * 129 + (*u8++) + LH_PRIME;
195                 len--;
196         }
197 
198         return h & CTHASH_MASK;
199 }
200 
201 /* Create new type element. */
202 CTypeID uc_ctype_new(CTState *cts, CType **ctp)
203 {
204         CTypeID id = cts->vtab.count;
205         CType *ct;
206         if (UC_UNLIKELY(id >= CTID_MAX))
207         {
208                 uc_vm_raise_exception(cts->vm, EXCEPTION_RUNTIME,
209                         "FFI type table overflow");
210                 return 0;
211         }
212 
213         uc_vector_grow(&cts->vtab);
214         *ctp = ct = &cts->vtab.entries[cts->vtab.count++];
215         ct->info = 0;
216         ct->size = 0;
217         ct->sib = 0;
218         ct->next = 0;
219         ct->uv_name = NULL;
220         return id;
221 }
222 
223 /* Intern a type element. */
224 CTypeID uc_ctype_intern(CTState *cts, CTInfo info, CTSize size)
225 {
226         uint32_t h = ct_hashtype(info, size);
227         CTypeID id = cts->hash[h];
228         uc_assertCTS(cts->L, "uninitialized cts->L");
229         while (id)
230         {
231                 CType *ct = ctype_get(cts, id);
232                 if (ct->info == info && ct->size == size)
233                         return id;
234                 id = ct->next;
235         }
236         uc_vector_grow(&cts->vtab);
237         id = cts->vtab.count++;
238         cts->vtab.entries[id].info = info;
239         cts->vtab.entries[id].size = size;
240         cts->vtab.entries[id].sib = 0;
241         cts->vtab.entries[id].next = cts->hash[h];
242         cts->vtab.entries[id].uv_name = NULL;
243         cts->hash[h] = (CTypeID1)id;
244         return id;
245 }
246 
247 /* Add type element to hash table. */
248 static void ctype_addtype(CTState *cts, CType *ct, CTypeID id)
249 {
250         uint32_t h = ct_hashtype(ct->info, ct->size);
251         ct->next = cts->hash[h];
252         cts->hash[h] = (CTypeID1)id;
253 }
254 
255 /* Add named element to hash table. */
256 void uc_ctype_addname(CTState *cts, CType *ct, CTypeID id)
257 {
258         uint32_t h = ct_hashname(ct->uv_name);
259         ct->next = cts->hash[h];
260         cts->hash[h] = (CTypeID1)id;
261 }
262 
263 /* Get a C type by name, matching the type mask. */
264 CTypeID uc_ctype_getname(CTState *cts, CType **ctp, uc_value_t *name, uint32_t tmask)
265 {
266         CTypeID id = cts->hash[ct_hashname(name)];
267         while (id)
268         {
269                 CType *ct = ctype_get(cts, id);
270 
271                 if (ucv_is_equal(ct->uv_name, name) && ((tmask >> ctype_type(ct->info)) & 1))
272                 {
273                         *ctp = ct;
274                         return id;
275                 }
276                 id = ct->next;
277         }
278         *ctp = &cts->vtab.entries[0]; /* Simplify caller logic. ctype_get() would assert. */
279         return 0;
280 }
281 
282 /* Get a struct/union/enum/function field by name. */
283 CType *uc_ctype_getfieldq(CTState *cts, CType *ct, uc_value_t *name, CTSize *ofs,
284                                                   CTInfo *qual)
285 {
286         while (ct->sib)
287         {
288                 ct = ctype_get(cts, ct->sib);
289                 if (ucv_is_equal(ct->uv_name, name))
290                 {
291                         *ofs = ct->size;
292                         return ct;
293                 }
294                 if (ctype_isxattrib(ct->info, CTA_SUBTYPE))
295                 {
296                         CType *fct, *cct = ctype_child(cts, ct);
297                         CTInfo q = 0;
298                         while (ctype_isattrib(cct->info))
299                         {
300                                 if (ctype_attrib(cct->info) == CTA_QUAL)
301                                         q |= cct->size;
302                                 cct = ctype_child(cts, cct);
303                         }
304                         fct = uc_ctype_getfieldq(cts, cct, name, ofs, qual);
305                         if (fct)
306                         {
307                                 if (qual)
308                                         *qual |= q;
309                                 *ofs += ct->size;
310                                 return fct;
311                         }
312                 }
313         }
314         return NULL; /* Not found. */
315 }
316 
317 /* -- C type information -------------------------------------------------- */
318 
319 /* Follow references and get raw type for a C type ID. */
320 CType *uc_ctype_rawref(CTState *cts, CTypeID id)
321 {
322         CType *ct = ctype_get(cts, id);
323         while (ctype_isattrib(ct->info) || ctype_isref(ct->info))
324                 ct = ctype_child(cts, ct);
325         return ct;
326 }
327 
328 /* Get size for a C type ID. Does NOT support VLA/VLS. */
329 CTSize uc_ctype_size(CTState *cts, CTypeID id)
330 {
331         CType *ct = ctype_raw(cts, id);
332         return ctype_hassize(ct->info) ? ct->size : CTSIZE_INVALID;
333 }
334 
335 /* Get size for a variable-length C type. Does NOT support other C types. */
336 CTSize uc_ctype_vlsize(CTState *cts, CType *ct, CTSize nelem)
337 {
338         uint64_t xsz = 0;
339         if (ctype_isstruct(ct->info))
340         {
341                 CTypeID arrid = 0, fid = ct->sib;
342                 xsz = ct->size; /* Add the struct size. */
343                 while (fid)
344                 {
345                         CType *ctf = ctype_get(cts, fid);
346                         if (ctype_type(ctf->info) == CT_FIELD)
347                                 arrid = ctype_cid(ctf->info); /* Remember last field of VLS. */
348                         fid = ctf->sib;
349                 }
350                 ct = ctype_raw(cts, arrid);
351         }
352         uc_assertCTS(ctype_isvlarray(ct->info), "VLA expected");
353         ct = ctype_rawchild(cts, ct); /* Get array element. */
354         uc_assertCTS(ctype_hassize(ct->info), "bad VLA without size");
355         /* Calculate actual size of VLA and check for overflow. */
356         xsz += (uint64_t)ct->size * nelem;
357         return xsz < 0x80000000u ? (CTSize)xsz : CTSIZE_INVALID;
358 }
359 
360 /* Get type, qualifiers, size and alignment for a C type ID. */
361 CTInfo uc_ctype_info(CTState *cts, CTypeID id, CTSize *szp)
362 {
363         CTInfo qual = 0;
364         CType *ct = ctype_get(cts, id);
365         for (;;)
366         {
367                 CTInfo info = ct->info;
368                 if (ctype_isenum(info))
369                 {
370                         /* Follow child. Need to look at its attributes, too. */
371                 }
372                 else if (ctype_isattrib(info))
373                 {
374                         if (ctype_isxattrib(info, CTA_QUAL))
375                                 qual |= ct->size;
376                         else if (ctype_isxattrib(info, CTA_ALIGN) && !(qual & CTFP_ALIGNED))
377                                 qual |= CTFP_ALIGNED + CTALIGN(ct->size);
378                 }
379                 else
380                 {
381                         if (!(qual & CTFP_ALIGNED))
382                                 qual |= (info & CTF_ALIGN);
383                         qual |= (info & ~(CTF_ALIGN | CTMASK_CID));
384                         uc_assertCTS(ctype_hassize(info) || ctype_isfunc(info),
385                                                  "ctype without size");
386                         *szp = ctype_isfunc(info) ? CTSIZE_INVALID : ct->size;
387                         break;
388                 }
389                 ct = ctype_get(cts, ctype_cid(info));
390         }
391         return qual;
392 }
393 
394 /* Ditto, but follow a reference. */
395 CTInfo uc_ctype_info_raw(CTState *cts, CTypeID id, CTSize *szp)
396 {
397         CType *ct = ctype_get(cts, id);
398         if (ctype_isref(ct->info))
399                 id = ctype_cid(ct->info);
400         return uc_ctype_info(cts, id, szp);
401 }
402 
403 /* -- C type representation ----------------------------------------------- */
404 
405 /* Fixed max. length of a C type representation. */
406 #define CTREPR_MAX 512
407 
408 typedef struct CTRepr
409 {
410         char *pb, *pe;
411         CTState *cts;
412         int needsp;
413         int ok;
414         char buf[CTREPR_MAX];
415 } CTRepr;
416 
417 /* Prepend string. */
418 static void ctype_prepstr(CTRepr *ctr, const char *str, size_t len)
419 {
420         char *p = ctr->pb;
421         if (ctr->buf + len + 1 > p)
422         {
423                 ctr->ok = 0;
424                 return;
425         }
426         if (ctr->needsp)
427                 *--p = ' ';
428         ctr->needsp = 1;
429         p -= len;
430         while (len-- > 0)
431                 p[len] = str[len];
432         ctr->pb = p;
433 }
434 
435 #define ctype_preplit(ctr, str) ctype_prepstr((ctr), "" str, sizeof(str) - 1)
436 
437 /* Prepend char. */
438 static void ctype_prepc(CTRepr *ctr, int c)
439 {
440         if (ctr->buf >= ctr->pb)
441         {
442                 ctr->ok = 0;
443                 return;
444         }
445         *--ctr->pb = c;
446 }
447 
448 /* Prepend number. */
449 static void ctype_prepnum(CTRepr *ctr, uint32_t n)
450 {
451         char *p = ctr->pb;
452         if (ctr->buf + 10 + 1 > p)
453         {
454                 ctr->ok = 0;
455                 return;
456         }
457         do
458         {
459                 *--p = (char)('' + n % 10);
460         } while (n /= 10);
461         ctr->pb = p;
462         ctr->needsp = 0;
463 }
464 
465 /* Append char. */
466 static void ctype_appc(CTRepr *ctr, int c)
467 {
468         if (ctr->pe >= ctr->buf + CTREPR_MAX)
469         {
470                 ctr->ok = 0;
471                 return;
472         }
473         *ctr->pe++ = c;
474 }
475 
476 /* Append number. */
477 static void ctype_appnum(CTRepr *ctr, uint32_t n)
478 {
479         char buf[10];
480         char *p = buf + sizeof(buf);
481         char *q = ctr->pe;
482         if (q > ctr->buf + CTREPR_MAX - 10)
483         {
484                 ctr->ok = 0;
485                 return;
486         }
487         do
488         {
489                 *--p = (char)('' + n % 10);
490         } while (n /= 10);
491         do
492         {
493                 *q++ = *p++;
494         } while (p < buf + sizeof(buf));
495         ctr->pe = q;
496 }
497 
498 /* Prepend qualifiers. */
499 static void ctype_prepqual(CTRepr *ctr, CTInfo info)
500 {
501         if ((info & CTF_VOLATILE))
502                 ctype_preplit(ctr, "volatile");
503         if ((info & CTF_CONST))
504                 ctype_preplit(ctr, "const");
505 }
506 
507 /* Prepend named type. */
508 static void ctype_preptype(CTRepr *ctr, CType *ct, CTInfo qual, const char *t)
509 {
510         if (ct->uv_name)
511         {
512                 ctype_prepstr(ctr, ucv_string_get(ct->uv_name), ucv_string_length(ct->uv_name));
513         }
514         else
515         {
516                 if (ctr->needsp)
517                         ctype_prepc(ctr, ' ');
518                 ctype_prepnum(ctr, ctype_typeid(ctr->cts, ct));
519                 ctr->needsp = 1;
520         }
521         ctype_prepstr(ctr, t, strlen(t));
522         ctype_prepqual(ctr, qual);
523 }
524 
525 static void ctype_repr(CTRepr *ctr, CTypeID id)
526 {
527         CType *ct = ctype_get(ctr->cts, id);
528         CTInfo qual = 0;
529         int ptrto = 0;
530         for (;;)
531         {
532                 CTInfo info = ct->info;
533                 CTSize size = ct->size;
534                 switch (ctype_type(info))
535                 {
536                 case CT_NUM:
537                         if ((info & CTF_BOOL))
538                         {
539                                 ctype_preplit(ctr, "bool");
540                         }
541                         else if ((info & CTF_FP))
542                         {
543                                 if (size == sizeof(double))
544                                         ctype_preplit(ctr, "double");
545                                 else if (size == sizeof(float))
546                                         ctype_preplit(ctr, "float");
547                                 else
548                                         ctype_preplit(ctr, "long double");
549                         }
550                         else if (size == 1)
551                         {
552                                 if (!((info ^ CTF_UCHAR) & CTF_UNSIGNED))
553                                         ctype_preplit(ctr, "char");
554                                 else if (CTF_UCHAR)
555                                         ctype_preplit(ctr, "signed char");
556                                 else
557                                         ctype_preplit(ctr, "unsigned char");
558                         }
559                         else if (size < 8)
560                         {
561                                 if (size == 4)
562                                         ctype_preplit(ctr, "int");
563                                 else
564                                         ctype_preplit(ctr, "short");
565                                 if ((info & CTF_UNSIGNED))
566                                         ctype_preplit(ctr, "unsigned");
567                         }
568                         else
569                         {
570                                 ctype_preplit(ctr, "_t");
571                                 ctype_prepnum(ctr, size * 8);
572                                 ctype_preplit(ctr, "int");
573                                 if ((info & CTF_UNSIGNED))
574                                         ctype_prepc(ctr, 'u');
575                         }
576                         ctype_prepqual(ctr, (qual | info));
577                         return;
578                 case CT_VOID:
579                         ctype_preplit(ctr, "void");
580                         ctype_prepqual(ctr, (qual | info));
581                         return;
582                 case CT_STRUCT:
583                         ctype_preptype(ctr, ct, qual, (info & CTF_UNION) ? "union" : "struct");
584                         return;
585                 case CT_ENUM:
586                         if (id == CTID_CTYPEID)
587                         {
588                                 ctype_preplit(ctr, "ctype");
589                                 return;
590                         }
591                         ctype_preptype(ctr, ct, qual, "enum");
592                         return;
593                 case CT_ATTRIB:
594                         if (ctype_attrib(info) == CTA_QUAL)
595                                 qual |= size;
596                         break;
597                 case CT_PTR:
598                         if ((info & CTF_REF))
599                         {
600                                 CType *ct_child = ctype_get(ctr->cts, ctype_cid(info));
601                                 if (ctype_type(ct_child->info) != CT_PTR)
602                                         ctype_prepc(ctr, '&');
603                         }
604                         else
605                         {
606                                 ctype_prepqual(ctr, (qual | info));
607                                 if (UC_64 && size == 4)
608                                         ctype_preplit(ctr, "__ptr32");
609                                 ctype_prepc(ctr, '*');
610                         }
611                         qual = 0;
612                         ptrto = 1;
613                         ctr->needsp = 1;
614                         break;
615                 case CT_ARRAY:
616                         if (ctype_isrefarray(info))
617                         {
618                                 ctr->needsp = 1;
619                                 if (ptrto)
620                                 {
621                                         ptrto = 0;
622                                         ctype_prepc(ctr, '(');
623                                         ctype_appc(ctr, ')');
624                                 }
625                                 ctype_appc(ctr, '[');
626                                 if (size != CTSIZE_INVALID)
627                                 {
628                                         CTSize csize = ctype_child(ctr->cts, ct)->size;
629                                         ctype_appnum(ctr, csize ? size / csize : 0);
630                                 }
631                                 else if ((info & CTF_VLA))
632                                 {
633                                         ctype_appc(ctr, '?');
634                                 }
635                                 ctype_appc(ctr, ']');
636                         }
637                         else if ((info & CTF_COMPLEX))
638                         {
639                                 if (size == 2 * sizeof(float))
640                                         ctype_preplit(ctr, "float");
641                                 ctype_preplit(ctr, "complex");
642                                 return;
643                         }
644                         else
645                         {
646                                 ctype_preplit(ctr, ")))");
647                                 ctype_prepnum(ctr, size);
648                                 ctype_preplit(ctr, "__attribute__((vector_size(");
649                         }
650                         break;
651                 case CT_FUNC:
652                         ctr->needsp = 1;
653                         if (ptrto)
654                         {
655                                 ptrto = 0;
656                                 ctype_prepc(ctr, '(');
657                                 ctype_appc(ctr, ')');
658                         }
659                         ctype_appc(ctr, '(');
660                         ctype_appc(ctr, ')');
661                         break;
662                 default:
663                         uc_assertG_(ctr->cts->g, 0, "bad ctype %08x", info);
664                         break;
665                 }
666                 ct = ctype_get(ctr->cts, ctype_cid(info));
667         }
668 }
669 
670 /* Return a printable representation of a C type. */
671 uc_value_t *uc_ctype_repr(uc_vm_t *vm, CTypeID id, uc_value_t *name)
672 {
673         CTRepr ctr;
674         ctr.pb = ctr.pe = &ctr.buf[CTREPR_MAX / 2];
675         ctr.cts = ctype_cts(vm);
676         ctr.ok = 1;
677         ctr.needsp = 0;
678         if (name)
679                 ctype_prepstr(&ctr, ucv_string_get(name), ucv_string_length(name));
680         ctype_repr(&ctr, id);
681         if (UC_UNLIKELY(!ctr.ok))
682                 return ucv_string_new("?");
683         return ucv_string_new_length(ctr.pb, ctr.pe - ctr.pb);
684 }
685 
686 /* Convert int64_t/uint64_t to string with 'LL' or 'ULL' suffix. */
687 uc_value_t *uc_ctype_repr_int64(uint64_t n, int isunsigned)
688 {
689         char buf[1 + 20 + 3];
690         char *p = buf + sizeof(buf);
691         int sign = 0;
692         *--p = 'L';
693         *--p = 'L';
694         if (isunsigned)
695         {
696                 *--p = 'U';
697         }
698         else if ((int64_t)n < 0)
699         {
700                 n = ~n + 1u;
701                 sign = 1;
702         }
703         do
704         {
705                 *--p = (char)('' + n % 10);
706         } while (n /= 10);
707         if (sign)
708                 *--p = '-';
709         return ucv_string_new_length(p, (size_t)(buf + sizeof(buf) - p));
710 }
711 
712 /* Convert complex to string with 'i' or 'I' suffix. */
713 uc_value_t *uc_ctype_repr_complex(void *sp, CTSize size)
714 {
715         uc_stringbuf_t *sb = ucv_stringbuf_new();
716         TValue re, im;
717         if (size == 2 * sizeof(double))
718         {
719                 re.n = *(double *)sp;
720                 im.n = ((double *)sp)[1];
721         }
722         else
723         {
724                 re.n = (double)*(float *)sp;
725                 im.n = (double)((float *)sp)[1];
726         }
727         ucv_stringbuf_printf(sb, "%.14g", re.n);
728         if (!(im.u32.hi & 0x80000000u) || im.n != im.n)
729                 ucv_stringbuf_append(sb, "+");
730         ucv_stringbuf_printf(sb, "%.14g", im.n);
731         if (sb->buf[sb->bpos - 1] >= 'a')
732                 ucv_stringbuf_append(sb, "I");
733         else
734                 ucv_stringbuf_append(sb, "i");
735         return ucv_stringbuf_finish(sb);
736 }
737 
738 /* -- C type state -------------------------------------------------------- */
739 
740 static void free_ctypes(void *ud)
741 {
742         CTState *cts = ud;
743 
744         while (cts->vtab.count)
745                 ucv_put(cts->vtab.entries[--cts->vtab.count].uv_name);
746 
747         free(cts->vtab.entries);
748         free(cts->vcbid.entries);
749         free(cts);
750 }
751 
752 /* Initialize C type table and state. */
753 CTState *uc_ctype_init(uc_vm_t *vm)
754 {
755         CTState *cts = xalloc(sizeof(CTState));
756         CType *ct; // = lj_mem_newvec(L, CTTYPETAB_MIN, CType);
757         const char *name = uc_ctype_typenames;
758         CTypeID id;
759         memset(cts, 0, sizeof(CTState));
760         // cts->tab = ct;
761         // cts->sizetab = CTTYPETAB_MIN;
762         // cts->top = CTTYPEINFO_NUM;
763         //cts->L = NULL;
764         //cts->g = G(L);
765         cts->vm = vm;
766 
767         for (id = 0; id < CTTYPEINFO_NUM; id++, ct++)
768         {
769                 CTInfo info = uc_ctype_typeinfo[id];
770                 uc_vector_grow(&cts->vtab);
771                 ct = &cts->vtab.entries[cts->vtab.count++];
772                 ct->size = (CTSize)((int32_t)(info << 16) >> 26);
773                 ct->info = info & 0xffff03ffu;
774                 ct->sib = 0;
775                 if (ctype_type(info) == CT_KW || ctype_istypedef(info))
776                 {
777                         size_t len = strlen(name);
778                         uc_value_t *str = ucv_string_new_length(name, len);
779                         ctype_setname(ct, str);
780                         ucv_put(str);
781                         name += len + 1;
782                         uc_ctype_addname(cts, ct, id);
783                 }
784                 else
785                 {
786                         ct->uv_name = NULL;
787                         ct->next = 0;
788                         if (!ctype_isenum(info))
789                                 ctype_addtype(cts, ct, id);
790                 }
791         }
792 
793         //setmref(G(L)->ctype_state, cts);
794 
795         uc_resource_type_t *cts_res;
796 
797         cts_res = ucv_resource_type_add(vm, "ffi.types", NULL, free_ctypes);
798 
799         uc_vm_registry_set(vm, "ffi.types", ucv_resource_new(cts_res, cts));
800 
801         return cts;
802 }
803 

This page was automatically generated by LXR 0.3.1.  •  OpenWrt