'fix(core): support keyword args in method calls
_translate_method_call ignored cl.keywords, so keyword-style calls
like add_argument("--count", short="-c", arg_type=INT) lost all
keyword values (short_name/arg_type stayed default), breaking
Test 4. Match keywords against function params by name, fill
missing params with zero values to keep call arity consistent.'
This commit is contained in:
1 parent
f7cc0f84d1
commit
987088fdff
5 files changed
+218
-145
No files matched your search
@@ -228,9 +228,6 @@ def _cache_vpi_return_annots_text(vpi_buf: bytes, src_sha1: str) -> int:
|
||||
vpi_buf + rstart, rtype_len)
|
||||
(_g_vpi_ret_strs + _g_vpi_ret_count * VPI_RET_LEN)[rtype_len] = '\0'
|
||||
_g_vpi_ret_count += 1
|
||||
# [DBG-MC] 临时诊断(验证后移除)
|
||||
if string.strstr(key_buf, "parse_args") is not None:
|
||||
stdio.printf("[DBG-MC] cache write idx=%d key=%s\n", _g_vpi_ret_count - 1, key_buf)
|
||||
stdlib.free(key_buf)
|
||||
stdlib.free(mname_buf)
|
||||
pos = le + 1
|
||||
@@ -245,10 +242,6 @@ def _cache_vpi_return_annots_text(vpi_buf: bytes, src_sha1: str) -> int:
|
||||
# ============================================================
|
||||
def _lookup_vpi_ret_annot(src_sha1: str, cls_name: str, method_name: str) -> str:
|
||||
"""查找缓存的方法返回注解字符串,未找到返回 None"""
|
||||
# [DBG-MC] 临时诊断(验证后移除)
|
||||
if method_name is not None and string.strcmp(method_name, "parse_args") == 0:
|
||||
stdio.printf("[DBG-MC] lookup parse_args keys=%d count=%d sha1=%s\n",
|
||||
1 if _g_vpi_ret_keys is not None else 0, _g_vpi_ret_count, src_sha1)
|
||||
if _g_vpi_ret_keys is None or _g_vpi_ret_count == 0:
|
||||
return None
|
||||
if src_sha1 is None or method_name is None:
|
||||
@@ -731,6 +724,14 @@ def _inject_function_declare(pool: memhub.MemBuddy | t.CPtr,
|
||||
resolved_ty: llvmlite.LLVMType | t.CPtr = HandlesType.resolve_annotation_type(
|
||||
pool, ag.annotation, imported_modules, from_imports, trans)
|
||||
if resolved_ty is not None:
|
||||
# 结构体按值参数 → i64:跨模块结构体在本模块是 opaque
|
||||
# (未定义字段),LLVM 不允许 opaque struct 作为函数参数
|
||||
# (llc: invalid type for function argument)。Windows ABI
|
||||
# 小结构体(≤8 字节,如 COORD)按整数寄存器传,映射 i64 兼容。
|
||||
match resolved_ty:
|
||||
case llvmlite.LLVMType.Struct(_, _, _):
|
||||
param_ty = llvmlite.Int64(pool)
|
||||
case _:
|
||||
param_ty = resolved_ty
|
||||
llvmlite.add_param(pool, func, param_ty, pname)
|
||||
# *args 变长参数:标记 IsVarArg=1,使调用侧走 C ABI 参数提升
|
||||
@@ -811,31 +812,6 @@ def _inject_method_declare(pool: memhub.MemBuddy | t.CPtr,
|
||||
if ret_ty is None:
|
||||
ret_ty = i32_ty
|
||||
|
||||
# [DBG-MC] 临时诊断(验证后移除)
|
||||
if cls_name is not None and string.strcmp(m_fd.name, "parse_args") == 0 and string.strcmp(cls_name, "ArgumentParser") == 0:
|
||||
if ret_annot is not None:
|
||||
stdio.printf("[DBG-MC] inject parse_args ret_annot='%s'\n", ret_annot)
|
||||
match ret_ty:
|
||||
case llvmlite.LLVMType.Ptr(pe_rt2):
|
||||
match pe_rt2:
|
||||
case llvmlite.LLVMType.Struct(f_rt2, c_rt2, n_rt2):
|
||||
if n_rt2 is not None:
|
||||
stdio.printf("[DBG-MC] inject parse_args ret_ty Ptr(Struct(%s))\n", n_rt2)
|
||||
else:
|
||||
stdio.printf("[DBG-MC] inject parse_args ret_ty Ptr(Struct<no-name>)\n")
|
||||
case llvmlite.LLVMType.Int(b_rt2):
|
||||
stdio.printf("[DBG-MC] inject parse_args ret_ty Ptr(i%d)\n", b_rt2)
|
||||
case _:
|
||||
stdio.printf("[DBG-MC] inject parse_args ret_ty Ptr(inner-other)\n")
|
||||
case llvmlite.LLVMType.Int(b_rt2):
|
||||
stdio.printf("[DBG-MC] inject parse_args ret_ty i%d\n", b_rt2)
|
||||
case llvmlite.LLVMType.Void():
|
||||
stdio.printf("[DBG-MC] inject parse_args ret_ty Void\n")
|
||||
case _:
|
||||
stdio.printf("[DBG-MC] inject parse_args ret_ty other\n")
|
||||
else:
|
||||
stdio.printf("[DBG-MC] inject parse_args ret_annot=None\n")
|
||||
|
||||
# 创建 declare
|
||||
func: llvmlite.Function | t.CPtr = llvmlite.create_declare(
|
||||
pool, mod, mangled_name, ret_ty)
|
||||
@@ -863,6 +839,14 @@ def _inject_method_declare(pool: memhub.MemBuddy | t.CPtr,
|
||||
resolved_ty: llvmlite.LLVMType | t.CPtr = HandlesType.resolve_annotation_type(
|
||||
pool, ag.annotation, imported_modules, from_imports, trans)
|
||||
if resolved_ty is not None:
|
||||
# 结构体按值参数 → i64:跨模块结构体在本模块是 opaque
|
||||
# (未定义字段),LLVM 不允许 opaque struct 作为函数参数
|
||||
# (llc: invalid type for function argument)。Windows ABI
|
||||
# 小结构体(≤8 字节,如 COORD)按整数寄存器传,映射 i64 兼容。
|
||||
match resolved_ty:
|
||||
case llvmlite.LLVMType.Struct(_, _, _):
|
||||
param_ty = llvmlite.Int64(pool)
|
||||
case _:
|
||||
param_ty = resolved_ty
|
||||
llvmlite.add_param(pool, func, param_ty, pname)
|
||||
|
||||
|
||||
@@ -288,6 +288,10 @@ def coerce_to_type(builder: llvmlite.IRBuilder | t.CPtr,
|
||||
if val_bits == target_bits:
|
||||
return val
|
||||
if val_bits < target_bits:
|
||||
# i1 (bool) → 更宽整数用 zext(bool 语义:1 保持 1,而非 sext 的 0xFF...)
|
||||
# 与 HandlesReturn 中 return 语句的 i1 扩展规则保持一致
|
||||
if val_bits == 1:
|
||||
return llvmlite.build_zext(builder, val, target_ty)
|
||||
return llvmlite.build_sext(builder, val, target_ty)
|
||||
return llvmlite.build_trunc(builder, val, target_ty)
|
||||
# 浮点转换
|
||||
@@ -987,12 +991,19 @@ def translate_compare(builder: llvmlite.IRBuilder | t.CPtr,
|
||||
rhs = llvmlite.const_int32(pool, 0)
|
||||
|
||||
# 类型对齐:icmp 要求两边类型相同
|
||||
# 仅对数值类型做 sext 对齐(指针类型无需对齐,LLVM 允许同层级指针直接 icmp)
|
||||
# 仅对数值类型做对齐(指针类型无需对齐,LLVM 允许同层级指针直接 icmp)
|
||||
# i1 (bool) 侧用 zext 对齐(1 保持 1,而非 sext 的 0xFF...)
|
||||
lhs_bits: int = get_llvm_type_bits(lhs.Ty)
|
||||
rhs_bits: int = get_llvm_type_bits(rhs.Ty)
|
||||
if lhs_bits != 0 and rhs_bits != 0 and lhs_bits != rhs_bits:
|
||||
if lhs_bits < rhs_bits:
|
||||
if lhs_bits == 1:
|
||||
lhs = llvmlite.build_zext(builder, lhs, rhs.Ty)
|
||||
else:
|
||||
lhs = llvmlite.build_sext(builder, lhs, rhs.Ty)
|
||||
else:
|
||||
if rhs_bits == 1:
|
||||
rhs = llvmlite.build_zext(builder, rhs, lhs.Ty)
|
||||
else:
|
||||
rhs = llvmlite.build_sext(builder, rhs, lhs.Ty)
|
||||
|
||||
|
||||
@@ -661,17 +661,23 @@ def _emit_llvm_memcpy_intrinsic(pool: memhub.MemBuddy | t.CPtr,
|
||||
return dst_coerced
|
||||
|
||||
# ============================================================
|
||||
# c.Deref(ptr) — 解引用指针,load i8(字符遍历用例)
|
||||
# c.Deref(ptr) — 解引用指针,按指针 pointee 类型读取
|
||||
#
|
||||
# 生成: %N = load i8, i8* %ptr
|
||||
# 返回 i8 值
|
||||
# 生成: %N = load <pointee_ty>, <pointee_ty>* %ptr
|
||||
# 返回 pointee 类型的值
|
||||
#
|
||||
# 注意: 必须按 ptr 的 pointee 类型决定读取宽度。
|
||||
# - i8* (str/bytes/字符遍历) → load i8
|
||||
# - i64* (t.CUInt64T, 块头部) → load i64(memhub 的 free list 链表读 8 字节头部)
|
||||
# 之前固定 load i8 导致 memhub 读块头部只读到低 8 位,
|
||||
# free list 的 next 指针被截断成 0x88 等垃圾值,alloc 崩溃。
|
||||
# ============================================================
|
||||
def translate_c_deref(pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
cl: ast.Call | t.CPtr,
|
||||
trans: HT.Translator | t.CPtr = None) -> llvmlite.Value | t.CPtr:
|
||||
"""c.Deref(ptr) → load i8 from ptr"""
|
||||
"""c.Deref(ptr) → load 按 ptr 的 pointee 类型"""
|
||||
if cl is None:
|
||||
return None
|
||||
cargs: list[ast.AST | t.CPtr] | t.CPtr = cl.args
|
||||
@@ -683,6 +689,11 @@ def translate_c_deref(pool: memhub.MemBuddy | t.CPtr,
|
||||
if ptr_val is None:
|
||||
return None
|
||||
|
||||
# 按 pointee 类型读取;非指针参数默认按 i8(保持向后兼容)
|
||||
if HandlesExpr.is_ptr_type(ptr_val.Ty) != 0:
|
||||
pointee: llvmlite.LLVMType | t.CPtr = ptr_val.Ty.Pointee
|
||||
if pointee is not None:
|
||||
return llvmlite.build_load(builder, pointee, ptr_val)
|
||||
i8_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool)
|
||||
return llvmlite.build_load(builder, i8_ty, ptr_val)
|
||||
|
||||
@@ -2795,16 +2806,41 @@ def _call_method_on_ptr(pool: memhub.MemBuddy | t.CPtr,
|
||||
frt: llvmlite.LLVMType | t.CPtr = llvmlite.function_get_ret_ty(found_func)
|
||||
if frt is not None:
|
||||
call_ret_ty = frt
|
||||
elif string.strcmp(method_name, "__getitem__") == 0 or string.strcmp(method_name, "__new__") == 0:
|
||||
# fail-fast:__getitem__/__new__ 必返回指针,返回类型缺失意味着
|
||||
# stub declare 损坏,静默推断会截断指针(32 位)崩溃,立即终止。
|
||||
err_cm1: t.CChar | t.CPtr = pool.alloc(256)
|
||||
if err_cm1 is not None:
|
||||
viperlib.snprintf(err_cm1, 256,
|
||||
"方法 '%s' 返回类型无法确定(stub declare 返回类型缺失)", method_name)
|
||||
HandlesType.fatal_error(None, err_cm1)
|
||||
HandlesType.fatal_error(None, "方法返回类型无法确定")
|
||||
else:
|
||||
# found_func 为 None(跨模块调用 stub 未注入):根据方法名推断返回类型
|
||||
# __new__ 返回 Ptr(struct_ty)
|
||||
# __getitem__ 返回 Ptr(struct_ty)(自定义结构体 subscript 读取)
|
||||
# 其他方法默认 void
|
||||
if string.strcmp(method_name, "__new__") == 0 and cmop_struct_ty is not None:
|
||||
call_ret_ty = llvmlite.Ptr(pool, cmop_struct_ty)
|
||||
elif string.strcmp(method_name, "__getitem__") == 0 and cmop_struct_ty is not None:
|
||||
# __getitem__ 返回对象指针 (如 JsonValue|t.CPtr, HashTable|t.CPtr)
|
||||
# found_func 为 None(跨模块调用 stub 未注入):无法从 declare 获取返回类型。
|
||||
# __new__ 返回 Ptr(struct_ty)(构造函数返回自身指针,可推断)。
|
||||
# __getitem__ 返回类型无法从 self 推断(可返回 i8* 如 HashTable.__getitem__
|
||||
# -> t.CPtr,或 Ptr(JsonValue) 如 JsonValue.__getitem__)——推断 Ptr(cmop_struct_ty)
|
||||
# 会与 define 返回类型不匹配,调用侧按错误类型读取返回值导致指针截断崩溃。
|
||||
# fail-fast:__getitem__ 无 stub declare 立即报错,暴露依赖模块 vpi 缺失或
|
||||
# 拓扑顺序错误(依赖模块未先翻译生成 vpi/text.ll)。
|
||||
if string.strcmp(method_name, "__new__") == 0:
|
||||
if cmop_struct_ty is not None:
|
||||
call_ret_ty = llvmlite.Ptr(pool, cmop_struct_ty)
|
||||
else:
|
||||
err_cm2: t.CChar | t.CPtr = pool.alloc(256)
|
||||
if err_cm2 is not None:
|
||||
viperlib.snprintf(err_cm2, 256,
|
||||
"方法 '%s' 的 self 结构体类型未知(字段类型退化,依赖模块未预注册?)", method_name)
|
||||
HandlesType.fatal_error(None, err_cm2)
|
||||
HandlesType.fatal_error(None, "self 结构体类型未知")
|
||||
elif string.strcmp(method_name, "__getitem__") == 0:
|
||||
err_cm3: t.CChar | t.CPtr = pool.alloc(256)
|
||||
if err_cm3 is not None:
|
||||
viperlib.snprintf(err_cm3, 256,
|
||||
"方法 '%s.__getitem__' 的 stub declare 未注入(依赖模块 vpi 缺失或拓扑顺序错误),无法确定返回类型",
|
||||
class_name)
|
||||
HandlesType.fatal_error(None, err_cm3)
|
||||
HandlesType.fatal_error(None, "__getitem__ stub declare 未注入")
|
||||
|
||||
# 构建参数链表: self_ptr → extra_args...
|
||||
llvmlite.value_set_next(self_ptr, None)
|
||||
@@ -3686,10 +3722,6 @@ def _translate_method_call(pool: memhub.MemBuddy | t.CPtr,
|
||||
if obj_ptr is None or cl is None:
|
||||
return None
|
||||
|
||||
# [DBG-MC] 临时诊断(验证后移除)
|
||||
if string.strcmp(method_name, "parse_args") == 0 or string.strcmp(method_name, "get_str") == 0:
|
||||
stdio.printf("[DBG-MC] method_call enter: %s.%s\n", class_name, method_name)
|
||||
|
||||
# 提前获取结构体 entry(用 find_struct_by_type 规避跨模块同名 find_struct 找错)
|
||||
# 用于继承链遍历、SHA1 查找和虚表分派
|
||||
mc_entry: HandlesStruct.StructEntry | t.CPtr = None
|
||||
@@ -3756,13 +3788,6 @@ def _translate_method_call(pool: memhub.MemBuddy | t.CPtr,
|
||||
viperlib.snprintf(mangled_mc, mangled_len_mc, "%s.%s", cls_sha1_mc, lookup_name)
|
||||
call_name = mangled_mc
|
||||
|
||||
# [DBG-MC] 临时诊断(验证后移除)
|
||||
if string.strcmp(method_name, "parse_args") == 0:
|
||||
if found_func is not None:
|
||||
stdio.printf("[DBG-MC] parse_args found_func=OK\n")
|
||||
else:
|
||||
stdio.printf("[DBG-MC] parse_args found_func=MISS cls_sha1=%s\n", cls_sha1_mc)
|
||||
|
||||
# 确定返回类型
|
||||
i32_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool)
|
||||
call_ret_ty: llvmlite.LLVMType | t.CPtr = i32_ty
|
||||
@@ -3780,43 +3805,66 @@ def _translate_method_call(pool: memhub.MemBuddy | t.CPtr,
|
||||
else:
|
||||
call_ret_ty = _infer_method_ret_ty(pool, method_name)
|
||||
|
||||
# [DBG-MC] 临时诊断(验证后移除)
|
||||
if string.strcmp(method_name, "parse_args") == 0:
|
||||
rt_kind: int = 0
|
||||
match call_ret_ty:
|
||||
case llvmlite.LLVMType.Ptr(pe_rt):
|
||||
rt_kind = 1
|
||||
match pe_rt:
|
||||
case llvmlite.LLVMType.Struct(f_rt_i, c_rt_i, n_rt_i):
|
||||
if n_rt_i is not None:
|
||||
stdio.printf("[DBG-MC] parse_args ret Ptr(Struct(%s))\n", n_rt_i)
|
||||
else:
|
||||
stdio.printf("[DBG-MC] parse_args ret Ptr(Struct<no-name>)\n")
|
||||
case llvmlite.LLVMType.Int(b_rt_i):
|
||||
stdio.printf("[DBG-MC] parse_args ret Ptr(i%d)\n", b_rt_i)
|
||||
case _:
|
||||
stdio.printf("[DBG-MC] parse_args ret Ptr(inner-other)\n")
|
||||
case llvmlite.LLVMType.Int(b_rt):
|
||||
rt_kind = 2
|
||||
stdio.printf("[DBG-MC] parse_args ret i%d\n", b_rt)
|
||||
case llvmlite.LLVMType.Void():
|
||||
rt_kind = 3
|
||||
stdio.printf("[DBG-MC] parse_args ret Void\n")
|
||||
case _:
|
||||
rt_kind = 0
|
||||
stdio.printf("[DBG-MC] parse_args ret kind=%d\n", rt_kind)
|
||||
|
||||
# 翻译调用参数
|
||||
cargs: list[ast.AST | t.CPtr] | t.CPtr = cl.args
|
||||
can: t.CSizeT = 0
|
||||
if cargs is not None:
|
||||
can = cargs.__len__()
|
||||
kw_calls: list[ast.AST | t.CPtr] | t.CPtr = cl.keywords
|
||||
kwc: t.CSizeT = 0
|
||||
if kw_calls is not None:
|
||||
kwc = kw_calls.__len__()
|
||||
|
||||
# 构建参数链表: obj_ptr → arg1 → arg2 → ...
|
||||
llvmlite.value_set_next(obj_ptr, None)
|
||||
head: llvmlite.Value | t.CPtr = obj_ptr
|
||||
tail: llvmlite.Value | t.CPtr = obj_ptr
|
||||
arg_count_eff: int = 0
|
||||
|
||||
if kwc > 0 and found_func is not None:
|
||||
# 关键字参数:遍历函数定义参数(跳过 self),位置参数优先,其余按名匹配
|
||||
# 缺失参数用零值兜底,保持 call 参数数量与 define 一致
|
||||
cur_param_k: llvmlite.Param | t.CPtr = llvmlite.function_get_param_head(found_func)
|
||||
if cur_param_k is not None:
|
||||
cur_param_k = llvmlite.param_get_next(cur_param_k) # 跳过 self
|
||||
pi_k: int = 0
|
||||
while cur_param_k is not None:
|
||||
arg_node_k: ast.AST | t.CPtr = None
|
||||
if pi_k < can:
|
||||
arg_node_k = cargs.get(pi_k)
|
||||
else:
|
||||
pname_k: t.CChar | t.CPtr = llvmlite.param_get_name(cur_param_k)
|
||||
if pname_k is not None:
|
||||
ki_k: int
|
||||
for ki_k in range(kwc):
|
||||
kw_k: ast.Keyword | t.CPtr = (ast.Keyword | t.CPtr)(kw_calls.get(ki_k))
|
||||
if kw_k is None or kw_k.arg is None or kw_k.value is None:
|
||||
continue
|
||||
if _kwarg_name_matches(kw_k.arg, pname_k) == 1:
|
||||
arg_node_k = kw_k.value
|
||||
break
|
||||
arg_val_k: llvmlite.Value | t.CPtr = None
|
||||
if arg_node_k is not None:
|
||||
arg_val_k = HandlesExpr.translate_value(
|
||||
builder, pool, mod, arg_node_k, None, 0, trans)
|
||||
if arg_val_k is None:
|
||||
# 缺失参数:零值兜底(保持参数数量匹配)
|
||||
pty_k: llvmlite.LLVMType | t.CPtr = llvmlite.param_get_ty(cur_param_k)
|
||||
if pty_k is not None:
|
||||
arg_val_k = llvmlite.ConstZero(pool, pty_k)
|
||||
if arg_val_k is not None:
|
||||
pty_k2: llvmlite.LLVMType | t.CPtr = llvmlite.param_get_ty(cur_param_k)
|
||||
if pty_k2 is not None:
|
||||
arg_val_k = HandlesExpr.coerce_to_type(
|
||||
builder, arg_val_k, pty_k2, arg_node_k)
|
||||
llvmlite.value_set_next(arg_val_k, None)
|
||||
llvmlite.value_set_next(tail, arg_val_k)
|
||||
tail = arg_val_k
|
||||
arg_count_eff += 1
|
||||
pi_k += 1
|
||||
cur_param_k = llvmlite.param_get_next(cur_param_k)
|
||||
else:
|
||||
# 位置参数(原逻辑)
|
||||
for ai in range(can):
|
||||
arg_node: ast.AST | t.CPtr = cargs.get(ai)
|
||||
if arg_node is None:
|
||||
@@ -3844,8 +3892,9 @@ def _translate_method_call(pool: memhub.MemBuddy | t.CPtr,
|
||||
llvmlite.value_set_next(arg_val, None)
|
||||
llvmlite.value_set_next(tail, arg_val)
|
||||
tail = arg_val
|
||||
arg_count_eff += 1
|
||||
|
||||
total_count: int = 1 + can
|
||||
total_count: int = 1 + arg_count_eff
|
||||
|
||||
# 默认参数填充:如果调用点参数少于函数定义参数,用默认值填充缺失参数
|
||||
# 查找函数的 defaults 信息
|
||||
@@ -3867,11 +3916,11 @@ def _translate_method_call(pool: memhub.MemBuddy | t.CPtr,
|
||||
mdf_param_count = mdf_gd.ParamCount
|
||||
|
||||
# 计算需要填充的参数(不含 self)
|
||||
# can = 已提供的非 self 参数数量
|
||||
# arg_count_eff = 已提供的非 self 参数数量(含关键字模式完整构建)
|
||||
# mdf_param_count = 函数定义的非 self 参数数量
|
||||
if mdf_param_count > can:
|
||||
if mdf_param_count > arg_count_eff:
|
||||
mdf_offset: int = mdf_param_count - mdf_default_count
|
||||
mdf_pi: int = can
|
||||
mdf_pi: int = arg_count_eff
|
||||
while mdf_pi < mdf_param_count:
|
||||
# 优先用默认值
|
||||
if mdf_defaults is not None and mdf_default_count > 0 and mdf_pi >= mdf_offset:
|
||||
@@ -4871,36 +4920,6 @@ def translate_call(pool: memhub.MemBuddy | t.CPtr,
|
||||
# 查找对象变量
|
||||
obj_var: llvmlite.Value | t.CPtr = HandlesVar.lookup_var(
|
||||
trans.SymTab, method_obj_nm.id)
|
||||
# [DBG-MC] 临时诊断(验证后移除)
|
||||
if string.strcmp(method_obj_nm.id, "args") == 0:
|
||||
if obj_var is None:
|
||||
stdio.printf("[DBG-MC] args NOT in symtab\n")
|
||||
elif obj_var.Ty is None:
|
||||
stdio.printf("[DBG-MC] args ty=None\n")
|
||||
else:
|
||||
akind: int = 0
|
||||
match obj_var.Ty:
|
||||
case llvmlite.LLVMType.Ptr(pe2):
|
||||
akind = 1
|
||||
match pe2:
|
||||
case llvmlite.LLVMType.Struct(f3, c3, n3):
|
||||
if n3 is not None:
|
||||
stdio.printf("[DBG-MC] args ty Ptr(Struct(%s))\n", n3)
|
||||
else:
|
||||
stdio.printf("[DBG-MC] args ty Ptr(Struct<no-name>)\n")
|
||||
case llvmlite.LLVMType.Int(b3):
|
||||
stdio.printf("[DBG-MC] args ty Ptr(i%d)\n", b3)
|
||||
case _:
|
||||
stdio.printf("[DBG-MC] args ty Ptr(inner-other)\n")
|
||||
case llvmlite.LLVMType.Int(b3b):
|
||||
akind = 2
|
||||
stdio.printf("[DBG-MC] args ty i%d\n", b3b)
|
||||
case llvmlite.LLVMType.Void():
|
||||
akind = 3
|
||||
stdio.printf("[DBG-MC] args ty Void\n")
|
||||
case _:
|
||||
akind = 0
|
||||
stdio.printf("[DBG-MC] args ty kind=%d\n", akind)
|
||||
if obj_var is not None and obj_var.Ty is not None:
|
||||
# 检查是否为 Ptr(Struct(...))(结构体值变量)
|
||||
# 或 Ptr(Ptr(Struct(...)))(指针变量,需 load)
|
||||
@@ -5488,9 +5507,6 @@ def translate_call(pool: memhub.MemBuddy | t.CPtr,
|
||||
# 跨模块函数调用:found_func 为 None 时,检查是否是模块限定调用
|
||||
# 如 string.strchr(...) → @{sha1_of_string}.strchr
|
||||
if cl.func is not None and cl.func.kind() == ast.ASTKind.Attribute:
|
||||
# [DBG-MC] 临时诊断(验证后移除)
|
||||
if string.strcmp(func_name, "get_str") == 0:
|
||||
stdio.printf("[DBG-MC] get_str reached cross-module path\n")
|
||||
xmod_at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(cl.func)
|
||||
if xmod_at.value is not None and xmod_at.value.kind() == ast.ASTKind.Name:
|
||||
xmod_nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(xmod_at.value)
|
||||
|
||||
@@ -722,9 +722,6 @@ def _parse_type_string(pool: memhub.MemBuddy | t.CPtr,
|
||||
name_buf[seg_len] = '\0'
|
||||
name_node: ast.AST | t.CPtr = ast.Name(pool, name_buf, ctx)
|
||||
stdlib.free(name_buf)
|
||||
# [DBG-MC] 临时诊断(验证后移除)
|
||||
if string.strstr(type_str, "ParsedArgs") is not None:
|
||||
stdio.printf("[DBG-MC] pts Name id_ptr=%p kind=%d\n", name_node.id, name_node.kind())
|
||||
return name_node
|
||||
|
||||
|
||||
@@ -921,6 +918,13 @@ def map_t_type(pool: memhub.MemBuddy | t.CPtr,
|
||||
return llvmlite.Ptr(pool, llvmlite.Int8(pool))
|
||||
elif string.strcmp(type_name, "CVoid") == 0:
|
||||
return llvmlite.Void(pool)
|
||||
# CNeedPtr/CAutoPtr: 参数自动取地址标记,LLVM 层均为通用指针 i8*。
|
||||
# (TPC 中二者继承 CPtr;TPV 未实现调用点自动取地址,非指针实参应在调用点报错,
|
||||
# 而非静默降级为 i32 导致指针截断。)
|
||||
elif string.strcmp(type_name, "CNeedPtr") == 0:
|
||||
return llvmlite.Ptr(pool, llvmlite.Int8(pool))
|
||||
elif string.strcmp(type_name, "CAutoPtr") == 0:
|
||||
return llvmlite.Ptr(pool, llvmlite.Int8(pool))
|
||||
# 无符号修饰
|
||||
elif string.strcmp(type_name, "CUnsigned") == 0:
|
||||
return llvmlite.Int32(pool)
|
||||
@@ -1570,7 +1574,12 @@ def resolve_annotation_type(pool: memhub.MemBuddy | t.CPtr,
|
||||
if at.value is not None and at.value.kind() == ast.ASTKind.Name:
|
||||
val_name: ast.Name | t.CPtr = (ast.Name | t.CPtr)(at.value)
|
||||
if val_name.id is not None:
|
||||
# 仅当模块已导入时才解析
|
||||
# t/c 是内建库(SHA1 豁免),显式写 t.XXX 即确指内建库,
|
||||
# 不依赖 imported_modules(t 可能不在其中,如 vpi 注入上下文)
|
||||
is_builtin_attr: int = 0
|
||||
if string.strcmp(val_name.id, "t") == 0 or string.strcmp(val_name.id, "c") == 0:
|
||||
is_builtin_attr = 1
|
||||
if is_builtin_attr == 0:
|
||||
mod_imp: int = HandlesImports.is_module_imported(imported_modules, val_name.id)
|
||||
if mod_imp == 0:
|
||||
return None
|
||||
@@ -1603,13 +1612,6 @@ def resolve_annotation_type(pool: memhub.MemBuddy | t.CPtr,
|
||||
# 检测 t.CPtr 标记(指针包装标记,支持 t.CPtr 与 from t import CPtr 裸名)
|
||||
left_is_cptr: int = _is_cptr_marker(bop.left, imported_modules)
|
||||
right_is_cptr: int = _is_cptr_marker(bop.right, imported_modules)
|
||||
# [DBG-MC] 临时诊断(验证后移除)
|
||||
if bop.left is not None and bop.left.kind() == ast.ASTKind.Name:
|
||||
lnm_dbg: ast.Name | t.CPtr = (ast.Name | t.CPtr)(bop.left)
|
||||
if lnm_dbg.id is not None and string.strcmp(lnm_dbg.id, "ParsedArgs") == 0:
|
||||
stdio.printf("[DBG-MC] BinOp ParsedArgs left_cptr=%d right_cptr=%d\n",
|
||||
left_is_cptr, right_is_cptr)
|
||||
|
||||
if left_is_cptr != 0 or right_is_cptr != 0:
|
||||
# 有 CPtr 标记:解析非 CPtr 一边的实际类型,包装为 Ptr
|
||||
# left 是 CPtr → other 是 right;right 是 CPtr → other 是 left
|
||||
@@ -1637,15 +1639,6 @@ def resolve_annotation_type(pool: memhub.MemBuddy | t.CPtr,
|
||||
return llvmlite.Ptr(pool, llvmlite.Int8(pool))
|
||||
other_ty: llvmlite.LLVMType | t.CPtr = resolve_annotation_type(
|
||||
pool, other_node, imported_modules, from_imports, trans)
|
||||
# [DBG-MC] 临时诊断(验证后移除)
|
||||
if other_node is not None:
|
||||
if other_node.kind() == ast.ASTKind.Name:
|
||||
onm3: ast.Name | t.CPtr = (ast.Name | t.CPtr)(other_node)
|
||||
if onm3.id is not None and string.strcmp(onm3.id, "ParsedArgs") == 0:
|
||||
stdio.printf("[DBG-MC] other_node Name(%s) ty=%p visible=%d\n",
|
||||
onm3.id, other_ty, HandlesStruct.is_struct_visible("ParsedArgs"))
|
||||
else:
|
||||
stdio.printf("[DBG-MC] other_node kind=%d ty=%p\n", other_node.kind(), other_ty)
|
||||
# 仅裸名(Name)场景验证解析结果必须是已注册 struct:
|
||||
# 损坏节点可能解析出基础类型垃圾(如 Int8 → Ptr(i8))。
|
||||
# Attribute 场景(Module.Class / t.XXX)resolve 结果直接可用
|
||||
@@ -1675,12 +1668,6 @@ def resolve_annotation_type(pool: memhub.MemBuddy | t.CPtr,
|
||||
other_cls_nm = other_nm.id
|
||||
if other_cls_nm is not None:
|
||||
other_cls_ty: llvmlite.LLVMType | t.CPtr = HandlesStruct.get_struct_type(other_cls_nm)
|
||||
# [DBG-MC] 临时诊断(验证后移除)
|
||||
if string.strcmp(other_cls_nm, "ParsedArgs") == 0:
|
||||
stdio.printf("[DBG-MC] fallback ParsedArgs get_struct=%p visible=%d count=%d\n",
|
||||
other_cls_ty,
|
||||
HandlesStruct.is_struct_visible("ParsedArgs"),
|
||||
HandlesStruct.get_struct_count())
|
||||
if other_cls_ty is not None:
|
||||
return llvmlite.Ptr(pool, other_cls_ty)
|
||||
# CPtr 单独使用或其他无效类型 → i8*
|
||||
|
||||
@@ -968,6 +968,81 @@ def RunPhase1(mb: memhub.MemBuddy | t.CPtr, includes_dir: str, temp_dir: str,
|
||||
# 1b 阶段新注册的 struct/enum 条目改 stdlib 分配(跨文件永久存活,不被 reset 回收)
|
||||
HandlesStruct.set_stdlib_alloc(1)
|
||||
|
||||
# ============================================================
|
||||
# Phase 1b-pre: 预生成所有待翻译文件的 .vpi stub
|
||||
#
|
||||
# 依赖模块的 .vpi 必须在翻译前可用:1b 主循环按扫描顺序翻译(非拓扑),
|
||||
# 若 argparse 先于 hashtable 翻译,hashtable.vpi 尚未生成,
|
||||
# LoadDepVpiIntoModule 读不到 → declare 未注入 → 跨模块调用
|
||||
# 返回类型推断错误(如 HashTable.__getitem__ 被推断为 Ptr(HashTable)
|
||||
# 而 define 返回 i8*)→ 运行时返回值截断崩溃。
|
||||
# ============================================================
|
||||
dir_len_pv: t.CSizeT = string.strlen(temp_dir)
|
||||
for i_pv in range(result.Count):
|
||||
entry_addr_pv: t.CUInt64T = t.CUInt64T(result.Entries) + i_pv * entry_size
|
||||
entry_pv: IncludesScanner.FileEntry | t.CPtr = (IncludesScanner.FileEntry | t.CPtr)(t.CVoid(entry_addr_pv, t.CPtr))
|
||||
if entry_pv is None or entry_pv.Sha1 is None:
|
||||
continue
|
||||
sha1_pv: str = entry_pv.Sha1
|
||||
in_set_pv: int = 0
|
||||
if use_reachable != 0:
|
||||
in_set_pv = StubMerger._is_in_sha1_set(sha1_pv, reachable_set, reachable_count)
|
||||
else:
|
||||
in_set_pv = StubMerger._is_in_sha1_set(sha1_pv, sha1_set, set_count)
|
||||
if in_set_pv == 0:
|
||||
continue
|
||||
# vpi 已存在则跳过
|
||||
vpi_path_pv: str = StubMerger._sliced_path(temp_dir, dir_len_pv, sha1_pv, "vpi")
|
||||
if vpi_path_pv is None:
|
||||
continue
|
||||
vf_pv: fileio.File | t.CPtr = fileio.File(vpi_path_pv, fileio.MODE.R)
|
||||
if not vf_pv.closed:
|
||||
vf_pv.close()
|
||||
stdlib.free(vpi_path_pv)
|
||||
continue
|
||||
stdlib.free(vpi_path_pv)
|
||||
# 读取文件、解析 AST、生成 vpi
|
||||
file_path_pv: str = entry_pv.Path
|
||||
f_pv: fileio.File | t.CPtr = fileio.File(file_path_pv, fileio.MODE.R)
|
||||
if f_pv.closed:
|
||||
continue
|
||||
src_buf_pv: bytes = stdlib.malloc(SRC_BUF_SIZE)
|
||||
if src_buf_pv is None:
|
||||
f_pv.close()
|
||||
continue
|
||||
bytes_read_pv: LONG = f_pv.read_all(src_buf_pv, SRC_BUF_SIZE)
|
||||
f_pv.close()
|
||||
if bytes_read_pv <= 0:
|
||||
stdlib.free(src_buf_pv)
|
||||
continue
|
||||
if bytes_read_pv < SRC_BUF_SIZE:
|
||||
src_buf_pv[bytes_read_pv] = 0
|
||||
else:
|
||||
src_buf_pv[SRC_BUF_SIZE - 1] = 0
|
||||
lx_pv: ast.Lexer | t.CPtr = ast.new_lexer(mb)
|
||||
if lx_pv is None:
|
||||
stdlib.free(src_buf_pv)
|
||||
continue
|
||||
ast._lexer_init(lx_pv, src_buf_pv, mb)
|
||||
tokens_pv: ast.Token | t.CPtr = ast.tokenize(lx_pv)
|
||||
tree_pv: ast.AST | t.CPtr = ast.parse_tokens(mb, tokens_pv)
|
||||
if tree_pv is None:
|
||||
stdlib.free(src_buf_pv)
|
||||
continue
|
||||
pyi_buf_pv: bytes = stdlib.malloc(PYI_BUF_SIZE)
|
||||
if pyi_buf_pv is not None:
|
||||
pyi_pos_pv: t.CSizeT = StubConverter._GeneratePyiFromAst(mb, tree_pv, entry_pv.RelPath, pyi_buf_pv, PYI_BUF_SIZE)
|
||||
if pyi_pos_pv > 0:
|
||||
pyi_path_pv: str = StubMerger._sliced_path(temp_dir, dir_len_pv, sha1_pv, "vpi")
|
||||
if pyi_path_pv is not None:
|
||||
pf_pv: fileio.File | t.CPtr = fileio.File(pyi_path_pv, fileio.MODE.W)
|
||||
if not pf_pv.closed:
|
||||
pf_pv.write(pyi_buf_pv, pyi_pos_pv)
|
||||
pf_pv.close()
|
||||
stdlib.free(pyi_path_pv)
|
||||
stdlib.free(pyi_buf_pv)
|
||||
stdlib.free(src_buf_pv)
|
||||
|
||||
# 遍历每个文件
|
||||
translated: int = 0
|
||||
skipped: int = 0
|
||||
|
||||
Reference in new issue
Block a user