fix(gen): 嵌套 def 的返回类型跟随 -> T 注解(原先写死 i32)
现场:def Inner(p: char*) -> char*: return p 报 CastError: implicit pointer-to-integer conversion is forbidden ... —— 因为 translate_nested_function_def 把提升后的闭包函数写死成 define i32 @__closure_Inner(i8* %env, i8* %p)(grep 过整个文件,从未读 fd.returns), return p 于是要把 char* 隐式转 i32。即"嵌套 def 只支持 int 返回",此前被同文件 更早的用例报错掩盖(EscapeMethodTest 的 (A)/(B) 因同命裁剪静音后才露出来)。 改动: - 提升函数按 fd.returns 解析返回类型(resolve_annotation_type);解析不出 -> fail-fast。 边界:fd.returns 为 None 或注解是 None / t.CVoid 时**保持 i32**(不改既有 ABI, 避免打断现有无返回值/无注解的嵌套 def)。 - 隐式收尾的零值改为 ConstZero(ret_ty)(原写死 const_int32(0),签名一变 llc 会拒绝), 取不到零值则 fail-fast。 已知未覆盖:lambda 的提升路径同样写死 i32(见 FuncGenMixin 中 lambda 分支), 本轮不动(lambda 无返回注解可跟随)。
This commit is contained in:
1 parent
41674d125c
commit
5d1e604aac
1 file changed
+36
-4
@@ -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 <ret> @__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)
|
||||
|
||||
Reference in new issue
Block a user