X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Fcompiler%2Fldump.lua;fp=src%2Fcompiler%2Fldump.lua;h=0000000000000000000000000000000000000000;hb=355ff0bc201e00856ba20d82c65b14ffa6fcfe4b;hp=3e07f70c21f9c5e7da1ebde39688bb777e0393ef;hpb=f998820846d157a0c28abfb71cfca4b273f45eb9;p=metalua.git diff --git a/src/compiler/ldump.lua b/src/compiler/ldump.lua deleted file mode 100644 index 3e07f70..0000000 --- a/src/compiler/ldump.lua +++ /dev/null @@ -1,441 +0,0 @@ ----------------------------------------------------------------------- --- --- WARNING! You're entering a hackish area, proceed at your own risks! --- --- This code results from the borrowing, then ruthless abuse, of --- Yueliang's implementation of Lua 5.0 compiler. I claim --- responsibility for all of the ugly, dirty stuff that you might spot --- in it. --- --- Eventually, this code will be rewritten, either in Lua or more --- probably in C. Meanwhile, if you're interested into digging --- metalua's sources, this is not the best part to invest your time --- on. --- --- End of warning. --- ----------------------------------------------------------------------- - ---[[-------------------------------------------------------------------- - - $Id$ - - ldump.lua - Save bytecodes in Lua - This file is part of Yueliang. - - Copyright (c) 2005 Kein-Hong Man - The COPYRIGHT file describes the conditions - under which this software may be distributed. - ------------------------------------------------------------------------- - - [FF] Slightly modified, mainly to produce Lua 5.1 bytecode. - -----------------------------------------------------------------------]] - ---[[-------------------------------------------------------------------- --- Notes: --- * LUA_NUMBER (double), byte order (little endian) and some other --- header values hard-coded; see other notes below... --- * One significant difference is that instructions are still in table --- form (with OP/A/B/C/Bx fields) and luaP:Instruction() is needed to --- convert them into 4-char strings --- * Deleted: --- luaU:DumpVector: folded into DumpLines, DumpCode --- * Added: --- luaU:endianness() (from lundump.c) --- luaU:make_setS: create a chunk writer that writes to a string --- luaU:make_setF: create a chunk writer that writes to a file --- (lua.h contains a typedef for a Chunkwriter pointer, and --- a Lua-based implementation exists, writer() in lstrlib.c) --- luaU:from_double(x): encode double value for writing --- luaU:from_int(x): encode integer value for writing --- (error checking is limited for these conversion functions) --- (double conversion does not support denormals or NaNs) --- luaU:ttype(o) (from lobject.h) -----------------------------------------------------------------------]] - -module("bytecode", package.seeall) - -format = { } -format.header = string.dump(function()end):sub(1, 12) -format.little_endian, format.int_size, -format.size_t_size, format.instr_size, -format.number_size, format.integral = format.header:byte(7, 12) -format.little_endian = format.little_endian~=0 -format.integral = format.integral ~=0 - -assert(format.integral or format.number_size==8, "Number format not supported by dumper") -assert(format.little_endian, "Big endian architectures not supported by dumper") - ---requires luaP -luaU = {} - --- constants used by dumper -luaU.LUA_TNIL = 0 -luaU.LUA_TBOOLEAN = 1 -luaU.LUA_TNUMBER = 3 -- (all in lua.h) -luaU.LUA_TSTRING = 4 -luaU.LUA_TNONE = -1 - --- definitions for headers of binary files ---luaU.LUA_SIGNATURE = "\27Lua" -- binary files start with "Lua" ---luaU.VERSION = 81 -- 0x50; last format change was in 5.0 ---luaU.FORMAT_VERSION = 0 -- 0 is official version. yeah I know I'm a liar. - --- a multiple of PI for testing native format --- multiplying by 1E7 gives non-trivial integer values ---luaU.TEST_NUMBER = 3.14159265358979323846E7 - ---[[-------------------------------------------------------------------- --- Additional functions to handle chunk writing --- * to use make_setS and make_setF, see test_ldump.lua elsewhere -----------------------------------------------------------------------]] - ------------------------------------------------------------------------- --- works like the lobject.h version except that TObject used in these --- scripts only has a 'value' field, no 'tt' field (native types used) ------------------------------------------------------------------------- -function luaU:ttype(o) - local tt = type(o.value) - if tt == "number" then return self.LUA_TNUMBER - elseif tt == "string" then return self.LUA_TSTRING - elseif tt == "nil" then return self.LUA_TNIL - elseif tt == "boolean" then return self.LUA_TBOOLEAN - else - return self.LUA_TNONE -- the rest should not appear - end -end - ------------------------------------------------------------------------- --- create a chunk writer that writes to a string --- * returns the writer function and a table containing the string --- * to get the final result, look in buff.data ------------------------------------------------------------------------- -function luaU:make_setS() - local buff = {} - buff.data = "" - local writer = - function(s, buff) -- chunk writer - if not s then return end - buff.data = buff.data..s - end - return writer, buff -end - ------------------------------------------------------------------------- --- create a chunk writer that writes to a file --- * returns the writer function and a table containing the file handle --- * if a nil is passed, then writer should close the open file ------------------------------------------------------------------------- -function luaU:make_setF(filename) - local buff = {} - buff.h = io.open(filename, "wb") - if not buff.h then return nil end - local writer = - function(s, buff) -- chunk writer - if not buff.h then return end - if not s then buff.h:close(); return end - buff.h:write(s) - end - return writer, buff -end - ------------------------------------------------------------------------ --- converts a IEEE754 double number to an 8-byte little-endian string --- * luaU:from_double() and luaU:from_int() are from ChunkBake project --- * supports +/- Infinity, but not denormals or NaNs ------------------------------------------------------------------------ -function luaU:from_double(x) - local function grab_byte(v) - return math.floor(v / 256), - string.char(math.mod(math.floor(v), 256)) - end - local sign = 0 - if x < 0 then sign = 1; x = -x end - local mantissa, exponent = math.frexp(x) - if x == 0 then -- zero - mantissa, exponent = 0, 0 - elseif x == 1/0 then - mantissa, exponent = 0, 2047 - else - mantissa = (mantissa * 2 - 1) * math.ldexp(0.5, 53) - exponent = exponent + 1022 - end - local v, byte = "" -- convert to bytes - x = mantissa - for i = 1,6 do - x, byte = grab_byte(x); v = v..byte -- 47:0 - end - x, byte = grab_byte(exponent * 16 + x); v = v..byte -- 55:48 - x, byte = grab_byte(sign * 128 + x); v = v..byte -- 63:56 - return v -end - ------------------------------------------------------------------------ --- converts a number to a little-endian 32-bit integer string --- * input value assumed to not overflow, can be signed/unsigned ------------------------------------------------------------------------ -function luaU:from_int(x, size) - local v = "" - x = math.floor(x) - if x >= 0 then - for i = 1, size do - v = v..string.char(math.mod(x, 256)); x = math.floor(x / 256) - end - else -- x < 0 - x = -x - local carry = 1 - for i = 1, size do - local c = 255 - math.mod(x, 256) + carry - if c == 256 then c = 0; carry = 1 else carry = 0 end - v = v..string.char(c); x = math.floor(x / 256) - end - end - return v -end - ---[[-------------------------------------------------------------------- --- Functions to make a binary chunk --- * many functions have the size parameter removed, since output is --- in the form of a string and some sizes are implicit or hard-coded --- * luaU:DumpVector has been deleted (used in DumpCode & DumpLines) -----------------------------------------------------------------------]] - ------------------------------------------------------------------------- --- dump a block of literal bytes ------------------------------------------------------------------------- -function luaU:DumpLiteral(s, D) self:DumpBlock(s, D) end - ---[[-------------------------------------------------------------------- --- struct DumpState: --- L -- lua_State (not used in this script) --- write -- lua_Chunkwriter (chunk writer function) --- data -- void* (chunk writer context or data already written) -----------------------------------------------------------------------]] - ------------------------------------------------------------------------- --- dumps a block of bytes --- * lua_unlock(D.L), lua_lock(D.L) deleted ------------------------------------------------------------------------- -function luaU:DumpBlock(b, D) D.write(b, D.data) end - ------------------------------------------------------------------------- --- dumps a single byte ------------------------------------------------------------------------- -function luaU:DumpByte(y, D) - self:DumpBlock(string.char(y), D) -end - ------------------------------------------------------------------------- --- dumps a 32-bit signed integer (for int) ------------------------------------------------------------------------- -function luaU:DumpInt(x, D) - self:DumpBlock(self:from_int(x, format.int_size), D) -end - ------------------------------------------------------------------------- --- dumps a 32-bit unsigned integer (for size_t) ------------------------------------------------------------------------- -function luaU:DumpSize(x, D) - self:DumpBlock(self:from_int(x, format.size_t_size), D) -end - ------------------------------------------------------------------------- --- dumps a LUA_NUMBER (hard-coded as a double) ------------------------------------------------------------------------- -function luaU:DumpNumber(x, D) - if format.integral then - self:DumpBlock(self:from_int(x, format.number_size), D) - else - self:DumpBlock(self:from_double(x), D) - end -end - ------------------------------------------------------------------------- --- dumps a Lua string ------------------------------------------------------------------------- -function luaU:DumpString(s, D) - if s == nil then - self:DumpSize(0, D) - else - s = s.."\0" -- include trailing '\0' - self:DumpSize(string.len(s), D) - self:DumpBlock(s, D) - end -end - ------------------------------------------------------------------------- --- dumps instruction block from function prototype ------------------------------------------------------------------------- -function luaU:DumpCode(f, D) - local n = f.sizecode - self:DumpInt(n, D) - --was DumpVector - for i = 0, n - 1 do - self:DumpBlock(luaP:Instruction(f.code[i]), D) - end -end - ------------------------------------------------------------------------- --- dumps local variable names from function prototype ------------------------------------------------------------------------- -function luaU:DumpLocals(f, D) - local n = f.sizelocvars - self:DumpInt(n, D) - for i = 0, n - 1 do - -- Dirty temporary fix: - -- `Stat{ } keeps properly count of the number of local vars, - -- but fails to keep score of their debug info (names). - -- It therefore might happen that #f.localvars < f.sizelocvars, or - -- that a variable's startpc and endpc fields are left unset. - -- FIXME: This might not be needed anymore, check the bug report - -- by J. Belmonte. - local var = f.locvars[i] - if not var then break end - -- printf("[DUMPLOCALS] dumping local var #%i = %s", i, table.tostring(var)) - self:DumpString(var.varname, D) - self:DumpInt(var.startpc or 0, D) - self:DumpInt(var.endpc or 0, D) - end -end - ------------------------------------------------------------------------- --- dumps line information from function prototype ------------------------------------------------------------------------- -function luaU:DumpLines(f, D) - local n = f.sizelineinfo - self:DumpInt(n, D) - --was DumpVector - for i = 0, n - 1 do - self:DumpInt(f.lineinfo[i], D) -- was DumpBlock - --print(i, f.lineinfo[i]) - end -end - ------------------------------------------------------------------------- --- dump upvalue names from function prototype ------------------------------------------------------------------------- -function luaU:DumpUpvalues(f, D) - local n = f.sizeupvalues - self:DumpInt(n, D) - for i = 0, n - 1 do - self:DumpString(f.upvalues[i], D) - end -end - ------------------------------------------------------------------------- --- dump constant pool from function prototype --- * nvalue(o) and tsvalue(o) macros removed ------------------------------------------------------------------------- -function luaU:DumpConstants(f, D) - local n = f.sizek - self:DumpInt(n, D) - for i = 0, n - 1 do - local o = f.k[i] -- TObject - local tt = self:ttype(o) - assert (tt >= 0) - self:DumpByte(tt, D) - if tt == self.LUA_TNUMBER then - self:DumpNumber(o.value, D) - elseif tt == self.LUA_TSTRING then - self:DumpString(o.value, D) - elseif tt == self.LUA_TBOOLEAN then - self:DumpByte (o.value and 1 or 0, D) - elseif tt == self.LUA_TNIL then - else - assert(false) -- cannot happen - end - end -end - - -function luaU:DumpProtos (f, D) - local n = f.sizep - assert (n) - self:DumpInt(n, D) - for i = 0, n - 1 do - self:DumpFunction(f.p[i], f.source, D) - end -end - -function luaU:DumpDebug(f, D) - self:DumpLines(f, D) - self:DumpLocals(f, D) - self:DumpUpvalues(f, D) -end - - ------------------------------------------------------------------------- --- dump child function prototypes from function prototype ---FF completely reworked for 5.1 format ------------------------------------------------------------------------- -function luaU:DumpFunction(f, p, D) - -- print "Dumping function:" - -- table.print(f, 60) - - local source = f.source - if source == p then source = nil end - self:DumpString(source, D) - self:DumpInt(f.lineDefined, D) - self:DumpInt(f.lastLineDefined or 42, D) - self:DumpByte(f.nups, D) - self:DumpByte(f.numparams, D) - self:DumpByte(f.is_vararg, D) - self:DumpByte(f.maxstacksize, D) - self:DumpCode(f, D) - self:DumpConstants(f, D) - self:DumpProtos( f, D) - self:DumpDebug(f, D) -end - ------------------------------------------------------------------------- --- dump Lua header section (some sizes hard-coded) ---FF: updated for version 5.1 ------------------------------------------------------------------------- -function luaU:DumpHeader(D) - self:DumpLiteral(format.header, D) -end - ------------------------------------------------------------------------- --- dump function as precompiled chunk --- * w, data are created from make_setS, make_setF ---FF: suppressed extraneous [L] param ------------------------------------------------------------------------- -function luaU:dump (Main, w, data) - local D = {} -- DumpState - D.write = w - D.data = data - self:DumpHeader(D) - self:DumpFunction(Main, nil, D) - -- added: for a chunk writer writing to a file, this final call with - -- nil data is to indicate to the writer to close the file - D.write(nil, D.data) -end - ------------------------------------------------------------------------- --- find byte order (from lundump.c) --- * hard-coded to little-endian ------------------------------------------------------------------------- -function luaU:endianness() - return 1 -end - --- FIXME: ugly concat-base generation in [make_setS], bufferize properly! -function dump_string (proto) - local writer, buff = luaU:make_setS() - luaU:dump (proto, writer, buff) - return buff.data -end - --- FIXME: [make_setS] sucks, perform synchronous file writing --- Now unused -function dump_file (proto, filename) - local writer, buff = luaU:make_setS() - luaU:dump (proto, writer, buff) - local file = io.open (filename, "wb") - file:write (buff.data) - io.close(file) - if UNIX_SHARPBANG then os.execute ("chmod a+x "..filename) end -end \ No newline at end of file