2 ** LuaJIT VM builder: library definition compiler.
3 ** Copyright (C) 2005-2015 Mike Pall. See Copyright Notice in luajit.h
10 #include "buildvm_libbc.h"
12 /* Context for library definitions. */
13 static uint8_t obuf
[8192];
15 static char modname
[80];
16 static size_t modnamelen
;
17 static char funcname
[80];
18 static int modstate
, regfunc
;
19 static int ffid
, recffid
, ffasmfunc
;
27 static void libdef_name(const char *p
, int kind
)
30 if (kind
!= LIBINIT_STRING
) {
31 if (n
> modnamelen
&& p
[modnamelen
] == '_' &&
32 !strncmp(p
, modname
, modnamelen
)) {
37 if (n
> LIBINIT_MAXSTR
) {
38 fprintf(stderr
, "Error: string too long: '%s'\n", p
);
41 if (optr
+1+n
+2 > obuf
+sizeof(obuf
)) { /* +2 for caller. */
42 fprintf(stderr
, "Error: output buffer overflow\n");
45 *optr
++ = (uint8_t)(n
| kind
);
50 static void libdef_endmodule(BuildCtx
*ctx
)
57 fprintf(ctx
->fp
, " (lua_CFunction)0");
58 fprintf(ctx
->fp
, "\n};\n");
59 fprintf(ctx
->fp
, "static const uint8_t %s%s[] = {\n",
60 LABEL_PREFIX_LIBINIT
, modname
);
62 for (n
= 0, p
= obuf
; p
< optr
; p
++) {
63 n
+= sprintf(line
+n
, "%d,", *p
);
65 fprintf(ctx
->fp
, "%s\n", line
);
70 fprintf(ctx
->fp
, "%s%d\n};\n#endif\n\n", line
, LIBINIT_END
);
74 static void libdef_module(BuildCtx
*ctx
, char *p
, int arg
)
77 if (ctx
->mode
== BUILD_libdef
) {
78 libdef_endmodule(ctx
);
80 *optr
++ = (uint8_t)ffid
;
81 *optr
++ = (uint8_t)ffasmfunc
;
82 *optr
++ = 0; /* Hash table size. */
84 fprintf(ctx
->fp
, "#ifdef %sMODULE_%s\n", LIBDEF_PREFIX
, p
);
85 fprintf(ctx
->fp
, "#undef %sMODULE_%s\n", LIBDEF_PREFIX
, p
);
86 fprintf(ctx
->fp
, "static const lua_CFunction %s%s[] = {\n",
87 LABEL_PREFIX_LIBCF
, p
);
89 modnamelen
= strlen(p
);
90 if (modnamelen
> sizeof(modname
)-1) {
91 fprintf(stderr
, "Error: module name too long: '%s'\n", p
);
97 static int find_ffofs(BuildCtx
*ctx
, const char *name
)
100 for (i
= 0; i
< ctx
->nglob
; i
++) {
101 const char *gl
= ctx
->globnames
[i
];
102 if (gl
[0] == 'f' && gl
[1] == 'f' && gl
[2] == '_' && !strcmp(gl
+3, name
)) {
103 return (int)((uint8_t *)ctx
->glob
[i
] - ctx
->code
);
106 fprintf(stderr
, "Error: undefined fast function %s%s\n",
107 LABEL_PREFIX_FF
, name
);
111 static void libdef_func(BuildCtx
*ctx
, char *p
, int arg
)
113 if (arg
!= LIBINIT_CF
)
115 if (ctx
->mode
== BUILD_libdef
) {
117 fprintf(stderr
, "Error: no module for function definition %s\n", p
);
120 if (regfunc
== REGFUNC_NOREG
) {
121 if (optr
+1 > obuf
+sizeof(obuf
)) {
122 fprintf(stderr
, "Error: output buffer overflow\n");
125 *optr
++ = LIBINIT_FFID
;
127 if (arg
!= LIBINIT_ASM_
) {
128 if (modstate
!= 1) fprintf(ctx
->fp
, ",\n");
130 fprintf(ctx
->fp
, " %s%s", arg
? LABEL_PREFIX_FFH
: LABEL_PREFIX_CF
, p
);
132 if (regfunc
!= REGFUNC_NOREGUV
) obuf
[2]++; /* Bump hash table size. */
133 libdef_name(regfunc
== REGFUNC_NOREGUV
? "" : p
, arg
);
135 } else if (ctx
->mode
== BUILD_ffdef
) {
136 fprintf(ctx
->fp
, "FFDEF(%s)\n", p
);
137 } else if (ctx
->mode
== BUILD_recdef
) {
138 if (strlen(p
) > sizeof(funcname
)-1) {
139 fprintf(stderr
, "Error: function name too long: '%s'\n", p
);
143 } else if (ctx
->mode
== BUILD_vmdef
) {
145 for (i
= 1; p
[i
] && modname
[i
-1]; i
++)
146 if (p
[i
] == '_') p
[i
] = '.';
147 fprintf(ctx
->fp
, "\"%s\",\n", p
);
148 } else if (ctx
->mode
== BUILD_bcdef
) {
149 if (arg
!= LIBINIT_CF
)
150 fprintf(ctx
->fp
, ",\n%d", find_ffofs(ctx
, p
));
153 regfunc
= REGFUNC_OK
;
156 static uint8_t *libdef_uleb128(uint8_t *p
, uint32_t *vv
)
160 int sh
= 0; v
&= 0x7f;
161 do { v
|= ((*p
& 0x7f) << (sh
+= 7)); } while (*p
++ >= 0x80);
167 static void libdef_fixupbc(uint8_t *p
)
171 p
= libdef_uleb128(p
, &sizebc
);
172 p
= libdef_uleb128(p
, &sizebc
);
173 p
= libdef_uleb128(p
, &sizebc
);
174 for (i
= 0; i
< sizebc
; i
++, p
+= 4) {
175 uint8_t op
= p
[libbc_endian
? 3 : 0];
176 uint8_t ra
= p
[libbc_endian
? 2 : 1];
177 uint8_t rc
= p
[libbc_endian
? 1 : 2];
178 uint8_t rb
= p
[libbc_endian
? 0 : 3];
179 if (!LJ_DUALNUM
&& op
== BC_ISTYPE
&& rc
== ~LJ_TNUMX
+1) {
182 p
[LJ_ENDIAN_SELECT(0, 3)] = op
;
183 p
[LJ_ENDIAN_SELECT(1, 2)] = ra
;
184 p
[LJ_ENDIAN_SELECT(2, 1)] = rc
;
185 p
[LJ_ENDIAN_SELECT(3, 0)] = rb
;
189 static void libdef_lua(BuildCtx
*ctx
, char *p
, int arg
)
192 if (ctx
->mode
== BUILD_libdef
) {
194 for (i
= 0; libbc_map
[i
].name
!= NULL
; i
++) {
195 if (!strcmp(libbc_map
[i
].name
, p
)) {
196 int ofs
= libbc_map
[i
].ofs
;
197 int len
= libbc_map
[i
+1].ofs
- ofs
;
198 obuf
[2]++; /* Bump hash table size. */
199 *optr
++ = LIBINIT_LUA
;
201 memcpy(optr
, libbc_code
+ ofs
, len
);
202 libdef_fixupbc(optr
);
207 fprintf(stderr
, "Error: missing libbc definition for %s\n", p
);
212 static uint32_t find_rec(char *name
)
214 char *p
= (char *)obuf
;
216 for (n
= 2; *p
; n
++) {
217 if (strcmp(p
, name
) == 0)
221 if (p
+strlen(name
)+1 >= (char *)obuf
+sizeof(obuf
)) {
222 fprintf(stderr
, "Error: output buffer overflow\n");
229 static void libdef_rec(BuildCtx
*ctx
, char *p
, int arg
)
232 if (ctx
->mode
== BUILD_recdef
) {
235 for (; recffid
+1 < ffid
; recffid
++)
236 fprintf(ctx
->fp
, ",\n0");
238 if (*p
== '.') p
= funcname
;
243 fprintf(ctx
->fp
, ",\n0x%02x00+(%s)", n
, q
);
245 fprintf(ctx
->fp
, ",\n0x%02x00", n
);
249 static void memcpy_endian(void *dst
, void *src
, size_t n
)
251 union { uint8_t b
; uint32_t u
; } host_endian
;
253 if (host_endian
.b
== LJ_ENDIAN_SELECT(1, 0)) {
257 for (i
= 0; i
< n
; i
++)
258 ((uint8_t *)dst
)[i
] = ((uint8_t *)src
)[n
-i
-1];
262 static void libdef_push(BuildCtx
*ctx
, char *p
, int arg
)
265 if (ctx
->mode
== BUILD_libdef
) {
266 int len
= (int)strlen(p
);
268 if (len
> 1 && p
[len
-1] == '"') {
270 libdef_name(p
+1, LIBINIT_STRING
);
273 } else if (*p
>= '0' && *p
<= '9') {
275 double d
= strtod(p
, &ep
);
277 if (optr
+1+sizeof(double) > obuf
+sizeof(obuf
)) {
278 fprintf(stderr
, "Error: output buffer overflow\n");
281 *optr
++ = LIBINIT_NUMBER
;
282 memcpy_endian(optr
, &d
, sizeof(double));
283 optr
+= sizeof(double);
286 } else if (!strcmp(p
, "lastcl")) {
287 if (optr
+1 > obuf
+sizeof(obuf
)) {
288 fprintf(stderr
, "Error: output buffer overflow\n");
291 *optr
++ = LIBINIT_LASTCL
;
293 } else if (len
> 4 && !strncmp(p
, "top-", 4)) {
294 if (optr
+2 > obuf
+sizeof(obuf
)) {
295 fprintf(stderr
, "Error: output buffer overflow\n");
298 *optr
++ = LIBINIT_COPY
;
299 *optr
++ = (uint8_t)atoi(p
+4);
302 fprintf(stderr
, "Error: bad value for %sPUSH(%s)\n", LIBDEF_PREFIX
, p
);
307 static void libdef_set(BuildCtx
*ctx
, char *p
, int arg
)
310 if (ctx
->mode
== BUILD_libdef
) {
311 if (p
[0] == '!' && p
[1] == '\0') p
[0] = '\0'; /* Set env. */
312 libdef_name(p
, LIBINIT_STRING
);
313 *optr
++ = LIBINIT_SET
;
314 obuf
[2]++; /* Bump hash table size. */
318 static void libdef_regfunc(BuildCtx
*ctx
, char *p
, int arg
)
320 UNUSED(ctx
); UNUSED(p
);
324 typedef void (*LibDefFunc
)(BuildCtx
*ctx
, char *p
, int arg
);
326 typedef struct LibDefHandler
{
329 const LibDefFunc func
;
333 static const LibDefHandler libdef_handlers
[] = {
334 { "MODULE_", " \t\r\n", libdef_module
, 0 },
335 { "CF(", ")", libdef_func
, LIBINIT_CF
},
336 { "ASM(", ")", libdef_func
, LIBINIT_ASM
},
337 { "ASM_(", ")", libdef_func
, LIBINIT_ASM_
},
338 { "LUA(", ")", libdef_lua
, 0 },
339 { "REC(", ")", libdef_rec
, 0 },
340 { "PUSH(", ")", libdef_push
, 0 },
341 { "SET(", ")", libdef_set
, 0 },
342 { "NOREGUV", NULL
, libdef_regfunc
, REGFUNC_NOREGUV
},
343 { "NOREG", NULL
, libdef_regfunc
, REGFUNC_NOREG
},
344 { NULL
, NULL
, (LibDefFunc
)0, 0 }
347 /* Emit C source code for library function definitions. */
348 void emit_lib(BuildCtx
*ctx
)
352 if (ctx
->mode
== BUILD_ffdef
|| ctx
->mode
== BUILD_libdef
||
353 ctx
->mode
== BUILD_recdef
)
354 fprintf(ctx
->fp
, "/* This is a generated file. DO NOT EDIT! */\n\n");
355 else if (ctx
->mode
== BUILD_vmdef
)
356 fprintf(ctx
->fp
, "ffnames = {\n[0]=\"Lua\",\n\"C\",\n");
357 if (ctx
->mode
== BUILD_recdef
)
358 fprintf(ctx
->fp
, "static const uint16_t recff_idmap[] = {\n0,\n0x0100");
359 recffid
= ffid
= FF_C
+1;
362 while ((fname
= *ctx
->args
++)) {
363 char buf
[256]; /* We don't care about analyzing lines longer than that. */
365 if (fname
[0] == '-' && fname
[1] == '\0') {
368 fp
= fopen(fname
, "r");
370 fprintf(stderr
, "Error: cannot open input file '%s': %s\n",
371 fname
, strerror(errno
));
376 regfunc
= REGFUNC_OK
;
377 while (fgets(buf
, sizeof(buf
), fp
) != NULL
) {
379 /* Simplistic pre-processor. Only handles top-level #if/#endif. */
380 if (buf
[0] == '#' && buf
[1] == 'i' && buf
[2] == 'f') {
382 if (!strcmp(buf
, "#if LJ_52\n"))
384 else if (!strcmp(buf
, "#if LJ_HASJIT\n"))
386 else if (!strcmp(buf
, "#if LJ_HASFFI\n"))
390 while (fgets(buf
, sizeof(buf
), fp
) != NULL
) {
391 if (buf
[0] == '#' && buf
[1] == 'e' && buf
[2] == 'n') {
392 if (--lvl
== 0) break;
393 } else if (buf
[0] == '#' && buf
[1] == 'i' && buf
[2] == 'f') {
400 for (p
= buf
; (p
= strstr(p
, LIBDEF_PREFIX
)) != NULL
; ) {
401 const LibDefHandler
*ldh
;
402 p
+= sizeof(LIBDEF_PREFIX
)-1;
403 for (ldh
= libdef_handlers
; ldh
->suffix
!= NULL
; ldh
++) {
404 size_t n
, len
= strlen(ldh
->suffix
);
405 if (!strncmp(p
, ldh
->suffix
, len
)) {
407 n
= ldh
->stop
? strcspn(p
, ldh
->stop
) : 0;
410 ldh
->func(ctx
, p
, ldh
->arg
);
415 if (ldh
->suffix
== NULL
) {
416 buf
[strlen(buf
)-1] = '\0';
417 fprintf(stderr
, "Error: unknown library definition tag %s%s\n",
424 if (ctx
->mode
== BUILD_libdef
) {
425 libdef_endmodule(ctx
);
429 if (ctx
->mode
== BUILD_ffdef
) {
430 fprintf(ctx
->fp
, "\n#undef FFDEF\n\n");
432 "#ifndef FF_NUM_ASMFUNC\n#define FF_NUM_ASMFUNC %d\n#endif\n\n",
434 } else if (ctx
->mode
== BUILD_vmdef
) {
435 fprintf(ctx
->fp
, "},\n\n");
436 } else if (ctx
->mode
== BUILD_bcdef
) {
438 fprintf(ctx
->fp
, "\n};\n\n");
439 fprintf(ctx
->fp
, "LJ_DATADEF const uint16_t lj_bc_mode[] = {\n");
440 fprintf(ctx
->fp
, "BCDEF(BCMODE)\n");
441 for (i
= ffasmfunc
-1; i
> 0; i
--)
442 fprintf(ctx
->fp
, "BCMODE_FF,\n");
443 fprintf(ctx
->fp
, "BCMODE_FF\n};\n\n");
444 } else if (ctx
->mode
== BUILD_recdef
) {
445 char *p
= (char *)obuf
;
446 fprintf(ctx
->fp
, "\n};\n\n");
447 fprintf(ctx
->fp
, "static const RecordFunc recff_func[] = {\n"
451 fprintf(ctx
->fp
, ",\nrecff_%s", p
);
454 fprintf(ctx
->fp
, "\n};\n\n");