diff options
Diffstat (limited to 'src/host')
-rw-r--r-- | src/host/buildvm.c | 36 | ||||
-rw-r--r-- | src/host/buildvm.h | 1 | ||||
-rw-r--r-- | src/host/buildvm_asm.c | 63 | ||||
-rw-r--r-- | src/host/buildvm_fold.c | 7 | ||||
-rw-r--r-- | src/host/buildvm_lib.c | 63 | ||||
-rw-r--r-- | src/host/buildvm_libbc.h | 81 | ||||
-rw-r--r-- | src/host/buildvm_peobj.c | 43 | ||||
-rw-r--r-- | src/host/genlibbc.lua | 225 |
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 | ||
252 | const char *const ir_names[] = { | 256 | const char *const ir_names[] = { |
253 | #define IRNAME(name, m, m1, m2) #name, | 257 | #define IRNAME(name, m, m1, m2) #name, |
254 | IRDEF(IRNAME) | 258 | IRDEF(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 | ||
293 | static const char *lower(char *buf, const char *s) | 299 | static 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. */ |
305 | static void emit_bcdef(BuildCtx *ctx) | 312 | static 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. */ |
318 | static void emit_vmdef(BuildCtx *ctx) | 325 | static 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. */ |
55 | static void emit_asm_reloc_mach(BuildCtx *ctx, uint8_t *cp, int n, | 55 | static 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 | ||
231 | void 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. */ |
11 | static uint8_t obuf[8192]; | 13 | static 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 | ||
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 | |||
154 | static uint32_t find_rec(char *name) | 212 | static 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 | |||
3 | static const int libbc_endian = 0; | ||
4 | |||
5 | static 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, | ||
8 | 220,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, | ||
10 | 198,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, | ||
13 | BC_KSHORT,2,1,0,BC_LEN,3,0,0,BC_KSHORT,4,1,0,BC_FORI,2,8,128,BC_MOV,6,1,0, | ||
14 | BC_MOV,8,5,0,BC_TGETR,9,5,0,BC_CALL,6,3,2,BC_ISEQP,6,0,0,BC_JMP,7,1,128, | ||
15 | BC_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, | ||
17 | 2,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, | ||
18 | BC_MOV,10,6,0,BC_CALL,7,3,2,BC_ISEQP,7,0,0,BC_JMP,8,1,128,BC_RET1,7,2,0, | ||
19 | BC_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, | ||
22 | 0,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, | ||
23 | BC_TSETR,4,2,0,BC_RET1,3,2,0,BC_JMP,3,18,128,BC_ISTYPE,1,14,0,BC_KSHORT,3,1,0, | ||
24 | BC_ISGT,3,1,0,BC_JMP,3,14,128,BC_ISGT,1,2,0,BC_JMP,3,12,128,BC_TGETR,3,1,0, | ||
25 | BC_ADDVN,4,1,1,BC_MOV,5,2,0,BC_KSHORT,6,1,0,BC_FORI,4,4,128,BC_SUBVN,8,1,7, | ||
26 | BC_TGETR,9,7,0,BC_TSETR,9,8,0,BC_FORL,4,252,127,BC_KPRI,4,0,0,BC_TSETR,4,2,0, | ||
27 | BC_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, | ||
29 | 2,14,0,BC_ISTYPE,3,14,0,BC_ISNEP,4,0,0,BC_JMP,5,1,128,BC_MOV,4,0,0,BC_ISTYPE, | ||
30 | 4,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, | ||
31 | 128,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, | ||
32 | BC_MOV,7,2,0,BC_KSHORT,8,1,0,BC_FORI,6,4,128,BC_ADDVV,10,5,9,BC_TGETR,11,9,0, | ||
33 | BC_TSETR,11,10,4,BC_FORL,6,252,127,BC_JMP,6,8,128,BC_MOV,6,2,0,BC_MOV,7,1,0, | ||
34 | BC_KSHORT,8,255,255,BC_FORI,6,4,128,BC_ADDVV,10,5,9,BC_TGETR,11,9,0,BC_TSETR, | ||
35 | 11,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, | ||
38 | 220,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, | ||
40 | 198,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, | ||
43 | BC_KSHORT,2,1,0,BC_LEN,3,0,0,BC_KSHORT,4,1,0,BC_FORI,2,8,128,BC_MOV,6,1,0, | ||
44 | BC_MOV,7,5,0,BC_TGETR,8,5,0,BC_CALL,6,3,2,BC_ISEQP,6,0,0,BC_JMP,7,1,128, | ||
45 | BC_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, | ||
47 | 2,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, | ||
48 | BC_MOV,9,6,0,BC_CALL,7,3,2,BC_ISEQP,7,0,0,BC_JMP,8,1,128,BC_RET1,7,2,0, | ||
49 | BC_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, | ||
52 | 0,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, | ||
53 | BC_TSETR,4,2,0,BC_RET1,3,2,0,BC_JMP,3,18,128,BC_ISTYPE,1,14,0,BC_KSHORT,3,1,0, | ||
54 | BC_ISGT,3,1,0,BC_JMP,3,14,128,BC_ISGT,1,2,0,BC_JMP,3,12,128,BC_TGETR,3,1,0, | ||
55 | BC_ADDVN,4,1,1,BC_MOV,5,2,0,BC_KSHORT,6,1,0,BC_FORI,4,4,128,BC_SUBVN,8,1,7, | ||
56 | BC_TGETR,9,7,0,BC_TSETR,9,8,0,BC_FORL,4,252,127,BC_KPRI,4,0,0,BC_TSETR,4,2,0, | ||
57 | BC_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, | ||
59 | 2,14,0,BC_ISTYPE,3,14,0,BC_ISNEP,4,0,0,BC_JMP,5,1,128,BC_MOV,4,0,0,BC_ISTYPE, | ||
60 | 4,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, | ||
61 | 128,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, | ||
62 | BC_MOV,7,2,0,BC_KSHORT,8,1,0,BC_FORI,6,4,128,BC_ADDVV,10,5,9,BC_TGETR,11,9,0, | ||
63 | BC_TSETR,11,10,4,BC_FORL,6,252,127,BC_JMP,6,8,128,BC_MOV,6,2,0,BC_MOV,7,1,0, | ||
64 | BC_KSHORT,8,255,255,BC_FORI,6,4,128,BC_ADDVV,10,5,9,BC_TGETR,11,9,0,BC_TSETR, | ||
65 | 11,10,4,BC_FORL,6,252,127,BC_RET1,4,2,0, | ||
66 | #endif | ||
67 | 0 | ||
68 | }; | ||
69 | |||
70 | static 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. */ |
15 | static char *strtab; | 15 | static 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 | |||
9 | local ffi = require("ffi") | ||
10 | local bit = require("bit") | ||
11 | local vmdef = require("jit.vmdef") | ||
12 | local bcnames = vmdef.bcnames | ||
13 | |||
14 | local format = string.format | ||
15 | |||
16 | local isbe = (string.byte(string.dump(function() end), 5) % 2 == 1) | ||
17 | |||
18 | local 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) | ||
22 | end | ||
23 | |||
24 | local 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 | ||
36 | end | ||
37 | |||
38 | local 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 | ||
46 | end | ||
47 | |||
48 | local 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 | ||
61 | end | ||
62 | |||
63 | local 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 | ||
75 | end | ||
76 | |||
77 | -- ORDER LJ_T | ||
78 | local name2itype = { | ||
79 | str = 5, func = 9, tab = 12, int = 14, num = 15 | ||
80 | } | ||
81 | |||
82 | local BC, BCN = {}, {} | ||
83 | for 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 | ||
87 | end | ||
88 | local xop, xra = isbe and 3 or 0, isbe and 2 or 1 | ||
89 | local xrc, xrb = isbe and 1 or 2, isbe and 0 or 3 | ||
90 | |||
91 | local 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 } | ||
139 | end | ||
140 | |||
141 | local 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 | ||
151 | end | ||
152 | |||
153 | local 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) | ||
201 | end | ||
202 | |||
203 | local 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 | ||
218 | end | ||
219 | |||
220 | local outfile = parse_arg(arg) | ||
221 | local src = read_files(arg) | ||
222 | local defs = find_defs(src) | ||
223 | local hdr = gen_header(defs) | ||
224 | write_file(outfile, hdr) | ||
225 | |||