feat(gen): 控制流汇合 Meet(M2.2)
- VarGenMixin:life_capture/life_restore/life_join(作用域链快照,池上 [count,(entry,life)…] 数组)。 - StmtGenCifMixin.translate_if:进分支前快照、then 末快照、else 前复位、出口按 min 合并。 - StmtGenMixin:while/for 统一在语句分派处 capture→run→join(一处覆盖全部迭代形态与解糖,含 0 次迭代路径)。
This commit is contained in:
1 parent
ec47401151
commit
a6e1957768
3 files changed
+79
-2
No files matched your search
@@ -708,6 +708,9 @@ novirtual class StmtGenCifMixin:
|
||||
if has_else == 1: mlirlite.build_cond_br(builder, cond_i1, then_bb, else_bb)
|
||||
else: mlirlite.build_cond_br(builder, cond_i1, then_bb, merge_bb)
|
||||
|
||||
# 生命期汇合:进入分支前快照(else 分支需从该状态重新开始,见 §11 控制流 Meet)
|
||||
life_snap0: sizet* = self.Gen.VarGen.life_capture(trans)
|
||||
|
||||
# 5. translate the then body; reset the merge-reachable flag first (nested control flow
|
||||
# overwrites it, so the branch-tail check must not see a stale value from before this If).
|
||||
trans._ctrl_merge_reachable = 1
|
||||
@@ -730,9 +733,14 @@ novirtual class StmtGenCifMixin:
|
||||
mlirlite.build_br(builder, merge_bb)
|
||||
then_branches_merge = 1
|
||||
|
||||
# then 末状态快照(供两端 Meet:先复位到 if 前状态,再与 then 末状态合并)
|
||||
life_snap1: sizet* = self.Gen.VarGen.life_capture(trans)
|
||||
|
||||
# 6. translate the else body (if any)
|
||||
else_branches_merge: int = 0
|
||||
if has_else == 1:
|
||||
# 复位到 if 前状态,让 else 分支从同一基线出发(否则会看到 then 分支写入的 Life)
|
||||
self.Gen.VarGen.life_restore(life_snap0)
|
||||
# as in then: reset the flag to avoid stale values from the then branch
|
||||
trans._ctrl_merge_reachable = 1
|
||||
mlirlite.position_at_end(builder, else_bb)
|
||||
@@ -748,6 +756,10 @@ novirtual class StmtGenCifMixin:
|
||||
mlirlite.build_br(builder, merge_bb)
|
||||
else_branches_merge = 1
|
||||
|
||||
# 生命期汇合:有 else → 与 then 末状态 Meet;无 else → 与 if 前状态 Meet(else 路径=跳过)
|
||||
if has_else == 1: self.Gen.VarGen.life_join(life_snap1)
|
||||
else: self.Gen.VarGen.life_join(life_snap0)
|
||||
|
||||
# 7. merge reachability (used by tail-flow checks): without else cond_br always reaches
|
||||
# merge; with else, any branch br reaching merge suffices; only all-return is unreachable.
|
||||
trans._ctrl_merge_reachable = 1
|
||||
|
||||
@@ -51,9 +51,19 @@ novirtual class StmtGenMixin(StmtGenDeclMixin.StmtGenDeclMixin):
|
||||
return self.Gen.FuncGen.translate_nested_function_def(trans, node)
|
||||
elif k == ast.ASTKind.Return: return self.Gen.StmtGenCif.translate_return(trans, node)
|
||||
elif k == ast.ASTKind.If: return self.Gen.StmtGenCif.translate_if(trans, node)
|
||||
elif k == ast.ASTKind.While: return self.Gen.StmtGenCif.translate_while(trans, node)
|
||||
elif k == ast.ASTKind.While:
|
||||
# 循环生命期汇合:循环可能 0 次执行,出口状态须与进入前状态 Meet(见 §11 控制流 Meet)
|
||||
snap_wh: sizet* = self.Gen.VarGen.life_capture(trans)
|
||||
rc_wh: int = self.Gen.StmtGenCif.translate_while(trans, node)
|
||||
self.Gen.VarGen.life_join(snap_wh)
|
||||
return rc_wh
|
||||
elif k == ast.ASTKind.AugAssign: return self.Gen.AssignGen.translate_augassign(trans, node)
|
||||
elif k == ast.ASTKind.For: return self.Gen.StmtGenCif.translate_for(trans, node)
|
||||
elif k == ast.ASTKind.For:
|
||||
# 同上:for 的各迭代形态(range/指针/数组/容器/解糖)统一在此收口
|
||||
snap_fr: sizet* = self.Gen.VarGen.life_capture(trans)
|
||||
rc_fr: int = self.Gen.StmtGenCif.translate_for(trans, node)
|
||||
self.Gen.VarGen.life_join(snap_fr)
|
||||
return rc_fr
|
||||
elif k == ast.ASTKind.ClassDef: return self.Gen.ClassGenDef.translate_class_def(trans, node)
|
||||
elif k == ast.ASTKind.Import: return self.Gen.ImportsGen.translate_import(trans, node)
|
||||
elif k == ast.ASTKind.ImportFrom:
|
||||
|
||||
@@ -204,6 +204,61 @@ novirtual class VarGenMixin:
|
||||
"""Meet of two life tags (min); used where branches join"""
|
||||
return a if a < b else b
|
||||
|
||||
# life_capture - 快照当前作用域链上所有变量的 LifeTag(供控制流汇合 Meet)。
|
||||
# 返回池上数组:buf[0]=count,其后每项 (entry_ptr, life) 各占一个 sizet 槽;失败返回 None。
|
||||
def life_capture(self, trans: HT.Translator*) -> sizet*:
|
||||
"""Snapshot every in-scope variable's LifeTag (control-flow merge support)"""
|
||||
if trans is None or trans.SymTab is None: return None
|
||||
pool: memhub.MemBuddy* = trans.Pool
|
||||
if pool is None: return None
|
||||
cnt: sizet = 0
|
||||
sc_c: GenTypes.Scope* = trans.SymTab.Current
|
||||
while sc_c is not None:
|
||||
cnt += sizet(sc_c.VarCount)
|
||||
sc_c = sc_c.Parent
|
||||
buf: sizet* = sizet*(pool.alloc(8 * (2 * cnt + 2)))
|
||||
if buf is None: return None
|
||||
buf[0] = cnt
|
||||
idx: sizet = 1
|
||||
esz: uint64 = uint64(GenTypes.VarEntry.__sizeof__())
|
||||
sc: GenTypes.Scope* = trans.SymTab.Current
|
||||
while sc is not None:
|
||||
if sc.Vars is not None and sc.VarCount > 0:
|
||||
j: int = 0
|
||||
while j < sc.VarCount:
|
||||
ent: GenTypes.VarEntry* = GenTypes.VarEntry*(uint64(sc.Vars) + uint64(j) * esz)
|
||||
buf[idx * 2] = sizet(uint64(ent))
|
||||
buf[idx * 2 + 1] = sizet(ent.Life)
|
||||
idx += 1
|
||||
j += 1
|
||||
sc = sc.Parent
|
||||
return buf
|
||||
|
||||
# life_restore - 把快照写回各变量(让 else 分支从 if 之前的状态开始)。
|
||||
def life_restore(self, buf: sizet*) -> int:
|
||||
"""Restore LifeTag values from a snapshot; 0=ok / 1=no snapshot"""
|
||||
if buf is None: return 1
|
||||
cnt: sizet = buf[0]
|
||||
i: sizet = 1
|
||||
while i <= cnt:
|
||||
ent: GenTypes.VarEntry* = GenTypes.VarEntry*(uint64(buf[i * 2]))
|
||||
if ent is not None: ent.Life = int(buf[i * 2 + 1])
|
||||
i += 1
|
||||
return 0
|
||||
|
||||
# life_join - 当前值与快照逐项 Meet(汇合:任一路径为短命即取短命)。
|
||||
def life_join(self, buf: sizet*) -> int:
|
||||
"""Meet the current LifeTags with a snapshot; 0=ok / 1=no snapshot"""
|
||||
if buf is None: return 1
|
||||
cnt: sizet = buf[0]
|
||||
i: sizet = 1
|
||||
while i <= cnt:
|
||||
ent: GenTypes.VarEntry* = GenTypes.VarEntry*(uint64(buf[i * 2]))
|
||||
if ent is not None:
|
||||
ent.Life = self.life_meet(ent.Life, int(buf[i * 2 + 1]))
|
||||
i += 1
|
||||
return 0
|
||||
|
||||
# add_var - add a variable to the variable table
|
||||
# ============================================================
|
||||
def add_var(self, vars_ptr: GenTypes.VarEntry*, var_count: int, name: str, alloca: mlirlite.Value*) -> int:
|
||||
|
||||
Reference in new issue
Block a user