修复了大量存在的问题,增加了假鸭子类型等等机制
This commit is contained in:
@@ -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")
|
||||
|
||||
Reference in New Issue
Block a user