修复了大量存在的问题,增加了假鸭子类型等等机制

This commit is contained in:
2026-06-25 14:49:46 +08:00
parent 19f2787db0
commit d88d11b646
827 changed files with 32617 additions and 18316 deletions

View File

@@ -1,17 +1,22 @@
from __future__ import annotations
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from lib.core.translator import Translator
from lib.core.Handles.HandlesBase import BaseHandle
import ast
import llvmlite.ir as ir
if TYPE_CHECKING:
from lib.core.translator import Translator
from lib.core.Translator.LlvmGenerator import LlvmGeneratorMixin
from lib.core.Handles.HandlesBase import BaseHandle, BuiltinTypeMap
from lib.includes.t import CTypeRegistry
from lib.core.SymbolUtils import IsTModule
from lib.core.VLogger import get_logger as _vlog
from lib.constants.config import mode as _config_mode
class CSpecialCallHandle(BaseHandle):
def _HandleCIfLlvm(self, Node):
Gen = self.Trans.LlvmGen
def _HandleCIfLlvm(self, Node: ast.Call) -> ir.Value:
Gen: LlvmGeneratorMixin = self.Trans.LlvmGen
if Node.args:
ArgVal = self.HandleExprLlvm(Node.args[0])
ArgVal: ir.Value | None = self.HandleExprLlvm(Node.args[0])
if ArgVal:
if isinstance(ArgVal, ir.Constant) and isinstance(ArgVal.type, ir.IntType):
return ir.Constant(ir.IntType(1), 1 if ArgVal.constant != 0 else 0)
@@ -20,8 +25,8 @@ class CSpecialCallHandle(BaseHandle):
if isinstance(ArgVal.type, ir.PointerType):
return Gen.builder.icmp_signed('!=', ArgVal, Gen._ZeroConst(ArgVal.type), name="cif_cond")
return ir.Constant(ir.IntType(1), 0)
def _HandleCAddrLlvm(self, Node):
Gen = self.Trans.LlvmGen
def _HandleCAddrLlvm(self, Node: ast.Call) -> ir.Value:
Gen: LlvmGeneratorMixin = self.Trans.LlvmGen
if not Node.args:
return ir.Constant(ir.IntType(8).as_pointer(), None)
Arg = Node.args[0]
@@ -36,7 +41,9 @@ class CSpecialCallHandle(BaseHandle):
if isinstance(StructType, ir.PointerType):
StructType = StructType.pointee
ObjPtr = Gen._allocaEntry(StructType, name=f"{ClassName}_obj")
Gen.builder.store(ir.Constant(StructType, None), ObjPtr)
zero_val = Gen._zero_value_for_type(StructType)
if zero_val is not None:
Gen.builder.store(zero_val, ObjPtr)
ConstructorName = f"{ClassName}.__init__"
if ConstructorName in Gen.functions:
func = Gen.functions[ConstructorName]
@@ -95,12 +102,12 @@ class CSpecialCallHandle(BaseHandle):
return Gen.builder.bitcast(ArgVal, ir.IntType(8).as_pointer(), name="addr_bitcast")
return ir.Constant(ir.IntType(8).as_pointer(), None)
def _HandleCSetLlvm(self, Node):
Gen = self.Trans.LlvmGen
def _HandleCSetLlvm(self, Node: ast.Call) -> ir.Value:
Gen: LlvmGeneratorMixin = self.Trans.LlvmGen
if len(Node.args) >= 2:
target_arg = Node.args[0]
value_arg = Node.args[1]
target_ptr = None
target_arg: ast.expr = Node.args[0]
value_arg: ast.expr = Node.args[1]
target_ptr: ir.Value | None = None
if isinstance(target_arg, ast.Call) and isinstance(target_arg.func, ast.Attribute):
if isinstance(target_arg.func.value, ast.Name) and target_arg.func.value.id == 'c':
if target_arg.func.attr == 'Deref' and target_arg.args:
@@ -116,7 +123,7 @@ class CSpecialCallHandle(BaseHandle):
target_ptr = inner_value
elif target_arg.func.attr == 'Addr' and target_arg.args:
target_ptr = self.HandleExprLlvm(target_arg)
elif isinstance(target_arg.func.value, ast.Name) and target_arg.func.value.id == 't':
elif isinstance(target_arg.func.value, ast.Name) and IsTModule(target_arg.func.value.id, self.Trans.SymbolTable):
type_attr = target_arg.func.attr
resolved_cname = self.Trans.TSpecialCallHandle._ResolveTAttrToCName(type_attr)
if target_arg.args and resolved_cname is not None:
@@ -158,12 +165,12 @@ class CSpecialCallHandle(BaseHandle):
Gen._store(ValToStore, target_ptr)
return ir.Constant(ir.IntType(32), 1)
def _HandleCLoadLlvm(self, Node):
Gen = self.Trans.LlvmGen
def _HandleCLoadLlvm(self, Node: ast.Call) -> ir.Value:
Gen: LlvmGeneratorMixin = self.Trans.LlvmGen
if len(Node.args) < 2:
return ir.Constant(ir.IntType(32), 0)
src_val = self.HandleExprLlvm(Node.args[0])
dst_val = self.HandleExprLlvm(Node.args[1])
src_val: ir.Value | None = self.HandleExprLlvm(Node.args[0])
dst_val: ir.Value | None = self.HandleExprLlvm(Node.args[1])
if not src_val or not dst_val:
return ir.Constant(ir.IntType(32), 0)
if not isinstance(src_val.type, ir.PointerType) or not isinstance(dst_val.type, ir.PointerType):
@@ -189,24 +196,80 @@ class CSpecialCallHandle(BaseHandle):
Gen._store(val_to_store, dst_val)
return ir.Constant(ir.IntType(32), 1)
def _HandleCDerefLlvm(self, Node):
Gen = self.Trans.LlvmGen
def _HandleCDerefLlvm(self, Node: ast.Call) -> ir.Value:
Gen: LlvmGeneratorMixin = self.Trans.LlvmGen
if not Node.args:
return ir.Constant(ir.IntType(64), 0)
arg_val = self.HandleExprLlvm(Node.args[0])
arg_val: ir.Value | None = self.HandleExprLlvm(Node.args[0])
if arg_val is None:
return ir.Constant(ir.IntType(32), 0)
if isinstance(arg_val.type, ir.PointerType):
pointee: ir.Type = arg_val.type.pointee
# void* (i8*) 需要根据赋值目标类型推断加载类型
if isinstance(pointee, ir.IntType) and pointee.width == 8:
target_type: ir.Type | None = self._infer_deref_target_type(Gen)
if target_type is not None and not isinstance(target_type, ir.IntType):
# bitcast i8* -> target_type* then load
casted: ir.Value = Gen.builder.bitcast(arg_val, ir.PointerType(target_type), name="deref_cast")
Loaded = Gen._load(casted, name="deref")
if Loaded is not None:
return Loaded
elif target_type is not None and isinstance(target_type, ir.IntType):
# 目标是整数类型 (如 i32/i64): bitcast 并加载
if target_type.width != 8:
casted: ir.Value = Gen.builder.bitcast(arg_val, ir.PointerType(target_type), name="deref_cast")
Loaded = Gen._load(casted, name="deref")
if Loaded is not None:
return Loaded
Loaded = Gen._load(arg_val, name="deref")
if Loaded is not None:
return Loaded
return arg_val
def _HandleCPtrToIntLlvm(self, Node):
Gen = self.Trans.LlvmGen
def _infer_deref_target_type(self, Gen: LlvmGeneratorMixin) -> ir.Type | None:
"""从当前赋值上下文推断 c.Deref 的目标加载类型。
当用户写 v: int = c.Deref(ptr) 时,从赋值注解推断目标类型。"""
assign_node: ast.AST | None = getattr(self.Trans, '_current_assign_node', None)
if not assign_node:
return None
ann: ast.AST | None = getattr(assign_node, 'annotation', None)
if not ann:
return None
ann_name: str | None = None
if isinstance(ann, ast.Name):
ann_name = ann.id
elif isinstance(ann, ast.Attribute):
ann_name = ann.attr
elif isinstance(ann, ast.BinOp) and isinstance(ann.op, ast.BitOr):
# 处理 int | t.CPtr 形式的联合类型注解
for side in (ann.left, ann.right):
if isinstance(side, ast.Name):
ann_name = side.id
break
elif isinstance(side, ast.Attribute):
ann_name = side.attr
break
if not ann_name:
return None
# 使用 BuiltinTypeMap 统一查询(同时支持 Python 类名和字符串速记)
entry: tuple[type, int] | None = BuiltinTypeMap.Get(ann_name)
if entry is not None:
ctype_cls: type = entry[0]
llvm_str: str | None = CTypeRegistry.CTypeToLLVM(ctype_cls)
if llvm_str:
resolved: ir.Type | None = Gen._type_str_to_llvm(llvm_str)
if resolved:
return resolved
# 检查是否是已注册的结构体类型
if ann_name in Gen.structs:
return Gen.structs[ann_name]
return None
def _HandleCPtrToIntLlvm(self, Node: ast.Call) -> ir.Value:
Gen: LlvmGeneratorMixin = self.Trans.LlvmGen
if not Node.args:
return ir.Constant(ir.IntType(64), 0)
arg_val = self.HandleExprLlvm(Node.args[0])
arg_val: ir.Value | None = self.HandleExprLlvm(Node.args[0])
if arg_val is None:
return ir.Constant(ir.IntType(64), 0)
if isinstance(arg_val.type, ir.PointerType):
@@ -223,38 +286,35 @@ class CSpecialCallHandle(BaseHandle):
class TSpecialCallHandle(BaseHandle):
@staticmethod
def _ResolveTAttrToCName(attr: str) -> str:
from lib.includes.t import CTypeRegistry
ctype_cls = CTypeRegistry.GetClassByName(attr)
def _ResolveTAttrToCName(attr: str) -> str | None:
ctype_cls: type | None = CTypeRegistry.GetClassByName(attr)
if ctype_cls is not None:
try:
inst = ctype_cls()
cname = getattr(inst, 'CName', '')
cname = type(inst).__name__
if cname:
return cname
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 None
def _HandleTSpecialCallLlvm(self, Node):
Gen = self.Trans.LlvmGen
def _HandleTSpecialCallLlvm(self, Node: ast.Call) -> ir.Value | None:
Gen: LlvmGeneratorMixin = self.Trans.LlvmGen
if not Node.args:
return None
attr = Node.func.attr
attr: str = Node.func.attr
if attr == 'CType':
return self._HandleCTypeLlvm(Node)
target_type = self._ResolveTAttrToCName(attr)
target_type: str | None = self._ResolveTAttrToCName(attr)
if target_type is not None:
IsPtr_cast = False
if len(Node.args) >= 2:
second_arg = Node.args[1]
if isinstance(second_arg, ast.Attribute) and isinstance(second_arg.value, ast.Name) and second_arg.value.id == 't' and second_arg.attr == 'CPtr':
if isinstance(second_arg, ast.Attribute) and isinstance(second_arg.value, ast.Name) and IsTModule(second_arg.value.id, self.Trans.SymbolTable) and second_arg.attr == 'CPtr':
IsPtr_cast = True
elif isinstance(second_arg, ast.Name) and second_arg.id == 'CPtr':
IsPtr_cast = True
@@ -265,20 +325,20 @@ class TSpecialCallHandle(BaseHandle):
return self.Trans.ExprCallHandle._HandleTypeCastLlvm(Node.args[0], target_type)
return None
def _HandleCTypeLlvm(self, Node):
Gen = self.Trans.LlvmGen
arg_val = self.HandleExprLlvm(Node.args[0])
def _HandleCTypeLlvm(self, Node: ast.Call) -> ir.Value | None:
Gen: LlvmGeneratorMixin = self.Trans.LlvmGen
arg_val: ir.Value | None = self.HandleExprLlvm(Node.args[0])
if not arg_val:
return None
target_type_str = 'unsigned long long'
target_type_str: str = 'unsigned long long'
if len(Node.args) >= 2:
type_parts = []
ptr_count = 0
type_parts: list[str] = []
ptr_count: int = 0
for i in range(1, len(Node.args)):
type_arg = Node.args[i]
if isinstance(type_arg, ast.Attribute) and isinstance(type_arg.value, ast.Name) and type_arg.value.id == 't':
if isinstance(type_arg, ast.Attribute) and isinstance(type_arg.value, ast.Name) and IsTModule(type_arg.value.id, self.Trans.SymbolTable):
type_attr = type_arg.attr
_PREFIX_MAP = {
_PREFIX_MAP: dict[str, str] = {
'CUnsigned': 'unsigned', 'CSigned': 'signed',
'CConst': 'const', 'CVolatile': 'volatile',
}
@@ -299,12 +359,11 @@ class TSpecialCallHandle(BaseHandle):
return int_val
return self.Trans.ExprCallHandle._HandleTypeCastLlvm(Node.args[0], target_type_str)
def _HandleTPtrCastLlvm(self, Node, attr):
Gen = self.Trans.LlvmGen
from lib.includes.t import CTypeRegistry
def _HandleTPtrCastLlvm(self, Node: ast.Call, attr: str) -> ir.Value | None:
Gen: LlvmGeneratorMixin = self.Trans.LlvmGen
if attr in ('CChar', 'CUnsignedChar'):
first_arg = Node.args[0]
if isinstance(first_arg, ast.Call) and isinstance(first_arg.func, ast.Attribute) and isinstance(first_arg.func.value, ast.Name) and first_arg.func.value.id == 't' and first_arg.func.attr == 'CInt' and first_arg.args:
if isinstance(first_arg, ast.Call) and isinstance(first_arg.func, ast.Attribute) and isinstance(first_arg.func.value, ast.Name) and IsTModule(first_arg.func.value.id, self.Trans.SymbolTable) and first_arg.func.attr == 'CInt' and first_arg.args:
inner_val = self.HandleExprLlvm(first_arg.args[0])
if isinstance(inner_val.type, ir.PointerType):
return Gen.builder.bitcast(inner_val, ir.PointerType(ir.IntType(8)), name=f"c{attr.lower()}_ptr_from_cint")