• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

tarantool / luajit / 9593251616

20 Jun 2024 07:14AM UTC coverage: 92.646% (+0.02%) from 92.624%
9593251616

push

github

Buristan
cmake: fix warning about minimum required version

Since CMake 3.27 compatibility with versions of CMake older than
3.5 is deprecated [1]. CMake produces an annoying warning on the
configuration stage:

| CMake Deprecation Warning at src/CMakeLists.txt:7 (cmake_minimum_required):
|  Compatibility with CMake < 3.5 will be removed from a future version of
|  CMake.

We cannot bump a minimum required CMake version without bumping it in
the Tarantool build system. However, we can set a <policy_max>
(introduced in CMake 3.12, see [1]) and suppress a warning. <policy_max>
means that this CMake version is known to work properly and will not
result in any build errors right away for higher versions.

Note that the current CMake minimum required version in Tarantool is
equal to 2.8, but <policy_max> is introduced in CMake 3.12 [1].
However, according to [1] it is not a problem because if CMake is "older
than 3.12, the extra ... dots will be seen as version component
separators, resulting in the ...<max> part being ignored and preserving
the pre-3.12 behavior of basing policies on <min>".

<policy_max> is set to 3.18 because compatibility with versions of CMake
older than 2.8.12 is deprecated. Calls to
cmake_minimum_required(VERSION) that do not specify at least 2.8.12 as
their policy version (optionally via ...<max>) will produce a
deprecation warning in CMake 3.19 and above [2]. Compatibility with
2.8.12 is needed for CMP0002 [3], see commit 049e296ee114 ("test: run
LuaJIT tests via CMake").

1. https://cmake.org/cmake/help/latest/command/cmake_minimum_required.html
2. https://cmake.org/cmake/help/latest/command/cmake_minimum_required.html#policy-settings
3. https://cmake.org/cmake/help/latest/policy/CMP0002.html

5665 of 6021 branches covered (94.09%)

Branch coverage included in aggregate %.

21621 of 23431 relevant lines covered (92.28%)

2937993.42 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

95.38
/src/lj_ctype.c
1
/*
2
** C type management.
3
** Copyright (C) 2005-2017 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)
67,552✔
153
{
154
  CTypeID id = cts->top;
67,552✔
155
  CType *ct;
67,552✔
156
  lj_assertCTS(cts->L, "uninitialized cts->L");
67,552✔
157
  if (LJ_UNLIKELY(id >= cts->sizetab)) {
67,552✔
158
    if (id >= CTID_MAX) lj_err_msg(cts->L, LJ_ERR_TABOV);
15✔
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);
14✔
168
#endif
169
  }
170
  cts->top = id+1;
67,551✔
171
  *ctp = ct = &cts->tab[id];
67,551✔
172
  ct->info = 0;
67,551✔
173
  ct->size = 0;
67,551✔
174
  ct->sib = 0;
67,551✔
175
  ct->next = 0;
67,551✔
176
  setgcrefnull(ct->name);
67,551✔
177
  return id;
67,551✔
178
}
179

180
/* Intern a type element. */
181
CTypeID lj_ctype_intern(CTState *cts, CTInfo info, CTSize size)
727,806✔
182
{
183
  uint32_t h = ct_hashtype(info, size);
727,806✔
184
  CTypeID id = cts->hash[h];
727,806✔
185
  lj_assertCTS(cts->L, "uninitialized cts->L");
727,806✔
186
  while (id) {
1,201,322✔
187
    CType *ct = ctype_get(cts, id);
1,200,954✔
188
    if (ct->info == info && ct->size == size)
1,200,954✔
189
      return id;
727,438✔
190
    id = ct->next;
473,516✔
191
  }
192
  id = cts->top;
368✔
193
  if (LJ_UNLIKELY(id >= cts->sizetab)) {
368✔
194
#ifdef LUAJIT_CTYPE_CHECK_ANCHOR
195
    CType *ct;
196
#endif
197
    if (id >= CTID_MAX) lj_err_msg(cts->L, LJ_ERR_TABOV);
4✔
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);
4✔
207
#endif
208
  }
209
  cts->top = id+1;
368✔
210
  cts->tab[id].info = info;
368✔
211
  cts->tab[id].size = size;
368✔
212
  cts->tab[id].sib = 0;
368✔
213
  cts->tab[id].next = cts->hash[h];
368✔
214
  setgcrefnull(cts->tab[id].name);
368✔
215
  cts->hash[h] = (CTypeID1)id;
368✔
216
  return id;
368✔
217
}
218

219
/* Add type element to hash table. */
220
static void ctype_addtype(CTState *cts, CType *ct, CTypeID id)
3,927✔
221
{
222
  uint32_t h = ct_hashtype(ct->info, ct->size);
3,927✔
223
  ct->next = cts->hash[h];
3,927✔
224
  cts->hash[h] = (CTypeID1)id;
3,927✔
225
}
3,927✔
226

227
/* Add named element to hash table. */
228
void lj_ctype_addname(CTState *cts, CType *ct, CTypeID id)
14,244✔
229
{
230
  uint32_t h = ct_hashname(gcref(ct->name));
14,244✔
231
  ct->next = cts->hash[h];
14,244✔
232
  cts->hash[h] = (CTypeID1)id;
14,244✔
233
}
13,838✔
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)
633,232✔
237
{
238
  CTypeID id = cts->hash[ct_hashname(name)];
633,232✔
239
  while (id) {
856,141✔
240
    CType *ct = ctype_get(cts, id);
854,561✔
241
    if (gcref(ct->name) == obj2gco(name) &&
854,561✔
242
        ((tmask >> ctype_type(ct->info)) & 1)) {
631,681✔
243
      *ctp = ct;
631,652✔
244
      return id;
631,652✔
245
    }
246
    id = ct->next;
222,909✔
247
  }
248
  *ctp = &cts->tab[0];  /* Simplify caller logic. ctype_get() would assert. */
1,580✔
249
  return 0;
1,580✔
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,
113,149✔
254
                          CTInfo *qual)
255
{
256
  while (ct->sib) {
138,726✔
257
    ct = ctype_get(cts, ct->sib);
138,325✔
258
    if (gcref(ct->name) == obj2gco(name)) {
138,325✔
259
      *ofs = ct->size;
112,537✔
260
      return ct;
112,537✔
261
    }
262
    if (ctype_isxattrib(ct->info, CTA_SUBTYPE)) {
25,788✔
263
      CType *fct, *cct = ctype_child(cts, ct);
436✔
264
      CTInfo q = 0;
436✔
265
      while (ctype_isattrib(cct->info)) {
444✔
266
        if (ctype_attrib(cct->info) == CTA_QUAL) q |= cct->size;
8✔
267
        cct = ctype_child(cts, cct);
8✔
268
      }
269
      fct = lj_ctype_getfieldq(cts, cct, name, ofs, qual);
436✔
270
      if (fct) {
436✔
271
        if (qual) *qual |= q;
211✔
272
        *ofs += ct->size;
211✔
273
        return fct;
211✔
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)
118,327✔
284
{
285
  CType *ct = ctype_get(cts, id);
118,327✔
286
  while (ctype_isattrib(ct->info) || ctype_isref(ct->info))
118,356✔
287
    ct = ctype_child(cts, ct);
29✔
288
  return ct;
118,327✔
289
}
290

291
/* Get size for a C type ID. Does NOT support VLA/VLS. */
292
CTSize lj_ctype_size(CTState *cts, CTypeID id)
747,185✔
293
{
294
  CType *ct = ctype_raw(cts, id);
747,185✔
295
  return ctype_hassize(ct->info) ? ct->size : CTSIZE_INVALID;
747,185✔
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)
1,300✔
300
{
301
  uint64_t xsz = 0;
1,300✔
302
  if (ctype_isstruct(ct->info)) {
1,300✔
303
    CTypeID arrid = 0, fid = ct->sib;
70✔
304
    xsz = ct->size;  /* Add the struct size. */
70✔
305
    while (fid) {
209✔
306
      CType *ctf = ctype_get(cts, fid);
139✔
307
      if (ctype_type(ctf->info) == CT_FIELD)
139✔
308
        arrid = ctype_cid(ctf->info);  /* Remember last field of VLS. */
139✔
309
      fid = ctf->sib;
139✔
310
    }
311
    ct = ctype_raw(cts, arrid);
70✔
312
  }
313
  lj_assertCTS(ctype_isvlarray(ct->info), "VLA expected");
1,300✔
314
  ct = ctype_rawchild(cts, ct);  /* Get array element. */
1,300✔
315
  lj_assertCTS(ctype_hassize(ct->info), "bad VLA without size");
1,300✔
316
  /* Calculate actual size of VLA and check for overflow. */
317
  xsz += (uint64_t)ct->size * nelem;
1,300✔
318
  return xsz < 0x80000000u ? (CTSize)xsz : CTSIZE_INVALID;
1,300✔
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)
532,015✔
323
{
324
  CTInfo qual = 0;
532,015✔
325
  CType *ct = ctype_get(cts, id);
532,015✔
326
  for (;;) {
532,191✔
327
    CTInfo info = ct->info;
532,103✔
328
    if (ctype_isenum(info)) {
532,103✔
329
      /* Follow child. Need to look at its attributes, too. */
330
    } else if (ctype_isattrib(info)) {
532,092✔
331
      if (ctype_isxattrib(info, CTA_QUAL))
77✔
332
        qual |= ct->size;
5✔
333
      else if (ctype_isxattrib(info, CTA_ALIGN) && !(qual & CTFP_ALIGNED))
72✔
334
        qual |= CTFP_ALIGNED + CTALIGN(ct->size);
72✔
335
    } else {
336
      if (!(qual & CTFP_ALIGNED)) qual |= (info & CTF_ALIGN);
532,015✔
337
      qual |= (info & ~(CTF_ALIGN|CTMASK_CID));
532,015✔
338
      lj_assertCTS(ctype_hassize(info) || ctype_isfunc(info),
532,015✔
339
                   "ctype without size");
340
      *szp = ctype_isfunc(info) ? CTSIZE_INVALID : ct->size;
532,015✔
341
      break;
532,015✔
342
    }
343
    ct = ctype_get(cts, ctype_cid(info));
88✔
344
  }
345
  return qual;
532,015✔
346
}
347

348
/* Ditto, but follow a reference. */
349
CTInfo lj_ctype_info_raw(CTState *cts, CTypeID id, CTSize *szp)
204✔
350
{
351
  CType *ct = ctype_get(cts, id);
204✔
352
  if (ctype_isref(ct->info)) id = ctype_cid(ct->info);
204✔
353
  return lj_ctype_info(cts, id, szp);
204✔
354
}
355

356
/* Get ctype metamethod. */
357
cTValue *lj_ctype_meta(CTState *cts, CTypeID id, MMS mm)
4,138✔
358
{
359
  CType *ct = ctype_get(cts, id);
4,138✔
360
  cTValue *tv;
4,138✔
361
  while (ctype_isattrib(ct->info) || ctype_isref(ct->info)) {
4,199✔
362
    id = ctype_cid(ct->info);
61✔
363
    ct = ctype_get(cts, id);
61✔
364
  }
365
  if (ctype_isptr(ct->info) &&
4,138✔
366
      ctype_isfunc(ctype_get(cts, ctype_cid(ct->info))->info))
43✔
367
    tv = lj_tab_getstr(cts->miscmap, &cts->g->strempty);
43✔
368
  else
369
    tv = lj_tab_getinth(cts->miscmap, -(int32_t)id);
4,095✔
370
  if (tv && tvistab(tv) &&
4,138✔
371
      (tv = lj_tab_getstr(tabV(tv), mmname_str(cts->g, mm))) && !tvisnil(tv))
646✔
372
    return tv;
386✔
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)
121✔
392
{
393
  char *p = ctr->pb;
121✔
394
  if (ctr->buf + len+1 > p) { ctr->ok = 0; return; }
37✔
395
  if (ctr->needsp) *--p = ' ';
121✔
396
  ctr->needsp = 1;
121✔
397
  p -= len;
121✔
398
  while (len-- > 0) p[len] = str[len];
741✔
399
  ctr->pb = p;
121✔
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)
50✔
406
{
407
  if (ctr->buf >= ctr->pb) { ctr->ok = 0; return; }
×
408
  *--ctr->pb = c;
50✔
409
}
410

411
/* Prepend number. */
412
static void ctype_prepnum(CTRepr *ctr, uint32_t n)
12✔
413
{
414
  char *p = ctr->pb;
12✔
415
  if (ctr->buf + 10+1 > p) { ctr->ok = 0; return; }
×
416
  do { *--p = (char)('0' + n % 10); } while (n /= 10);
31✔
417
  ctr->pb = p;
12✔
418
  ctr->needsp = 0;
12✔
419
}
420

421
/* Append char. */
422
static void ctype_appc(CTRepr *ctr, int c)
62✔
423
{
424
  if (ctr->pe >= ctr->buf + CTREPR_MAX) { ctr->ok = 0; return; }
×
425
  *ctr->pe++ = c;
62✔
426
}
427

428
/* Append number. */
429
static void ctype_appnum(CTRepr *ctr, uint32_t n)
22✔
430
{
431
  char buf[10];
22✔
432
  char *p = buf+sizeof(buf);
22✔
433
  char *q = ctr->pe;
22✔
434
  if (q > ctr->buf + CTREPR_MAX - 10) { ctr->ok = 0; return; }
22✔
435
  do { *--p = (char)('0' + n % 10); } while (n /= 10);
35✔
436
  do { *q++ = *p++; } while (p < buf+sizeof(buf));
35✔
437
  ctr->pe = q;
22✔
438
}
439

440
/* Prepend qualifiers. */
441
static void ctype_prepqual(CTRepr *ctr, CTInfo info)
126✔
442
{
443
  if ((info & CTF_VOLATILE)) ctype_preplit(ctr, "volatile");
126✔
444
  if ((info & CTF_CONST)) ctype_preplit(ctr, "const");
126✔
445
}
126✔
446

447
/* Prepend named type. */
448
static void ctype_preptype(CTRepr *ctr, CType *ct, CTInfo qual, const char *t)
22✔
449
{
450
  if (gcref(ct->name)) {
22✔
451
    GCstr *str = gco2str(gcref(ct->name));
15✔
452
    ctype_prepstr(ctr, strdata(str), str->len);
15✔
453
  } else {
454
    if (ctr->needsp) ctype_prepc(ctr, ' ');
7✔
455
    ctype_prepnum(ctr, ctype_typeid(ctr->cts, ct));
7✔
456
    ctr->needsp = 1;
7✔
457
  }
458
  ctype_prepstr(ctr, t, (MSize)strlen(t));
22✔
459
  ctype_prepqual(ctr, qual);
22✔
460
}
22✔
461

462
static void ctype_repr(CTRepr *ctr, CTypeID id)
88✔
463
{
464
  CType *ct = ctype_get(ctr->cts, id);
88✔
465
  CTInfo qual = 0;
88✔
466
  int ptrto = 0;
88✔
467
  for (;;) {
74✔
468
    CTInfo info = ct->info;
162✔
469
    CTSize size = ct->size;
162✔
470
    switch (ctype_type(info)) {
162✔
471
    case CT_NUM:
58✔
472
      if ((info & CTF_BOOL)) {
58✔
473
        ctype_preplit(ctr, "bool");
4✔
474
      } else if ((info & CTF_FP)) {
54✔
475
        if (size == sizeof(double)) ctype_preplit(ctr, "double");
2✔
476
        else if (size == sizeof(float)) ctype_preplit(ctr, "float");
×
477
        else ctype_preplit(ctr, "long double");
×
478
      } else if (size == 1) {
52✔
479
        if (!((info ^ CTF_UCHAR) & CTF_UNSIGNED)) ctype_preplit(ctr, "char");
2✔
480
        else if (CTF_UCHAR) ctype_preplit(ctr, "signed char");
×
481
        else ctype_preplit(ctr, "unsigned char");
×
482
      } else if (size < 8) {
50✔
483
        if (size == 4) ctype_preplit(ctr, "int");
47✔
484
        else ctype_preplit(ctr, "short");
×
485
        if ((info & CTF_UNSIGNED)) ctype_preplit(ctr, "unsigned");
47✔
486
      } else {
487
        ctype_preplit(ctr, "_t");
3✔
488
        ctype_prepnum(ctr, size*8);
3✔
489
        ctype_preplit(ctr, "int");
3✔
490
        if ((info & CTF_UNSIGNED)) ctype_prepc(ctr, 'u');
3✔
491
      }
492
      ctype_prepqual(ctr, (qual|info));
58✔
493
      return;
58✔
494
    case CT_VOID:
495
      ctype_preplit(ctr, "void");
2✔
496
      ctype_prepqual(ctr, (qual|info));
2✔
497
      return;
2✔
498
    case CT_STRUCT:
21✔
499
      ctype_preptype(ctr, ct, qual, (info & CTF_UNION) ? "union" : "struct");
21✔
500
      return;
21✔
501
    case CT_ENUM:
1✔
502
      if (id == CTID_CTYPEID) {
1✔
503
        ctype_preplit(ctr, "ctype");
×
504
        return;
×
505
      }
506
      ctype_preptype(ctr, ct, qual, "enum");
1✔
507
      return;
1✔
508
    case CT_ATTRIB:
×
509
      if (ctype_attrib(info) == CTA_QUAL) qual |= size;
×
510
      break;
511
    case CT_PTR:
44✔
512
      if ((info & CTF_REF)) {
44✔
513
        ctype_prepc(ctr, '&');
×
514
      } else {
515
        ctype_prepqual(ctr, (qual|info));
44✔
516
        if (LJ_64 && size == 4) ctype_preplit(ctr, "__ptr32");
44✔
517
        ctype_prepc(ctr, '*');
44✔
518
      }
519
      qual = 0;
44✔
520
      ptrto = 1;
44✔
521
      ctr->needsp = 1;
44✔
522
      break;
44✔
523
    case CT_ARRAY:
33✔
524
      if (ctype_isrefarray(info)) {
33✔
525
        ctr->needsp = 1;
25✔
526
        if (ptrto) { ptrto = 0; ctype_prepc(ctr, '('); ctype_appc(ctr, ')'); }
28✔
527
        ctype_appc(ctr, '[');
25✔
528
        if (size != CTSIZE_INVALID) {
25✔
529
          CTSize csize = ctype_child(ctr->cts, ct)->size;
22✔
530
          ctype_appnum(ctr, csize ? size/csize : 0);
22✔
531
        } else if ((info & CTF_VLA)) {
3✔
532
          ctype_appc(ctr, '?');
1✔
533
        }
534
        ctype_appc(ctr, ']');
25✔
535
      } else if ((info & CTF_COMPLEX)) {
8✔
536
        if (size == 2*sizeof(float)) ctype_preplit(ctr, "float");
6✔
537
        ctype_preplit(ctr, "complex");
6✔
538
        return;
6✔
539
      } else {
540
        ctype_preplit(ctr, ")))");
2✔
541
        ctype_prepnum(ctr, size);
2✔
542
        ctype_preplit(ctr, "__attribute__((vector_size(");
2✔
543
      }
544
      break;
545
    case CT_FUNC:
3✔
546
      ctr->needsp = 1;
3✔
547
      if (ptrto) { ptrto = 0; ctype_prepc(ctr, '('); ctype_appc(ctr, ')'); }
5✔
548
      ctype_appc(ctr, '(');
3✔
549
      ctype_appc(ctr, ')');
3✔
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));
74✔
556
  }
557
}
558

559
/* Return a printable representation of a C type. */
560
GCstr *lj_ctype_repr(lua_State *L, CTypeID id, GCstr *name)
88✔
561
{
562
  global_State *g = G(L);
88✔
563
  CTRepr ctr;
88✔
564
  ctr.pb = ctr.pe = &ctr.buf[CTREPR_MAX/2];
88✔
565
  ctr.cts = ctype_ctsG(g);
88✔
566
  ctr.L = L;
88✔
567
  ctr.ok = 1;
88✔
568
  ctr.needsp = 0;
88✔
569
  if (name) ctype_prepstr(&ctr, strdata(name), name->len);
88✔
570
  ctype_repr(&ctr, id);
88✔
571
  if (LJ_UNLIKELY(!ctr.ok)) return lj_str_newlit(L, "?");
88✔
572
  return lj_str_new(L, ctr.pb, ctr.pe - ctr.pb);
88✔
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)
20✔
577
{
578
  char buf[1+20+3];
20✔
579
  char *p = buf+sizeof(buf);
20✔
580
  int sign = 0;
20✔
581
  *--p = 'L'; *--p = 'L';
20✔
582
  if (isunsigned) {
20✔
583
    *--p = 'U';
9✔
584
  } else if ((int64_t)n < 0) {
11✔
585
    n = (uint64_t)-(int64_t)n;
3✔
586
    sign = 1;
3✔
587
  }
588
  do { *--p = (char)('0' + n % 10); } while (n /= 10);
169✔
589
  if (sign) *--p = '-';
20✔
590
  return lj_str_new(L, p, (size_t)(buf+sizeof(buf)-p));
20✔
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)
16✔
595
{
596
  SBuf *sb = lj_buf_tmp_(L);
16✔
597
  TValue re, im;
16✔
598
  if (size == 2*sizeof(double)) {
16✔
599
    re.n = *(double *)sp; im.n = ((double *)sp)[1];
15✔
600
  } else {
601
    re.n = (double)*(float *)sp; im.n = (double)((float *)sp)[1];
1✔
602
  }
603
  lj_strfmt_putfnum(sb, STRFMT_G14, re.n);
16✔
604
  if (!(im.u32.hi & 0x80000000u) || im.n != im.n) lj_buf_putchar(sb, '+');
16✔
605
  lj_strfmt_putfnum(sb, STRFMT_G14, im.n);
16✔
606
  lj_buf_putchar(sb, sbufP(sb)[-1] >= 'a' ? 'I' : 'i');
28✔
607
  return lj_buf_str(L, sb);
16✔
608
}
609

610
/* -- C type state -------------------------------------------------------- */
611

612
/* Initialize C type table and state. */
613
CTState *lj_ctype_init(lua_State *L)
187✔
614
{
615
  CTState *cts = lj_mem_newt(L, sizeof(CTState), CTState);
187✔
616
  CType *ct = lj_mem_newvec(L, CTTYPETAB_MIN, CType);
187✔
617
  const char *name = lj_ctype_typenames;
187✔
618
  CTypeID id;
187✔
619
  memset(cts, 0, sizeof(CTState));
187✔
620
  cts->tab = ct;
187✔
621
  cts->sizetab = CTTYPETAB_MIN;
187✔
622
  cts->top = CTTYPEINFO_NUM;
187✔
623
  cts->L = NULL;
187✔
624
  cts->g = G(L);
187✔
625
  for (id = 0; id < CTTYPEINFO_NUM; id++, ct++) {
18,139✔
626
    CTInfo info = lj_ctype_typeinfo[id];
17,952✔
627
    ct->size = (CTSize)((int32_t)(info << 16) >> 26);
17,952✔
628
    ct->info = info & 0xffff03ffu;
17,952✔
629
    ct->sib = 0;
17,952✔
630
    if (ctype_type(info) == CT_KW || ctype_istypedef(info)) {
17,952✔
631
      size_t len = strlen(name);
13,838✔
632
      GCstr *str = lj_str_new(L, name, len);
13,838✔
633
      ctype_setname(ct, str);
13,838✔
634
      name += len+1;
13,838✔
635
      lj_ctype_addname(cts, ct, id);
13,838✔
636
    } else {
637
      setgcrefnull(ct->name);
4,114✔
638
      ct->next = 0;
4,114✔
639
      if (!ctype_isenum(info)) ctype_addtype(cts, ct, id);
17,952✔
640
    }
641
  }
642
  setmref(G(L)->ctype_state, cts);
187✔
643
  return cts;
187✔
644
}
645

646
/* Free C type table and state. */
647
void lj_ctype_freestate(global_State *g)
322✔
648
{
649
  CTState *cts = ctype_ctsG(g);
322✔
650
  if (cts) {
322✔
651
    lj_ccallback_mcode_free(cts);
183✔
652
    lj_mem_freevec(g, cts->tab, cts->sizetab, CType);
183✔
653
    lj_mem_freevec(g, cts->cb.cbid, cts->cb.sizeid, CTypeID1);
183✔
654
    lj_mem_freet(g, cts);
183✔
655
  }
656
}
322✔
657

658
#endif
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc