diff options
Diffstat (limited to 'src/jit/bcsave.lua')
-rw-r--r-- | src/jit/bcsave.lua | 84 |
1 files changed, 44 insertions, 40 deletions
diff --git a/src/jit/bcsave.lua b/src/jit/bcsave.lua index 2553d97e..41081184 100644 --- a/src/jit/bcsave.lua +++ b/src/jit/bcsave.lua | |||
@@ -17,6 +17,10 @@ local bit = require("bit") | |||
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, arm64 = true, arm64be = true, | 70 | x86 = { e = "le", b = 32, m = 3, p = 0x14c, }, |
67 | ppc = true, 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,7 +132,7 @@ 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 |
@@ -128,7 +142,7 @@ __declspec(dllexport) | |||
128 | const unsigned 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 unsigned 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)) |
@@ -138,13 +152,13 @@ static const unsigned 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" or ctx.arch == "arm64" or ctx.arch == "arm64be" then | 217 | local is64, isbe = ai.b == 64, ai.e == "be" |
204 | is64 = true | ||
205 | elseif ctx.arch == "ppc" 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, arm64=183, arm64be=183, ppc=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) |
@@ -605,16 +609,16 @@ local function docmd(...) | |||
605 | local n = 1 | 609 | local n = 1 |
606 | local list = false | 610 | local list = false |
607 | local ctx = { | 611 | local ctx = { |
608 | strip = true, arch = jit.arch, os = string.lower(jit.os), | 612 | strip = true, arch = jit.arch, os = jit.os:lower(), |
609 | type = false, modname = false, | 613 | type = false, modname = false, |
610 | } | 614 | } |
611 | while n <= #arg do | 615 | while n <= #arg do |
612 | local a = arg[n] | 616 | local a = arg[n] |
613 | 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 |
614 | table.remove(arg, n) | 618 | tremove(arg, n) |
615 | if a == "--" then break end | 619 | if a == "--" then break end |
616 | for m=2,#a do | 620 | for m=2,#a do |
617 | local opt = string.sub(a, m, m) | 621 | local opt = a:sub(m, m) |
618 | if opt == "l" then | 622 | if opt == "l" then |
619 | list = true | 623 | list = true |
620 | elseif opt == "s" then | 624 | elseif opt == "s" then |
@@ -627,13 +631,13 @@ local function docmd(...) | |||
627 | if n ~= 1 then usage() end | 631 | if n ~= 1 then usage() end |
628 | arg[1] = check(loadstring(arg[1])) | 632 | arg[1] = check(loadstring(arg[1])) |
629 | elseif opt == "n" then | 633 | elseif opt == "n" then |
630 | ctx.modname = checkmodname(table.remove(arg, n)) | 634 | ctx.modname = checkmodname(tremove(arg, n)) |
631 | elseif opt == "t" then | 635 | elseif opt == "t" then |
632 | ctx.type = checkarg(table.remove(arg, n), map_type, "file type") | 636 | ctx.type = checkarg(tremove(arg, n), map_type, "file type") |
633 | elseif opt == "a" then | 637 | elseif opt == "a" then |
634 | ctx.arch = checkarg(table.remove(arg, n), map_arch, "architecture") | 638 | ctx.arch = checkarg(tremove(arg, n), map_arch, "architecture") |
635 | elseif opt == "o" then | 639 | elseif opt == "o" then |
636 | ctx.os = checkarg(table.remove(arg, n), map_os, "OS name") | 640 | ctx.os = checkarg(tremove(arg, n), map_os, "OS name") |
637 | else | 641 | else |
638 | usage() | 642 | usage() |
639 | end | 643 | end |