fix(gen): define 位宽/整数提升/移位/AugAssign 规则收敛,修 va_list 与 traceback 卡死

- define 位宽:cdefine_decl_bits 单一裁决(注解 → 右侧强转 → 值最小可存宽度),定义方与 VpiReader 两处跨模块注册共用;lookup_cdefine_bits 取最后一条非零记录;存储即截断;使用侧改按声明位宽;通用求值器加编译期除零/移位越界 fail-fast
- 消除对无符号强转加宽方向的依赖:define_min_width 改 (value>>32)==0,截断改左移+算术右移,修 TPC/TPV 判定不一致导致 0x80000000 误判 64 位
- 整数提升:算术/移位、比较、一元 +/-/~ 提升到 i32;位运算保持同宽不提升
- AugAssign:y 有效宽度须 <= x、禁 y 显式有符号而 x 无符号;移位计数静态范围检查
- 函数入口复位 va_list 状态与 willFree 失效槽表(FuncGenDef/FuncGenMixin/VarGenMixin 等)
- BuildPipeline:traceback 逐行扫描改 span 判定,去掉对全文 strlen 的 O(n^2)
This commit is contained in:
TermiNexus committed 2026-10-12 12:37:48 +08:00
1 parent be4db7b5d1
commit 4e46a25ab1
18 files changed
+1247 -843

No files matched your search

+15 -7
View File
@@ -164,9 +164,17 @@ def is_cdefine_found() -> int:
# ---------------- register_cdefine_constant (delegates to TypeGenCDef.register_cdefine_constant) ----------------
def register_cdefine_constant(pool: memhub.MemBuddy*, name: str, value: int64):
"""Delegate to gen.register_cdefine_constant"""
if _g_gen is not None: _g_gen.TypeGenCDef.register_cdefine_constant(pool, name, value)
def register_cdefine_constant(pool: memhub.MemBuddy*, name: str, value: int64, bits: int = 0):
"""Delegate to gen.register_cdefine_constant (bits: 0=未知;8/16/32/64=已知位宽)"""
if _g_gen is not None: _g_gen.TypeGenCDef.register_cdefine_constant(pool, name, value, bits)
# ---------------- cdefine_decl_bits (delegates to AssignGenMixin.cdefine_decl_bits) ----------------
def cdefine_decl_bits(pool: memhub.MemBuddy*, annot: ast.AST*, value_node: ast.AST*) -> int:
"""define 声明的位宽裁决(注解 → 右侧显式强转 → 值的最小可存宽度);0=非整型/无法裁决。
跨模块(.vpi 重解析 define 的 AST)注册时必须用它,否则使用方位宽与定义方不一致。"""
if _g_gen is not None: return _g_gen.AssignGen.cdefine_decl_bits(pool, annot, value_node)
return 0
# ---------------- register_cdefine_double (delegates to TypeGenCDef.register_cdefine_double) ----------------
@@ -341,7 +349,7 @@ def compute_willfree_mask(fd: ast.AST*) -> int:
dn: sizet = len(dl)
if dn == 0: return 0
mask: int = 0
for i in range(dn):
for i in range(int(dn)):
deco: ast.AST* = dl.get(i)
if deco is None or deco.kind() != ast.ASTKind.Call: continue
dc: ast.Call* = ast.Call*(deco)
@@ -352,7 +360,7 @@ def compute_willfree_mask(fd: ast.AST*) -> int:
# @life(<tag>, <tag>, ...):逐个标签并入
if dc.args is not None:
an: sizet = len(dc.args)
for j in range(an):
for j in range(int(an)):
mask = _WillFreeMergeTag(fn, dc.args.get(j), mask)
elif string.strcmp(fname.id, "willFree") == 0:
# 兼容形式:@willFree(0) 直接叠加(与 @life 等价、可混用)
@@ -636,7 +644,7 @@ def _WillFreeArgIndex(fn: ast.FunctionDef*, arg: ast.AST*) -> int:
if arg.kind() == ast.ASTKind.Name:
nma: ast.Name* = ast.Name*(arg)
if nma.id is None: return -1
for k in range(pn):
for k in range(int(pn)):
pa: ast.AST* = pl.get(k)
if pa is None or pa.kind() != ast.ASTKind.Arg: continue
aa: ast.Arg* = ast.Arg*(pa)
@@ -901,7 +909,7 @@ def fail_if_fstring_escape(node: ast.AST*, where: str) -> int:
tp: ast.Tuple* = ast.Tuple*(node)
if tp.elts is not None:
en: sizet = len(tp.elts)
for i in range(en):
for i in range(int(en)):
e: ast.AST* = tp.elts.get(i)
if e is not None:
ek: int = e.kind()