2 ** LuaJIT VM builder: library definition compiler.
3 ** Copyright (C) 2005-2009 Mike Pall. See Copyright Notice in luajit.h
11 /* Context for library definitions. */
12 static uint8_t obuf
[8192];
14 static char modname
[80];
15 static size_t modnamelen
;
16 static char funcname
[80];
17 static int modstate
, regfunc
;
18 static int ffid
, recffid
;
26 static void libdef_name(char *p
, int kind
)
29 if (kind
!= LIBINIT_STRING
) {
30 if (n
> modnamelen
&& p
[modnamelen
] == '_' &&
31 !strncmp(p
, modname
, modnamelen
)) {
36 if (n
> LIBINIT_MAXSTR
) {
37 fprintf(stderr
, "Error: string too long: '%s'\n", p
);
40 if (optr
+1+n
+2 > obuf
+sizeof(obuf
)) { /* +2 for caller. */
41 fprintf(stderr
, "Error: output buffer overflow\n");
44 *optr
++ = (uint8_t)(n
| kind
);
49 static void libdef_endmodule(BuildCtx
*ctx
)
56 fprintf(ctx
->fp
, " (lua_CFunction)0");
57 fprintf(ctx
->fp
, "\n};\n");
58 fprintf(ctx
->fp
, "static const uint8_t %s%s[] = {\n",
59 LABEL_PREFIX_LIBINIT
, modname
);
61 for (n
= 0, p
= obuf
; p
< optr
; p
++) {
62 n
+= sprintf(line
+n
, "%d,", *p
);
64 fprintf(ctx
->fp
, "%s\n", line
);
69 fprintf(ctx
->fp
, "%s%d\n};\n#endif\n\n", line
, LIBINIT_END
);
73 static void libdef_module(BuildCtx
*ctx
, char *p
, int arg
)
76 if (ctx
->mode
== BUILD_libdef
) {
77 libdef_endmodule(ctx
);
79 *optr
++ = (uint8_t)ffid
;
82 fprintf(ctx
->fp
, "#ifdef %sMODULE_%s\n", LIBDEF_PREFIX
, p
);
83 fprintf(ctx
->fp
, "#undef %sMODULE_%s\n", LIBDEF_PREFIX
, p
);
84 fprintf(ctx
->fp
, "static const lua_CFunction %s%s[] = {\n",
85 LABEL_PREFIX_LIBCF
, p
);
87 modnamelen
= strlen(p
);
88 if (modnamelen
> sizeof(modname
)-1) {
89 fprintf(stderr
, "Error: module name too long: '%s'\n", p
);
95 static int find_ffofs(BuildCtx
*ctx
, const char *name
)
98 for (i
= 0; i
< ctx
->nglob
; i
++) {
99 const char *gl
= ctx
->globnames
[i
];
100 if (gl
[0] == 'f' && gl
[1] == 'f' && gl
[2] == '_' && !strcmp(gl
+3, name
)) {
101 return (int)((uint8_t *)ctx
->glob
[i
] - ctx
->code
);
104 fprintf(stderr
, "Error: undefined fast function %s%s\n",
105 LABEL_PREFIX_FF
, name
);
109 static void libdef_func(BuildCtx
*ctx
, char *p
, int arg
)
111 if (ctx
->mode
== BUILD_libdef
) {
112 int ofs
= arg
!= LIBINIT_CF
? find_ffofs(ctx
, p
) : 0;
114 fprintf(stderr
, "Error: no module for function definition %s\n", p
);
117 if (regfunc
== REGFUNC_NOREG
) {
118 if (optr
+1 > obuf
+sizeof(obuf
)) {
119 fprintf(stderr
, "Error: output buffer overflow\n");
122 *optr
++ = LIBINIT_FFID
;
124 if (arg
!= LIBINIT_ASM_
) {
125 if (modstate
!= 1) fprintf(ctx
->fp
, ",\n");
127 fprintf(ctx
->fp
, " %s%s", arg
? LABEL_PREFIX_FFH
: LABEL_PREFIX_CF
, p
);
129 if (regfunc
!= REGFUNC_NOREGUV
) obuf
[1]++; /* Bump hash table size. */
130 libdef_name(regfunc
== REGFUNC_NOREGUV
? "" : p
, arg
);
132 *optr
++ = (uint8_t)ofs
;
133 *optr
++ = (uint8_t)(ofs
>> 8);
136 } else if (ctx
->mode
== BUILD_ffdef
) {
137 fprintf(ctx
->fp
, "FFDEF(%s)\n", p
);
138 } else if (ctx
->mode
== BUILD_recdef
) {
139 if (strlen(p
) > sizeof(funcname
)-1) {
140 fprintf(stderr
, "Error: function name too long: '%s'\n", p
);
144 } else if (ctx
->mode
== BUILD_vmdef
) {
146 for (i
= 1; p
[i
] && modname
[i
-1]; i
++)
147 if (p
[i
] == '_') p
[i
] = '.';
148 fprintf(ctx
->fp
, "\"%s\",\n", p
);
151 regfunc
= REGFUNC_OK
;
154 static uint32_t find_rec(char *name
)
156 char *p
= (char *)obuf
;
158 for (n
= 2; *p
; n
++) {
159 if (strcmp(p
, name
) == 0)
163 if (p
+strlen(name
)+1 >= (char *)obuf
+sizeof(obuf
)) {
164 fprintf(stderr
, "Error: output buffer overflow\n");
171 static void libdef_rec(BuildCtx
*ctx
, char *p
, int arg
)
174 if (ctx
->mode
== BUILD_recdef
) {
177 for (; recffid
+1 < ffid
; recffid
++)
178 fprintf(ctx
->fp
, ",\n0");
180 if (*p
== '.') p
= funcname
;
185 fprintf(ctx
->fp
, ",\n0x%02x00+(%s)", n
, q
);
187 fprintf(ctx
->fp
, ",\n0x%02x00", n
);
191 static void memcpy_endian(void *dst
, void *src
, size_t n
)
193 union { uint8_t b
; uint32_t u
; } host_endian
;
195 if (host_endian
.b
== LJ_ENDIAN_SELECT(1, 0)) {
199 for (i
= 0; i
< n
; i
++)
200 ((uint8_t *)dst
)[i
] = ((uint8_t *)src
)[n
-i
];
204 static void libdef_push(BuildCtx
*ctx
, char *p
, int arg
)
207 if (ctx
->mode
== BUILD_libdef
) {
208 int len
= (int)strlen(p
);
210 if (len
> 1 && p
[len
-1] == '"') {
212 libdef_name(p
+1, LIBINIT_STRING
);
215 } else if (*p
>= '0' && *p
<= '9') {
217 double d
= strtod(p
, &ep
);
219 if (optr
+1+sizeof(double) > obuf
+sizeof(obuf
)) {
220 fprintf(stderr
, "Error: output buffer overflow\n");
223 *optr
++ = LIBINIT_NUMBER
;
224 memcpy_endian(optr
, &d
, sizeof(double));
225 optr
+= sizeof(double);
228 } else if (!strcmp(p
, "lastcl")) {
229 if (optr
+1 > obuf
+sizeof(obuf
)) {
230 fprintf(stderr
, "Error: output buffer overflow\n");
233 *optr
++ = LIBINIT_LASTCL
;
235 } else if (len
> 4 && !strncmp(p
, "top-", 4)) {
236 if (optr
+2 > obuf
+sizeof(obuf
)) {
237 fprintf(stderr
, "Error: output buffer overflow\n");
240 *optr
++ = LIBINIT_COPY
;
241 *optr
++ = (uint8_t)atoi(p
+4);
244 fprintf(stderr
, "Error: bad value for %sPUSH(%s)\n", LIBDEF_PREFIX
, p
);
249 static void libdef_set(BuildCtx
*ctx
, char *p
, int arg
)
252 if (ctx
->mode
== BUILD_libdef
) {
253 if (p
[0] == '!' && p
[1] == '\0') p
[0] = '\0'; /* Set env. */
254 libdef_name(p
, LIBINIT_STRING
);
255 *optr
++ = LIBINIT_SET
;
256 obuf
[1]++; /* Bump hash table size. */
260 static void libdef_regfunc(BuildCtx
*ctx
, char *p
, int arg
)
262 UNUSED(ctx
); UNUSED(p
);
266 typedef void (*LibDefFunc
)(BuildCtx
*ctx
, char *p
, int arg
);
268 typedef struct LibDefHandler
{
271 const LibDefFunc func
;
275 static const LibDefHandler libdef_handlers
[] = {
276 { "MODULE_", " \t\r\n", libdef_module
, 0 },
277 { "CF(", ")", libdef_func
, LIBINIT_CF
},
278 { "ASM(", ")", libdef_func
, LIBINIT_ASM
},
279 { "ASM_(", ")", libdef_func
, LIBINIT_ASM_
},
280 { "REC(", ")", libdef_rec
, 0 },
281 { "PUSH(", ")", libdef_push
, 0 },
282 { "SET(", ")", libdef_set
, 0 },
283 { "NOREGUV", NULL
, libdef_regfunc
, REGFUNC_NOREGUV
},
284 { "NOREG", NULL
, libdef_regfunc
, REGFUNC_NOREG
},
285 { NULL
, NULL
, (LibDefFunc
)0, 0 }
288 /* Emit C source code for library function definitions. */
289 void emit_lib(BuildCtx
*ctx
)
293 if (ctx
->mode
== BUILD_ffdef
|| ctx
->mode
== BUILD_libdef
||
294 ctx
->mode
== BUILD_recdef
)
295 fprintf(ctx
->fp
, "/* This is a generated file. DO NOT EDIT! */\n\n");
296 else if (ctx
->mode
== BUILD_vmdef
)
297 fprintf(ctx
->fp
, "ffnames = {\n[0]=\"Lua\",\n\"C\",\n");
298 if (ctx
->mode
== BUILD_recdef
)
299 fprintf(ctx
->fp
, "static const uint16_t recff_idmap[] = {\n0,\n0x0100");
300 recffid
= ffid
= FF_C
+1;
302 while ((fname
= *ctx
->args
++)) {
303 char buf
[256]; /* We don't care about analyzing lines longer than that. */
305 if (fname
[0] == '-' && fname
[1] == '\0') {
308 fp
= fopen(fname
, "r");
310 fprintf(stderr
, "Error: cannot open input file '%s': %s\n",
311 fname
, strerror(errno
));
316 regfunc
= REGFUNC_OK
;
317 while (fgets(buf
, sizeof(buf
), fp
) != NULL
) {
319 for (p
= buf
; (p
= strstr(p
, LIBDEF_PREFIX
)) != NULL
; ) {
320 const LibDefHandler
*ldh
;
321 p
+= sizeof(LIBDEF_PREFIX
)-1;
322 for (ldh
= libdef_handlers
; ldh
->suffix
!= NULL
; ldh
++) {
323 size_t n
, len
= strlen(ldh
->suffix
);
324 if (!strncmp(p
, ldh
->suffix
, len
)) {
326 n
= ldh
->stop
? strcspn(p
, ldh
->stop
) : 0;
329 ldh
->func(ctx
, p
, ldh
->arg
);
334 if (ldh
->suffix
== NULL
) {
335 buf
[strlen(buf
)-1] = '\0';
336 fprintf(stderr
, "Error: unknown library definition tag %s%s\n",
343 if (ctx
->mode
== BUILD_libdef
) {
344 libdef_endmodule(ctx
);
348 if (ctx
->mode
== BUILD_ffdef
) {
349 fprintf(ctx
->fp
, "\n#undef FFDEF\n\n");
350 } else if (ctx
->mode
== BUILD_vmdef
) {
351 fprintf(ctx
->fp
, "}\n\n");
352 } else if (ctx
->mode
== BUILD_recdef
) {
353 char *p
= (char *)obuf
;
354 fprintf(ctx
->fp
, "\n};\n\n");
355 fprintf(ctx
->fp
, "static const RecordFunc recff_func[] = {\n"
359 fprintf(ctx
->fp
, ",\nrecff_%s", p
);
362 fprintf(ctx
->fp
, "\n};\n\n");