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 | 67 | ||||
| -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 | 151 | ||||
| -rw-r--r-- | src/host/genlibbc.lua | 234 |
8 files changed, 591 insertions, 49 deletions
diff --git a/src/host/buildvm.c b/src/host/buildvm.c index eb22bbbd..27f90066 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 9fe2f0b6..cfdadc2c 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 7a059762..8cd8727b 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 |
| @@ -302,6 +339,10 @@ void emit_asm(BuildCtx *ctx) | |||
| 302 | fprintf(ctx->fp, "\t.ident \"%s\"\n", ctx->dasm_ident); | 339 | fprintf(ctx->fp, "\t.ident \"%s\"\n", ctx->dasm_ident); |
| 303 | break; | 340 | break; |
| 304 | case BUILD_machasm: | 341 | case BUILD_machasm: |
| 342 | #if defined(__apple_build_version__) && __apple_build_version__ >= 15000000 && __apple_build_version__ < 15000300 | ||
| 343 | /* Workaround for XCode 15.0 - 15.2. */ | ||
| 344 | fprintf(ctx->fp, "\t.subsections_via_symbols\n"); | ||
| 345 | #endif | ||
| 305 | fprintf(ctx->fp, | 346 | fprintf(ctx->fp, |
| 306 | "\t.cstring\n" | 347 | "\t.cstring\n" |
| 307 | "\t.ascii \"%s\\0\"\n", ctx->dasm_ident); | 348 | "\t.ascii \"%s\\0\"\n", ctx->dasm_ident); |
diff --git a/src/host/buildvm_fold.c b/src/host/buildvm_fold.c index 3aa445ac..e0b19e8c 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 7147c2c8..51ac5f12 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 7cbe1438..247b9d2d 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_WINDOWS || LJ_TARGET_CYGWIN |
| 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,17 @@ 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 | 96 | #define PEOBJ_PDATA_NRELOC 6 |
| 97 | #define PEOBJ_ARCH_TARGET 0x01f2 | 97 | #define PEOBJ_XDATA_SIZE (8*2+4+6*2) |
| 98 | #define PEOBJ_RELOC_REL32 0x06 | 98 | #elif LJ_TARGET_ARM64 |
| 99 | #define PEOBJ_RELOC_DIR32 0x02 | 99 | #define PEOBJ_ARCH_TARGET 0xaa64 |
| 100 | #define PEOBJ_RELOC_REL32 0x03 /* MS: BRANCH26. */ | ||
| 101 | #define PEOBJ_RELOC_DIR32 0x01 | ||
| 102 | #define PEOBJ_RELOC_ADDR32NB 0x02 | ||
| 100 | #define PEOBJ_RELOC_OFS (-4) | 103 | #define PEOBJ_RELOC_OFS (-4) |
| 101 | #define PEOBJ_TEXT_FLAGS 0x60400020 /* 60=r+x, 40=align8, 20=code. */ | 104 | #define PEOBJ_TEXT_FLAGS 0x60500020 /* 60=r+x, 50=align16, 20=code. */ |
| 105 | #define PEOBJ_PDATA_NRELOC 4 | ||
| 106 | #define PEOBJ_XDATA_SIZE (4+24+4 +4+8) | ||
| 102 | #endif | 107 | #endif |
| 103 | 108 | ||
| 104 | /* Section numbers (0-based). */ | 109 | /* Section numbers (0-based). */ |
| @@ -106,9 +111,11 @@ enum { | |||
| 106 | PEOBJ_SECT_ABS = -2, | 111 | PEOBJ_SECT_ABS = -2, |
| 107 | PEOBJ_SECT_UNDEF = -1, | 112 | PEOBJ_SECT_UNDEF = -1, |
| 108 | PEOBJ_SECT_TEXT, | 113 | PEOBJ_SECT_TEXT, |
| 109 | #if LJ_TARGET_X64 | 114 | #ifdef PEOBJ_PDATA_NRELOC |
| 110 | PEOBJ_SECT_PDATA, | 115 | PEOBJ_SECT_PDATA, |
| 111 | PEOBJ_SECT_XDATA, | 116 | PEOBJ_SECT_XDATA, |
| 117 | #elif LJ_TARGET_X86 | ||
| 118 | PEOBJ_SECT_SXDATA, | ||
| 112 | #endif | 119 | #endif |
| 113 | PEOBJ_SECT_RDATA_Z, | 120 | PEOBJ_SECT_RDATA_Z, |
| 114 | PEOBJ_NSECTIONS | 121 | PEOBJ_NSECTIONS |
| @@ -179,6 +186,9 @@ void emit_peobj(BuildCtx *ctx) | |||
| 179 | uint32_t sofs; | 186 | uint32_t sofs; |
| 180 | int i, nrsym; | 187 | int i, nrsym; |
| 181 | union { uint8_t b; uint32_t u; } host_endian; | 188 | union { uint8_t b; uint32_t u; } host_endian; |
| 189 | #ifdef PEOBJ_PDATA_NRELOC | ||
| 190 | uint32_t fcofs = (uint32_t)ctx->sym[ctx->nsym-1].ofs; | ||
| 191 | #endif | ||
| 182 | 192 | ||
| 183 | sofs = sizeof(PEheader) + PEOBJ_NSECTIONS*sizeof(PEsection); | 193 | sofs = sizeof(PEheader) + PEOBJ_NSECTIONS*sizeof(PEsection); |
| 184 | 194 | ||
| @@ -192,22 +202,29 @@ void emit_peobj(BuildCtx *ctx) | |||
| 192 | /* Flags: 60 = read+execute, 50 = align16, 20 = code. */ | 202 | /* Flags: 60 = read+execute, 50 = align16, 20 = code. */ |
| 193 | pesect[PEOBJ_SECT_TEXT].flags = PEOBJ_TEXT_FLAGS; | 203 | pesect[PEOBJ_SECT_TEXT].flags = PEOBJ_TEXT_FLAGS; |
| 194 | 204 | ||
| 195 | #if LJ_TARGET_X64 | 205 | #ifdef PEOBJ_PDATA_NRELOC |
| 196 | memcpy(pesect[PEOBJ_SECT_PDATA].name, ".pdata", sizeof(".pdata")-1); | 206 | memcpy(pesect[PEOBJ_SECT_PDATA].name, ".pdata", sizeof(".pdata")-1); |
| 197 | pesect[PEOBJ_SECT_PDATA].ofs = sofs; | 207 | pesect[PEOBJ_SECT_PDATA].ofs = sofs; |
| 198 | sofs += (pesect[PEOBJ_SECT_PDATA].size = 6*4); | 208 | sofs += (pesect[PEOBJ_SECT_PDATA].size = PEOBJ_PDATA_NRELOC*4); |
| 199 | pesect[PEOBJ_SECT_PDATA].relocofs = sofs; | 209 | pesect[PEOBJ_SECT_PDATA].relocofs = sofs; |
| 200 | sofs += (pesect[PEOBJ_SECT_PDATA].nreloc = 6) * PEOBJ_RELOC_SIZE; | 210 | sofs += (pesect[PEOBJ_SECT_PDATA].nreloc = PEOBJ_PDATA_NRELOC) * PEOBJ_RELOC_SIZE; |
| 201 | /* Flags: 40 = read, 30 = align4, 40 = initialized data. */ | 211 | /* Flags: 40 = read, 30 = align4, 40 = initialized data. */ |
| 202 | pesect[PEOBJ_SECT_PDATA].flags = 0x40300040; | 212 | pesect[PEOBJ_SECT_PDATA].flags = 0x40300040; |
| 203 | 213 | ||
| 204 | memcpy(pesect[PEOBJ_SECT_XDATA].name, ".xdata", sizeof(".xdata")-1); | 214 | memcpy(pesect[PEOBJ_SECT_XDATA].name, ".xdata", sizeof(".xdata")-1); |
| 205 | pesect[PEOBJ_SECT_XDATA].ofs = sofs; | 215 | pesect[PEOBJ_SECT_XDATA].ofs = sofs; |
| 206 | sofs += (pesect[PEOBJ_SECT_XDATA].size = 8*2+4+6*2); /* See below. */ | 216 | sofs += (pesect[PEOBJ_SECT_XDATA].size = PEOBJ_XDATA_SIZE); /* See below. */ |
| 207 | pesect[PEOBJ_SECT_XDATA].relocofs = sofs; | 217 | pesect[PEOBJ_SECT_XDATA].relocofs = sofs; |
| 208 | sofs += (pesect[PEOBJ_SECT_XDATA].nreloc = 1) * PEOBJ_RELOC_SIZE; | 218 | sofs += (pesect[PEOBJ_SECT_XDATA].nreloc = 1) * PEOBJ_RELOC_SIZE; |
| 209 | /* Flags: 40 = read, 30 = align4, 40 = initialized data. */ | 219 | /* Flags: 40 = read, 30 = align4, 40 = initialized data. */ |
| 210 | pesect[PEOBJ_SECT_XDATA].flags = 0x40300040; | 220 | pesect[PEOBJ_SECT_XDATA].flags = 0x40300040; |
| 221 | #elif LJ_TARGET_X86 | ||
| 222 | memcpy(pesect[PEOBJ_SECT_SXDATA].name, ".sxdata", sizeof(".sxdata")-1); | ||
| 223 | pesect[PEOBJ_SECT_SXDATA].ofs = sofs; | ||
| 224 | sofs += (pesect[PEOBJ_SECT_SXDATA].size = 4); | ||
| 225 | pesect[PEOBJ_SECT_SXDATA].relocofs = sofs; | ||
| 226 | /* Flags: 40 = read, 30 = align4, 02 = lnk_info, 40 = initialized data. */ | ||
| 227 | pesect[PEOBJ_SECT_SXDATA].flags = 0x40300240; | ||
| 211 | #endif | 228 | #endif |
| 212 | 229 | ||
| 213 | memcpy(pesect[PEOBJ_SECT_RDATA_Z].name, ".rdata$Z", sizeof(".rdata$Z")-1); | 230 | memcpy(pesect[PEOBJ_SECT_RDATA_Z].name, ".rdata$Z", sizeof(".rdata$Z")-1); |
| @@ -231,8 +248,8 @@ void emit_peobj(BuildCtx *ctx) | |||
| 231 | */ | 248 | */ |
| 232 | nrsym = ctx->nrelocsym; | 249 | nrsym = ctx->nrelocsym; |
| 233 | pehdr.nsyms = 1+PEOBJ_NSECTIONS*2 + 1+ctx->nsym + nrsym; | 250 | pehdr.nsyms = 1+PEOBJ_NSECTIONS*2 + 1+ctx->nsym + nrsym; |
| 234 | #if LJ_TARGET_X64 | 251 | #ifdef PEOBJ_PDATA_NRELOC |
| 235 | pehdr.nsyms += 1; /* Symbol for lj_err_unwind_win64. */ | 252 | pehdr.nsyms += 1; /* Symbol for lj_err_unwind_win. */ |
| 236 | #endif | 253 | #endif |
| 237 | 254 | ||
| 238 | /* Write PE object header and all sections. */ | 255 | /* Write PE object header and all sections. */ |
| @@ -242,15 +259,8 @@ void emit_peobj(BuildCtx *ctx) | |||
| 242 | /* Write .text section. */ | 259 | /* Write .text section. */ |
| 243 | host_endian.u = 1; | 260 | host_endian.u = 1; |
| 244 | if (host_endian.b != LJ_ENDIAN_SELECT(1, 0)) { | 261 | 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"); | 262 | fprintf(stderr, "Error: different byte order for host and target\n"); |
| 252 | exit(1); | 263 | exit(1); |
| 253 | #endif | ||
| 254 | } | 264 | } |
| 255 | owrite(ctx, ctx->code, ctx->codesz); | 265 | owrite(ctx, ctx->code, ctx->codesz); |
| 256 | for (i = 0; i < ctx->nreloc; i++) { | 266 | for (i = 0; i < ctx->nreloc; i++) { |
| @@ -263,7 +273,6 @@ void emit_peobj(BuildCtx *ctx) | |||
| 263 | 273 | ||
| 264 | #if LJ_TARGET_X64 | 274 | #if LJ_TARGET_X64 |
| 265 | { /* Write .pdata section. */ | 275 | { /* Write .pdata section. */ |
| 266 | uint32_t fcofs = (uint32_t)ctx->sym[ctx->nsym-1].ofs; | ||
| 267 | uint32_t pdata[3]; /* Start of .text, end of .text and .xdata. */ | 276 | uint32_t pdata[3]; /* Start of .text, end of .text and .xdata. */ |
| 268 | PEreloc reloc; | 277 | PEreloc reloc; |
| 269 | pdata[0] = 0; pdata[1] = fcofs; pdata[2] = 0; | 278 | pdata[0] = 0; pdata[1] = fcofs; pdata[2] = 0; |
| @@ -312,6 +321,100 @@ void emit_peobj(BuildCtx *ctx) | |||
| 312 | reloc.type = PEOBJ_RELOC_ADDR32NB; | 321 | reloc.type = PEOBJ_RELOC_ADDR32NB; |
| 313 | owrite(ctx, &reloc, PEOBJ_RELOC_SIZE); | 322 | owrite(ctx, &reloc, PEOBJ_RELOC_SIZE); |
| 314 | } | 323 | } |
| 324 | #elif LJ_TARGET_ARM64 | ||
| 325 | /* https://learn.microsoft.com/en-us/cpp/build/arm64-exception-handling */ | ||
| 326 | { /* Write .pdata section. */ | ||
| 327 | uint32_t pdata[4]; | ||
| 328 | PEreloc reloc; | ||
| 329 | pdata[0] = 0; | ||
| 330 | pdata[1] = 0; | ||
| 331 | pdata[2] = fcofs; | ||
| 332 | pdata[3] = 4+24+4; | ||
| 333 | owrite(ctx, &pdata, sizeof(pdata)); | ||
| 334 | /* Start of .text and start of .xdata. */ | ||
| 335 | reloc.vaddr = 0; reloc.symidx = 1+2+nrsym+2+2+1; | ||
| 336 | reloc.type = PEOBJ_RELOC_ADDR32NB; | ||
| 337 | owrite(ctx, &reloc, PEOBJ_RELOC_SIZE); | ||
| 338 | reloc.vaddr = 4; reloc.symidx = 1+2+nrsym+2; | ||
| 339 | reloc.type = PEOBJ_RELOC_ADDR32NB; | ||
| 340 | owrite(ctx, &reloc, PEOBJ_RELOC_SIZE); | ||
| 341 | /* Start of vm_ffi_call and start of second part of .xdata. */ | ||
| 342 | reloc.vaddr = 8; reloc.symidx = 1+2+nrsym+2+2+1; | ||
| 343 | reloc.type = PEOBJ_RELOC_ADDR32NB; | ||
| 344 | owrite(ctx, &reloc, PEOBJ_RELOC_SIZE); | ||
| 345 | reloc.vaddr = 12; reloc.symidx = 1+2+nrsym+2; | ||
| 346 | reloc.type = PEOBJ_RELOC_ADDR32NB; | ||
| 347 | owrite(ctx, &reloc, PEOBJ_RELOC_SIZE); | ||
| 348 | } | ||
| 349 | { /* Write .xdata section. */ | ||
| 350 | uint32_t u32; | ||
| 351 | uint8_t *p, uwc[24]; | ||
| 352 | PEreloc reloc; | ||
| 353 | |||
| 354 | #define CBE16(x) (*p = ((x) >> 8) & 0xff, p[1] = (x) & 0xff, p += 2) | ||
| 355 | #define CALLOC_S(s) (*p++ = ((s) >> 4)) /* s < 512 */ | ||
| 356 | #define CSAVE_FPLR(o) (*p++ = 0x40 | ((o) >> 3)) /* o <= 504 */ | ||
| 357 | #define CSAVE_REGP(r,o) CBE16(0xc800 | (((r) - 19) << 6) | ((o) >> 3)) | ||
| 358 | #define CSAVE_REGS(r1,r2,o1) do { \ | ||
| 359 | int r, o; for (r = r1, o = o1; r <= r2; r += 2, o -= 16) CSAVE_REGP(r, o); \ | ||
| 360 | } while (0) | ||
| 361 | #define CSAVE_REGPX(r,o) CBE16(0xcc00 | (((r) - 19) << 6) | (~(o) >> 3)) | ||
| 362 | #define CSAVE_FREGP(r,o) CBE16(0xd800 | (((r) - 8) << 6) | ((o) >> 3)) | ||
| 363 | #define CSAVE_FREGS(r1,r2,o1) do { \ | ||
| 364 | int r, o; for (r = r1, o = o1; r <= r2; r += 2, o -= 16) CSAVE_FREGP(r, o); \ | ||
| 365 | } while (0) | ||
| 366 | #define CADD_FP(s) CBE16(0xe200 | ((s) >> 3)) /* s < 8*256 */ | ||
| 367 | #define CODE_NOP 0xe3 | ||
| 368 | #define CODE_END 0xe4 | ||
| 369 | #define CEND_ALIGN do { \ | ||
| 370 | *p++ = CODE_END; \ | ||
| 371 | while ((p - uwc) & 3) *p++ = CODE_NOP; \ | ||
| 372 | } while (0) | ||
| 373 | |||
| 374 | /* Unwind codes for .text section with handler. */ | ||
| 375 | p = uwc; | ||
| 376 | CADD_FP(192); /* +2 */ | ||
| 377 | CSAVE_REGS(19, 28, 176); /* +5*2 */ | ||
| 378 | CSAVE_FREGS(8, 15, 96); /* +4*2 */ | ||
| 379 | CSAVE_FPLR(192); /* +1 */ | ||
| 380 | CALLOC_S(208); /* +1 */ | ||
| 381 | CEND_ALIGN; /* +1 +1 -> 24 */ | ||
| 382 | |||
| 383 | u32 = ((24u >> 2) << 27) | (1u << 20) | (fcofs >> 2); | ||
| 384 | owrite(ctx, &u32, 4); | ||
| 385 | owrite(ctx, &uwc, 24); | ||
| 386 | |||
| 387 | u32 = 0; /* Handler RVA to be relocated at 4 + 24. */ | ||
| 388 | owrite(ctx, &u32, 4); | ||
| 389 | |||
| 390 | /* Unwind codes for vm_ffi_call without handler. */ | ||
| 391 | p = uwc; | ||
| 392 | CADD_FP(16); /* +2 */ | ||
| 393 | CSAVE_FPLR(16); /* +1 */ | ||
| 394 | CSAVE_REGPX(19, -32); /* +2 */ | ||
| 395 | CEND_ALIGN; /* +1 +2 -> 8 */ | ||
| 396 | |||
| 397 | u32 = ((8u >> 2) << 27) | (((uint32_t)ctx->codesz - fcofs) >> 2); | ||
| 398 | owrite(ctx, &u32, 4); | ||
| 399 | owrite(ctx, &uwc, 8); | ||
| 400 | |||
| 401 | reloc.vaddr = 4 + 24; reloc.symidx = 1+2+nrsym+2+2; | ||
| 402 | reloc.type = PEOBJ_RELOC_ADDR32NB; | ||
| 403 | owrite(ctx, &reloc, PEOBJ_RELOC_SIZE); | ||
| 404 | } | ||
| 405 | #elif LJ_TARGET_X86 | ||
| 406 | /* Write .sxdata section. */ | ||
| 407 | for (i = 0; i < nrsym; i++) { | ||
| 408 | if (!strcmp(ctx->relocsym[i], "_lj_err_unwind_win")) { | ||
| 409 | uint32_t symidx = 1+2+i; | ||
| 410 | owrite(ctx, &symidx, 4); | ||
| 411 | break; | ||
| 412 | } | ||
| 413 | } | ||
| 414 | if (i == nrsym) { | ||
| 415 | fprintf(stderr, "Error: extern lj_err_unwind_win not used\n"); | ||
| 416 | exit(1); | ||
| 417 | } | ||
| 315 | #endif | 418 | #endif |
| 316 | 419 | ||
| 317 | /* Write .rdata$Z section. */ | 420 | /* Write .rdata$Z section. */ |
| @@ -330,11 +433,13 @@ void emit_peobj(BuildCtx *ctx) | |||
| 330 | emit_peobj_sym(ctx, ctx->relocsym[i], 0, | 433 | emit_peobj_sym(ctx, ctx->relocsym[i], 0, |
| 331 | PEOBJ_SECT_UNDEF, PEOBJ_TYPE_FUNC, PEOBJ_SCL_EXTERN); | 434 | PEOBJ_SECT_UNDEF, PEOBJ_TYPE_FUNC, PEOBJ_SCL_EXTERN); |
| 332 | 435 | ||
| 333 | #if LJ_TARGET_X64 | 436 | #ifdef PEOBJ_PDATA_NRELOC |
| 334 | emit_peobj_sym_sect(ctx, pesect, PEOBJ_SECT_PDATA); | 437 | emit_peobj_sym_sect(ctx, pesect, PEOBJ_SECT_PDATA); |
| 335 | emit_peobj_sym_sect(ctx, pesect, PEOBJ_SECT_XDATA); | 438 | emit_peobj_sym_sect(ctx, pesect, PEOBJ_SECT_XDATA); |
| 336 | emit_peobj_sym(ctx, "lj_err_unwind_win64", 0, | 439 | emit_peobj_sym(ctx, "lj_err_unwind_win", 0, |
| 337 | PEOBJ_SECT_UNDEF, PEOBJ_TYPE_FUNC, PEOBJ_SCL_EXTERN); | 440 | PEOBJ_SECT_UNDEF, PEOBJ_TYPE_FUNC, PEOBJ_SCL_EXTERN); |
| 441 | #elif LJ_TARGET_X86 | ||
| 442 | emit_peobj_sym_sect(ctx, pesect, PEOBJ_SECT_SXDATA); | ||
| 338 | #endif | 443 | #endif |
| 339 | 444 | ||
| 340 | emit_peobj_sym(ctx, ctx->beginsym, 0, | 445 | 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..3eb1b827 --- /dev/null +++ b/src/host/genlibbc.lua | |||
| @@ -0,0 +1,234 @@ | |||
| 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-2026 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, mode) | ||
| 142 | local defs = {} | ||
| 143 | for name, code in string.gmatch(src, "LJLIB_LUA%(([^)]*)%)%s*/%*(.-)%*/") do | ||
| 144 | local tcode, fixup = transform_lua(code) | ||
| 145 | local func = assert(load(tcode, "", mode)) | ||
| 146 | defs[name] = fixup_dump(string.dump(func, mode), fixup) | ||
| 147 | defs[#defs+1] = name | ||
| 148 | end | ||
| 149 | return defs | ||
| 150 | end | ||
| 151 | |||
| 152 | local function gen_header(defs32, defs64) | ||
| 153 | local t = {} | ||
| 154 | local function w(x) t[#t+1] = x end | ||
| 155 | w("/* This is a generated file. DO NOT EDIT! */\n\n") | ||
| 156 | w("static const int libbc_endian = ") w(isbe and 1 or 0) w(";\n\n") | ||
| 157 | for j,defs in ipairs{defs64, defs32} do | ||
| 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 | if j == 1 then | ||
| 167 | w("static const uint8_t libbc_code[] = {\n#if LJ_FR2\n") | ||
| 168 | else | ||
| 169 | w("\n#else\n") | ||
| 170 | end | ||
| 171 | local n = 0 | ||
| 172 | for i=1,#s do | ||
| 173 | local x = string.byte(s, i) | ||
| 174 | local xb = string.byte(sb, i) | ||
| 175 | if xb == 255 then | ||
| 176 | local name = BCN[x] | ||
| 177 | local m = #name + 4 | ||
| 178 | if n + m > 78 then n = 0; w("\n") end | ||
| 179 | n = n + m | ||
| 180 | w("BC_"); w(name) | ||
| 181 | else | ||
| 182 | local m = x < 10 and 2 or (x < 100 and 3 or 4) | ||
| 183 | if xb == 0 then | ||
| 184 | if n + m > 78 then n = 0; w("\n") end | ||
| 185 | else | ||
| 186 | local name = defs[xb]:gsub("_", ".") | ||
| 187 | if n ~= 0 then w("\n") end | ||
| 188 | w("/* "); w(name); w(" */ ") | ||
| 189 | n = #name + 7 | ||
| 190 | end | ||
| 191 | n = n + m | ||
| 192 | w(x) | ||
| 193 | end | ||
| 194 | w(",") | ||
| 195 | end | ||
| 196 | end | ||
| 197 | w("\n#endif\n0\n};\n\n") | ||
| 198 | w("static const struct { const char *name; int ofs; } libbc_map[] = {\n") | ||
| 199 | local m32, m64 = 0, 0 | ||
| 200 | for i,name in ipairs(defs32) do | ||
| 201 | assert(name == defs64[i]) | ||
| 202 | w('{"'); w(name); w('",'); w(m32) w('},\n') | ||
| 203 | m32 = m32 + #defs32[name].dump | ||
| 204 | m64 = m64 + #defs64[name].dump | ||
| 205 | assert(m32 == m64) | ||
| 206 | end | ||
| 207 | w("{NULL,"); w(m32); w("}\n};\n\n") | ||
| 208 | return table.concat(t) | ||
| 209 | end | ||
| 210 | |||
| 211 | local function write_file(name, data) | ||
| 212 | if name == "-" then | ||
| 213 | assert(io.write(data)) | ||
| 214 | assert(io.flush()) | ||
| 215 | else | ||
| 216 | local fp = io.open(name) | ||
| 217 | if fp then | ||
| 218 | local old = fp:read("*a") | ||
| 219 | fp:close() | ||
| 220 | if data == old then return end | ||
| 221 | end | ||
| 222 | fp = assert(io.open(name, "w")) | ||
| 223 | assert(fp:write(data)) | ||
| 224 | assert(fp:close()) | ||
| 225 | end | ||
| 226 | end | ||
| 227 | |||
| 228 | local outfile = parse_arg(arg) | ||
| 229 | local src = read_files(arg) | ||
| 230 | local defs32 = find_defs(src, "Wdts") | ||
| 231 | local defs64 = find_defs(src, "Xdts") | ||
| 232 | local hdr = gen_header(defs32, defs64) | ||
| 233 | write_file(outfile, hdr) | ||
| 234 | |||
