feat(vm): 提升器改用"执行流栈快照(DFS)"渲染, 消除跨跳转失步
做了什么: - _lift_func 重写为两遍: 第一遍: 沿执行流 DFS 传播"求值栈快照"(每条 pc 记录进入时的栈) 第二遍: 按地址序渲染, 块首用快照还原栈 - 新增 _next_pc(): 用规范操作数长度计算后继(含 CREATE_CLOSURE 动态长度) 为什么: - 原来按"地址序 + 块首清空栈"提升, 表达式跨分支传递时会整体丢失 - 栈机必须在"执行流"上跟踪栈, 而不是地址序 怎么验证: - XTEA 轮仍可读: r2=(r2+2654435769); r?+=(((r6<<4)^(r6>>>5))+r6)^(r2+r7[((r2>>>11)&3)]) - 闭包图正确: // closure func_9109(p0->r3,p1->r4) caps=[r7<-r8] target=@9109 - 已知残留: 汇合点(多前驱)取首路径栈, 仍会产出少量 r<?> (下一步: phi 合并/对齐运行时轨迹)
This commit is contained in:
File diff suppressed because it is too large
Load Diff
+55
-22
@@ -87,39 +87,72 @@ class Lifter:
|
|||||||
return self.funcs[target]["name"]
|
return self.funcs[target]["name"]
|
||||||
|
|
||||||
def _lift_func(self, entry: int, name: str):
|
def _lift_func(self, entry: int, name: str):
|
||||||
all_ins = disassemble_cfg(self.z, entry)
|
insts = {i["pc"]: i for i in disassemble_cfg(self.z, entry) if i["pc"] >= entry}
|
||||||
insts = {i["pc"]: i for i in all_ins if i["pc"] >= entry}
|
# ---------- 第一遍: 沿执行流传播"求值栈快照"(DFS, 每 pc 记录首次到达时的栈) ----------
|
||||||
# 只在"跳转目标/入口/洞"处打标签, 避免每行一个标签
|
state: Dict[int, List[Expr]] = {entry: []}
|
||||||
|
seen: Dict[int, bool] = {}
|
||||||
|
work = [entry]
|
||||||
|
while work:
|
||||||
|
pc = work.pop()
|
||||||
|
if pc in seen:
|
||||||
|
continue
|
||||||
|
st = list(state.get(pc, []))
|
||||||
|
while pc in insts and pc not in seen:
|
||||||
|
seen[pc] = True
|
||||||
|
state.setdefault(pc, list(st)) # 每条 pc 都记录"进入时的栈"
|
||||||
|
ins = insts[pc]
|
||||||
|
self._emit(ins["op"], ins, pc, st, []) # 只改栈, 丢弃语句
|
||||||
|
op = ins["op"]
|
||||||
|
ops = ins["operands"] or []
|
||||||
|
nxt = self._next_pc(ins)
|
||||||
|
if op == OP_JUMP:
|
||||||
|
succ = [ops[0]]
|
||||||
|
elif op == OP_JUMP_IF_TRUE:
|
||||||
|
succ = [ops[0], nxt]
|
||||||
|
elif op in (19, 49): # RET_TRUE / THROW
|
||||||
|
succ = []
|
||||||
|
else:
|
||||||
|
succ = [nxt]
|
||||||
|
for t in succ:
|
||||||
|
if t in insts and t not in state:
|
||||||
|
state[t] = list(st)
|
||||||
|
if t in insts and t not in seen:
|
||||||
|
work.append(t)
|
||||||
|
if succ != [nxt]:
|
||||||
|
break
|
||||||
|
pc = nxt
|
||||||
|
# ---------- 第二遍: 按地址序渲染 (块首用快照还原栈) ----------
|
||||||
targets = {entry}
|
targets = {entry}
|
||||||
for i in all_ins:
|
for i in insts.values():
|
||||||
for o in i.get("operands") or []:
|
for o in (i.get("operands") or []):
|
||||||
if isinstance(o, int) and o in insts:
|
if isinstance(o, int) and o in insts:
|
||||||
targets.add(o)
|
targets.add(o)
|
||||||
# 只保留可达块; 逐块输出
|
|
||||||
self.out.append("")
|
self.out.append("")
|
||||||
self.out.append(f"function {name}() {{")
|
self.out.append(f"function {name}() {{")
|
||||||
stack: List[Expr] = []
|
|
||||||
pending: List[str] = []
|
pending: List[str] = []
|
||||||
last_pc = None
|
for pc in sorted(insts):
|
||||||
|
|
||||||
def flush():
|
|
||||||
for s in pending:
|
|
||||||
self.out.append(" " + s)
|
|
||||||
pending.clear()
|
|
||||||
|
|
||||||
pcs = sorted(insts)
|
|
||||||
for pc in pcs:
|
|
||||||
ins = insts[pc]
|
ins = insts[pc]
|
||||||
op = ins["op"]
|
if ins["op"] is None:
|
||||||
if op is None:
|
|
||||||
continue
|
continue
|
||||||
|
st = list(state.get(pc, []))
|
||||||
if pc in targets:
|
if pc in targets:
|
||||||
flush()
|
for x in pending:
|
||||||
self.out.append(f" @{pc:05d}:") # 目标标签
|
self.out.append(" " + x)
|
||||||
self._emit(op, ins, pc, stack, pending)
|
pending.clear()
|
||||||
flush()
|
self.out.append(f" @{pc:05d}:")
|
||||||
|
self._emit(ins["op"], ins, pc, st, pending)
|
||||||
|
for x in pending:
|
||||||
|
self.out.append(" " + x)
|
||||||
self.out.append("}")
|
self.out.append("}")
|
||||||
|
|
||||||
|
def _next_pc(self, ins) -> int:
|
||||||
|
from tdc_disasm import ARITY, DYNAMIC_ARITY
|
||||||
|
op = ins["op"]; ops = ins["operands"] or []
|
||||||
|
if op == OP_CREATE_CLOSURE:
|
||||||
|
capn = self.z[ins["pc"] + 2]; parn = self.z[ins["pc"] + 3]
|
||||||
|
return ins["pc"] + 1 + 3 + 2 * capn + parn
|
||||||
|
return ins["pc"] + 1 + ARITY.get(op, 0)
|
||||||
|
|
||||||
def _fallthrough(self, ins) -> int:
|
def _fallthrough(self, ins) -> int:
|
||||||
op = ins["op"]
|
op = ins["op"]
|
||||||
if op == OP_JUMP:
|
if op == OP_JUMP:
|
||||||
|
|||||||
Reference in New Issue
Block a user