debug(funcattrs): 添加 @c.Attribute 属性提取链运行时诊断,定位 stackrealign 未进 IR

This commit is contained in:
TermiNexus committed 2026-08-26 20:35:09 +08:00
1 parent 2165c171e7
commit e60be41ad8
2 files changed
+95 -21

No files matched your search

+41 -7
View File
@@ -48,31 +48,60 @@ class FuncGenBase(CallGenBase.CallGenBase):
attrs_buf[0] = '\0'
found_any: int = 0
# [ATTR-DIAG] 运行时诊断:定位 @c.Attribute 属性为何未进入 IR(stackrealign)
stdio.printf("[ATTR] extract_func_attrs: dlist_len=%d\n", dn)
for di in range(dn):
deco: ast.AST | t.CPtr = decorator_list.get(di)
if deco is None or deco.kind() != ast.ASTKind.Call:
if deco is None:
stdio.printf("[ATTR] deco[%d]=None\n", di)
continue
dk: int = deco.kind()
stdio.printf("[ATTR] deco[%d] kind=%d\n", di, dk)
if dk != ast.ASTKind.Call:
continue
call_node: ast.Call | t.CPtr = (ast.Call | t.CPtr)(deco)
if call_node.func is None or call_node.func.kind() != ast.ASTKind.Attribute:
if call_node.func is None:
stdio.printf("[ATTR] call.func=None\n")
continue
cfk: int = call_node.func.kind()
stdio.printf("[ATTR] call.func kind=%d\n", cfk)
if cfk != ast.ASTKind.Attribute:
continue
# 检测 c.Attribute
func_attr: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(call_node.func)
if func_attr.attr is None or string.strcmp(func_attr.attr, "Attribute") != 0:
if func_attr.attr is None:
stdio.printf("[ATTR] func_attr.attr=None\n")
continue
if func_attr.value is None or func_attr.value.kind() != ast.ASTKind.Name:
stdio.printf("[ATTR] func_attr.attr='%s'\n", func_attr.attr)
if string.strcmp(func_attr.attr, "Attribute") != 0:
continue
if func_attr.value is None:
stdio.printf("[ATTR] func_attr.value=None\n")
continue
fvk: int = func_attr.value.kind()
stdio.printf("[ATTR] func_attr.value kind=%d\n", fvk)
if fvk != ast.ASTKind.Name:
continue
c_name: ast.Name | t.CPtr = (ast.Name | t.CPtr)(func_attr.value)
if c_name.id is None or string.strcmp(c_name.id, "c") != 0:
if c_name.id is None:
stdio.printf("[ATTR] c_name.id=None\n")
continue
if self.Gen.ImportsGen.is_module_imported(imported_modules, "c") == 0:
stdio.printf("[ATTR] c_name.id='%s'\n", c_name.id)
if string.strcmp(c_name.id, "c") != 0:
continue
imp_c: int = self.Gen.ImportsGen.is_module_imported(imported_modules, "c")
stdio.printf("[ATTR] is_module_imported('c')=%d\n", imp_c)
if imp_c == 0:
continue
# 遍历参数提取属性
if call_node.args is None:
stdio.printf("[ATTR] call.args=None\n")
continue
args_list: list[ast.AST | t.CPtr] | t.CPtr = call_node.args
an: t.CSizeT = len(args_list)
stdio.printf("[ATTR] args_len=%d\n", an)
for ai in range(an):
arg_node: ast.AST | t.CPtr = args_list.get(ai)
if arg_node is None:
@@ -81,14 +110,19 @@ class FuncGenBase(CallGenBase.CallGenBase):
# 提取属性名(t.attr.xxx / t.attr.xxx() / t.attr.llvm.xxx)
attr_name: str = self._get_attr_name_from_node(arg_node)
if attr_name is None:
stdio.printf("[ATTR] arg[%d] name=None\n", ai)
continue
# 映射到 LLVM 属性名并追加
if self._append_llvm_attr(attrs_buf, attr_name) != 0:
ar: int = self._append_llvm_attr(attrs_buf, attr_name)
stdio.printf("[ATTR] arg[%d] name='%s' append=%d buf='%s'\n",
ai, attr_name, ar, attrs_buf)
if ar != 0:
found_any = 1
# 追加成功后,如果不是最后一个属性,添加空格分隔
# 在下一次追加前由 _append_str 处理
stdio.printf("[ATTR] found_any=%d return='%s'\n", found_any, attrs_buf)
if found_any == 0:
return None
return attrs_buf
+54 -14
View File
@@ -91,10 +91,27 @@ class FuncGenDef(CallGenBase.CallGenBase):
ret_ty: llvmlite.LLVMType | t.CPtr = None
if fd.returns is not None:
ret_ty = self.Gen.TypeGenResolve.resolve_annotation_type(
pool, fd.returns, imported_modules, from_imports, trans)
pool, fd.returns, imported_modules, from_imports, trans, 0)
# 单独 t.CExport 返回注解(def free(...) -> t.CExport:)=
# 导出修饰符,无实际返回类型 → Void(根因:CExport 被 map_t_type
# 回退为 i32 → 掉尾检查强制 return i32,mm.vp free 根因)。
# CExport 混用实际类型(-> t.CExport | t.CInt)时保持解析结果。
if fd.returns.kind() == ast.ASTKind.Attribute:
ce_at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(fd.returns)
if ce_at.attr is not None and string.strcmp(ce_at.attr, "CExport") == 0:
if ce_at.value is not None and ce_at.value.kind() == ast.ASTKind.Name:
ce_nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(ce_at.value)
if ce_nm.id is not None and string.strcmp(ce_nm.id, "t") == 0:
ret_ty = llvmlite.Void(pool)
if ret_ty is None and fd.returns is not None:
if self.Gen.TypeGenErr.has_decorator_marker(fd.returns, "State") != 0:
if self.Gen.TypeGenErr.has_decorator_marker(fd.returns, "State", 0) != 0:
ret_ty = llvmlite.Void(pool)
# @c.CReturn(ty1, ...) → 多返回 struct(前向声明必须与定义一致,
# 否则 declare i32 + define {i64,i64,i64} → llc "value doesn't
# match function result type"——GetMemoryStats 根因)
if ret_ty is None:
ret_ty = self.Gen.FuncGenBase._resolve_creturn_ret_ty(
pool, fd, imported_modules, from_imports, trans)
if ret_ty is None:
ret_ty = i32_ty
@@ -103,9 +120,9 @@ class FuncGenDef(CallGenBase.CallGenBase):
has_state: int = 0
has_export: int = 0
if fd.returns is not None:
has_extern = self.Gen.TypeGenErr.has_decorator_marker(fd.returns, "CExtern")
has_state = self.Gen.TypeGenErr.has_decorator_marker(fd.returns, "State")
has_export = self.Gen.TypeGenErr.has_decorator_marker(fd.returns, "CExport")
has_extern = self.Gen.TypeGenErr.has_decorator_marker(fd.returns, "CExtern", 0)
has_state = self.Gen.TypeGenErr.has_decorator_marker(fd.returns, "State", 0)
has_export = self.Gen.TypeGenErr.has_decorator_marker(fd.returns, "CExport", 0)
# 装饰器形式存储类标记(@t.CExport/@t.CExtern/@t.State/@t.CStatic)
# 对齐 TPC HandlesFunctions._extract_decorator_storage_flags;
# CExport/CExtern/State 影响函数名(导出裸名),CStatic 仅标记。
@@ -187,7 +204,7 @@ class FuncGenDef(CallGenBase.CallGenBase):
param_ty: llvmlite.LLVMType | t.CPtr = i32_ty
if arg.annotation is not None:
resolved: llvmlite.LLVMType | t.CPtr = self.Gen.TypeGenResolve.resolve_annotation_type(
pool, arg.annotation, imported_modules, from_imports, trans)
pool, arg.annotation, imported_modules, from_imports, trans, 0)
if resolved is not None:
# 裸类形参 → Ptr(struct)(对象即指针,与方法形参一致)
# CArray 形参 → 元素指针 ty*(C 数组衰减,与 add_param 一致)
@@ -246,14 +263,34 @@ class FuncGenDef(CallGenBase.CallGenBase):
ret_ty: llvmlite.LLVMType | t.CPtr = None
if fd.returns is not None:
ret_ty = self.Gen.TypeGenResolve.resolve_annotation_type(
pool, fd.returns, imported_modules, from_imports, trans)
pool, fd.returns, imported_modules, from_imports, trans, 0)
# 单独 t.CExport 返回注解(def free(...) -> t.CExport:)= 导出
# 修饰符,无实际返回类型 → Void(根因:CExport 被 map_t_type 回退
# 为 i32 → 掉尾检查强制 return i32,mm.vp free 根因)。
# 混合实际类型(-> t.CExport | t.CInt)时保持解析结果。
if fd.returns.kind() == ast.ASTKind.Attribute:
ce_at2: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(fd.returns)
if ce_at2.attr is not None and string.strcmp(ce_at2.attr, "CExport") == 0:
if ce_at2.value is not None and ce_at2.value.kind() == ast.ASTKind.Name:
ce_nm2: ast.Name | t.CPtr = (ast.Name | t.CPtr)(ce_at2.value)
if ce_nm2.id is not None and string.strcmp(ce_nm2.id, "t") == 0:
ret_ty = llvmlite.Void(pool)
# 如果返回类型注解纯装饰器标记(如 t.State,无实际类型),使用 void
# 注意:必须在 infer_return_type 之前检测,因为 infer_return_type 至少返回 i32
if ret_ty is None and fd.returns is not None:
if self.Gen.TypeGenErr.has_decorator_marker(fd.returns, "State") != 0:
if self.Gen.TypeGenErr.has_decorator_marker(fd.returns, "State", 0) != 0:
ret_ty = llvmlite.Void(pool)
# @c.CReturn(ty1, ty2, ...) 装饰器 → 多返回 struct 类型
# (GetMemoryStats 根因:TPC DeclarationGenerator 处理 CReturn 为
# '{i64, i64, i64}',TPV pre_scan 前向声明阶段未实现 → 无注解函数
# declare 成 i32 → 定义阶段 ret {i64,i64,i64} 与 i32 不匹配。
# 公共方法 _resolve_creturn_ret_ty 保证声明/定义两阶段一致)
if ret_ty is None:
ret_ty = self.Gen.FuncGenBase._resolve_creturn_ret_ty(
pool, fd, imported_modules, from_imports, trans)
# 如果仍然为 None,扫描 return 语句推断(至少返回 i32)
if ret_ty is None:
param_types_str: str = self.Gen.TypeGenErr.build_param_types_str(pool, fd.args)
@@ -269,9 +306,9 @@ class FuncGenDef(CallGenBase.CallGenBase):
has_extern: int = 0
has_state: int = 0
if fd.returns is not None:
has_extern = self.Gen.TypeGenErr.has_decorator_marker(fd.returns, "CExtern")
has_state = self.Gen.TypeGenErr.has_decorator_marker(fd.returns, "State")
has_export = self.Gen.TypeGenErr.has_decorator_marker(fd.returns, "CExport")
has_extern = self.Gen.TypeGenErr.has_decorator_marker(fd.returns, "CExtern", 0)
has_state = self.Gen.TypeGenErr.has_decorator_marker(fd.returns, "State", 0)
has_export = self.Gen.TypeGenErr.has_decorator_marker(fd.returns, "CExport", 0)
# t.CExtern/t.State 忽略 body 体,仅声明(无论 body 是否为 pass)
if has_extern != 0 or has_state != 0:
is_extern_decl = 1
@@ -400,7 +437,7 @@ class FuncGenDef(CallGenBase.CallGenBase):
param_ty_e: llvmlite.LLVMType | t.CPtr = i32_ty
if arg_e.annotation is not None:
resolved_e: llvmlite.LLVMType | t.CPtr = self.Gen.TypeGenResolve.resolve_annotation_type(
pool, arg_e.annotation, imported_modules, from_imports, trans)
pool, arg_e.annotation, imported_modules, from_imports, trans, 0)
if resolved_e is None:
# fail-fast:外部声明函数参数有注解但类型解析失败,
# 不再静默保持 i32(声明签名错误会在 ABI 层暴露)
@@ -424,6 +461,7 @@ class FuncGenDef(CallGenBase.CallGenBase):
llvmlite.add_param(pool, func, param_ty_e, pname_e)
# 提取 @c.Attribute 装饰器属性并设置到函数
stdio.printf("[ATTR] call@decl: func='%s'\n", fd.name)
func_attrs_e: str = self.Gen.FuncGenBase.extract_func_attrs(pool, fd.decorator_list, imported_modules)
if func_attrs_e is not None:
llvmlite.function_set_attrs(func, func_attrs_e)
@@ -442,6 +480,7 @@ class FuncGenDef(CallGenBase.CallGenBase):
# 复用前向声明:清除 IsDeclared 标记,转为 define
func.IsDeclared = 0
# 装饰器属性设置(前向声明时未设置)
stdio.printf("[ATTR] call@reuse: func='%s'\n", fd.name)
func_attrs_reuse: str = self.Gen.FuncGenBase.extract_func_attrs(pool, fd.decorator_list, imported_modules)
if func_attrs_reuse is not None:
llvmlite.function_set_attrs(func, func_attrs_reuse)
@@ -456,6 +495,7 @@ class FuncGenDef(CallGenBase.CallGenBase):
return 0
# 提取 @c.Attribute 装饰器属性并设置到函数
stdio.printf("[ATTR] call@new: func='%s'\n", fd.name)
func_attrs: str = self.Gen.FuncGenBase.extract_func_attrs(pool, fd.decorator_list, imported_modules)
if func_attrs is not None:
llvmlite.function_set_attrs(func, func_attrs)
@@ -497,7 +537,7 @@ class FuncGenDef(CallGenBase.CallGenBase):
param_ty: llvmlite.LLVMType | t.CPtr = i32_ty
if arg.annotation is not None:
resolved: llvmlite.LLVMType | t.CPtr = self.Gen.TypeGenResolve.resolve_annotation_type(
pool, arg.annotation, imported_modules, from_imports, trans)
pool, arg.annotation, imported_modules, from_imports, trans, 0)
if resolved is not None:
# 裸类形参 → Ptr(struct)(对象即指针,与方法形参一致)
# CArray 形参 → 元素指针 ty*(C 数组衰减:final(out: t.CArray[..., N])
@@ -651,7 +691,7 @@ class FuncGenDef(CallGenBase.CallGenBase):
param_ty2: llvmlite.LLVMType | t.CPtr = i32_ty
if arg2.annotation is not None:
resolved2: llvmlite.LLVMType | t.CPtr = self.Gen.TypeGenResolve.resolve_annotation_type(
pool, arg2.annotation, imported_modules, from_imports, trans)
pool, arg2.annotation, imported_modules, from_imports, trans, 0)
if resolved2 is None:
# fail-fast:参数有注解但类型解析失败,不再静默保持 i32
self.Gen.TypeGenErr.fatal_error(