~ubuntu-branches/ubuntu/trusty/luajit/trusty

« back to all changes in this revision

Viewing changes to src/buildvm_lib.c

  • Committer: Package Import Robot
  • Author(s): Enrico Tassi
  • Date: 2012-11-03 14:07:56 UTC
  • mfrom: (1.2.1) (15.1.1 experimental)
  • Revision ID: package-import@ubuntu.com-20121103140756-z0zcnyrwqlvuc2m5
Tags: 2.0.0+dfsg-1
New upstream release

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
** LuaJIT VM builder: library definition compiler.
3
 
** Copyright (C) 2005-2011 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
 
      for (p = buf; (p = strstr(p, LIBDEF_PREFIX)) != NULL; ) {
321
 
        const LibDefHandler *ldh;
322
 
        p += sizeof(LIBDEF_PREFIX)-1;
323
 
        for (ldh = libdef_handlers; ldh->suffix != NULL; ldh++) {
324
 
          size_t n, len = strlen(ldh->suffix);
325
 
          if (!strncmp(p, ldh->suffix, len)) {
326
 
            p += len;
327
 
            n = ldh->stop ? strcspn(p, ldh->stop) : 0;
328
 
            if (!p[n]) break;
329
 
            p[n] = '\0';
330
 
            ldh->func(ctx, p, ldh->arg);
331
 
            p += n+1;
332
 
            break;
333
 
          }
334
 
        }
335
 
        if (ldh->suffix == NULL) {
336
 
          buf[strlen(buf)-1] = '\0';
337
 
          fprintf(stderr, "Error: unknown library definition tag %s%s\n",
338
 
                  LIBDEF_PREFIX, p);
339
 
          exit(1);
340
 
        }
341
 
      }
342
 
    }
343
 
    fclose(fp);
344
 
    if (ctx->mode == BUILD_libdef) {
345
 
      libdef_endmodule(ctx);
346
 
    }
347
 
  }
348
 
 
349
 
  if (ctx->mode == BUILD_ffdef) {
350
 
    fprintf(ctx->fp, "\n#undef FFDEF\n\n");
351
 
    fprintf(ctx->fp,
352
 
      "#ifndef FF_NUM_ASMFUNC\n#define FF_NUM_ASMFUNC %d\n#endif\n\n",
353
 
      ffasmfunc);
354
 
  } else if (ctx->mode == BUILD_vmdef) {
355
 
    fprintf(ctx->fp, "}\n\n");
356
 
  } else if (ctx->mode == BUILD_bcdef) {
357
 
    int i;
358
 
    fprintf(ctx->fp, "\n};\n\n");
359
 
    fprintf(ctx->fp, "LJ_DATADEF const uint16_t lj_bc_mode[] = {\n");
360
 
    fprintf(ctx->fp, "BCDEF(BCMODE)\n");
361
 
    for (i = ffasmfunc-1; i > 0; i--)
362
 
      fprintf(ctx->fp, "BCMODE_FF,\n");
363
 
    fprintf(ctx->fp, "BCMODE_FF\n};\n\n");
364
 
  } else if (ctx->mode == BUILD_recdef) {
365
 
    char *p = (char *)obuf;
366
 
    fprintf(ctx->fp, "\n};\n\n");
367
 
    fprintf(ctx->fp, "static const RecordFunc recff_func[] = {\n"
368
 
            "recff_nyi,\n"
369
 
            "recff_c");
370
 
    while (*p) {
371
 
      fprintf(ctx->fp, ",\nrecff_%s", p);
372
 
      p += strlen(p)+1;
373
 
    }
374
 
    fprintf(ctx->fp, "\n};\n\n");
375
 
  }
376
 
}
377