尝试进行 Qt 测试,增加了 AI 人机调试工具 _console,以及 TransPyV 进行修正
This commit is contained in:
@@ -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):
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 基类本身无 bases,base 检测无法触发,
|
||||
需要直接按类名检查。
|
||||
|
||||
注意: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=0,CType 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 基类本身无 bases,base 检测无法触发,
|
||||
# 此处在方法入口直接按类名跳过。
|
||||
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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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])
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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}")
|
||||
|
||||
@@ -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=0,CType 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
|
||||
|
||||
Reference in New Issue
Block a user