From e60be41ad8a01abfd3fdd41ad8ca9d19eba737a6 Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Wed, 26 Aug 2026 20:35:09 +0800 Subject: [PATCH] =?UTF-8?q?debug(funcattrs):=20=E6=B7=BB=E5=8A=A0=20@c.Att?= =?UTF-8?q?ribute=20=E5=B1=9E=E6=80=A7=E6=8F=90=E5=8F=96=E9=93=BE=E8=BF=90?= =?UTF-8?q?=E8=A1=8C=E6=97=B6=E8=AF=8A=E6=96=AD=EF=BC=8C=E5=AE=9A=E4=BD=8D?= =?UTF-8?q?=20stackrealign=20=E6=9C=AA=E8=BF=9B=20IR?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- App/lib/core/Gen/FuncGenBase.vp | 48 +++++++++++++++++++---- App/lib/core/Gen/FuncGenDef.vp | 68 ++++++++++++++++++++++++++------- 2 files changed, 95 insertions(+), 21 deletions(-) diff --git a/App/lib/core/Gen/FuncGenBase.vp b/App/lib/core/Gen/FuncGenBase.vp index c5ab58d..41b4d0c 100644 --- a/App/lib/core/Gen/FuncGenBase.vp +++ b/App/lib/core/Gen/FuncGenBase.vp @@ -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 diff --git a/App/lib/core/Gen/FuncGenDef.vp b/App/lib/core/Gen/FuncGenDef.vp index b18ebb7..c083651 100644 --- a/App/lib/core/Gen/FuncGenDef.vp +++ b/App/lib/core/Gen/FuncGenDef.vp @@ -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(