-- Computes the local origin of a variable definition local utils = require 'luainlua.common.utils' local cfg = require 'luainlua.cfg.cfg' local undump = require 'luainlua.bytecode.undump' local worklist = require 'luainlua.common.worklist' local TOP = 'TOP' local origin = {} local woot = function(n) n = unpack(n) return n > 255 and {} or {n} end local A = function(instr) return woot {instr.A.raw} end local B = function(instr) return woot {instr.B.raw} end local C = function(instr) return woot {instr.C.raw} end local function top(number) return function(instr) local x = unpack(number(instr)) if x == 0 then return {TOP} end return {x} end end local function range(from, number) return function(instr) local left = unpack(from(instr)) local num = unpack(number(instr)) local registers = {} if num == TOP then return {left} end for i = 0, num do table.insert(registers, left + i) end return registers end end local function offset(start, amount, invert) return function(instr) local left = unpack(start(instr)) local off = unpack(amount(instr)) if left == TOP then return {TOP} end return {invert and (left - off) or (left + off)} end end local function constant(n) return function() return {n} end end local function kill(...) local actions = {...} return function(self, pc, instr, current, graph, node) local new = utils.copy(current) for action in utils.loop(actions) do for register in utils.loop(action(instr)) do new[register] = {[pc] = true} end end return new end end local actions = { {"MOVE", kill(A)}, --R(A) := R(B) {"LOADK", kill(A)}, --R(A) := Kst(Bx) {"LOADKX", kill(A)}, --R(A) := Kst(extra arg) {"LOADBOOL", kill(A)}, --R(A) := (Bool)B; if (C) pc++ {"LOADNIL", kill(range(A, offset(B, A, true)))}, --R(A) := ... := R(B) := nil {"GETUPVAL", kill(A)}, --R(A) := UpValue[B] {"GETTABUP", kill(A)}, --R(A) := UpValue[B][RK(C)] {"GETTABLE", kill(A)}, --R(A) := R(B)[RK(C)] {"SETTABUP", kill()}, --UpValue[A][RK(B)] := RK(C) {"SETUPVAL", kill()}, --UpValue[B] := R(A) {"SETTABLE", kill()}, --R(A)[RK(B)] := RK(C) {"NEWTABLE", kill(A)}, --R(A) := {} (size = B,C) {"SELF", kill(A, offset(A, constant(1)))}, --R(A+1) := R(B); R(A) := R(B)[RK(C)] {"ADD", kill(A)}, --R(A) := RK(B) + RK(C) {"SUB", kill(A)}, --R(A) := RK(B) - RK(C) {"MUL", kill(A)}, --R(A) := RK(B) * RK(C) {"DIV", kill(A)}, --R(A) := RK(B) / RK(C) {"MOD", kill(A)}, --R(A) := RK(B) % RK(C) {"POW", kill(A)}, --R(A) := RK(B) ^ RK(C) {"UNM", kill(A)}, --R(A) := -R(B) {"NOT", kill(A)}, --R(A) := not R(B) {"LEN", kill(A)}, --R(A) := length of R(B) {"CONCAT", kill(A)}, --R(A) := R(B).. ... ..R(C) {"JMP", kill()}, --pc+=sBx {"EQ", kill()}, --if ((RK(B) == RK(C)) ~= A) then pc++ {"LT", kill()}, --if ((RK(B) < RK(C)) ~= A) then pc++ {"LE", kill()}, --if ((RK(B) <= RK(C)) ~= A) then pc++ {"TEST", kill()}, --if not (R(A) <=> C) then pc++ {"TESTSET", kill(A)}, --if (R(B) <=> C) then R(A) := R(B) else pc++ {"CALL", kill(range(A, offset(top(C), constant(-2))))}, --R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) {"TAILCALL", kill()}, --return R(A)(R(A+1), ... ,R(A+B-1)) {"RETURN", kill()}, --return R(A), ... ,R(A+B-2)(see note) {"FORLOOP", kill(A, offset(A, constant(1)), offset(A, constant(2)), offset(A, constant(3)))}, --R(A)+=R(A+2); --if R(A) ', origin_print(solution:after(pc))) --end origin.solve = solve return origin