Some simple information syncing
This commit is contained in:
@@ -238,7 +238,10 @@ def coerce_to_type(builder: llvmlite.IRBuilder | t.CPtr,
|
||||
if val_bits != 0 and is_ptr_type(target_ty) != 0:
|
||||
return llvmlite.build_inttoptr(builder, val, target_ty)
|
||||
# 指针 → 整数: ptrtoint(当目标明确是整数而非指针时)
|
||||
if is_ptr_type(val.Ty) != 0 and target_bits != 0 and is_ptr_type(target_ty) == 0:
|
||||
# 注意: target_bits == 8 时跳过 ptrtoint,走后面的 build_load 解引用首字符
|
||||
# 修复: buf[idx] = '\0' 中 '\0' 是 CONST_STR → i8* 指针,
|
||||
# ptrtoint 会截断地址低 8 位(非 0),应 load 解引用取首字符 0
|
||||
if is_ptr_type(val.Ty) != 0 and target_bits != 0 and target_bits != 8 and is_ptr_type(target_ty) == 0:
|
||||
return llvmlite.build_ptrtoint(builder, val, target_ty)
|
||||
if val_bits != 0 and target_bits != 0:
|
||||
if val_bits == target_bits:
|
||||
@@ -284,8 +287,6 @@ def create_global_string(builder: llvmlite.IRBuilder | t.CPtr,
|
||||
"""创建全局字符串常量并返回 i8* bitcast"""
|
||||
escaped: t.CChar | t.CPtr = escape_llvm_string(pool, str_val)
|
||||
if escaped is None:
|
||||
stdio.printf("[CGS] escape_llvm_string None\n")
|
||||
stdio.fflush(0)
|
||||
return None
|
||||
|
||||
slen: t.CSizeT = string.strlen(str_val)
|
||||
@@ -301,8 +302,6 @@ def create_global_string(builder: llvmlite.IRBuilder | t.CPtr,
|
||||
# 字符串名加 SHA1 前缀,和函数导出规则一致,避免跨模块重名
|
||||
gv_name: t.CChar | t.CPtr = pool.alloc(48)
|
||||
if gv_name is None:
|
||||
stdio.printf("[CGS] gv_name alloc None\n")
|
||||
stdio.fflush(0)
|
||||
return None
|
||||
if trans.ModuleSha1 is not None:
|
||||
viperlib.snprintf(gv_name, 48, ".str.%s.%d", trans.ModuleSha1, str_idx)
|
||||
@@ -311,8 +310,6 @@ def create_global_string(builder: llvmlite.IRBuilder | t.CPtr,
|
||||
|
||||
gv: llvmlite.GlobalVariable | t.CPtr = llvmlite.new_global_variable(pool, gv_name, arr_ty)
|
||||
if gv is None:
|
||||
stdio.printf("[CGS] new_global_variable None name=%s\n", gv_name)
|
||||
stdio.fflush(0)
|
||||
return None
|
||||
llvmlite.module_add_global(mod, gv)
|
||||
|
||||
@@ -324,8 +321,6 @@ def create_global_string(builder: llvmlite.IRBuilder | t.CPtr,
|
||||
arr_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, arr_ty)
|
||||
gv_ref_name: t.CChar | t.CPtr = pool.alloc(64)
|
||||
if gv_ref_name is None:
|
||||
stdio.printf("[CGS] gv_ref_name alloc None\n")
|
||||
stdio.fflush(0)
|
||||
return None
|
||||
viperlib.snprintf(gv_ref_name, 64, "@%s", gv.Name)
|
||||
gv_ref: llvmlite.Value | t.CPtr = llvmlite.SSAValue(pool, arr_ptr_ty, gv_ref_name)
|
||||
@@ -333,9 +328,6 @@ def create_global_string(builder: llvmlite.IRBuilder | t.CPtr,
|
||||
i8_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty)
|
||||
|
||||
bc: llvmlite.Value | t.CPtr = llvmlite.build_bitcast(builder, gv_ref, i8_ptr_ty)
|
||||
if bc is None:
|
||||
stdio.printf("[CGS] build_bitcast None\n")
|
||||
stdio.fflush(0)
|
||||
return bc
|
||||
|
||||
|
||||
@@ -350,12 +342,8 @@ def translate_constant(builder: llvmlite.IRBuilder | t.CPtr,
|
||||
"""翻译常量(int/str/bool)"""
|
||||
cn: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(node)
|
||||
if cn is None:
|
||||
stdio.printf("[TC] cn is None\n")
|
||||
stdio.fflush(0)
|
||||
return None
|
||||
ck: int = cn.const_kind
|
||||
stdio.printf("[TC] const_kind=%d\n", ck)
|
||||
stdio.fflush(0)
|
||||
if cn.const_kind == ast.CONST_INT:
|
||||
# 超出 i32 范围则用 i64(避免常量创建时被截断)
|
||||
iv: t.CInt64T = cn.int_val
|
||||
@@ -366,18 +354,15 @@ def translate_constant(builder: llvmlite.IRBuilder | t.CPtr,
|
||||
# 浮点常量默认创建为 double(64 位),赋值时由 coerce_to_type 自动 fptrunc
|
||||
double_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Double(pool)
|
||||
return llvmlite.ConstFloat(pool, double_ty, cn.float_val)
|
||||
elif cn.const_kind == ast.CONST_CHAR:
|
||||
# 单引号单字符 → i32 值(字符 ASCII 码),coerce_to_type 会 trunc 为 i8
|
||||
cv: t.CInt64T = cn.int_val
|
||||
return llvmlite.const_int32(pool, cv)
|
||||
elif cn.const_kind == ast.CONST_STR:
|
||||
sv: str = cn.str_val
|
||||
if sv is None:
|
||||
stdio.printf("[TC] CONST_STR but str_val is None\n")
|
||||
stdio.fflush(0)
|
||||
return None
|
||||
stdio.printf("[TC] CONST_STR sv[0]=%d\n", sv[0])
|
||||
stdio.fflush(0)
|
||||
r: llvmlite.Value | t.CPtr = create_global_string(builder, pool, mod, sv, trans)
|
||||
if r is None:
|
||||
stdio.printf("[TC] create_global_string returned None\n")
|
||||
stdio.fflush(0)
|
||||
return r
|
||||
elif cn.const_kind == ast.CONST_BOOL:
|
||||
if cn.int_val != 0:
|
||||
@@ -385,32 +370,14 @@ def translate_constant(builder: llvmlite.IRBuilder | t.CPtr,
|
||||
return llvmlite.const_int32(pool, 0)
|
||||
elif cn.const_kind == ast.CONST_NONE:
|
||||
# None → i8* null(空指针常量),用于 `p is None` / `p is not None` 比较
|
||||
stdio.printf("[TC] NONE step1 Int8\n")
|
||||
stdio.fflush(0)
|
||||
i8_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool)
|
||||
if i8_ty is None:
|
||||
stdio.printf("[TC] NONE Int8 alloc None\n")
|
||||
stdio.fflush(0)
|
||||
return None
|
||||
stdio.printf("[TC] NONE step2 Ptr\n")
|
||||
stdio.fflush(0)
|
||||
i8_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty)
|
||||
if i8_ptr_ty is None:
|
||||
stdio.printf("[TC] NONE Ptr alloc None\n")
|
||||
stdio.fflush(0)
|
||||
return None
|
||||
stdio.printf("[TC] NONE step3 ConstNull\n")
|
||||
stdio.fflush(0)
|
||||
rv_none: llvmlite.Value | t.CPtr = llvmlite.ConstNull(pool, i8_ptr_ty, "null")
|
||||
if rv_none is None:
|
||||
stdio.printf("[TC] NONE ConstNull None\n")
|
||||
stdio.fflush(0)
|
||||
else:
|
||||
stdio.printf("[TC] NONE ok\n")
|
||||
stdio.fflush(0)
|
||||
return rv_none
|
||||
stdio.printf("[TC] unknown const_kind=%d\n", ck)
|
||||
stdio.fflush(0)
|
||||
return None
|
||||
|
||||
|
||||
@@ -632,12 +599,6 @@ def translate_value(builder: llvmlite.IRBuilder | t.CPtr,
|
||||
k: int = node.kind()
|
||||
if k == ast.ASTKind.Constant:
|
||||
rv: llvmlite.Value | t.CPtr = translate_constant(builder, pool, mod, node, trans)
|
||||
if rv is None:
|
||||
stdio.printf("[TV] Constant returned None\n")
|
||||
stdio.fflush(0)
|
||||
else:
|
||||
stdio.printf("[TV] Constant ok\n")
|
||||
stdio.fflush(0)
|
||||
return rv
|
||||
elif k == ast.ASTKind.Name:
|
||||
return translate_name_value(builder, pool, node, trans)
|
||||
@@ -686,24 +647,25 @@ def translate_ifexp(builder: llvmlite.IRBuilder | t.CPtr,
|
||||
|
||||
func: llvmlite.Function | t.CPtr = trans._cur_func
|
||||
if func is None:
|
||||
stdio.printf("[IFEXP] func=None\n")
|
||||
stdio.fflush(0)
|
||||
return None
|
||||
|
||||
# 1. 求值条件
|
||||
cond_val: llvmlite.Value | t.CPtr = translate_value(
|
||||
builder, pool, mod, ie.test, None, 0, trans)
|
||||
if cond_val is None:
|
||||
stdio.printf("[IFEXP] cond_val=None\n")
|
||||
stdio.fflush(0)
|
||||
return None
|
||||
# 转换为 i1
|
||||
cond_bits: int = get_llvm_type_bits(cond_val.Ty)
|
||||
if cond_bits == 1:
|
||||
cond_i1: llvmlite.Value | t.CPtr = cond_val
|
||||
else:
|
||||
zero: llvmlite.Value | t.CPtr = llvmlite.const_int32(pool, 0)
|
||||
cond_i1 = llvmlite.build_icmp(builder, llvmlite.ICMP_NE, cond_val, zero)
|
||||
if is_ptr_type(cond_val.Ty) != 0:
|
||||
# 指针类型:与 null 比较
|
||||
null_cond: llvmlite.Value | t.CPtr = llvmlite.ConstNull(pool, cond_val.Ty, "null")
|
||||
cond_i1 = llvmlite.build_icmp(builder, llvmlite.ICMP_NE, cond_val, null_cond)
|
||||
else:
|
||||
zero: llvmlite.Value | t.CPtr = llvmlite.const_int32(pool, 0)
|
||||
cond_i1 = llvmlite.build_icmp(builder, llvmlite.ICMP_NE, cond_val, zero)
|
||||
|
||||
# 2. 创建三个基本块
|
||||
cnt: int = trans._label_counter
|
||||
@@ -818,14 +780,10 @@ def translate_compare(builder: llvmlite.IRBuilder | t.CPtr,
|
||||
|
||||
comparators: list[ast.AST | t.CPtr] | t.CPtr = cmp.comparators
|
||||
if comparators is None or comparators.__len__() == 0:
|
||||
stdio.printf("[CMP] comparators empty\n")
|
||||
stdio.fflush(0)
|
||||
return None
|
||||
rhs: llvmlite.Value | t.CPtr = translate_value(
|
||||
builder, pool, mod, comparators.get(0), None, 0, trans)
|
||||
if rhs is None:
|
||||
stdio.printf("[CMP] rhs=None\n")
|
||||
stdio.fflush(0)
|
||||
return None
|
||||
|
||||
# === 比较运算符重载路径 1: lhs 是 Name 且对应结构体变量 ===
|
||||
@@ -846,8 +804,6 @@ def translate_compare(builder: llvmlite.IRBuilder | t.CPtr,
|
||||
lhs: llvmlite.Value | t.CPtr = translate_value(
|
||||
builder, pool, mod, cmp.left, None, 0, trans)
|
||||
if lhs is None:
|
||||
stdio.printf("[CMP] lhs=None\n")
|
||||
stdio.fflush(0)
|
||||
return None
|
||||
|
||||
# === 比较运算符重载路径 2: lhs 是 Ptr(Struct) ===
|
||||
@@ -933,7 +889,11 @@ def translate_unaryop(builder: llvmlite.IRBuilder | t.CPtr,
|
||||
# +x = x
|
||||
return operand
|
||||
elif uo.op == ast.OpKind.Not:
|
||||
# not x = (x == 0),返回 i1
|
||||
# not x = (x == 0/null),返回 i1
|
||||
if is_ptr_type(operand.Ty) != 0:
|
||||
# 指针类型:与 null 比较
|
||||
null_op: llvmlite.Value | t.CPtr = llvmlite.ConstNull(pool, operand.Ty, "null")
|
||||
return llvmlite.build_icmp(builder, llvmlite.ICMP_EQ, operand, null_op)
|
||||
operand_bits_not: int = get_llvm_type_bits(operand.Ty)
|
||||
zero = llvmlite.const_int32(pool, 0)
|
||||
if operand_bits_not == 64:
|
||||
@@ -1009,12 +969,17 @@ def translate_boolop(builder: llvmlite.IRBuilder | t.CPtr,
|
||||
if val is None:
|
||||
return None
|
||||
|
||||
# 转为 i1(已经是 i1 的直接用,否则与 0 比较)
|
||||
# 转为 i1(已经是 i1 的直接用,否则与 0/null 比较)
|
||||
val_bits: int = get_llvm_type_bits(val.Ty)
|
||||
val_i1: llvmlite.Value | t.CPtr = val
|
||||
if val_bits != 1:
|
||||
zero: llvmlite.Value | t.CPtr = llvmlite.const_int32(pool, 0)
|
||||
val_i1 = llvmlite.build_icmp(builder, llvmlite.ICMP_NE, val, zero)
|
||||
if is_ptr_type(val.Ty) != 0:
|
||||
# 指针类型:与 null 比较(避免 i8* 与 i32 类型不匹配)
|
||||
null_val: llvmlite.Value | t.CPtr = llvmlite.ConstNull(pool, val.Ty, "null")
|
||||
val_i1 = llvmlite.build_icmp(builder, llvmlite.ICMP_NE, val, null_val)
|
||||
else:
|
||||
zero: llvmlite.Value | t.CPtr = llvmlite.const_int32(pool, 0)
|
||||
val_i1 = llvmlite.build_icmp(builder, llvmlite.ICMP_NE, val, zero)
|
||||
|
||||
# 创建 next BB(求值下一个值)
|
||||
cnt = builder.Counter
|
||||
@@ -1051,8 +1016,13 @@ def translate_boolop(builder: llvmlite.IRBuilder | t.CPtr,
|
||||
last_bits: int = get_llvm_type_bits(last_val.Ty)
|
||||
last_i1: llvmlite.Value | t.CPtr = last_val
|
||||
if last_bits != 1:
|
||||
zero = llvmlite.const_int32(pool, 0)
|
||||
last_i1 = llvmlite.build_icmp(builder, llvmlite.ICMP_NE, last_val, zero)
|
||||
if is_ptr_type(last_val.Ty) != 0:
|
||||
# 指针类型:与 null 比较(避免 i8* 与 i32 类型不匹配)
|
||||
null_val2: llvmlite.Value | t.CPtr = llvmlite.ConstNull(pool, last_val.Ty, "null")
|
||||
last_i1 = llvmlite.build_icmp(builder, llvmlite.ICMP_NE, last_val, null_val2)
|
||||
else:
|
||||
zero = llvmlite.const_int32(pool, 0)
|
||||
last_i1 = llvmlite.build_icmp(builder, llvmlite.ICMP_NE, last_val, zero)
|
||||
|
||||
llvmlite.build_br(builder, merge_bb)
|
||||
|
||||
@@ -1147,33 +1117,27 @@ def _lookup_cross_module_cdefine(pool: memhub.MemBuddy | t.CPtr,
|
||||
name: str,
|
||||
from_imports: str) -> int:
|
||||
"""跨模块查找 CDefine 常量,返回值或 -1(未找到)"""
|
||||
# [XMOD-CD] 诊断:记录跨模块 CDefine 查找入口
|
||||
_xmod_log_buf: str = pool.alloc(512)
|
||||
if _xmod_log_buf is not None:
|
||||
viperlib.snprintf(_xmod_log_buf, 512, "[XMOD-CD] enter name=%s from_imports=%s\n", name, from_imports)
|
||||
_xmod_lf: fileio.File | t.CPtr = fileio.File(
|
||||
"d:/Users/TermiNexus/Desktop/TransPyC/_xmod_cdefine.log", fileio.MODE.A)
|
||||
if not _xmod_lf.closed:
|
||||
_xmod_lf.write_str(_xmod_log_buf)
|
||||
_xmod_lf.close()
|
||||
|
||||
if name is None or from_imports is None:
|
||||
stdio.printf("[XMCD] FAIL name=%s reason=from_imports_is_none\n", name)
|
||||
return -1
|
||||
|
||||
# 1. 从 from_imports 查找名称对应的模块名
|
||||
# allow_star_fallback=1: CDefine 常量(如 INVALID_HANDLE_VALUE)通过
|
||||
# from w32.win32base import * 导入,不会作为精确条目出现在 from_imports 中,
|
||||
# 而是作为 *:w32.win32base 条目。必须启用 star import 回退才能找到源模块。
|
||||
mod_name_raw: str = HandlesImports.lookup_from_import(from_imports, name, 1)
|
||||
# 先尝试精确匹配(allow_star_fallback=0),避免 CDefine 常量被 star import 误导
|
||||
mod_name_raw: str = HandlesImports.lookup_from_import(from_imports, name, 0)
|
||||
if mod_name_raw is None:
|
||||
if _xmod_log_buf is not None:
|
||||
viperlib.snprintf(_xmod_log_buf, 512, "[XMOD-CD] FAIL step1 mod=None name=%s\n", name)
|
||||
_xmod_lf2: fileio.File | t.CPtr = fileio.File(
|
||||
"d:/Users/TermiNexus/Desktop/TransPyC/_xmod_cdefine.log", fileio.MODE.A)
|
||||
if not _xmod_lf2.closed:
|
||||
_xmod_lf2.write_str(_xmod_log_buf)
|
||||
_xmod_lf2.close()
|
||||
return -1
|
||||
# 精确匹配失败:尝试 star import 回退
|
||||
# CDefine 常量(如 INVALID_HANDLE_VALUE)通过 from w32.win32base import * 导入,
|
||||
# 不会作为精确条目出现在 from_imports 中,而是作为 *:w32.win32base 条目。
|
||||
mod_name_raw = HandlesImports.lookup_from_import(from_imports, name, 1)
|
||||
if mod_name_raw is None:
|
||||
stdio.printf("[XMCD] FAIL name=%s reason=lookup_from_import_returned_none\n", name)
|
||||
return -1
|
||||
stdio.printf("[XMCD] star_fallback name=%s mod=%s\n", name, mod_name_raw)
|
||||
# 打印 from_imports 用于诊断精确匹配失败原因
|
||||
fi_len: t.CSizeT = string.strlen(from_imports)
|
||||
stdio.printf("[XMCD] from_imports (len=%d): %s\n", fi_len, from_imports)
|
||||
else:
|
||||
stdio.printf("[XMCD] exact_match name=%s mod=%s\n", name, mod_name_raw)
|
||||
|
||||
# 2. 复制模块名到新缓冲区(lookup_from_import 返回的是内部指针)
|
||||
# 截断于空格、null、或 ':'(别名格式的分隔符)
|
||||
@@ -1197,29 +1161,9 @@ def _lookup_cross_module_cdefine(pool: memhub.MemBuddy | t.CPtr,
|
||||
if sha1 is None:
|
||||
sha1 = HandlesExprCall._lookup_module_sha1_suffix(base_mod)
|
||||
if sha1 is None:
|
||||
if _xmod_log_buf is not None:
|
||||
viperlib.snprintf(_xmod_log_buf, 512, "[XMOD-CD] FAIL step4 sha1=None base_mod=%s\n", base_mod)
|
||||
_xmod_lf3: fileio.File | t.CPtr = fileio.File(
|
||||
"d:/Users/TermiNexus/Desktop/TransPyC/_xmod_cdefine.log", fileio.MODE.A)
|
||||
if not _xmod_lf3.closed:
|
||||
_xmod_lf3.write_str(_xmod_log_buf)
|
||||
_xmod_lf3.close()
|
||||
stdio.printf("[XMCD] FAIL name=%s base_mod=%s reason=sha1_not_found\n", name, base_mod)
|
||||
return -1
|
||||
|
||||
# [XMOD-CD] 诊断:记录 SHA1 查找成功
|
||||
if _xmod_log_buf is not None:
|
||||
viperlib.snprintf(_xmod_log_buf, 512, "[XMOD-CD] ok step4 base_mod=%s sha1=%s\n", base_mod, sha1)
|
||||
_xmod_lf4: fileio.File | t.CPtr = fileio.File(
|
||||
"d:/Users/TermiNexus/Desktop/TransPyC/_xmod_cdefine.log", fileio.MODE.A)
|
||||
if not _xmod_lf4.closed:
|
||||
_xmod_lf4.write_str(_xmod_log_buf)
|
||||
_xmod_lf4.close()
|
||||
|
||||
# 4.5 优先查全局跨模块 CDefine 表(编译期注册,无需文件 I/O)
|
||||
gcdef_val: int = HandlesType.lookup_global_cdefine(sha1, name)
|
||||
if HandlesType.is_cdefine_found() != 0:
|
||||
return gcdef_val
|
||||
|
||||
# 5. 获取 temp_dir
|
||||
temp_dir: str = HandlesType.get_temp_dir()
|
||||
if temp_dir is None:
|
||||
@@ -1271,44 +1215,14 @@ def _lookup_cross_module_cdefine(pool: memhub.MemBuddy | t.CPtr,
|
||||
VLogger.error(err_buf, "XMOD-CD")
|
||||
stdlib.free(pyi_buf)
|
||||
return -1
|
||||
# [XMOD-CD] 诊断:记录 src_path
|
||||
_xmod_dbg_sp2: str = pool.alloc(512)
|
||||
if _xmod_dbg_sp2 is not None:
|
||||
viperlib.snprintf(_xmod_dbg_sp2, 512,
|
||||
"[XMOD-CD] py-fallback src_path=%s sha1=%s\n", src_path, sha1)
|
||||
_xmod_lf_sp2: fileio.File | t.CPtr = fileio.File(
|
||||
"d:/Users/TermiNexus/Desktop/TransPyC/_xmod_cdefine.log", fileio.MODE.A)
|
||||
if not _xmod_lf_sp2.closed:
|
||||
_xmod_lf_sp2.write_str(_xmod_dbg_sp2)
|
||||
_xmod_lf_sp2.close()
|
||||
pf = fileio.File(src_path, fileio.MODE.R)
|
||||
stdlib.free(src_path)
|
||||
if pf.closed:
|
||||
# [XMOD-CD] 诊断:文件打开失败
|
||||
_xmod_dbg_fc: str = pool.alloc(512)
|
||||
if _xmod_dbg_fc is not None:
|
||||
viperlib.snprintf(_xmod_dbg_fc, 512,
|
||||
"[XMOD-CD] FAIL file-closed sha1=%s\n", sha1)
|
||||
_xmod_lf_fc: fileio.File | t.CPtr = fileio.File(
|
||||
"d:/Users/TermiNexus/Desktop/TransPyC/_xmod_cdefine.log", fileio.MODE.A)
|
||||
if not _xmod_lf_fc.closed:
|
||||
_xmod_lf_fc.write_str(_xmod_dbg_fc)
|
||||
_xmod_lf_fc.close()
|
||||
stdlib.free(pyi_buf)
|
||||
return -1
|
||||
bytes_read = pf.read_all(pyi_buf, PYI_READ_BUF_SIZE)
|
||||
pf.close()
|
||||
if bytes_read <= 0:
|
||||
# [XMOD-CD] 诊断:文件读取失败
|
||||
_xmod_dbg_br: str = pool.alloc(512)
|
||||
if _xmod_dbg_br is not None:
|
||||
viperlib.snprintf(_xmod_dbg_br, 512,
|
||||
"[XMOD-CD] FAIL bytes_read=%d sha1=%s\n", bytes_read, sha1)
|
||||
_xmod_lf_br: fileio.File | t.CPtr = fileio.File(
|
||||
"d:/Users/TermiNexus/Desktop/TransPyC/_xmod_cdefine.log", fileio.MODE.A)
|
||||
if not _xmod_lf_br.closed:
|
||||
_xmod_lf_br.write_str(_xmod_dbg_br)
|
||||
_xmod_lf_br.close()
|
||||
stdlib.free(pyi_buf)
|
||||
return -1
|
||||
if bytes_read < PYI_READ_BUF_SIZE:
|
||||
@@ -1320,25 +1234,6 @@ def _lookup_cross_module_cdefine(pool: memhub.MemBuddy | t.CPtr,
|
||||
# 格式: NAME: t.CDefine = value
|
||||
name_len: t.CSizeT = string.strlen(name)
|
||||
total_len: t.CSizeT = string.strlen(pyi_buf)
|
||||
# [XMOD-CD] 诊断:记录文件读取结果和 total_len
|
||||
_xmod_dbg1: str = pool.alloc(512)
|
||||
if _xmod_dbg1 is not None:
|
||||
_dbg_first80: str = pool.alloc(81)
|
||||
if _dbg_first80 is not None:
|
||||
_dbg_n: int = 0
|
||||
while _dbg_n < 80 and _dbg_n < total_len:
|
||||
_dbg_first80[_dbg_n] = pyi_buf[_dbg_n]
|
||||
_dbg_n += 1
|
||||
_dbg_first80[_dbg_n] = '\0'
|
||||
else:
|
||||
_dbg_first80 = "<alloc-fail>"
|
||||
viperlib.snprintf(_xmod_dbg1, 512, "[XMOD-CD] file-read name=%s bytes_read=%d total_len=%d first80=%.80s\n",
|
||||
name, bytes_read, total_len, _dbg_first80)
|
||||
_xmod_lf_d1: fileio.File | t.CPtr = fileio.File(
|
||||
"d:/Users/TermiNexus/Desktop/TransPyC/_xmod_cdefine.log", fileio.MODE.A)
|
||||
if not _xmod_lf_d1.closed:
|
||||
_xmod_lf_d1.write_str(_xmod_dbg1)
|
||||
_xmod_lf_d1.close()
|
||||
pos: t.CSizeT = 0
|
||||
result_val: int = 0
|
||||
result_found: int = 0
|
||||
@@ -1393,7 +1288,29 @@ def _lookup_cross_module_cdefine(pool: memhub.MemBuddy | t.CPtr,
|
||||
while eq_pos < line_start + line_len and pyi_buf[eq_pos] == ' ':
|
||||
eq_pos += 1
|
||||
|
||||
# 解析整数值(支持十六进制 0x 前缀)
|
||||
# 检查是否是 t.CUnsignedLong(...) / t.CLong(...) / t.CInt(...) 等类型构造函数
|
||||
# 格式: t.CUnsignedLong(-11) / t.CUnsignedLong(0xFFFFFFFF)
|
||||
# 如果是,跳过 "t.CXxx(" 前缀,解析括号内的值,忽略结尾 ')'
|
||||
is_type_ctor: int = 0
|
||||
if eq_pos + 2 < line_start + line_len:
|
||||
if pyi_buf[eq_pos] == 't' and pyi_buf[eq_pos + 1] == '.':
|
||||
# 找到 '(' 的位置
|
||||
paren_pos: t.CSizeT = eq_pos + 2
|
||||
while paren_pos < line_start + line_len and pyi_buf[paren_pos] != '(':
|
||||
paren_pos += 1
|
||||
if paren_pos < line_start + line_len and pyi_buf[paren_pos] == '(':
|
||||
is_type_ctor = 1
|
||||
eq_pos = paren_pos + 1 # 跳过 '('
|
||||
# 跳过括号内可能的前导空格
|
||||
while eq_pos < line_start + line_len and pyi_buf[eq_pos] == ' ':
|
||||
eq_pos += 1
|
||||
|
||||
# 解析整数值(支持十六进制 0x 前缀和负号)
|
||||
# 负号标记
|
||||
is_neg: int = 0
|
||||
if eq_pos < line_start + line_len and pyi_buf[eq_pos] == '-':
|
||||
is_neg = 1
|
||||
eq_pos += 1
|
||||
val_str_start: t.CSizeT = eq_pos
|
||||
val_str_len: t.CSizeT = 0
|
||||
is_hex: int = 0
|
||||
@@ -1447,9 +1364,13 @@ def _lookup_cross_module_cdefine(pool: memhub.MemBuddy | t.CPtr,
|
||||
break
|
||||
hex_result = hex_result * 16 + hd
|
||||
result_val = hex_result
|
||||
# 十六进制负值(如 0xFFFFFFFF)保持原样,由 32 位截断处理
|
||||
result_found = 1
|
||||
else:
|
||||
result_val = string.atoi(val_buf)
|
||||
# 应用负号(如 t.CUnsignedLong(-11) → -11)
|
||||
if is_neg != 0:
|
||||
result_val = -result_val
|
||||
result_found = 1
|
||||
break
|
||||
|
||||
@@ -1488,26 +1409,6 @@ def _lookup_cross_module_cdefine(pool: memhub.MemBuddy | t.CPtr,
|
||||
if rc_sub_len == 0:
|
||||
continue
|
||||
|
||||
# [XMOD-CD] 诊断:记录找到的 from . 行和子模块名
|
||||
_xmod_dbg_rc: str = pool.alloc(512)
|
||||
if _xmod_dbg_rc is not None:
|
||||
_rc_sub_buf_dbg: str = pool.alloc(rc_sub_len + 1)
|
||||
if _rc_sub_buf_dbg is not None:
|
||||
_rc_si2: t.CSizeT
|
||||
for _rc_si2 in range(rc_sub_len):
|
||||
_rc_sub_buf_dbg[_rc_si2] = pyi_buf[rc_sub_start + _rc_si2]
|
||||
_rc_sub_buf_dbg[rc_sub_len] = '\0'
|
||||
else:
|
||||
_rc_sub_buf_dbg = "<alloc-fail>"
|
||||
viperlib.snprintf(_xmod_dbg_rc, 512,
|
||||
"[XMOD-CD] rc-from-line name=%s sub=%s rc_line_start=%d rc_line_len=%d\n",
|
||||
name, _rc_sub_buf_dbg, rc_line_start, rc_line_len)
|
||||
_xmod_lf_rc: fileio.File | t.CPtr = fileio.File(
|
||||
"d:/Users/TermiNexus/Desktop/TransPyC/_xmod_cdefine.log", fileio.MODE.A)
|
||||
if not _xmod_lf_rc.closed:
|
||||
_xmod_lf_rc.write_str(_xmod_dbg_rc)
|
||||
_xmod_lf_rc.close()
|
||||
|
||||
# 检查行是否包含 "import"
|
||||
rc_has_import: int = 0
|
||||
rc_ipos: t.CSizeT = rc_sub_end
|
||||
@@ -1594,18 +1495,6 @@ def _lookup_cross_module_cdefine(pool: memhub.MemBuddy | t.CPtr,
|
||||
rc_name_match = 1
|
||||
rc_cpos += 1
|
||||
|
||||
# [XMOD-CD] 诊断:记录 NAME 匹配结果
|
||||
_xmod_dbg_match: str = pool.alloc(512)
|
||||
if _xmod_dbg_match is not None:
|
||||
viperlib.snprintf(_xmod_dbg_match, 512,
|
||||
"[XMOD-CD] rc-match name=%s star=%d name_match=%d has_paren=%d rc_scan_end=%d rc_imp_start=%d\n",
|
||||
name, rc_star, rc_name_match, rc_has_paren, rc_scan_end, rc_imp_start)
|
||||
_xmod_lf_m: fileio.File | t.CPtr = fileio.File(
|
||||
"d:/Users/TermiNexus/Desktop/TransPyC/_xmod_cdefine.log", fileio.MODE.A)
|
||||
if not _xmod_lf_m.closed:
|
||||
_xmod_lf_m.write_str(_xmod_dbg_match)
|
||||
_xmod_lf_m.close()
|
||||
|
||||
if rc_star == 0 and rc_name_match == 0:
|
||||
continue
|
||||
|
||||
@@ -1632,18 +1521,6 @@ def _lookup_cross_module_cdefine(pool: memhub.MemBuddy | t.CPtr,
|
||||
continue
|
||||
viperlib.snprintf(rc_fi, rc_fi_len, "%s:%s", name, rc_full_mod)
|
||||
|
||||
# [XMOD-CD] 诊断:记录递归调用前的状态
|
||||
_xmod_dbg_recurse: str = pool.alloc(512)
|
||||
if _xmod_dbg_recurse is not None:
|
||||
viperlib.snprintf(_xmod_dbg_recurse, 512,
|
||||
"[XMOD-CD] rc-recurse name=%s full_mod=%s fi=%s star=%d name_match=%d has_paren=%d scan_end=%d\n",
|
||||
name, rc_full_mod, rc_fi, rc_star, rc_name_match, rc_has_paren, rc_scan_end)
|
||||
_xmod_lf_rec: fileio.File | t.CPtr = fileio.File(
|
||||
"d:/Users/TermiNexus/Desktop/TransPyC/_xmod_cdefine.log", fileio.MODE.A)
|
||||
if not _xmod_lf_rec.closed:
|
||||
_xmod_lf_rec.write_str(_xmod_dbg_recurse)
|
||||
_xmod_lf_rec.close()
|
||||
|
||||
# 递归调用查找子模块
|
||||
rc_sub_val: int = _lookup_cross_module_cdefine(pool, name, rc_fi)
|
||||
if HandlesType.is_cdefine_found() != 0:
|
||||
@@ -1659,21 +1536,37 @@ def _lookup_cross_module_cdefine(pool: memhub.MemBuddy | t.CPtr,
|
||||
else:
|
||||
HandlesType.set_cdefine_found(0)
|
||||
|
||||
# [XMOD-CD] 诊断:记录查找结果
|
||||
if _xmod_log_buf is not None:
|
||||
if result_found != 0:
|
||||
viperlib.snprintf(_xmod_log_buf, 512, "[XMOD-CD] FOUND name=%s val=%d base_mod=%s\n", name, result_val, base_mod)
|
||||
else:
|
||||
viperlib.snprintf(_xmod_log_buf, 512, "[XMOD-CD] NOTFOUND name=%s base_mod=%s sha1=%s\n", name, base_mod, sha1)
|
||||
_xmod_lf5: fileio.File | t.CPtr = fileio.File(
|
||||
"d:/Users/TermiNexus/Desktop/TransPyC/_xmod_cdefine.log", fileio.MODE.A)
|
||||
if not _xmod_lf5.closed:
|
||||
_xmod_lf5.write_str(_xmod_log_buf)
|
||||
_xmod_lf5.close()
|
||||
|
||||
return result_val
|
||||
|
||||
|
||||
# ============================================================
|
||||
# _is_cdefine_name_pattern - 检查名字是否符合 CDefine 命名约定
|
||||
#
|
||||
# CDefine 常量(如 FOREGROUND_GREEN, STD_OUTPUT_HANDLE, SCOPE_MODULE)
|
||||
# 都遵循 ALL_CAPS 约定:仅含大写字母 A-Z、数字 0-9、下划线 _,
|
||||
# 且至少含一个大写字母。
|
||||
#
|
||||
# Python 关键字(match, if, for)和变量名(self, pool, builder)
|
||||
# 都含小写字母,不会匹配,从而避免 fail-fast 误报。
|
||||
#
|
||||
# 返回: 1=符合 CDefine 命名约定, 0=不符合
|
||||
# ============================================================
|
||||
def _is_cdefine_name_pattern(name: str) -> int:
|
||||
"""检查名字是否符合 CDefine 命名约定(全大写+下划线+数字)"""
|
||||
if name is None:
|
||||
return 0
|
||||
has_upper: int = 0
|
||||
i: t.CSizeT = 0
|
||||
while name[i] != '\0':
|
||||
c: t.CChar = name[i]
|
||||
if c >= 'a' and c <= 'z':
|
||||
return 0
|
||||
if c >= 'A' and c <= 'Z':
|
||||
has_upper = 1
|
||||
i += 1
|
||||
return has_upper
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 翻译变量引用(Name 节点)→ load
|
||||
# ============================================================
|
||||
@@ -1690,27 +1583,21 @@ def translate_name_value(builder: llvmlite.IRBuilder | t.CPtr,
|
||||
return None
|
||||
|
||||
# CDefine 编译期常量: 直接返回整数常量值(不生成运行时代码)
|
||||
# NAME: t.CDefine = value 形式定义的常量在编译期已注册到全局表
|
||||
# NAME: t.CDefine = value 形式定义的常量在编译期已注册到本地表
|
||||
cdef_val: int = HandlesType.lookup_cdefine_constant(nm_id)
|
||||
if HandlesType.is_cdefine_found() != 0:
|
||||
return llvmlite.const_int32(pool, cdef_val)
|
||||
|
||||
# 本地 CDefine 表未找到:尝试跨模块查找
|
||||
# 对于 from w32.win32base import * 导入的 INVALID_HANDLE_VALUE 等常量,
|
||||
# CDefine 表在模块切换时被清空,需要从 from_imports 查找来源模块并读取 .pyi
|
||||
if trans is not None:
|
||||
if trans._from_imports is not None:
|
||||
# 本地表未找到:尝试跨模块 .pyi 查找(保证多模块查表存表一致)
|
||||
# 仅对符合 CDefine 命名约定(ALL_CAPS)的名字触发跨模块查找,
|
||||
# 避免对普通变量名(mb/name/ptr/pool/self 等)误触发,造成严重性能损耗
|
||||
if _is_cdefine_name_pattern(nm_id) != 0:
|
||||
if trans is not None and trans._from_imports is not None:
|
||||
cdef_val = _lookup_cross_module_cdefine(pool, nm_id, trans._from_imports)
|
||||
if HandlesType.is_cdefine_found() != 0:
|
||||
return llvmlite.const_int32(pool, cdef_val)
|
||||
|
||||
# 模块别名检查:如果 nm_id 是已导入模块名(如 win32file, fileio),
|
||||
# 不应被当作普通变量或全局变量,返回 None 让上层处理
|
||||
if trans is not None and trans._imported_modules is not None:
|
||||
if HandlesImports.is_module_imported(trans._imported_modules, nm_id) != 0:
|
||||
return None
|
||||
|
||||
# global 变量:从模块作用域查找
|
||||
# global 变量:从模块作用域查找(global 声明优先级最高)
|
||||
if trans is not None:
|
||||
if HT.is_global_name(trans, nm_id) != 0:
|
||||
mod_alloca: llvmlite.Value | t.CPtr = HandlesVar.lookup_module_var(
|
||||
@@ -1727,23 +1614,40 @@ def translate_name_value(builder: llvmlite.IRBuilder | t.CPtr,
|
||||
if HT.is_nonlocal_name(trans, nm_id) != 0:
|
||||
return HandlesNonlocal.load_nonlocal_var(trans, nm_id)
|
||||
|
||||
# 局部变量查找(必须先于模块别名检查)
|
||||
# 否则与模块同名的局部变量(如 `import t, c` 后的局部变量 c)会被误判为模块别名,
|
||||
# 导致 SymTab 已注册的局部变量查找不到(rhs_val is None bug 根因)
|
||||
alloca: llvmlite.Value | t.CPtr = HandlesVar.lookup_var(trans.SymTab, nm_id)
|
||||
if alloca is None:
|
||||
# 跨模块 CDefine 查找(仅当 Name 不是任何变量时才尝试):
|
||||
# 从 from_imports 解析源模块,再从该模块的 pyi 文件中解析 CDefine 常量值
|
||||
# (如 FLAG_IS_ASYNC 从 base.py 导入)
|
||||
if trans is not None and trans._from_imports is not None:
|
||||
cross_val: int = _lookup_cross_module_cdefine(pool, nm_id, trans._from_imports)
|
||||
if cross_val >= 0:
|
||||
return llvmlite.const_int32(pool, cross_val)
|
||||
return None
|
||||
if alloca is not None:
|
||||
load_ty: llvmlite.LLVMType | t.CPtr = None
|
||||
if alloca.Ty is not None:
|
||||
load_ty = alloca.Ty.Pointee
|
||||
if load_ty is None:
|
||||
load_ty = llvmlite.Int32(pool)
|
||||
return llvmlite.build_load(builder, load_ty, alloca)
|
||||
|
||||
load_ty: llvmlite.LLVMType | t.CPtr = None
|
||||
if alloca.Ty is not None:
|
||||
load_ty = alloca.Ty.Pointee
|
||||
if load_ty is None:
|
||||
load_ty = llvmlite.Int32(pool)
|
||||
return llvmlite.build_load(builder, load_ty, alloca)
|
||||
# 模块别名检查:SymTab 查找失败后才检查
|
||||
# 如果 nm_id 是已导入模块名(如 win32file, fileio)且未被声明为局部变量,
|
||||
# 返回 None 让上层处理(用于属性访问 win32file.CreateFileA)
|
||||
if trans is not None and trans._imported_modules is not None:
|
||||
if HandlesImports.is_module_imported(trans._imported_modules, nm_id) != 0:
|
||||
return None
|
||||
|
||||
# 所有查找路径均失败
|
||||
# fail-fast: 仅对符合 CDefine 命名约定(ALL_CAPS)的名字报错
|
||||
# 避免对 match/self/pool 等关键字和变量名误报
|
||||
# 跨模块 CDefine 查找已在上方完成,此处不重复
|
||||
if _is_cdefine_name_pattern(nm_id) != 0:
|
||||
err_buf2: str = pool.alloc(256)
|
||||
if err_buf2 is not None:
|
||||
cur_sha1: str = "(unknown)"
|
||||
if trans is not None and trans.ModuleSha1 is not None:
|
||||
cur_sha1 = trans.ModuleSha1
|
||||
viperlib.snprintf(err_buf2, 256,
|
||||
"[CD] FATAL: Name '%s' NOT found (CDefine local+cross + global + nonlocal + alloca + module alias) in module sha1=%s\n",
|
||||
nm_id, cur_sha1)
|
||||
VLogger.error(err_buf2, "CD")
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
@@ -1989,22 +1893,11 @@ def translate_subscript(builder: llvmlite.IRBuilder | t.CPtr,
|
||||
nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(sub.value)
|
||||
if nm.id is not None and trans is not None:
|
||||
alloca: llvmlite.Value | t.CPtr = HandlesVar.lookup_var(trans.SymTab, nm.id)
|
||||
if alloca is None:
|
||||
stdio.printf("[TS] alloca=None var=%s\n", nm.id)
|
||||
stdio.fflush(0)
|
||||
elif alloca.Ty is None:
|
||||
stdio.printf("[TS] alloca.Ty=None var=%s\n", nm.id)
|
||||
stdio.fflush(0)
|
||||
if alloca is not None and alloca.Ty is not None:
|
||||
if is_ptr_type(alloca.Ty) != 0:
|
||||
pointee: llvmlite.LLVMType | t.CPtr = alloca.Ty.Pointee
|
||||
if pointee is None:
|
||||
stdio.printf("[TS] pointee=None var=%s\n", nm.id)
|
||||
stdio.fflush(0)
|
||||
if pointee is not None:
|
||||
# 不调用 pointee.kind() 避免跨模块引用 LLVMType.kind 符号
|
||||
stdio.printf("[TS] var=%s pointee_not_null\n", nm.id)
|
||||
stdio.fflush(0)
|
||||
# 单层 match(避免嵌套 match 的编译器 bug)
|
||||
match pointee:
|
||||
case llvmlite.LLVMType.Array(elem_ty, count):
|
||||
@@ -2015,8 +1908,6 @@ def translate_subscript(builder: llvmlite.IRBuilder | t.CPtr,
|
||||
return llvmlite.build_load(builder, elem_ty, elem_ptr)
|
||||
return None
|
||||
case llvmlite.LLVMType.Ptr(inner_ty):
|
||||
stdio.printf("[TS] matched Ptr var=%s\n", nm.id)
|
||||
stdio.fflush(0)
|
||||
# 检查 inner_ty 是否是 list[T] 类型(泛型类不注册 struct)
|
||||
# list 的 subscript 应该走 __getitem__ 内联路径,而非指针遍历
|
||||
list_struct_name: str = None
|
||||
@@ -2064,32 +1955,16 @@ def translate_subscript(builder: llvmlite.IRBuilder | t.CPtr,
|
||||
# 自定义结构体 (如 HashTable|t.CPtr, JsonValue|t.CPtr):
|
||||
# 优先转发到 __getitem__,避免 IsPtrElement 误判为指针遍历
|
||||
cls_nm_rd_ptr: str = _get_custom_struct_cls_nm(pool, inner_ty)
|
||||
if cls_nm_rd_ptr is None:
|
||||
stdio.printf("[TS] cls_nm=None var=%s\n", nm.id)
|
||||
stdio.fflush(0)
|
||||
if not (cls_nm_rd_ptr is None):
|
||||
stdio.printf("[TS] cls_nm=%s var=%s\n", cls_nm_rd_ptr, nm.id)
|
||||
stdio.fflush(0)
|
||||
stdio.printf("[TS] pre_getitem cls=%s\n", cls_nm_rd_ptr)
|
||||
stdio.fflush(0)
|
||||
obj_ptr_rd: llvmlite.Value | t.CPtr = llvmlite.build_load(
|
||||
builder, pointee, alloca)
|
||||
if obj_ptr_rd is None:
|
||||
stdio.printf("[TS] __getitem__ build_load=None\n")
|
||||
stdio.fflush(0)
|
||||
if not (obj_ptr_rd is None):
|
||||
arg_vals_rd_p: t.CSizeT | t.CPtr = pool.alloc(8)
|
||||
if arg_vals_rd_p is None:
|
||||
stdio.printf("[TS] __getitem__ alloc=None\n")
|
||||
stdio.fflush(0)
|
||||
if not (arg_vals_rd_p is None):
|
||||
arg_vals_rd_p[0] = t.CSizeT(idx_val)
|
||||
ret_rd_p: llvmlite.Value | t.CPtr = HandlesExprCall._call_method_on_ptr(
|
||||
pool, builder, mod, cls_nm_rd_ptr, "__getitem__",
|
||||
obj_ptr_rd, arg_vals_rd_p, 1, trans)
|
||||
if ret_rd_p is None:
|
||||
stdio.printf("[TS] __getitem__ call=None cls=%s\n", cls_nm_rd_ptr)
|
||||
stdio.fflush(0)
|
||||
if not (ret_rd_p is None):
|
||||
return ret_rd_p
|
||||
return None
|
||||
@@ -2493,11 +2368,6 @@ def translate_attribute(builder: llvmlite.IRBuilder | t.CPtr,
|
||||
obj_ptr = translate_value(builder, pool, mod, at.value, None, 0, trans)
|
||||
|
||||
if obj_ptr is None or obj_ptr.Ty is None:
|
||||
if at.value.kind() == ast.ASTKind.Name:
|
||||
nm_d: ast.Name | t.CPtr = (ast.Name | t.CPtr)(at.value)
|
||||
if nm_d.id is not None:
|
||||
stdio.printf("[TA-DIAG] obj_ptr=None attr=%s name=%s\n",
|
||||
at.attr, nm_d.id)
|
||||
return None
|
||||
|
||||
# 如果 obj_ptr 是 Ptr(Ptr(Struct))(X|t.CPtr 变量的 alloca),
|
||||
@@ -2540,29 +2410,15 @@ def translate_attribute(builder: llvmlite.IRBuilder | t.CPtr,
|
||||
var_entry: HandlesVar.VarEntry | t.CPtr = HandlesVar.lookup_var_entry(
|
||||
trans.SymTab, nm_fb.id)
|
||||
if var_entry is not None and var_entry.AnnotClassName is not None:
|
||||
stdio.printf("[TA-DIAG] fallback annot=%s attr=%s\n",
|
||||
var_entry.AnnotClassName, at.attr)
|
||||
cur_sha1: str = trans.ModuleSha1
|
||||
field_info = HandlesStruct.lookup_field_by_class(
|
||||
var_entry.AnnotClassName, at.attr, cur_sha1)
|
||||
if field_info is None:
|
||||
stdio.printf("[TA-DIAG] lfbc_failed annot=%s attr=%s\n",
|
||||
var_entry.AnnotClassName, at.attr)
|
||||
stdio.fflush(0)
|
||||
else:
|
||||
stdio.printf("[TA-DIAG] lfbc_ok annot=%s attr=%s idx=%d\n",
|
||||
var_entry.AnnotClassName, at.attr, field_info.Index)
|
||||
stdio.fflush(0)
|
||||
# 回退 1 成功:bitcast obj_ptr 到 AnnotClassName 对应的结构体类型
|
||||
# 原始 struct_ty 可能是 i8(X|t.CPtr 简化为 Ptr(i8)),
|
||||
# 需用实际结构体类型做 GEP,否则 GEP i8 失败
|
||||
if field_info is not None:
|
||||
annot_se: HandlesStruct.StructEntry | t.CPtr = \
|
||||
HandlesStruct.find_struct(var_entry.AnnotClassName)
|
||||
if annot_se is None:
|
||||
stdio.printf("[TA-DIAG] fb1 find_struct None annot=%s\n",
|
||||
var_entry.AnnotClassName)
|
||||
stdio.fflush(0)
|
||||
if annot_se is not None and annot_se.Ty is not None:
|
||||
annot_ptr_ty: llvmlite.LLVMType | t.CPtr = \
|
||||
llvmlite.Ptr(pool, annot_se.Ty)
|
||||
@@ -2576,11 +2432,6 @@ def translate_attribute(builder: llvmlite.IRBuilder | t.CPtr,
|
||||
# (原始 struct_ty 可能是 i8,ensure 无效)
|
||||
HandlesStruct.ensure_struct_def_in_module(
|
||||
pool, mod, annot_se.Ty)
|
||||
stdio.printf("[TA-DIAG] fb1 struct_ty updated\n")
|
||||
stdio.fflush(0)
|
||||
else:
|
||||
stdio.printf("[TA-DIAG] fb1 bitcast None\n")
|
||||
stdio.fflush(0)
|
||||
# 回退 2: 子类搜索 — 注解类型是基类但实际值是派生类
|
||||
# 如 node: AST | t.CPtr = If(...),访问 node.orelse
|
||||
if field_info is None:
|
||||
@@ -2615,29 +2466,14 @@ def translate_attribute(builder: llvmlite.IRBuilder | t.CPtr,
|
||||
return None
|
||||
# 普通结构体:GEP + load
|
||||
field_idx: int = field_info.Index
|
||||
stdio.printf("[TA-DIAG] gep_try idx=%d struct_is_ptr=%d\n",
|
||||
field_idx, is_ptr_type(struct_ty))
|
||||
stdio.fflush(0)
|
||||
field_ptr: llvmlite.Value | t.CPtr = llvmlite.build_gep_struct(
|
||||
builder, struct_ty, field_ty, obj_ptr, field_idx)
|
||||
if field_ptr is None:
|
||||
stdio.printf("[TA-DIAG] gep_failed idx=%d\n", field_idx)
|
||||
stdio.fflush(0)
|
||||
if field_ptr is not None:
|
||||
stdio.printf("[TA-DIAG] gep_ok idx=%d is_array=%d\n",
|
||||
field_idx, is_array_type(field_ty))
|
||||
stdio.fflush(0)
|
||||
# 数组类型字段不能 load 为 SSA value,直接返回字段指针
|
||||
# 用于后续下标访问: self.state[0] → GEP state 字段 → GEP 数组元素
|
||||
if is_array_type(field_ty) != 0:
|
||||
return field_ptr
|
||||
stdio.printf("[TA-DIAG] pre_load idx=%d field_ty_not_null=%d\n",
|
||||
field_idx, 1 if field_ty is not None else 0)
|
||||
stdio.fflush(0)
|
||||
loaded_val: llvmlite.Value | t.CPtr = llvmlite.build_load(builder, field_ty, field_ptr)
|
||||
stdio.printf("[TA-DIAG] post_load idx=%d loaded=%d\n",
|
||||
field_idx, 1 if loaded_val is not None else 0)
|
||||
stdio.fflush(0)
|
||||
# 联合类型字段(如 Token | t.CPtr)被编译为 i8*,
|
||||
# 若 AnnotClassName 指示了具体结构体类型,bitcast 为正确的结构体指针
|
||||
if loaded_val is not None and field_info.AnnotClassName is not None:
|
||||
@@ -2647,17 +2483,8 @@ def translate_attribute(builder: llvmlite.IRBuilder | t.CPtr,
|
||||
annot_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, annot_struct.Ty)
|
||||
return llvmlite.build_bitcast(builder, loaded_val, annot_ptr_ty)
|
||||
return loaded_val
|
||||
# 诊断:所有字段查找路径失败
|
||||
sn_diag: str = HandlesStruct._extract_struct_name(struct_ty)
|
||||
if sn_diag is not None:
|
||||
stdio.printf("[TA-DIAG] field=None attr=%s sname=%s\n",
|
||||
at.attr, sn_diag)
|
||||
else:
|
||||
stdio.printf("[TA-DIAG] field=None attr=%s sname=(null)\n",
|
||||
at.attr)
|
||||
return None
|
||||
case _:
|
||||
stdio.printf("[TA-DIAG] type_mismatch attr=%s\n", at.attr)
|
||||
return None
|
||||
|
||||
# ============================================================
|
||||
@@ -2686,34 +2513,17 @@ def get_subscript_ptr(builder: llvmlite.IRBuilder | t.CPtr,
|
||||
nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(sub.value)
|
||||
if nm.id is not None and trans is not None:
|
||||
alloca: llvmlite.Value | t.CPtr = HandlesVar.lookup_var(trans.SymTab, nm.id)
|
||||
if alloca is None:
|
||||
stdio.printf("[GSP] alloca=None var=%s\n", nm.id)
|
||||
stdio.fflush(0)
|
||||
elif alloca.Ty is None:
|
||||
stdio.printf("[GSP] alloca.Ty=None var=%s\n", nm.id)
|
||||
stdio.fflush(0)
|
||||
if alloca is not None and alloca.Ty is not None:
|
||||
if is_ptr_type(alloca.Ty) != 0:
|
||||
pointee: llvmlite.LLVMType | t.CPtr = alloca.Ty.Pointee
|
||||
if pointee is None:
|
||||
stdio.printf("[GSP] pointee=None var=%s\n", nm.id)
|
||||
stdio.fflush(0)
|
||||
if pointee is not None:
|
||||
pe_arr: int = is_array_type(pointee)
|
||||
pe_ptr: int = is_ptr_type(pointee)
|
||||
stdio.printf("[GSP] var=%s pe_arr=%d pe_ptr=%d\n", nm.id, pe_arr, pe_ptr)
|
||||
stdio.fflush(0)
|
||||
# 单层 match(避免嵌套 match 的编译器 bug)
|
||||
match pointee:
|
||||
case llvmlite.LLVMType.Array(elem_ty, count):
|
||||
stdio.printf("[GSP] matched Array\n")
|
||||
stdio.fflush(0)
|
||||
# 数组遍历
|
||||
return llvmlite.build_gep_array(
|
||||
builder, pointee, elem_ty, alloca, idx_val)
|
||||
case llvmlite.LLVMType.Ptr(inner_ty):
|
||||
stdio.printf("[GSP] matched Ptr\n")
|
||||
stdio.fflush(0)
|
||||
# inner_ty 是 Ptr 说明 alloca.Ty 是三重指针,
|
||||
# 即 X|t.CPtr 当 X 本身是指针类型 (如 T=AST|t.CPtr, T|t.CPtr=AST**)。
|
||||
# 此时 [i]=val 应该是指针解引用赋值, 而非调用 __setitem__。
|
||||
@@ -2731,9 +2541,6 @@ def get_subscript_ptr(builder: llvmlite.IRBuilder | t.CPtr,
|
||||
if cls_nm_ptr_chk is None:
|
||||
pass
|
||||
if not (cls_nm_ptr_chk is None):
|
||||
stdio.printf("[GSP] custom struct %s, defer to __setitem__\n",
|
||||
cls_nm_ptr_chk)
|
||||
stdio.fflush(0)
|
||||
return None
|
||||
# bytes|t.CPtr / str|t.CPtr: alloca 是 i8**,
|
||||
# 直接 GEP 按 i8* 步长(8 字节),不 load
|
||||
@@ -2742,39 +2549,26 @@ def get_subscript_ptr(builder: llvmlite.IRBuilder | t.CPtr,
|
||||
ve_pe: HandlesVar.VarEntry | t.CPtr = \
|
||||
HandlesVar.lookup_var_entry(trans.SymTab, nm.id)
|
||||
if ve_pe is not None and ve_pe.IsPtrElement == 1:
|
||||
stdio.printf("[GSP] IsPtrElement=1, gep direct\n")
|
||||
stdio.fflush(0)
|
||||
return llvmlite.build_gep(
|
||||
builder, pointee, alloca, idx_val)
|
||||
# 普通指针遍历: 先 load 指针值,再 GEP
|
||||
ptr_val: llvmlite.Value | t.CPtr = llvmlite.build_load(
|
||||
builder, pointee, alloca)
|
||||
if ptr_val is None:
|
||||
stdio.printf("[GSP] build_load=None\n")
|
||||
stdio.fflush(0)
|
||||
return None
|
||||
gep_r: llvmlite.Value | t.CPtr = llvmlite.build_gep(
|
||||
builder, inner_ty, ptr_val, idx_val)
|
||||
if gep_r is None:
|
||||
stdio.printf("[GSP] build_gep=None\n")
|
||||
stdio.fflush(0)
|
||||
return gep_r
|
||||
case _:
|
||||
# pointee 是普通标量类型 (如 i64, i32, i8):
|
||||
# alloca 是 Ptr(标量), 直接 GEP 获取第 idx 个元素指针
|
||||
# 支持 arg_vals[i] = val 这类参数数组下标赋值
|
||||
stdio.printf("[GSP] matched scalar, gep direct\n")
|
||||
stdio.fflush(0)
|
||||
return llvmlite.build_gep(builder, pointee, alloca, idx_val)
|
||||
|
||||
# 通用路径
|
||||
stdio.printf("[GSP] fallback to generic path\n")
|
||||
stdio.fflush(0)
|
||||
ptr_val: llvmlite.Value | t.CPtr = translate_value(
|
||||
builder, pool, mod, sub.value, None, 0, trans)
|
||||
if ptr_val is None or ptr_val.Ty is None:
|
||||
stdio.printf("[GSP] generic: ptr_val=None\n")
|
||||
stdio.fflush(0)
|
||||
return None
|
||||
if is_ptr_type(ptr_val.Ty) != 0:
|
||||
elem_ty2: llvmlite.LLVMType | t.CPtr = ptr_val.Ty.Pointee
|
||||
@@ -2792,9 +2586,6 @@ def get_subscript_ptr(builder: llvmlite.IRBuilder | t.CPtr,
|
||||
if cls_nm_gen is None:
|
||||
pass
|
||||
if not (cls_nm_gen is None):
|
||||
stdio.printf("[GSP] generic custom struct %s, defer to __setitem__\n",
|
||||
cls_nm_gen)
|
||||
stdio.fflush(0)
|
||||
return None
|
||||
# 指针类型: 单索引 GEP (getelementptr ty, ptr, idx)
|
||||
return llvmlite.build_gep(builder, elem_ty2, ptr_val, idx_val)
|
||||
|
||||
Reference in New Issue
Block a user