fix(gen): struct 返回类型解析 + 变参提升 + 泛型隐式推断三组修复
1. _ParseLLVMRetTyStr 支持 struct 字面量 {T1,T2,...}:"{i8*,i16}" 内含 * 被
误判为 i8*,b2a_hqx tuple[str,u16] 调用侧返回类型退化 → HandlesAssign
tuple 解包静默跳过 → 目标未初始化 → free 垃圾指针崩溃(HashLibTest hqx);
2. 变参提升 is_u_va 失败时 i8 默认 zext:printf("%02x", uint8) 不再 sext 成
0xFFFFFFF3 输出 ffffffXX(对齐 should_zext_widen 无符号字节策略);
3. _infer_generic_ctor_type_arg:Name("CInt")/("CFloat64T") 裸名类型转换补
strstr 匹配(from t import 后 func 是 Name);非类型转换实参(pool 等非
T 参数)返回默认 int 被"过滤纯 int"排除,不再 fail-fast(VectorGenericTest
隐式泛型推断),仅 Call 类型转换识别失败才 fail-fast。
This commit is contained in:
1 parent
9bb6dd7612
commit
19f48eea02
1 file changed
+71
-8
@@ -3018,6 +3018,49 @@ class CallGenMixin:
|
||||
if ty_len == 0:
|
||||
return None
|
||||
|
||||
# struct 字面量 {T1, T2, ...}(tuple 打包返回类型,如 b2a_hqx ->
|
||||
# tuple[str, t.CUnsignedShort] 编译为 {i8*, i16})。必须在 * 检查
|
||||
# 之前——否则 "{i8*, i16}" 内含 * 会被误判为 i8*(b2a_hqx 调用侧
|
||||
# 返回类型退化 i8* → HandlesAssign tuple 解包静默跳过 → free 未初始化
|
||||
# 指针崩溃,HashLibTest hqx 段)。
|
||||
if s < e and buf[s] == '{':
|
||||
th_st: llvmlite.ParamNode | t.CPtr = None
|
||||
tt_st: llvmlite.ParamNode | t.CPtr = None
|
||||
tc_st: int = 0
|
||||
ps_st: t.CSizeT = s + 1
|
||||
while ps_st < e and buf[ps_st] != '}':
|
||||
while ps_st < e and (buf[ps_st] == ' ' or buf[ps_st] == ','):
|
||||
ps_st += 1
|
||||
if ps_st >= e or buf[ps_st] == '}':
|
||||
break
|
||||
es_st: t.CSizeT = ps_st
|
||||
while ps_st < e and buf[ps_st] != ',' and buf[ps_st] != '}':
|
||||
ps_st += 1
|
||||
ee_st: t.CSizeT = ps_st
|
||||
if ee_st > es_st:
|
||||
et_st: llvmlite.LLVMType | t.CPtr = self._ParseLLVMRetTyStr(
|
||||
pool, buf, es_st, ee_st)
|
||||
if et_st is None:
|
||||
return None
|
||||
en_st: llvmlite.ParamNode | t.CPtr = llvmlite.new_param_node(
|
||||
pool, et_st)
|
||||
if en_st is None:
|
||||
return None
|
||||
if th_st is None:
|
||||
th_st = en_st
|
||||
else:
|
||||
llvmlite.paramnode_set_next(tt_st, en_st)
|
||||
tt_st = en_st
|
||||
tc_st += 1
|
||||
if th_st is None or tc_st == 0:
|
||||
return None
|
||||
st_ty_st: llvmlite.LLVMType | t.CPtr = llvmlite.Struct(pool, th_st, tc_st, None)
|
||||
# 指针到 struct({i32, i8}*):返回 Ptr(Struct);纯 tuple 打包
|
||||
# ({i8*, i16})无尾部 *,返回 Struct 本身。
|
||||
if ps_st < e and buf[ps_st] == '*':
|
||||
return llvmlite.Ptr(pool, st_ty_st)
|
||||
return st_ty_st
|
||||
|
||||
# 检查是否含 * (指针类型) → 返回 i8* (通用指针)
|
||||
# 包括 i8*, i32*, %"name"*, { i32, i8 }* 等
|
||||
ci: t.CSizeT = s
|
||||
@@ -4793,9 +4836,16 @@ class CallGenMixin:
|
||||
if cl_f.func.kind() == ast.ASTKind.Name:
|
||||
fn_nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(cl_f.func)
|
||||
if fn_nm.id is not None:
|
||||
if string.strcmp(fn_nm.id, "float") == 0:
|
||||
# 与下方 Attribute 分支的 strstr 匹配一致:from t import CInt
|
||||
# 后 `CInt(0)` 的 func 是 Name("CInt"),仅精确匹配 int/float
|
||||
# 会漏判 → fail-fast 误杀(VectorGenericTest 隐式泛型推断)。
|
||||
if string.strcmp(fn_nm.id, "float") == 0 or string.strcmp(fn_nm.id, "double") == 0 \
|
||||
or string.strstr(fn_nm.id, "Float") is not None or string.strstr(fn_nm.id, "Double") is not None:
|
||||
return "double"
|
||||
if string.strcmp(fn_nm.id, "int") == 0:
|
||||
if string.strcmp(fn_nm.id, "int") == 0 \
|
||||
or string.strstr(fn_nm.id, "Int") is not None or string.strstr(fn_nm.id, "UInt") is not None \
|
||||
or string.strstr(fn_nm.id, "Char") is not None or string.strstr(fn_nm.id, "Short") is not None \
|
||||
or string.strstr(fn_nm.id, "Long") is not None:
|
||||
return "int"
|
||||
elif cl_f.func.kind() == ast.ASTKind.Attribute:
|
||||
fn_at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(cl_f.func)
|
||||
@@ -4804,11 +4854,16 @@ class CallGenMixin:
|
||||
return "double"
|
||||
if string.strstr(fn_at.attr, "Int") is not None or string.strstr(fn_at.attr, "UInt") is not None or string.strstr(fn_at.attr, "Char") is not None or string.strstr(fn_at.attr, "Short") is not None or string.strstr(fn_at.attr, "Long") is not None:
|
||||
return "int"
|
||||
# 无法从 AST 静态推断:fail-fast,绝不静默默认 "int"(会特化出错误类型)
|
||||
HandlesType.fatal_error(
|
||||
arg_node,
|
||||
f"无法从实参推断泛型类 '{class_name}' 的类型实参,请显式标注如 {class_name}[类型](...)",
|
||||
"TypeError")
|
||||
# 类型转换调用(Call)但函数名无法识别:明确的类型意图却无法解析,
|
||||
# fail-fast(区别于普通变量 Name——那是非 T 参数,默认 int 被过滤)。
|
||||
HandlesType.fatal_error(
|
||||
arg_node,
|
||||
f"无法从实参推断泛型类 '{class_name}' 的类型实参,请显式标注如 {class_name}[类型](...)",
|
||||
"TypeError")
|
||||
return "int"
|
||||
# 非类型转换节点(普通变量 Name/Attribute 等,如 Vector(pool, 8, ...)
|
||||
# 的 pool 参数):不是 T 类型提示,返回默认 "int"(调用方"过滤纯 int"
|
||||
# 逻辑将其排除,只保留 float/str 等区分性提示)。
|
||||
return "int"
|
||||
|
||||
def _translate_generic_ctor_call(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
@@ -7619,7 +7674,15 @@ class CallGenMixin:
|
||||
if is_u_va != 0:
|
||||
promoted = llvmlite.build_zext(builder, cur, i32_ty_promote)
|
||||
else:
|
||||
promoted = HandlesExpr.coerce_to_type(builder, cur, i32_ty_promote, None)
|
||||
# is_u_va 判断失败(arg_nodes/trans 缺失或变量注解查不到)时,
|
||||
# i8 按系统编程惯例默认 zext(对齐 should_zext_widen 的
|
||||
# "i8 → zext(系统编程中 i8 几乎总是无符号字节)"策略),
|
||||
# 否则 printf("%02x", buf[i]) 中 uint8 字节被 sext 成
|
||||
# 0xFFFFFFF3,哈希摘要输出 ffffffXX 垃圾。
|
||||
if HandlesExpr.get_llvm_type_bits(cur.Ty) == 8:
|
||||
promoted = llvmlite.build_zext(builder, cur, i32_ty_promote)
|
||||
else:
|
||||
promoted = HandlesExpr.coerce_to_type(builder, cur, i32_ty_promote, None)
|
||||
if promoted is not None:
|
||||
promoted.Next = next_node
|
||||
if prev is not None:
|
||||
|
||||
Reference in new issue
Block a user