Mercurial
comparison third_party/luajit/src/lj_ctype.c @ 178:94705b5986b3
[ThirdParty] Added WRK and luajit for load testing.
| author | MrJuneJune <me@mrjunejune.com> |
|---|---|
| date | Thu, 22 Jan 2026 20:10:30 -0800 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 177:24fe8ff94056 | 178:94705b5986b3 |
|---|---|
| 1 /* | |
| 2 ** C type management. | |
| 3 ** Copyright (C) 2005-2023 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 lj_assertCTS(cts->L, "uninitialized 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 lj_assertCTS(cts->L, "uninitialized 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 #ifdef LUAJIT_CTYPE_CHECK_ANCHOR | |
| 195 CType *ct; | |
| 196 #endif | |
| 197 if (id >= CTID_MAX) lj_err_msg(cts->L, LJ_ERR_TABOV); | |
| 198 #ifdef LUAJIT_CTYPE_CHECK_ANCHOR | |
| 199 ct = lj_mem_newvec(cts->L, id+1, CType); | |
| 200 memcpy(ct, cts->tab, id*sizeof(CType)); | |
| 201 memset(cts->tab, 0, id*sizeof(CType)); | |
| 202 lj_mem_freevec(cts->g, cts->tab, cts->sizetab, CType); | |
| 203 cts->tab = ct; | |
| 204 cts->sizetab = id+1; | |
| 205 #else | |
| 206 lj_mem_growvec(cts->L, cts->tab, cts->sizetab, CTID_MAX, CType); | |
| 207 #endif | |
| 208 } | |
| 209 cts->top = id+1; | |
| 210 cts->tab[id].info = info; | |
| 211 cts->tab[id].size = size; | |
| 212 cts->tab[id].sib = 0; | |
| 213 cts->tab[id].next = cts->hash[h]; | |
| 214 setgcrefnull(cts->tab[id].name); | |
| 215 cts->hash[h] = (CTypeID1)id; | |
| 216 return id; | |
| 217 } | |
| 218 | |
| 219 /* Add type element to hash table. */ | |
| 220 static void ctype_addtype(CTState *cts, CType *ct, CTypeID id) | |
| 221 { | |
| 222 uint32_t h = ct_hashtype(ct->info, ct->size); | |
| 223 ct->next = cts->hash[h]; | |
| 224 cts->hash[h] = (CTypeID1)id; | |
| 225 } | |
| 226 | |
| 227 /* Add named element to hash table. */ | |
| 228 void lj_ctype_addname(CTState *cts, CType *ct, CTypeID id) | |
| 229 { | |
| 230 uint32_t h = ct_hashname(gcref(ct->name)); | |
| 231 ct->next = cts->hash[h]; | |
| 232 cts->hash[h] = (CTypeID1)id; | |
| 233 } | |
| 234 | |
| 235 /* Get a C type by name, matching the type mask. */ | |
| 236 CTypeID lj_ctype_getname(CTState *cts, CType **ctp, GCstr *name, uint32_t tmask) | |
| 237 { | |
| 238 CTypeID id = cts->hash[ct_hashname(name)]; | |
| 239 while (id) { | |
| 240 CType *ct = ctype_get(cts, id); | |
| 241 if (gcref(ct->name) == obj2gco(name) && | |
| 242 ((tmask >> ctype_type(ct->info)) & 1)) { | |
| 243 *ctp = ct; | |
| 244 return id; | |
| 245 } | |
| 246 id = ct->next; | |
| 247 } | |
| 248 *ctp = &cts->tab[0]; /* Simplify caller logic. ctype_get() would assert. */ | |
| 249 return 0; | |
| 250 } | |
| 251 | |
| 252 /* Get a struct/union/enum/function field by name. */ | |
| 253 CType *lj_ctype_getfieldq(CTState *cts, CType *ct, GCstr *name, CTSize *ofs, | |
| 254 CTInfo *qual) | |
| 255 { | |
| 256 while (ct->sib) { | |
| 257 ct = ctype_get(cts, ct->sib); | |
| 258 if (gcref(ct->name) == obj2gco(name)) { | |
| 259 *ofs = ct->size; | |
| 260 return ct; | |
| 261 } | |
| 262 if (ctype_isxattrib(ct->info, CTA_SUBTYPE)) { | |
| 263 CType *fct, *cct = ctype_child(cts, ct); | |
| 264 CTInfo q = 0; | |
| 265 while (ctype_isattrib(cct->info)) { | |
| 266 if (ctype_attrib(cct->info) == CTA_QUAL) q |= cct->size; | |
| 267 cct = ctype_child(cts, cct); | |
| 268 } | |
| 269 fct = lj_ctype_getfieldq(cts, cct, name, ofs, qual); | |
| 270 if (fct) { | |
| 271 if (qual) *qual |= q; | |
| 272 *ofs += ct->size; | |
| 273 return fct; | |
| 274 } | |
| 275 } | |
| 276 } | |
| 277 return NULL; /* Not found. */ | |
| 278 } | |
| 279 | |
| 280 /* -- C type information -------------------------------------------------- */ | |
| 281 | |
| 282 /* Follow references and get raw type for a C type ID. */ | |
| 283 CType *lj_ctype_rawref(CTState *cts, CTypeID id) | |
| 284 { | |
| 285 CType *ct = ctype_get(cts, id); | |
| 286 while (ctype_isattrib(ct->info) || ctype_isref(ct->info)) | |
| 287 ct = ctype_child(cts, ct); | |
| 288 return ct; | |
| 289 } | |
| 290 | |
| 291 /* Get size for a C type ID. Does NOT support VLA/VLS. */ | |
| 292 CTSize lj_ctype_size(CTState *cts, CTypeID id) | |
| 293 { | |
| 294 CType *ct = ctype_raw(cts, id); | |
| 295 return ctype_hassize(ct->info) ? ct->size : CTSIZE_INVALID; | |
| 296 } | |
| 297 | |
| 298 /* Get size for a variable-length C type. Does NOT support other C types. */ | |
| 299 CTSize lj_ctype_vlsize(CTState *cts, CType *ct, CTSize nelem) | |
| 300 { | |
| 301 uint64_t xsz = 0; | |
| 302 if (ctype_isstruct(ct->info)) { | |
| 303 CTypeID arrid = 0, fid = ct->sib; | |
| 304 xsz = ct->size; /* Add the struct size. */ | |
| 305 while (fid) { | |
| 306 CType *ctf = ctype_get(cts, fid); | |
| 307 if (ctype_type(ctf->info) == CT_FIELD) | |
| 308 arrid = ctype_cid(ctf->info); /* Remember last field of VLS. */ | |
| 309 fid = ctf->sib; | |
| 310 } | |
| 311 ct = ctype_raw(cts, arrid); | |
| 312 } | |
| 313 lj_assertCTS(ctype_isvlarray(ct->info), "VLA expected"); | |
| 314 ct = ctype_rawchild(cts, ct); /* Get array element. */ | |
| 315 lj_assertCTS(ctype_hassize(ct->info), "bad VLA without size"); | |
| 316 /* Calculate actual size of VLA and check for overflow. */ | |
| 317 xsz += (uint64_t)ct->size * nelem; | |
| 318 return xsz < 0x80000000u ? (CTSize)xsz : CTSIZE_INVALID; | |
| 319 } | |
| 320 | |
| 321 /* Get type, qualifiers, size and alignment for a C type ID. */ | |
| 322 CTInfo lj_ctype_info(CTState *cts, CTypeID id, CTSize *szp) | |
| 323 { | |
| 324 CTInfo qual = 0; | |
| 325 CType *ct = ctype_get(cts, id); | |
| 326 for (;;) { | |
| 327 CTInfo info = ct->info; | |
| 328 if (ctype_isenum(info)) { | |
| 329 /* Follow child. Need to look at its attributes, too. */ | |
| 330 } else if (ctype_isattrib(info)) { | |
| 331 if (ctype_isxattrib(info, CTA_QUAL)) | |
| 332 qual |= ct->size; | |
| 333 else if (ctype_isxattrib(info, CTA_ALIGN) && !(qual & CTFP_ALIGNED)) | |
| 334 qual |= CTFP_ALIGNED + CTALIGN(ct->size); | |
| 335 } else { | |
| 336 if (!(qual & CTFP_ALIGNED)) qual |= (info & CTF_ALIGN); | |
| 337 qual |= (info & ~(CTF_ALIGN|CTMASK_CID)); | |
| 338 lj_assertCTS(ctype_hassize(info) || ctype_isfunc(info), | |
| 339 "ctype without size"); | |
| 340 *szp = ctype_isfunc(info) ? CTSIZE_INVALID : ct->size; | |
| 341 break; | |
| 342 } | |
| 343 ct = ctype_get(cts, ctype_cid(info)); | |
| 344 } | |
| 345 return qual; | |
| 346 } | |
| 347 | |
| 348 /* Ditto, but follow a reference. */ | |
| 349 CTInfo lj_ctype_info_raw(CTState *cts, CTypeID id, CTSize *szp) | |
| 350 { | |
| 351 CType *ct = ctype_get(cts, id); | |
| 352 if (ctype_isref(ct->info)) id = ctype_cid(ct->info); | |
| 353 return lj_ctype_info(cts, id, szp); | |
| 354 } | |
| 355 | |
| 356 /* Get ctype metamethod. */ | |
| 357 cTValue *lj_ctype_meta(CTState *cts, CTypeID id, MMS mm) | |
| 358 { | |
| 359 CType *ct = ctype_get(cts, id); | |
| 360 cTValue *tv; | |
| 361 while (ctype_isattrib(ct->info) || ctype_isref(ct->info)) { | |
| 362 id = ctype_cid(ct->info); | |
| 363 ct = ctype_get(cts, id); | |
| 364 } | |
| 365 if (ctype_isptr(ct->info) && | |
| 366 ctype_isfunc(ctype_get(cts, ctype_cid(ct->info))->info)) | |
| 367 tv = lj_tab_getstr(cts->miscmap, &cts->g->strempty); | |
| 368 else | |
| 369 tv = lj_tab_getinth(cts->miscmap, -(int32_t)id); | |
| 370 if (tv && tvistab(tv) && | |
| 371 (tv = lj_tab_getstr(tabV(tv), mmname_str(cts->g, mm))) && !tvisnil(tv)) | |
| 372 return tv; | |
| 373 return NULL; | |
| 374 } | |
| 375 | |
| 376 /* -- C type representation ----------------------------------------------- */ | |
| 377 | |
| 378 /* Fixed max. length of a C type representation. */ | |
| 379 #define CTREPR_MAX 512 | |
| 380 | |
| 381 typedef struct CTRepr { | |
| 382 char *pb, *pe; | |
| 383 CTState *cts; | |
| 384 lua_State *L; | |
| 385 int needsp; | |
| 386 int ok; | |
| 387 char buf[CTREPR_MAX]; | |
| 388 } CTRepr; | |
| 389 | |
| 390 /* Prepend string. */ | |
| 391 static void ctype_prepstr(CTRepr *ctr, const char *str, MSize len) | |
| 392 { | |
| 393 char *p = ctr->pb; | |
| 394 if (ctr->buf + len+1 > p) { ctr->ok = 0; return; } | |
| 395 if (ctr->needsp) *--p = ' '; | |
| 396 ctr->needsp = 1; | |
| 397 p -= len; | |
| 398 while (len-- > 0) p[len] = str[len]; | |
| 399 ctr->pb = p; | |
| 400 } | |
| 401 | |
| 402 #define ctype_preplit(ctr, str) ctype_prepstr((ctr), "" str, sizeof(str)-1) | |
| 403 | |
| 404 /* Prepend char. */ | |
| 405 static void ctype_prepc(CTRepr *ctr, int c) | |
| 406 { | |
| 407 if (ctr->buf >= ctr->pb) { ctr->ok = 0; return; } | |
| 408 *--ctr->pb = c; | |
| 409 } | |
| 410 | |
| 411 /* Prepend number. */ | |
| 412 static void ctype_prepnum(CTRepr *ctr, uint32_t n) | |
| 413 { | |
| 414 char *p = ctr->pb; | |
| 415 if (ctr->buf + 10+1 > p) { ctr->ok = 0; return; } | |
| 416 do { *--p = (char)('0' + n % 10); } while (n /= 10); | |
| 417 ctr->pb = p; | |
| 418 ctr->needsp = 0; | |
| 419 } | |
| 420 | |
| 421 /* Append char. */ | |
| 422 static void ctype_appc(CTRepr *ctr, int c) | |
| 423 { | |
| 424 if (ctr->pe >= ctr->buf + CTREPR_MAX) { ctr->ok = 0; return; } | |
| 425 *ctr->pe++ = c; | |
| 426 } | |
| 427 | |
| 428 /* Append number. */ | |
| 429 static void ctype_appnum(CTRepr *ctr, uint32_t n) | |
| 430 { | |
| 431 char buf[10]; | |
| 432 char *p = buf+sizeof(buf); | |
| 433 char *q = ctr->pe; | |
| 434 if (q > ctr->buf + CTREPR_MAX - 10) { ctr->ok = 0; return; } | |
| 435 do { *--p = (char)('0' + n % 10); } while (n /= 10); | |
| 436 do { *q++ = *p++; } while (p < buf+sizeof(buf)); | |
| 437 ctr->pe = q; | |
| 438 } | |
| 439 | |
| 440 /* Prepend qualifiers. */ | |
| 441 static void ctype_prepqual(CTRepr *ctr, CTInfo info) | |
| 442 { | |
| 443 if ((info & CTF_VOLATILE)) ctype_preplit(ctr, "volatile"); | |
| 444 if ((info & CTF_CONST)) ctype_preplit(ctr, "const"); | |
| 445 } | |
| 446 | |
| 447 /* Prepend named type. */ | |
| 448 static void ctype_preptype(CTRepr *ctr, CType *ct, CTInfo qual, const char *t) | |
| 449 { | |
| 450 if (gcref(ct->name)) { | |
| 451 GCstr *str = gco2str(gcref(ct->name)); | |
| 452 ctype_prepstr(ctr, strdata(str), str->len); | |
| 453 } else { | |
| 454 if (ctr->needsp) ctype_prepc(ctr, ' '); | |
| 455 ctype_prepnum(ctr, ctype_typeid(ctr->cts, ct)); | |
| 456 ctr->needsp = 1; | |
| 457 } | |
| 458 ctype_prepstr(ctr, t, (MSize)strlen(t)); | |
| 459 ctype_prepqual(ctr, qual); | |
| 460 } | |
| 461 | |
| 462 static void ctype_repr(CTRepr *ctr, CTypeID id) | |
| 463 { | |
| 464 CType *ct = ctype_get(ctr->cts, id); | |
| 465 CTInfo qual = 0; | |
| 466 int ptrto = 0; | |
| 467 for (;;) { | |
| 468 CTInfo info = ct->info; | |
| 469 CTSize size = ct->size; | |
| 470 switch (ctype_type(info)) { | |
| 471 case CT_NUM: | |
| 472 if ((info & CTF_BOOL)) { | |
| 473 ctype_preplit(ctr, "bool"); | |
| 474 } else if ((info & CTF_FP)) { | |
| 475 if (size == sizeof(double)) ctype_preplit(ctr, "double"); | |
| 476 else if (size == sizeof(float)) ctype_preplit(ctr, "float"); | |
| 477 else ctype_preplit(ctr, "long double"); | |
| 478 } else if (size == 1) { | |
| 479 if (!((info ^ CTF_UCHAR) & CTF_UNSIGNED)) ctype_preplit(ctr, "char"); | |
| 480 else if (CTF_UCHAR) ctype_preplit(ctr, "signed char"); | |
| 481 else ctype_preplit(ctr, "unsigned char"); | |
| 482 } else if (size < 8) { | |
| 483 if (size == 4) ctype_preplit(ctr, "int"); | |
| 484 else ctype_preplit(ctr, "short"); | |
| 485 if ((info & CTF_UNSIGNED)) ctype_preplit(ctr, "unsigned"); | |
| 486 } else { | |
| 487 ctype_preplit(ctr, "_t"); | |
| 488 ctype_prepnum(ctr, size*8); | |
| 489 ctype_preplit(ctr, "int"); | |
| 490 if ((info & CTF_UNSIGNED)) ctype_prepc(ctr, 'u'); | |
| 491 } | |
| 492 ctype_prepqual(ctr, (qual|info)); | |
| 493 return; | |
| 494 case CT_VOID: | |
| 495 ctype_preplit(ctr, "void"); | |
| 496 ctype_prepqual(ctr, (qual|info)); | |
| 497 return; | |
| 498 case CT_STRUCT: | |
| 499 ctype_preptype(ctr, ct, qual, (info & CTF_UNION) ? "union" : "struct"); | |
| 500 return; | |
| 501 case CT_ENUM: | |
| 502 if (id == CTID_CTYPEID) { | |
| 503 ctype_preplit(ctr, "ctype"); | |
| 504 return; | |
| 505 } | |
| 506 ctype_preptype(ctr, ct, qual, "enum"); | |
| 507 return; | |
| 508 case CT_ATTRIB: | |
| 509 if (ctype_attrib(info) == CTA_QUAL) qual |= size; | |
| 510 break; | |
| 511 case CT_PTR: | |
| 512 if ((info & CTF_REF)) { | |
| 513 ctype_prepc(ctr, '&'); | |
| 514 } else { | |
| 515 ctype_prepqual(ctr, (qual|info)); | |
| 516 if (LJ_64 && size == 4) ctype_preplit(ctr, "__ptr32"); | |
| 517 ctype_prepc(ctr, '*'); | |
| 518 } | |
| 519 qual = 0; | |
| 520 ptrto = 1; | |
| 521 ctr->needsp = 1; | |
| 522 break; | |
| 523 case CT_ARRAY: | |
| 524 if (ctype_isrefarray(info)) { | |
| 525 ctr->needsp = 1; | |
| 526 if (ptrto) { ptrto = 0; ctype_prepc(ctr, '('); ctype_appc(ctr, ')'); } | |
| 527 ctype_appc(ctr, '['); | |
| 528 if (size != CTSIZE_INVALID) { | |
| 529 CTSize csize = ctype_child(ctr->cts, ct)->size; | |
| 530 ctype_appnum(ctr, csize ? size/csize : 0); | |
| 531 } else if ((info & CTF_VLA)) { | |
| 532 ctype_appc(ctr, '?'); | |
| 533 } | |
| 534 ctype_appc(ctr, ']'); | |
| 535 } else if ((info & CTF_COMPLEX)) { | |
| 536 if (size == 2*sizeof(float)) ctype_preplit(ctr, "float"); | |
| 537 ctype_preplit(ctr, "complex"); | |
| 538 return; | |
| 539 } else { | |
| 540 ctype_preplit(ctr, ")))"); | |
| 541 ctype_prepnum(ctr, size); | |
| 542 ctype_preplit(ctr, "__attribute__((vector_size("); | |
| 543 } | |
| 544 break; | |
| 545 case CT_FUNC: | |
| 546 ctr->needsp = 1; | |
| 547 if (ptrto) { ptrto = 0; ctype_prepc(ctr, '('); ctype_appc(ctr, ')'); } | |
| 548 ctype_appc(ctr, '('); | |
| 549 ctype_appc(ctr, ')'); | |
| 550 break; | |
| 551 default: | |
| 552 lj_assertG_(ctr->cts->g, 0, "bad ctype %08x", info); | |
| 553 break; | |
| 554 } | |
| 555 ct = ctype_get(ctr->cts, ctype_cid(info)); | |
| 556 } | |
| 557 } | |
| 558 | |
| 559 /* Return a printable representation of a C type. */ | |
| 560 GCstr *lj_ctype_repr(lua_State *L, CTypeID id, GCstr *name) | |
| 561 { | |
| 562 global_State *g = G(L); | |
| 563 CTRepr ctr; | |
| 564 ctr.pb = ctr.pe = &ctr.buf[CTREPR_MAX/2]; | |
| 565 ctr.cts = ctype_ctsG(g); | |
| 566 ctr.L = L; | |
| 567 ctr.ok = 1; | |
| 568 ctr.needsp = 0; | |
| 569 if (name) ctype_prepstr(&ctr, strdata(name), name->len); | |
| 570 ctype_repr(&ctr, id); | |
| 571 if (LJ_UNLIKELY(!ctr.ok)) return lj_str_newlit(L, "?"); | |
| 572 return lj_str_new(L, ctr.pb, ctr.pe - ctr.pb); | |
| 573 } | |
| 574 | |
| 575 /* Convert int64_t/uint64_t to string with 'LL' or 'ULL' suffix. */ | |
| 576 GCstr *lj_ctype_repr_int64(lua_State *L, uint64_t n, int isunsigned) | |
| 577 { | |
| 578 char buf[1+20+3]; | |
| 579 char *p = buf+sizeof(buf); | |
| 580 int sign = 0; | |
| 581 *--p = 'L'; *--p = 'L'; | |
| 582 if (isunsigned) { | |
| 583 *--p = 'U'; | |
| 584 } else if ((int64_t)n < 0) { | |
| 585 n = ~n+1u; | |
| 586 sign = 1; | |
| 587 } | |
| 588 do { *--p = (char)('0' + n % 10); } while (n /= 10); | |
| 589 if (sign) *--p = '-'; | |
| 590 return lj_str_new(L, p, (size_t)(buf+sizeof(buf)-p)); | |
| 591 } | |
| 592 | |
| 593 /* Convert complex to string with 'i' or 'I' suffix. */ | |
| 594 GCstr *lj_ctype_repr_complex(lua_State *L, void *sp, CTSize size) | |
| 595 { | |
| 596 SBuf *sb = lj_buf_tmp_(L); | |
| 597 TValue re, im; | |
| 598 if (size == 2*sizeof(double)) { | |
| 599 re.n = *(double *)sp; im.n = ((double *)sp)[1]; | |
| 600 } else { | |
| 601 re.n = (double)*(float *)sp; im.n = (double)((float *)sp)[1]; | |
| 602 } | |
| 603 lj_strfmt_putfnum(sb, STRFMT_G14, re.n); | |
| 604 if (!(im.u32.hi & 0x80000000u) || im.n != im.n) lj_buf_putchar(sb, '+'); | |
| 605 lj_strfmt_putfnum(sb, STRFMT_G14, im.n); | |
| 606 lj_buf_putchar(sb, sb->w[-1] >= 'a' ? 'I' : 'i'); | |
| 607 return lj_buf_str(L, sb); | |
| 608 } | |
| 609 | |
| 610 /* -- C type state -------------------------------------------------------- */ | |
| 611 | |
| 612 /* Initialize C type table and state. */ | |
| 613 CTState *lj_ctype_init(lua_State *L) | |
| 614 { | |
| 615 CTState *cts = lj_mem_newt(L, sizeof(CTState), CTState); | |
| 616 CType *ct = lj_mem_newvec(L, CTTYPETAB_MIN, CType); | |
| 617 const char *name = lj_ctype_typenames; | |
| 618 CTypeID id; | |
| 619 memset(cts, 0, sizeof(CTState)); | |
| 620 cts->tab = ct; | |
| 621 cts->sizetab = CTTYPETAB_MIN; | |
| 622 cts->top = CTTYPEINFO_NUM; | |
| 623 cts->L = NULL; | |
| 624 cts->g = G(L); | |
| 625 for (id = 0; id < CTTYPEINFO_NUM; id++, ct++) { | |
| 626 CTInfo info = lj_ctype_typeinfo[id]; | |
| 627 ct->size = (CTSize)((int32_t)(info << 16) >> 26); | |
| 628 ct->info = info & 0xffff03ffu; | |
| 629 ct->sib = 0; | |
| 630 if (ctype_type(info) == CT_KW || ctype_istypedef(info)) { | |
| 631 size_t len = strlen(name); | |
| 632 GCstr *str = lj_str_new(L, name, len); | |
| 633 ctype_setname(ct, str); | |
| 634 name += len+1; | |
| 635 lj_ctype_addname(cts, ct, id); | |
| 636 } else { | |
| 637 setgcrefnull(ct->name); | |
| 638 ct->next = 0; | |
| 639 if (!ctype_isenum(info)) ctype_addtype(cts, ct, id); | |
| 640 } | |
| 641 } | |
| 642 setmref(G(L)->ctype_state, cts); | |
| 643 return cts; | |
| 644 } | |
| 645 | |
| 646 /* Free C type table and state. */ | |
| 647 void lj_ctype_freestate(global_State *g) | |
| 648 { | |
| 649 CTState *cts = ctype_ctsG(g); | |
| 650 if (cts) { | |
| 651 lj_ccallback_mcode_free(cts); | |
| 652 lj_mem_freevec(g, cts->tab, cts->sizetab, CType); | |
| 653 lj_mem_freevec(g, cts->cb.cbid, cts->cb.sizeid, CTypeID1); | |
| 654 lj_mem_freet(g, cts); | |
| 655 } | |
| 656 } | |
| 657 | |
| 658 #endif |