debug(funcattrs): 添加 @c.Attribute 属性提取链运行时诊断,定位 stackrealign 未进 IR
This commit is contained in:
1 parent
2165c171e7
commit
e60be41ad8
2 files changed
+95
-21
No files matched your search
@@ -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
|
||||
|
||||
@@ -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(
|
||||
|
||||
Reference in new issue
Block a user