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"]
|
||||
|
||||
def _lift_func(self, entry: int, name: str):
|
||||
all_ins = disassemble_cfg(self.z, entry)
|
||||
insts = {i["pc"]: i for i in all_ins if i["pc"] >= entry}
|
||||
# 只在"跳转目标/入口/洞"处打标签, 避免每行一个标签
|
||||
insts = {i["pc"]: i for i in disassemble_cfg(self.z, entry) 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}
|
||||
for i in all_ins:
|
||||
for o in i.get("operands") or []:
|
||||
for i in insts.values():
|
||||
for o in (i.get("operands") or []):
|
||||
if isinstance(o, int) and o in insts:
|
||||
targets.add(o)
|
||||
# 只保留可达块; 逐块输出
|
||||
self.out.append("")
|
||||
self.out.append(f"function {name}() {{")
|
||||
stack: List[Expr] = []
|
||||
pending: List[str] = []
|
||||
last_pc = None
|
||||
|
||||
def flush():
|
||||
for s in pending:
|
||||
self.out.append(" " + s)
|
||||
pending.clear()
|
||||
|
||||
pcs = sorted(insts)
|
||||
for pc in pcs:
|
||||
for pc in sorted(insts):
|
||||
ins = insts[pc]
|
||||
op = ins["op"]
|
||||
if op is None:
|
||||
if ins["op"] is None:
|
||||
continue
|
||||
st = list(state.get(pc, []))
|
||||
if pc in targets:
|
||||
flush()
|
||||
self.out.append(f" @{pc:05d}:") # 目标标签
|
||||
self._emit(op, ins, pc, stack, pending)
|
||||
flush()
|
||||
for x in pending:
|
||||
self.out.append(" " + x)
|
||||
pending.clear()
|
||||
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("}")
|
||||
|
||||
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:
|
||||
op = ins["op"]
|
||||
if op == OP_JUMP:
|
||||
|
||||
Reference in New Issue
Block a user