aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMike Pall <mike>2010-12-05 00:20:59 +0100
committerMike Pall <mike>2010-12-05 00:20:59 +0100
commit233076d3f922c390fa9c258284cf99058cec69cb (patch)
tree953d1c28bb381befb6830d1f856adaa5f047610e /src
parent526e087e63daaaeab517932351c8941f678e071c (diff)
downloadluajit-233076d3f922c390fa9c258284cf99058cec69cb.tar.gz
luajit-233076d3f922c390fa9c258284cf99058cec69cb.tar.bz2
luajit-233076d3f922c390fa9c258284cf99058cec69cb.zip
FFI: Add C declaration parser.
Diffstat (limited to 'src')
-rw-r--r--src/Makefile2
-rw-r--r--src/Makefile.dep17
-rw-r--r--src/lj_cparse.c1802
-rw-r--r--src/lj_cparse.h63
-rw-r--r--src/ljamalg.c1
5 files changed, 1877 insertions, 8 deletions
diff --git a/src/Makefile b/src/Makefile
index 34a966cd..6e72d16b 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -327,7 +327,7 @@ LJCORE_O= lj_gc.o lj_err.o lj_char.o lj_bc.o lj_obj.o \
327 lj_ir.o lj_opt_mem.o lj_opt_fold.o lj_opt_narrow.o \ 327 lj_ir.o lj_opt_mem.o lj_opt_fold.o lj_opt_narrow.o \
328 lj_opt_dce.o lj_opt_loop.o \ 328 lj_opt_dce.o lj_opt_loop.o \
329 lj_mcode.o lj_snap.o lj_record.o lj_asm.o lj_trace.o lj_gdbjit.o \ 329 lj_mcode.o lj_snap.o lj_record.o lj_asm.o lj_trace.o lj_gdbjit.o \
330 lj_ctype.o lj_cdata.o lj_cconv.o \ 330 lj_ctype.o lj_cdata.o lj_cconv.o lj_cparse.o \
331 lj_lib.o lj_alloc.o lib_aux.o \ 331 lj_lib.o lj_alloc.o lib_aux.o \
332 $(LJLIB_O) lib_init.o 332 $(LJLIB_O) lib_init.o
333 333
diff --git a/src/Makefile.dep b/src/Makefile.dep
index f7ee92ec..28fad93f 100644
--- a/src/Makefile.dep
+++ b/src/Makefile.dep
@@ -57,6 +57,9 @@ lj_cconv.o: lj_cconv.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
57lj_cdata.o: lj_cdata.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ 57lj_cdata.o: lj_cdata.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
58 lj_gc.h lj_err.h lj_errmsg.h lj_str.h lj_ctype.h lj_cconv.h lj_cdata.h 58 lj_gc.h lj_err.h lj_errmsg.h lj_str.h lj_ctype.h lj_cconv.h lj_cdata.h
59lj_char.o: lj_char.c lj_char.h lj_def.h lua.h luaconf.h 59lj_char.o: lj_char.c lj_char.h lj_def.h lua.h luaconf.h
60lj_cparse.o: lj_cparse.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
61 lj_gc.h lj_err.h lj_errmsg.h lj_str.h lj_ctype.h lj_cparse.h lj_frame.h \
62 lj_bc.h lj_vm.h lj_char.h
60lj_ctype.o: lj_ctype.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ 63lj_ctype.o: lj_ctype.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
61 lj_gc.h lj_err.h lj_errmsg.h lj_str.h lj_tab.h lj_ctype.h 64 lj_gc.h lj_err.h lj_errmsg.h lj_str.h lj_tab.h lj_ctype.h
62lj_dispatch.o: lj_dispatch.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ 65lj_dispatch.o: lj_dispatch.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
@@ -139,11 +142,11 @@ ljamalg.o: ljamalg.c lua.h luaconf.h lauxlib.h lj_gc.c lj_obj.h lj_def.h \
139 lj_func.c lj_udata.c lj_meta.c lj_state.c lj_lex.h lj_alloc.h \ 142 lj_func.c lj_udata.c lj_meta.c lj_state.c lj_lex.h lj_alloc.h \
140 lj_dispatch.c lj_ff.h lj_ffdef.h luajit.h lj_vmevent.c lj_vmevent.h \ 143 lj_dispatch.c lj_ff.h lj_ffdef.h luajit.h lj_vmevent.c lj_vmevent.h \
141 lj_api.c lj_parse.h lj_lex.c lj_parse.c lj_ctype.c lj_cdata.c lj_cconv.h \ 144 lj_api.c lj_parse.h lj_lex.c lj_parse.c lj_ctype.c lj_cdata.c lj_cconv.h \
142 lj_cconv.c lj_lib.c lj_lib.h lj_ir.c lj_iropt.h lj_opt_mem.c \ 145 lj_cconv.c lj_cparse.c lj_cparse.h lj_lib.c lj_lib.h lj_ir.c lj_iropt.h \
143 lj_opt_fold.c lj_folddef.h lj_opt_narrow.c lj_opt_dce.c lj_opt_loop.c \ 146 lj_opt_mem.c lj_opt_fold.c lj_folddef.h lj_opt_narrow.c lj_opt_dce.c \
144 lj_snap.h lj_mcode.c lj_mcode.h lj_snap.c lj_target.h lj_target_*.h \ 147 lj_opt_loop.c lj_snap.h lj_mcode.c lj_mcode.h lj_snap.c lj_target.h \
145 lj_record.c lj_record.h lj_asm.h lj_recdef.h lj_asm.c lj_trace.c \ 148 lj_target_*.h lj_record.c lj_record.h lj_asm.h lj_recdef.h lj_asm.c \
146 lj_gdbjit.h lj_gdbjit.c lj_alloc.c lib_aux.c lib_base.c lualib.h \ 149 lj_trace.c lj_gdbjit.h lj_gdbjit.c lj_alloc.c lib_aux.c lib_base.c \
147 lj_libdef.h lib_math.c lib_string.c lib_table.c lib_io.c lib_os.c \ 150 lualib.h lj_libdef.h lib_math.c lib_string.c lib_table.c lib_io.c \
148 lib_package.c lib_debug.c lib_bit.c lib_jit.c lib_init.c 151 lib_os.c lib_package.c lib_debug.c lib_bit.c lib_jit.c lib_init.c
149luajit.o: luajit.c lua.h luaconf.h lauxlib.h lualib.h luajit.h lj_arch.h 152luajit.o: luajit.c lua.h luaconf.h lauxlib.h lualib.h luajit.h lj_arch.h
diff --git a/src/lj_cparse.c b/src/lj_cparse.c
new file mode 100644
index 00000000..ddb2e1c9
--- /dev/null
+++ b/src/lj_cparse.c
@@ -0,0 +1,1802 @@
1/*
2** C declaration parser.
3** Copyright (C) 2005-2010 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_ctype.h"
14#include "lj_cparse.h"
15#include "lj_frame.h"
16#include "lj_vm.h"
17#include "lj_char.h"
18
19/*
20** Important note: this is NOT a validating C parser! This is a minimal
21** C declaration parser, solely for use by the LuaJIT FFI.
22**
23** It ought to return correct results for properly formed C declarations,
24** but it may accept some invalid declarations, too (and return nonsense).
25** Also, it shows rather generic error messages to avoid unnecessary bloat.
26** If in doubt, please check the input against your favorite C compiler.
27*/
28
29/* -- C lexer ------------------------------------------------------------- */
30
31/* C lexer token names. */
32static const char *const ctoknames[] = {
33#define CTOKSTR(name, str) str,
34CTOKDEF(CTOKSTR)
35#undef CTOKSTR
36 NULL
37};
38
39/* Forward declaration. */
40LJ_NORET static void cp_err(CPState *cp, ErrMsg em);
41
42static const char *cp_tok2str(CPState *cp, CPToken tok)
43{
44 lua_assert(tok < CTOK_FIRSTDECL);
45 if (tok > CTOK_OFS)
46 return ctoknames[tok-CTOK_OFS-1];
47 else if (!lj_char_iscntrl(tok))
48 return lj_str_pushf(cp->L, "%c", tok);
49 else
50 return lj_str_pushf(cp->L, "char(%d)", tok);
51}
52
53/* End-of-line? */
54static LJ_AINLINE int cp_iseol(CPChar c)
55{
56 return (c == '\n' || c == '\r');
57}
58
59static LJ_AINLINE CPChar cp_get(CPState *cp);
60
61/* Peek next raw character. */
62static LJ_AINLINE CPChar cp_rawpeek(CPState *cp)
63{
64 return (CPChar)(uint8_t)(*cp->p);
65}
66
67/* Transparently skip backslash-escaped line breaks. */
68static LJ_NOINLINE CPChar cp_get_bs(CPState *cp)
69{
70 CPChar c2, c = cp_rawpeek(cp);
71 if (!cp_iseol(c)) return cp->c;
72 cp->p++;
73 c2 = cp_rawpeek(cp);
74 if (cp_iseol(c2) && c2 != c) cp->p++;
75 cp->linenumber++;
76 return cp_get(cp);
77}
78
79/* Get next character. */
80static LJ_AINLINE CPChar cp_get(CPState *cp)
81{
82 cp->c = (CPChar)(uint8_t)(*cp->p++);
83 if (LJ_LIKELY(cp->c != '\\')) return cp->c;
84 return cp_get_bs(cp);
85}
86
87/* Grow save buffer. */
88static LJ_NOINLINE void cp_save_grow(CPState *cp, CPChar c)
89{
90 MSize newsize;
91 if (cp->sb.sz >= CPARSE_MAX_BUF/2)
92 cp_err(cp, LJ_ERR_XELEM);
93 newsize = cp->sb.sz * 2;
94 lj_str_resizebuf(cp->L, &cp->sb, newsize);
95 cp->sb.buf[cp->sb.n++] = (char)c;
96}
97
98/* Save character in buffer. */
99static LJ_AINLINE void cp_save(CPState *cp, CPChar c)
100{
101 if (LJ_UNLIKELY(cp->sb.n + 1 > cp->sb.sz))
102 cp_save_grow(cp, c);
103 else
104 cp->sb.buf[cp->sb.n++] = (char)c;
105}
106
107/* Skip line break. Handles "\n", "\r", "\r\n" or "\n\r". */
108static void cp_newline(CPState *cp)
109{
110 CPChar c = cp_rawpeek(cp);
111 if (cp_iseol(c) && c != cp->c) cp->p++;
112 cp->linenumber++;
113}
114
115LJ_NORET static void cp_errmsg(CPState *cp, CPToken tok, ErrMsg em, ...)
116{
117 const char *msg, *tokstr;
118 lua_State *L;
119 va_list argp;
120 if (tok == 0) {
121 tokstr = NULL;
122 } else if (tok == CTOK_IDENT || tok == CTOK_INTEGER || tok == CTOK_STRING ||
123 tok >= CTOK_FIRSTDECL) {
124 cp_save(cp, '\0');
125 tokstr = cp->sb.buf;
126 } else {
127 tokstr = cp_tok2str(cp, tok);
128 }
129 L = cp->L;
130 va_start(argp, em);
131 msg = lj_str_pushvf(L, err2msg(em), argp);
132 va_end(argp);
133 if (tokstr)
134 msg = lj_str_pushf(L, err2msg(LJ_ERR_XNEAR), msg, tokstr);
135 if (cp->linenumber > 1)
136 msg = lj_str_pushf(L, "%s at line %d", msg, cp->linenumber);
137 lj_err_callermsg(L, msg);
138}
139
140LJ_NORET LJ_NOINLINE static void cp_err_token(CPState *cp, CPToken tok)
141{
142 cp_errmsg(cp, cp->tok, LJ_ERR_XTOKEN, cp_tok2str(cp, tok));
143}
144
145LJ_NORET LJ_NOINLINE static void cp_err_badidx(CPState *cp, CType *ct)
146{
147 GCstr *s = lj_ctype_repr(cp->cts->L, ctype_typeid(cp->cts, ct), NULL);
148 cp_errmsg(cp, 0, LJ_ERR_FFI_BADIDX, strdata(s));
149}
150
151LJ_NORET LJ_NOINLINE static void cp_err(CPState *cp, ErrMsg em)
152{
153 cp_errmsg(cp, 0, em);
154}
155
156/* -- Main lexical scanner ------------------------------------------------ */
157
158/* Parse integer literal. */
159static CPToken cp_integer(CPState *cp)
160{
161 uint32_t n = 0;
162 cp->val.id = CTID_INT32;
163 if (cp->c != '0') { /* Decimal. */
164 do {
165 n = n*10 + (cp->c - '0');
166 } while (lj_char_isdigit(cp_get(cp)));
167 } else if (cp_get(cp) == 'x') { /* Hexadeximal. */
168 if (!lj_char_isxdigit(cp_get(cp)))
169 cp_err(cp, LJ_ERR_XNUMBER);
170 do {
171 n = n*16 + (cp->c & 15);
172 if (!lj_char_isdigit(cp->c)) n += 9;
173 } while (lj_char_isxdigit(cp_get(cp)));
174 if (n >= 0x80000000u) cp->val.id = CTID_UINT32;
175 } else { /* Octal. */
176 while (cp->c >= '0' && cp->c <= '7') {
177 n = n*8 + (cp->c - '0');
178 cp_get(cp);
179 }
180 if (n >= 0x80000000u) cp->val.id = CTID_UINT32;
181 }
182 cp->val.u32 = n;
183 for (;;) { /* Parse suffixes. */
184 if ((cp->c & ~0x20) == 'U')
185 cp->val.id = CTID_UINT32;
186 else if ((cp->c & ~0x20) != 'L')
187 break;
188 cp_get(cp);
189 }
190 if (lj_char_isident(cp->c))
191 cp_errmsg(cp, cp->c, LJ_ERR_XNUMBER);
192 return CTOK_INTEGER;
193}
194
195/* Parse identifier or keyword. */
196static CPToken cp_ident(CPState *cp)
197{
198 do { cp_save(cp, cp->c); } while (lj_char_isident(cp_get(cp)));
199 cp->str = lj_str_new(cp->L, cp->sb.buf, cp->sb.n);
200 cp->val.id = lj_ctype_getname(cp->cts, &cp->ct, cp->str, cp->tmask);
201 if (ctype_type(cp->ct->info) == CT_KW)
202 return ctype_cid(cp->ct->info);
203 return CTOK_IDENT;
204}
205
206/* Parse string or character constant. */
207static CPToken cp_string(CPState *cp)
208{
209 CPChar delim = cp->c;
210 cp_get(cp);
211 while (cp->c != delim) {
212 CPChar c = cp->c;
213 if (c == '\0') cp_errmsg(cp, CTOK_EOF, LJ_ERR_XSTR);
214 if (c == '\\') {
215 c = cp_get(cp);
216 switch (c) {
217 case '\0': cp_errmsg(cp, CTOK_EOF, LJ_ERR_XSTR); break;
218 case 'a': c = '\a'; break;
219 case 'b': c = '\b'; break;
220 case 'f': c = '\f'; break;
221 case 'n': c = '\n'; break;
222 case 'r': c = '\r'; break;
223 case 't': c = '\t'; break;
224 case 'v': c = '\v'; break;
225 case 'e': c = 27; break;
226 case 'x':
227 c = 0;
228 while (lj_char_isxdigit(cp_get(cp)))
229 c = (c<<4) + (lj_char_isdigit(cp->c) ? cp->c-'0' : (cp->c&15)+9);
230 cp_save(cp, (c & 0xff));
231 continue;
232 default:
233 if (lj_char_isdigit(c)) {
234 c -= '0';
235 if (lj_char_isdigit(cp_get(cp))) {
236 c = c*8 + (cp->c - '0');
237 if (lj_char_isdigit(cp_get(cp))) {
238 c = c*8 + (cp->c - '0');
239 cp_get(cp);
240 }
241 }
242 cp_save(cp, (c & 0xff));
243 continue;
244 }
245 break;
246 }
247 }
248 cp_save(cp, c);
249 cp_get(cp);
250 }
251 cp_get(cp);
252 if (delim == '"') {
253 cp->str = lj_str_new(cp->L, cp->sb.buf, cp->sb.n);
254 return CTOK_STRING;
255 } else {
256 if (cp->sb.n != 1) cp_err_token(cp, '\'');
257 cp->val.i32 = (int32_t)(char)cp->sb.buf[0];
258 cp->val.id = CTID_INT32;
259 return CTOK_INTEGER;
260 }
261}
262
263/* Skip C comment. */
264static void cp_comment_c(CPState *cp)
265{
266 do {
267 if (cp_get(cp) == '*' && cp_get(cp) == '/') { cp_get(cp); break; }
268 if (cp_iseol(cp->c)) cp_newline(cp);
269 } while (cp->c != '\0');
270}
271
272/* Skip C++ comment. */
273static void cp_comment_cpp(CPState *cp)
274{
275 while (!cp_iseol(cp_get(cp)) && cp->c != '\0')
276 ;
277}
278
279/* Lexical scanner for C. Only a minimal subset is implemented. */
280static CPToken cp_next_(CPState *cp)
281{
282 lj_str_resetbuf(&cp->sb);
283 for (;;) {
284 if (lj_char_isident(cp->c))
285 return lj_char_isdigit(cp->c) ? cp_integer(cp) : cp_ident(cp);
286 switch (cp->c) {
287 case '\n': case '\r': cp_newline(cp); /* fallthrough. */
288 case ' ': case '\t': case '\v': case '\f': cp_get(cp); break;
289 case '"': case '\'': return cp_string(cp);
290 case '/':
291 cp_get(cp);
292 if (cp->c == '*') cp_comment_c(cp);
293 else if (cp->c == '/') cp_comment_cpp(cp);
294 else return '/';
295 break;
296 case '|':
297 cp_get(cp); if (cp->c != '|') return '|'; cp_get(cp); return CTOK_OROR;
298 case '&':
299 cp_get(cp); if (cp->c != '&') return '&'; cp_get(cp); return CTOK_ANDAND;
300 case '=':
301 cp_get(cp); if (cp->c != '=') return '='; cp_get(cp); return CTOK_EQ;
302 case '!':
303 cp_get(cp); if (cp->c != '=') return '!'; cp_get(cp); return CTOK_NE;
304 case '<':
305 cp_get(cp);
306 if (cp->c == '=') { cp_get(cp); return CTOK_LE; }
307 else if (cp->c == '<') { cp_get(cp); return CTOK_SHL; }
308 return '<';
309 case '>':
310 cp_get(cp);
311 if (cp->c == '=') { cp_get(cp); return CTOK_GE; }
312 else if (cp->c == '>') { cp_get(cp); return CTOK_SHR; }
313 return '>';
314 case '-':
315 cp_get(cp); if (cp->c != '>') return '-'; cp_get(cp); return CTOK_DEREF;
316 case '\0': return CTOK_EOF;
317 default: { CPToken c = cp->c; cp_get(cp); return c; }
318 }
319 }
320}
321
322static LJ_NOINLINE CPToken cp_next(CPState *cp)
323{
324 return (cp->tok = cp_next_(cp));
325}
326
327/* -- C parser ------------------------------------------------------------ */
328
329/* Namespaces for resolving identifiers. */
330#define CPNS_DEFAULT \
331 ((1u<<CT_KW)|(1u<<CT_TYPEDEF)|(1u<<CT_FUNC)|(1u<<CT_EXTERN)|(1u<<CT_CONSTVAL))
332#define CPNS_STRUCT ((1u<<CT_KW)|(1u<<CT_STRUCT)|(1u<<CT_ENUM))
333
334typedef CTypeID CPDeclIdx; /* Index into declaration stack. */
335typedef uint32_t CPscl; /* Storage class flags. */
336
337/* Type declaration context. */
338typedef struct CPDecl {
339 CPDeclIdx top; /* Top of declaration stack. */
340 CPDeclIdx pos; /* Insertion position in declaration chain. */
341 CPDeclIdx specpos; /* Saved position for declaration specifier. */
342 uint32_t mode; /* Declarator mode. */
343 CPState *cp; /* C parser state. */
344 GCstr *name; /* Name of declared identifier (if direct). */
345 CTypeID nameid; /* Existing typedef for declared identifier. */
346 CTInfo attr; /* Attributes. */
347 CTInfo fattr; /* Function attributes. */
348 CTInfo specattr; /* Saved attributes. */
349 CTInfo specfattr; /* Saved function attributes. */
350 CTSize bits; /* Field size in bits (if any). */
351 CType stack[CPARSE_MAX_DECLSTACK]; /* Type declaration stack. */
352} CPDecl;
353
354/* Forward declarations. */
355static CPscl cp_decl_spec(CPState *cp, CPDecl *decl, CPscl scl);
356static void cp_declarator(CPState *cp, CPDecl *decl);
357static CTypeID cp_decl_abstract(CPState *cp);
358
359/* Initialize C parser state. Caller must set up: L, p, srcname, mode. */
360static void cp_init(CPState *cp)
361{
362 cp->linenumber = 1;
363 cp->depth = 0;
364 cp->curpack = 0;
365 cp->packstack[0] = 255;
366 lj_str_initbuf(cp->L, &cp->sb);
367 lj_str_resizebuf(cp->L, &cp->sb, LJ_MIN_SBUF);
368 lua_assert(cp->p != NULL);
369 cp_get(cp); /* Read-ahead first char. */
370 cp->tok = 0;
371 cp->tmask = CPNS_DEFAULT;
372 cp_next(cp); /* Read-ahead first token. */
373}
374
375/* Cleanup C parser state. */
376static void cp_cleanup(CPState *cp)
377{
378 global_State *g = G(cp->L);
379 lj_str_freebuf(g, &cp->sb);
380}
381
382/* Check and consume optional token. */
383static int cp_opt(CPState *cp, CPToken tok)
384{
385 if (cp->tok == tok) { cp_next(cp); return 1; }
386 return 0;
387}
388
389/* Check and consume token. */
390static void cp_check(CPState *cp, CPToken tok)
391{
392 if (cp->tok != tok) cp_err_token(cp, tok);
393 cp_next(cp);
394}
395
396/* Check if the next token may start a type declaration. */
397static int cp_istypedecl(CPState *cp)
398{
399 if (cp->tok >= CTOK_FIRSTDECL && cp->tok <= CTOK_LASTDECL) return 1;
400 if (cp->tok == CTOK_IDENT && ctype_istypedef(cp->ct->info)) return 1;
401 return 0;
402}
403
404/* -- Constant expression evaluator --------------------------------------- */
405
406/* Forward declarations. */
407static void cp_expr_unary(CPState *cp, CPValue *k);
408static void cp_expr_sub(CPState *cp, CPValue *k, int pri);
409
410/* Please note that type handling is very weak here. Most ops simply
411** assume integer operands. Accessors are only needed to compute types and
412** return synthetic values. The only purpose of the expression evaluator
413** is to compute the values of constant expressions one would typically
414** find in C header files. And again: this is NOT a validating C parser!
415*/
416
417/* Parse comma separated expression and return last result. */
418static void cp_expr_comma(CPState *cp, CPValue *k)
419{
420 do { cp_expr_sub(cp, k, 0); } while (cp_opt(cp, ','));
421}
422
423/* Parse sizeof/alignof operator. */
424static void cp_expr_sizeof(CPState *cp, CPValue *k, int wantsz)
425{
426 CTSize sz;
427 CTInfo info;
428 if (cp_opt(cp, '(')) {
429 if (cp_istypedecl(cp))
430 k->id = cp_decl_abstract(cp);
431 else
432 cp_expr_comma(cp, k);
433 cp_check(cp, ')');
434 } else {
435 cp_expr_unary(cp, k);
436 }
437 info = lj_ctype_info(cp->cts, k->id, &sz);
438 if (wantsz) {
439 if (sz != CTSIZE_INVALID)
440 k->u32 = sz;
441 else if (k->id != CTID_A_CCHAR) /* Special case for sizeof("string"). */
442 cp_err(cp, LJ_ERR_FFI_INVSIZE);
443 } else {
444 k->u32 = 1u << ctype_align(info);
445 }
446 k->id = CTID_UINT32; /* Really size_t. */
447}
448
449/* Parse prefix operators. */
450static void cp_expr_prefix(CPState *cp, CPValue *k)
451{
452 if (cp->tok == CTOK_INTEGER) {
453 *k = cp->val; cp_next(cp);
454 } else if (cp_opt(cp, '+')) {
455 cp_expr_unary(cp, k); /* Nothing to do (well, integer promotion). */
456 } else if (cp_opt(cp, '-')) {
457 cp_expr_unary(cp, k); k->i32 = -k->i32;
458 } else if (cp_opt(cp, '~')) {
459 cp_expr_unary(cp, k); k->i32 = ~k->i32;
460 } else if (cp_opt(cp, '!')) {
461 cp_expr_unary(cp, k); k->i32 = !k->i32; k->id = CTID_INT32;
462 } else if (cp_opt(cp, '(')) {
463 if (cp_istypedecl(cp)) { /* Cast operator. */
464 CTypeID id = cp_decl_abstract(cp);
465 cp_check(cp, ')');
466 cp_expr_unary(cp, k);
467 k->id = id; /* No conversion performed. */
468 } else { /* Sub-expression. */
469 cp_expr_comma(cp, k);
470 cp_check(cp, ')');
471 }
472 } else if (cp_opt(cp, '*')) { /* Indirection. */
473 CType *ct;
474 cp_expr_unary(cp, k);
475 ct = lj_ctype_rawref(cp->cts, k->id);
476 if (!ctype_ispointer(ct->info))
477 cp_err_badidx(cp, ct);
478 k->u32 = 0; k->id = ctype_cid(ct->info);
479 } else if (cp_opt(cp, '&')) { /* Address operator. */
480 cp_expr_unary(cp, k);
481 k->id = lj_ctype_intern(cp->cts, CTINFO(CT_PTR, CTALIGN_PTR+k->id),
482 CTSIZE_PTR);
483 } else if (cp_opt(cp, CTOK_SIZEOF)) {
484 cp_expr_sizeof(cp, k, 1);
485 } else if (cp_opt(cp, CTOK_ALIGNOF)) {
486 cp_expr_sizeof(cp, k, 0);
487 } else if (cp->tok == CTOK_IDENT) {
488 if (ctype_type(cp->ct->info) == CT_CONSTVAL) {
489 k->u32 = cp->ct->size; k->id = ctype_cid(cp->ct->info);
490 } else if (ctype_type(cp->ct->info) == CT_EXTERN) {
491 k->u32 = cp->val.id; k->id = ctype_cid(cp->ct->info);
492 } else if (ctype_type(cp->ct->info) == CT_FUNC) {
493 k->u32 = cp->val.id; k->id = cp->val.id;
494 } else {
495 goto err_expr;
496 }
497 cp_next(cp);
498 } else if (cp->tok == CTOK_STRING) {
499 CTSize sz = cp->str->len;
500 while (cp_next(cp) == CTOK_STRING)
501 sz += cp->str->len;
502 k->u32 = sz + 1;
503 k->id = CTID_A_CCHAR;
504 } else {
505 err_expr:
506 cp_errmsg(cp, cp->tok, LJ_ERR_XSYMBOL);
507 }
508}
509
510/* Parse postfix operators. */
511static void cp_expr_postfix(CPState *cp, CPValue *k)
512{
513 for (;;) {
514 CType *ct;
515 if (cp_opt(cp, '[')) { /* Array/pointer index. */
516 CPValue k2;
517 cp_expr_comma(cp, &k2);
518 ct = lj_ctype_rawref(cp->cts, k->id);
519 if (!ctype_ispointer(ct->info)) {
520 ct = lj_ctype_rawref(cp->cts, k2.id);
521 if (!ctype_ispointer(ct->info))
522 cp_err_badidx(cp, ct);
523 }
524 cp_check(cp, ']');
525 k->u32 = 0;
526 } else if (cp->tok == '.' || cp->tok == CTOK_DEREF) { /* Struct deref. */
527 CTSize ofs;
528 CType *fct;
529 ct = lj_ctype_rawref(cp->cts, k->id);
530 if (cp->tok == CTOK_DEREF) {
531 if (!ctype_ispointer(ct->info))
532 cp_err_badidx(cp, ct);
533 ct = lj_ctype_rawref(cp->cts, ctype_cid(ct->info));
534 }
535 cp_next(cp);
536 if (cp->tok != CTOK_IDENT) cp_err_token(cp, CTOK_IDENT);
537 if (!ctype_isstruct(ct->info) || ct->size == CTSIZE_INVALID ||
538 !(fct = lj_ctype_getfield(cp->cts, ct, cp->str, &ofs)) ||
539 ctype_isbitfield(fct->info)) {
540 GCstr *s = lj_ctype_repr(cp->cts->L, ctype_typeid(cp->cts, ct), NULL);
541 cp_errmsg(cp, 0, LJ_ERR_FFI_BADMEMBER, strdata(s), strdata(cp->str));
542 }
543 ct = fct;
544 k->u32 = ctype_isconstval(ct->info) ? ct->size : 0;
545 cp_next(cp);
546 } else {
547 return;
548 }
549 k->id = ctype_cid(ct->info);
550 }
551}
552
553/* Parse infix operators. */
554static void cp_expr_infix(CPState *cp, CPValue *k, int pri)
555{
556 CPValue k2;
557 k2.u32 = 0; k2.id = 0; /* Silence the compiler. */
558 for (;;) {
559 switch (pri) {
560 case 0:
561 if (cp_opt(cp, '?')) {
562 CPValue k3;
563 cp_expr_comma(cp, &k2); /* Right-associative. */
564 cp_check(cp, ':');
565 cp_expr_sub(cp, &k3, 0);
566 k->u32 = k->u32 ? k2.u32 : k3.u32;
567 k->id = k2.id > k3.id ? k2.id : k3.id;
568 continue;
569 }
570 case 1:
571 if (cp_opt(cp, CTOK_OROR)) {
572 cp_expr_sub(cp, &k2, 2); k->i32 = k->u32 || k2.u32; k->id = CTID_INT32;
573 continue;
574 }
575 case 2:
576 if (cp_opt(cp, CTOK_ANDAND)) {
577 cp_expr_sub(cp, &k2, 3); k->i32 = k->u32 && k2.u32; k->id = CTID_INT32;
578 continue;
579 }
580 case 3:
581 if (cp_opt(cp, '|')) {
582 cp_expr_sub(cp, &k2, 4); k->u32 = k->u32 | k2.u32; goto arith_result;
583 }
584 case 4:
585 if (cp_opt(cp, '^')) {
586 cp_expr_sub(cp, &k2, 5); k->u32 = k->u32 ^ k2.u32; goto arith_result;
587 }
588 case 5:
589 if (cp_opt(cp, '&')) {
590 cp_expr_sub(cp, &k2, 6); k->u32 = k->u32 & k2.u32; goto arith_result;
591 }
592 case 6:
593 if (cp_opt(cp, CTOK_EQ)) {
594 cp_expr_sub(cp, &k2, 7); k->i32 = k->u32 == k2.u32; k->id = CTID_INT32;
595 continue;
596 } else if (cp_opt(cp, CTOK_NE)) {
597 cp_expr_sub(cp, &k2, 7); k->i32 = k->u32 != k2.u32; k->id = CTID_INT32;
598 continue;
599 }
600 case 7:
601 if (cp_opt(cp, '<')) {
602 cp_expr_sub(cp, &k2, 8);
603 if (k->id == CTID_INT32 && k2.id == CTID_INT32)
604 k->i32 = k->i32 < k2.i32;
605 else
606 k->i32 = k->u32 < k2.u32;
607 k->id = CTID_INT32;
608 continue;
609 } else if (cp_opt(cp, '>')) {
610 cp_expr_sub(cp, &k2, 8);
611 if (k->id == CTID_INT32 && k2.id == CTID_INT32)
612 k->i32 = k->i32 > k2.i32;
613 else
614 k->i32 = k->u32 > k2.u32;
615 k->id = CTID_INT32;
616 continue;
617 } else if (cp_opt(cp, CTOK_LE)) {
618 cp_expr_sub(cp, &k2, 8);
619 if (k->id == CTID_INT32 && k2.id == CTID_INT32)
620 k->i32 = k->i32 <= k2.i32;
621 else
622 k->i32 = k->u32 <= k2.u32;
623 k->id = CTID_INT32;
624 continue;
625 } else if (cp_opt(cp, CTOK_GE)) {
626 cp_expr_sub(cp, &k2, 8);
627 if (k->id == CTID_INT32 && k2.id == CTID_INT32)
628 k->i32 = k->i32 >= k2.i32;
629 else
630 k->i32 = k->u32 >= k2.u32;
631 k->id = CTID_INT32;
632 continue;
633 }
634 case 8:
635 if (cp_opt(cp, CTOK_SHL)) {
636 cp_expr_sub(cp, &k2, 9); k->u32 = k->u32 << k2.u32;
637 continue;
638 } else if (cp_opt(cp, CTOK_SHR)) {
639 cp_expr_sub(cp, &k2, 9);
640 if (k->id == CTID_INT32)
641 k->i32 = k->i32 >> k2.i32;
642 else
643 k->u32 = k->u32 >> k2.u32;
644 continue;
645 }
646 case 9:
647 if (cp_opt(cp, '+')) {
648 cp_expr_sub(cp, &k2, 10); k->u32 = k->u32 + k2.u32;
649 arith_result:
650 if (k2.id > k->id) k->id = k2.id; /* Trivial promotion to unsigned. */
651 continue;
652 } else if (cp_opt(cp, '-')) {
653 cp_expr_sub(cp, &k2, 10); k->u32 = k->u32 - k2.u32; goto arith_result;
654 }
655 case 10:
656 if (cp_opt(cp, '*')) {
657 cp_expr_unary(cp, &k2); k->u32 = k->u32 * k2.u32; goto arith_result;
658 } else if (cp_opt(cp, '/')) {
659 cp_expr_unary(cp, &k2);
660 if (k2.id > k->id) k->id = k2.id; /* Trivial promotion to unsigned. */
661 if (k2.u32 == 0 ||
662 (k->id == CTID_INT32 && k->u32 == 0x80000000u && k2.i32 == -1))
663 cp_err(cp, LJ_ERR_BADVAL);
664 if (k->id == CTID_INT32)
665 k->i32 = k->i32 / k2.i32;
666 else
667 k->u32 = k->u32 / k2.u32;
668 continue;
669 } else if (cp_opt(cp, '%')) {
670 cp_expr_unary(cp, &k2);
671 if (k2.id > k->id) k->id = k2.id; /* Trivial promotion to unsigned. */
672 if (k2.u32 == 0 ||
673 (k->id == CTID_INT32 && k->u32 == 0x80000000u && k2.i32 == -1))
674 cp_err(cp, LJ_ERR_BADVAL);
675 if (k->id == CTID_INT32)
676 k->i32 = k->i32 % k2.i32;
677 else
678 k->u32 = k->u32 % k2.u32;
679 continue;
680 }
681 default:
682 return;
683 }
684 }
685}
686
687/* Parse and evaluate unary expression. */
688static void cp_expr_unary(CPState *cp, CPValue *k)
689{
690 if (++cp->depth > CPARSE_MAX_DECLDEPTH) cp_err(cp, LJ_ERR_XLEVELS);
691 cp_expr_prefix(cp, k);
692 cp_expr_postfix(cp, k);
693 cp->depth--;
694}
695
696/* Parse and evaluate sub-expression. */
697static void cp_expr_sub(CPState *cp, CPValue *k, int pri)
698{
699 cp_expr_unary(cp, k);
700 cp_expr_infix(cp, k, pri);
701}
702
703/* Parse constant integer expression. */
704static void cp_expr_kint(CPState *cp, CPValue *k)
705{
706 CType *ct;
707 cp_expr_sub(cp, k, 0);
708 ct = ctype_raw(cp->cts, k->id);
709 if (!ctype_isinteger(ct->info)) cp_err(cp, LJ_ERR_BADVAL);
710}
711
712/* Parse (non-negative) size expression. */
713static CTSize cp_expr_ksize(CPState *cp)
714{
715 CPValue k;
716 cp_expr_kint(cp, &k);
717 if (k.u32 >= 0x80000000u) cp_err(cp, LJ_ERR_FFI_INVSIZE);
718 return k.u32;
719}
720
721/* -- Type declaration stack management ----------------------------------- */
722
723/* Add declaration element behind the insertion position. */
724static CPDeclIdx cp_add(CPDecl *decl, CTInfo info, CTSize size)
725{
726 CPDeclIdx top = decl->top;
727 if (top >= CPARSE_MAX_DECLSTACK) cp_err(decl->cp, LJ_ERR_XLEVELS);
728 decl->stack[top].info = info;
729 decl->stack[top].size = size;
730 decl->stack[top].sib = 0;
731 setgcrefnull(decl->stack[top].name);
732 decl->stack[top].next = decl->stack[decl->pos].next;
733 decl->stack[decl->pos].next = (CTypeID1)top;
734 decl->top = top+1;
735 return top;
736}
737
738/* Push declaration element before the insertion position. */
739static CPDeclIdx cp_push(CPDecl *decl, CTInfo info, CTSize size)
740{
741 return (decl->pos = cp_add(decl, info, size));
742}
743
744/* Push or merge attributes. */
745static void cp_push_attributes(CPDecl *decl)
746{
747 CType *ct = &decl->stack[decl->pos];
748 if (ctype_isfunc(ct->info)) { /* Ok to modify in-place. */
749#if LJ_TARGET_X86
750 if ((decl->fattr & CTFP_CCONV))
751 ct->info = (ct->info & (CTMASK_NUM|CTF_VARARG|CTMASK_CID)) +
752 (decl->fattr & ~CTMASK_CID);
753#endif
754 } else {
755 if ((decl->attr & CTFP_ALIGNED) && !(decl->mode & CPARSE_MODE_FIELD))
756 cp_push(decl, CTINFO(CT_ATTRIB, CTATTRIB(CTA_ALIGN)),
757 ctype_align(decl->attr));
758 }
759}
760
761/* Push unrolled type to declaration stack and merge qualifiers. */
762static void cp_push_type(CPDecl *decl, CTypeID id)
763{
764 CType *ct = ctype_get(decl->cp->cts, id);
765 CTInfo info = ct->info;
766 CTSize size = ct->size;
767 switch (ctype_type(info)) {
768 case CT_STRUCT: case CT_ENUM:
769 cp_push(decl, CTINFO(CT_TYPEDEF, id), 0); /* Don't copy unique types. */
770 if ((decl->attr & CTF_QUAL)) { /* Push unmerged qualifiers. */
771 cp_push(decl, CTINFO(CT_ATTRIB, CTATTRIB(CTA_QUAL)),
772 (decl->attr & CTF_QUAL));
773 decl->attr &= ~CTF_QUAL;
774 }
775 break;
776 case CT_ATTRIB:
777 if (ctype_isxattrib(info, CTA_QUAL))
778 decl->attr &= ~size; /* Remove redundant qualifiers. */
779 cp_push_type(decl, ctype_cid(info)); /* Unroll. */
780 cp_push(decl, info & ~CTMASK_CID, size); /* Copy type. */
781 break;
782 case CT_ARRAY:
783 cp_push_type(decl, ctype_cid(info)); /* Unroll. */
784 cp_push(decl, info & ~CTMASK_CID, size); /* Copy type. */
785 decl->stack[decl->pos].sib = 1; /* Mark as already checked and sized. */
786 /* Note: this is not copied to the ct->sib in the C type table. */
787 break;
788 case CT_FUNC:
789 /* Copy type, link parameters (shared). */
790 decl->stack[cp_push(decl, info, size)].sib = ct->sib;
791 break;
792 default:
793 /* Copy type, merge common qualifiers. */
794 cp_push(decl, info|(decl->attr & CTF_QUAL), size);
795 decl->attr &= ~CTF_QUAL;
796 break;
797 }
798}
799
800/* Consume the declaration element chain and intern the C type. */
801static CTypeID cp_decl_intern(CPState *cp, CPDecl *decl)
802{
803 CTypeID id = 0;
804 CPDeclIdx idx = 0;
805 CTSize csize = CTSIZE_INVALID;
806 CTSize cinfo = 0;
807 do {
808 CType *ct = &decl->stack[idx];
809 CTInfo info = ct->info;
810 CTInfo size = ct->size;
811 /* The cid is already part of info for copies of pointers/functions. */
812 idx = ct->next;
813 if (ctype_istypedef(info)) {
814 lua_assert(id == 0);
815 id = ctype_cid(info);
816 /* Always refetch info/size, since struct/enum may have been completed. */
817 cinfo = ctype_get(cp->cts, id)->info;
818 csize = ctype_get(cp->cts, id)->size;
819 lua_assert(ctype_isstruct(cinfo) || ctype_isenum(cinfo));
820 } else if (ctype_isfunc(info)) { /* Intern function. */
821 CType *fct;
822 CTypeID fid;
823 if (id) {
824 CType *refct = ctype_raw(cp->cts, id);
825 /* Reject function or refarray return types. */
826 if (ctype_isfunc(refct->info) || ctype_isrefarray(refct->info))
827 cp_err(cp, LJ_ERR_FFI_INVTYPE);
828 }
829 /* No intervening attributes allowed, skip forward. */
830 while (idx) {
831 CType *ctn = &decl->stack[idx];
832 if (!ctype_isattrib(ctn->info)) break;
833 idx = ctn->next; /* Skip attribute. */
834 }
835 fid = lj_ctype_new(cp->cts, &fct);
836 csize = CTSIZE_INVALID;
837 fct->info = cinfo = info + id;
838 fct->size = ct->size;
839 fct->sib = ct->sib;
840 id = fid;
841 } else if (ctype_isattrib(info)) {
842 if (ctype_isxattrib(info, CTA_QUAL))
843 cinfo |= size;
844 else if (ctype_isxattrib(info, CTA_ALIGN))
845 CTF_INSERT(cinfo, ALIGN, size);
846 id = lj_ctype_intern(cp->cts, info+id, size);
847 /* Inherit csize/cinfo from original type. */
848 } else {
849 if (ctype_isnum(info)) { /* Handle mode/vector-size attributes. */
850 lua_assert(id == 0);
851 if (!(info & CTF_BOOL)) {
852 CTSize msize = ctype_msizeP(decl->attr);
853 CTSize vsize = ctype_vsizeP(decl->attr);
854 if (msize && (!(info & CTF_FP) || (msize == 4 || msize == 8)))
855 size = msize; /* Override size via mode. */
856 if (vsize) { /* Vector size set? */
857 CTSize esize = lj_fls(size);
858 if (vsize >= esize) {
859 /* Intern the element type first. */
860 id = lj_ctype_intern(cp->cts, info, size);
861 /* Then create a vector (array) with vsize alignment. */
862 if (ctype_align(info) > vsize) vsize = ctype_align(info);
863 info = CTINFO(CT_ARRAY, (info & CTF_QUAL) + CTF_VECTOR +
864 CTALIGN(vsize));
865 size = (1u << vsize);
866 }
867 }
868 }
869 } else if (ctype_isptr(info)) {
870 /* Reject pointer/ref to ref. */
871 if (id && ctype_isref(ctype_raw(cp->cts, id)->info))
872 cp_err(cp, LJ_ERR_FFI_INVTYPE);
873 if (ctype_isref(info)) {
874 info &= ~CTF_VOLATILE; /* Refs are always const, never volatile. */
875 /* No intervening attributes allowed, skip forward. */
876 while (idx) {
877 CType *ctn = &decl->stack[idx];
878 if (!ctype_isattrib(ctn->info)) break;
879 idx = ctn->next; /* Skip attribute. */
880 }
881 }
882 } else if (ctype_isarray(info)) { /* Check for valid array size etc. */
883 if (ct->sib == 0) { /* Only check/size arrays not copied by unroll. */
884 if (ctype_isref(cinfo)) /* Reject arrays of refs. */
885 cp_err(cp, LJ_ERR_FFI_INVTYPE);
886 /* Reject VLS or unknown-sized types. */
887 if (ctype_isvltype(cinfo) || csize == CTSIZE_INVALID)
888 cp_err(cp, LJ_ERR_FFI_INVSIZE);
889 /* a[] and a[?] keep their invalid size. */
890 if (size != CTSIZE_INVALID) {
891 uint64_t xsz = (uint64_t)size * csize;
892 if (xsz >= 0x80000000u) cp_err(cp, LJ_ERR_FFI_INVSIZE);
893 size = (CTSize)xsz;
894 }
895 }
896 info |= (cinfo & (CTF_QUAL|CTF_ALIGN)); /* Inherit qual and align. */
897 } else {
898 lua_assert(ctype_isvoid(info));
899 }
900 csize = size;
901 cinfo = info+id;
902 id = lj_ctype_intern(cp->cts, info+id, size);
903 }
904 } while (idx);
905 return id;
906}
907
908/* -- C declaration parser ------------------------------------------------ */
909
910#define H_(le, be) LJ_ENDIAN_SELECT(0x##le, 0x##be)
911
912/* Reset declaration state to declaration specifier. */
913static void cp_decl_reset(CPDecl *decl)
914{
915 decl->pos = decl->specpos;
916 decl->top = decl->specpos+1;
917 decl->stack[decl->specpos].next = 0;
918 decl->attr = decl->specattr;
919 decl->fattr = decl->specfattr;
920 decl->name = NULL;
921}
922
923/* Parse constant initializer. */
924/* NYI: FP constants and strings as initializers. */
925static CTypeID cp_decl_constinit(CPState *cp, CType **ctp, CTypeID typeid)
926{
927 CType *ctt = ctype_get(cp->cts, typeid);
928 CPValue k;
929 CTypeID constid;
930 while (ctype_isattrib(ctt->info)) { /* Skip attributes. */
931 typeid = ctype_cid(ctt->info); /* Update ID, too. */
932 ctt = ctype_get(cp->cts, typeid);
933 }
934 if (!ctype_isinteger(ctt->info) || !(ctt->info & CTF_CONST) || ctt->size > 4)
935 cp_err(cp, LJ_ERR_FFI_INVTYPE);
936 cp_check(cp, '=');
937 cp_expr_sub(cp, &k, 0);
938 constid = lj_ctype_new(cp->cts, ctp);
939 (*ctp)->info = CTINFO(CT_CONSTVAL, CTF_CONST|typeid);
940 k.u32 <<= 8*(4-ctt->size);
941 if ((ctt->info & CTF_UNSIGNED))
942 k.u32 >>= 8*(4-ctt->size);
943 else
944 k.u32 = (uint32_t)((int32_t)k.u32 >> 8*(4-ctt->size));
945 (*ctp)->size = k.u32;
946 return constid;
947}
948
949/* Parse size in parentheses as part of attribute. */
950static CTSize cp_decl_sizeattr(CPState *cp)
951{
952 CTSize sz;
953 uint32_t oldtmask = cp->tmask;
954 cp->tmask = CPNS_DEFAULT; /* Required for expression evaluator. */
955 cp_check(cp, '(');
956 sz = cp_expr_ksize(cp);
957 cp->tmask = oldtmask;
958 cp_check(cp, ')');
959 return sz;
960}
961
962/* Parse alignment attribute. */
963static void cp_decl_align(CPState *cp, CPDecl *decl)
964{
965 CTSize al = 4; /* Unspecified alignment is 16 bytes. */
966 if (cp->tok == '(') {
967 al = cp_decl_sizeattr(cp);
968 al = al ? lj_fls(al) : 0;
969 }
970 CTF_INSERT(decl->attr, ALIGN, al);
971 decl->attr |= CTFP_ALIGNED;
972}
973
974/* Parse GCC asm("name") redirect. */
975static void cp_decl_asm(CPState *cp, CPDecl *decl)
976{
977 UNUSED(decl);
978 cp_next(cp);
979 cp_check(cp, '(');
980 while (cp->tok == CTOK_STRING) cp_next(cp); /* NYI: currently ignored. */
981 cp_check(cp, ')');
982}
983
984/* Parse GCC __attribute__((mode(...))). */
985static void cp_decl_mode(CPState *cp, CPDecl *decl)
986{
987 cp_check(cp, '(');
988 if (cp->tok == CTOK_IDENT) {
989 const char *s = strdata(cp->str);
990 CTSize sz = 0, vlen = 0;
991 if (s[0] == '_' && s[1] == '_') s += 2;
992 if (*s == 'V') {
993 s++;
994 vlen = *s++ - '0';
995 if (*s >= '0' && *s <= '9')
996 vlen = vlen*10 + (*s++ - '0');
997 }
998 switch (*s++) {
999 case 'Q': sz = 1; break;
1000 case 'H': sz = 2; break;
1001 case 'S': sz = 4; break;
1002 case 'D': sz = 8; break;
1003 case 'T': sz = 16; break;
1004 case 'O': sz = 32; break;
1005 default: goto bad_size;
1006 }
1007 if (*s == 'I' || *s == 'F') {
1008 CTF_INSERT(decl->attr, MSIZEP, sz);
1009 if (vlen) CTF_INSERT(decl->attr, VSIZEP, lj_fls(vlen*sz));
1010 }
1011 bad_size:
1012 cp_next(cp);
1013 }
1014 cp_check(cp, ')');
1015}
1016
1017/* Parse GCC __attribute__((...)). */
1018static void cp_decl_gccattribute(CPState *cp, CPDecl *decl)
1019{
1020 cp_next(cp);
1021 cp_check(cp, '(');
1022 cp_check(cp, '(');
1023 while (cp->tok != ')') {
1024 if (cp->tok == CTOK_IDENT) {
1025 GCstr *attrstr = cp->str;
1026 cp_next(cp);
1027 switch (attrstr->hash) {
1028 case H_(64a9208e,8ce14319): case H_(8e6331b2,95a282af): /* aligned */
1029 cp_decl_align(cp, decl);
1030 break;
1031 case H_(42eb47de,f0ede26c): case H_(29f48a09,cf383e0c): /* packed */
1032 decl->attr |= CTFP_PACKED;
1033 break;
1034 case H_(0a84eef6,8dfab04c): case H_(995cf92c,d5696591): /* mode */
1035 cp_decl_mode(cp, decl);
1036 break;
1037 case H_(0ab31997,2d5213fa): case H_(bf875611,200e9990): /* vector_size */
1038 {
1039 CTSize vsize = cp_decl_sizeattr(cp);
1040 if (vsize) CTF_INSERT(decl->attr, VSIZEP, lj_fls(vsize));
1041 }
1042 break;
1043#if LJ_TARGET_X86
1044 case H_(5ad22db8,c689b848): case H_(439150fa,65ea78cb): /* regparm */
1045 CTF_INSERT(decl->fattr, REGPARM, cp_decl_sizeattr(cp));
1046 decl->fattr |= CTFP_CCONV;
1047 break;
1048 case H_(18fc0b98,7ff4c074): case H_(4e62abed,0a747424): /* cdecl */
1049 CTF_INSERT(decl->fattr, CCONV, CTCC_CDECL);
1050 decl->fattr |= CTFP_CCONV;
1051 break;
1052 case H_(72b2e41b,494c5a44): case H_(f2356d59,f25fc9bd): /* thiscall */
1053 CTF_INSERT(decl->fattr, CCONV, CTCC_THISCALL);
1054 decl->fattr |= CTFP_CCONV;
1055 break;
1056 case H_(0d0ffc42,ab746f88): case H_(21c54ba1,7f0ca7e3): /* fastcall */
1057 CTF_INSERT(decl->fattr, CCONV, CTCC_FASTCALL);
1058 decl->fattr |= CTFP_CCONV;
1059 break;
1060 case H_(ef76b040,9412e06a): case H_(de56697b,c750e6e1): /* stdcall */
1061 CTF_INSERT(decl->fattr, CCONV, CTCC_STDCALL);
1062 decl->fattr |= CTFP_CCONV;
1063 break;
1064 case H_(ea78b622,f234bd8e): case H_(252ffb06,8d50f34b): /* sseregparm */
1065 decl->fattr |= CTF_SSEREGPARM;
1066 decl->fattr |= CTFP_CCONV;
1067 break;
1068#endif
1069 default: /* Skip all other attributes. */
1070 goto skip_attr;
1071 }
1072 } else if (cp->tok >= CTOK_FIRSTDECL) { /* For __attribute((const)) etc. */
1073 cp_next(cp);
1074 skip_attr:
1075 if (cp_opt(cp, '(')) {
1076 while (cp->tok != ')' && cp->tok != CTOK_EOF) cp_next(cp);
1077 cp_check(cp, ')');
1078 }
1079 } else {
1080 break;
1081 }
1082 if (!cp_opt(cp, ',')) break;
1083 }
1084 cp_check(cp, ')');
1085 cp_check(cp, ')');
1086}
1087
1088/* Parse MSVC __declspec(...). */
1089static void cp_decl_msvcattribute(CPState *cp, CPDecl *decl)
1090{
1091 cp_next(cp);
1092 cp_check(cp, '(');
1093 while (cp->tok == CTOK_IDENT) {
1094 GCstr *attrstr = cp->str;
1095 cp_next(cp);
1096 switch (attrstr->hash) {
1097 case H_(bc2395fa,98f267f8): /* align */
1098 cp_decl_align(cp, decl);
1099 break;
1100 default: /* Ignore all other attributes. */
1101 if (cp_opt(cp, '(')) {
1102 while (cp->tok != ')' && cp->tok != CTOK_EOF) cp_next(cp);
1103 cp_check(cp, ')');
1104 }
1105 break;
1106 }
1107 }
1108 cp_check(cp, ')');
1109}
1110
1111/* Parse declaration attributes (and common qualifiers). */
1112static void cp_decl_attributes(CPState *cp, CPDecl *decl)
1113{
1114 for (;;) {
1115 switch (cp->tok) {
1116 case CTOK_CONST: decl->attr |= CTF_CONST; break;
1117 case CTOK_VOLATILE: decl->attr |= CTF_VOLATILE; break;
1118 case CTOK_RESTRICT: break; /* Ignore. */
1119 case CTOK_EXTENSION: break; /* Ignore. */
1120 case CTOK_ATTRIBUTE: cp_decl_gccattribute(cp, decl); continue;
1121 case CTOK_ASM: cp_decl_asm(cp, decl); continue;
1122 case CTOK_DECLSPEC: cp_decl_msvcattribute(cp, decl); continue;
1123 case CTOK_CCDECL:
1124#if LJ_TARGET_X86
1125 CTF_INSERT(decl->fattr, CCONV, cp->ct->size);
1126 decl->fattr |= CTFP_CCONV;
1127#endif
1128 break;
1129 case CTOK_PTRSZ:
1130#if LJ_64
1131 CTF_INSERT(decl->attr, MSIZEP, cp->ct->size);
1132#endif
1133 break;
1134 default: return;
1135 }
1136 cp_next(cp);
1137 }
1138}
1139
1140/* Parse struct/union/enum name. */
1141static CTypeID cp_struct_name(CPState *cp, CPDecl *sdecl, CTInfo info)
1142{
1143 CTypeID sid;
1144 CType *ct;
1145 cp->tmask = CPNS_STRUCT;
1146 cp_next(cp);
1147 cp_decl_attributes(cp, sdecl);
1148 cp->tmask = CPNS_DEFAULT;
1149 if (cp->tok != '{') {
1150 if (cp->tok != CTOK_IDENT) cp_err_token(cp, CTOK_IDENT);
1151 if (cp->val.id) { /* Name of existing struct/union/enum. */
1152 sid = cp->val.id;
1153 ct = cp->ct;
1154 if ((ct->info ^ info) & (CTMASK_NUM|CTF_UNION)) /* Wrong type. */
1155 cp_errmsg(cp, 0, LJ_ERR_FFI_REDEF, strdata(gco2str(gcref(ct->name))));
1156 } else { /* Create named, incomplete struct/union/enum. */
1157 if ((cp->mode & CPARSE_MODE_NOIMPLICIT))
1158 cp_errmsg(cp, 0, LJ_ERR_FFI_BADTAG, strdata(cp->str));
1159 sid = lj_ctype_new(cp->cts, &ct);
1160 ct->info = info;
1161 ct->size = CTSIZE_INVALID;
1162 ctype_setname(ct, cp->str);
1163 lj_ctype_addname(cp->cts, ct, sid);
1164 }
1165 cp_next(cp);
1166 } else { /* Create anonymous, incomplete struct/union/enum. */
1167 sid = lj_ctype_new(cp->cts, &ct);
1168 ct->info = info;
1169 ct->size = CTSIZE_INVALID;
1170 }
1171 if (cp->tok == '{') {
1172 if (ct->size != CTSIZE_INVALID || ct->sib)
1173 cp_errmsg(cp, 0, LJ_ERR_FFI_REDEF, strdata(gco2str(gcref(ct->name))));
1174 ct->sib = 1; /* Indicate the type is currently being defined. */
1175 }
1176 return sid;
1177}
1178
1179/* Determine field alignment. */
1180static CTSize cp_field_align(CPState *cp, CType *ct, CTInfo info)
1181{
1182 CTSize align = ctype_align(info);
1183 UNUSED(cp); UNUSED(ct);
1184#if LJ_TARGET_X86 && !LJ_ABI_WIN
1185 /* The SYSV i386 ABI limits alignment of non-vector fields to 4 bytes. */
1186 if (align > 2 && !(info & CTFP_ALIGNED)) {
1187 if (ctype_isarray(info) && !(info & CTF_VECTOR)) {
1188 do {
1189 ct = ctype_rawchild(cp->cts, ct);
1190 info = ct->info;
1191 } while (ctype_isarray(info) && !(info & CTF_VECTOR));
1192 }
1193 if (ctype_isnum(info) || ctype_isenum(info))
1194 align = 2;
1195 }
1196#endif
1197 return align;
1198}
1199
1200/* Layout struct/union fields. */
1201static void cp_struct_layout(CPState *cp, CTypeID sid, CTInfo sattr)
1202{
1203 CTSize bofs = 0, bmaxofs = 0; /* Bit offset and max. bit offset. */
1204 CTSize maxalign = ctype_align(sattr);
1205 CType *sct = ctype_get(cp->cts, sid);
1206 CTInfo sinfo = sct->info;
1207 CTypeID fieldid = sct->sib;
1208 while (fieldid) {
1209 CType *ct = ctype_get(cp->cts, fieldid);
1210 CTInfo attr = ct->size; /* Field declaration attributes (temp.). */
1211
1212 if (ctype_isfield(ct->info) ||
1213 (ctype_isxattrib(ct->info, CTA_SUBTYPE) && attr)) {
1214 CTSize align, amask; /* Alignment (pow2) and alignment mask (bits). */
1215 CTSize sz;
1216 CTInfo info = lj_ctype_info(cp->cts, ctype_cid(ct->info), &sz);
1217 CTSize bsz, csz = 8*sz; /* Field size and container size (in bits). */
1218 sinfo |= (info & (CTF_QUAL|CTF_VLA)); /* Merge pseudo-qualifiers. */
1219
1220 /* Check for size overflow and determine alignment. */
1221 if (sz >= 0x20000000u || bofs + csz < bofs) {
1222 if (!(sz == CTSIZE_INVALID && ctype_isarray(info) &&
1223 !(sinfo & CTF_UNION)))
1224 cp_err(cp, LJ_ERR_FFI_INVSIZE);
1225 csz = sz = 0; /* Treat a[] and a[?] as zero-sized. */
1226 }
1227 align = cp_field_align(cp, ct, info);
1228 if (((attr|sattr) & CTFP_PACKED) ||
1229 ((attr & CTFP_ALIGNED) && ctype_align(attr) > align))
1230 align = ctype_align(attr);
1231 if (cp->packstack[cp->curpack] < align)
1232 align = cp->packstack[cp->curpack];
1233 if (align > maxalign) maxalign = align;
1234 amask = (8u << align) - 1;
1235
1236 bsz = ctype_bitcsz(ct->info); /* Bitfield size (temp.). */
1237 if (bsz == CTBSZ_FIELD || !ctype_isfield(ct->info)) {
1238 bsz = csz; /* Regular fields or subtypes always fill the container. */
1239 bofs = (bofs + amask) & ~amask; /* Start new aligned field. */
1240 ct->size = (bofs >> 3); /* Store field offset. */
1241 } else { /* Bitfield. */
1242 if (bsz == 0 || (attr & CTFP_ALIGNED) ||
1243 (!((attr|sattr) & CTFP_PACKED) && (bofs & amask) + bsz > csz))
1244 bofs = (bofs + amask) & ~amask; /* Start new aligned field. */
1245
1246 /* Prefer regular field over bitfield. */
1247 if (bsz == csz && (bofs & amask) == 0) {
1248 ct->info = CTINFO(CT_FIELD, ctype_cid(ct->info));
1249 ct->size = (bofs >> 3); /* Store field offset. */
1250 } else {
1251 ct->info = CTINFO(CT_BITFIELD,
1252 (info & (CTF_QUAL|CTF_UNSIGNED|CTF_BOOL)) +
1253 (csz << (CTSHIFT_BITCSZ-3)) + (bsz << CTSHIFT_BITBSZ));
1254#if LJ_BE
1255 ct->info += ((csz - (bofs & (csz-1)) - bsz) << CTSHIFT_BITPOS);
1256#else
1257 ct->info += ((bofs & (csz-1)) << CTSHIFT_BITPOS);
1258#endif
1259 ct->size = ((bofs & ~(csz-1)) >> 3); /* Store container offset. */
1260 }
1261 }
1262
1263 /* Determine next offset or max. offset. */
1264 if ((sinfo & CTF_UNION)) {
1265 if (bsz > bmaxofs) bmaxofs = bsz;
1266 } else {
1267 bofs += bsz;
1268 }
1269 } /* All other fields in the chain are already set up. */
1270
1271 fieldid = ct->sib;
1272 }
1273
1274 /* Complete struct/union. */
1275 sct->info = sinfo + CTALIGN(maxalign);
1276 bofs = (sinfo & CTF_UNION) ? bmaxofs : bofs;
1277 maxalign = (8u << maxalign) - 1;
1278 sct->size = (((bofs + maxalign) & ~maxalign) >> 3);
1279}
1280
1281/* Parse struct/union declaration. */
1282static CTypeID cp_decl_struct(CPState *cp, CPDecl *sdecl, CTInfo sinfo)
1283{
1284 CTypeID sid = cp_struct_name(cp, sdecl, sinfo);
1285 if (cp_opt(cp, '{')) { /* Struct/union definition. */
1286 CTypeID lastid = sid;
1287 int lastdecl = 0;
1288 while (cp->tok != '}') {
1289 CPDecl decl;
1290 CPscl scl = cp_decl_spec(cp, &decl, CDF_STATIC);
1291 decl.mode = scl ? CPARSE_MODE_DIRECT :
1292 CPARSE_MODE_DIRECT|CPARSE_MODE_ABSTRACT|CPARSE_MODE_FIELD;
1293
1294 for (;;) {
1295 CType *fct;
1296 CTypeID typeid;
1297
1298 if (lastdecl) cp_err_token(cp, '}');
1299
1300 /* Parse field declarator. */
1301 decl.bits = CTSIZE_INVALID;
1302 cp_declarator(cp, &decl);
1303 typeid = cp_decl_intern(cp, &decl);
1304 fct = ctype_raw(cp->cts, typeid);
1305
1306 if ((scl & CDF_STATIC)) { /* Static constant in struct namespace. */
1307 CType *ct;
1308 CTypeID fieldid = cp_decl_constinit(cp, &ct, typeid);
1309 ctype_get(cp->cts, lastid)->sib = fieldid;
1310 lastid = fieldid;
1311 ctype_setname(ct, decl.name);
1312 } else {
1313 CTSize bsz = CTBSZ_FIELD; /* Temp. for layout phase. */
1314 CType *ct;
1315 CTypeID fieldid = lj_ctype_new(cp->cts, &ct); /* Do this first. */
1316 CType *tct = ctype_raw(cp->cts, typeid);
1317
1318 if (decl.bits == CTSIZE_INVALID) { /* Regular field. */
1319 if (ctype_isarray(tct->info) && tct->size == CTSIZE_INVALID)
1320 lastdecl = 1; /* a[] or a[?] must be the last declared field. */
1321
1322 /* Accept transparent struct/union/enum. */
1323 if (!decl.name) {
1324 if (!((ctype_isstruct(tct->info) && !(tct->info & CTF_VLA)) ||
1325 ctype_isenum(tct->info)))
1326 cp_err_token(cp, CTOK_IDENT);
1327 ct->info = CTINFO(CT_ATTRIB, CTATTRIB(CTA_SUBTYPE) + typeid);
1328 ct->size = ctype_isstruct(tct->info) ?
1329 (decl.attr|0x80000000u) : 0; /* For layout phase. */
1330 goto add_field;
1331 }
1332 } else { /* Bitfield. */
1333 bsz = decl.bits;
1334 if (!ctype_isinteger_or_bool(tct->info) ||
1335 (bsz == 0 && decl.name) || 8*tct->size > CTBSZ_MAX ||
1336 bsz > ((tct->info & CTF_BOOL) ? 1 : 8*tct->size))
1337 cp_errmsg(cp, ':', LJ_ERR_BADVAL);
1338 }
1339
1340 /* Create temporary field for layout phase. */
1341 ct->info = CTINFO(CT_FIELD, typeid + (bsz << CTSHIFT_BITCSZ));
1342 ct->size = decl.attr;
1343 if (decl.name) ctype_setname(ct, decl.name);
1344
1345 add_field:
1346 ctype_get(cp->cts, lastid)->sib = fieldid;
1347 lastid = fieldid;
1348 }
1349 if (!cp_opt(cp, ',')) break;
1350 cp_decl_reset(&decl);
1351 }
1352 cp_check(cp, ';');
1353 }
1354 cp_check(cp, '}');
1355 ctype_get(cp->cts, lastid)->sib = 0; /* Drop sib = 1 for empty structs. */
1356 cp_decl_attributes(cp, sdecl); /* Layout phase needs postfix attributes. */
1357 cp_struct_layout(cp, sid, sdecl->attr);
1358 }
1359 return sid;
1360}
1361
1362/* Parse enum declaration. */
1363static CTypeID cp_decl_enum(CPState *cp, CPDecl *sdecl)
1364{
1365 CTypeID eid = cp_struct_name(cp, sdecl, CTINFO(CT_ENUM, CTID_VOID));
1366 CTInfo einfo = CTINFO(CT_ENUM, CTALIGN(2) + CTID_UINT32);
1367 CTSize esize = 4; /* Only 32 bit enums are supported. */
1368 if (cp_opt(cp, '{')) { /* Enum definition. */
1369 CPValue k;
1370 CTypeID lastid = eid;
1371 k.u32 = 0;
1372 k.id = CTID_INT32;
1373 do {
1374 GCstr *name = cp->str;
1375 if (cp->tok != CTOK_IDENT) cp_err_token(cp, CTOK_IDENT);
1376 if (cp->val.id) cp_errmsg(cp, 0, LJ_ERR_FFI_REDEF, strdata(name));
1377 cp_next(cp);
1378 if (cp_opt(cp, '=')) {
1379 cp_expr_kint(cp, &k);
1380 if (k.id == CTID_UINT32) {
1381 /* C99 says that enum constants are always (signed) integers.
1382 ** But since unsigned constants like 0x80000000 are quite common,
1383 ** those are left as uint32_t.
1384 */
1385 if (k.i32 >= 0) k.id = CTID_INT32;
1386 } else {
1387 /* OTOH it's common practice and even mandated by some ABIs
1388 ** that the enum type itself is unsigned, unless there are any
1389 ** negative constants.
1390 */
1391 k.id = CTID_INT32;
1392 if (k.i32 < 0) einfo = CTINFO(CT_ENUM, CTALIGN(2) + CTID_INT32);
1393 }
1394 }
1395 /* Add named enum constant. */
1396 {
1397 CType *ct;
1398 CTypeID constid = lj_ctype_new(cp->cts, &ct);
1399 ctype_get(cp->cts, lastid)->sib = constid;
1400 lastid = constid;
1401 ctype_setname(ct, name);
1402 ct->info = CTINFO(CT_CONSTVAL, CTF_CONST|k.id);
1403 ct->size = k.u32++;
1404 if (k.u32 == 0x80000000u) k.id = CTID_UINT32;
1405 lj_ctype_addname(cp->cts, ct, constid);
1406 }
1407 if (!cp_opt(cp, ',')) break;
1408 } while (cp->tok != '}'); /* Trailing ',' is ok. */
1409 cp_check(cp, '}');
1410 /* Complete enum. */
1411 ctype_get(cp->cts, eid)->info = einfo;
1412 ctype_get(cp->cts, eid)->size = esize;
1413 }
1414 return eid;
1415}
1416
1417/* Parse declaration specifiers. */
1418static CPscl cp_decl_spec(CPState *cp, CPDecl *decl, CPscl scl)
1419{
1420 uint32_t cds = 0, sz = 0;
1421 CTInfo tdef = 0;
1422
1423 decl->cp = cp;
1424 decl->mode = cp->mode;
1425 decl->name = NULL;
1426 decl->attr = 0;
1427 decl->fattr = 0;
1428 decl->pos = decl->top = 0;
1429 decl->stack[0].next = 0;
1430
1431 for (;;) { /* Parse basic types. */
1432 cp_decl_attributes(cp, decl);
1433 switch (cp->tok) {
1434 case CTOK_STRUCT:
1435 tdef = cp_decl_struct(cp, decl, CTINFO(CT_STRUCT, 0));
1436 break;
1437 case CTOK_UNION:
1438 tdef = cp_decl_struct(cp, decl, CTINFO(CT_STRUCT, CTF_UNION));
1439 break;
1440 case CTOK_ENUM:
1441 tdef = cp_decl_enum(cp, decl);
1442 break;
1443 case CTOK_IDENT:
1444 if (!ctype_istypedef(cp->ct->info) || sz || tdef ||
1445 (cds & (CDF_SHORT|CDF_LONG|CDF_SIGNED|CDF_UNSIGNED|CDF_COMPLEX)))
1446 goto end_decl;
1447 tdef = ctype_cid(cp->ct->info); /* Get typedef. */
1448 cp_next(cp);
1449 break;
1450 default:
1451 if (cp->tok >= CTOK_FIRSTDECL && cp->tok <= CTOK_LASTDECLFLAG) {
1452 uint32_t cbit;
1453 if (cp->ct->size) {
1454 if (sz) goto end_decl;
1455 sz = cp->ct->size;
1456 }
1457 cbit = (1u << (cp->tok - CTOK_FIRSTDECL));
1458 cds = cds | cbit | ((cbit & cds & CDF_LONG) << 1);
1459 if (cp->tok >= CTOK_FIRSTSCL && !(scl & cbit))
1460 cp_errmsg(cp, cp->tok, LJ_ERR_FFI_BADSCL);
1461 cp_next(cp);
1462 break;
1463 }
1464 goto end_decl;
1465 }
1466 }
1467end_decl:
1468
1469 if ((cds & CDF_COMPLEX)) /* Use predefined complex types. */
1470 tdef = sz == 4 ? CTID_COMPLEX_FLOAT : CTID_COMPLEX_DOUBLE;
1471
1472 if (tdef) {
1473 cp_push_type(decl, tdef);
1474 } else if ((cds & CDF_VOID)) {
1475 cp_push(decl, CTINFO(CT_VOID, (decl->attr & CTF_QUAL)), CTSIZE_INVALID);
1476 decl->attr &= ~CTF_QUAL;
1477 } else {
1478 /* Determine type info and size. */
1479 CTInfo info = CTINFO(CT_NUM, (cds & CDF_UNSIGNED) ? CTF_UNSIGNED : 0);
1480 if ((cds & CDF_BOOL)) {
1481 info = CTINFO(CT_NUM, CTF_UNSIGNED|CTF_BOOL);
1482 lua_assert(sz == 1);
1483 } else if ((cds & CDF_FP)) {
1484 info = CTINFO(CT_NUM, CTF_FP);
1485 if ((cds & CDF_LONG)) sz = sizeof(long double);
1486 } else if ((cds & CDF_CHAR)) {
1487 if ((cds & (CDF_CHAR|CDF_SIGNED|CDF_UNSIGNED)) == CDF_CHAR)
1488 info |= CTF_UCHAR; /* Handle platforms where char is unsigned. */
1489 } else if ((cds & CDF_SHORT)) {
1490 sz = sizeof(short);
1491 } else if ((cds & CDF_LONGLONG)) {
1492 sz = 8;
1493 } else if ((cds & CDF_LONG)) {
1494 info |= CTF_LONG;
1495 sz = sizeof(long);
1496 } else if (!sz) {
1497 if (!(cds & (CDF_SIGNED|CDF_UNSIGNED)))
1498 cp_errmsg(cp, cp->tok, LJ_ERR_FFI_DECLSPEC);
1499 sz = sizeof(int);
1500 }
1501 lua_assert(sz != 0);
1502 info += CTALIGN(lj_fls(sz)); /* Use natural alignment. */
1503 info += (decl->attr & CTF_QUAL); /* Merge qualifiers. */
1504 cp_push(decl, info, sz);
1505 decl->attr &= ~CTF_QUAL;
1506 }
1507 decl->specpos = decl->pos;
1508 decl->specattr = decl->attr;
1509 decl->specfattr = decl->fattr;
1510 return (cds & CDF_SCL); /* Return storage class. */
1511}
1512
1513/* Parse array declaration. */
1514static void cp_decl_array(CPState *cp, CPDecl *decl)
1515{
1516 CTInfo info = CTINFO(CT_ARRAY, 0);
1517 CTSize nelem = CTSIZE_INVALID; /* Default size for a[] or a[?]. */
1518 cp_decl_attributes(cp, decl);
1519 if (cp_opt(cp, '?'))
1520 info |= CTF_VLA; /* Create variable-length array a[?]. */
1521 else if (cp->tok != ']')
1522 nelem = cp_expr_ksize(cp);
1523 cp_check(cp, ']');
1524 cp_add(decl, info, nelem);
1525}
1526
1527/* Parse function declaration. */
1528static void cp_decl_func(CPState *cp, CPDecl *fdecl)
1529{
1530 CTSize nargs = 0;
1531 CTInfo info = CTINFO(CT_FUNC, 0);
1532 CTypeID lastid = 0, anchor = 0;
1533 if (cp->tok != ')') {
1534 do {
1535 CPDecl decl;
1536 CTypeID typeid, fieldid;
1537 CType *ct;
1538 if (cp_opt(cp, '.')) { /* Vararg function. */
1539 cp_check(cp, '.'); /* Workaround for the minimalistic lexer. */
1540 cp_check(cp, '.');
1541 info |= CTF_VARARG;
1542 break;
1543 }
1544 cp_decl_spec(cp, &decl, CDF_REGISTER);
1545 decl.mode = CPARSE_MODE_DIRECT|CPARSE_MODE_ABSTRACT;
1546 cp_declarator(cp, &decl);
1547 typeid = cp_decl_intern(cp, &decl);
1548 ct = ctype_raw(cp->cts, typeid);
1549 if (ctype_isvoid(ct->info))
1550 break;
1551 else if (ctype_isrefarray(ct->info))
1552 typeid = lj_ctype_intern(cp->cts,
1553 CTINFO(CT_PTR, CTALIGN_PTR|ctype_cid(ct->info)), CTSIZE_PTR);
1554 else if (ctype_isfunc(ct->info))
1555 typeid = lj_ctype_intern(cp->cts,
1556 CTINFO(CT_PTR, CTALIGN_PTR|typeid), CTSIZE_PTR);
1557 /* Add new parameter. */
1558 fieldid = lj_ctype_new(cp->cts, &ct);
1559 if (anchor)
1560 ctype_get(cp->cts, lastid)->sib = fieldid;
1561 else
1562 anchor = fieldid;
1563 lastid = fieldid;
1564 if (decl.name) ctype_setname(ct, decl.name);
1565 ct->info = CTINFO(CT_FIELD, typeid);
1566 ct->size = nargs++;
1567 } while (cp_opt(cp, ','));
1568 }
1569 cp_check(cp, ')');
1570 if (cp_opt(cp, '{')) { /* Skip function definition. */
1571 int level = 1;
1572 for (;;) {
1573 if (cp->tok == '{') level++;
1574 else if (cp->tok == '}' && --level == 0) break;
1575 else if (cp->tok == CTOK_EOF) cp_err_token(cp, '}');
1576 cp_next(cp);
1577 }
1578 cp->tok = ';'; /* Ok for cp_decl_multi(), error in cp_decl_single(). */
1579 }
1580 cp_add(fdecl, info | (fdecl->fattr & ~CTMASK_CID), nargs);
1581 fdecl->fattr = 0;
1582}
1583
1584/* Parse declarator. */
1585static void cp_declarator(CPState *cp, CPDecl *decl)
1586{
1587 if (++cp->depth > CPARSE_MAX_DECLDEPTH) cp_err(cp, LJ_ERR_XLEVELS);
1588
1589 for (;;) { /* Head of declarator. */
1590 if (cp_opt(cp, '*')) { /* Pointer. */
1591 CTSize sz;
1592 CTInfo info;
1593 cp_decl_attributes(cp, decl);
1594 sz = CTSIZE_PTR;
1595 info = CTINFO(CT_PTR, CTALIGN_PTR);
1596#if LJ_64
1597 if (ctype_msizeP(decl->attr) == 4) {
1598 sz = 4;
1599 info = CTINFO(CT_PTR, CTALIGN(2));
1600 }
1601#endif
1602 info += (decl->attr & (CTF_QUAL|CTF_REF));
1603 decl->attr &= ~(CTF_QUAL|(CTMASK_MSIZEP<<CTSHIFT_MSIZEP));
1604 cp_push(decl, info, sz);
1605 } else if (cp_opt(cp, '&') || cp_opt(cp, CTOK_ANDAND)) { /* Reference. */
1606 decl->attr &= ~(CTF_QUAL|(CTMASK_MSIZEP<<CTSHIFT_MSIZEP));
1607 cp_push(decl, CTINFO_REF(0), CTSIZE_PTR);
1608 } else {
1609 break;
1610 }
1611 }
1612
1613 if (cp_opt(cp, '(')) { /* Inner declarator. */
1614 CPDeclIdx pos;
1615 cp_decl_attributes(cp, decl);
1616 /* Resolve ambiguity between inner declarator and 1st function parameter. */
1617 if ((decl->mode & CPARSE_MODE_ABSTRACT) &&
1618 (cp->tok == ')' || cp_istypedecl(cp))) goto func_decl;
1619 pos = decl->pos;
1620 cp_declarator(cp, decl);
1621 cp_check(cp, ')');
1622 decl->pos = pos;
1623 } else if (cp->tok == CTOK_IDENT) { /* Direct declarator. */
1624 if (!(decl->mode & CPARSE_MODE_DIRECT)) cp_err_token(cp, CTOK_EOF);
1625 decl->name = cp->str;
1626 decl->nameid = cp->val.id;
1627 cp_next(cp);
1628 } else { /* Abstract declarator. */
1629 if (!(decl->mode & CPARSE_MODE_ABSTRACT)) cp_err_token(cp, CTOK_IDENT);
1630 }
1631
1632 for (;;) { /* Tail of declarator. */
1633 if (cp_opt(cp, '[')) { /* Array. */
1634 cp_decl_array(cp, decl);
1635 } else if (cp_opt(cp, '(')) { /* Function. */
1636 func_decl:
1637 cp_decl_func(cp, decl);
1638 } else {
1639 break;
1640 }
1641 }
1642
1643 if ((decl->mode & CPARSE_MODE_FIELD) && cp_opt(cp, ':')) /* Field width. */
1644 decl->bits = cp_expr_ksize(cp);
1645
1646 /* Process postfix attributes. */
1647 cp_decl_attributes(cp, decl);
1648 cp_push_attributes(decl);
1649
1650 cp->depth--;
1651}
1652
1653/* Parse an abstract type declaration and return it's C type ID. */
1654static CTypeID cp_decl_abstract(CPState *cp)
1655{
1656 CPDecl decl;
1657 cp_decl_spec(cp, &decl, 0);
1658 decl.mode = CPARSE_MODE_ABSTRACT;
1659 cp_declarator(cp, &decl);
1660 return cp_decl_intern(cp, &decl);
1661}
1662
1663/* Handle pragmas. */
1664static void cp_pragma(CPState *cp, BCLine pragmaline)
1665{
1666 cp_next(cp);
1667 if (cp->tok == CTOK_IDENT &&
1668 cp->str->hash == H_(e79b999f,42ca3e85)) { /* pack */
1669 cp_next(cp);
1670 cp_check(cp, '(');
1671 if (cp->tok == CTOK_IDENT) {
1672 if (cp->str->hash == H_(738e923c,a1b65954)) { /* push */
1673 if (cp->curpack < CPARSE_MAX_PACKSTACK) {
1674 cp->packstack[cp->curpack+1] = cp->packstack[cp->curpack];
1675 cp->curpack++;
1676 }
1677 } else if (cp->str->hash == H_(6c71cf27,6c71cf27)) { /* pop */
1678 if (cp->curpack > 0) cp->curpack--;
1679 } else {
1680 cp_errmsg(cp, cp->tok, LJ_ERR_XSYMBOL);
1681 }
1682 cp_next(cp);
1683 if (!cp_opt(cp, ',')) goto end_pack;
1684 }
1685 if (cp->tok == CTOK_INTEGER) {
1686 cp->packstack[cp->curpack] = cp->val.u32 ? lj_fls(cp->val.u32) : 0;
1687 cp_next(cp);
1688 } else {
1689 cp->packstack[cp->curpack] = 255;
1690 }
1691 end_pack:
1692 cp_check(cp, ')');
1693 } else { /* Ignore all other pragmas. */
1694 while (cp->tok != CTOK_EOF && cp->linenumber == pragmaline)
1695 cp_next(cp);
1696 }
1697}
1698
1699/* Parse multiple C declarations of types or extern identifiers. */
1700static void cp_decl_multi(CPState *cp)
1701{
1702 int first = 1;
1703 while (cp->tok != CTOK_EOF) {
1704 CPDecl decl;
1705 CPscl scl;
1706 if (cp->tok == '#') { /* Workaround, since we have no preprocessor, yet. */
1707 BCLine pragmaline = cp->linenumber;
1708 if (!(cp_next(cp) == CTOK_IDENT &&
1709 cp->str->hash == H_(f5e6b4f8,1d509107))) /* pragma */
1710 cp_errmsg(cp, cp->tok, LJ_ERR_XSYMBOL);
1711 cp_pragma(cp, pragmaline);
1712 continue;
1713 }
1714 scl = cp_decl_spec(cp, &decl, CDF_TYPEDEF|CDF_EXTERN|CDF_STATIC);
1715 if ((cp->tok == ';' || cp->tok == CTOK_EOF) &&
1716 ctype_istypedef(decl.stack[0].info)) {
1717 CTInfo info = ctype_rawchild(cp->cts, &decl.stack[0])->info;
1718 if (ctype_isstruct(info) || ctype_isenum(info))
1719 goto decl_end; /* Accept empty declaration of struct/union/enum. */
1720 }
1721 for (;;) {
1722 CTypeID typeid;
1723 cp_declarator(cp, &decl);
1724 typeid = cp_decl_intern(cp, &decl);
1725 if (decl.name && !decl.nameid) { /* NYI: redeclarations are ignored. */
1726 if ((scl & CDF_TYPEDEF)) { /* Create new typedef. */
1727 CType *ct;
1728 CTypeID tdefid = lj_ctype_new(cp->cts, &ct);
1729 ct->info = CTINFO(CT_TYPEDEF, typeid);
1730 ctype_setname(ct, decl.name);
1731 lj_ctype_addname(cp->cts, ct, tdefid);
1732 } else if (ctype_isfunc(ctype_get(cp->cts, typeid)->info)) {
1733 /* Treat both static and extern function declarations as extern. */
1734 CType *ct = ctype_get(cp->cts, typeid);
1735 /* We always get new anonymous functions (typedefs are copied). */
1736 lua_assert(gcref(ct->name) == NULL);
1737 ctype_setname(ct, decl.name); /* Just name it. */
1738 lj_ctype_addname(cp->cts, ct, typeid);
1739 } else if ((scl & CDF_STATIC)) { /* Accept static constants. */
1740 CType *ct;
1741 CTypeID constid = cp_decl_constinit(cp, &ct, typeid);
1742 ctype_setname(ct, decl.name);
1743 lj_ctype_addname(cp->cts, ct, constid);
1744 } else { /* External references have extern or no storage class. */
1745 CType *ct;
1746 CTypeID extid = lj_ctype_new(cp->cts, &ct);
1747 ct->info = CTINFO(CT_EXTERN, typeid);
1748 ctype_setname(ct, decl.name);
1749 lj_ctype_addname(cp->cts, ct, extid);
1750 }
1751 }
1752 if (!cp_opt(cp, ',')) break;
1753 cp_decl_reset(&decl);
1754 }
1755 decl_end:
1756 if (cp->tok == CTOK_EOF && first) break; /* May omit ';' for 1 decl. */
1757 first = 0;
1758 cp_check(cp, ';');
1759 }
1760}
1761
1762/* Parse a single C type declaration. */
1763static void cp_decl_single(CPState *cp)
1764{
1765 CPDecl decl;
1766 cp_decl_spec(cp, &decl, 0);
1767 cp_declarator(cp, &decl);
1768 cp->val.id = cp_decl_intern(cp, &decl);
1769 if (cp->tok != CTOK_EOF) cp_err_token(cp, CTOK_EOF);
1770}
1771
1772#undef H_
1773
1774/* ------------------------------------------------------------------------ */
1775
1776/* Protected callback for C parser. */
1777static TValue *cpcparser(lua_State *L, lua_CFunction dummy, void *ud)
1778{
1779 CPState *cp = cast(CPState *, ud);
1780 UNUSED(dummy);
1781 cframe_errfunc(L->cframe) = -1; /* Inherit error function. */
1782 cp_init(cp);
1783 if ((cp->mode & CPARSE_MODE_MULTI))
1784 cp_decl_multi(cp);
1785 else
1786 cp_decl_single(cp);
1787 lua_assert(cp->depth == 0);
1788 return NULL;
1789}
1790
1791/* C parser. */
1792int lj_cparse(CPState *cp)
1793{
1794 LJ_CTYPE_SAVE(cp->cts);
1795 int errcode = lj_vm_cpcall(cp->L, NULL, cp, cpcparser);
1796 if (errcode)
1797 LJ_CTYPE_RESTORE(cp->cts);
1798 cp_cleanup(cp);
1799 return errcode;
1800}
1801
1802#endif
diff --git a/src/lj_cparse.h b/src/lj_cparse.h
new file mode 100644
index 00000000..2d2f4684
--- /dev/null
+++ b/src/lj_cparse.h
@@ -0,0 +1,63 @@
1/*
2** C declaration parser.
3** Copyright (C) 2005-2010 Mike Pall. See Copyright Notice in luajit.h
4*/
5
6#ifndef _LJ_CPARSE_H
7#define _LJ_CPARSE_H
8
9#include "lj_obj.h"
10#include "lj_ctype.h"
11
12#if LJ_HASFFI
13
14/* C parser limits. */
15#define CPARSE_MAX_BUF 32768 /* Max. token buffer size. */
16#define CPARSE_MAX_DECLSTACK 100 /* Max. declaration stack depth. */
17#define CPARSE_MAX_DECLDEPTH 20 /* Max. recursive declaration depth. */
18#define CPARSE_MAX_PACKSTACK 7 /* Max. pack pragma stack depth. */
19
20/* Flags for C parser mode. */
21#define CPARSE_MODE_MULTI 1 /* Process multiple declarations. */
22#define CPARSE_MODE_ABSTRACT 2 /* Accept abstract declarators. */
23#define CPARSE_MODE_DIRECT 4 /* Accept direct declarators. */
24#define CPARSE_MODE_FIELD 8 /* Accept field width in bits, too. */
25#define CPARSE_MODE_NOIMPLICIT 16 /* Reject implicit declarations. */
26
27typedef int CPChar; /* C parser character. Unsigned ext. from char. */
28typedef int CPToken; /* C parser token. */
29
30/* C parser internal value representation. */
31typedef struct CPValue {
32 union {
33 int32_t i32; /* Value for CTID_INT32. */
34 uint32_t u32; /* Value for CTID_UINT32. */
35 };
36 CTypeID id; /* C Type ID of the value. */
37} CPValue;
38
39/* C parser state. */
40typedef struct CPState {
41 CPChar c; /* Current character. */
42 CPToken tok; /* Current token. */
43 CPValue val; /* Token value. */
44 GCstr *str; /* Interned string of identifier/keyword. */
45 CType *ct; /* C type table entry. */
46 const char *p; /* Current position in input buffer. */
47 SBuf sb; /* String buffer for tokens. */
48 lua_State *L; /* Lua state. */
49 CTState *cts; /* C type state. */
50 const char *srcname; /* Current source name. */
51 BCLine linenumber; /* Input line counter. */
52 int depth; /* Recursive declaration depth. */
53 uint32_t tmask; /* Type mask for next identifier. */
54 uint32_t mode; /* C parser mode. */
55 uint8_t packstack[CPARSE_MAX_PACKSTACK]; /* Stack for pack pragmas. */
56 uint8_t curpack; /* Current position in pack pragma stack. */
57} CPState;
58
59LJ_FUNC int lj_cparse(CPState *cp);
60
61#endif
62
63#endif
diff --git a/src/ljamalg.c b/src/ljamalg.c
index dac09561..9681d759 100644
--- a/src/ljamalg.c
+++ b/src/ljamalg.c
@@ -43,6 +43,7 @@
43#include "lj_ctype.c" 43#include "lj_ctype.c"
44#include "lj_cdata.c" 44#include "lj_cdata.c"
45#include "lj_cconv.c" 45#include "lj_cconv.c"
46#include "lj_cparse.c"
46#include "lj_lib.c" 47#include "lj_lib.c"
47#include "lj_ir.c" 48#include "lj_ir.c"
48#include "lj_opt_mem.c" 49#include "lj_opt_mem.c"