diff options
Diffstat (limited to 'src/host')
-rw-r--r-- | src/host/buildvm.c | 26 | ||||
-rw-r--r-- | src/host/buildvm.h | 1 | ||||
-rw-r--r-- | src/host/buildvm_asm.c | 67 | ||||
-rw-r--r-- | src/host/buildvm_lib.c | 61 | ||||
-rw-r--r-- | src/host/buildvm_libbc.h | 56 | ||||
-rw-r--r-- | src/host/buildvm_peobj.c | 28 | ||||
-rw-r--r-- | src/host/genlibbc.lua | 197 |
7 files changed, 410 insertions, 26 deletions
diff --git a/src/host/buildvm.c b/src/host/buildvm.c index b9560f31..de23fabd 100644 --- a/src/host/buildvm.c +++ b/src/host/buildvm.c | |||
@@ -59,10 +59,10 @@ static int collect_reloc(BuildCtx *ctx, uint8_t *addr, int idx, int type); | |||
59 | #include "../dynasm/dasm_x86.h" | 59 | #include "../dynasm/dasm_x86.h" |
60 | #elif LJ_TARGET_ARM | 60 | #elif LJ_TARGET_ARM |
61 | #include "../dynasm/dasm_arm.h" | 61 | #include "../dynasm/dasm_arm.h" |
62 | #elif LJ_TARGET_ARM64 | ||
63 | #include "../dynasm/dasm_arm64.h" | ||
62 | #elif LJ_TARGET_PPC | 64 | #elif LJ_TARGET_PPC |
63 | #include "../dynasm/dasm_ppc.h" | 65 | #include "../dynasm/dasm_ppc.h" |
64 | #elif LJ_TARGET_PPCSPE | ||
65 | #include "../dynasm/dasm_ppc.h" | ||
66 | #elif LJ_TARGET_MIPS | 66 | #elif LJ_TARGET_MIPS |
67 | #include "../dynasm/dasm_mips.h" | 67 | #include "../dynasm/dasm_mips.h" |
68 | #else | 68 | #else |
@@ -110,11 +110,11 @@ static const char *sym_decorate(BuildCtx *ctx, | |||
110 | if (p) { | 110 | if (p) { |
111 | #if LJ_TARGET_X86ORX64 | 111 | #if LJ_TARGET_X86ORX64 |
112 | if (!LJ_64 && (ctx->mode == BUILD_coffasm || ctx->mode == BUILD_peobj)) | 112 | if (!LJ_64 && (ctx->mode == BUILD_coffasm || ctx->mode == BUILD_peobj)) |
113 | name[0] = '@'; | 113 | name[0] = name[1] == 'R' ? '_' : '@'; /* Just for _RtlUnwind@16. */ |
114 | else | 114 | else |
115 | *p = '\0'; | 115 | *p = '\0'; |
116 | #elif (LJ_TARGET_PPC || LJ_TARGET_PPCSPE) && !LJ_TARGET_CONSOLE | 116 | #elif LJ_TARGET_PPC && !LJ_TARGET_CONSOLE |
117 | /* Keep @plt. */ | 117 | /* Keep @plt etc. */ |
118 | #else | 118 | #else |
119 | *p = '\0'; | 119 | *p = '\0'; |
120 | #endif | 120 | #endif |
@@ -179,6 +179,7 @@ static int build_code(BuildCtx *ctx) | |||
179 | ctx->nreloc = 0; | 179 | ctx->nreloc = 0; |
180 | 180 | ||
181 | ctx->globnames = globnames; | 181 | ctx->globnames = globnames; |
182 | ctx->extnames = extnames; | ||
182 | ctx->relocsym = (const char **)malloc(NRELOCSYM*sizeof(const char *)); | 183 | ctx->relocsym = (const char **)malloc(NRELOCSYM*sizeof(const char *)); |
183 | ctx->nrelocsym = 0; | 184 | ctx->nrelocsym = 0; |
184 | for (i = 0; i < (int)NRELOCSYM; i++) relocmap[i] = -1; | 185 | for (i = 0; i < (int)NRELOCSYM; i++) relocmap[i] = -1; |
@@ -320,20 +321,20 @@ static void emit_vmdef(BuildCtx *ctx) | |||
320 | char buf[80]; | 321 | char buf[80]; |
321 | int i; | 322 | int i; |
322 | fprintf(ctx->fp, "-- This is a generated file. DO NOT EDIT!\n\n"); | 323 | fprintf(ctx->fp, "-- This is a generated file. DO NOT EDIT!\n\n"); |
323 | fprintf(ctx->fp, "module(...)\n\n"); | 324 | fprintf(ctx->fp, "return {\n\n"); |
324 | 325 | ||
325 | fprintf(ctx->fp, "bcnames = \""); | 326 | fprintf(ctx->fp, "bcnames = \""); |
326 | for (i = 0; bc_names[i]; i++) fprintf(ctx->fp, "%-6s", bc_names[i]); | 327 | for (i = 0; bc_names[i]; i++) fprintf(ctx->fp, "%-6s", bc_names[i]); |
327 | fprintf(ctx->fp, "\"\n\n"); | 328 | fprintf(ctx->fp, "\",\n\n"); |
328 | 329 | ||
329 | fprintf(ctx->fp, "irnames = \""); | 330 | fprintf(ctx->fp, "irnames = \""); |
330 | for (i = 0; ir_names[i]; i++) fprintf(ctx->fp, "%-6s", ir_names[i]); | 331 | for (i = 0; ir_names[i]; i++) fprintf(ctx->fp, "%-6s", ir_names[i]); |
331 | fprintf(ctx->fp, "\"\n\n"); | 332 | fprintf(ctx->fp, "\",\n\n"); |
332 | 333 | ||
333 | fprintf(ctx->fp, "irfpm = { [0]="); | 334 | fprintf(ctx->fp, "irfpm = { [0]="); |
334 | for (i = 0; irfpm_names[i]; i++) | 335 | for (i = 0; irfpm_names[i]; i++) |
335 | fprintf(ctx->fp, "\"%s\", ", lower(buf, irfpm_names[i])); | 336 | fprintf(ctx->fp, "\"%s\", ", lower(buf, irfpm_names[i])); |
336 | fprintf(ctx->fp, "}\n\n"); | 337 | fprintf(ctx->fp, "},\n\n"); |
337 | 338 | ||
338 | fprintf(ctx->fp, "irfield = { [0]="); | 339 | fprintf(ctx->fp, "irfield = { [0]="); |
339 | for (i = 0; irfield_names[i]; i++) { | 340 | for (i = 0; irfield_names[i]; i++) { |
@@ -343,17 +344,17 @@ static void emit_vmdef(BuildCtx *ctx) | |||
343 | if (p) *p = '.'; | 344 | if (p) *p = '.'; |
344 | fprintf(ctx->fp, "\"%s\", ", buf); | 345 | fprintf(ctx->fp, "\"%s\", ", buf); |
345 | } | 346 | } |
346 | fprintf(ctx->fp, "}\n\n"); | 347 | fprintf(ctx->fp, "},\n\n"); |
347 | 348 | ||
348 | fprintf(ctx->fp, "ircall = {\n[0]="); | 349 | fprintf(ctx->fp, "ircall = {\n[0]="); |
349 | for (i = 0; ircall_names[i]; i++) | 350 | for (i = 0; ircall_names[i]; i++) |
350 | fprintf(ctx->fp, "\"%s\",\n", ircall_names[i]); | 351 | fprintf(ctx->fp, "\"%s\",\n", ircall_names[i]); |
351 | fprintf(ctx->fp, "}\n\n"); | 352 | fprintf(ctx->fp, "},\n\n"); |
352 | 353 | ||
353 | fprintf(ctx->fp, "traceerr = {\n[0]="); | 354 | fprintf(ctx->fp, "traceerr = {\n[0]="); |
354 | for (i = 0; trace_errors[i]; i++) | 355 | for (i = 0; trace_errors[i]; i++) |
355 | fprintf(ctx->fp, "\"%s\",\n", trace_errors[i]); | 356 | fprintf(ctx->fp, "\"%s\",\n", trace_errors[i]); |
356 | fprintf(ctx->fp, "}\n\n"); | 357 | fprintf(ctx->fp, "},\n\n"); |
357 | } | 358 | } |
358 | 359 | ||
359 | /* -- Argument parsing ---------------------------------------------------- */ | 360 | /* -- Argument parsing ---------------------------------------------------- */ |
@@ -490,6 +491,7 @@ int main(int argc, char **argv) | |||
490 | case BUILD_vmdef: | 491 | case BUILD_vmdef: |
491 | emit_vmdef(ctx); | 492 | emit_vmdef(ctx); |
492 | emit_lib(ctx); | 493 | emit_lib(ctx); |
494 | fprintf(ctx->fp, "}\n\n"); | ||
493 | break; | 495 | break; |
494 | case BUILD_ffdef: | 496 | case BUILD_ffdef: |
495 | case BUILD_libdef: | 497 | case BUILD_libdef: |
diff --git a/src/host/buildvm.h b/src/host/buildvm.h index e6dd3dcb..b90428dc 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 81a3969a..43595b31 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 |
@@ -117,6 +144,14 @@ static void emit_asm_wordreloc(BuildCtx *ctx, uint8_t *p, int n, | |||
117 | fprintf(ctx->fp, "\t%s %d, %d, " TOCPREFIX "%s\n", | 144 | fprintf(ctx->fp, "\t%s %d, %d, " TOCPREFIX "%s\n", |
118 | (ins & 1) ? "bcl" : "bc", (ins >> 21) & 31, (ins >> 16) & 31, sym); | 145 | (ins & 1) ? "bcl" : "bc", (ins >> 21) & 31, (ins >> 16) & 31, sym); |
119 | } else if ((ins >> 26) == 18) { | 146 | } else if ((ins >> 26) == 18) { |
147 | #if LJ_ARCH_PPC64 | ||
148 | const char *suffix = strchr(sym, '@'); | ||
149 | if (suffix && suffix[1] == 'h') { | ||
150 | fprintf(ctx->fp, "\taddis 11, 2, %s\n", sym); | ||
151 | } else if (suffix && suffix[1] == 'l') { | ||
152 | fprintf(ctx->fp, "\tld 12, %s\n", sym); | ||
153 | } else | ||
154 | #endif | ||
120 | fprintf(ctx->fp, "\t%s " TOCPREFIX "%s\n", (ins & 1) ? "bl" : "b", sym); | 155 | fprintf(ctx->fp, "\t%s " TOCPREFIX "%s\n", (ins & 1) ? "bl" : "b", sym); |
121 | } else { | 156 | } else { |
122 | fprintf(stderr, | 157 | fprintf(stderr, |
@@ -215,6 +250,9 @@ void emit_asm(BuildCtx *ctx) | |||
215 | int i, rel; | 250 | int i, rel; |
216 | 251 | ||
217 | fprintf(ctx->fp, "\t.file \"buildvm_%s.dasc\"\n", ctx->dasm_arch); | 252 | fprintf(ctx->fp, "\t.file \"buildvm_%s.dasc\"\n", ctx->dasm_arch); |
253 | #if LJ_ARCH_PPC64 | ||
254 | fprintf(ctx->fp, "\t.abiversion 2\n"); | ||
255 | #endif | ||
218 | fprintf(ctx->fp, "\t.text\n"); | 256 | fprintf(ctx->fp, "\t.text\n"); |
219 | emit_asm_align(ctx, 4); | 257 | emit_asm_align(ctx, 4); |
220 | 258 | ||
@@ -228,11 +266,20 @@ void emit_asm(BuildCtx *ctx) | |||
228 | 266 | ||
229 | #if LJ_TARGET_ARM && defined(__GNUC__) && !LJ_NO_UNWIND | 267 | #if LJ_TARGET_ARM && defined(__GNUC__) && !LJ_NO_UNWIND |
230 | /* This should really be moved into buildvm_arm.dasc. */ | 268 | /* This should really be moved into buildvm_arm.dasc. */ |
269 | #if LJ_ARCH_HASFPU | ||
270 | fprintf(ctx->fp, | ||
271 | ".fnstart\n" | ||
272 | ".save {r5, r6, r7, r8, r9, r10, r11, lr}\n" | ||
273 | ".vsave {d8-d15}\n" | ||
274 | ".save {r4}\n" | ||
275 | ".pad #28\n"); | ||
276 | #else | ||
231 | fprintf(ctx->fp, | 277 | fprintf(ctx->fp, |
232 | ".fnstart\n" | 278 | ".fnstart\n" |
233 | ".save {r4, r5, r6, r7, r8, r9, r10, r11, lr}\n" | 279 | ".save {r4, r5, r6, r7, r8, r9, r10, r11, lr}\n" |
234 | ".pad #28\n"); | 280 | ".pad #28\n"); |
235 | #endif | 281 | #endif |
282 | #endif | ||
236 | #if LJ_TARGET_MIPS | 283 | #if LJ_TARGET_MIPS |
237 | fprintf(ctx->fp, ".set nomips16\n.abicalls\n.set noreorder\n.set nomacro\n"); | 284 | fprintf(ctx->fp, ".set nomips16\n.abicalls\n.set noreorder\n.set nomacro\n"); |
238 | #endif | 285 | #endif |
@@ -255,8 +302,9 @@ void emit_asm(BuildCtx *ctx) | |||
255 | BuildReloc *r = &ctx->reloc[rel]; | 302 | BuildReloc *r = &ctx->reloc[rel]; |
256 | int n = r->ofs - ofs; | 303 | int n = r->ofs - ofs; |
257 | #if LJ_TARGET_X86ORX64 | 304 | #if LJ_TARGET_X86ORX64 |
258 | if (ctx->mode == BUILD_machasm && r->type != 0) { | 305 | if (r->type != 0 && |
259 | emit_asm_reloc_mach(ctx, ctx->code+ofs, n, ctx->relocsym[r->sym]); | 306 | (ctx->mode == BUILD_elfasm || ctx->mode == BUILD_machasm)) { |
307 | emit_asm_reloc_text(ctx, ctx->code+ofs, n, ctx->relocsym[r->sym]); | ||
260 | } else { | 308 | } else { |
261 | emit_asm_bytes(ctx, ctx->code+ofs, n); | 309 | emit_asm_bytes(ctx, ctx->code+ofs, n); |
262 | emit_asm_reloc(ctx, r->type, ctx->relocsym[r->sym]); | 310 | emit_asm_reloc(ctx, r->type, ctx->relocsym[r->sym]); |
@@ -290,10 +338,7 @@ void emit_asm(BuildCtx *ctx) | |||
290 | #if !(LJ_TARGET_PS3 || LJ_TARGET_PSVITA) | 338 | #if !(LJ_TARGET_PS3 || LJ_TARGET_PSVITA) |
291 | fprintf(ctx->fp, "\t.section .note.GNU-stack,\"\"," ELFASM_PX "progbits\n"); | 339 | fprintf(ctx->fp, "\t.section .note.GNU-stack,\"\"," ELFASM_PX "progbits\n"); |
292 | #endif | 340 | #endif |
293 | #if LJ_TARGET_PPCSPE | 341 | #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. */ | 342 | /* Hard-float ABI. */ |
298 | fprintf(ctx->fp, "\t.gnu_attribute 4, 1\n"); | 343 | fprintf(ctx->fp, "\t.gnu_attribute 4, 1\n"); |
299 | #endif | 344 | #endif |
diff --git a/src/host/buildvm_lib.c b/src/host/buildvm_lib.c index 569e2caf..2956fdb6 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 }, |
@@ -373,7 +432,7 @@ void emit_lib(BuildCtx *ctx) | |||
373 | "#ifndef FF_NUM_ASMFUNC\n#define FF_NUM_ASMFUNC %d\n#endif\n\n", | 432 | "#ifndef FF_NUM_ASMFUNC\n#define FF_NUM_ASMFUNC %d\n#endif\n\n", |
374 | ffasmfunc); | 433 | ffasmfunc); |
375 | } else if (ctx->mode == BUILD_vmdef) { | 434 | } else if (ctx->mode == BUILD_vmdef) { |
376 | fprintf(ctx->fp, "}\n\n"); | 435 | fprintf(ctx->fp, "},\n\n"); |
377 | } else if (ctx->mode == BUILD_bcdef) { | 436 | } else if (ctx->mode == BUILD_bcdef) { |
378 | int i; | 437 | int i; |
379 | fprintf(ctx->fp, "\n};\n\n"); | 438 | 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..b2600bd5 --- /dev/null +++ b/src/host/buildvm_libbc.h | |||
@@ -0,0 +1,56 @@ | |||
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 | 0,1,2,0,0,1,2,24,1,0,0,76,1,2,0,241,135,158,166,3,220,203,178,130,4,0,1,2,0, | ||
8 | 0,1,2,24,1,0,0,76,1,2,0,243,244,148,165,20,198,190,199,252,3,0,1,2,0,0,0,3, | ||
9 | 16,0,5,0,21,1,0,0,76,1,2,0,0,2,10,0,0,0,15,16,0,12,0,16,1,9,0,41,2,1,0,21,3, | ||
10 | 0,0,41,4,1,0,77,2,8,128,18,6,1,0,18,8,5,0,59,9,5,0,66,6,3,2,10,6,0,0,88,7,1, | ||
11 | 128,76,6,2,0,79,2,248,127,75,0,1,0,0,2,11,0,0,0,16,16,0,12,0,16,1,9,0,43,2, | ||
12 | 0,0,18,3,0,0,41,4,0,0,88,5,7,128,18,7,1,0,18,9,5,0,18,10,6,0,66,7,3,2,10,7, | ||
13 | 0,0,88,8,1,128,76,7,2,0,70,5,3,3,82,5,247,127,75,0,1,0,0,1,2,0,0,0,3,16,0,12, | ||
14 | 0,21,1,0,0,76,1,2,0,0,2,10,0,0,2,30,16,0,12,0,21,2,0,0,11,1,0,0,88,3,7,128, | ||
15 | 8,2,0,0,88,3,23,128,59,3,2,0,43,4,0,0,64,4,2,0,76,3,2,0,88,3,18,128,16,1,14, | ||
16 | 0,41,3,1,0,3,3,1,0,88,3,14,128,3,1,2,0,88,3,12,128,59,3,1,0,22,4,1,1,18,5,2, | ||
17 | 0,41,6,1,0,77,4,4,128,23,8,1,7,59,9,7,0,64,9,8,0,79,4,252,127,43,4,0,0,64,4, | ||
18 | 2,0,76,3,2,0,75,0,1,0,0,2,0,5,12,0,0,0,35,16,0,12,0,16,1,14,0,16,2,14,0,16, | ||
19 | 3,14,0,11,4,0,0,88,5,1,128,18,4,0,0,16,4,12,0,3,1,2,0,88,5,24,128,33,5,1,3, | ||
20 | 0,2,3,0,88,6,4,128,2,3,1,0,88,6,2,128,4,4,0,0,88,6,9,128,18,6,1,0,18,7,2,0, | ||
21 | 41,8,1,0,77,6,4,128,32,10,5,9,59,11,9,0,64,11,10,4,79,6,252,127,88,6,8,128, | ||
22 | 18,6,2,0,18,7,1,0,41,8,255,255,77,6,4,128,32,10,5,9,59,11,9,0,64,11,10,4,79, | ||
23 | 6,252,127,76,4,2,0,0 | ||
24 | #else | ||
25 | 0,1,2,0,0,1,2,24,1,0,0,76,1,2,0,241,135,158,166,3,220,203,178,130,4,0,1,2,0, | ||
26 | 0,1,2,24,1,0,0,76,1,2,0,243,244,148,165,20,198,190,199,252,3,0,1,2,0,0,0,3, | ||
27 | 16,0,5,0,21,1,0,0,76,1,2,0,0,2,9,0,0,0,15,16,0,12,0,16,1,9,0,41,2,1,0,21,3, | ||
28 | 0,0,41,4,1,0,77,2,8,128,18,6,1,0,18,7,5,0,59,8,5,0,66,6,3,2,10,6,0,0,88,7,1, | ||
29 | 128,76,6,2,0,79,2,248,127,75,0,1,0,0,2,10,0,0,0,16,16,0,12,0,16,1,9,0,43,2, | ||
30 | 0,0,18,3,0,0,41,4,0,0,88,5,7,128,18,7,1,0,18,8,5,0,18,9,6,0,66,7,3,2,10,7,0, | ||
31 | 0,88,8,1,128,76,7,2,0,70,5,3,3,82,5,247,127,75,0,1,0,0,1,2,0,0,0,3,16,0,12, | ||
32 | 0,21,1,0,0,76,1,2,0,0,2,10,0,0,2,30,16,0,12,0,21,2,0,0,11,1,0,0,88,3,7,128, | ||
33 | 8,2,0,0,88,3,23,128,59,3,2,0,43,4,0,0,64,4,2,0,76,3,2,0,88,3,18,128,16,1,14, | ||
34 | 0,41,3,1,0,3,3,1,0,88,3,14,128,3,1,2,0,88,3,12,128,59,3,1,0,22,4,1,1,18,5,2, | ||
35 | 0,41,6,1,0,77,4,4,128,23,8,1,7,59,9,7,0,64,9,8,0,79,4,252,127,43,4,0,0,64,4, | ||
36 | 2,0,76,3,2,0,75,0,1,0,0,2,0,5,12,0,0,0,35,16,0,12,0,16,1,14,0,16,2,14,0,16, | ||
37 | 3,14,0,11,4,0,0,88,5,1,128,18,4,0,0,16,4,12,0,3,1,2,0,88,5,24,128,33,5,1,3, | ||
38 | 0,2,3,0,88,6,4,128,2,3,1,0,88,6,2,128,4,4,0,0,88,6,9,128,18,6,1,0,18,7,2,0, | ||
39 | 41,8,1,0,77,6,4,128,32,10,5,9,59,11,9,0,64,11,10,4,79,6,252,127,88,6,8,128, | ||
40 | 18,6,2,0,18,7,1,0,41,8,255,255,77,6,4,128,32,10,5,9,59,11,9,0,64,11,10,4,79, | ||
41 | 6,252,127,76,4,2,0,0 | ||
42 | #endif | ||
43 | }; | ||
44 | |||
45 | static const struct { const char *name; int ofs; } libbc_map[] = { | ||
46 | {"math_deg",0}, | ||
47 | {"math_rad",25}, | ||
48 | {"string_len",50}, | ||
49 | {"table_foreachi",69}, | ||
50 | {"table_foreach",136}, | ||
51 | {"table_getn",207}, | ||
52 | {"table_remove",226}, | ||
53 | {"table_move",355}, | ||
54 | {NULL,502} | ||
55 | }; | ||
56 | |||
diff --git a/src/host/buildvm_peobj.c b/src/host/buildvm_peobj.c index aab00d68..2eb2bb7b 100644 --- a/src/host/buildvm_peobj.c +++ b/src/host/buildvm_peobj.c | |||
@@ -109,6 +109,8 @@ enum { | |||
109 | #if LJ_TARGET_X64 | 109 | #if LJ_TARGET_X64 |
110 | PEOBJ_SECT_PDATA, | 110 | PEOBJ_SECT_PDATA, |
111 | PEOBJ_SECT_XDATA, | 111 | PEOBJ_SECT_XDATA, |
112 | #elif LJ_TARGET_X86 | ||
113 | PEOBJ_SECT_SXDATA, | ||
112 | #endif | 114 | #endif |
113 | PEOBJ_SECT_RDATA_Z, | 115 | PEOBJ_SECT_RDATA_Z, |
114 | PEOBJ_NSECTIONS | 116 | PEOBJ_NSECTIONS |
@@ -208,6 +210,13 @@ void emit_peobj(BuildCtx *ctx) | |||
208 | sofs += (pesect[PEOBJ_SECT_XDATA].nreloc = 1) * PEOBJ_RELOC_SIZE; | 210 | sofs += (pesect[PEOBJ_SECT_XDATA].nreloc = 1) * PEOBJ_RELOC_SIZE; |
209 | /* Flags: 40 = read, 30 = align4, 40 = initialized data. */ | 211 | /* Flags: 40 = read, 30 = align4, 40 = initialized data. */ |
210 | pesect[PEOBJ_SECT_XDATA].flags = 0x40300040; | 212 | pesect[PEOBJ_SECT_XDATA].flags = 0x40300040; |
213 | #elif LJ_TARGET_X86 | ||
214 | memcpy(pesect[PEOBJ_SECT_SXDATA].name, ".sxdata", sizeof(".sxdata")-1); | ||
215 | pesect[PEOBJ_SECT_SXDATA].ofs = sofs; | ||
216 | sofs += (pesect[PEOBJ_SECT_SXDATA].size = 4); | ||
217 | pesect[PEOBJ_SECT_SXDATA].relocofs = sofs; | ||
218 | /* Flags: 40 = read, 30 = align4, 02 = lnk_info, 40 = initialized data. */ | ||
219 | pesect[PEOBJ_SECT_SXDATA].flags = 0x40300240; | ||
211 | #endif | 220 | #endif |
212 | 221 | ||
213 | memcpy(pesect[PEOBJ_SECT_RDATA_Z].name, ".rdata$Z", sizeof(".rdata$Z")-1); | 222 | memcpy(pesect[PEOBJ_SECT_RDATA_Z].name, ".rdata$Z", sizeof(".rdata$Z")-1); |
@@ -232,7 +241,7 @@ void emit_peobj(BuildCtx *ctx) | |||
232 | nrsym = ctx->nrelocsym; | 241 | nrsym = ctx->nrelocsym; |
233 | pehdr.nsyms = 1+PEOBJ_NSECTIONS*2 + 1+ctx->nsym + nrsym; | 242 | pehdr.nsyms = 1+PEOBJ_NSECTIONS*2 + 1+ctx->nsym + nrsym; |
234 | #if LJ_TARGET_X64 | 243 | #if LJ_TARGET_X64 |
235 | pehdr.nsyms += 1; /* Symbol for lj_err_unwind_win64. */ | 244 | pehdr.nsyms += 1; /* Symbol for lj_err_unwind_win. */ |
236 | #endif | 245 | #endif |
237 | 246 | ||
238 | /* Write PE object header and all sections. */ | 247 | /* Write PE object header and all sections. */ |
@@ -312,6 +321,19 @@ 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_X86 | ||
325 | /* Write .sxdata section. */ | ||
326 | for (i = 0; i < nrsym; i++) { | ||
327 | if (!strcmp(ctx->relocsym[i], "_lj_err_unwind_win")) { | ||
328 | uint32_t symidx = 1+2+i; | ||
329 | owrite(ctx, &symidx, 4); | ||
330 | break; | ||
331 | } | ||
332 | } | ||
333 | if (i == nrsym) { | ||
334 | fprintf(stderr, "Error: extern lj_err_unwind_win not used\n"); | ||
335 | exit(1); | ||
336 | } | ||
315 | #endif | 337 | #endif |
316 | 338 | ||
317 | /* Write .rdata$Z section. */ | 339 | /* Write .rdata$Z section. */ |
@@ -333,8 +355,10 @@ void emit_peobj(BuildCtx *ctx) | |||
333 | #if LJ_TARGET_X64 | 355 | #if LJ_TARGET_X64 |
334 | emit_peobj_sym_sect(ctx, pesect, PEOBJ_SECT_PDATA); | 356 | emit_peobj_sym_sect(ctx, pesect, PEOBJ_SECT_PDATA); |
335 | emit_peobj_sym_sect(ctx, pesect, PEOBJ_SECT_XDATA); | 357 | emit_peobj_sym_sect(ctx, pesect, PEOBJ_SECT_XDATA); |
336 | emit_peobj_sym(ctx, "lj_err_unwind_win64", 0, | 358 | emit_peobj_sym(ctx, "lj_err_unwind_win", 0, |
337 | PEOBJ_SECT_UNDEF, PEOBJ_TYPE_FUNC, PEOBJ_SCL_EXTERN); | 359 | PEOBJ_SECT_UNDEF, PEOBJ_TYPE_FUNC, PEOBJ_SCL_EXTERN); |
360 | #elif LJ_TARGET_X86 | ||
361 | emit_peobj_sym_sect(ctx, pesect, PEOBJ_SECT_SXDATA); | ||
338 | #endif | 362 | #endif |
339 | 363 | ||
340 | emit_peobj_sym(ctx, ctx->beginsym, 0, | 364 | 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..6f5a05cc --- /dev/null +++ b/src/host/genlibbc.lua | |||
@@ -0,0 +1,197 @@ | |||
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-2017 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, 0", 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 = {} | ||
83 | for i=0,#bcnames/6-1 do | ||
84 | BC[string.gsub(string.sub(bcnames, i*6+1, i*6+6), " ", "")] = i | ||
85 | end | ||
86 | local xop, xra = isbe and 3 or 0, isbe and 2 or 1 | ||
87 | local xrc, xrb = isbe and 1 or 2, isbe and 0 or 3 | ||
88 | |||
89 | local function fixup_dump(dump, fixup) | ||
90 | local buf = ffi.new("uint8_t[?]", #dump+1, dump) | ||
91 | local p = buf+5 | ||
92 | local n, sizebc | ||
93 | p, n = read_uleb128(p) | ||
94 | local start = p | ||
95 | p = p + 4 | ||
96 | p = read_uleb128(p) | ||
97 | p = read_uleb128(p) | ||
98 | p, sizebc = read_uleb128(p) | ||
99 | local rawtab = {} | ||
100 | for i=0,sizebc-1 do | ||
101 | local op = p[xop] | ||
102 | if op == BC.KSHORT then | ||
103 | local rd = p[xrc] + 256*p[xrb] | ||
104 | rd = bit.arshift(bit.lshift(rd, 16), 16) | ||
105 | local f = fixup[rd] | ||
106 | if f then | ||
107 | if f[1] == "CHECK" then | ||
108 | local tp = f[2] | ||
109 | if tp == "tab" then rawtab[p[xra]] = true end | ||
110 | p[xop] = tp == "num" and BC.ISNUM or BC.ISTYPE | ||
111 | p[xrb] = 0 | ||
112 | p[xrc] = name2itype[tp] | ||
113 | else | ||
114 | error("unhandled fixup type: "..f[1]) | ||
115 | end | ||
116 | end | ||
117 | elseif op == BC.TGETV then | ||
118 | if rawtab[p[xrb]] then | ||
119 | p[xop] = BC.TGETR | ||
120 | end | ||
121 | elseif op == BC.TSETV then | ||
122 | if rawtab[p[xrb]] then | ||
123 | p[xop] = BC.TSETR | ||
124 | end | ||
125 | elseif op == BC.ITERC then | ||
126 | if fixup.PAIRS then | ||
127 | p[xop] = BC.ITERN | ||
128 | end | ||
129 | end | ||
130 | p = p + 4 | ||
131 | end | ||
132 | return ffi.string(start, n) | ||
133 | end | ||
134 | |||
135 | local function find_defs(src) | ||
136 | local defs = {} | ||
137 | for name, code in string.gmatch(src, "LJLIB_LUA%(([^)]*)%)%s*/%*(.-)%*/") do | ||
138 | local env = {} | ||
139 | local tcode, fixup = transform_lua(code) | ||
140 | local func = assert(load(tcode, "", nil, env))() | ||
141 | defs[name] = fixup_dump(string.dump(func, true), fixup) | ||
142 | defs[#defs+1] = name | ||
143 | end | ||
144 | return defs | ||
145 | end | ||
146 | |||
147 | local function gen_header(defs) | ||
148 | local t = {} | ||
149 | local function w(x) t[#t+1] = x end | ||
150 | w("/* This is a generated file. DO NOT EDIT! */\n\n") | ||
151 | w("static const int libbc_endian = ") w(isbe and 1 or 0) w(";\n\n") | ||
152 | local s = "" | ||
153 | for _,name in ipairs(defs) do | ||
154 | s = s .. defs[name] | ||
155 | end | ||
156 | w("static const uint8_t libbc_code[] = {\n") | ||
157 | local n = 0 | ||
158 | for i=1,#s do | ||
159 | local x = string.byte(s, i) | ||
160 | w(x); w(",") | ||
161 | n = n + (x < 10 and 2 or (x < 100 and 3 or 4)) | ||
162 | if n >= 75 then n = 0; w("\n") end | ||
163 | end | ||
164 | w("0\n};\n\n") | ||
165 | w("static const struct { const char *name; int ofs; } libbc_map[] = {\n") | ||
166 | local m = 0 | ||
167 | for _,name in ipairs(defs) do | ||
168 | w('{"'); w(name); w('",'); w(m) w('},\n') | ||
169 | m = m + #defs[name] | ||
170 | end | ||
171 | w("{NULL,"); w(m); w("}\n};\n\n") | ||
172 | return table.concat(t) | ||
173 | end | ||
174 | |||
175 | local function write_file(name, data) | ||
176 | if name == "-" then | ||
177 | assert(io.write(data)) | ||
178 | assert(io.flush()) | ||
179 | else | ||
180 | local fp = io.open(name) | ||
181 | if fp then | ||
182 | local old = fp:read("*a") | ||
183 | fp:close() | ||
184 | if data == old then return end | ||
185 | end | ||
186 | fp = assert(io.open(name, "w")) | ||
187 | assert(fp:write(data)) | ||
188 | assert(fp:close()) | ||
189 | end | ||
190 | end | ||
191 | |||
192 | local outfile = parse_arg(arg) | ||
193 | local src = read_files(arg) | ||
194 | local defs = find_defs(src) | ||
195 | local hdr = gen_header(defs) | ||
196 | write_file(outfile, hdr) | ||
197 | |||