尝试进行 Qt 测试,增加了 AI 人机调试工具 _console,以及 TransPyV 进行修正

This commit is contained in:
2026-07-21 14:41:22 +08:00
parent a277ded8d4
commit 135aa05485
311 changed files with 7084 additions and 2131 deletions

View File

@@ -149,16 +149,8 @@ class AnnAssignHandle(BaseHandle):
if isinstance(TargetType, ir.IntType) and isinstance(Value.type, ir.IntType):
if TargetType.width < Value.type.width:
Value = Gen.builder.trunc(Value, TargetType, name="trunc")
elif TargetType.width > Value.type.width:
if Value.type.width == 1:
# i1 是布尔值,无符号语义,必须 zext
Value = Gen.builder.zext(Value, TargetType, name="zext")
else:
is_unsigned: bool = id(Value) in Gen._unsigned_results
if is_unsigned:
Value = Gen.builder.zext(Value, TargetType, name="zext")
else:
Value = Gen.builder.sext(Value, TargetType, name="sext")
else:
Value = Gen.builder.zext(Value, TargetType, name="zext")
elif isinstance(TargetType, ir.PointerType) and isinstance(Value.type, ir.PointerType):
Value = Gen.builder.bitcast(Value, TargetType, name="ptr_bitcast")
elif isinstance(TargetType, ir.PointerType) and isinstance(Value.type, ir.IntType):
@@ -317,7 +309,6 @@ class AnnAssignHandle(BaseHandle):
TypeInfo = CTypeInfo()
TypeInfo.BaseType = t.CInt()
IsPtr: bool = TypeInfo.IsPtr
if TypeInfo.IsDefine:
if Node.value and isinstance(Node.value, ast.Constant):
if not hasattr(Gen, '_define_constants'):
@@ -556,22 +547,14 @@ class AnnAssignHandle(BaseHandle):
VarPtr: ir.Value = Gen.variables[VarName]
if isinstance(VarPtr.type, ir.PointerType):
TargetType: ir.Type = VarPtr.type.pointee
if InitValue.type != TargetType:
if isinstance(InitValue.type, ir.IntType) and isinstance(TargetType, ir.IntType):
if TargetType.width > InitValue.type.width:
if InitValue.type.width == 1:
# i1 是布尔值,无符号语义,必须 zext
InitValue = Gen.builder.zext(InitValue, TargetType, name=f"zext_{VarName}")
else:
is_unsigned: bool = (Node.value is not None and Gen._check_node_unsigned(Node.value)) or id(InitValue) in Gen._unsigned_results
if is_unsigned:
InitValue = Gen.builder.zext(InitValue, TargetType, name=f"zext_{VarName}")
else:
InitValue = Gen.builder.sext(InitValue, TargetType, name=f"sext_{VarName}")
elif TargetType.width < InitValue.type.width:
InitValue = Gen.builder.trunc(InitValue, TargetType, name=f"trunc_{VarName}")
elif isinstance(InitValue.type, ir.PointerType) and isinstance(TargetType, ir.PointerType):
InitValue = Gen.builder.bitcast(InitValue, TargetType, name=f"cast_{VarName}")
if InitValue.type != TargetType:
if isinstance(InitValue.type, ir.IntType) and isinstance(TargetType, ir.IntType):
if TargetType.width > InitValue.type.width:
InitValue = Gen.builder.zext(InitValue, TargetType, name=f"zext_{VarName}")
elif TargetType.width < InitValue.type.width:
InitValue = Gen.builder.trunc(InitValue, TargetType, name=f"trunc_{VarName}")
elif isinstance(InitValue.type, ir.PointerType) and isinstance(TargetType, ir.PointerType):
InitValue = Gen.builder.bitcast(InitValue, TargetType, name=f"cast_{VarName}")
Gen._store(InitValue, VarPtr)
except Exception as _e:
if _config_mode == "strict":
@@ -648,15 +631,7 @@ class AnnAssignHandle(BaseHandle):
if InitValue.type != VarType:
if isinstance(InitValue.type, ir.IntType) and isinstance(VarType, ir.IntType):
if VarType.width > InitValue.type.width:
if InitValue.type.width == 1:
# i1 是布尔值,无符号语义,必须 zext
InitValue = Gen.builder.zext(InitValue, VarType, name=f"zext_{VarName}")
else:
is_unsigned: bool = (Node.value is not None and Gen._check_node_unsigned(Node.value)) or id(InitValue) in Gen._unsigned_results
if is_unsigned:
InitValue = Gen.builder.zext(InitValue, VarType, name=f"zext_{VarName}")
else:
InitValue = Gen.builder.sext(InitValue, VarType, name=f"sext_{VarName}")
InitValue = Gen.builder.zext(InitValue, VarType, name=f"zext_{VarName}")
elif VarType.width < InitValue.type.width:
InitValue = Gen.builder.trunc(InitValue, VarType, name=f"trunc_{VarName}")
elif isinstance(InitValue.type, ir.PointerType) and isinstance(VarType, ir.PointerType):

View File

@@ -536,15 +536,7 @@ class AssignHandle(BaseHandle):
if DefVal.type != expected_type:
if isinstance(expected_type, ir.IntType) and isinstance(DefVal.type, ir.IntType):
if DefVal.type.width < expected_type.width:
if DefVal.type.width == 1:
# i1 是布尔值,无符号语义,必须 zext
DefVal = Gen.builder.zext(DefVal, expected_type, name=f"zext_default_{arg_idx}")
else:
is_unsigned: bool = Gen._check_node_unsigned(arg_def[def_idx]) or id(DefVal) in Gen._unsigned_results
if is_unsigned:
DefVal = Gen.builder.zext(DefVal, expected_type, name=f"zext_default_{arg_idx}")
else:
DefVal = Gen.builder.sext(DefVal, expected_type, name=f"sext_default_{arg_idx}")
DefVal = Gen.builder.zext(DefVal, expected_type, name=f"zext_default_{arg_idx}")
elif DefVal.type.width > expected_type.width:
DefVal = Gen.builder.trunc(DefVal, expected_type, name=f"trunc_default_{arg_idx}")
CallArgs.append(DefVal)

View File

@@ -253,6 +253,10 @@ class ClassHandle(BaseHandle):
return 'union'
if issubclass(cls, t.CStruct):
return 'struct'
# CType 及其子类CChar/CInt/CVoid/CPtr 等)是"类型强转"标记,
# 不应被编译为真实结构体。
if issubclass(cls, t.CType):
return 'ctype_marker'
# 2) 查 t 模块属性(直接引用 t.CEnum 等)
t_cls: type | None = getattr(t, base_name, None)
@@ -263,9 +267,47 @@ class ClassHandle(BaseHandle):
return 'union'
if issubclass(t_cls, t.CStruct):
return 'struct'
# CType 及其子类是"类型强转"标记,不编译为结构体。
return 'ctype_marker'
return None
@staticmethod
def _is_classname_ctype_marker(class_name: str) -> bool:
"""检查类名是否是 t.CType 的"类型强转"标记子类。
只有 position 不含 BASE 的纯修饰符/标记类型CPtr/CVolatile/CConst/
CInline/CStatic/CExtern/CExport/CRegister/CAuto/_CTypedef/CTypeDefault 等)
才应跳过编译。有 BASE position 的基本类型CInt/CChar/CSizeT/CLong 等)
有具体大小应被正常编译。CType 基类本身无 basesbase 检测无法触发,
需要直接按类名检查。
注意CTypeRegistry.GetClassByName 会跳过 CType 本身和 CTypeDefault
所以这里直接用 getattr(t, name) 检查 t 模块属性。
Returns:
True 如果 class_name 是 CType 标记子类名(应跳过编译)
"""
if not class_name:
return False
# 直接查 t 模块属性CTypeRegistry._build 会跳过 CType/CTypeDefault/BigEndian/LittleEndian
t_cls: type | None = getattr(t, class_name, None)
if not isinstance(t_cls, type) or not issubclass(t_cls, t.CType):
return False
if issubclass(t_cls, (t.CStruct, t.CEnum, t.REnum, t.CUnion)):
return False
# 基本类型position 含 BASE 且 Size > 0有具体大小不应跳过
# CVoid 虽含 BASE 但 Size=0CType Size=None仍需跳过
if t.CType.BASE in t_cls.position:
try:
inst = t_cls()
size_val = getattr(inst, 'Size', None)
if size_val is not None and size_val > 0:
return False
except Exception:
pass
return True
def _resolve_decorator_kind(self, Node: ast.ClassDef, Gen: LlvmGeneratorMixin) -> str | None:
"""从装饰器列表中解析结构体类型种类
@@ -409,6 +451,11 @@ class ClassHandle(BaseHandle):
def _EmitClassLlvm(self, Node: ast.ClassDef, Gen: LlvmGeneratorMixin, declare_only: bool = False) -> None:
ClassName: str = Node.name
# t.CType 及其子类CChar/CInt/CVoid/CPtr/CTypeDefault 等)是"类型强转"标记,
# 不应被编译为真实结构体。CType 基类本身无 basesbase 检测无法触发,
# 此处在方法入口直接按类名跳过。
if self._is_classname_ctype_marker(ClassName):
return
if self._is_generic_class(Node):
if not hasattr(self, '_generic_class_templates'):
self._generic_class_templates = {}
@@ -449,6 +496,10 @@ class ClassHandle(BaseHandle):
IsCunion = True
elif kind == 'renum':
IsRenum = True
elif kind == 'ctype_marker':
# CType 及其子类CChar/CInt/CVoid/CPtr/CTypeDefault 等)是
# "类型强转"标记,不应被编译为真实结构体。直接 return 跳过编译。
return
if IsCenum:
self._RegisterEnumMembers(Node)
return
@@ -540,50 +591,33 @@ class ClassHandle(BaseHandle):
if pm_name in parent_defaults:
Gen.class_member_defaults[ClassName][pm_name] = parent_defaults[pm_name]
Gen.class_members[ClassName] = inherited + Gen.class_members[ClassName]
if ParentClass in Gen.class_methods:
parent_methods: list = list(Gen.class_methods[ParentClass])
# 从 Node.body 收集子类有方法(此时 Gen.class_methods[ClassName] 可能为空,
# 因为自有方法在 L660-676 才注册。若直接用 Gen.class_methods[ClassName]
# child_method_map 会为空,所有父类方法被当作"未覆盖"添加为包装器,
# 然后 register_method 又把它们追加到 Gen.class_methods[ClassName]
# L566 循环再次添加 → 产生重复条目vtable 布局与导入模块不一致)
child_method_map: dict[str, str] = {}
child_self_methods_snapshot: list[str] = []
for _item in Node.body:
if isinstance(_item, ast.FunctionDef):
_mname: str = _item.name
if _mname in ('__new__', '__init__', '__before_init__'):
continue
_item_meta: FuncMeta = self.Trans.FunctionHandler._ExtractFuncMeta(_item.decorator_list)
if FuncMeta.PROPERTY_SETTER in _item_meta:
_full: str = f"{ClassName}.{_mname}$set"
elif FuncMeta.PROPERTY_DELETER in _item_meta:
_full = f"{ClassName}.{_mname}$del"
else:
_full = f"{ClassName}.{_mname}"
_short: str = _mname
child_method_map[_short] = _full
child_self_methods_snapshot.append(_full)
# 父类方法在前(保证 vtable 布局一致性,子类多态分派索引正确),
# 子类新增方法在后。子类覆盖的方法放在父类方法的位置(用子类实现)。
new_methods: list = []
covered_names: set[str] = set()
for pm in parent_methods:
method_name: str = pm.split('.')[-1] if '.' in pm else pm
if method_name in child_method_map:
# 子类覆盖了父类方法 — 用子类的实现,放在父类的位置
new_methods.append(child_method_map[method_name])
covered_names.add(method_name)
else:
# 父类独有方法 — 子类未覆盖,注册子类包装器
child_method: str = f"{ClassName}.{method_name}"
new_methods.append(child_method)
Gen.register_method(ClassName, child_method)
# 添加子类新增方法(不在父类中的)— 使用快照避免 register_method 污染
for m in child_self_methods_snapshot:
method_name: str = m.split('.')[-1] if '.' in m else m
if method_name not in covered_names:
new_methods.append(m)
if ParentClass in Gen.class_methods:
parent_methods: list = list(Gen.class_methods[ParentClass])
# 构建子类有方法映射(方法短名 -> 方法全名)
child_method_map: dict[str, str] = {}
for m in Gen.class_methods[ClassName]:
method_name: str = m.split('.')[-1] if '.' in m else m
child_method_map[method_name] = m
# 父类方法在前(保证 vtable 布局一致性,子类多态分派索引正确),
# 子类新增方法在后。子类覆盖的方法放在父类方法的位置(用子类实现)。
new_methods: list = []
covered_names: set[str] = set()
for pm in parent_methods:
method_name: str = pm.split('.')[-1] if '.' in pm else pm
if method_name in child_method_map:
# 子类覆盖了父类方法 — 用子类的实现,放在父类的位置
new_methods.append(child_method_map[method_name])
covered_names.add(method_name)
else:
# 父类独有方法 — 子类未覆盖,注册子类包装器
child_method: str = f"{ClassName}.{method_name}"
new_methods.append(child_method)
Gen.register_method(ClassName, child_method)
# 添加子类新增方法(不在父类中的)
for m in Gen.class_methods[ClassName]:
method_name: str = m.split('.')[-1] if '.' in m else m
if method_name not in covered_names:
new_methods.append(m)
Gen.class_methods[ClassName] = new_methods
# 提取首个裸字符串字面量作为结构体 __doc__ docstring
if (Node.body and isinstance(Node.body[0], ast.Expr)

View File

@@ -52,6 +52,9 @@ class ExprAsmHandle(BaseHandle):
def _HandleAsmLlvm(self, Node: ast.Call) -> ir.Value | None:
Gen: LlvmCodeGenerator = self.Trans.LlvmGen
# DEBUG: 验证 _HandleAsmLlvm 是否被调用
import sys as _dbg_sys
print(f"[DEBUG_ASM] _HandleAsmLlvm called, Node.args={len(Node.args)}, keywords={[kw.arg for kw in Node.keywords]}", file=_dbg_sys.stderr)
op_arg: Any = None
input_arg: Any = None

View File

@@ -165,6 +165,39 @@ class ExprBuiltinHandle(BaseHandle):
return ir.Constant(ir.IntType(8).as_pointer(), None)
elif FuncName == 'input':
return self._HandleInputLlvm(Node)
elif FuncName == 'isinstance':
# isinstance(obj, Type) — 静态类型系统下编译时解析
# TransPyC 是静态类型系统,运行时无 RTTI。
# 对于编译时已知类型,若变量类型是目标类型的子类则生成 true否则 false。
# 若无法确定(如基类指针指向子类),保守生成 false。
# 注意:这主要让编译时辅助方法(如 c.py 中的 Asm._parse_asm_descr能通过编译
# 这些方法不在运行时被调用,行为不正确不影响程序。
if len(Node.args) >= 2:
ObjVal: ir.Value | None = self.HandleExprLlvm(Node.args[0])
TypeNode: ast.expr = Node.args[1]
TargetClassName: str = ''
if isinstance(TypeNode, ast.Name):
TargetClassName = TypeNode.id
elif isinstance(TypeNode, ast.Attribute):
TargetClassName = TypeNode.attr
if ObjVal is not None and TargetClassName:
ObjType: ir.Type = ObjVal.type
# 解引用指针获取 pointee 类型
if isinstance(ObjType, ir.PointerType):
ObjType = ObjType.pointee
# 检查 pointee 是否是目标结构体类型
if isinstance(ObjType, ir.IdentifiedStructType):
ObjStructName: str = getattr(ObjType, 'name', '')
ShortName: str = ObjStructName.split('.')[-1] if '.' in ObjStructName else ObjStructName
if ShortName == TargetClassName:
return ir.Constant(ir.IntType(1), 1)
# 检查 Gen.var_struct_class
if isinstance(Node.args[0], ast.Name):
VarClassName: str | None = Gen.var_struct_class.get(Node.args[0].id)
if VarClassName == TargetClassName:
return ir.Constant(ir.IntType(1), 1)
return ir.Constant(ir.IntType(1), 0)
return ir.Constant(ir.IntType(1), 0)
elif FuncName == 'ord':
if Node.args:
return self._HandleOrdLlvm(Node.args[0])

View File

@@ -572,10 +572,9 @@ class ExprCallHandle(BaseHandle):
result = self._HandleClassNewLlvm(Node, FuncAttr, module_sha1=_ctor_module_sha1)
if result is not None:
return result
if FuncAttr in Gen.structs:
result = self._HandleClassNewLlvm(Node, FuncAttr, module_sha1=_ctor_module_sha1)
if result is not None:
return result
# c 模块的特殊语法设施Addr/Deref/DerefAs/Set/Load/Asm 等)必须优先处理,
# 即使它们在 Gen.structs 中c.py 的类会被声明为结构体但不应被实例化)。
# c.py 是语法部分,不应被编译,其中的类是编译器语法设施。
if ModulePath == 'c':
if FuncAttr == 'Asm':
return self.Trans.ExprAsmHandle._HandleAsmLlvm(Node)
@@ -607,6 +606,10 @@ class ExprCallHandle(BaseHandle):
return self._HandleLLVMIRLlvm(Node)
elif FuncAttr in ('LInp', 'LOut'):
return ir.Constant(ir.IntType(32), 0)
if FuncAttr in Gen.structs:
result = self._HandleClassNewLlvm(Node, FuncAttr, module_sha1=_ctor_module_sha1)
if result is not None:
return result
if ModulePath == 't':
MethodResult_t = self._HandleMethodCallLlvm(Node)
if MethodResult_t is not None:
@@ -1272,13 +1275,7 @@ class ExprCallHandle(BaseHandle):
if expected_type.width < val.type.width:
return Gen.builder.trunc(val, expected_type)
else:
if val.type.width == 1:
# i1 是布尔值,无符号语义,必须 zext
return Gen.builder.zext(val, expected_type, name="zext")
is_unsigned: bool = id(val) in Gen._unsigned_results
if is_unsigned:
return Gen.builder.zext(val, expected_type, name="zext")
return Gen.builder.sext(val, expected_type, name="sext")
return Gen.builder.zext(val, expected_type)
if isinstance(val.type, ir.PointerType) and isinstance(expected_type, ir.IntType):
if expected_type.width == 64:
return Gen.builder.ptrtoint(val, expected_type)
@@ -1631,14 +1628,7 @@ class ExprCallHandle(BaseHandle):
return ArgVal
if isinstance(TargetType, ir.IntType) and isinstance(ArgVal.type, ir.IntType):
if ArgVal.type.width < TargetType.width:
if ArgVal.type.width == 1:
# i1 是布尔值,无符号语义,必须 zext
return Gen.builder.zext(ArgVal, TargetType, name=f"zext_{TypedefName}_cast")
# C cast 语义:源有符号 → sext源无符号 → zext目标符号性仅影响解释
is_unsigned: bool = (Node.args and Gen._check_node_unsigned(Node.args[0])) or id(ArgVal) in Gen._unsigned_results
if is_unsigned:
return Gen.builder.zext(ArgVal, TargetType, name=f"zext_{TypedefName}_cast")
return Gen.builder.sext(ArgVal, TargetType, name=f"sext_{TypedefName}_cast")
return Gen.builder.zext(ArgVal, TargetType, name=f"zext_{TypedefName}_cast")
elif ArgVal.type.width > TargetType.width:
return Gen.builder.trunc(ArgVal, TargetType, name=f"trunc_{TypedefName}_cast")
return ArgVal
@@ -1767,15 +1757,7 @@ class ExprCallHandle(BaseHandle):
if default_val.type != param_type:
if isinstance(param_type, ir.IntType) and isinstance(default_val.type, ir.IntType):
if default_val.type.width < param_type.width:
if default_val.type.width == 1:
# i1 是布尔值,无符号语义,必须 zext
default_val = Gen.builder.zext(default_val, param_type, name=f"zext_default_{i}")
else:
is_unsigned: bool = Gen._check_node_unsigned(default_node) or id(default_val) in Gen._unsigned_results
if is_unsigned:
default_val = Gen.builder.zext(default_val, param_type, name=f"zext_default_{i}")
else:
default_val = Gen.builder.sext(default_val, param_type, name=f"sext_default_{i}")
default_val = Gen.builder.zext(default_val, param_type, name=f"zext_default_{i}")
elif default_val.type.width > param_type.width:
default_val = Gen.builder.trunc(default_val, param_type, name=f"trunc_default_{i}")
elif isinstance(param_type, ir.PointerType) and isinstance(default_val.type, ir.IntType):
@@ -1844,16 +1826,7 @@ class ExprCallHandle(BaseHandle):
elif isinstance(arg.type, ir.PointerType) and isinstance(param_type, ir.IntType):
adjusted.append(Gen.builder.ptrtoint(arg, param_type))
elif isinstance(arg.type, ir.IntType) and arg.type.width < param_type.width:
if arg.type.width == 1:
# i1 是布尔值,无符号语义,必须 zext
adjusted.append(Gen.builder.zext(arg, param_type, name=f"zext_vararg_fixed_{i}"))
else:
arg_node = Node.args[i] if i < len(Node.args) else None
is_unsigned: bool = (arg_node is not None and Gen._check_node_unsigned(arg_node)) or id(arg) in Gen._unsigned_results
if is_unsigned:
adjusted.append(Gen.builder.zext(arg, param_type, name=f"zext_vararg_fixed_{i}"))
else:
adjusted.append(Gen.builder.sext(arg, param_type, name=f"sext_vararg_fixed_{i}"))
adjusted.append(Gen.builder.zext(arg, param_type))
elif isinstance(arg.type, ir.PointerType) and isinstance(param_type, ir.PointerType):
adjusted.append(Gen.builder.bitcast(arg, param_type, name=f"cast_arg_{i}"))
else:
@@ -2024,23 +1997,6 @@ class ExprCallHandle(BaseHandle):
else:
# 跨模块基类 — 查找基类的 sha1
base_sha1 = struct_sha1_map.get(base_name)
# 回退:若 _struct_sha1_map 未命中(普通类导入时不填充),
# 扫描 temp/ 下所有 .pyi 查找包含该基类定义的文件
if base_sha1 is None:
temp_dir = os.path.join(project_root, 'temp')
try:
pyi_files = os.listdir(temp_dir)
except OSError:
pyi_files = []
for pyi_file in pyi_files:
if not pyi_file.endswith('.pyi'):
continue
candidate_sha1 = pyi_file[:-4]
candidate_map = load_pyi(candidate_sha1)
if candidate_map and base_name in candidate_map:
base_sha1 = candidate_sha1
struct_sha1_map[base_name] = base_sha1
break
if base_sha1:
base_methods, base_cvtable, base_novtable, _ = collect_class_methods(base_name, base_sha1, visited)
if base_novtable:

View File

@@ -45,15 +45,7 @@ class ReturnHandle(BaseHandle):
if Val.type != ExpectedType:
if isinstance(ExpectedType, ir.IntType) and isinstance(Val.type, ir.IntType):
if Val.type.width < ExpectedType.width:
if Val.type.width == 1:
# i1 是布尔值,无符号语义,必须 zext
Val = Gen.builder.zext(Val, ExpectedType, name=f"zext_ret_{i}")
else:
is_unsigned: bool = Gen._check_node_unsigned(val) or id(Val) in Gen._unsigned_results
if is_unsigned:
Val = Gen.builder.zext(Val, ExpectedType, name=f"zext_ret_{i}")
else:
Val = Gen.builder.sext(Val, ExpectedType, name=f"sext_ret_{i}")
Val = Gen.builder.zext(Val, ExpectedType, name=f"zext_ret_{i}")
elif Val.type.width > ExpectedType.width:
Val = Gen.builder.trunc(Val, ExpectedType, name=f"trunc_ret_{i}")
elif isinstance(ExpectedType, ir.PointerType) and isinstance(Val.type, ir.PointerType):
@@ -115,15 +107,7 @@ class ReturnHandle(BaseHandle):
result = Gen.builder.insert_value(result, Val, j, name=f"ret_field_{j}")
elif isinstance(elem_type, ir.IntType) and isinstance(Val.type, ir.IntType):
if Val.type.width < elem_type.width:
if Val.type.width == 1:
# i1 是布尔值,无符号语义,必须 zext
Val = Gen.builder.zext(Val, elem_type, name=f"zext_ret_{j}")
else:
is_unsigned: bool = (Node.value is not None and Gen._check_node_unsigned(Node.value)) or id(Val) in Gen._unsigned_results
if is_unsigned:
Val = Gen.builder.zext(Val, elem_type, name=f"zext_ret_{j}")
else:
Val = Gen.builder.sext(Val, elem_type, name=f"sext_ret_{j}")
Val = Gen.builder.zext(Val, elem_type, name=f"zext_ret_{j}")
elif Val.type.width > elem_type.width:
Val = Gen.builder.trunc(Val, elem_type, name=f"trunc_ret_{j}")
result = Gen.builder.insert_value(result, Val, j, name=f"ret_field_{j}")

View File

@@ -292,6 +292,22 @@ class BaseGenMixin:
return existing
if clean_name in {'typedef', 'CType', 'CVolatile', 'CEnum', 'CUnion', 'CStruct', 'enum', 'REnum', 'renum', 'Void', 'void'}:
return ir.IntType(8)
# typing.Any 是"任意类型"标记,应解析为 i8*(通用指针),
# 而非创建为 opaque 结构体(否则包含 Any 字段的结构体会变成 unsized
if clean_name == 'Any':
return ir.IntType(8).as_pointer()
# t.CType 的基本类型子类CInt/CChar/CSizeT/CLong/CFloat/CDouble 等,
# position 含 BASE 且 Size>0有具体 LLVM 类型,应直接返回对应的
# ir.IntType/ir.FloatType/ir.DoubleType而非创建结构体。
# _is_ctype_marker_name 对这些类型返回 False不跳过需要在此处拦截。
_basic_llvm_type: ir.Type | None = self._try_resolve_ctype_basic(clean_name)
if _basic_llvm_type is not None:
return _basic_llvm_type
# t.CType 及其子类是"类型强转"标记,不应被编译为真实结构体。
# 动态检查 t 模块中所有 CType 子类名(排除 CStruct/CEnum/CUnion/REnum 子类,
# 因为用户定义的结构体类继承自它们,需要被创建为结构体)。
if self._is_ctype_marker_name(clean_name):
return ir.IntType(8)
if self.SymbolTable:
Entry: _CTypeInfo | None = self.SymbolTable.lookup(clean_name)
if Entry and Entry.IsTypedef:
@@ -409,8 +425,93 @@ class BaseGenMixin:
pass
return 0 # 标记为 typedef但位宽为 0非整数
# t.CType 及其子类是"类型强转"标记,不应被创建为结构体。
# 动态检查 t 模块中所有 CType 子类名(排除 CStruct/CEnum/CUnion/REnum 子类)。
# 返回 0 标记为 typedef使 _get_or_create_struct 走 typedef 路径返回 i8。
if self._is_ctype_marker_name(name):
return 0
return None
@staticmethod
def _is_ctype_marker_name(name: str) -> bool:
"""检查名称是否是 t.CType 的"类型强转"标记子类名。
只有 position 不含 BASE 的纯修饰符/标记类型CPtr/CVolatile/CConst/
CInline/CStatic/CExtern/CExport/CRegister/CAuto/_CTypedef/CTypeDefault 等)
才应该跳过结构体创建。有 BASE position 的基本类型CInt/CChar/CSizeT/
CLong/CFloat/CDouble 等)有具体大小,应被正常解析为对应宽度的整数/浮点。
CStruct/CEnum/CUnion/REnum 的用户子类是合法结构体,需要被创建。
注意CTypeRegistry.GetClassByName 会跳过 CType 本身和 CTypeDefault
所以这里直接用 getattr(t, name) 检查 t 模块属性。
Returns:
True 如果 name 是 CType 标记子类名(应跳过结构体创建)
"""
if not name:
return False
# 去除可能的 SHA1 前缀(如 "abc123.CPtr" -> "CPtr"
short_name: str = name.split('.')[-1] if '.' in name else name
# 直接查 t 模块属性CTypeRegistry._build 会跳过 CType/CTypeDefault/BigEndian/LittleEndian
t_cls: Any = getattr(_t, short_name, None)
if not isinstance(t_cls, type) or not issubclass(t_cls, _t.CType):
return False
# 排除 CStruct/CEnum/CUnion/REnum 子类(它们是命名类型的基类,
# 用户定义的结构体继承自它们,需要被创建为结构体)
if issubclass(t_cls, (_t.CStruct, _t.CEnum, _t.REnum, _t.CUnion)):
return False
# 基本类型position 含 BASE 且 Size > 0有具体大小不应跳过
# CInt→i32, CChar→i8, CSizeT→i64, CLong→i64, CFloat→f32 等)
# CVoid 虽含 BASE 但 Size=0CType Size=None仍需跳过
if _t.CType.BASE in t_cls.position:
# 检查实例的 Size类属性可能未设置用实例获取
try:
inst = t_cls()
size_val = getattr(inst, 'Size', None)
if size_val is not None and size_val > 0:
return False
except Exception:
pass
return True
def _try_resolve_ctype_basic(self, name: str) -> ir.Type | None:
"""尝试将 t.CType 的基本类型子类名解析为对应的 LLVM 基本类型。
仅对 t 模块内的 CType 基本类型子类CInt/CChar/CSizeT/CLong/CFloat/
CDouble 等,即 position 含 BASE 且 Size>0生效返回对应的
ir.IntType/ir.FloatType/ir.DoubleType。
CStruct/CEnum/CUnion/REnum 子类不在此处理(用户自定义结构体需要被
创建为结构体。CVoid/CType/CPtr 等无 Size 或 Size=0 的类型也不在此
处理(应通过 _is_ctype_marker_name 跳过结构体创建)。
Returns:
对应的 ir.Type或 None 表示不是基本类型,需要继续走结构体创建路径。
"""
if not name:
return None
short_name: str = name.split('.')[-1] if '.' in name else name
cls: Any = getattr(_t, short_name, None)
if not isinstance(cls, type) or not issubclass(cls, _t.CType):
return None
if issubclass(cls, (_t.CStruct, _t.CEnum, _t.REnum, _t.CUnion)):
return None
if _t.CType.BASE not in getattr(cls, 'position', frozenset()):
return None
try:
inst = cls()
size_val = getattr(inst, 'Size', None)
if size_val is None or size_val <= 0:
return None
except Exception:
return None
llvm_str: str | None = CTypeRegistry.NameToLLVM(short_name)
if not llvm_str:
return None
return self._type_str_to_llvm(llvm_str)
def _set_node_info(self, node: ast.AST, extra_info: str = "") -> None:
if hasattr(node, 'lineno'):
self._current_lineno = node.lineno