src/host/buildvm_lib.c - luajit-2.0-src

Global variables defined

Data types defined

Functions defined

Source code

  1. /*
  2. ** LuaJIT VM builder: library definition compiler.
  3. ** Copyright (C) 2005-2015 Mike Pall. See Copyright Notice in luajit.h
  4. */

  5. #include "buildvm.h"
  6. #include "lj_obj.h"
  7. #include "lj_bc.h"
  8. #include "lj_lib.h"
  9. #include "buildvm_libbc.h"

  10. /* Context for library definitions. */
  11. static uint8_t obuf[8192];
  12. static uint8_t *optr;
  13. static char modname[80];
  14. static size_t modnamelen;
  15. static char funcname[80];
  16. static int modstate, regfunc;
  17. static int ffid, recffid, ffasmfunc;

  18. enum {
  19.   REGFUNC_OK,
  20.   REGFUNC_NOREG,
  21.   REGFUNC_NOREGUV
  22. };

  23. static void libdef_name(const char *p, int kind)
  24. {
  25.   size_t n = strlen(p);
  26.   if (kind != LIBINIT_STRING) {
  27.     if (n > modnamelen && p[modnamelen] == '_' &&
  28.         !strncmp(p, modname, modnamelen)) {
  29.       p += modnamelen+1;
  30.       n -= modnamelen+1;
  31.     }
  32.   }
  33.   if (n > LIBINIT_MAXSTR) {
  34.     fprintf(stderr, "Error: string too long: '%s'\n",  p);
  35.     exit(1);
  36.   }
  37.   if (optr+1+n+2 > obuf+sizeof(obuf)) {  /* +2 for caller. */
  38.     fprintf(stderr, "Error: output buffer overflow\n");
  39.     exit(1);
  40.   }
  41.   *optr++ = (uint8_t)(n | kind);
  42.   memcpy(optr, p, n);
  43.   optr += n;
  44. }

  45. static void libdef_endmodule(BuildCtx *ctx)
  46. {
  47.   if (modstate != 0) {
  48.     char line[80];
  49.     const uint8_t *p;
  50.     int n;
  51.     if (modstate == 1)
  52.       fprintf(ctx->fp, "  (lua_CFunction)0");
  53.     fprintf(ctx->fp, "\n};\n");
  54.     fprintf(ctx->fp, "static const uint8_t %s%s[] = {\n",
  55.             LABEL_PREFIX_LIBINIT, modname);
  56.     line[0] = '\0';
  57.     for (n = 0, p = obuf; p < optr; p++) {
  58.       n += sprintf(line+n, "%d,", *p);
  59.       if (n >= 75) {
  60.         fprintf(ctx->fp, "%s\n", line);
  61.         n = 0;
  62.         line[0] = '\0';
  63.       }
  64.     }
  65.     fprintf(ctx->fp, "%s%d\n};\n#endif\n\n", line, LIBINIT_END);
  66.   }
  67. }

  68. static void libdef_module(BuildCtx *ctx, char *p, int arg)
  69. {
  70.   UNUSED(arg);
  71.   if (ctx->mode == BUILD_libdef) {
  72.     libdef_endmodule(ctx);
  73.     optr = obuf;
  74.     *optr++ = (uint8_t)ffid;
  75.     *optr++ = (uint8_t)ffasmfunc;
  76.     *optr++ = 0/* Hash table size. */
  77.     modstate = 1;
  78.     fprintf(ctx->fp, "#ifdef %sMODULE_%s\n", LIBDEF_PREFIX, p);
  79.     fprintf(ctx->fp, "#undef %sMODULE_%s\n", LIBDEF_PREFIX, p);
  80.     fprintf(ctx->fp, "static const lua_CFunction %s%s[] = {\n",
  81.             LABEL_PREFIX_LIBCF, p);
  82.   }
  83.   modnamelen = strlen(p);
  84.   if (modnamelen > sizeof(modname)-1) {
  85.     fprintf(stderr, "Error: module name too long: '%s'\n", p);
  86.     exit(1);
  87.   }
  88.   strcpy(modname, p);
  89. }

  90. static int find_ffofs(BuildCtx *ctx, const char *name)
  91. {
  92.   int i;
  93.   for (i = 0; i < ctx->nglob; i++) {
  94.     const char *gl = ctx->globnames[i];
  95.     if (gl[0] == 'f' && gl[1] == 'f' && gl[2] == '_' && !strcmp(gl+3, name)) {
  96.       return (int)((uint8_t *)ctx->glob[i] - ctx->code);
  97.     }
  98.   }
  99.   fprintf(stderr, "Error: undefined fast function %s%s\n",
  100.           LABEL_PREFIX_FF, name);
  101.   exit(1);
  102. }

  103. static void libdef_func(BuildCtx *ctx, char *p, int arg)
  104. {
  105.   if (arg != LIBINIT_CF)
  106.     ffasmfunc++;
  107.   if (ctx->mode == BUILD_libdef) {
  108.     if (modstate == 0) {
  109.       fprintf(stderr, "Error: no module for function definition %s\n", p);
  110.       exit(1);
  111.     }
  112.     if (regfunc == REGFUNC_NOREG) {
  113.       if (optr+1 > obuf+sizeof(obuf)) {
  114.         fprintf(stderr, "Error: output buffer overflow\n");
  115.         exit(1);
  116.       }
  117.       *optr++ = LIBINIT_FFID;
  118.     } else {
  119.       if (arg != LIBINIT_ASM_) {
  120.         if (modstate != 1) fprintf(ctx->fp, ",\n");
  121.         modstate = 2;
  122.         fprintf(ctx->fp, %s%s", arg ? LABEL_PREFIX_FFH : LABEL_PREFIX_CF, p);
  123.       }
  124.       if (regfunc != REGFUNC_NOREGUV) obuf[2]++;  /* Bump hash table size. */
  125.       libdef_name(regfunc == REGFUNC_NOREGUV ? "" : p, arg);
  126.     }
  127.   } else if (ctx->mode == BUILD_ffdef) {
  128.     fprintf(ctx->fp, "FFDEF(%s)\n", p);
  129.   } else if (ctx->mode == BUILD_recdef) {
  130.     if (strlen(p) > sizeof(funcname)-1) {
  131.       fprintf(stderr, "Error: function name too long: '%s'\n", p);
  132.       exit(1);
  133.     }
  134.     strcpy(funcname, p);
  135.   } else if (ctx->mode == BUILD_vmdef) {
  136.     int i;
  137.     for (i = 1; p[i] && modname[i-1]; i++)
  138.       if (p[i] == '_') p[i] = '.';
  139.     fprintf(ctx->fp, "\"%s\",\n", p);
  140.   } else if (ctx->mode == BUILD_bcdef) {
  141.     if (arg != LIBINIT_CF)
  142.       fprintf(ctx->fp, ",\n%d", find_ffofs(ctx, p));
  143.   }
  144.   ffid++;
  145.   regfunc = REGFUNC_OK;
  146. }

  147. static uint8_t *libdef_uleb128(uint8_t *p, uint32_t *vv)
  148. {
  149.   uint32_t v = *p++;
  150.   if (v >= 0x80) {
  151.     int sh = 0; v &= 0x7f;
  152.     do { v |= ((*p & 0x7f) << (sh += 7)); } while (*p++ >= 0x80);
  153.   }
  154.   *vv = v;
  155.   return p;
  156. }

  157. static void libdef_fixupbc(uint8_t *p)
  158. {
  159.   uint32_t i, sizebc;
  160.   p += 4;
  161.   p = libdef_uleb128(p, &sizebc);
  162.   p = libdef_uleb128(p, &sizebc);
  163.   p = libdef_uleb128(p, &sizebc);
  164.   for (i = 0; i < sizebc; i++, p += 4) {
  165.     uint8_t op = p[libbc_endian ? 3 : 0];
  166.     uint8_t ra = p[libbc_endian ? 2 : 1];
  167.     uint8_t rc = p[libbc_endian ? 1 : 2];
  168.     uint8_t rb = p[libbc_endian ? 0 : 3];
  169.     if (!LJ_DUALNUM && op == BC_ISTYPE && rc == ~LJ_TNUMX+1) {
  170.       op = BC_ISNUM; rc++;
  171.     }
  172.     p[LJ_ENDIAN_SELECT(0, 3)] = op;
  173.     p[LJ_ENDIAN_SELECT(1, 2)] = ra;
  174.     p[LJ_ENDIAN_SELECT(2, 1)] = rc;
  175.     p[LJ_ENDIAN_SELECT(3, 0)] = rb;
  176.   }
  177. }

  178. static void libdef_lua(BuildCtx *ctx, char *p, int arg)
  179. {
  180.   UNUSED(arg);
  181.   if (ctx->mode == BUILD_libdef) {
  182.     int i;
  183.     for (i = 0; libbc_map[i].name != NULL; i++) {
  184.       if (!strcmp(libbc_map[i].name, p)) {
  185.         int ofs = libbc_map[i].ofs;
  186.         int len = libbc_map[i+1].ofs - ofs;
  187.         obuf[2]++;  /* Bump hash table size. */
  188.         *optr++ = LIBINIT_LUA;
  189.         libdef_name(p, 0);
  190.         memcpy(optr, libbc_code + ofs, len);
  191.         libdef_fixupbc(optr);
  192.         optr += len;
  193.         return;
  194.       }
  195.     }
  196.     fprintf(stderr, "Error: missing libbc definition for %s\n", p);
  197.     exit(1);
  198.   }
  199. }

  200. static uint32_t find_rec(char *name)
  201. {
  202.   char *p = (char *)obuf;
  203.   uint32_t n;
  204.   for (n = 2; *p; n++) {
  205.     if (strcmp(p, name) == 0)
  206.       return n;
  207.     p += strlen(p)+1;
  208.   }
  209.   if (p+strlen(name)+1 >= (char *)obuf+sizeof(obuf)) {
  210.     fprintf(stderr, "Error: output buffer overflow\n");
  211.     exit(1);
  212.   }
  213.   strcpy(p, name);
  214.   return n;
  215. }

  216. static void libdef_rec(BuildCtx *ctx, char *p, int arg)
  217. {
  218.   UNUSED(arg);
  219.   if (ctx->mode == BUILD_recdef) {
  220.     char *q;
  221.     uint32_t n;
  222.     for (; recffid+1 < ffid; recffid++)
  223.       fprintf(ctx->fp, ",\n0");
  224.     recffid = ffid;
  225.     if (*p == '.') p = funcname;
  226.     q = strchr(p, ' ');
  227.     if (q) *q++ = '\0';
  228.     n = find_rec(p);
  229.     if (q)
  230.       fprintf(ctx->fp, ",\n0x%02x00+(%s)", n, q);
  231.     else
  232.       fprintf(ctx->fp, ",\n0x%02x00", n);
  233.   }
  234. }

  235. static void memcpy_endian(void *dst, void *src, size_t n)
  236. {
  237.   union { uint8_t b; uint32_t u; } host_endian;
  238.   host_endian.u = 1;
  239.   if (host_endian.b == LJ_ENDIAN_SELECT(1, 0)) {
  240.     memcpy(dst, src, n);
  241.   } else {
  242.     size_t i;
  243.     for (i = 0; i < n; i++)
  244.       ((uint8_t *)dst)[i] = ((uint8_t *)src)[n-i-1];
  245.   }
  246. }

  247. static void libdef_push(BuildCtx *ctx, char *p, int arg)
  248. {
  249.   UNUSED(arg);
  250.   if (ctx->mode == BUILD_libdef) {
  251.     int len = (int)strlen(p);
  252.     if (*p == '"') {
  253.       if (len > 1 && p[len-1] == '"') {
  254.         p[len-1] = '\0';
  255.         libdef_name(p+1, LIBINIT_STRING);
  256.         return;
  257.       }
  258.     } else if (*p >= '0' && *p <= '9') {
  259.       char *ep;
  260.       double d = strtod(p, &ep);
  261.       if (*ep == '\0') {
  262.         if (optr+1+sizeof(double) > obuf+sizeof(obuf)) {
  263.           fprintf(stderr, "Error: output buffer overflow\n");
  264.           exit(1);
  265.         }
  266.         *optr++ = LIBINIT_NUMBER;
  267.         memcpy_endian(optr, &d, sizeof(double));
  268.         optr += sizeof(double);
  269.         return;
  270.       }
  271.     } else if (!strcmp(p, "lastcl")) {
  272.       if (optr+1 > obuf+sizeof(obuf)) {
  273.         fprintf(stderr, "Error: output buffer overflow\n");
  274.         exit(1);
  275.       }
  276.       *optr++ = LIBINIT_LASTCL;
  277.       return;
  278.     } else if (len > 4 && !strncmp(p, "top-", 4)) {
  279.       if (optr+2 > obuf+sizeof(obuf)) {
  280.         fprintf(stderr, "Error: output buffer overflow\n");
  281.         exit(1);
  282.       }
  283.       *optr++ = LIBINIT_COPY;
  284.       *optr++ = (uint8_t)atoi(p+4);
  285.       return;
  286.     }
  287.     fprintf(stderr, "Error: bad value for %sPUSH(%s)\n", LIBDEF_PREFIX, p);
  288.     exit(1);
  289.   }
  290. }

  291. static void libdef_set(BuildCtx *ctx, char *p, int arg)
  292. {
  293.   UNUSED(arg);
  294.   if (ctx->mode == BUILD_libdef) {
  295.     if (p[0] == '!' && p[1] == '\0') p[0] = '\0'/* Set env. */
  296.     libdef_name(p, LIBINIT_STRING);
  297.     *optr++ = LIBINIT_SET;
  298.     obuf[2]++;  /* Bump hash table size. */
  299.   }
  300. }

  301. static void libdef_regfunc(BuildCtx *ctx, char *p, int arg)
  302. {
  303.   UNUSED(ctx); UNUSED(p);
  304.   regfunc = arg;
  305. }

  306. typedef void (*LibDefFunc)(BuildCtx *ctx, char *p, int arg);

  307. typedef struct LibDefHandler {
  308.   const char *suffix;
  309.   const char *stop;
  310.   const LibDefFunc func;
  311.   const int arg;
  312. } LibDefHandler;

  313. static const LibDefHandler libdef_handlers[] = {
  314.   { "MODULE_",        " \t\r\n",        libdef_module,                0 },
  315.   { "CF(",        ")",                libdef_func,                LIBINIT_CF },
  316.   { "ASM(",        ")",                libdef_func,                LIBINIT_ASM },
  317.   { "ASM_(",        ")",                libdef_func,                LIBINIT_ASM_ },
  318.   { "LUA(",        ")",                libdef_lua,                0 },
  319.   { "REC(",        ")",                libdef_rec,                0 },
  320.   { "PUSH(",        ")",                libdef_push,                0 },
  321.   { "SET(",        ")",                libdef_set,                0 },
  322.   { "NOREGUV",        NULL,                libdef_regfunc,                REGFUNC_NOREGUV },
  323.   { "NOREG",        NULL,                libdef_regfunc,                REGFUNC_NOREG },
  324.   { NULL,        NULL,                (LibDefFunc)0,                0 }
  325. };

  326. /* Emit C source code for library function definitions. */
  327. void emit_lib(BuildCtx *ctx)
  328. {
  329.   const char *fname;

  330.   if (ctx->mode == BUILD_ffdef || ctx->mode == BUILD_libdef ||
  331.       ctx->mode == BUILD_recdef)
  332.     fprintf(ctx->fp, "/* This is a generated file. DO NOT EDIT! */\n\n");
  333.   else if (ctx->mode == BUILD_vmdef)
  334.     fprintf(ctx->fp, "ffnames = {\n[0]=\"Lua\",\n\"C\",\n");
  335.   if (ctx->mode == BUILD_recdef)
  336.     fprintf(ctx->fp, "static const uint16_t recff_idmap[] = {\n0,\n0x0100");
  337.   recffid = ffid = FF_C+1;
  338.   ffasmfunc = 0;

  339.   while ((fname = *ctx->args++)) {
  340.     char buf[256];  /* We don't care about analyzing lines longer than that. */
  341.     FILE *fp;
  342.     if (fname[0] == '-' && fname[1] == '\0') {
  343.       fp = stdin;
  344.     } else {
  345.       fp = fopen(fname, "r");
  346.       if (!fp) {
  347.         fprintf(stderr, "Error: cannot open input file '%s': %s\n",
  348.                 fname, strerror(errno));
  349.         exit(1);
  350.       }
  351.     }
  352.     modstate = 0;
  353.     regfunc = REGFUNC_OK;
  354.     while (fgets(buf, sizeof(buf), fp) != NULL) {
  355.       char *p;
  356.       /* Simplistic pre-processor. Only handles top-level #if/#endif. */
  357.       if (buf[0] == '#' && buf[1] == 'i' && buf[2] == 'f') {
  358.         int ok = 1;
  359.         if (!strcmp(buf, "#if LJ_52\n"))
  360.           ok = LJ_52;
  361.         else if (!strcmp(buf, "#if LJ_HASJIT\n"))
  362.           ok = LJ_HASJIT;
  363.         else if (!strcmp(buf, "#if LJ_HASFFI\n"))
  364.           ok = LJ_HASFFI;
  365.         if (!ok) {
  366.           int lvl = 1;
  367.           while (fgets(buf, sizeof(buf), fp) != NULL) {
  368.             if (buf[0] == '#' && buf[1] == 'e' && buf[2] == 'n') {
  369.               if (--lvl == 0) break;
  370.             } else if (buf[0] == '#' && buf[1] == 'i' && buf[2] == 'f') {
  371.               lvl++;
  372.             }
  373.           }
  374.           continue;
  375.         }
  376.       }
  377.       for (p = buf; (p = strstr(p, LIBDEF_PREFIX)) != NULL; ) {
  378.         const LibDefHandler *ldh;
  379.         p += sizeof(LIBDEF_PREFIX)-1;
  380.         for (ldh = libdef_handlers; ldh->suffix != NULL; ldh++) {
  381.           size_t n, len = strlen(ldh->suffix);
  382.           if (!strncmp(p, ldh->suffix, len)) {
  383.             p += len;
  384.             n = ldh->stop ? strcspn(p, ldh->stop) : 0;
  385.             if (!p[n]) break;
  386.             p[n] = '\0';
  387.             ldh->func(ctx, p, ldh->arg);
  388.             p += n+1;
  389.             break;
  390.           }
  391.         }
  392.         if (ldh->suffix == NULL) {
  393.           buf[strlen(buf)-1] = '\0';
  394.           fprintf(stderr, "Error: unknown library definition tag %s%s\n",
  395.                   LIBDEF_PREFIX, p);
  396.           exit(1);
  397.         }
  398.       }
  399.     }
  400.     fclose(fp);
  401.     if (ctx->mode == BUILD_libdef) {
  402.       libdef_endmodule(ctx);
  403.     }
  404.   }

  405.   if (ctx->mode == BUILD_ffdef) {
  406.     fprintf(ctx->fp, "\n#undef FFDEF\n\n");
  407.     fprintf(ctx->fp,
  408.       "#ifndef FF_NUM_ASMFUNC\n#define FF_NUM_ASMFUNC %d\n#endif\n\n",
  409.       ffasmfunc);
  410.   } else if (ctx->mode == BUILD_vmdef) {
  411.     fprintf(ctx->fp, "},\n\n");
  412.   } else if (ctx->mode == BUILD_bcdef) {
  413.     int i;
  414.     fprintf(ctx->fp, "\n};\n\n");
  415.     fprintf(ctx->fp, "LJ_DATADEF const uint16_t lj_bc_mode[] = {\n");
  416.     fprintf(ctx->fp, "BCDEF(BCMODE)\n");
  417.     for (i = ffasmfunc-1; i > 0; i--)
  418.       fprintf(ctx->fp, "BCMODE_FF,\n");
  419.     fprintf(ctx->fp, "BCMODE_FF\n};\n\n");
  420.   } else if (ctx->mode == BUILD_recdef) {
  421.     char *p = (char *)obuf;
  422.     fprintf(ctx->fp, "\n};\n\n");
  423.     fprintf(ctx->fp, "static const RecordFunc recff_func[] = {\n"
  424.             "recff_nyi,\n"
  425.             "recff_c");
  426.     while (*p) {
  427.       fprintf(ctx->fp, ",\nrecff_%s", p);
  428.       p += strlen(p)+1;
  429.     }
  430.     fprintf(ctx->fp, "\n};\n\n");
  431.   }
  432. }