diff options
Diffstat (limited to 'src/host')
-rw-r--r-- | src/host/buildvm_lib.c | 32 | ||||
-rw-r--r-- | src/host/buildvm_libbc.h | 4 | ||||
-rw-r--r-- | src/host/genlibbc.lua | 108 |
3 files changed, 122 insertions, 22 deletions
diff --git a/src/host/buildvm_lib.c b/src/host/buildvm_lib.c index 182ab90f..dcd3ca41 100644 --- a/src/host/buildvm_lib.c +++ b/src/host/buildvm_lib.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 | #include "lj_bc.h" | ||
8 | #include "lj_lib.h" | 9 | #include "lj_lib.h" |
9 | #include "buildvm_libbc.h" | 10 | #include "buildvm_libbc.h" |
10 | 11 | ||
@@ -152,28 +153,36 @@ static void libdef_func(BuildCtx *ctx, char *p, int arg) | |||
152 | regfunc = REGFUNC_OK; | 153 | regfunc = REGFUNC_OK; |
153 | } | 154 | } |
154 | 155 | ||
155 | static uint32_t libdef_uleb128(uint8_t **pp) | 156 | static uint8_t *libdef_uleb128(uint8_t *p, uint32_t *vv) |
156 | { | 157 | { |
157 | uint8_t *p = *pp; | ||
158 | uint32_t v = *p++; | 158 | uint32_t v = *p++; |
159 | if (v >= 0x80) { | 159 | if (v >= 0x80) { |
160 | int sh = 0; v &= 0x7f; | 160 | int sh = 0; v &= 0x7f; |
161 | do { v |= ((*p & 0x7f) << (sh += 7)); } while (*p++ >= 0x80); | 161 | do { v |= ((*p & 0x7f) << (sh += 7)); } while (*p++ >= 0x80); |
162 | } | 162 | } |
163 | *pp = p; | 163 | *vv = v; |
164 | return v; | 164 | return p; |
165 | } | 165 | } |
166 | 166 | ||
167 | static void libdef_swapbc(uint8_t *p) | 167 | static void libdef_fixupbc(uint8_t *p) |
168 | { | 168 | { |
169 | uint32_t i, sizebc; | 169 | uint32_t i, sizebc; |
170 | p += 4; | 170 | p += 4; |
171 | libdef_uleb128(&p); | 171 | p = libdef_uleb128(p, &sizebc); |
172 | libdef_uleb128(&p); | 172 | p = libdef_uleb128(p, &sizebc); |
173 | sizebc = libdef_uleb128(&p); | 173 | p = libdef_uleb128(p, &sizebc); |
174 | for (i = 0; i < sizebc; i++, p += 4) { | 174 | for (i = 0; i < sizebc; i++, p += 4) { |
175 | uint8_t t = p[0]; p[0] = p[3]; p[3] = t; | 175 | uint8_t op = p[libbc_endian ? 3 : 0]; |
176 | t = p[1]; p[1] = p[2]; p[2] = t; | 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; | ||
177 | } | 186 | } |
178 | } | 187 | } |
179 | 188 | ||
@@ -190,8 +199,7 @@ static void libdef_lua(BuildCtx *ctx, char *p, int arg) | |||
190 | *optr++ = LIBINIT_LUA; | 199 | *optr++ = LIBINIT_LUA; |
191 | libdef_name(p, 0); | 200 | libdef_name(p, 0); |
192 | memcpy(optr, libbc_code + ofs, len); | 201 | memcpy(optr, libbc_code + ofs, len); |
193 | if (libbc_endian != LJ_BE) | 202 | libdef_fixupbc(optr); |
194 | libdef_swapbc(optr); | ||
195 | optr += len; | 203 | optr += len; |
196 | return; | 204 | return; |
197 | } | 205 | } |
diff --git a/src/host/buildvm_libbc.h b/src/host/buildvm_libbc.h index ee97836a..6b0e1d03 100644 --- a/src/host/buildvm_libbc.h +++ b/src/host/buildvm_libbc.h | |||
@@ -3,8 +3,8 @@ | |||
3 | static const int libbc_endian = 0; | 3 | static const int libbc_endian = 0; |
4 | 4 | ||
5 | static const uint8_t libbc_code[] = { | 5 | static const uint8_t libbc_code[] = { |
6 | 0,1,2,0,0,1,2,22,1,0,0,72,1,2,0,241,135,158,166,3,220,203,178,130,4,0,1,2,0, | 6 | 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, |
7 | 0,1,2,22,1,0,0,72,1,2,0,243,244,148,165,20,198,190,199,252,3,0 | 7 | 0,1,2,24,1,0,0,76,1,2,0,243,244,148,165,20,198,190,199,252,3,0 |
8 | }; | 8 | }; |
9 | 9 | ||
10 | static const struct { const char *name; int ofs; } libbc_map[] = { | 10 | static const struct { const char *name; int ofs; } libbc_map[] = { |
diff --git a/src/host/genlibbc.lua b/src/host/genlibbc.lua index bdcfb588..72c55d73 100644 --- a/src/host/genlibbc.lua +++ b/src/host/genlibbc.lua | |||
@@ -6,6 +6,15 @@ | |||
6 | -- Released under the MIT license. See Copyright Notice in luajit.h | 6 | -- Released under the MIT license. See Copyright Notice in luajit.h |
7 | ---------------------------------------------------------------------------- | 7 | ---------------------------------------------------------------------------- |
8 | 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 | |||
9 | local function usage(arg) | 18 | local function usage(arg) |
10 | io.stderr:write("Usage: ", arg and arg[0] or "genlibbc", | 19 | io.stderr:write("Usage: ", arg and arg[0] or "genlibbc", |
11 | " [-o buildvm_libbc.h] lib_*.c\n") | 20 | " [-o buildvm_libbc.h] lib_*.c\n") |
@@ -36,15 +45,100 @@ local function read_files(names) | |||
36 | return src | 45 | return src |
37 | end | 46 | end |
38 | 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, 128), 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 | |||
39 | local function find_defs(src) | 135 | local function find_defs(src) |
40 | local defs = {} | 136 | local defs = {} |
41 | for name, code in string.gmatch(src, "LJLIB_LUA%(([^)]*)%)%s*/%*(.-)%*/") do | 137 | for name, code in string.gmatch(src, "LJLIB_LUA%(([^)]*)%)%s*/%*(.-)%*/") do |
42 | local env = {} | 138 | local env = {} |
43 | local func = assert(load("return "..code, "", nil, env))() | 139 | local tcode, fixup = transform_lua(code) |
44 | local d = string.dump(func, true) | 140 | local func = assert(load(tcode, "", nil, env))() |
45 | local ofs = 6 | 141 | defs[name] = fixup_dump(string.dump(func, true), fixup) |
46 | while string.byte(d, ofs) > 127 do ofs = ofs + 1 end | ||
47 | defs[name] = string.sub(d, ofs+1, -2) | ||
48 | defs[#defs+1] = name | 142 | defs[#defs+1] = name |
49 | end | 143 | end |
50 | return defs | 144 | return defs |
@@ -54,9 +148,7 @@ local function gen_header(defs) | |||
54 | local t = {} | 148 | local t = {} |
55 | local function w(x) t[#t+1] = x end | 149 | local function w(x) t[#t+1] = x end |
56 | w("/* This is a generated file. DO NOT EDIT! */\n\n") | 150 | w("/* This is a generated file. DO NOT EDIT! */\n\n") |
57 | w("static const int libbc_endian = ") | 151 | w("static const int libbc_endian = ") w(isbe and 1 or 0) w(";\n\n") |
58 | w(string.byte(string.dump(function() end), 5) % 2) | ||
59 | w(";\n\n") | ||
60 | local s = "" | 152 | local s = "" |
61 | for _,name in ipairs(defs) do | 153 | for _,name in ipairs(defs) do |
62 | s = s .. defs[name] | 154 | s = s .. defs[name] |