可用的回归测试通过的标准版本

This commit is contained in:
2026-06-18 00:39:43 +08:00
parent bffb0cb6b7
commit e02c867edf
365 changed files with 22562 additions and 24532 deletions

View File

@@ -48,9 +48,9 @@ class ExprCallHandle(BaseHandle):
elif arg.name == '__eh_code_out__' and eh_code_ptr is None:
eh_code_ptr = arg
if eh_msg_ptr is None:
eh_msg_ptr = Gen._alloca_entry(ir.PointerType(ir.IntType(8)), name="eh_msg_out_null")
eh_msg_ptr = Gen._allocaEntry(ir.PointerType(ir.IntType(8)), name="eh_msg_out_null")
if eh_code_ptr is None:
eh_code_ptr = Gen._alloca_entry(ir.IntType(32), name="eh_code_out_null")
eh_code_ptr = Gen._allocaEntry(ir.IntType(32), name="eh_code_out_null")
Gen._store(ir.Constant(ir.PointerType(ir.IntType(8)), None), eh_msg_ptr)
Gen._store(ir.Constant(ir.IntType(32), 0), eh_code_ptr)
CallArgs.append(eh_msg_ptr)
@@ -83,7 +83,7 @@ class ExprCallHandle(BaseHandle):
elif arg.name == '__eh_code_out__' and eh_code_ptr is None:
eh_code_ptr = arg
if eh_msg_ptr is not None:
eh_msg_val = Gen._load(eh_msg_ptr, name=f"load_eh_msg_{func_name}")
eh_msg_val = Gen._load(eh_msg_ptr, name=f"Load_eh_msg_{func_name}")
null_ptr = ir.Constant(ir.PointerType(ir.IntType(8)), None)
is_error = Gen.builder.icmp_signed('!=', eh_msg_val, null_ptr, name=f"check_eh_msg_{func_name}")
OkBB = Gen.func.append_basic_block(name=f"ok_after_{func_name}")
@@ -114,7 +114,7 @@ class ExprCallHandle(BaseHandle):
ExceptBB, _, exception_code, _ = Gen.eh_except_block_stack[-1]
if ExceptBB is not None:
if has_eh_code_out and eh_code_ptr is not None:
eh_code_val = Gen._load(eh_code_ptr, name=f"load_eh_code_{func_name}")
eh_code_val = Gen._load(eh_code_ptr, name=f"Load_eh_code_{func_name}")
Gen._store(eh_code_val, exception_code)
else:
Gen._store(ir.Constant(ir.IntType(32), 1), exception_code)
@@ -199,8 +199,8 @@ class ExprCallHandle(BaseHandle):
def _HandleCallLlvm(self, Node):
Gen = self.Trans.LlvmGen
func_attr = None
module_path = None
FuncAttr = None
ModulePath = None
if isinstance(Node.func, ast.Name):
FuncName = Node.func.id
if hasattr(self.Trans.FunctionHandler, '_generic_templates') and FuncName in self.Trans.FunctionHandler._generic_templates:
@@ -231,9 +231,9 @@ class ExprCallHandle(BaseHandle):
if isinstance(Val.type, ir.IntType):
if Val.type.width == 1:
return Val
return Gen.builder.icmp_signed('!=', Val, Gen._zero_const(Val.type), name="bool_result")
return Gen.builder.icmp_signed('!=', Val, Gen._ZeroConst(Val.type), name="bool_result")
elif isinstance(Val.type, ir.PointerType):
return Gen.builder.icmp_signed('!=', Val, Gen._zero_const(Val.type), name="bool_result")
return Gen.builder.icmp_signed('!=', Val, Gen._ZeroConst(Val.type), name="bool_result")
return Val
return ir.Constant(ir.IntType(1), 0)
elif FuncName == 'int':
@@ -355,7 +355,7 @@ class ExprCallHandle(BaseHandle):
return self._HandleCallLlvm(virtual_node)
# 检查是否是闭包变量lambda 赋值给变量后调用)
if FuncName in Gen.variables and Gen.variables[FuncName] is not None:
closure_ptr = Gen._load(Gen.variables[FuncName], name=f"load_closure_{FuncName}")
closure_ptr = Gen._load(Gen.variables[FuncName], name=f"Load_closure_{FuncName}")
if isinstance(closure_ptr.type, ir.PointerType) and isinstance(closure_ptr.type.pointee, ir.LiteralStructType):
st = closure_ptr.type.pointee
if len(st.elements) == 2 and isinstance(st.elements[1], ir.PointerType) and isinstance(st.elements[1].pointee, ir.FunctionType):
@@ -428,30 +428,30 @@ class ExprCallHandle(BaseHandle):
type_name = Node.func.value.attr
SizeofNode = ast.Name(id=type_name, ctx=ast.Load())
return self._HandleSizeofLlvm(SizeofNode)
module_path = self._get_module_path(Node.func.value)
if module_path:
aliases = getattr(self.Trans, '_import_aliases', {})
first_part = module_path.split('.')[0]
ModulePath = self._get_ModulePath(Node.func.value)
if ModulePath:
aliases = getattr(self.Trans, '_ImportAliases', {})
first_part = ModulePath.split('.')[0]
if first_part in aliases:
module_path = aliases[first_part] + module_path[len(first_part):]
is_instance_var = isinstance(Node.func.value, ast.Name) and Node.func.value.id in Gen.var_struct_class and Node.func.value.id not in Gen.module_sha1_map
ModulePath = aliases[first_part] + ModulePath[len(first_part):]
is_instance_var = isinstance(Node.func.value, ast.Name) and Node.func.value.id in Gen.var_struct_class and Node.func.value.id not in Gen.ModuleSha1Map
is_class_name = isinstance(Node.func.value, ast.Name) and (Node.func.value.id in Gen.structs or (Node.func.value.id in self.Trans.SymbolTable and getattr(self.Trans.SymbolTable[Node.func.value.id], 'IsStruct', False)))
if is_instance_var and not is_class_name:
return self._HandleMethodCallLlvm(Node)
func_attr = Node.func.attr
if func_attr in Gen.structs:
result = self._HandleClassNewLlvm(Node, func_attr)
FuncAttr = Node.func.attr
if FuncAttr in Gen.structs:
result = self._HandleClassNewLlvm(Node, FuncAttr)
if result is not None:
return result
if hasattr(self.Trans.ClassHandler, '_generic_class_templates') and func_attr in self.Trans.ClassHandler._generic_class_templates:
return self._HandleGenericClassNewLlvm(Node, func_attr)
if func_attr in self.Trans.SymbolTable:
SymInfo = self.Trans.SymbolTable[func_attr]
if hasattr(self.Trans.ClassHandler, '_generic_class_templates') and FuncAttr in self.Trans.ClassHandler._generic_class_templates:
return self._HandleGenericClassNewLlvm(Node, FuncAttr)
if FuncAttr in self.Trans.SymbolTable:
SymInfo = self.Trans.SymbolTable[FuncAttr]
if SymInfo.IsStruct:
if func_attr not in Gen.structs:
self._ensure_struct_declared(func_attr)
if func_attr in Gen.structs:
result = self._HandleClassNewLlvm(Node, func_attr)
if FuncAttr not in Gen.structs:
self._ensure_struct_declared(FuncAttr)
if FuncAttr in Gen.structs:
result = self._HandleClassNewLlvm(Node, FuncAttr)
if result is not None:
return result
if getattr(SymInfo, 'IsEnumMember', False) and getattr(SymInfo, 'EnumName', None):
@@ -459,58 +459,58 @@ class ExprCallHandle(BaseHandle):
if EnumName in self.Trans.SymbolTable:
EnumInfo = self.Trans.SymbolTable[EnumName]
if getattr(EnumInfo, 'IsRenum', False):
result = self._HandleREnumConstructLlvm(Node, EnumName, func_attr, SymInfo.value)
result = self._HandleREnumConstructLlvm(Node, EnumName, FuncAttr, SymInfo.value)
if result is not None:
return result
FullAttrKey = f"{module_path}.{func_attr}"
FullAttrKey = f"{ModulePath}.{FuncAttr}"
if FullAttrKey in self.Trans.SymbolTable:
SymInfo = self.Trans.SymbolTable[FullAttrKey]
if SymInfo.IsStruct:
if func_attr not in Gen.structs:
self._ensure_struct_declared(func_attr)
if func_attr in Gen.structs:
result = self._HandleClassNewLlvm(Node, func_attr)
if FuncAttr not in Gen.structs:
self._ensure_struct_declared(FuncAttr)
if FuncAttr in Gen.structs:
result = self._HandleClassNewLlvm(Node, FuncAttr)
if result is not None:
return result
if is_class_name:
ClassName = Node.func.value.id
result = self._HandleStaticMethodCallLlvm(Node, ClassName, func_attr)
result = self._HandleStaticMethodCallLlvm(Node, ClassName, FuncAttr)
if result is not None:
return result
FullAttrKey = f"{module_path}.{func_attr}"
FullAttrKey = f"{ModulePath}.{FuncAttr}"
if FullAttrKey in self.Trans.SymbolTable:
SymInfo = self.Trans.SymbolTable[FullAttrKey]
if getattr(SymInfo, 'IsTypedef', False):
return ir.Constant(ir.IntType(32), 0)
if getattr(SymInfo, 'IsStruct', False):
if func_attr not in Gen.structs:
self._ensure_struct_declared(func_attr)
if func_attr in Gen.structs:
result = self._HandleClassNewLlvm(Node, func_attr)
if FuncAttr not in Gen.structs:
self._ensure_struct_declared(FuncAttr)
if FuncAttr in Gen.structs:
result = self._HandleClassNewLlvm(Node, FuncAttr)
if result is not None:
return result
if func_attr in Gen.structs:
result = self._HandleClassNewLlvm(Node, func_attr)
if FuncAttr in Gen.structs:
result = self._HandleClassNewLlvm(Node, FuncAttr)
if result is not None:
return result
if module_path == 'c':
if func_attr == 'Asm':
if ModulePath == 'c':
if FuncAttr == 'Asm':
return self.Trans.ExprAsmHandle._HandleAsmLlvm(Node)
elif func_attr == 'Addr':
elif FuncAttr == 'Addr':
return self.Trans.CSpecialCallHandle._HandleCAddrLlvm(Node)
elif func_attr == 'Set':
elif FuncAttr == 'Set':
return self.Trans.CSpecialCallHandle._HandleCSetLlvm(Node)
elif func_attr == 'Load':
elif FuncAttr == 'Load':
return self.Trans.CSpecialCallHandle._HandleCLoadLlvm(Node)
elif func_attr == 'Deref':
elif FuncAttr == 'Deref':
return self.Trans.CSpecialCallHandle._HandleCDerefLlvm(Node)
elif func_attr == 'DerefAs':
elif FuncAttr == 'DerefAs':
return self._HandleCDerefAsLlvm(Node)
elif func_attr == 'PtrToInt':
elif FuncAttr == 'PtrToInt':
return self.Trans.CSpecialCallHandle._HandleCPtrToIntLlvm(Node)
elif func_attr in ('CIf', 'CElif'):
elif FuncAttr in ('CIf', 'CElif'):
return self.Trans.CSpecialCallHandle._HandleCIfLlvm(Node)
elif func_attr == 'CError':
elif FuncAttr == 'CError':
msg = "compile-time error"
if Node.args:
arg = Node.args[0]
@@ -520,52 +520,119 @@ class ExprCallHandle(BaseHandle):
msg = arg.s
lineno = getattr(Node, 'lineno', 0)
raise Exception(f"#error: {msg} (line {lineno})")
elif func_attr in ('AsmInp', 'AsmOut'):
elif FuncAttr in ('AsmInp', 'AsmOut'):
return ir.Constant(ir.IntType(32), 0)
elif func_attr == 'LLVMIR':
elif FuncAttr == 'LLVMIR':
return self._HandleLLVMIRLlvm(Node)
elif func_attr in ('LInp', 'LOut'):
elif FuncAttr in ('LInp', 'LOut'):
return ir.Constant(ir.IntType(32), 0)
if module_path == 't':
method_result_t = self._HandleMethodCallLlvm(Node)
if method_result_t is not None:
return method_result_t
raise Exception(f"Undefined method: 't.{func_attr}'")
if ModulePath == 't':
MethodResult_t = self._HandleMethodCallLlvm(Node)
if MethodResult_t is not None:
return MethodResult_t
raise Exception(f"Undefined method: 't.{FuncAttr}'")
if isinstance(Node.func.value, ast.Attribute):
inner_attr = Node.func.value.attr
if inner_attr in Gen.structs or (inner_attr in self.Trans.SymbolTable and getattr(self.Trans.SymbolTable[inner_attr], 'IsStruct', False)):
static_result = self._HandleStaticMethodCallLlvm(Node, inner_attr, func_attr)
static_result = self._HandleStaticMethodCallLlvm(Node, inner_attr, FuncAttr)
if static_result is not None:
return static_result
method_result_attr = self._HandleMethodCallLlvm(Node)
is_zero_attr = isinstance(method_result_attr, ir.Constant) and isinstance(method_result_attr.type, ir.IntType) and method_result_attr.constant == 0
if method_result_attr is not None and not is_zero_attr:
return method_result_attr
result = self._HandleExternalCallLlvm(Node, func_attr, module_path)
MethodResult_attr = self._HandleMethodCallLlvm(Node)
is_zero_attr = isinstance(MethodResult_attr, ir.Constant) and isinstance(MethodResult_attr.type, ir.IntType) and MethodResult_attr.constant == 0
if MethodResult_attr is not None and not is_zero_attr:
return MethodResult_attr
result = self._HandleExternalCallLlvm(Node, FuncAttr, ModulePath)
if result is not None:
return result
method_result = self._HandleMethodCallLlvm(Node)
is_zero_result = isinstance(method_result, ir.Constant) and isinstance(method_result.type, ir.IntType) and method_result.constant == 0
if is_zero_result and func_attr is not None:
mangled_name = Gen._mangle_func_name(func_attr, module_path if module_path and module_path != 't' else None)
MethodResult = self._HandleMethodCallLlvm(Node)
IsZeroResult = isinstance(MethodResult, ir.Constant) and isinstance(MethodResult.type, ir.IntType) and MethodResult.constant == 0
if IsZeroResult and FuncAttr is not None:
mangled_name = Gen._mangle_func_name(FuncAttr, ModulePath if ModulePath and ModulePath != 't' else None)
if Gen._has_function(mangled_name):
CallArgs = []
for arg in Node.args:
ArgVal = self.HandleExprLlvm(arg)
if ArgVal:
CallArgs.append(ArgVal)
return Gen.builder.call(Gen._get_function(mangled_name), CallArgs, name=f"call_{func_attr}")
if method_result is None or is_zero_result:
imported = getattr(self.Trans, '_imported_modules', set())
aliases = getattr(self.Trans, '_import_aliases', {})
is_known = module_path in imported or module_path in aliases
if module_path and is_known:
raise Exception(f"Undefined symbol: '{module_path}.{func_attr}'")
if module_path and module_path not in {'t', 'c'} and not is_known:
raise Exception(f"Unknown module: '{module_path}' (undefined symbol: '{module_path}.{func_attr}')")
if not module_path and func_attr:
raise Exception(f"Undefined method: '{func_attr}'")
return method_result if method_result is not None else ir.Constant(ir.IntType(32), 0)
return Gen.builder.call(Gen._get_function(mangled_name), CallArgs, name=f"call_{FuncAttr}")
if MethodResult is None or IsZeroResult:
imported = getattr(self.Trans, '_ImportedModules', set())
aliases = getattr(self.Trans, '_ImportAliases', {})
ModuleSha1Map = getattr(Gen, 'ModuleSha1Map', {})
IsKnown = (ModulePath in imported or ModulePath in aliases or
ModulePath in ModuleSha1Map)
if not IsKnown and ModulePath and '.' in ModulePath:
LastPart = ModulePath.split('.')[-1]
IsKnown = (LastPart in imported or LastPart in aliases or
LastPart in ModuleSha1Map)
# 最后尝试: 用 FuncAttr 直接查找 Gen.functions_find_function 会遍历 SHA1 前缀)
if FuncAttr and ModulePath and ModulePath not in {'t', 'c'}:
# 优先检查 FuncAttr 是否为 struct/类构造器
if FuncAttr not in Gen.structs:
self._ensure_struct_declared(FuncAttr)
if FuncAttr in Gen.structs:
result = self._HandleClassNewLlvm(Node, FuncAttr)
if result is not None:
return result
# 检查 FullAttrKey 是否为 struct如 hashlib.md5
if ModulePath:
FullAttrKey = f"{ModulePath}.{FuncAttr}"
if FullAttrKey in self.Trans.SymbolTable:
FullSymInfo = self.Trans.SymbolTable[FullAttrKey]
if getattr(FullSymInfo, 'IsStruct', False) or getattr(FullSymInfo, 'IsCpythonObject', False):
if FuncAttr not in Gen.structs:
self._ensure_struct_declared(FuncAttr)
if FuncAttr in Gen.structs:
result = self._HandleClassNewLlvm(Node, FuncAttr)
if result is not None:
return result
fallback_func = Gen._find_function(FuncAttr)
if fallback_func is not None:
CallArgs = []
for arg in Node.args:
ArgVal = self.HandleExprLlvm(arg)
if ArgVal:
CallArgs.append(ArgVal)
self._append_eh_msg_out_arg(CallArgs, fallback_func, Gen)
result = Gen.builder.call(fallback_func, CallArgs, name=f"call_{FuncAttr}")
return self._check_eh_return(result, FuncAttr, Gen, called_func=fallback_func)
# 尝试从 stub 按需加载函数声明
if ModulePath in ModuleSha1Map:
sha1 = ModuleSha1Map[ModulePath]
stub_mangled = f"{sha1}.{FuncAttr}"
try:
stub_func_type = self.Trans.ImportHandler._LookupStubFuncType(stub_mangled, Gen)
except Exception:
stub_func_type = None
if not stub_func_type:
try:
stub_func_type = self.Trans.ImportHandler._LookupStubFuncType(FuncAttr, Gen)
except Exception:
stub_func_type = None
if stub_func_type:
decl_name = stub_mangled if stub_mangled in getattr(self.Trans.ImportHandler, '_stub_func_cache', {}) else FuncAttr
if decl_name not in Gen.functions:
func_decl = ir.Function(Gen.module, stub_func_type, name=decl_name)
Gen.functions[decl_name] = func_decl
if decl_name != FuncAttr and FuncAttr not in Gen.functions:
Gen.functions[FuncAttr] = func_decl
else:
func_decl = Gen.functions[decl_name]
CallArgs = []
for arg in Node.args:
ArgVal = self.HandleExprLlvm(arg)
if ArgVal:
CallArgs.append(ArgVal)
self._append_eh_msg_out_arg(CallArgs, func_decl, Gen)
result = Gen.builder.call(func_decl, CallArgs, name=f"call_{FuncAttr}")
return self._check_eh_return(result, FuncAttr, Gen, called_func=func_decl)
if ModulePath and IsKnown:
raise Exception(f"Undefined symbol: '{ModulePath}.{FuncAttr}'")
if ModulePath and ModulePath not in {'t', 'c'} and not IsKnown:
raise Exception(f"Unknown module: '{ModulePath}' (undefined symbol: '{ModulePath}.{FuncAttr}')")
if not ModulePath and FuncAttr:
raise Exception(f"Undefined method: '{FuncAttr}'")
return MethodResult if MethodResult is not None else ir.Constant(ir.IntType(32), 0)
if isinstance(Node.func, ast.BinOp) and isinstance(Node.func.op, ast.BitOr):
return self._HandleTypeUnionCastLlvm(Node)
raise Exception(f"Unsupported call expression")
@@ -771,7 +838,7 @@ class ExprCallHandle(BaseHandle):
ast.copy_location(new_node, Node)
return new_node
def _get_module_path(self, node):
def _get_ModulePath(self, node):
parts = []
while isinstance(node, ast.Attribute):
parts.append(node.attr)
@@ -936,9 +1003,9 @@ class ExprCallHandle(BaseHandle):
result = method(src_val, dest_type, name="llvmir_result")
return self._StoreLLVMIROutputs(Gen, result, output_targets)
load_match = re.match(r'load\s+(\w+),\s*(\w+)\s+%__OP(\d+)__', template)
if load_match:
ptr_val = resolve_op(int(load_match.group(3)))
Load_match = re.match(r'Load\s+(\w+),\s*(\w+)\s+%__OP(\d+)__', template)
if Load_match:
ptr_val = resolve_op(int(Load_match.group(3)))
if ptr_val:
result = Gen.builder.load(ptr_val, name="llvmir_result")
return self._StoreLLVMIROutputs(Gen, result, output_targets)
@@ -1095,8 +1162,8 @@ class ExprCallHandle(BaseHandle):
expected_type = self._ParseLLVMType(Gen, expected_type_str.rstrip('*'))
if not expected_type:
return val
is_ptr = expected_type_str.endswith('*')
if is_ptr:
IsPtr = expected_type_str.endswith('*')
if IsPtr:
expected_ptr_type = ir.PointerType(expected_type)
if isinstance(val.type, ir.PointerType) and val.type != expected_ptr_type:
try:
@@ -1124,31 +1191,32 @@ class ExprCallHandle(BaseHandle):
return Gen.builder.inttoptr(val, expected_type)
return val
def _HandleExternalCallLlvm(self, Node, func_name, module_path):
def _HandleExternalCallLlvm(self, Node, func_name, ModulePath):
Gen = self.Trans.LlvmGen
# 解析 import 别名: 如 window -> vpsdk.window
if module_path and module_path not in ('c', 't'):
import_aliases = getattr(self.Trans, '_import_aliases', {})
if module_path in import_aliases:
module_path = import_aliases[module_path]
if ModulePath and ModulePath not in ('c', 't'):
import_aliases = getattr(self.Trans, '_ImportAliases', {})
if ModulePath in import_aliases:
ModulePath = import_aliases[ModulePath]
is_user_module = (module_path and module_path not in ('c', 't') and
(module_path in Gen.module_sha1_map or
module_path in getattr(self.Trans, '_imported_modules', set()) or
module_path in getattr(self.Trans, '_import_aliases', {})))
if module_path and module_path not in ('c', 't') and not is_user_module:
is_user_module = (module_path in Gen.module_sha1_map or
module_path.split('.')[-1] in Gen.module_sha1_map)
if is_user_module and module_path not in Gen.module_sha1_map:
module_path = module_path.split('.')[-1]
is_user_module = (ModulePath and ModulePath not in ('c', 't') and
(ModulePath in Gen.ModuleSha1Map or
ModulePath in getattr(self.Trans, '_ImportedModules', set()) or
ModulePath in getattr(self.Trans, '_ImportAliases', {})))
if ModulePath and ModulePath not in ('c', 't') and not is_user_module:
is_user_module = (ModulePath in Gen.ModuleSha1Map or
ModulePath.split('.')[-1] in Gen.ModuleSha1Map or
ModulePath.split('.')[-1] in getattr(self.Trans, '_ImportedModules', set()))
if is_user_module and ModulePath not in Gen.ModuleSha1Map and ModulePath not in getattr(self.Trans, '_ImportedModules', set()):
ModulePath = ModulePath.split('.')[-1]
if module_path and module_path not in ('c', 't') and not is_user_module:
if ModulePath and ModulePath not in ('c', 't') and not is_user_module:
return None
if is_user_module:
mangled_name = Gen._mangle_func_name(func_name, module_path)
sym_key = f'{module_path}.{func_name}'
mangled_name = Gen._mangle_func_name(func_name, ModulePath)
sym_key = f'{ModulePath}.{func_name}'
sym_info = self.Trans.SymbolTable.get(sym_key) or self.Trans.SymbolTable.get(func_name)
is_inline = sym_info and (getattr(sym_info, 'IsInline', False) or isinstance(getattr(sym_info, 'Storage', None), t.CInline))
if is_inline and getattr(sym_info, 'InlineBody', None):
@@ -1166,11 +1234,11 @@ class ExprCallHandle(BaseHandle):
kw_provided.add(exact_param_names.index(kw.arg))
for i in range(len(exact_param_names)):
if i >= provided and i not in kw_provided:
raise Exception(f"调用 {module_path}.{func_name}() 缺少必需参数 '{exact_param_names[i]}',该参数没有默认值")
elif module_path in Gen.module_sha1_map and len(Node.args) == 0:
raise Exception(f"调用 {ModulePath}.{func_name}() 缺少必需参数 '{exact_param_names[i]}',该参数没有默认值")
elif ModulePath in Gen.ModuleSha1Map and len(Node.args) == 0:
func = Gen.functions.get(mangled_name)
if func and len(func.function_type.args) > 0:
raise Exception(f"调用 {module_path}.{func_name}() 缺少必需参数,函数需要 {len(func.function_type.args)} 个参数但未传入任何参数")
raise Exception(f"调用 {ModulePath}.{func_name}() 缺少必需参数,函数需要 {len(func.function_type.args)} 个参数但未传入任何参数")
if Gen._has_function(mangled_name):
return self._HandleClosureCallLlvm(Node, mangled_name)
try:
@@ -1195,7 +1263,7 @@ class ExprCallHandle(BaseHandle):
if decl_name != func_name and func_name not in Gen.functions:
Gen.functions[func_name] = func_decl
return self._HandleClosureCallLlvm(Node, decl_name)
sym_key = f'{module_path}.{func_name}'
sym_key = f'{ModulePath}.{func_name}'
sym_info = self.Trans.SymbolTable.get(sym_key)
if not sym_info:
sym_info = self.Trans.SymbolTable.get(func_name)
@@ -1234,9 +1302,13 @@ class ExprCallHandle(BaseHandle):
if replaced and replaced != existing:
Gen.functions[mangled_name] = replaced
return self._HandleClosureCallLlvm(Node, mangled_name)
# 回退: 直接用 func_name 查找_find_function 会遍历 SHA1 前缀)
fallback_func = Gen._find_function(func_name)
if fallback_func is not None:
return self._HandleClosureCallLlvm(Node, func_name)
return None
if module_path == 'c':
if ModulePath == 'c':
if func_name == 'Asm':
return self.Trans.ExprAsmHandle._HandleAsmLlvm(Node)
elif func_name == 'Addr':
@@ -1276,7 +1348,7 @@ class ExprCallHandle(BaseHandle):
'GetConsoleOutputCP': (ir.IntType(32), []),
'GetConsoleCP': (ir.IntType(32), []),
}
if module_path and 'win32console' in module_path and func_name in win32_apis:
if ModulePath and 'win32console' in ModulePath and func_name in win32_apis:
ret_type, param_types = win32_apis[func_name]
if func_name not in Gen.functions:
func_type = ir.FunctionType(ret_type, param_types)
@@ -1304,7 +1376,7 @@ class ExprCallHandle(BaseHandle):
if func_name in self._C_LIB_FUNCS:
return self._HandleClosureCallLlvm(Node, func_name)
mangled_name = Gen._mangle_func_name(func_name, module_path)
mangled_name = Gen._mangle_func_name(func_name, ModulePath)
try:
stub_func_type = self.Trans.ImportHandler._LookupStubFuncType(mangled_name, Gen)
except Exception:
@@ -1322,7 +1394,7 @@ class ExprCallHandle(BaseHandle):
Gen.functions[func_name] = func_decl
return self._HandleClosureCallLlvm(Node, decl_name)
sym_key = f'{module_path}.{func_name}' if module_path else func_name
sym_key = f'{ModulePath}.{func_name}' if ModulePath else func_name
sym_info = self.Trans.SymbolTable.get(sym_key)
if not sym_info:
sym_info = self.Trans.SymbolTable.get(func_name)
@@ -1347,7 +1419,7 @@ class ExprCallHandle(BaseHandle):
if isinstance(lp, ir.VoidType):
lp = ir.IntType(8).as_pointer()
llvm_param_types.append(lp)
mangled_name = Gen._mangle_func_name(func_name, module_path)
mangled_name = Gen._mangle_func_name(func_name, ModulePath)
if mangled_name not in Gen.functions:
func_type = ir.FunctionType(ret_type, llvm_param_types, var_arg=sym_is_variadic)
func_decl = ir.Function(Gen.module, func_type, name=mangled_name)
@@ -1372,18 +1444,22 @@ class ExprCallHandle(BaseHandle):
type_info = None
try:
type_info = getattr(self.Trans, 'TypeMergeHandler', None) and self.Trans.TypeMergeHandler.MergeTypes(Node.func)
except Exception:
pass
except Exception as _e:
from lib.core.VLogger import get_logger as _vlog
from lib.constants.config import mode as _config_mode
if _config_mode == "strict":
raise
_vlog().warning(f"解析类型失败: {_e}", "Exception")
if not isinstance(type_info, CTypeInfo):
return None
target_type_str = type_info.ToString()
is_ptr = type_info.IsPtr
if is_ptr and target_type_str and '*' not in target_type_str:
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 is_ptr:
is_ptr = True
if type_info.IsPtr and not IsPtr:
IsPtr = True
if '*' not in target_type_str:
target_type_str += ' *'
if isinstance(type_info.Storage, t.CExport) or isinstance(type_info.Storage, t.CExtern):
@@ -1408,8 +1484,8 @@ class ExprCallHandle(BaseHandle):
dst_is_float = isinstance(target_type, (ir.FloatType, ir.DoubleType))
src_is_int = isinstance(val.type, ir.IntType)
dst_is_int = isinstance(target_type, ir.IntType)
src_is_ptr = isinstance(val.type, ir.PointerType)
dst_is_ptr = isinstance(target_type, ir.PointerType)
src_IsPtr = isinstance(val.type, ir.PointerType)
dst_IsPtr = isinstance(target_type, ir.PointerType)
if src_is_int and dst_is_float:
is_unsigned = Gen._check_node_unsigned(expr_node)
if is_unsigned:
@@ -1442,17 +1518,17 @@ class ExprCallHandle(BaseHandle):
if isinstance(val.type, ir.DoubleType) and isinstance(target_type, ir.FloatType):
return Gen.builder.fptrunc(val, target_type, name="fptrunc_cast")
return val
if src_is_ptr and dst_is_int:
if src_IsPtr and dst_is_int:
if target_type.width < 64:
ptr_to_i64 = Gen.builder.ptrtoint(val, ir.IntType(64), name="ptr2i64")
return Gen.builder.trunc(ptr_to_i64, target_type, name="ptr2int_cast")
return Gen.builder.ptrtoint(val, target_type, name="ptr2int_cast")
if src_is_int and dst_is_ptr:
if src_is_int and dst_IsPtr:
return Gen.builder.inttoptr(val, target_type, name="int2ptr_cast")
if src_is_ptr and dst_is_ptr:
if src_IsPtr and dst_IsPtr:
if isinstance(val.type.pointee, ir.PointerType) and isinstance(target_type.pointee, ir.IntType):
loaded = Gen._load(val, name="load_ptr")
return loaded
Loaded = Gen._load(val, name="load_ptr")
return Loaded
return Gen.builder.bitcast(val, target_type, name="ptrcast")
try:
return Gen.builder.bitcast(val, target_type, name="cast")
@@ -1464,7 +1540,7 @@ class ExprCallHandle(BaseHandle):
if RenumName not in Gen.structs:
return None
RenumType = Gen.structs[RenumName]
result = Gen._alloca_entry(RenumType, name=f"{RenumName}_{VariantName}")
result = Gen._allocaEntry(RenumType, name=f"{RenumName}_{VariantName}")
tag_ptr = Gen.builder.gep(result, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), 0)], name="renum_tag_ptr")
Gen._store(ir.Constant(ir.IntType(32), TagValue), tag_ptr)
NestedStructName = f"{RenumName}_{VariantName}"
@@ -1473,10 +1549,10 @@ class ExprCallHandle(BaseHandle):
NestedStructPtrType = ir.PointerType(NestedStructType)
variant_ptr = Gen.builder.bitcast(result, NestedStructPtrType, name=f"cast_{NestedStructName}")
members = Gen.class_members.get(NestedStructName, [])
payload_members = [(n, t) for n, t in members if n != '__tag']
payLoad_members = [(n, t) for n, t in members if n != '__tag']
for i, arg in enumerate(Node.args):
if i < len(payload_members):
member_name, member_type = payload_members[i]
if i < len(payLoad_members):
member_name, member_type = payLoad_members[i]
ArgVal = self.HandleExprLlvm(arg)
if ArgVal:
Coerced = Gen._coerce_value(ArgVal, member_type)
@@ -1543,7 +1619,7 @@ class ExprCallHandle(BaseHandle):
old_var_scopes = list(self.Trans.VarScopes)
for param_name, val in saved_vars.items():
if val is not None:
alloca = Gen._alloca_entry(val.type, name=f"inline_arg_{param_name}")
alloca = Gen._allocaEntry(val.type, name=f"inline_arg_{param_name}")
Gen._store(val, alloca)
self.Trans.VarScopes.append((param_name, alloca))
self.Trans.BodyHandler.HandleBodyLlvm(inline_body)
@@ -1679,7 +1755,7 @@ class ExprCallHandle(BaseHandle):
CallArgs.append(Gen.variables[var_name])
elif var_name in Gen._reg_values:
OldVal = Gen._reg_values[var_name]
var = Gen._alloca_entry(OldVal.type, name=var_name)
var = Gen._allocaEntry(OldVal.type, name=var_name)
Gen._store(OldVal, var)
Gen.variables[var_name] = var
del Gen._reg_values[var_name]
@@ -1762,7 +1838,7 @@ class ExprCallHandle(BaseHandle):
if target_bits is None:
target_bits = 0
is_float = getattr(ctype_inst, 'IsSigned', False) is None and target_bits > 0 if ctype_inst else False
is_ptr_cast = len(Node.args) >= 2 and (
IsPtr_cast = len(Node.args) >= 2 and (
(isinstance(Node.args[1], ast.Attribute) and Node.args[1].attr == 'CPtr' and isinstance(Node.args[1].value, ast.Name) and Node.args[1].value.id == 't') or
(isinstance(Node.args[1], ast.Name) and Node.args[1].id == 'CPtr')
)
@@ -1771,10 +1847,10 @@ class ExprCallHandle(BaseHandle):
if isinstance(ArgNode, ast.Subscript):
SubscriptPtr = self._HandleSubscriptPtrLlvm(ArgNode)
if SubscriptPtr:
if MethodName == 'CPtr' or is_ptr_cast:
if MethodName == 'CPtr' or IsPtr_cast:
return SubscriptPtr
if isinstance(SubscriptPtr.type, ir.PointerType):
val = Gen._load(SubscriptPtr, name="load_subscript_val")
val = Gen._load(SubscriptPtr, name="Load_subscript_val")
else:
val = SubscriptPtr
if target_bits > 0 and isinstance(val.type, ir.IntType) and not is_float:
@@ -1784,7 +1860,7 @@ class ExprCallHandle(BaseHandle):
val = Gen.builder.trunc(val, ir.IntType(target_bits), name="trunc_cast")
return val
val = self.HandleExprLlvm(ArgNode)
if is_ptr_cast:
if IsPtr_cast:
if target_bits > 0 and not is_float:
target_ptr_type = ir.PointerType(ir.IntType(target_bits))
elif is_float and target_bits == 32:
@@ -1839,9 +1915,9 @@ class ExprCallHandle(BaseHandle):
if isinstance(ArgVal, ir.Constant) and isinstance(ArgVal.type, ir.IntType):
return ir.Constant(ir.IntType(1), 1 if ArgVal.constant != 0 else 0)
if isinstance(ArgVal.type, ir.IntType):
return Gen.builder.icmp_signed('!=', ArgVal, Gen._zero_const(ArgVal.type), name="cif_cond")
return Gen.builder.icmp_signed('!=', ArgVal, Gen._ZeroConst(ArgVal.type), name="cif_cond")
if isinstance(ArgVal.type, ir.PointerType):
return Gen.builder.icmp_signed('!=', ArgVal, Gen._zero_const(ArgVal.type), name="cif_cond")
return Gen.builder.icmp_signed('!=', ArgVal, Gen._ZeroConst(ArgVal.type), name="cif_cond")
return ir.Constant(ir.IntType(1), 0)
elif MethodName in ('CIfdef', 'CIfndef'):
return ir.Constant(ir.IntType(1), 1)
@@ -1858,8 +1934,12 @@ class ExprCallHandle(BaseHandle):
val = self.HandleExprLlvm(arg)
if isinstance(val, str):
msg = val
except Exception:
pass
except Exception as _e:
from lib.core.VLogger import get_logger as _vlog
from lib.constants.config import mode as _config_mode
if _config_mode == "strict":
raise
_vlog().warning(f"处理函数调用失败: {_e}", "Exception")
lineno = getattr(Node, 'lineno', 0)
raise Exception(f"#error: {msg} (line {lineno})")
elif MethodName in ('CElse', 'CEndif', 'CPragma', 'CUndef'):
@@ -1877,21 +1957,21 @@ class ExprCallHandle(BaseHandle):
if isinstance(var_ptr.type, ir.PointerType) and isinstance(var_ptr.type.pointee, (ir.IdentifiedStructType, ir.LiteralStructType)):
ObjVal = var_ptr
else:
tmp = Gen._alloca_entry(ObjVal.type, name="chain_method_tmp")
tmp = Gen._allocaEntry(ObjVal.type, name="chain_method_tmp")
Gen._store(ObjVal, tmp)
ObjVal = tmp
else:
tmp = Gen._alloca_entry(ObjVal.type, name="chain_method_tmp")
tmp = Gen._allocaEntry(ObjVal.type, name="chain_method_tmp")
Gen._store(ObjVal, tmp)
ObjVal = tmp
else:
tmp = Gen._alloca_entry(ObjVal.type, name="chain_method_tmp")
tmp = Gen._allocaEntry(ObjVal.type, name="chain_method_tmp")
Gen._store(ObjVal, tmp)
ObjVal = tmp
if isinstance(Node.func.value, ast.Name):
ModuleName = Node.func.value.id
aliases = getattr(self.Trans, '_import_aliases', {})
imported = getattr(self.Trans, '_imported_modules', set())
aliases = getattr(self.Trans, '_ImportAliases', {})
imported = getattr(self.Trans, '_ImportedModules', set())
actual_module = aliases.get(ModuleName, ModuleName)
if ModuleName in imported or actual_module in imported:
mangled_name = Gen._mangle_func_name(MethodName, actual_module)
@@ -2001,7 +2081,7 @@ class ExprCallHandle(BaseHandle):
if not stub_func_type:
stub_func_type = self.Trans.ImportHandler._LookupStubFuncType(MethodName, Gen)
if not stub_func_type and mangled_name != MethodName:
for sha1 in getattr(Gen, 'module_sha1_map', {}).values():
for sha1 in getattr(Gen, 'ModuleSha1Map', {}).values():
alt_name = f"{sha1}.{MethodName}"
stub_func_type = self.Trans.ImportHandler._LookupStubFuncType(alt_name, Gen)
if stub_func_type:
@@ -2250,7 +2330,7 @@ class ExprCallHandle(BaseHandle):
val = Gen.builder.zext(val, ir.IntType(32), name="zext_bool_print")
elif val.type.width == 8:
if self._is_char_type(arg):
char_var = Gen._alloca_entry(ir.IntType(8), name="print_char_buf")
char_var = Gen._allocaEntry(ir.IntType(8), name="print_char_buf")
Gen.builder.store(val, char_var)
fmt_parts.append('%c')
fmt_args.append(char_var)
@@ -2314,7 +2394,7 @@ class ExprCallHandle(BaseHandle):
if ClassName in Gen.structs:
obj_val = Gen.builder.bitcast(obj_val, ir.PointerType(Gen.structs[ClassName]), name=f"cast_{ClassName}")
str_val = Gen.builder.call(Gen._get_function(f'{ClassName}.__str__'), [obj_val], name=f"call_{ClassName}.__str__")
Gen._register_temp_ptr(str_val)
Gen._RegisterTempPtr(str_val)
Gen._emit_printf([str_val], unsigned_flags=[False], sep=None, end=None)
elif isinstance(arg, ast.Name) and arg.id in Gen.var_struct_class:
ClassName = Gen.var_struct_class[arg.id]
@@ -2325,7 +2405,7 @@ class ExprCallHandle(BaseHandle):
if isinstance(obj_val.type, ir.PointerType) and not isinstance(obj_val.type.pointee, type(Gen.structs[ClassName])):
obj_val = Gen.builder.bitcast(obj_val, ir.PointerType(Gen.structs[ClassName]), name=f"cast_{ClassName}")
str_val = Gen.builder.call(str_func, [obj_val], name=f"call_{ClassName}.__str__")
Gen._register_temp_ptr(str_val)
Gen._RegisterTempPtr(str_val)
Gen._emit_printf([str_val], unsigned_flags=[False], sep=None, end=None)
else:
val = self.HandleExprLlvm(arg)
@@ -2340,7 +2420,7 @@ class ExprCallHandle(BaseHandle):
pointee = val.type.pointee
if not self._is_char_pointer(val):
try:
val = Gen._load(val, name="print_load")
val = Gen._load(val, name="print_Load")
except Exception as _e:
if __import__('lib.constants.config', fromlist=['mode']).mode == "strict":
self.Trans.LogWarning(f"异常被忽略: {_e}")
@@ -2431,7 +2511,7 @@ class ExprCallHandle(BaseHandle):
if isinstance(pointee, (ir.IdentifiedStructType, ir.LiteralStructType)):
for CN, ST in Gen.structs.items():
if pointee == ST:
result = self.Trans.ExprUtils._try_operator_overload(CN, '__len__', val, Gen)
result = self.Trans.ExprUtils._try_operator_overLoad(CN, '__len__', val, Gen)
if result is not None:
return result
break
@@ -2479,8 +2559,12 @@ class ExprCallHandle(BaseHandle):
size_bits = getattr(ctype_inst, 'Size', 0) or 0
size_bytes = size_bits // 8
return ir.Constant(ir.IntType(64), size_bytes)
except Exception:
pass
except Exception as _e:
from lib.core.VLogger import get_logger as _vlog
from lib.constants.config import mode as _config_mode
if _config_mode == "strict":
raise
_vlog().warning(f"解析类型失败: {_e}", "Exception")
resolved = CTypeRegistry.ResolveName(type_name)
if resolved:
ctype_cls, ptr_level = resolved
@@ -2491,8 +2575,12 @@ class ExprCallHandle(BaseHandle):
if ptr_level > 0:
size_bytes = 8
return ir.Constant(ir.IntType(64), size_bytes)
except Exception:
pass
except Exception as _e:
from lib.core.VLogger import get_logger as _vlog
from lib.constants.config import mode as _config_mode
if _config_mode == "strict":
raise
_vlog().warning(f"解析类型失败: {_e}", "Exception")
return ir.Constant(ir.IntType(64), 0)
struct_type = Gen.structs[type_name]
@@ -2516,7 +2604,7 @@ class ExprCallHandle(BaseHandle):
if isinstance(pointee, (ir.IdentifiedStructType, ir.LiteralStructType)):
for CN, ST in Gen.structs.items():
if pointee == ST:
result = self.Trans.ExprUtils._try_operator_overload(CN, '__abs__', val, Gen)
result = self.Trans.ExprUtils._try_operator_overLoad(CN, '__abs__', val, Gen)
if result is not None:
return result
break
@@ -2562,12 +2650,12 @@ class ExprCallHandle(BaseHandle):
if TypeInfo.IsEnum:
enum_type_name = arg_name
elif isinstance(arg, ast.Attribute):
last_part = None
LastPart = None
enum_class_name = None
if isinstance(arg.value, ast.Name):
last_part = arg.attr
if last_part in self.Trans.SymbolTable:
AttrInfo = self.Trans.SymbolTable[last_part]
LastPart = arg.attr
if LastPart in self.Trans.SymbolTable:
AttrInfo = self.Trans.SymbolTable[LastPart]
if AttrInfo.IsEnumMember and AttrInfo.EnumName:
enum_type_name = AttrInfo.EnumName
elif isinstance(arg.value, ast.Attribute):
@@ -2576,9 +2664,9 @@ class ExprCallHandle(BaseHandle):
parts = attr_path.split('.')
if len(parts) >= 2:
enum_class_name = parts[-2]
last_part = parts[-1]
qualified_name_dot = f"{enum_class_name}.{last_part}"
qualified_name_under = f"{enum_class_name}_{last_part}"
LastPart = parts[-1]
qualified_name_dot = f"{enum_class_name}.{LastPart}"
qualified_name_under = f"{enum_class_name}_{LastPart}"
enum_member_found = None
for qname in (qualified_name_dot, qualified_name_under):
if qname in self.Trans.SymbolTable:
@@ -2588,7 +2676,7 @@ class ExprCallHandle(BaseHandle):
break
if not enum_member_found:
for key in self.Trans.SymbolTable:
if key == last_part:
if key == LastPart:
info = self.Trans.SymbolTable[key]
if info.IsEnumMember and info.EnumName == enum_class_name:
enum_member_found = info
@@ -2921,7 +3009,7 @@ class ExprCallHandle(BaseHandle):
NewFunc = Gen._get_function(NewFuncName)
StructType = Gen.structs.get(ClassName)
if StructType:
result = Gen._alloca_entry(StructType, name=f"{ClassName}_alloca")
result = Gen._allocaEntry(StructType, name=f"{ClassName}_alloca")
else:
return ir.Constant(ir.IntType(32), 0)
Gen.builder.call(NewFunc, [result], name=f"before_init_{ClassName}")
@@ -2983,7 +3071,7 @@ class ExprCallHandle(BaseHandle):
StructType = StructType.pointee
is_opaque = isinstance(StructType, ir.IdentifiedStructType) and (StructType.elements is None or len(StructType.elements) == 0)
if is_opaque:
result = Gen._alloca_entry(StructType, name=f"{ClassName}_alloca")
result = Gen._allocaEntry(StructType, name=f"{ClassName}_alloca")
Gen.builder.store(ir.Constant(StructType, None), result)
InitFunc = Gen.functions.get(InitFuncName)
if not InitFunc:
@@ -3006,7 +3094,7 @@ class ExprCallHandle(BaseHandle):
adjusted_init = Gen._adjust_args(InitArgs, InitFunc)
Gen.builder.call(InitFunc, adjusted_init, name=f"init_{ClassName}")
return result
result = Gen._alloca_entry(StructType, name=f"{ClassName}_alloca")
result = Gen._allocaEntry(StructType, name=f"{ClassName}_alloca")
# Call __new__ method if it exists (may replace self with heap pointer)
if has_new_method:
NewMethodFunc = Gen._find_function(NewMethodFuncName)
@@ -3196,7 +3284,7 @@ class ExprCallHandle(BaseHandle):
return ptr
return None
if isinstance(ValueVal.type, ir.PointerType) and isinstance(ValueVal.type.pointee, ir.PointerType):
LoadedValueVal = Gen._load(ValueVal, name="load_subscript")
LoadedValueVal = Gen._load(ValueVal, name="Load_subscript")
if isinstance(LoadedValueVal.type, ir.PointerType):
ElemPtr = Gen.builder.gep(LoadedValueVal, [IndexVal], name="subscript")
return ElemPtr
@@ -3232,7 +3320,7 @@ class ExprCallHandle(BaseHandle):
IndexVal = Gen.builder.trunc(IndexVal, ir.IntType(32), name="trunc_arr_index")
ElemPtr = Gen.builder.gep(VarPtr, [zero, IndexVal], name="subscript")
return ElemPtr
arr_alloc = Gen._alloca_entry(ValueVal.type, name="arr_subscript_tmp")
arr_alloc = Gen._allocaEntry(ValueVal.type, name="arr_subscript_tmp")
Gen._store(ValueVal, arr_alloc)
ElemPtr = Gen.builder.gep(arr_alloc, [zero, IndexVal], name="subscript")
return ElemPtr