ljx

FORK: LuaJIT with native 5.2 and 5.3 support
git clone https://git.neptards.moe/neptards/ljx.git
Log | Files | Refs | README

buildvm_lib.c (12305B)


      1 /*
      2 ** LuaJIT VM builder: library definition compiler.
      3 ** Copyright (C) 2005-2016 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 
     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 
     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 
     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 
     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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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. */
    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_HASJIT\n"))
    383 	  ok = LJ_HASJIT;
    384 	else if (!strcmp(buf, "#if LJ_HASFFI\n"))
    385 	  ok = LJ_HASFFI;
    386 	else if (!strcmp(buf, "#if LJ_51\n"))
    387 	  ok = LJ_51;
    388 	else if (!strcmp(buf, "#if !LJ_51\n"))
    389 	  ok = !LJ_51;
    390 	else if (!strcmp(buf, "#if LJ_53\n"))
    391 	  ok = LJ_53;
    392 	else if (!strcmp(buf, "#if !LJ_53\n"))
    393 	  ok = !LJ_53;
    394 	if (!ok) {
    395 	  int lvl = 1;
    396 	  while (fgets(buf, sizeof(buf), fp) != NULL) {
    397 	    if (buf[0] == '#' && buf[1] == 'e' && buf[2] == 'n') {
    398 	      if (--lvl == 0) break;
    399 	    } else if (buf[0] == '#' && buf[1] == 'i' && buf[2] == 'f') {
    400 	      lvl++;
    401 	    }
    402 	  }
    403 	  continue;
    404 	}
    405       }
    406       for (p = buf; (p = strstr(p, LIBDEF_PREFIX)) != NULL; ) {
    407 	const LibDefHandler *ldh;
    408 	p += sizeof(LIBDEF_PREFIX)-1;
    409 	for (ldh = libdef_handlers; ldh->suffix != NULL; ldh++) {
    410 	  size_t n, len = strlen(ldh->suffix);
    411 	  if (!strncmp(p, ldh->suffix, len)) {
    412 	    p += len;
    413 	    n = ldh->stop ? strcspn(p, ldh->stop) : 0;
    414 	    if (!p[n]) break;
    415 	    p[n] = '\0';
    416 	    ldh->func(ctx, p, ldh->arg);
    417 	    p += n+1;
    418 	    break;
    419 	  }
    420 	}
    421 	if (ldh->suffix == NULL) {
    422 	  buf[strlen(buf)-1] = '\0';
    423 	  fprintf(stderr, "Error: unknown library definition tag %s%s\n",
    424 		  LIBDEF_PREFIX, p);
    425 	  exit(1);
    426 	}
    427       }
    428     }
    429     fclose(fp);
    430     if (ctx->mode == BUILD_libdef) {
    431       libdef_endmodule(ctx);
    432     }
    433   }
    434 
    435   if (ctx->mode == BUILD_ffdef) {
    436     fprintf(ctx->fp, "\n#undef FFDEF\n\n");
    437     fprintf(ctx->fp,
    438       "#ifndef FF_NUM_ASMFUNC\n#define FF_NUM_ASMFUNC %d\n#endif\n\n",
    439       ffasmfunc);
    440   } else if (ctx->mode == BUILD_vmdef) {
    441     fprintf(ctx->fp, "},\n\n");
    442   } else if (ctx->mode == BUILD_bcdef) {
    443     int i;
    444     fprintf(ctx->fp, "\n};\n\n");
    445     fprintf(ctx->fp, "LJ_DATADEF const uint16_t lj_bc_mode[] = {\n");
    446     fprintf(ctx->fp, "BCDEF(BCMODE)\n");
    447     for (i = ffasmfunc-1; i > 0; i--)
    448       fprintf(ctx->fp, "BCMODE_FF,\n");
    449     fprintf(ctx->fp, "BCMODE_FF\n};\n\n");
    450   } else if (ctx->mode == BUILD_recdef) {
    451     char *p = (char *)obuf;
    452     fprintf(ctx->fp, "\n};\n\n");
    453     fprintf(ctx->fp, "static const RecordFunc recff_func[] = {\n"
    454 	    "recff_nyi,\n"
    455 	    "recff_c");
    456     while (*p) {
    457       fprintf(ctx->fp, ",\nrecff_%s", p);
    458       p += strlen(p)+1;
    459     }
    460     fprintf(ctx->fp, "\n};\n\n");
    461   }
    462 }
    463