root/host/buildvm_lib.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. libdef_name
  2. libdef_endmodule
  3. libdef_module
  4. find_ffofs
  5. libdef_func
  6. libdef_uleb128
  7. libdef_fixupbc
  8. libdef_lua
  9. find_rec
  10. libdef_rec
  11. memcpy_endian
  12. libdef_push
  13. libdef_set
  14. libdef_regfunc
  15. emit_lib

   1 /*
   2 ** LuaJIT VM builder: library definition compiler.
   3 ** Copyright (C) 2005-2017 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_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         if (!ok) {
 389           int lvl = 1;
 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') {
 394               lvl++;
 395             }
 396           }
 397           continue;
 398         }
 399       }
 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)) {
 406             p += len;
 407             n = ldh->stop ? strcspn(p, ldh->stop) : 0;
 408             if (!p[n]) break;
 409             p[n] = '\0';
 410             ldh->func(ctx, p, ldh->arg);
 411             p += n+1;
 412             break;
 413           }
 414         }
 415         if (ldh->suffix == NULL) {
 416           buf[strlen(buf)-1] = '\0';
 417           fprintf(stderr, "Error: unknown library definition tag %s%s\n",
 418                   LIBDEF_PREFIX, p);
 419           exit(1);
 420         }
 421       }
 422     }
 423     fclose(fp);
 424     if (ctx->mode == BUILD_libdef) {
 425       libdef_endmodule(ctx);
 426     }
 427   }
 428 
 429   if (ctx->mode == BUILD_ffdef) {
 430     fprintf(ctx->fp, "\n#undef FFDEF\n\n");
 431     fprintf(ctx->fp,
 432       "#ifndef FF_NUM_ASMFUNC\n#define FF_NUM_ASMFUNC %d\n#endif\n\n",
 433       ffasmfunc);
 434   } else if (ctx->mode == BUILD_vmdef) {
 435     fprintf(ctx->fp, "},\n\n");
 436   } else if (ctx->mode == BUILD_bcdef) {
 437     int i;
 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"
 448             "recff_nyi,\n"
 449             "recff_c");
 450     while (*p) {
 451       fprintf(ctx->fp, ",\nrecff_%s", p);
 452       p += strlen(p)+1;
 453     }
 454     fprintf(ctx->fp, "\n};\n\n");
 455   }
 456 }
 457 

/* [<][>][^][v][top][bottom][index][help] */