diff options
| author | Mike Pall <mike> | 2013-02-22 01:40:41 +0100 |
|---|---|---|
| committer | Mike Pall <mike> | 2013-02-22 01:40:41 +0100 |
| commit | e20157c6e68472e7c4d82d9ed4c0bb5be029c388 (patch) | |
| tree | b26bfadc10b7301d73b84293630c44e7d1fb37f9 /src/host | |
| parent | c3219b7d177f6722b9de808cfd3d3dbfc6808e6f (diff) | |
| download | luajit-e20157c6e68472e7c4d82d9ed4c0bb5be029c388.tar.gz luajit-e20157c6e68472e7c4d82d9ed4c0bb5be029c388.tar.bz2 luajit-e20157c6e68472e7c4d82d9ed4c0bb5be029c388.zip | |
Add support for embedding LuaJIT bytecode for builtins.
Diffstat (limited to 'src/host')
| -rw-r--r-- | src/host/buildvm_lib.c | 51 | ||||
| -rw-r--r-- | src/host/buildvm_libbc.h | 12 | ||||
| -rw-r--r-- | src/host/genlibbc.lua | 68 |
3 files changed, 131 insertions, 0 deletions
diff --git a/src/host/buildvm_lib.c b/src/host/buildvm_lib.c index 40141dfb..182ab90f 100644 --- a/src/host/buildvm_lib.c +++ b/src/host/buildvm_lib.c | |||
| @@ -6,6 +6,7 @@ | |||
| 6 | #include "buildvm.h" | 6 | #include "buildvm.h" |
| 7 | #include "lj_obj.h" | 7 | #include "lj_obj.h" |
| 8 | #include "lj_lib.h" | 8 | #include "lj_lib.h" |
| 9 | #include "buildvm_libbc.h" | ||
| 9 | 10 | ||
| 10 | /* Context for library definitions. */ | 11 | /* Context for library definitions. */ |
| 11 | static uint8_t obuf[8192]; | 12 | static uint8_t obuf[8192]; |
| @@ -151,6 +152,55 @@ static void libdef_func(BuildCtx *ctx, char *p, int arg) | |||
| 151 | regfunc = REGFUNC_OK; | 152 | regfunc = REGFUNC_OK; |
| 152 | } | 153 | } |
| 153 | 154 | ||
| 155 | static uint32_t libdef_uleb128(uint8_t **pp) | ||
| 156 | { | ||
| 157 | uint8_t *p = *pp; | ||
| 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 | *pp = p; | ||
| 164 | return v; | ||
| 165 | } | ||
| 166 | |||
| 167 | static void libdef_swapbc(uint8_t *p) | ||
| 168 | { | ||
| 169 | uint32_t i, sizebc; | ||
| 170 | p += 4; | ||
| 171 | libdef_uleb128(&p); | ||
| 172 | libdef_uleb128(&p); | ||
| 173 | sizebc = libdef_uleb128(&p); | ||
| 174 | for (i = 0; i < sizebc; i++, p += 4) { | ||
| 175 | uint8_t t = p[0]; p[0] = p[3]; p[3] = t; | ||
| 176 | t = p[1]; p[1] = p[2]; p[2] = t; | ||
| 177 | } | ||
| 178 | } | ||
| 179 | |||
| 180 | static void libdef_lua(BuildCtx *ctx, char *p, int arg) | ||
| 181 | { | ||
| 182 | UNUSED(arg); | ||
| 183 | if (ctx->mode == BUILD_libdef) { | ||
| 184 | int i; | ||
| 185 | for (i = 0; libbc_map[i].name != NULL; i++) { | ||
| 186 | if (!strcmp(libbc_map[i].name, p)) { | ||
| 187 | int ofs = libbc_map[i].ofs; | ||
| 188 | int len = libbc_map[i+1].ofs - ofs; | ||
| 189 | obuf[2]++; /* Bump hash table size. */ | ||
| 190 | *optr++ = LIBINIT_LUA; | ||
| 191 | libdef_name(p, 0); | ||
| 192 | memcpy(optr, libbc_code + ofs, len); | ||
| 193 | if (libbc_endian != LJ_BE) | ||
| 194 | libdef_swapbc(optr); | ||
| 195 | optr += len; | ||
| 196 | return; | ||
| 197 | } | ||
| 198 | } | ||
| 199 | fprintf(stderr, "Error: missing libbc definition for %s\n", p); | ||
| 200 | exit(1); | ||
| 201 | } | ||
| 202 | } | ||
| 203 | |||
| 154 | static uint32_t find_rec(char *name) | 204 | static uint32_t find_rec(char *name) |
| 155 | { | 205 | { |
| 156 | char *p = (char *)obuf; | 206 | char *p = (char *)obuf; |
| @@ -277,6 +327,7 @@ static const LibDefHandler libdef_handlers[] = { | |||
| 277 | { "CF(", ")", libdef_func, LIBINIT_CF }, | 327 | { "CF(", ")", libdef_func, LIBINIT_CF }, |
| 278 | { "ASM(", ")", libdef_func, LIBINIT_ASM }, | 328 | { "ASM(", ")", libdef_func, LIBINIT_ASM }, |
| 279 | { "ASM_(", ")", libdef_func, LIBINIT_ASM_ }, | 329 | { "ASM_(", ")", libdef_func, LIBINIT_ASM_ }, |
| 330 | { "LUA(", ")", libdef_lua, 0 }, | ||
| 280 | { "REC(", ")", libdef_rec, 0 }, | 331 | { "REC(", ")", libdef_rec, 0 }, |
| 281 | { "PUSH(", ")", libdef_push, 0 }, | 332 | { "PUSH(", ")", libdef_push, 0 }, |
| 282 | { "SET(", ")", libdef_set, 0 }, | 333 | { "SET(", ")", libdef_set, 0 }, |
diff --git a/src/host/buildvm_libbc.h b/src/host/buildvm_libbc.h new file mode 100644 index 00000000..d2d83ea6 --- /dev/null +++ b/src/host/buildvm_libbc.h | |||
| @@ -0,0 +1,12 @@ | |||
| 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 | 0 | ||
| 7 | }; | ||
| 8 | |||
| 9 | static const struct { const char *name; int ofs; } libbc_map[] = { | ||
| 10 | {NULL,0} | ||
| 11 | }; | ||
| 12 | |||
diff --git a/src/host/genlibbc.lua b/src/host/genlibbc.lua new file mode 100644 index 00000000..b0dbf17a --- /dev/null +++ b/src/host/genlibbc.lua | |||
| @@ -0,0 +1,68 @@ | |||
| 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-2013 Mike Pall. All rights reserved. | ||
| 6 | -- Released under the MIT license. See Copyright Notice in luajit.h | ||
| 7 | ---------------------------------------------------------------------------- | ||
| 8 | |||
| 9 | local function usage() | ||
| 10 | io.stderr:write("Usage: ", arg and arg[0] or "genlibbc", " lib_*.c\n") | ||
| 11 | os.exit(1) | ||
| 12 | end | ||
| 13 | |||
| 14 | local function read_source() | ||
| 15 | if not (arg and arg[1]) then usage() end | ||
| 16 | local src = "" | ||
| 17 | for _,name in ipairs(arg) do | ||
| 18 | local fp = assert(io.open(name)) | ||
| 19 | src = src .. fp:read("*a") | ||
| 20 | fp:close() | ||
| 21 | end | ||
| 22 | return src | ||
| 23 | end | ||
| 24 | |||
| 25 | local function find_defs(src) | ||
| 26 | local defs = {} | ||
| 27 | for name, code in string.gmatch(src, "LJLIB_LUA%(([^)]*)%)%s*/%*(.-)%*/") do | ||
| 28 | local env = {} | ||
| 29 | local func = assert(load("return "..code, "", nil, env))() | ||
| 30 | local d = string.dump(func, true) | ||
| 31 | local ofs = 6 | ||
| 32 | while string.byte(d, ofs) > 127 do ofs = ofs + 1 end | ||
| 33 | defs[name] = string.sub(d, ofs+1, -2) | ||
| 34 | defs[#defs+1] = name | ||
| 35 | end | ||
| 36 | return defs | ||
| 37 | end | ||
| 38 | |||
| 39 | local function write_defs(fp, defs) | ||
| 40 | fp:write("/* This is a generated file. DO NOT EDIT! */\n\n") | ||
| 41 | fp:write("static const int libbc_endian = ", | ||
| 42 | string.byte(string.dump(function() end), 5) % 2, ";\n\n") | ||
| 43 | local s = "" | ||
| 44 | for _,name in ipairs(defs) do | ||
| 45 | s = s .. defs[name] | ||
| 46 | end | ||
| 47 | fp:write("static const uint8_t libbc_code[] = {\n") | ||
| 48 | local n = 0 | ||
| 49 | for i=1,#s do | ||
| 50 | local x = string.byte(s, i) | ||
| 51 | fp:write(x, ",") | ||
| 52 | n = n + (x < 10 and 2 or (x < 100 and 3 or 4)) | ||
| 53 | if n >= 75 then n = 0; fp:write("\n") end | ||
| 54 | end | ||
| 55 | fp:write("0\n};\n\n") | ||
| 56 | fp:write("static const struct { const char *name; int ofs; } libbc_map[] = {\n") | ||
| 57 | local m = 0 | ||
| 58 | for _,name in ipairs(defs) do | ||
| 59 | fp:write('{"', name, '",', m, '},\n') | ||
| 60 | m = m + #defs[name] | ||
| 61 | end | ||
| 62 | fp:write("{NULL,", m, "}\n};\n\n") | ||
| 63 | fp:flush() | ||
| 64 | end | ||
| 65 | |||
| 66 | local src = read_source() | ||
| 67 | local defs = find_defs(src) | ||
| 68 | write_defs(io.stdout, defs) | ||
