修正了一些错误
This commit is contained in:
@@ -205,6 +205,15 @@ class ClassHandle(BaseHandle):
|
||||
saved_block: ir.Block | None = None
|
||||
if Gen.builder and Gen.builder.block and not Gen.builder.block.is_terminated:
|
||||
saved_block = Gen.builder.block
|
||||
# 切换 module_sha1 为泛型模板定义模块的 SHA1,
|
||||
# 使结构体类型名和方法定义名都用定义模块的 SHA1 前缀,
|
||||
# 与调用端 _struct_sha1_map 查到的 SHA1 一致。
|
||||
template_sha1: str | None = template.get('sha1')
|
||||
saved_gen_sha1: str | None = getattr(Gen, 'module_sha1', None)
|
||||
saved_trans_sha1: str | None = getattr(self.Trans, '_module_sha1', None)
|
||||
if template_sha1:
|
||||
Gen.module_sha1 = template_sha1
|
||||
self.Trans._module_sha1 = template_sha1
|
||||
try:
|
||||
self._EmitClassLlvm(SpecNode, Gen, declare_only=declare_only)
|
||||
finally:
|
||||
@@ -219,6 +228,9 @@ class ClassHandle(BaseHandle):
|
||||
Gen.var_signedness = saved_var_signedness
|
||||
Gen.global_vars = saved_global_vars
|
||||
self.Trans.VarScopes = saved_var_scopes
|
||||
# 恢复原始 module_sha1
|
||||
Gen.module_sha1 = saved_gen_sha1
|
||||
self.Trans._module_sha1 = saved_trans_sha1
|
||||
Gen._generic_class_specializations[spec_key] = (spec_name, declare_only)
|
||||
# 缓存 type_args/type_names,供后续 declare_only=False 完整特化补发方法体使用
|
||||
# (如 _HandleMethodCallLlvm 中发现方法未定义时触发)
|
||||
@@ -228,7 +240,10 @@ class ClassHandle(BaseHandle):
|
||||
if not hasattr(self.Trans, '_generic_class_specializations'):
|
||||
self.Trans._generic_class_specializations = {}
|
||||
self.Trans._generic_class_specializations[spec_key] = spec_name
|
||||
if hasattr(self.Trans, '_module_sha1') and self.Trans._module_sha1:
|
||||
# 用模板定义模块的 SHA1 注册到 _struct_sha1_map,与方法定义端一致
|
||||
if template_sha1:
|
||||
Gen._struct_sha1_map[spec_name] = template_sha1
|
||||
elif hasattr(self.Trans, '_module_sha1') and self.Trans._module_sha1:
|
||||
Gen._struct_sha1_map[spec_name] = self.Trans._module_sha1
|
||||
return spec_name
|
||||
|
||||
@@ -460,9 +475,12 @@ class ClassHandle(BaseHandle):
|
||||
if not hasattr(self, '_generic_class_templates'):
|
||||
self._generic_class_templates = {}
|
||||
type_params: list[str] = [tp.name for tp in Node.type_params]
|
||||
# 记录泛型模板定义模块的 SHA1,用于特化时统一命名空间
|
||||
template_sha1: str | None = getattr(self.Trans, '_module_sha1', None)
|
||||
self._generic_class_templates[ClassName] = {
|
||||
'node': Node,
|
||||
'type_params': type_params,
|
||||
'sha1': template_sha1,
|
||||
}
|
||||
return
|
||||
if self._is_exception_class(Node):
|
||||
|
||||
@@ -7,6 +7,13 @@ from lib.core.Handles.HandlesBase import BaseHandle, FuncMeta
|
||||
import ast
|
||||
import llvmlite.ir as ir
|
||||
|
||||
# [CDF-LOAD] 模块加载标记:用于确认修复后的代码被实际加载
|
||||
try:
|
||||
with open('d:/Users/TermiNexus/Desktop/TransPyC/_attr_debug.log', 'a', encoding='utf-8') as _f:
|
||||
_f.write('[CDF-LOAD] HandlesExprAttr.py loaded (with CDefine fix)\n')
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
||||
class ExprAttrHandle(BaseHandle):
|
||||
|
||||
@@ -174,25 +181,44 @@ class ExprAttrHandle(BaseHandle):
|
||||
return None
|
||||
|
||||
def _lookup_cdefine(self, Gen: LlvmCodeGenerator, VarName: str, AttrName: str) -> ir.Value | None:
|
||||
"""在符号表和模块中查找 CDefine 常量值"""
|
||||
imported_modules: Any = getattr(self.Trans, '_ImportedModules', None)
|
||||
if not imported_modules:
|
||||
return None
|
||||
"""在符号表和模块中查找 CDefine 常量值
|
||||
|
||||
注意:不再强制依赖 _ImportedModules。即使该集合为空(例如自举编译
|
||||
阶段尚未填充),也始终检查符号表与 Gen._define_constants,确保
|
||||
ast.CONST_INT 这类 CDefine 常量能够被解析为立即数而非全局变量引用。
|
||||
"""
|
||||
PossibleKeys: list[str] = [f"{VarName}.{AttrName}", AttrName]
|
||||
for mod_name in imported_modules:
|
||||
if mod_name.endswith(f".{VarName}") or mod_name == VarName:
|
||||
key: str = f"{mod_name}.{AttrName}"
|
||||
if key not in PossibleKeys:
|
||||
PossibleKeys.append(key)
|
||||
imported_modules: Any = getattr(self.Trans, '_ImportedModules', None)
|
||||
if imported_modules:
|
||||
for mod_name in imported_modules:
|
||||
if mod_name.endswith(f".{VarName}") or mod_name == VarName:
|
||||
key: str = f"{mod_name}.{AttrName}"
|
||||
if key not in PossibleKeys:
|
||||
PossibleKeys.append(key)
|
||||
# 始终遍历符号表(不依赖 imported_modules 是否为空)
|
||||
for lookup_key in PossibleKeys:
|
||||
SymInfo: Any = self.Trans.SymbolTable.lookup(lookup_key)
|
||||
if SymInfo and SymInfo.IsDefine and SymInfo.DefineValue is not None:
|
||||
return self._make_define_constant(Gen, SymInfo.DefineValue)
|
||||
# 也检查 _define_constants
|
||||
# 也检查 _define_constants(LlvmGenerator 预扫描阶段填充)
|
||||
define_constants: Any = getattr(Gen, '_define_constants', {})
|
||||
for key in (f"{VarName}.{AttrName}", AttrName):
|
||||
if key in define_constants:
|
||||
return self._make_define_constant(Gen, define_constants[key])
|
||||
# [CDF-DBG] CDefine 查找失败时的诊断输出
|
||||
if AttrName in ('CONST_INT', 'CONST_FLOAT', 'CONST_STR', 'CONST_BOOL', 'CONST_NONE'):
|
||||
_dbg_keys: list[str] = []
|
||||
for _k in PossibleKeys:
|
||||
_si: Any = self.Trans.SymbolTable.lookup(_k)
|
||||
_dbg_keys.append(f"{_k}=>si={_si is not None},isdef={getattr(_si, 'IsDefine', None)},dv={getattr(_si, 'DefineValue', None)}")
|
||||
_dc_keys: list[str] = [f"{k}=>{define_constants.get(k, '<miss>')}" for k in (f"{VarName}.{AttrName}", AttrName)]
|
||||
try:
|
||||
with open('d:/Users/TermiNexus/Desktop/TransPyC/_attr_debug.log', 'a', encoding='utf-8') as _f:
|
||||
_f.write(f"[CDF-DBG] miss VarName={VarName} AttrName={AttrName} imported_modules={imported_modules}\n")
|
||||
_f.write(f"[CDF-DBG] sym_keys={_dbg_keys}\n")
|
||||
_f.write(f"[CDF-DBG] dc_keys={_dc_keys}\n")
|
||||
except Exception:
|
||||
pass
|
||||
return None
|
||||
|
||||
def _lookup_module_global(self, Gen: LlvmCodeGenerator, VarName: str, AttrName: str) -> ir.Value | None:
|
||||
@@ -394,6 +420,18 @@ class ExprAttrHandle(BaseHandle):
|
||||
Gen: LlvmCodeGenerator = self.Trans.LlvmGen
|
||||
AttrName: str = Node.attr
|
||||
|
||||
# [HAN-DBG] 入口诊断:标记 CONST_* 属性访问
|
||||
if AttrName in ('CONST_INT', 'CONST_FLOAT', 'CONST_STR', 'CONST_BOOL', 'CONST_NONE'):
|
||||
_in_globals: bool = AttrName in Gen.module.globals
|
||||
_gv_type: Any = None
|
||||
if _in_globals:
|
||||
_gv_type = str(Gen.module.globals[AttrName].type)
|
||||
try:
|
||||
with open('d:/Users/TermiNexus/Desktop/TransPyC/_attr_debug.log', 'a', encoding='utf-8') as _f:
|
||||
_f.write(f"[HAN-DBG] enter VarName={VarName} AttrName={AttrName} in_globals={_in_globals} gv_type={_gv_type}\n")
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# __doc__ 魔法字符串:函数/结构体的 docstring
|
||||
if AttrName == '__doc__':
|
||||
doc_ptr: ir.Value | None = Gen._get_doc_ptr(VarName)
|
||||
@@ -410,9 +448,26 @@ class ExprAttrHandle(BaseHandle):
|
||||
if result is not None:
|
||||
return result
|
||||
|
||||
# 冗余回退:直接以短名/全名查符号表的 CDefine 条目
|
||||
# 覆盖 _ImportedModules 未填充但符号表已注册 CDefine 的场景
|
||||
# (例如自举编译期 ast.CONST_INT 在 LlvmGenerator 预扫描阶段
|
||||
# 已注册到 SymbolTable,但 _ImportedModules 仍为空)。
|
||||
for _cdefine_key in (AttrName, f"{VarName}.{AttrName}"):
|
||||
_sym: Any = self.Trans.SymbolTable.lookup(_cdefine_key)
|
||||
if _sym and _sym.IsDefine and _sym.DefineValue is not None:
|
||||
_const_val: Any = self._make_define_constant(Gen, _sym.DefineValue)
|
||||
if _const_val is not None:
|
||||
return _const_val
|
||||
|
||||
# 尝试 import 模块全局变量
|
||||
result = self._lookup_module_global(Gen, VarName, AttrName)
|
||||
if result is not None:
|
||||
if AttrName in ('CONST_INT', 'CONST_FLOAT', 'CONST_STR', 'CONST_BOOL', 'CONST_NONE'):
|
||||
try:
|
||||
with open('d:/Users/TermiNexus/Desktop/TransPyC/_attr_debug.log', 'a', encoding='utf-8') as _f:
|
||||
_f.write(f"[HAN-DBG] module_global HIT VarName={VarName} AttrName={AttrName} result_type={result.type}\n")
|
||||
except Exception:
|
||||
pass
|
||||
return result
|
||||
|
||||
# FakeDuck: 检查是否有影子结构体 a__meta__ (str 变量的 per-instance 字段存储)
|
||||
@@ -433,6 +488,12 @@ class ExprAttrHandle(BaseHandle):
|
||||
# 尝试 attr 直接作为全局变量(仅当 VarName 不是结构体变量时)
|
||||
if not ClassName and AttrName in Gen.module.globals:
|
||||
gv: Any = Gen.module.globals[AttrName]
|
||||
if AttrName in ('CONST_INT', 'CONST_FLOAT', 'CONST_STR', 'CONST_BOOL', 'CONST_NONE'):
|
||||
try:
|
||||
with open('d:/Users/TermiNexus/Desktop/TransPyC/_attr_debug.log', 'a', encoding='utf-8') as _f:
|
||||
_f.write(f"[HAN-DBG] FALLBACK_TO_GLOBAL VarName={VarName} AttrName={AttrName} gv_type={gv.type}\n")
|
||||
except Exception:
|
||||
pass
|
||||
if AttrName in Gen.variables and Gen.variables[AttrName] is None:
|
||||
str_gv_name: str = AttrName + '_str'
|
||||
if str_gv_name in Gen.module.globals:
|
||||
@@ -838,6 +899,20 @@ class ExprAttrHandle(BaseHandle):
|
||||
def _HandleAttributeLlvm(self, Node: ast.Attribute) -> ir.Value | None:
|
||||
Gen: LlvmCodeGenerator = self.Trans.LlvmGen
|
||||
|
||||
# [ATTR-DBG] 入口诊断:标记 CONST_* 属性访问的派发路径
|
||||
if Node.attr in ('CONST_INT', 'CONST_FLOAT', 'CONST_STR', 'CONST_BOOL', 'CONST_NONE'):
|
||||
_val_kind: str = type(Node.value).__name__
|
||||
_val_id: str = ''
|
||||
if isinstance(Node.value, ast.Name):
|
||||
_val_id = Node.value.id
|
||||
elif isinstance(Node.value, ast.Attribute):
|
||||
_val_id = f"<Attribute attr={Node.value.attr}>"
|
||||
try:
|
||||
with open('d:/Users/TermiNexus/Desktop/TransPyC/_attr_debug.log', 'a', encoding='utf-8') as _f:
|
||||
_f.write(f"[ATTR-DBG] dispatch Node.attr={Node.attr} value_kind={_val_kind} value_id={_val_id}\n")
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
if isinstance(Node.value, ast.Name):
|
||||
VarName: str = Node.value.id
|
||||
# 处理 t/c import 的别名重定向
|
||||
@@ -846,6 +921,12 @@ class ExprAttrHandle(BaseHandle):
|
||||
src_module: str
|
||||
src_name: str
|
||||
src_module, src_name = t_c_imported[VarName]
|
||||
if Node.attr in ('CONST_INT', 'CONST_FLOAT', 'CONST_STR', 'CONST_BOOL', 'CONST_NONE'):
|
||||
try:
|
||||
with open('d:/Users/TermiNexus/Desktop/TransPyC/_attr_debug.log', 'a', encoding='utf-8') as _f:
|
||||
_f.write(f"[ATTR-DBG] REDIRECT VarName={VarName} -> src_module={src_module} src_name={src_name}\n")
|
||||
except Exception:
|
||||
pass
|
||||
virtual_attr: ast.Attribute = ast.Attribute(
|
||||
value=ast.Name(id=src_module, ctx=ast.Load()),
|
||||
attr=src_name, ctx=ast.Load()
|
||||
@@ -1388,10 +1469,13 @@ class ExprAttrHandle(BaseHandle):
|
||||
return parts
|
||||
|
||||
def _try_resolve_nested_cdefine(self, Node: ast.Attribute) -> ir.Value | None:
|
||||
"""尝试解析嵌套属性路径上的 CDefine 常量
|
||||
|
||||
注意:不再强制依赖 _ImportedModules。即使该集合为空(如自举编译
|
||||
早期阶段),也始终构建属性路径并检查符号表,确保 ast.CONST_INT
|
||||
这类跨模块 CDefine 常量可被解析为立即数。
|
||||
"""
|
||||
Gen: LlvmCodeGenerator = self.Trans.LlvmGen
|
||||
imported_modules: Any = getattr(self.Trans, '_ImportedModules', None)
|
||||
if not imported_modules:
|
||||
return None
|
||||
parts: list[str] = self._build_attr_path(Node)
|
||||
if len(parts) < 2:
|
||||
return None
|
||||
@@ -1400,6 +1484,7 @@ class ExprAttrHandle(BaseHandle):
|
||||
possible_keys: list[str] = [attr_name]
|
||||
full_path: str = '.'.join(parts)
|
||||
possible_keys.append(full_path)
|
||||
imported_modules: Any = getattr(self.Trans, '_ImportedModules', None)
|
||||
if module_parts:
|
||||
ModulePath: str = '.'.join(module_parts)
|
||||
resolved_first: str = self.Trans.SymbolTable.resolve_alias(module_parts[0])
|
||||
@@ -1407,15 +1492,16 @@ class ExprAttrHandle(BaseHandle):
|
||||
resolved_parts: list[str] = [resolved_first] + module_parts[1:]
|
||||
resolved_path: str = '.'.join(resolved_parts)
|
||||
possible_keys.append(f"{resolved_path}.{attr_name}")
|
||||
for mod_name in imported_modules:
|
||||
if mod_name.endswith('.' + ModulePath) or mod_name == ModulePath:
|
||||
key: str = f"{mod_name}.{attr_name}"
|
||||
if key not in possible_keys:
|
||||
possible_keys.append(key)
|
||||
if module_parts and (mod_name.endswith('.' + module_parts[-1]) or mod_name == module_parts[-1]):
|
||||
key = f"{mod_name}.{attr_name}"
|
||||
if key not in possible_keys:
|
||||
possible_keys.append(key)
|
||||
if imported_modules:
|
||||
for mod_name in imported_modules:
|
||||
if mod_name.endswith('.' + ModulePath) or mod_name == ModulePath:
|
||||
key: str = f"{mod_name}.{attr_name}"
|
||||
if key not in possible_keys:
|
||||
possible_keys.append(key)
|
||||
if module_parts and (mod_name.endswith('.' + module_parts[-1]) or mod_name == module_parts[-1]):
|
||||
key = f"{mod_name}.{attr_name}"
|
||||
if key not in possible_keys:
|
||||
possible_keys.append(key)
|
||||
for lookup_key in possible_keys:
|
||||
SymInfo: Any = self.Trans.SymbolTable.lookup(lookup_key)
|
||||
if SymInfo and SymInfo.IsDefine and SymInfo.DefineValue is not None:
|
||||
@@ -1426,6 +1512,17 @@ class ExprAttrHandle(BaseHandle):
|
||||
return ir.Constant(ir.IntType(32), val)
|
||||
elif isinstance(val, float):
|
||||
return ir.Constant(ir.FloatType(), val)
|
||||
# 回退:检查 Gen._define_constants(LlvmGenerator 预扫描阶段填充)
|
||||
define_constants: Any = getattr(Gen, '_define_constants', {})
|
||||
for key in (attr_name, full_path):
|
||||
if key in define_constants:
|
||||
val: Any = define_constants[key]
|
||||
if isinstance(val, int):
|
||||
if val > 0x7FFFFFFF or val < -0x80000000:
|
||||
return ir.Constant(ir.IntType(64), val & 0xFFFFFFFFFFFFFFFF)
|
||||
return ir.Constant(ir.IntType(32), val)
|
||||
elif isinstance(val, float):
|
||||
return ir.Constant(ir.FloatType(), val)
|
||||
return None
|
||||
|
||||
def _try_resolve_cross_module_enum(self, module_alias: str, enum_class_name: str, member_name: str) -> ir.Value | None:
|
||||
|
||||
@@ -1562,30 +1562,127 @@ class ExprCallHandle(BaseHandle):
|
||||
if not Node.args:
|
||||
return None
|
||||
type_info = None
|
||||
MergeException = None
|
||||
try:
|
||||
type_info = getattr(self.Trans, 'TypeMergeHandler', None) and self.Trans.TypeMergeHandler.MergeTypes(Node.func)
|
||||
except Exception as _e:
|
||||
MergeException = _e
|
||||
if _config_mode == "strict":
|
||||
raise
|
||||
_vlog().warning(f"解析类型失败: {_e}", "Exception")
|
||||
if not isinstance(type_info, CTypeInfo):
|
||||
return None
|
||||
target_type_str = type_info.ToString()
|
||||
IsPtr = type_info.IsPtr
|
||||
if IsPtr and target_type_str and '*' not in target_type_str:
|
||||
target_type_str += ' *'
|
||||
if not target_type_str:
|
||||
return None
|
||||
if type_info.IsPtr and not IsPtr:
|
||||
IsPtr = True
|
||||
if '*' not in target_type_str:
|
||||
if isinstance(type_info, CTypeInfo):
|
||||
# 主路径:MergeTypes 成功返回 CTypeInfo,沿用原有逻辑生成类型字符串
|
||||
target_type_str = type_info.ToString()
|
||||
IsPtr = type_info.IsPtr
|
||||
if IsPtr and target_type_str and '*' not in target_type_str:
|
||||
target_type_str += ' *'
|
||||
if isinstance(type_info.Storage, t.CExport) or isinstance(type_info.Storage, t.CExtern):
|
||||
pass
|
||||
if type_info.IsState:
|
||||
Gen._export_funcs.add('_type_union_cast')
|
||||
if not target_type_str:
|
||||
# Fallback:ToString 返回空字符串时,尝试手动从 BinOp 提取类型字符串
|
||||
_vlog().warning(
|
||||
f"_HandleTypeUnionCastLlvm: ToString 返回空字符串,启用 fallback 手动解析 "
|
||||
f"(type_info={type_info!r})"
|
||||
)
|
||||
target_type_str = self._ExtractTypeStrFromUnionBinOp(Node.func)
|
||||
if target_type_str and type_info.IsPtr and not IsPtr:
|
||||
if '*' not in target_type_str:
|
||||
target_type_str += ' *'
|
||||
if isinstance(type_info.Storage, t.CExport) or isinstance(type_info.Storage, t.CExtern):
|
||||
pass
|
||||
if type_info.IsState:
|
||||
Gen._export_funcs.add('_type_union_cast')
|
||||
else:
|
||||
# Fallback 路径:MergeTypes 失败(返回 None 或抛异常)时,手动从 BinOp 提取类型信息
|
||||
# 处理 (BaseType | t.CPtr) 这种模式,手动解析为 "{BaseType} *"
|
||||
_vlog().warning(
|
||||
f"_HandleTypeUnionCastLlvm: MergeTypes 未返回 CTypeInfo "
|
||||
f"(type_info={type_info!r}, exception={MergeException!r}),启用 fallback 手动解析"
|
||||
)
|
||||
target_type_str = self._ExtractTypeStrFromUnionBinOp(Node.func)
|
||||
if not target_type_str:
|
||||
# Fallback 也无法解析:记录详细诊断信息后返回 None
|
||||
_vlog().warning(
|
||||
f"_HandleTypeUnionCastLlvm: fallback 解析失败,无法确定目标类型 "
|
||||
f"(Node.func={ast.dump(Node.func)})"
|
||||
)
|
||||
return None
|
||||
return self._HandleTypeCastLlvm(Node.args[0], target_type_str)
|
||||
|
||||
def _ExtractTypeStrFromUnionBinOp(self, NodeFunc: ast.AST) -> str | None:
|
||||
"""Fallback:从类型联合 BinOp 手动提取类型字符串。
|
||||
|
||||
处理 (BaseType | t.CPtr) 这种模式,手动解析为 "{BaseType} *"。
|
||||
支持嵌套的 | 操作(如 (t.CInt | t.CPtr) | t.CStatic)。
|
||||
|
||||
策略:
|
||||
- 递归展平所有 | 操作数
|
||||
- t.CPtr 视为指针修饰符(生成 "{BaseType} *" 格式)
|
||||
- 其他 CType 子类作为基础类型(取第一个)
|
||||
- 跳过存储类/限定符修饰符(CExport/CExtern/CStatic/CConst/CVolatile/CInline 等)
|
||||
"""
|
||||
if not isinstance(NodeFunc, ast.BinOp) or not isinstance(NodeFunc.op, ast.BitOr):
|
||||
return None
|
||||
|
||||
# 存储类/限定符/修饰符类型名集合:这些类型在类型联合中只起修饰作用,
|
||||
# 不是基础类型,应跳过(参考 HandlesTypeMerge._GetCTypeInfoInternal 的分类逻辑)
|
||||
StorageQualifierNames = {
|
||||
'CArrayPtr', 'CConst', 'CVolatile', 'CInline',
|
||||
'CStatic', 'CExtern', 'CExport', 'CAuto', 'CRegister',
|
||||
'CDefine', 'CPass', 'CTypeDefault', 'State',
|
||||
'BigEndian', 'LittleEndian',
|
||||
}
|
||||
|
||||
# 递归展平所有 | 操作数
|
||||
Operands = []
|
||||
|
||||
def CollectOperands(node: ast.AST) -> None:
|
||||
if isinstance(node, ast.BinOp) and isinstance(node.op, ast.BitOr):
|
||||
CollectOperands(node.left)
|
||||
CollectOperands(node.right)
|
||||
else:
|
||||
Operands.append(node)
|
||||
|
||||
CollectOperands(NodeFunc)
|
||||
|
||||
HasCPtr = False # 是否包含 t.CPtr(指针修饰符)
|
||||
BaseTypeName = None # 基础类型名(如 "CInt"、"CChar")
|
||||
|
||||
for Operand in Operands:
|
||||
AttrName = None
|
||||
if isinstance(Operand, ast.Attribute):
|
||||
AttrName = Operand.attr
|
||||
elif isinstance(Operand, ast.Name):
|
||||
AttrName = Operand.id
|
||||
else:
|
||||
continue
|
||||
|
||||
# t.CPtr 是指针修饰符,单独处理(增加一层 *)
|
||||
if AttrName == 'CPtr':
|
||||
HasCPtr = True
|
||||
continue
|
||||
|
||||
# 跳过存储类/限定符/修饰符类型,它们不是基础类型
|
||||
if AttrName in StorageQualifierNames:
|
||||
continue
|
||||
|
||||
# 通过 t 模块获取类型类,验证是否为 CType 子类
|
||||
TypeClass = getattr(t, AttrName, None)
|
||||
if not (isinstance(TypeClass, type) and issubclass(TypeClass, t.CType)):
|
||||
# 非 CType 类,跳过
|
||||
continue
|
||||
|
||||
# 记录第一个非 CPtr 基础类型
|
||||
if BaseTypeName is None:
|
||||
BaseTypeName = AttrName
|
||||
|
||||
if not BaseTypeName:
|
||||
return None
|
||||
|
||||
# 包含 t.CPtr 时,生成 "{BaseType} *" 格式
|
||||
# _CType2LLVM 已验证能解析 "CInt *" → i32*(ir.PointerType(ir.IntType(32)))
|
||||
if HasCPtr:
|
||||
return f"{BaseTypeName} *"
|
||||
return BaseTypeName
|
||||
|
||||
def _HandleTypeCastLlvm(self, expr_node: ast.AST, target_type_str: str) -> ir.Value | None:
|
||||
Gen = self.Trans.LlvmGen
|
||||
val = self.HandleExprLlvm(expr_node)
|
||||
|
||||
@@ -336,6 +336,19 @@ class ExprOpsHandle(BaseHandle):
|
||||
}
|
||||
result: bool = cmp_map.get(ComparatorSymbol, False)
|
||||
return ir.Constant(ir.IntType(1), 1 if result else 0)
|
||||
# is / is not: 值类型(IntType)与 None(空指针常量)比较
|
||||
# 值类型(如 i8/i32)永远不可能为 None,因此:
|
||||
# - 值类型 is None → 恒为 false (i1 0)
|
||||
# - 值类型 is not None → 恒为 true (i1 1)
|
||||
# 此检查必须在类型对齐之前,否则类型对齐会对 i8* null 执行 load(空指针解引用)导致崩溃
|
||||
if ComparatorSymbol in ('is', 'is not'):
|
||||
LeftIsNullPtr: bool = isinstance(LeftVal, ir.Constant) and LeftVal.constant is None and isinstance(LeftVal.type, ir.PointerType)
|
||||
RightIsNullPtr: bool = isinstance(RightVal, ir.Constant) and RightVal.constant is None and isinstance(RightVal.type, ir.PointerType)
|
||||
LeftIsValueType: bool = isinstance(LeftVal.type, ir.IntType)
|
||||
RightIsValueType: bool = isinstance(RightVal.type, ir.IntType)
|
||||
if (LeftIsValueType and RightIsNullPtr) or (RightIsValueType and LeftIsNullPtr):
|
||||
IsNotResult: int = 1 if ComparatorSymbol == 'is not' else 0
|
||||
return ir.Constant(ir.IntType(1), IsNotResult)
|
||||
if isinstance(LeftVal.type, ir.IntType) and isinstance(RightVal.type, ir.IntType):
|
||||
if LeftVal.type.width < RightVal.type.width:
|
||||
# 如果宽类型常量值超出窄类型有符号范围,则必须用zext
|
||||
|
||||
@@ -356,9 +356,21 @@ class ImportHandle(BaseHandle):
|
||||
if not hasattr(self.Trans.ClassHandler, '_generic_class_templates'):
|
||||
self.Trans.ClassHandler._generic_class_templates = {}
|
||||
type_params = [tp.name for tp in node.type_params]
|
||||
# 保留 prescan 阶段已注册的 sha1;若无则从 _ModuleSha1Map 查找,
|
||||
# 避免覆盖带 sha1 的注册导致特化时 SHA1 前缀丢失
|
||||
existing = self.Trans.ClassHandler._generic_class_templates.get(node.name)
|
||||
template_sha1 = existing.get('sha1') if existing else None
|
||||
if template_sha1 is None:
|
||||
msm = getattr(self.Trans, '_ModuleSha1Map', None)
|
||||
if msm:
|
||||
for lookup_name in (file_module_name, module_name, actual_module_name):
|
||||
if lookup_name and lookup_name in msm:
|
||||
template_sha1 = msm[lookup_name]
|
||||
break
|
||||
self.Trans.ClassHandler._generic_class_templates[node.name] = {
|
||||
'node': node,
|
||||
'type_params': type_params,
|
||||
'sha1': template_sha1,
|
||||
}
|
||||
# 治本修复:使用 file_module_name(源模块名)而非 module_name(可能是别名/类名)。
|
||||
# 这样 _EmitExternalClassDeclLlvm 内的 ModuleSha1Map 查找才能命中,
|
||||
@@ -647,9 +659,18 @@ class ImportHandle(BaseHandle):
|
||||
if not hasattr(self.Trans.ClassHandler, '_generic_class_templates'):
|
||||
self.Trans.ClassHandler._generic_class_templates = {}
|
||||
type_params = [tp.name for tp in node.type_params]
|
||||
# 保留 prescan 阶段已注册的 sha1;若无则从 _ModuleSha1Map 查找,
|
||||
# 避免覆盖带 sha1 的注册导致特化时 SHA1 前缀丢失
|
||||
existing = self.Trans.ClassHandler._generic_class_templates.get(node.name)
|
||||
template_sha1 = existing.get('sha1') if existing else None
|
||||
if template_sha1 is None:
|
||||
msm = getattr(self.Trans, '_ModuleSha1Map', None)
|
||||
if msm and module_name in msm:
|
||||
template_sha1 = msm[module_name]
|
||||
self.Trans.ClassHandler._generic_class_templates[node.name] = {
|
||||
'node': node,
|
||||
'type_params': type_params,
|
||||
'sha1': template_sha1,
|
||||
}
|
||||
self._EmitExternalClassDeclLlvm(node, Gen, module_name=module_name)
|
||||
has_functions_or_classes = True
|
||||
|
||||
Reference in New Issue
Block a user