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