1 /*
2 ** LuaJIT VM builder: library definition compiler.
3 ** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
4 */
5 
6 #include "buildvm.h"
7 #include "lj_obj.h"
8 #include "lj_bc.h"
9 #include "lj_lib.h"
10 #include "buildvm_libbc.h"
11 
12 /* Context for library definitions. */
13 static uint8_t obuf[8192];
14 static uint8_t *optr;
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;
20 
21 enum {
22   REGFUNC_OK,
23   REGFUNC_NOREG,
24   REGFUNC_NOREGUV
25 };
26 
libdef_name(const char * p,int kind)27 static void libdef_name(const char *p, int kind)
28 {
29   size_t n = strlen(p);
30   if (kind != LIBINIT_STRING) {
31     if (n > modnamelen && p[modnamelen] == '_' &&
32 	!strncmp(p, modname, modnamelen)) {
33       p += modnamelen+1;
34       n -= modnamelen+1;
35     }
36   }
37   if (n > LIBINIT_MAXSTR) {
38     fprintf(stderr, "Error: string too long: '%s'\n",  p);
39     exit(1);
40   }
41   if (optr+1+n+2 > obuf+sizeof(obuf)) {  /* +2 for caller. */
42     fprintf(stderr, "Error: output buffer overflow\n");
43     exit(1);
44   }
45   *optr++ = (uint8_t)(n | kind);
46   memcpy(optr, p, n);
47   optr += n;
48 }
49 
libdef_endmodule(BuildCtx * ctx)50 static void libdef_endmodule(BuildCtx *ctx)
51 {
52   if (modstate != 0) {
53     char line[80];
54     const uint8_t *p;
55     int n;
56     if (modstate == 1)
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);
61     line[0] = '\0';
62     for (n = 0, p = obuf; p < optr; p++) {
63       n += sprintf(line+n, "%d,", *p);
64       if (n >= 75) {
65 	fprintf(ctx->fp, "%s\n", line);
66 	n = 0;
67 	line[0] = '\0';
68       }
69     }
70     fprintf(ctx->fp, "%s%d\n};\n#endif\n\n", line, LIBINIT_END);
71   }
72 }
73 
libdef_module(BuildCtx * ctx,char * p,int arg)74 static void libdef_module(BuildCtx *ctx, char *p, int arg)
75 {
76   UNUSED(arg);
77   if (ctx->mode == BUILD_libdef) {
78     libdef_endmodule(ctx);
79     optr = obuf;
80     *optr++ = (uint8_t)ffid;
81     *optr++ = (uint8_t)ffasmfunc;
82     *optr++ = 0;  /* Hash table size. */
83     modstate = 1;
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);
88   }
89   modnamelen = strlen(p);
90   if (modnamelen > sizeof(modname)-1) {
91     fprintf(stderr, "Error: module name too long: '%s'\n", p);
92     exit(1);
93   }
94   strcpy(modname, p);
95 }
96 
find_ffofs(BuildCtx * ctx,const char * name)97 static int find_ffofs(BuildCtx *ctx, const char *name)
98 {
99   int i;
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);
104     }
105   }
106   fprintf(stderr, "Error: undefined fast function %s%s\n",
107 	  LABEL_PREFIX_FF, name);
108   exit(1);
109 }
110 
libdef_func(BuildCtx * ctx,char * p,int arg)111 static void libdef_func(BuildCtx *ctx, char *p, int arg)
112 {
113   if (arg != LIBINIT_CF)
114     ffasmfunc++;
115   if (ctx->mode == BUILD_libdef) {
116     if (modstate == 0) {
117       fprintf(stderr, "Error: no module for function definition %s\n", p);
118       exit(1);
119     }
120     if (regfunc == REGFUNC_NOREG) {
121       if (optr+1 > obuf+sizeof(obuf)) {
122 	fprintf(stderr, "Error: output buffer overflow\n");
123 	exit(1);
124       }
125       *optr++ = LIBINIT_FFID;
126     } else {
127       if (arg != LIBINIT_ASM_) {
128 	if (modstate != 1) fprintf(ctx->fp, ",\n");
129 	modstate = 2;
130 	fprintf(ctx->fp, "  %s%s", arg ? LABEL_PREFIX_FFH : LABEL_PREFIX_CF, p);
131       }
132       if (regfunc != REGFUNC_NOREGUV) obuf[2]++;  /* Bump hash table size. */
133       libdef_name(regfunc == REGFUNC_NOREGUV ? "" : p, arg);
134     }
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);
140       exit(1);
141     }
142     strcpy(funcname, p);
143   } else if (ctx->mode == BUILD_vmdef) {
144     int i;
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));
151   }
152   ffid++;
153   regfunc = REGFUNC_OK;
154 }
155 
libdef_uleb128(uint8_t * p,uint32_t * vv)156 static uint8_t *libdef_uleb128(uint8_t *p, uint32_t *vv)
157 {
158   uint32_t v = *p++;
159   if (v >= 0x80) {
160     int sh = 0; v &= 0x7f;
161     do { v |= ((*p & 0x7f) << (sh += 7)); } while (*p++ >= 0x80);
162   }
163   *vv = v;
164   return p;
165 }
166 
libdef_fixupbc(uint8_t * p)167 static void libdef_fixupbc(uint8_t *p)
168 {
169   uint32_t i, sizebc;
170   p += 4;
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) {
180       op = BC_ISNUM; rc++;
181     }
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;
186   }
187 }
188 
libdef_lua(BuildCtx * ctx,char * p,int arg)189 static void libdef_lua(BuildCtx *ctx, char *p, int arg)
190 {
191   UNUSED(arg);
192   if (ctx->mode == BUILD_libdef) {
193     int i;
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;
200 	libdef_name(p, 0);
201 	memcpy(optr, libbc_code + ofs, len);
202 	libdef_fixupbc(optr);
203 	optr += len;
204 	return;
205       }
206     }
207     fprintf(stderr, "Error: missing libbc definition for %s\n", p);
208     exit(1);
209   }
210 }
211 
find_rec(char * name)212 static uint32_t find_rec(char *name)
213 {
214   char *p = (char *)obuf;
215   uint32_t n;
216   for (n = 2; *p; n++) {
217     if (strcmp(p, name) == 0)
218       return n;
219     p += strlen(p)+1;
220   }
221   if (p+strlen(name)+1 >= (char *)obuf+sizeof(obuf)) {
222     fprintf(stderr, "Error: output buffer overflow\n");
223     exit(1);
224   }
225   strcpy(p, name);
226   return n;
227 }
228 
libdef_rec(BuildCtx * ctx,char * p,int arg)229 static void libdef_rec(BuildCtx *ctx, char *p, int arg)
230 {
231   UNUSED(arg);
232   if (ctx->mode == BUILD_recdef) {
233     char *q;
234     uint32_t n;
235     for (; recffid+1 < ffid; recffid++)
236       fprintf(ctx->fp, ",\n0");
237     recffid = ffid;
238     if (*p == '.') p = funcname;
239     q = strchr(p, ' ');
240     if (q) *q++ = '\0';
241     n = find_rec(p);
242     if (q)
243       fprintf(ctx->fp, ",\n0x%02x00+(%s)", n, q);
244     else
245       fprintf(ctx->fp, ",\n0x%02x00", n);
246   }
247 }
248 
memcpy_endian(void * dst,void * src,size_t n)249 static void memcpy_endian(void *dst, void *src, size_t n)
250 {
251   union { uint8_t b; uint32_t u; } host_endian;
252   host_endian.u = 1;
253   if (host_endian.b == LJ_ENDIAN_SELECT(1, 0)) {
254     memcpy(dst, src, n);
255   } else {
256     size_t i;
257     for (i = 0; i < n; i++)
258       ((uint8_t *)dst)[i] = ((uint8_t *)src)[n-i-1];
259   }
260 }
261 
libdef_push(BuildCtx * ctx,char * p,int arg)262 static void libdef_push(BuildCtx *ctx, char *p, int arg)
263 {
264   UNUSED(arg);
265   if (ctx->mode == BUILD_libdef) {
266     int len = (int)strlen(p);
267     if (*p == '"') {
268       if (len > 1 && p[len-1] == '"') {
269 	p[len-1] = '\0';
270 	libdef_name(p+1, LIBINIT_STRING);
271 	return;
272       }
273     } else if (*p >= '0' && *p <= '9') {
274       char *ep;
275       double d = strtod(p, &ep);
276       if (*ep == '\0') {
277 	if (optr+1+sizeof(double) > obuf+sizeof(obuf)) {
278 	  fprintf(stderr, "Error: output buffer overflow\n");
279 	  exit(1);
280 	}
281 	*optr++ = LIBINIT_NUMBER;
282 	memcpy_endian(optr, &d, sizeof(double));
283 	optr += sizeof(double);
284 	return;
285       }
286     } else if (!strcmp(p, "lastcl")) {
287       if (optr+1 > obuf+sizeof(obuf)) {
288 	fprintf(stderr, "Error: output buffer overflow\n");
289 	exit(1);
290       }
291       *optr++ = LIBINIT_LASTCL;
292       return;
293     } else if (len > 4 && !strncmp(p, "top-", 4)) {
294       if (optr+2 > obuf+sizeof(obuf)) {
295 	fprintf(stderr, "Error: output buffer overflow\n");
296 	exit(1);
297       }
298       *optr++ = LIBINIT_COPY;
299       *optr++ = (uint8_t)atoi(p+4);
300       return;
301     }
302     fprintf(stderr, "Error: bad value for %sPUSH(%s)\n", LIBDEF_PREFIX, p);
303     exit(1);
304   }
305 }
306 
libdef_set(BuildCtx * ctx,char * p,int arg)307 static void libdef_set(BuildCtx *ctx, char *p, int arg)
308 {
309   UNUSED(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. */
315   }
316 }
317 
libdef_regfunc(BuildCtx * ctx,char * p,int arg)318 static void libdef_regfunc(BuildCtx *ctx, char *p, int arg)
319 {
320   UNUSED(ctx); UNUSED(p);
321   regfunc = arg;
322 }
323 
324 typedef void (*LibDefFunc)(BuildCtx *ctx, char *p, int arg);
325 
326 typedef struct LibDefHandler {
327   const char *suffix;
328   const char *stop;
329   const LibDefFunc func;
330   const int arg;
331 } LibDefHandler;
332 
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 }
345 };
346 
347 /* Emit C source code for library function definitions. */
emit_lib(BuildCtx * ctx)348 void emit_lib(BuildCtx *ctx)
349 {
350   const char *fname;
351 
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;
360   ffasmfunc = 0;
361 
362   while ((fname = *ctx->args++)) {
363     char buf[256];  /* We don't care about analyzing lines longer than that. */
364     FILE *fp;
365     if (fname[0] == '-' && fname[1] == '\0') {
366       fp = stdin;
367     } else {
368       fp = fopen(fname, "r");
369       if (!fp) {
370 	fprintf(stderr, "Error: cannot open input file '%s': %s\n",
371 		fname, strerror(errno));
372 	exit(1);
373       }
374     }
375     modstate = 0;
376     regfunc = REGFUNC_OK;
377     while (fgets(buf, sizeof(buf), fp) != NULL) {
378       char *p;
379       /* Simplistic pre-processor. Only handles top-level #if/#endif. */
380       if (buf[0] == '#' && buf[1] == 'i' && buf[2] == 'f') {
381 	int ok = 1;
382 	if (!strcmp(buf, "#if LJ_52\n"))
383 	  ok = LJ_52;
384 	else if (!strcmp(buf, "#if LJ_HASJIT\n"))
385 	  ok = LJ_HASJIT;
386 	else if (!strcmp(buf, "#if LJ_HASFFI\n"))
387 	  ok = LJ_HASFFI;
388 	else if (!strcmp(buf, "#if LJ_HASBUFFER\n"))
389 	  ok = LJ_HASBUFFER;
390 	if (!ok) {
391 	  int lvl = 1;
392 	  while (fgets(buf, sizeof(buf), fp) != NULL) {
393 	    if (buf[0] == '#' && buf[1] == 'e' && buf[2] == 'n') {
394 	      if (--lvl == 0) break;
395 	    } else if (buf[0] == '#' && buf[1] == 'i' && buf[2] == 'f') {
396 	      lvl++;
397 	    }
398 	  }
399 	  continue;
400 	}
401       }
402       for (p = buf; (p = strstr(p, LIBDEF_PREFIX)) != NULL; ) {
403 	const LibDefHandler *ldh;
404 	p += sizeof(LIBDEF_PREFIX)-1;
405 	for (ldh = libdef_handlers; ldh->suffix != NULL; ldh++) {
406 	  size_t n, len = strlen(ldh->suffix);
407 	  if (!strncmp(p, ldh->suffix, len)) {
408 	    p += len;
409 	    n = ldh->stop ? strcspn(p, ldh->stop) : 0;
410 	    if (!p[n]) break;
411 	    p[n] = '\0';
412 	    ldh->func(ctx, p, ldh->arg);
413 	    p += n+1;
414 	    break;
415 	  }
416 	}
417 	if (ldh->suffix == NULL) {
418 	  buf[strlen(buf)-1] = '\0';
419 	  fprintf(stderr, "Error: unknown library definition tag %s%s\n",
420 		  LIBDEF_PREFIX, p);
421 	  exit(1);
422 	}
423       }
424     }
425     fclose(fp);
426     if (ctx->mode == BUILD_libdef) {
427       libdef_endmodule(ctx);
428     }
429   }
430 
431   if (ctx->mode == BUILD_ffdef) {
432     fprintf(ctx->fp, "\n#undef FFDEF\n\n");
433     fprintf(ctx->fp,
434       "#ifndef FF_NUM_ASMFUNC\n#define FF_NUM_ASMFUNC %d\n#endif\n\n",
435       ffasmfunc);
436   } else if (ctx->mode == BUILD_vmdef) {
437     fprintf(ctx->fp, "},\n\n");
438   } else if (ctx->mode == BUILD_bcdef) {
439     int i;
440     fprintf(ctx->fp, "\n};\n\n");
441     fprintf(ctx->fp, "LJ_DATADEF const uint16_t lj_bc_mode[] = {\n");
442     fprintf(ctx->fp, "BCDEF(BCMODE)\n");
443     for (i = ffasmfunc-1; i > 0; i--)
444       fprintf(ctx->fp, "BCMODE_FF,\n");
445     fprintf(ctx->fp, "BCMODE_FF\n};\n\n");
446   } else if (ctx->mode == BUILD_recdef) {
447     char *p = (char *)obuf;
448     fprintf(ctx->fp, "\n};\n\n");
449     fprintf(ctx->fp, "static const RecordFunc recff_func[] = {\n"
450 	    "recff_nyi,\n"
451 	    "recff_c");
452     while (*p) {
453       fprintf(ctx->fp, ",\nrecff_%s", p);
454       p += strlen(p)+1;
455     }
456     fprintf(ctx->fp, "\n};\n\n");
457   }
458 }
459 
460