diff --git a/App/lib/core/Gen/Func/FuncGenMixin.vp b/App/lib/core/Gen/Func/FuncGenMixin.vp index f87b305..344125f 100644 --- a/App/lib/core/Gen/Func/FuncGenMixin.vp +++ b/App/lib/core/Gen/Func/FuncGenMixin.vp @@ -47,8 +47,35 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase): if promoted_name is not None: viperlib.snprintf(promoted_name, 64, "__closure_%s", func_name) mangled_promoted: str = self.Gen.FuncGenBase._mangle_name(trans, promoted_name) - # 2. Create the promoted function: define i32 @__closure_{name}(i8* %env, args...) - func: mlirlite.Function* = mlirlite.create_function(pool, mod, mangled_promoted, i32_ty) + # 2. Create the promoted function: define @__closure_{name}(i8* %env, args...) + # 返回类型**跟随 `-> T` 注解**。原实现写死 i32:于是 `def Inner(p: char*) -> char*: return p` + # 生成 `define i32 @__closure_Inner(i8* %env, i8* %p)`,而 `return p` 要把 char* 隐式转 i32 + # → 撞 coerce_to_type 的 CastError(现场:EscapeMethodTest 的 (C) 用例)。那是"嵌套 def + # 只支持 int 返回"这个预先存在的缺口,此前被同文件更早的用例报错掩盖。 + # 约定(最小改动的边界): + # · `fd.returns is None` 或注解是 `None` / `t.CVoid` → **保持 i32**(不改既有 ABI, + # 避免打断现有"无返回值/无注解"的嵌套 def;这是已知缺口,不在本次范围内); + # · 其余注解采用 resolve_annotation_type 的结果;解析不出 → fail-fast,不静默兜底。 + ret_ty_n: mlirlite.LLVMType* = i32_ty + if fd.returns is not None: + keep_i32_n: int = 0 + if fd.returns.kind() == ast.ASTKind.Constant: + rc_n: ast.Constant* = ast.Constant*(fd.returns) + if rc_n is not None and rc_n.const_kind == ast.CONST_NONE: keep_i32_n = 1 + if self.Gen.TypeGenResolve._is_cvoid_marker(fd.returns, trans._imported_modules) != 0: keep_i32_n = 1 + if keep_i32_n == 0: + rt_res_n: mlirlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(pool, fd.returns, trans._imported_modules, trans._from_imports, trans, 0) + if rt_res_n is None: + self.Gen.TypeGenErr.fatal_error(fd, f"nested function '{fd.name}': cannot resolve the return type annotation for the promoted closure", "TypeError") + else: + rt_is_void_n: int = 0 + match rt_res_n: + case mlirlite.LLVMType.Void(): + rt_is_void_n = 1 + case _: + pass + if rt_is_void_n == 0: ret_ty_n = rt_res_n + func: mlirlite.Function* = mlirlite.create_function(pool, mod, mangled_promoted, ret_ty_n) if func is None: return 0 mlirlite.add_param(pool, func, i8_ptr_ty, "%env") @@ -225,8 +252,13 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase): if last_is_return == 0: # M3:隐式收尾也是函数出口,先释放本嵌套函数登记的 slife self.Gen.VarGen._SlifeEmitFrees(pool, func_builder, mod, trans) - zero_val: mlirlite.Value* = mlirlite.const_int32(pool, 0) - mlirlite.build_ret(func_builder, zero_val) + # 零值必须与**本函数的返回类型**一致(原实现写死 const_int32(0):一旦返回类型改为 + # `char*` 之类,`ret i32 0` 与签名不符,llc 会直接拒绝)。ret_ty_n 见第 2 步。 + zero_val: mlirlite.Value* = mlirlite.ConstZero(pool, ret_ty_n) + if zero_val is None: + self.Gen.TypeGenErr.fatal_error(fd, f"nested function '{fd.name}': flow falls off the end without an implicit return and the return type has no zero value", "TypeError") + else: + mlirlite.build_ret(func_builder, zero_val) # M3:弹回外层登记区间(释放已在本嵌套函数各出口完成) self.Gen.VarGen._SlifeRestore(old_slife_base)