ljx

FORK: LuaJIT with native 5.2 and 5.3 support
git clone https://git.neptards.moe/neptards/ljx.git
Log | Files | Refs | README

lj_ctype.c (18236B)


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