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. find_rec
  7. libdef_rec
  8. memcpy_endian
  9. libdef_push
  10. libdef_set
  11. libdef_regfunc
  12. 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_lib.h"
   9 
  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 
  19 enum {
  20   REGFUNC_OK,
  21   REGFUNC_NOREG,
  22   REGFUNC_NOREGUV
  23 };
  24 
  25 static void libdef_name(const char *p, int kind)
  26 {
  27   size_t n = strlen(p);
  28   if (kind != LIBINIT_STRING) {
  29     if (n > modnamelen && p[modnamelen] == '_' &&
  30         !strncmp(p, modname, modnamelen)) {
  31       p += modnamelen+1;
  32       n -= modnamelen+1;
  33     }
  34   }
  35   if (n > LIBINIT_MAXSTR) {
  36     fprintf(stderr, "Error: string too long: '%s'\n",  p);
  37     exit(1);
  38   }
  39   if (optr+1+n+2 > obuf+sizeof(obuf)) {  /* +2 for caller. */
  40     fprintf(stderr, "Error: output buffer overflow\n");
  41     exit(1);
  42   }
  43   *optr++ = (uint8_t)(n | kind);
  44   memcpy(optr, p, n);
  45   optr += n;
  46 }
  47 
  48 static void libdef_endmodule(BuildCtx *ctx)
  49 {
  50   if (modstate != 0) {
  51     char line[80];
  52     const uint8_t *p;
  53     int n;
  54     if (modstate == 1)
  55       fprintf(ctx->fp, "  (lua_CFunction)0");
  56     fprintf(ctx->fp, "\n};\n");
  57     fprintf(ctx->fp, "static const uint8_t %s%s[] = {\n",
  58             LABEL_PREFIX_LIBINIT, modname);
  59     line[0] = '\0';
  60     for (n = 0, p = obuf; p < optr; p++) {
  61       n += sprintf(line+n, "%d,", *p);
  62       if (n >= 75) {
  63         fprintf(ctx->fp, "%s\n", line);
  64         n = 0;
  65         line[0] = '\0';
  66       }
  67     }
  68     fprintf(ctx->fp, "%s%d\n};\n#endif\n\n", line, LIBINIT_END);
  69   }
  70 }
  71 
  72 static void libdef_module(BuildCtx *ctx, char *p, int arg)
  73 {
  74   UNUSED(arg);
  75   if (ctx->mode == BUILD_libdef) {
  76     libdef_endmodule(ctx);
  77     optr = obuf;
  78     *optr++ = (uint8_t)ffid;
  79     *optr++ = (uint8_t)ffasmfunc;
  80     *optr++ = 0;  /* Hash table size. */
  81     modstate = 1;
  82     fprintf(ctx->fp, "#ifdef %sMODULE_%s\n", LIBDEF_PREFIX, p);
  83     fprintf(ctx->fp, "#undef %sMODULE_%s\n", LIBDEF_PREFIX, p);
  84     fprintf(ctx->fp, "static const lua_CFunction %s%s[] = {\n",
  85             LABEL_PREFIX_LIBCF, p);
  86   }
  87   modnamelen = strlen(p);
  88   if (modnamelen > sizeof(modname)-1) {
  89     fprintf(stderr, "Error: module name too long: '%s'\n", p);
  90     exit(1);
  91   }
  92   strcpy(modname, p);
  93 }
  94 
  95 static int find_ffofs(BuildCtx *ctx, const char *name)
  96 {
  97   int i;
  98   for (i = 0; i < ctx->nglob; i++) {
  99     const char *gl = ctx->globnames[i];
 100     if (gl[0] == 'f' && gl[1] == 'f' && gl[2] == '_' && !strcmp(gl+3, name)) {
 101       return (int)((uint8_t *)ctx->glob[i] - ctx->code);
 102     }
 103   }
 104   fprintf(stderr, "Error: undefined fast function %s%s\n",
 105           LABEL_PREFIX_FF, name);
 106   exit(1);
 107 }
 108 
 109 static void libdef_func(BuildCtx *ctx, char *p, int arg)
 110 {
 111   if (arg != LIBINIT_CF)
 112     ffasmfunc++;
 113   if (ctx->mode == BUILD_libdef) {
 114     if (modstate == 0) {
 115       fprintf(stderr, "Error: no module for function definition %s\n", p);
 116       exit(1);
 117     }
 118     if (regfunc == REGFUNC_NOREG) {
 119       if (optr+1 > obuf+sizeof(obuf)) {
 120         fprintf(stderr, "Error: output buffer overflow\n");
 121         exit(1);
 122       }
 123       *optr++ = LIBINIT_FFID;
 124     } else {
 125       if (arg != LIBINIT_ASM_) {
 126         if (modstate != 1) fprintf(ctx->fp, ",\n");
 127         modstate = 2;
 128         fprintf(ctx->fp, "  %s%s", arg ? LABEL_PREFIX_FFH : LABEL_PREFIX_CF, p);
 129       }
 130       if (regfunc != REGFUNC_NOREGUV) obuf[2]++;  /* Bump hash table size. */
 131       libdef_name(regfunc == REGFUNC_NOREGUV ? "" : p, arg);
 132     }
 133   } else if (ctx->mode == BUILD_ffdef) {
 134     fprintf(ctx->fp, "FFDEF(%s)\n", p);
 135   } else if (ctx->mode == BUILD_recdef) {
 136     if (strlen(p) > sizeof(funcname)-1) {
 137       fprintf(stderr, "Error: function name too long: '%s'\n", p);
 138       exit(1);
 139     }
 140     strcpy(funcname, p);
 141   } else if (ctx->mode == BUILD_vmdef) {
 142     int i;
 143     for (i = 1; p[i] && modname[i-1]; i++)
 144       if (p[i] == '_') p[i] = '.';
 145     fprintf(ctx->fp, "\"%s\",\n", p);
 146   } else if (ctx->mode == BUILD_bcdef) {
 147     if (arg != LIBINIT_CF)
 148       fprintf(ctx->fp, ",\n%d", find_ffofs(ctx, p));
 149   }
 150   ffid++;
 151   regfunc = REGFUNC_OK;
 152 }
 153 
 154 static uint32_t find_rec(char *name)
 155 {
 156   char *p = (char *)obuf;
 157   uint32_t n;
 158   for (n = 2; *p; n++) {
 159     if (strcmp(p, name) == 0)
 160       return n;
 161     p += strlen(p)+1;
 162   }
 163   if (p+strlen(name)+1 >= (char *)obuf+sizeof(obuf)) {
 164     fprintf(stderr, "Error: output buffer overflow\n");
 165     exit(1);
 166   }
 167   strcpy(p, name);
 168   return n;
 169 }
 170 
 171 static void libdef_rec(BuildCtx *ctx, char *p, int arg)
 172 {
 173   UNUSED(arg);
 174   if (ctx->mode == BUILD_recdef) {
 175     char *q;
 176     uint32_t n;
 177     for (; recffid+1 < ffid; recffid++)
 178       fprintf(ctx->fp, ",\n0");
 179     recffid = ffid;
 180     if (*p == '.') p = funcname;
 181     q = strchr(p, ' ');
 182     if (q) *q++ = '\0';
 183     n = find_rec(p);
 184     if (q)
 185       fprintf(ctx->fp, ",\n0x%02x00+(%s)", n, q);
 186     else
 187       fprintf(ctx->fp, ",\n0x%02x00", n);
 188   }
 189 }
 190 
 191 static void memcpy_endian(void *dst, void *src, size_t n)
 192 {
 193   union { uint8_t b; uint32_t u; } host_endian;
 194   host_endian.u = 1;
 195   if (host_endian.b == LJ_ENDIAN_SELECT(1, 0)) {
 196     memcpy(dst, src, n);
 197   } else {
 198     size_t i;
 199     for (i = 0; i < n; i++)
 200       ((uint8_t *)dst)[i] = ((uint8_t *)src)[n-i-1];
 201   }
 202 }
 203 
 204 static void libdef_push(BuildCtx *ctx, char *p, int arg)
 205 {
 206   UNUSED(arg);
 207   if (ctx->mode == BUILD_libdef) {
 208     int len = (int)strlen(p);
 209     if (*p == '"') {
 210       if (len > 1 && p[len-1] == '"') {
 211         p[len-1] = '\0';
 212         libdef_name(p+1, LIBINIT_STRING);
 213         return;
 214       }
 215     } else if (*p >= '0' && *p <= '9') {
 216       char *ep;
 217       double d = strtod(p, &ep);
 218       if (*ep == '\0') {
 219         if (optr+1+sizeof(double) > obuf+sizeof(obuf)) {
 220           fprintf(stderr, "Error: output buffer overflow\n");
 221           exit(1);
 222         }
 223         *optr++ = LIBINIT_NUMBER;
 224         memcpy_endian(optr, &d, sizeof(double));
 225         optr += sizeof(double);
 226         return;
 227       }
 228     } else if (!strcmp(p, "lastcl")) {
 229       if (optr+1 > obuf+sizeof(obuf)) {
 230         fprintf(stderr, "Error: output buffer overflow\n");
 231         exit(1);
 232       }
 233       *optr++ = LIBINIT_LASTCL;
 234       return;
 235     } else if (len > 4 && !strncmp(p, "top-", 4)) {
 236       if (optr+2 > obuf+sizeof(obuf)) {
 237         fprintf(stderr, "Error: output buffer overflow\n");
 238         exit(1);
 239       }
 240       *optr++ = LIBINIT_COPY;
 241       *optr++ = (uint8_t)atoi(p+4);
 242       return;
 243     }
 244     fprintf(stderr, "Error: bad value for %sPUSH(%s)\n", LIBDEF_PREFIX, p);
 245     exit(1);
 246   }
 247 }
 248 
 249 static void libdef_set(BuildCtx *ctx, char *p, int arg)
 250 {
 251   UNUSED(arg);
 252   if (ctx->mode == BUILD_libdef) {
 253     if (p[0] == '!' && p[1] == '\0') p[0] = '\0';  /* Set env. */
 254     libdef_name(p, LIBINIT_STRING);
 255     *optr++ = LIBINIT_SET;
 256     obuf[2]++;  /* Bump hash table size. */
 257   }
 258 }
 259 
 260 static void libdef_regfunc(BuildCtx *ctx, char *p, int arg)
 261 {
 262   UNUSED(ctx); UNUSED(p);
 263   regfunc = arg;
 264 }
 265 
 266 typedef void (*LibDefFunc)(BuildCtx *ctx, char *p, int arg);
 267 
 268 typedef struct LibDefHandler {
 269   const char *suffix;
 270   const char *stop;
 271   const LibDefFunc func;
 272   const int arg;
 273 } LibDefHandler;
 274 
 275 static const LibDefHandler libdef_handlers[] = {
 276   { "MODULE_",  " \t\r\n",      libdef_module,          0 },
 277   { "CF(",      ")",            libdef_func,            LIBINIT_CF },
 278   { "ASM(",     ")",            libdef_func,            LIBINIT_ASM },
 279   { "ASM_(",    ")",            libdef_func,            LIBINIT_ASM_ },
 280   { "REC(",     ")",            libdef_rec,             0 },
 281   { "PUSH(",    ")",            libdef_push,            0 },
 282   { "SET(",     ")",            libdef_set,             0 },
 283   { "NOREGUV",  NULL,           libdef_regfunc,         REGFUNC_NOREGUV },
 284   { "NOREG",    NULL,           libdef_regfunc,         REGFUNC_NOREG },
 285   { NULL,       NULL,           (LibDefFunc)0,          0 }
 286 };
 287 
 288 /* Emit C source code for library function definitions. */
 289 void emit_lib(BuildCtx *ctx)
 290 {
 291   const char *fname;
 292 
 293   if (ctx->mode == BUILD_ffdef || ctx->mode == BUILD_libdef ||
 294       ctx->mode == BUILD_recdef)
 295     fprintf(ctx->fp, "/* This is a generated file. DO NOT EDIT! */\n\n");
 296   else if (ctx->mode == BUILD_vmdef)
 297     fprintf(ctx->fp, "ffnames = {\n[0]=\"Lua\",\n\"C\",\n");
 298   if (ctx->mode == BUILD_recdef)
 299     fprintf(ctx->fp, "static const uint16_t recff_idmap[] = {\n0,\n0x0100");
 300   recffid = ffid = FF_C+1;
 301   ffasmfunc = 0;
 302 
 303   while ((fname = *ctx->args++)) {
 304     char buf[256];  /* We don't care about analyzing lines longer than that. */
 305     FILE *fp;
 306     if (fname[0] == '-' && fname[1] == '\0') {
 307       fp = stdin;
 308     } else {
 309       fp = fopen(fname, "r");
 310       if (!fp) {
 311         fprintf(stderr, "Error: cannot open input file '%s': %s\n",
 312                 fname, strerror(errno));
 313         exit(1);
 314       }
 315     }
 316     modstate = 0;
 317     regfunc = REGFUNC_OK;
 318     while (fgets(buf, sizeof(buf), fp) != NULL) {
 319       char *p;
 320       /* Simplistic pre-processor. Only handles top-level #if/#endif. */
 321       if (buf[0] == '#' && buf[1] == 'i' && buf[2] == 'f') {
 322         int ok = 1;
 323         if (!strcmp(buf, "#if LJ_52\n"))
 324           ok = LJ_52;
 325         else if (!strcmp(buf, "#if LJ_HASJIT\n"))
 326           ok = LJ_HASJIT;
 327         else if (!strcmp(buf, "#if LJ_HASFFI\n"))
 328           ok = LJ_HASFFI;
 329         if (!ok) {
 330           int lvl = 1;
 331           while (fgets(buf, sizeof(buf), fp) != NULL) {
 332             if (buf[0] == '#' && buf[1] == 'e' && buf[2] == 'n') {
 333               if (--lvl == 0) break;
 334             } else if (buf[0] == '#' && buf[1] == 'i' && buf[2] == 'f') {
 335               lvl++;
 336             }
 337           }
 338           continue;
 339         }
 340       }
 341       for (p = buf; (p = strstr(p, LIBDEF_PREFIX)) != NULL; ) {
 342         const LibDefHandler *ldh;
 343         p += sizeof(LIBDEF_PREFIX)-1;
 344         for (ldh = libdef_handlers; ldh->suffix != NULL; ldh++) {
 345           size_t n, len = strlen(ldh->suffix);
 346           if (!strncmp(p, ldh->suffix, len)) {
 347             p += len;
 348             n = ldh->stop ? strcspn(p, ldh->stop) : 0;
 349             if (!p[n]) break;
 350             p[n] = '\0';
 351             ldh->func(ctx, p, ldh->arg);
 352             p += n+1;
 353             break;
 354           }
 355         }
 356         if (ldh->suffix == NULL) {
 357           buf[strlen(buf)-1] = '\0';
 358           fprintf(stderr, "Error: unknown library definition tag %s%s\n",
 359                   LIBDEF_PREFIX, p);
 360           exit(1);
 361         }
 362       }
 363     }
 364     fclose(fp);
 365     if (ctx->mode == BUILD_libdef) {
 366       libdef_endmodule(ctx);
 367     }
 368   }
 369 
 370   if (ctx->mode == BUILD_ffdef) {
 371     fprintf(ctx->fp, "\n#undef FFDEF\n\n");
 372     fprintf(ctx->fp,
 373       "#ifndef FF_NUM_ASMFUNC\n#define FF_NUM_ASMFUNC %d\n#endif\n\n",
 374       ffasmfunc);
 375   } else if (ctx->mode == BUILD_vmdef) {
 376     fprintf(ctx->fp, "}\n\n");
 377   } else if (ctx->mode == BUILD_bcdef) {
 378     int i;
 379     fprintf(ctx->fp, "\n};\n\n");
 380     fprintf(ctx->fp, "LJ_DATADEF const uint16_t lj_bc_mode[] = {\n");
 381     fprintf(ctx->fp, "BCDEF(BCMODE)\n");
 382     for (i = ffasmfunc-1; i > 0; i--)
 383       fprintf(ctx->fp, "BCMODE_FF,\n");
 384     fprintf(ctx->fp, "BCMODE_FF\n};\n\n");
 385   } else if (ctx->mode == BUILD_recdef) {
 386     char *p = (char *)obuf;
 387     fprintf(ctx->fp, "\n};\n\n");
 388     fprintf(ctx->fp, "static const RecordFunc recff_func[] = {\n"
 389             "recff_nyi,\n"
 390             "recff_c");
 391     while (*p) {
 392       fprintf(ctx->fp, ",\nrecff_%s", p);
 393       p += strlen(p)+1;
 394     }
 395     fprintf(ctx->fp, "\n};\n\n");
 396   }
 397 }
 398 

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