summaryrefslogtreecommitdiff
path: root/src/host
diff options
context:
space:
mode:
Diffstat (limited to 'src/host')
-rw-r--r--src/host/buildvm.c36
-rw-r--r--src/host/buildvm.h1
-rw-r--r--src/host/buildvm_asm.c63
-rw-r--r--src/host/buildvm_fold.c7
-rw-r--r--src/host/buildvm_lib.c63
-rw-r--r--src/host/buildvm_libbc.h81
-rw-r--r--src/host/buildvm_peobj.c43
-rw-r--r--src/host/genlibbc.lua225
8 files changed, 477 insertions, 42 deletions
diff --git a/src/host/buildvm.c b/src/host/buildvm.c
index 39c2bc24..ec99e501 100644
--- a/src/host/buildvm.c
+++ b/src/host/buildvm.c
@@ -18,8 +18,10 @@
18#include "lj_obj.h" 18#include "lj_obj.h"
19#include "lj_gc.h" 19#include "lj_gc.h"
20#include "lj_bc.h" 20#include "lj_bc.h"
21#if LJ_HASJIT
21#include "lj_ir.h" 22#include "lj_ir.h"
22#include "lj_ircall.h" 23#include "lj_ircall.h"
24#endif
23#include "lj_frame.h" 25#include "lj_frame.h"
24#include "lj_dispatch.h" 26#include "lj_dispatch.h"
25#if LJ_HASFFI 27#if LJ_HASFFI
@@ -59,10 +61,10 @@ static int collect_reloc(BuildCtx *ctx, uint8_t *addr, int idx, int type);
59#include "../dynasm/dasm_x86.h" 61#include "../dynasm/dasm_x86.h"
60#elif LJ_TARGET_ARM 62#elif LJ_TARGET_ARM
61#include "../dynasm/dasm_arm.h" 63#include "../dynasm/dasm_arm.h"
64#elif LJ_TARGET_ARM64
65#include "../dynasm/dasm_arm64.h"
62#elif LJ_TARGET_PPC 66#elif LJ_TARGET_PPC
63#include "../dynasm/dasm_ppc.h" 67#include "../dynasm/dasm_ppc.h"
64#elif LJ_TARGET_PPCSPE
65#include "../dynasm/dasm_ppc.h"
66#elif LJ_TARGET_MIPS 68#elif LJ_TARGET_MIPS
67#include "../dynasm/dasm_mips.h" 69#include "../dynasm/dasm_mips.h"
68#else 70#else
@@ -110,11 +112,11 @@ static const char *sym_decorate(BuildCtx *ctx,
110 if (p) { 112 if (p) {
111#if LJ_TARGET_X86ORX64 113#if LJ_TARGET_X86ORX64
112 if (!LJ_64 && (ctx->mode == BUILD_coffasm || ctx->mode == BUILD_peobj)) 114 if (!LJ_64 && (ctx->mode == BUILD_coffasm || ctx->mode == BUILD_peobj))
113 name[0] = '@'; 115 name[0] = name[1] == 'R' ? '_' : '@'; /* Just for _RtlUnwind@16. */
114 else 116 else
115 *p = '\0'; 117 *p = '\0';
116#elif (LJ_TARGET_PPC || LJ_TARGET_PPCSPE) && !LJ_TARGET_CONSOLE 118#elif LJ_TARGET_PPC && !LJ_TARGET_CONSOLE
117 /* Keep @plt. */ 119 /* Keep @plt etc. */
118#else 120#else
119 *p = '\0'; 121 *p = '\0';
120#endif 122#endif
@@ -179,6 +181,7 @@ static int build_code(BuildCtx *ctx)
179 ctx->nreloc = 0; 181 ctx->nreloc = 0;
180 182
181 ctx->globnames = globnames; 183 ctx->globnames = globnames;
184 ctx->extnames = extnames;
182 ctx->relocsym = (const char **)malloc(NRELOCSYM*sizeof(const char *)); 185 ctx->relocsym = (const char **)malloc(NRELOCSYM*sizeof(const char *));
183 ctx->nrelocsym = 0; 186 ctx->nrelocsym = 0;
184 for (i = 0; i < (int)NRELOCSYM; i++) relocmap[i] = -1; 187 for (i = 0; i < (int)NRELOCSYM; i++) relocmap[i] = -1;
@@ -249,6 +252,7 @@ BCDEF(BCNAME)
249 NULL 252 NULL
250}; 253};
251 254
255#if LJ_HASJIT
252const char *const ir_names[] = { 256const char *const ir_names[] = {
253#define IRNAME(name, m, m1, m2) #name, 257#define IRNAME(name, m, m1, m2) #name,
254IRDEF(IRNAME) 258IRDEF(IRNAME)
@@ -289,7 +293,9 @@ static const char *const trace_errors[] = {
289#include "lj_traceerr.h" 293#include "lj_traceerr.h"
290 NULL 294 NULL
291}; 295};
296#endif
292 297
298#if LJ_HASJIT
293static const char *lower(char *buf, const char *s) 299static const char *lower(char *buf, const char *s)
294{ 300{
295 char *p = buf; 301 char *p = buf;
@@ -300,6 +306,7 @@ static const char *lower(char *buf, const char *s)
300 *p = '\0'; 306 *p = '\0';
301 return buf; 307 return buf;
302} 308}
309#endif
303 310
304/* Emit C source code for bytecode-related definitions. */ 311/* Emit C source code for bytecode-related definitions. */
305static void emit_bcdef(BuildCtx *ctx) 312static void emit_bcdef(BuildCtx *ctx)
@@ -317,24 +324,27 @@ static void emit_bcdef(BuildCtx *ctx)
317/* Emit VM definitions as Lua code for debug modules. */ 324/* Emit VM definitions as Lua code for debug modules. */
318static void emit_vmdef(BuildCtx *ctx) 325static void emit_vmdef(BuildCtx *ctx)
319{ 326{
327#if LJ_HASJIT
320 char buf[80]; 328 char buf[80];
329#endif
321 int i; 330 int i;
322 fprintf(ctx->fp, "-- This is a generated file. DO NOT EDIT!\n\n"); 331 fprintf(ctx->fp, "-- This is a generated file. DO NOT EDIT!\n\n");
323 fprintf(ctx->fp, "assert(require(\"jit\").version == \"%s\", \"LuaJIT core/library version mismatch\")\n\n", LUAJIT_VERSION); 332 fprintf(ctx->fp, "assert(require(\"jit\").version == \"%s\", \"LuaJIT core/library version mismatch\")\n\n", LUAJIT_VERSION);
324 fprintf(ctx->fp, "module(...)\n\n"); 333 fprintf(ctx->fp, "return {\n\n");
325 334
326 fprintf(ctx->fp, "bcnames = \""); 335 fprintf(ctx->fp, "bcnames = \"");
327 for (i = 0; bc_names[i]; i++) fprintf(ctx->fp, "%-6s", bc_names[i]); 336 for (i = 0; bc_names[i]; i++) fprintf(ctx->fp, "%-6s", bc_names[i]);
328 fprintf(ctx->fp, "\"\n\n"); 337 fprintf(ctx->fp, "\",\n\n");
329 338
339#if LJ_HASJIT
330 fprintf(ctx->fp, "irnames = \""); 340 fprintf(ctx->fp, "irnames = \"");
331 for (i = 0; ir_names[i]; i++) fprintf(ctx->fp, "%-6s", ir_names[i]); 341 for (i = 0; ir_names[i]; i++) fprintf(ctx->fp, "%-6s", ir_names[i]);
332 fprintf(ctx->fp, "\"\n\n"); 342 fprintf(ctx->fp, "\",\n\n");
333 343
334 fprintf(ctx->fp, "irfpm = { [0]="); 344 fprintf(ctx->fp, "irfpm = { [0]=");
335 for (i = 0; irfpm_names[i]; i++) 345 for (i = 0; irfpm_names[i]; i++)
336 fprintf(ctx->fp, "\"%s\", ", lower(buf, irfpm_names[i])); 346 fprintf(ctx->fp, "\"%s\", ", lower(buf, irfpm_names[i]));
337 fprintf(ctx->fp, "}\n\n"); 347 fprintf(ctx->fp, "},\n\n");
338 348
339 fprintf(ctx->fp, "irfield = { [0]="); 349 fprintf(ctx->fp, "irfield = { [0]=");
340 for (i = 0; irfield_names[i]; i++) { 350 for (i = 0; irfield_names[i]; i++) {
@@ -344,17 +354,18 @@ static void emit_vmdef(BuildCtx *ctx)
344 if (p) *p = '.'; 354 if (p) *p = '.';
345 fprintf(ctx->fp, "\"%s\", ", buf); 355 fprintf(ctx->fp, "\"%s\", ", buf);
346 } 356 }
347 fprintf(ctx->fp, "}\n\n"); 357 fprintf(ctx->fp, "},\n\n");
348 358
349 fprintf(ctx->fp, "ircall = {\n[0]="); 359 fprintf(ctx->fp, "ircall = {\n[0]=");
350 for (i = 0; ircall_names[i]; i++) 360 for (i = 0; ircall_names[i]; i++)
351 fprintf(ctx->fp, "\"%s\",\n", ircall_names[i]); 361 fprintf(ctx->fp, "\"%s\",\n", ircall_names[i]);
352 fprintf(ctx->fp, "}\n\n"); 362 fprintf(ctx->fp, "},\n\n");
353 363
354 fprintf(ctx->fp, "traceerr = {\n[0]="); 364 fprintf(ctx->fp, "traceerr = {\n[0]=");
355 for (i = 0; trace_errors[i]; i++) 365 for (i = 0; trace_errors[i]; i++)
356 fprintf(ctx->fp, "\"%s\",\n", trace_errors[i]); 366 fprintf(ctx->fp, "\"%s\",\n", trace_errors[i]);
357 fprintf(ctx->fp, "}\n\n"); 367 fprintf(ctx->fp, "},\n\n");
368#endif
358} 369}
359 370
360/* -- Argument parsing ---------------------------------------------------- */ 371/* -- Argument parsing ---------------------------------------------------- */
@@ -491,6 +502,7 @@ int main(int argc, char **argv)
491 case BUILD_vmdef: 502 case BUILD_vmdef:
492 emit_vmdef(ctx); 503 emit_vmdef(ctx);
493 emit_lib(ctx); 504 emit_lib(ctx);
505 fprintf(ctx->fp, "}\n\n");
494 break; 506 break;
495 case BUILD_ffdef: 507 case BUILD_ffdef:
496 case BUILD_libdef: 508 case BUILD_libdef:
diff --git a/src/host/buildvm.h b/src/host/buildvm.h
index ded45d94..add8ee15 100644
--- a/src/host/buildvm.h
+++ b/src/host/buildvm.h
@@ -82,6 +82,7 @@ typedef struct BuildCtx {
82 const char *beginsym; 82 const char *beginsym;
83 /* Strings generated by DynASM. */ 83 /* Strings generated by DynASM. */
84 const char *const *globnames; 84 const char *const *globnames;
85 const char *const *extnames;
85 const char *dasm_ident; 86 const char *dasm_ident;
86 const char *dasm_arch; 87 const char *dasm_arch;
87 /* Relocations. */ 88 /* Relocations. */
diff --git a/src/host/buildvm_asm.c b/src/host/buildvm_asm.c
index 458ce733..e7c5de70 100644
--- a/src/host/buildvm_asm.c
+++ b/src/host/buildvm_asm.c
@@ -51,8 +51,8 @@ static const char *const jccnames[] = {
51 "js", "jns", "jpe", "jpo", "jl", "jge", "jle", "jg" 51 "js", "jns", "jpe", "jpo", "jl", "jge", "jle", "jg"
52}; 52};
53 53
54/* Emit relocation for the incredibly stupid OSX assembler. */ 54/* Emit x86/x64 text relocations. */
55static void emit_asm_reloc_mach(BuildCtx *ctx, uint8_t *cp, int n, 55static void emit_asm_reloc_text(BuildCtx *ctx, uint8_t *cp, int n,
56 const char *sym) 56 const char *sym)
57{ 57{
58 const char *opname = NULL; 58 const char *opname = NULL;
@@ -71,6 +71,20 @@ err:
71 exit(1); 71 exit(1);
72 } 72 }
73 emit_asm_bytes(ctx, cp, n); 73 emit_asm_bytes(ctx, cp, n);
74 if (strncmp(sym+(*sym == '_'), LABEL_PREFIX, sizeof(LABEL_PREFIX)-1)) {
75 /* Various fixups for external symbols outside of our binary. */
76 if (ctx->mode == BUILD_elfasm) {
77 if (LJ_32)
78 fprintf(ctx->fp, "#if __PIC__\n\t%s lj_wrap_%s\n#else\n", opname, sym);
79 fprintf(ctx->fp, "\t%s %s@PLT\n", opname, sym);
80 if (LJ_32)
81 fprintf(ctx->fp, "#endif\n");
82 return;
83 } else if (LJ_32 && ctx->mode == BUILD_machasm) {
84 fprintf(ctx->fp, "\t%s L%s$stub\n", opname, sym);
85 return;
86 }
87 }
74 fprintf(ctx->fp, "\t%s %s\n", opname, sym); 88 fprintf(ctx->fp, "\t%s %s\n", opname, sym);
75} 89}
76#else 90#else
@@ -79,10 +93,14 @@ static void emit_asm_words(BuildCtx *ctx, uint8_t *p, int n)
79{ 93{
80 int i; 94 int i;
81 for (i = 0; i < n; i += 4) { 95 for (i = 0; i < n; i += 4) {
96 uint32_t ins = *(uint32_t *)(p+i);
97#if LJ_TARGET_ARM64 && LJ_BE
98 ins = lj_bswap(ins); /* ARM64 instructions are always little-endian. */
99#endif
82 if ((i & 15) == 0) 100 if ((i & 15) == 0)
83 fprintf(ctx->fp, "\t.long 0x%08x", *(uint32_t *)(p+i)); 101 fprintf(ctx->fp, "\t.long 0x%08x", ins);
84 else 102 else
85 fprintf(ctx->fp, ",0x%08x", *(uint32_t *)(p+i)); 103 fprintf(ctx->fp, ",0x%08x", ins);
86 if ((i & 15) == 12) putc('\n', ctx->fp); 104 if ((i & 15) == 12) putc('\n', ctx->fp);
87 } 105 }
88 if ((n & 15) != 0) putc('\n', ctx->fp); 106 if ((n & 15) != 0) putc('\n', ctx->fp);
@@ -107,7 +125,16 @@ static void emit_asm_wordreloc(BuildCtx *ctx, uint8_t *p, int n,
107 ins, sym); 125 ins, sym);
108 exit(1); 126 exit(1);
109 } 127 }
110#elif LJ_TARGET_PPC || LJ_TARGET_PPCSPE 128#elif LJ_TARGET_ARM64
129 if ((ins >> 26) == 0x25u) {
130 fprintf(ctx->fp, "\tbl %s\n", sym);
131 } else {
132 fprintf(stderr,
133 "Error: unsupported opcode %08x for %s symbol relocation.\n",
134 ins, sym);
135 exit(1);
136 }
137#elif LJ_TARGET_PPC
111#if LJ_TARGET_PS3 138#if LJ_TARGET_PS3
112#define TOCPREFIX "." 139#define TOCPREFIX "."
113#else 140#else
@@ -216,6 +243,12 @@ void emit_asm(BuildCtx *ctx)
216 243
217 fprintf(ctx->fp, "\t.file \"buildvm_%s.dasc\"\n", ctx->dasm_arch); 244 fprintf(ctx->fp, "\t.file \"buildvm_%s.dasc\"\n", ctx->dasm_arch);
218 fprintf(ctx->fp, "\t.text\n"); 245 fprintf(ctx->fp, "\t.text\n");
246#if LJ_TARGET_MIPS32 && !LJ_ABI_SOFTFP
247 fprintf(ctx->fp, "\t.module fp=32\n");
248#endif
249#if LJ_TARGET_MIPS
250 fprintf(ctx->fp, "\t.set nomips16\n\t.abicalls\n\t.set noreorder\n\t.set nomacro\n");
251#endif
219 emit_asm_align(ctx, 4); 252 emit_asm_align(ctx, 4);
220 253
221#if LJ_TARGET_PS3 254#if LJ_TARGET_PS3
@@ -228,13 +261,19 @@ void emit_asm(BuildCtx *ctx)
228 261
229#if LJ_TARGET_ARM && defined(__GNUC__) && !LJ_NO_UNWIND 262#if LJ_TARGET_ARM && defined(__GNUC__) && !LJ_NO_UNWIND
230 /* This should really be moved into buildvm_arm.dasc. */ 263 /* This should really be moved into buildvm_arm.dasc. */
264#if LJ_ARCH_HASFPU
265 fprintf(ctx->fp,
266 ".fnstart\n"
267 ".save {r5, r6, r7, r8, r9, r10, r11, lr}\n"
268 ".vsave {d8-d15}\n"
269 ".save {r4}\n"
270 ".pad #28\n");
271#else
231 fprintf(ctx->fp, 272 fprintf(ctx->fp,
232 ".fnstart\n" 273 ".fnstart\n"
233 ".save {r4, r5, r6, r7, r8, r9, r10, r11, lr}\n" 274 ".save {r4, r5, r6, r7, r8, r9, r10, r11, lr}\n"
234 ".pad #28\n"); 275 ".pad #28\n");
235#endif 276#endif
236#if LJ_TARGET_MIPS
237 fprintf(ctx->fp, ".set nomips16\n.abicalls\n.set noreorder\n.set nomacro\n");
238#endif 277#endif
239 278
240 for (i = rel = 0; i < ctx->nsym; i++) { 279 for (i = rel = 0; i < ctx->nsym; i++) {
@@ -255,8 +294,9 @@ void emit_asm(BuildCtx *ctx)
255 BuildReloc *r = &ctx->reloc[rel]; 294 BuildReloc *r = &ctx->reloc[rel];
256 int n = r->ofs - ofs; 295 int n = r->ofs - ofs;
257#if LJ_TARGET_X86ORX64 296#if LJ_TARGET_X86ORX64
258 if (ctx->mode == BUILD_machasm && r->type != 0) { 297 if (r->type != 0 &&
259 emit_asm_reloc_mach(ctx, ctx->code+ofs, n, ctx->relocsym[r->sym]); 298 (ctx->mode == BUILD_elfasm || ctx->mode == BUILD_machasm)) {
299 emit_asm_reloc_text(ctx, ctx->code+ofs, n, ctx->relocsym[r->sym]);
260 } else { 300 } else {
261 emit_asm_bytes(ctx, ctx->code+ofs, n); 301 emit_asm_bytes(ctx, ctx->code+ofs, n);
262 emit_asm_reloc(ctx, r->type, ctx->relocsym[r->sym]); 302 emit_asm_reloc(ctx, r->type, ctx->relocsym[r->sym]);
@@ -290,10 +330,7 @@ void emit_asm(BuildCtx *ctx)
290#if !(LJ_TARGET_PS3 || LJ_TARGET_PSVITA) 330#if !(LJ_TARGET_PS3 || LJ_TARGET_PSVITA)
291 fprintf(ctx->fp, "\t.section .note.GNU-stack,\"\"," ELFASM_PX "progbits\n"); 331 fprintf(ctx->fp, "\t.section .note.GNU-stack,\"\"," ELFASM_PX "progbits\n");
292#endif 332#endif
293#if LJ_TARGET_PPCSPE 333#if LJ_TARGET_PPC && !LJ_TARGET_PS3 && !LJ_ABI_SOFTFP
294 /* Soft-float ABI + SPE. */
295 fprintf(ctx->fp, "\t.gnu_attribute 4, 2\n\t.gnu_attribute 8, 3\n");
296#elif LJ_TARGET_PPC && !LJ_TARGET_PS3
297 /* Hard-float ABI. */ 334 /* Hard-float ABI. */
298 fprintf(ctx->fp, "\t.gnu_attribute 4, 1\n"); 335 fprintf(ctx->fp, "\t.gnu_attribute 4, 1\n");
299#endif 336#endif
diff --git a/src/host/buildvm_fold.c b/src/host/buildvm_fold.c
index 388a8146..cc392e93 100644
--- a/src/host/buildvm_fold.c
+++ b/src/host/buildvm_fold.c
@@ -5,6 +5,7 @@
5 5
6#include "buildvm.h" 6#include "buildvm.h"
7#include "lj_obj.h" 7#include "lj_obj.h"
8#if LJ_HASJIT
8#include "lj_ir.h" 9#include "lj_ir.h"
9 10
10/* Context for the folding hash table generator. */ 11/* Context for the folding hash table generator. */
@@ -226,4 +227,10 @@ void emit_fold(BuildCtx *ctx)
226 227
227 makehash(ctx); 228 makehash(ctx);
228} 229}
230#else
231void emit_fold(BuildCtx *ctx)
232{
233 UNUSED(ctx);
234}
235#endif
229 236
diff --git a/src/host/buildvm_lib.c b/src/host/buildvm_lib.c
index 36797e4c..99d12a27 100644
--- a/src/host/buildvm_lib.c
+++ b/src/host/buildvm_lib.c
@@ -5,7 +5,9 @@
5 5
6#include "buildvm.h" 6#include "buildvm.h"
7#include "lj_obj.h" 7#include "lj_obj.h"
8#include "lj_bc.h"
8#include "lj_lib.h" 9#include "lj_lib.h"
10#include "buildvm_libbc.h"
9 11
10/* Context for library definitions. */ 12/* Context for library definitions. */
11static uint8_t obuf[8192]; 13static uint8_t obuf[8192];
@@ -151,6 +153,62 @@ static void libdef_func(BuildCtx *ctx, char *p, int arg)
151 regfunc = REGFUNC_OK; 153 regfunc = REGFUNC_OK;
152} 154}
153 155
156static 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
167static 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
189static 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
154static uint32_t find_rec(char *name) 212static uint32_t find_rec(char *name)
155{ 213{
156 char *p = (char *)obuf; 214 char *p = (char *)obuf;
@@ -277,6 +335,7 @@ static const LibDefHandler libdef_handlers[] = {
277 { "CF(", ")", libdef_func, LIBINIT_CF }, 335 { "CF(", ")", libdef_func, LIBINIT_CF },
278 { "ASM(", ")", libdef_func, LIBINIT_ASM }, 336 { "ASM(", ")", libdef_func, LIBINIT_ASM },
279 { "ASM_(", ")", libdef_func, LIBINIT_ASM_ }, 337 { "ASM_(", ")", libdef_func, LIBINIT_ASM_ },
338 { "LUA(", ")", libdef_lua, 0 },
280 { "REC(", ")", libdef_rec, 0 }, 339 { "REC(", ")", libdef_rec, 0 },
281 { "PUSH(", ")", libdef_push, 0 }, 340 { "PUSH(", ")", libdef_push, 0 },
282 { "SET(", ")", libdef_set, 0 }, 341 { "SET(", ")", libdef_set, 0 },
@@ -333,6 +392,8 @@ void emit_lib(BuildCtx *ctx)
333 ok = LJ_HASJIT; 392 ok = LJ_HASJIT;
334 else if (!strcmp(buf, "#if LJ_HASFFI")) 393 else if (!strcmp(buf, "#if LJ_HASFFI"))
335 ok = LJ_HASFFI; 394 ok = LJ_HASFFI;
395 else if (!strcmp(buf, "#if LJ_HASBUFFER"))
396 ok = LJ_HASBUFFER;
336 if (!ok) { 397 if (!ok) {
337 int lvl = 1; 398 int lvl = 1;
338 while (fgets(buf, sizeof(buf), fp) != NULL) { 399 while (fgets(buf, sizeof(buf), fp) != NULL) {
@@ -380,7 +441,7 @@ void emit_lib(BuildCtx *ctx)
380 "#ifndef FF_NUM_ASMFUNC\n#define FF_NUM_ASMFUNC %d\n#endif\n\n", 441 "#ifndef FF_NUM_ASMFUNC\n#define FF_NUM_ASMFUNC %d\n#endif\n\n",
381 ffasmfunc); 442 ffasmfunc);
382 } else if (ctx->mode == BUILD_vmdef) { 443 } else if (ctx->mode == BUILD_vmdef) {
383 fprintf(ctx->fp, "}\n\n"); 444 fprintf(ctx->fp, "},\n\n");
384 } else if (ctx->mode == BUILD_bcdef) { 445 } else if (ctx->mode == BUILD_bcdef) {
385 int i; 446 int i;
386 fprintf(ctx->fp, "\n};\n\n"); 447 fprintf(ctx->fp, "\n};\n\n");
diff --git a/src/host/buildvm_libbc.h b/src/host/buildvm_libbc.h
new file mode 100644
index 00000000..276463b2
--- /dev/null
+++ b/src/host/buildvm_libbc.h
@@ -0,0 +1,81 @@
1/* This is a generated file. DO NOT EDIT! */
2
3static const int libbc_endian = 0;
4
5static const uint8_t libbc_code[] = {
6#if LJ_FR2
7/* math.deg */ 0,1,2,0,0,1,2,BC_MULVN,1,0,0,BC_RET1,1,2,0,241,135,158,166,3,
8220,203,178,130,4,
9/* math.rad */ 0,1,2,0,0,1,2,BC_MULVN,1,0,0,BC_RET1,1,2,0,243,244,148,165,20,
10198,190,199,252,3,
11/* string.len */ 0,1,2,0,0,0,3,BC_ISTYPE,0,5,0,BC_LEN,1,0,0,BC_RET1,1,2,0,
12/* table.foreachi */ 0,2,10,0,0,0,15,BC_ISTYPE,0,12,0,BC_ISTYPE,1,9,0,
13BC_KSHORT,2,1,0,BC_LEN,3,0,0,BC_KSHORT,4,1,0,BC_FORI,2,8,128,BC_MOV,6,1,0,
14BC_MOV,8,5,0,BC_TGETR,9,5,0,BC_CALL,6,3,2,BC_ISEQP,6,0,0,BC_JMP,7,1,128,
15BC_RET1,6,2,0,BC_FORL,2,248,127,BC_RET0,0,1,0,
16/* table.foreach */ 0,2,11,0,0,1,16,BC_ISTYPE,0,12,0,BC_ISTYPE,1,9,0,BC_KPRI,
172,0,0,BC_MOV,3,0,0,BC_KNUM,4,0,0,BC_JMP,5,7,128,BC_MOV,7,1,0,BC_MOV,9,5,0,
18BC_MOV,10,6,0,BC_CALL,7,3,2,BC_ISEQP,7,0,0,BC_JMP,8,1,128,BC_RET1,7,2,0,
19BC_ITERN,5,3,3,BC_ITERL,5,247,127,BC_RET0,0,1,0,1,255,255,249,255,15,
20/* table.getn */ 0,1,2,0,0,0,3,BC_ISTYPE,0,12,0,BC_LEN,1,0,0,BC_RET1,1,2,0,
21/* table.remove */ 0,2,10,0,0,2,30,BC_ISTYPE,0,12,0,BC_LEN,2,0,0,BC_ISNEP,1,0,
220,BC_JMP,3,7,128,BC_ISEQN,2,0,0,BC_JMP,3,23,128,BC_TGETR,3,2,0,BC_KPRI,4,0,0,
23BC_TSETR,4,2,0,BC_RET1,3,2,0,BC_JMP,3,18,128,BC_ISTYPE,1,14,0,BC_KSHORT,3,1,0,
24BC_ISGT,3,1,0,BC_JMP,3,14,128,BC_ISGT,1,2,0,BC_JMP,3,12,128,BC_TGETR,3,1,0,
25BC_ADDVN,4,1,1,BC_MOV,5,2,0,BC_KSHORT,6,1,0,BC_FORI,4,4,128,BC_SUBVN,8,1,7,
26BC_TGETR,9,7,0,BC_TSETR,9,8,0,BC_FORL,4,252,127,BC_KPRI,4,0,0,BC_TSETR,4,2,0,
27BC_RET1,3,2,0,BC_RET0,0,1,0,0,2,
28/* table.move */ 0,5,12,0,0,0,35,BC_ISTYPE,0,12,0,BC_ISTYPE,1,14,0,BC_ISTYPE,
292,14,0,BC_ISTYPE,3,14,0,BC_ISNEP,4,0,0,BC_JMP,5,1,128,BC_MOV,4,0,0,BC_ISTYPE,
304,12,0,BC_ISGT,1,2,0,BC_JMP,5,24,128,BC_SUBVV,5,1,3,BC_ISLT,2,3,0,BC_JMP,6,4,
31128,BC_ISLE,3,1,0,BC_JMP,6,2,128,BC_ISEQV,4,0,0,BC_JMP,6,9,128,BC_MOV,6,1,0,
32BC_MOV,7,2,0,BC_KSHORT,8,1,0,BC_FORI,6,4,128,BC_ADDVV,10,5,9,BC_TGETR,11,9,0,
33BC_TSETR,11,10,4,BC_FORL,6,252,127,BC_JMP,6,8,128,BC_MOV,6,2,0,BC_MOV,7,1,0,
34BC_KSHORT,8,255,255,BC_FORI,6,4,128,BC_ADDVV,10,5,9,BC_TGETR,11,9,0,BC_TSETR,
3511,10,4,BC_FORL,6,252,127,BC_RET1,4,2,0,
36#else
37/* math.deg */ 0,1,2,0,0,1,2,BC_MULVN,1,0,0,BC_RET1,1,2,0,241,135,158,166,3,
38220,203,178,130,4,
39/* math.rad */ 0,1,2,0,0,1,2,BC_MULVN,1,0,0,BC_RET1,1,2,0,243,244,148,165,20,
40198,190,199,252,3,
41/* string.len */ 0,1,2,0,0,0,3,BC_ISTYPE,0,5,0,BC_LEN,1,0,0,BC_RET1,1,2,0,
42/* table.foreachi */ 0,2,9,0,0,0,15,BC_ISTYPE,0,12,0,BC_ISTYPE,1,9,0,
43BC_KSHORT,2,1,0,BC_LEN,3,0,0,BC_KSHORT,4,1,0,BC_FORI,2,8,128,BC_MOV,6,1,0,
44BC_MOV,7,5,0,BC_TGETR,8,5,0,BC_CALL,6,3,2,BC_ISEQP,6,0,0,BC_JMP,7,1,128,
45BC_RET1,6,2,0,BC_FORL,2,248,127,BC_RET0,0,1,0,
46/* table.foreach */ 0,2,10,0,0,1,16,BC_ISTYPE,0,12,0,BC_ISTYPE,1,9,0,BC_KPRI,
472,0,0,BC_MOV,3,0,0,BC_KNUM,4,0,0,BC_JMP,5,7,128,BC_MOV,7,1,0,BC_MOV,8,5,0,
48BC_MOV,9,6,0,BC_CALL,7,3,2,BC_ISEQP,7,0,0,BC_JMP,8,1,128,BC_RET1,7,2,0,
49BC_ITERN,5,3,3,BC_ITERL,5,247,127,BC_RET0,0,1,0,1,255,255,249,255,15,
50/* table.getn */ 0,1,2,0,0,0,3,BC_ISTYPE,0,12,0,BC_LEN,1,0,0,BC_RET1,1,2,0,
51/* table.remove */ 0,2,10,0,0,2,30,BC_ISTYPE,0,12,0,BC_LEN,2,0,0,BC_ISNEP,1,0,
520,BC_JMP,3,7,128,BC_ISEQN,2,0,0,BC_JMP,3,23,128,BC_TGETR,3,2,0,BC_KPRI,4,0,0,
53BC_TSETR,4,2,0,BC_RET1,3,2,0,BC_JMP,3,18,128,BC_ISTYPE,1,14,0,BC_KSHORT,3,1,0,
54BC_ISGT,3,1,0,BC_JMP,3,14,128,BC_ISGT,1,2,0,BC_JMP,3,12,128,BC_TGETR,3,1,0,
55BC_ADDVN,4,1,1,BC_MOV,5,2,0,BC_KSHORT,6,1,0,BC_FORI,4,4,128,BC_SUBVN,8,1,7,
56BC_TGETR,9,7,0,BC_TSETR,9,8,0,BC_FORL,4,252,127,BC_KPRI,4,0,0,BC_TSETR,4,2,0,
57BC_RET1,3,2,0,BC_RET0,0,1,0,0,2,
58/* table.move */ 0,5,12,0,0,0,35,BC_ISTYPE,0,12,0,BC_ISTYPE,1,14,0,BC_ISTYPE,
592,14,0,BC_ISTYPE,3,14,0,BC_ISNEP,4,0,0,BC_JMP,5,1,128,BC_MOV,4,0,0,BC_ISTYPE,
604,12,0,BC_ISGT,1,2,0,BC_JMP,5,24,128,BC_SUBVV,5,1,3,BC_ISLT,2,3,0,BC_JMP,6,4,
61128,BC_ISLE,3,1,0,BC_JMP,6,2,128,BC_ISEQV,4,0,0,BC_JMP,6,9,128,BC_MOV,6,1,0,
62BC_MOV,7,2,0,BC_KSHORT,8,1,0,BC_FORI,6,4,128,BC_ADDVV,10,5,9,BC_TGETR,11,9,0,
63BC_TSETR,11,10,4,BC_FORL,6,252,127,BC_JMP,6,8,128,BC_MOV,6,2,0,BC_MOV,7,1,0,
64BC_KSHORT,8,255,255,BC_FORI,6,4,128,BC_ADDVV,10,5,9,BC_TGETR,11,9,0,BC_TSETR,
6511,10,4,BC_FORL,6,252,127,BC_RET1,4,2,0,
66#endif
670
68};
69
70static const struct { const char *name; int ofs; } libbc_map[] = {
71{"math_deg",0},
72{"math_rad",25},
73{"string_len",50},
74{"table_foreachi",69},
75{"table_foreach",136},
76{"table_getn",213},
77{"table_remove",232},
78{"table_move",361},
79{NULL,508}
80};
81
diff --git a/src/host/buildvm_peobj.c b/src/host/buildvm_peobj.c
index 4fbc11b9..5bca6df8 100644
--- a/src/host/buildvm_peobj.c
+++ b/src/host/buildvm_peobj.c
@@ -9,7 +9,7 @@
9#include "buildvm.h" 9#include "buildvm.h"
10#include "lj_bc.h" 10#include "lj_bc.h"
11 11
12#if LJ_TARGET_X86ORX64 || LJ_TARGET_PPC 12#if LJ_TARGET_X86ORX64
13 13
14/* Context for PE object emitter. */ 14/* Context for PE object emitter. */
15static char *strtab; 15static char *strtab;
@@ -93,12 +93,6 @@ typedef struct PEsymaux {
93#define PEOBJ_RELOC_ADDR32NB 0x03 93#define PEOBJ_RELOC_ADDR32NB 0x03
94#define PEOBJ_RELOC_OFS 0 94#define PEOBJ_RELOC_OFS 0
95#define PEOBJ_TEXT_FLAGS 0x60500020 /* 60=r+x, 50=align16, 20=code. */ 95#define PEOBJ_TEXT_FLAGS 0x60500020 /* 60=r+x, 50=align16, 20=code. */
96#elif LJ_TARGET_PPC
97#define PEOBJ_ARCH_TARGET 0x01f2
98#define PEOBJ_RELOC_REL32 0x06
99#define PEOBJ_RELOC_DIR32 0x02
100#define PEOBJ_RELOC_OFS (-4)
101#define PEOBJ_TEXT_FLAGS 0x60400020 /* 60=r+x, 40=align8, 20=code. */
102#endif 96#endif
103 97
104/* Section numbers (0-based). */ 98/* Section numbers (0-based). */
@@ -109,6 +103,8 @@ enum {
109#if LJ_TARGET_X64 103#if LJ_TARGET_X64
110 PEOBJ_SECT_PDATA, 104 PEOBJ_SECT_PDATA,
111 PEOBJ_SECT_XDATA, 105 PEOBJ_SECT_XDATA,
106#elif LJ_TARGET_X86
107 PEOBJ_SECT_SXDATA,
112#endif 108#endif
113 PEOBJ_SECT_RDATA_Z, 109 PEOBJ_SECT_RDATA_Z,
114 PEOBJ_NSECTIONS 110 PEOBJ_NSECTIONS
@@ -208,6 +204,13 @@ void emit_peobj(BuildCtx *ctx)
208 sofs += (pesect[PEOBJ_SECT_XDATA].nreloc = 1) * PEOBJ_RELOC_SIZE; 204 sofs += (pesect[PEOBJ_SECT_XDATA].nreloc = 1) * PEOBJ_RELOC_SIZE;
209 /* Flags: 40 = read, 30 = align4, 40 = initialized data. */ 205 /* Flags: 40 = read, 30 = align4, 40 = initialized data. */
210 pesect[PEOBJ_SECT_XDATA].flags = 0x40300040; 206 pesect[PEOBJ_SECT_XDATA].flags = 0x40300040;
207#elif LJ_TARGET_X86
208 memcpy(pesect[PEOBJ_SECT_SXDATA].name, ".sxdata", sizeof(".sxdata")-1);
209 pesect[PEOBJ_SECT_SXDATA].ofs = sofs;
210 sofs += (pesect[PEOBJ_SECT_SXDATA].size = 4);
211 pesect[PEOBJ_SECT_SXDATA].relocofs = sofs;
212 /* Flags: 40 = read, 30 = align4, 02 = lnk_info, 40 = initialized data. */
213 pesect[PEOBJ_SECT_SXDATA].flags = 0x40300240;
211#endif 214#endif
212 215
213 memcpy(pesect[PEOBJ_SECT_RDATA_Z].name, ".rdata$Z", sizeof(".rdata$Z")-1); 216 memcpy(pesect[PEOBJ_SECT_RDATA_Z].name, ".rdata$Z", sizeof(".rdata$Z")-1);
@@ -232,7 +235,7 @@ void emit_peobj(BuildCtx *ctx)
232 nrsym = ctx->nrelocsym; 235 nrsym = ctx->nrelocsym;
233 pehdr.nsyms = 1+PEOBJ_NSECTIONS*2 + 1+ctx->nsym + nrsym; 236 pehdr.nsyms = 1+PEOBJ_NSECTIONS*2 + 1+ctx->nsym + nrsym;
234#if LJ_TARGET_X64 237#if LJ_TARGET_X64
235 pehdr.nsyms += 1; /* Symbol for lj_err_unwind_win64. */ 238 pehdr.nsyms += 1; /* Symbol for lj_err_unwind_win. */
236#endif 239#endif
237 240
238 /* Write PE object header and all sections. */ 241 /* Write PE object header and all sections. */
@@ -242,15 +245,8 @@ void emit_peobj(BuildCtx *ctx)
242 /* Write .text section. */ 245 /* Write .text section. */
243 host_endian.u = 1; 246 host_endian.u = 1;
244 if (host_endian.b != LJ_ENDIAN_SELECT(1, 0)) { 247 if (host_endian.b != LJ_ENDIAN_SELECT(1, 0)) {
245#if LJ_TARGET_PPC
246 uint32_t *p = (uint32_t *)ctx->code;
247 int n = (int)(ctx->codesz >> 2);
248 for (i = 0; i < n; i++, p++)
249 *p = lj_bswap(*p); /* Byteswap .text section. */
250#else
251 fprintf(stderr, "Error: different byte order for host and target\n"); 248 fprintf(stderr, "Error: different byte order for host and target\n");
252 exit(1); 249 exit(1);
253#endif
254 } 250 }
255 owrite(ctx, ctx->code, ctx->codesz); 251 owrite(ctx, ctx->code, ctx->codesz);
256 for (i = 0; i < ctx->nreloc; i++) { 252 for (i = 0; i < ctx->nreloc; i++) {
@@ -312,6 +308,19 @@ void emit_peobj(BuildCtx *ctx)
312 reloc.type = PEOBJ_RELOC_ADDR32NB; 308 reloc.type = PEOBJ_RELOC_ADDR32NB;
313 owrite(ctx, &reloc, PEOBJ_RELOC_SIZE); 309 owrite(ctx, &reloc, PEOBJ_RELOC_SIZE);
314 } 310 }
311#elif LJ_TARGET_X86
312 /* Write .sxdata section. */
313 for (i = 0; i < nrsym; i++) {
314 if (!strcmp(ctx->relocsym[i], "_lj_err_unwind_win")) {
315 uint32_t symidx = 1+2+i;
316 owrite(ctx, &symidx, 4);
317 break;
318 }
319 }
320 if (i == nrsym) {
321 fprintf(stderr, "Error: extern lj_err_unwind_win not used\n");
322 exit(1);
323 }
315#endif 324#endif
316 325
317 /* Write .rdata$Z section. */ 326 /* Write .rdata$Z section. */
@@ -333,8 +342,10 @@ void emit_peobj(BuildCtx *ctx)
333#if LJ_TARGET_X64 342#if LJ_TARGET_X64
334 emit_peobj_sym_sect(ctx, pesect, PEOBJ_SECT_PDATA); 343 emit_peobj_sym_sect(ctx, pesect, PEOBJ_SECT_PDATA);
335 emit_peobj_sym_sect(ctx, pesect, PEOBJ_SECT_XDATA); 344 emit_peobj_sym_sect(ctx, pesect, PEOBJ_SECT_XDATA);
336 emit_peobj_sym(ctx, "lj_err_unwind_win64", 0, 345 emit_peobj_sym(ctx, "lj_err_unwind_win", 0,
337 PEOBJ_SECT_UNDEF, PEOBJ_TYPE_FUNC, PEOBJ_SCL_EXTERN); 346 PEOBJ_SECT_UNDEF, PEOBJ_TYPE_FUNC, PEOBJ_SCL_EXTERN);
347#elif LJ_TARGET_X86
348 emit_peobj_sym_sect(ctx, pesect, PEOBJ_SECT_SXDATA);
338#endif 349#endif
339 350
340 emit_peobj_sym(ctx, ctx->beginsym, 0, 351 emit_peobj_sym(ctx, ctx->beginsym, 0,
diff --git a/src/host/genlibbc.lua b/src/host/genlibbc.lua
new file mode 100644
index 00000000..3621c3f5
--- /dev/null
+++ b/src/host/genlibbc.lua
@@ -0,0 +1,225 @@
1----------------------------------------------------------------------------
2-- Lua script to dump the bytecode of the library functions written in Lua.
3-- The resulting 'buildvm_libbc.h' is used for the build process of LuaJIT.
4----------------------------------------------------------------------------
5-- Copyright (C) 2005-2023 Mike Pall. All rights reserved.
6-- Released under the MIT license. See Copyright Notice in luajit.h
7----------------------------------------------------------------------------
8
9local ffi = require("ffi")
10local bit = require("bit")
11local vmdef = require("jit.vmdef")
12local bcnames = vmdef.bcnames
13
14local format = string.format
15
16local isbe = (string.byte(string.dump(function() end), 5) % 2 == 1)
17
18local function usage(arg)
19 io.stderr:write("Usage: ", arg and arg[0] or "genlibbc",
20 " [-o buildvm_libbc.h] lib_*.c\n")
21 os.exit(1)
22end
23
24local function parse_arg(arg)
25 local outfile = "-"
26 if not (arg and arg[1]) then
27 usage(arg)
28 end
29 if arg[1] == "-o" then
30 outfile = arg[2]
31 if not outfile then usage(arg) end
32 table.remove(arg, 1)
33 table.remove(arg, 1)
34 end
35 return outfile
36end
37
38local function read_files(names)
39 local src = ""
40 for _,name in ipairs(names) do
41 local fp = assert(io.open(name))
42 src = src .. fp:read("*a")
43 fp:close()
44 end
45 return src
46end
47
48local function transform_lua(code)
49 local fixup = {}
50 local n = -30000
51 code = string.gsub(code, "CHECK_(%w*)%((.-)%)", function(tp, var)
52 n = n + 1
53 fixup[n] = { "CHECK", tp }
54 return format("%s=%d", var, n)
55 end)
56 code = string.gsub(code, "PAIRS%((.-)%)", function(var)
57 fixup.PAIRS = true
58 return format("nil, %s, 0x4dp80", var)
59 end)
60 return "return "..code, fixup
61end
62
63local function read_uleb128(p)
64 local v = p[0]; p = p + 1
65 if v >= 128 then
66 local sh = 7; v = v - 128
67 repeat
68 local r = p[0]
69 v = v + bit.lshift(bit.band(r, 127), sh)
70 sh = sh + 7
71 p = p + 1
72 until r < 128
73 end
74 return p, v
75end
76
77-- ORDER LJ_T
78local name2itype = {
79 str = 5, func = 9, tab = 12, int = 14, num = 15
80}
81
82local BC, BCN = {}, {}
83for i=0,#bcnames/6-1 do
84 local name = bcnames:sub(i*6+1, i*6+6):gsub(" ", "")
85 BC[name] = i
86 BCN[i] = name
87end
88local xop, xra = isbe and 3 or 0, isbe and 2 or 1
89local xrc, xrb = isbe and 1 or 2, isbe and 0 or 3
90
91local function fixup_dump(dump, fixup)
92 local buf = ffi.new("uint8_t[?]", #dump+1, dump)
93 local p = buf+5
94 local n, sizebc
95 p, n = read_uleb128(p)
96 local start = p
97 p = p + 4
98 p = read_uleb128(p)
99 p = read_uleb128(p)
100 p, sizebc = read_uleb128(p)
101 local startbc = tonumber(p - start)
102 local rawtab = {}
103 for i=0,sizebc-1 do
104 local op = p[xop]
105 if op == BC.KSHORT then
106 local rd = p[xrc] + 256*p[xrb]
107 rd = bit.arshift(bit.lshift(rd, 16), 16)
108 local f = fixup[rd]
109 if f then
110 if f[1] == "CHECK" then
111 local tp = f[2]
112 if tp == "tab" then rawtab[p[xra]] = true end
113 p[xop] = tp == "num" and BC.ISNUM or BC.ISTYPE
114 p[xrb] = 0
115 p[xrc] = name2itype[tp]
116 else
117 error("unhandled fixup type: "..f[1])
118 end
119 end
120 elseif op == BC.TGETV then
121 if rawtab[p[xrb]] then
122 p[xop] = BC.TGETR
123 end
124 elseif op == BC.TSETV then
125 if rawtab[p[xrb]] then
126 p[xop] = BC.TSETR
127 end
128 elseif op == BC.ITERC then
129 if fixup.PAIRS then
130 p[xop] = BC.ITERN
131 end
132 end
133 p = p + 4
134 end
135 local ndump = ffi.string(start, n)
136 -- Fixup hi-part of 0x4dp80 to LJ_KEYINDEX.
137 ndump = ndump:gsub("\x80\x80\xcd\xaa\x04", "\xff\xff\xf9\xff\x0f")
138 return { dump = ndump, startbc = startbc, sizebc = sizebc }
139end
140
141local function find_defs(src)
142 local defs = {}
143 for name, code in string.gmatch(src, "LJLIB_LUA%(([^)]*)%)%s*/%*(.-)%*/") do
144 local env = {}
145 local tcode, fixup = transform_lua(code)
146 local func = assert(load(tcode, "", nil, env))()
147 defs[name] = fixup_dump(string.dump(func, true), fixup)
148 defs[#defs+1] = name
149 end
150 return defs
151end
152
153local function gen_header(defs)
154 local t = {}
155 local function w(x) t[#t+1] = x end
156 w("/* This is a generated file. DO NOT EDIT! */\n\n")
157 w("static const int libbc_endian = ") w(isbe and 1 or 0) w(";\n\n")
158 local s, sb = "", ""
159 for i,name in ipairs(defs) do
160 local d = defs[name]
161 s = s .. d.dump
162 sb = sb .. string.char(i) .. ("\0"):rep(d.startbc - 1)
163 .. (isbe and "\0\0\0\255" or "\255\0\0\0"):rep(d.sizebc)
164 .. ("\0"):rep(#d.dump - d.startbc - d.sizebc*4)
165 end
166 w("static const uint8_t libbc_code[] = {\n")
167 local n = 0
168 for i=1,#s do
169 local x = string.byte(s, i)
170 local xb = string.byte(sb, i)
171 if xb == 255 then
172 local name = BCN[x]
173 local m = #name + 4
174 if n + m > 78 then n = 0; w("\n") end
175 n = n + m
176 w("BC_"); w(name)
177 else
178 local m = x < 10 and 2 or (x < 100 and 3 or 4)
179 if xb == 0 then
180 if n + m > 78 then n = 0; w("\n") end
181 else
182 local name = defs[xb]:gsub("_", ".")
183 if n ~= 0 then w("\n") end
184 w("/* "); w(name); w(" */ ")
185 n = #name + 7
186 end
187 n = n + m
188 w(x)
189 end
190 w(",")
191 end
192 w("\n0\n};\n\n")
193 w("static const struct { const char *name; int ofs; } libbc_map[] = {\n")
194 local m = 0
195 for _,name in ipairs(defs) do
196 w('{"'); w(name); w('",'); w(m) w('},\n')
197 m = m + #defs[name].dump
198 end
199 w("{NULL,"); w(m); w("}\n};\n\n")
200 return table.concat(t)
201end
202
203local function write_file(name, data)
204 if name == "-" then
205 assert(io.write(data))
206 assert(io.flush())
207 else
208 local fp = io.open(name)
209 if fp then
210 local old = fp:read("*a")
211 fp:close()
212 if data == old then return end
213 end
214 fp = assert(io.open(name, "w"))
215 assert(fp:write(data))
216 assert(fp:close())
217 end
218end
219
220local outfile = parse_arg(arg)
221local src = read_files(arg)
222local defs = find_defs(src)
223local hdr = gen_header(defs)
224write_file(outfile, hdr)
225