1
----------------------------------------------------------------------------
3
----------------------------------------------------------------------------
14
------------------------------------------------------------------------------
16
local jit = require("jit")
17
assert(jit.version_num == 20000, "LuaJIT core/library version mismatch")
18
local jutil = require("jit.util")
19
local vmdef = require("jit.vmdef")
20
local bit = require("bit")
21
local sub, gsub, format = string.sub, string.gsub, string.format
22
local byte, band, shr = string.byte, bit.band, bit.rshift
23
local funcinfo, funcbc, funck = jutil.funcinfo, jutil.funcbc, jutil.funck
24
local funcuvname = jutil.funcuvname
25
local bcnames = vmdef.bcnames
26
local stdout, stderr = io.stdout, io.stderr
28
------------------------------------------------------------------------------
30
local function ctlsub(c)
31
if c == "\n" then return "\\n"
32
elseif c == "\r" then return "\\r"
33
elseif c == "\t" then return "\\t"
34
elseif c == "\r" then return "\\r"
35
else return format("\\%03d", byte(c))
39
local function bcline(func, pc, prefix)
40
local ins, m = funcbc(func, pc)
41
if not ins then return end
42
local ma, mb, mc = band(m, 7), band(m, 15*8), band(m, 15*128)
43
local a = band(shr(ins, 8), 0xff)
44
local oidx = 6*band(ins, 0xff)
45
local op = sub(bcnames, oidx+1, oidx+6)
46
local s = format("%04d %s %-6s %3s ",
47
pc, prefix or " ", op, ma == 0 and "" or a)
48
local d = shr(ins, 16)
49
if mc == 13*128 then -- BCMjump
50
return format("%s=> %04d\n", s, pc+d-0x7fff)
58
if mc == 10*128 then -- BCMstr
59
kc = funck(func, -d-1)
60
kc = format(#kc > 40 and '"%.40s"~' or '"%s"', gsub(kc, "%c", ctlsub))
61
elseif mc == 9*128 then -- BCMnum
63
if op == "TSETM " then kc = kc - 2^52 end
64
elseif mc == 12*128 then -- BCMfunc
65
local fi = funcinfo(funck(func, -d-1))
67
kc = vmdef.ffnames[fi.ffid]
71
elseif mc == 5*128 then -- BCMuv
72
kc = funcuvname(func, d)
74
if ma == 5 then -- BCMuv
75
local ka = funcuvname(func, a)
76
if kc then kc = ka.." ; "..kc else kc = ka end
79
local b = shr(ins, 24)
80
if kc then return format("%s%3d %3d ; %s\n", s, b, d, kc) end
81
return format("%s%3d %3d\n", s, b, d)
83
if kc then return format("%s%3d ; %s\n", s, d, kc) end
84
if mc == 7*128 and d > 32767 then d = d - 65536 end -- BCMlits
85
return format("%s%3d\n", s, d)
88
local function bctargets(func)
90
for pc=1,1000000000 do
91
local ins, m = funcbc(func, pc)
92
if not ins then break end
93
if band(m, 15*128) == 13*128 then target[pc+shr(ins, 16)-0x7fff] = true end
98
local function bcdump(func, out, all)
99
if not out then out = stdout end
100
local fi = funcinfo(func)
101
if all and fi.children then
102
for n=-1,-1000000000,-1 do
103
local k = funck(func, n)
104
if not k then break end
105
if type(k) == "proto" then bcdump(k, out, true) end
108
out:write(format("-- BYTECODE -- %s-%d\n", fi.loc, fi.lastlinedefined))
109
local target = bctargets(func)
110
for pc=1,1000000000 do
111
local s = bcline(func, pc, target[pc] and "=>")
112
if not s then break end
119
------------------------------------------------------------------------------
123
local function h_list(func)
124
return bcdump(func, out)
127
local function bclistoff()
131
if out and out ~= stdout and out ~= stderr then out:close() end
136
local function bcliston(outfile)
137
if active then bclistoff() end
138
if not outfile then outfile = os.getenv("LUAJIT_LISTFILE") end
140
out = outfile == "-" and stdout or assert(io.open(outfile, "w"))
144
jit.attach(h_list, "bc")
156
start = bcliston -- For -j command line option.