diff options
Diffstat (limited to 'src/jit/bcsave.lua')
-rw-r--r-- | src/jit/bcsave.lua | 106 |
1 files changed, 56 insertions, 50 deletions
diff --git a/src/jit/bcsave.lua b/src/jit/bcsave.lua index 58351c16..42d7240b 100644 --- a/src/jit/bcsave.lua +++ b/src/jit/bcsave.lua | |||
@@ -11,12 +11,16 @@ | |||
11 | ------------------------------------------------------------------------------ | 11 | ------------------------------------------------------------------------------ |
12 | 12 | ||
13 | local jit = require("jit") | 13 | local jit = require("jit") |
14 | assert(jit.version_num == 20005, "LuaJIT core/library version mismatch") | 14 | assert(jit.version_num == 20100, "LuaJIT core/library version mismatch") |
15 | local bit = require("bit") | 15 | local bit = require("bit") |
16 | 16 | ||
17 | -- Symbol name prefix for LuaJIT bytecode. | 17 | -- Symbol name prefix for LuaJIT bytecode. |
18 | local LJBC_PREFIX = "luaJIT_BC_" | 18 | local LJBC_PREFIX = "luaJIT_BC_" |
19 | 19 | ||
20 | local type, assert = type, assert | ||
21 | local format = string.format | ||
22 | local tremove, tconcat = table.remove, table.concat | ||
23 | |||
20 | ------------------------------------------------------------------------------ | 24 | ------------------------------------------------------------------------------ |
21 | 25 | ||
22 | local function usage() | 26 | local function usage() |
@@ -63,8 +67,18 @@ local map_type = { | |||
63 | } | 67 | } |
64 | 68 | ||
65 | local map_arch = { | 69 | local map_arch = { |
66 | x86 = true, x64 = true, arm = true, ppc = true, ppcspe = true, | 70 | x86 = { e = "le", b = 32, m = 3, p = 0x14c, }, |
67 | mips = true, mipsel = true, | 71 | x64 = { e = "le", b = 64, m = 62, p = 0x8664, }, |
72 | arm = { e = "le", b = 32, m = 40, p = 0x1c0, }, | ||
73 | arm64 = { e = "le", b = 64, m = 183, p = 0xaa64, }, | ||
74 | arm64be = { e = "be", b = 64, m = 183, }, | ||
75 | ppc = { e = "be", b = 32, m = 20, }, | ||
76 | mips = { e = "be", b = 32, m = 8, f = 0x50001006, }, | ||
77 | mipsel = { e = "le", b = 32, m = 8, f = 0x50001006, }, | ||
78 | mips64 = { e = "be", b = 64, m = 8, f = 0x80000007, }, | ||
79 | mips64el = { e = "le", b = 64, m = 8, f = 0x80000007, }, | ||
80 | mips64r6 = { e = "be", b = 64, m = 8, f = 0xa0000407, }, | ||
81 | mips64r6el = { e = "le", b = 64, m = 8, f = 0xa0000407, }, | ||
68 | } | 82 | } |
69 | 83 | ||
70 | local map_os = { | 84 | local map_os = { |
@@ -73,33 +87,33 @@ local map_os = { | |||
73 | } | 87 | } |
74 | 88 | ||
75 | local function checkarg(str, map, err) | 89 | local function checkarg(str, map, err) |
76 | str = string.lower(str) | 90 | str = str:lower() |
77 | local s = check(map[str], "unknown ", err) | 91 | local s = check(map[str], "unknown ", err) |
78 | return s == true and str or s | 92 | return type(s) == "string" and s or str |
79 | end | 93 | end |
80 | 94 | ||
81 | local function detecttype(str) | 95 | local function detecttype(str) |
82 | local ext = string.match(string.lower(str), "%.(%a+)$") | 96 | local ext = str:lower():match("%.(%a+)$") |
83 | return map_type[ext] or "raw" | 97 | return map_type[ext] or "raw" |
84 | end | 98 | end |
85 | 99 | ||
86 | local function checkmodname(str) | 100 | local function checkmodname(str) |
87 | check(string.match(str, "^[%w_.%-]+$"), "bad module name") | 101 | check(str:match("^[%w_.%-]+$"), "bad module name") |
88 | return string.gsub(str, "[%.%-]", "_") | 102 | return str:gsub("[%.%-]", "_") |
89 | end | 103 | end |
90 | 104 | ||
91 | local function detectmodname(str) | 105 | local function detectmodname(str) |
92 | if type(str) == "string" then | 106 | if type(str) == "string" then |
93 | local tail = string.match(str, "[^/\\]+$") | 107 | local tail = str:match("[^/\\]+$") |
94 | if tail then str = tail end | 108 | if tail then str = tail end |
95 | local head = string.match(str, "^(.*)%.[^.]*$") | 109 | local head = str:match("^(.*)%.[^.]*$") |
96 | if head then str = head end | 110 | if head then str = head end |
97 | str = string.match(str, "^[%w_.%-]+") | 111 | str = str:match("^[%w_.%-]+") |
98 | else | 112 | else |
99 | str = nil | 113 | str = nil |
100 | end | 114 | end |
101 | check(str, "cannot derive module name, use -n name") | 115 | check(str, "cannot derive module name, use -n name") |
102 | return string.gsub(str, "[%.%-]", "_") | 116 | return str:gsub("[%.%-]", "_") |
103 | end | 117 | end |
104 | 118 | ||
105 | ------------------------------------------------------------------------------ | 119 | ------------------------------------------------------------------------------ |
@@ -118,19 +132,19 @@ end | |||
118 | local function bcsave_c(ctx, output, s) | 132 | local function bcsave_c(ctx, output, s) |
119 | local fp = savefile(output, "w") | 133 | local fp = savefile(output, "w") |
120 | if ctx.type == "c" then | 134 | if ctx.type == "c" then |
121 | fp:write(string.format([[ | 135 | fp:write(format([[ |
122 | #ifdef __cplusplus | 136 | #ifdef __cplusplus |
123 | extern "C" | 137 | extern "C" |
124 | #endif | 138 | #endif |
125 | #ifdef _WIN32 | 139 | #ifdef _WIN32 |
126 | __declspec(dllexport) | 140 | __declspec(dllexport) |
127 | #endif | 141 | #endif |
128 | const char %s%s[] = { | 142 | const unsigned char %s%s[] = { |
129 | ]], LJBC_PREFIX, ctx.modname)) | 143 | ]], LJBC_PREFIX, ctx.modname)) |
130 | else | 144 | else |
131 | fp:write(string.format([[ | 145 | fp:write(format([[ |
132 | #define %s%s_SIZE %d | 146 | #define %s%s_SIZE %d |
133 | static const char %s%s[] = { | 147 | static const unsigned char %s%s[] = { |
134 | ]], LJBC_PREFIX, ctx.modname, #s, LJBC_PREFIX, ctx.modname)) | 148 | ]], LJBC_PREFIX, ctx.modname, #s, LJBC_PREFIX, ctx.modname)) |
135 | end | 149 | end |
136 | local t, n, m = {}, 0, 0 | 150 | local t, n, m = {}, 0, 0 |
@@ -138,13 +152,13 @@ static const char %s%s[] = { | |||
138 | local b = tostring(string.byte(s, i)) | 152 | local b = tostring(string.byte(s, i)) |
139 | m = m + #b + 1 | 153 | m = m + #b + 1 |
140 | if m > 78 then | 154 | if m > 78 then |
141 | fp:write(table.concat(t, ",", 1, n), ",\n") | 155 | fp:write(tconcat(t, ",", 1, n), ",\n") |
142 | n, m = 0, #b + 1 | 156 | n, m = 0, #b + 1 |
143 | end | 157 | end |
144 | n = n + 1 | 158 | n = n + 1 |
145 | t[n] = b | 159 | t[n] = b |
146 | end | 160 | end |
147 | bcsave_tail(fp, output, table.concat(t, ",", 1, n).."\n};\n") | 161 | bcsave_tail(fp, output, tconcat(t, ",", 1, n).."\n};\n") |
148 | end | 162 | end |
149 | 163 | ||
150 | local function bcsave_elfobj(ctx, output, s, ffi) | 164 | local function bcsave_elfobj(ctx, output, s, ffi) |
@@ -199,12 +213,8 @@ typedef struct { | |||
199 | } ELF64obj; | 213 | } ELF64obj; |
200 | ]] | 214 | ]] |
201 | local symname = LJBC_PREFIX..ctx.modname | 215 | local symname = LJBC_PREFIX..ctx.modname |
202 | local is64, isbe = false, false | 216 | local ai = assert(map_arch[ctx.arch]) |
203 | if ctx.arch == "x64" then | 217 | local is64, isbe = ai.b == 64, ai.e == "be" |
204 | is64 = true | ||
205 | elseif ctx.arch == "ppc" or ctx.arch == "ppcspe" or ctx.arch == "mips" then | ||
206 | isbe = true | ||
207 | end | ||
208 | 218 | ||
209 | -- Handle different host/target endianess. | 219 | -- Handle different host/target endianess. |
210 | local function f32(x) return x end | 220 | local function f32(x) return x end |
@@ -237,10 +247,8 @@ typedef struct { | |||
237 | hdr.eendian = isbe and 2 or 1 | 247 | hdr.eendian = isbe and 2 or 1 |
238 | hdr.eversion = 1 | 248 | hdr.eversion = 1 |
239 | hdr.type = f16(1) | 249 | hdr.type = f16(1) |
240 | hdr.machine = f16(({ x86=3, x64=62, arm=40, ppc=20, ppcspe=20, mips=8, mipsel=8 })[ctx.arch]) | 250 | hdr.machine = f16(ai.m) |
241 | if ctx.arch == "mips" or ctx.arch == "mipsel" then | 251 | hdr.flags = f32(ai.f or 0) |
242 | hdr.flags = f32(0x50001006) | ||
243 | end | ||
244 | hdr.version = f32(1) | 252 | hdr.version = f32(1) |
245 | hdr.shofs = fofs(ffi.offsetof(o, "sect")) | 253 | hdr.shofs = fofs(ffi.offsetof(o, "sect")) |
246 | hdr.ehsize = f16(ffi.sizeof(hdr)) | 254 | hdr.ehsize = f16(ffi.sizeof(hdr)) |
@@ -336,12 +344,8 @@ typedef struct { | |||
336 | } PEobj; | 344 | } PEobj; |
337 | ]] | 345 | ]] |
338 | local symname = LJBC_PREFIX..ctx.modname | 346 | local symname = LJBC_PREFIX..ctx.modname |
339 | local is64 = false | 347 | local ai = assert(map_arch[ctx.arch]) |
340 | if ctx.arch == "x86" then | 348 | local is64 = ai.b == 64 |
341 | symname = "_"..symname | ||
342 | elseif ctx.arch == "x64" then | ||
343 | is64 = true | ||
344 | end | ||
345 | local symexport = " /EXPORT:"..symname..",DATA " | 349 | local symexport = " /EXPORT:"..symname..",DATA " |
346 | 350 | ||
347 | -- The file format is always little-endian. Swap if the host is big-endian. | 351 | -- The file format is always little-endian. Swap if the host is big-endian. |
@@ -355,7 +359,7 @@ typedef struct { | |||
355 | -- Create PE object and fill in header. | 359 | -- Create PE object and fill in header. |
356 | local o = ffi.new("PEobj") | 360 | local o = ffi.new("PEobj") |
357 | local hdr = o.hdr | 361 | local hdr = o.hdr |
358 | hdr.arch = f16(({ x86=0x14c, x64=0x8664, arm=0x1c0, ppc=0x1f2, mips=0x366, mipsel=0x366 })[ctx.arch]) | 362 | hdr.arch = f16(assert(ai.p)) |
359 | hdr.nsects = f16(2) | 363 | hdr.nsects = f16(2) |
360 | hdr.symtabofs = f32(ffi.offsetof(o, "sym0")) | 364 | hdr.symtabofs = f32(ffi.offsetof(o, "sym0")) |
361 | hdr.nsyms = f32(6) | 365 | hdr.nsyms = f32(6) |
@@ -477,13 +481,13 @@ typedef struct { | |||
477 | } mach_obj_64; | 481 | } mach_obj_64; |
478 | typedef struct { | 482 | typedef struct { |
479 | mach_fat_header fat; | 483 | mach_fat_header fat; |
480 | mach_fat_arch fat_arch[4]; | 484 | mach_fat_arch fat_arch[2]; |
481 | struct { | 485 | struct { |
482 | mach_header hdr; | 486 | mach_header hdr; |
483 | mach_segment_command seg; | 487 | mach_segment_command seg; |
484 | mach_section sec; | 488 | mach_section sec; |
485 | mach_symtab_command sym; | 489 | mach_symtab_command sym; |
486 | } arch[4]; | 490 | } arch[2]; |
487 | mach_nlist sym_entry; | 491 | mach_nlist sym_entry; |
488 | uint8_t space[4096]; | 492 | uint8_t space[4096]; |
489 | } mach_fat_obj; | 493 | } mach_fat_obj; |
@@ -494,6 +498,8 @@ typedef struct { | |||
494 | is64, align, mobj = true, 8, "mach_obj_64" | 498 | is64, align, mobj = true, 8, "mach_obj_64" |
495 | elseif ctx.arch == "arm" then | 499 | elseif ctx.arch == "arm" then |
496 | isfat, mobj = true, "mach_fat_obj" | 500 | isfat, mobj = true, "mach_fat_obj" |
501 | elseif ctx.arch == "arm64" then | ||
502 | is64, align, isfat, mobj = true, 8, true, "mach_fat_obj" | ||
497 | else | 503 | else |
498 | check(ctx.arch == "x86", "unsupported architecture for OSX") | 504 | check(ctx.arch == "x86", "unsupported architecture for OSX") |
499 | end | 505 | end |
@@ -503,8 +509,8 @@ typedef struct { | |||
503 | -- Create Mach-O object and fill in header. | 509 | -- Create Mach-O object and fill in header. |
504 | local o = ffi.new(mobj) | 510 | local o = ffi.new(mobj) |
505 | local mach_size = aligned(ffi.offsetof(o, "space")+#symname+2, align) | 511 | local mach_size = aligned(ffi.offsetof(o, "space")+#symname+2, align) |
506 | local cputype = ({ x86={7}, x64={0x01000007}, arm={7,12,12,12} })[ctx.arch] | 512 | local cputype = ({ x86={7}, x64={0x01000007}, arm={7,12}, arm64={0x01000007,0x0100000c} })[ctx.arch] |
507 | local cpusubtype = ({ x86={3}, x64={3}, arm={3,6,9,11} })[ctx.arch] | 513 | local cpusubtype = ({ x86={3}, x64={3}, arm={3,9}, arm64={3,0} })[ctx.arch] |
508 | if isfat then | 514 | if isfat then |
509 | o.fat.magic = be32(0xcafebabe) | 515 | o.fat.magic = be32(0xcafebabe) |
510 | o.fat.nfat_arch = be32(#cpusubtype) | 516 | o.fat.nfat_arch = be32(#cpusubtype) |
@@ -603,16 +609,16 @@ local function docmd(...) | |||
603 | local n = 1 | 609 | local n = 1 |
604 | local list = false | 610 | local list = false |
605 | local ctx = { | 611 | local ctx = { |
606 | strip = true, arch = jit.arch, os = string.lower(jit.os), | 612 | strip = true, arch = jit.arch, os = jit.os:lower(), |
607 | type = false, modname = false, | 613 | type = false, modname = false, |
608 | } | 614 | } |
609 | while n <= #arg do | 615 | while n <= #arg do |
610 | local a = arg[n] | 616 | local a = arg[n] |
611 | if type(a) == "string" and string.sub(a, 1, 1) == "-" and a ~= "-" then | 617 | if type(a) == "string" and a:sub(1, 1) == "-" and a ~= "-" then |
612 | table.remove(arg, n) | 618 | tremove(arg, n) |
613 | if a == "--" then break end | 619 | if a == "--" then break end |
614 | for m=2,#a do | 620 | for m=2,#a do |
615 | local opt = string.sub(a, m, m) | 621 | local opt = a:sub(m, m) |
616 | if opt == "l" then | 622 | if opt == "l" then |
617 | list = true | 623 | list = true |
618 | elseif opt == "s" then | 624 | elseif opt == "s" then |
@@ -625,13 +631,13 @@ local function docmd(...) | |||
625 | if n ~= 1 then usage() end | 631 | if n ~= 1 then usage() end |
626 | arg[1] = check(loadstring(arg[1])) | 632 | arg[1] = check(loadstring(arg[1])) |
627 | elseif opt == "n" then | 633 | elseif opt == "n" then |
628 | ctx.modname = checkmodname(table.remove(arg, n)) | 634 | ctx.modname = checkmodname(tremove(arg, n)) |
629 | elseif opt == "t" then | 635 | elseif opt == "t" then |
630 | ctx.type = checkarg(table.remove(arg, n), map_type, "file type") | 636 | ctx.type = checkarg(tremove(arg, n), map_type, "file type") |
631 | elseif opt == "a" then | 637 | elseif opt == "a" then |
632 | ctx.arch = checkarg(table.remove(arg, n), map_arch, "architecture") | 638 | ctx.arch = checkarg(tremove(arg, n), map_arch, "architecture") |
633 | elseif opt == "o" then | 639 | elseif opt == "o" then |
634 | ctx.os = checkarg(table.remove(arg, n), map_os, "OS name") | 640 | ctx.os = checkarg(tremove(arg, n), map_os, "OS name") |
635 | else | 641 | else |
636 | usage() | 642 | usage() |
637 | end | 643 | end |
@@ -653,7 +659,7 @@ end | |||
653 | ------------------------------------------------------------------------------ | 659 | ------------------------------------------------------------------------------ |
654 | 660 | ||
655 | -- Public module functions. | 661 | -- Public module functions. |
656 | module(...) | 662 | return { |
657 | 663 | start = docmd -- Process -b command line option. | |
658 | start = docmd -- Process -b command line option. | 664 | } |
659 | 665 | ||