refactor(handles): 删除 CSpecialCallHandle/TSpecialCallHandle

EmitRawCopyLlvm 改为模块级函数;删除 c./t. 语法糖处理类及 BaseTranslator 实例化,全仓零引用。
This commit is contained in:
TermiNexus committed 2026-10-18 21:51:10 +08:00
1 parent d15ae02f3e
commit 2e80424d67
6 files changed
+30 -193

No files matched your search

+2 -1
View File
@@ -6,6 +6,7 @@ import vast as ast
import sys
import llvmlite.ir as ir
from lib.core.Handles.HandlesBase import BaseHandle, CTypeInfo, FuncMeta
from lib.core.Handles.HandlesSpecialCall import EmitRawCopyLlvm
from lib.core.VLogger import get_logger as _vlog
from lib.core.ConstEvaluator import ConstEvaluator, EvalContext
from lib.constants.config import mode as _config_mode
@@ -599,7 +600,7 @@ class AssignHandle(BaseHandle):
f"解引用赋值右侧 '*' 的操作数必须是指针类型(类型推断退化,"
f"实际 {SrcPtr.type}){Gen._get_node_info()}"
)
if self.Trans.CSpecialCallHandle.EmitRawCopyLlvm(Ptr, SrcPtr, Gen):
if EmitRawCopyLlvm(Ptr, SrcPtr, Gen):
return
DerefValue: ir.Value | None = self.HandleExprLlvm(Node.value)
if DerefValue is None:
-10
View File
@@ -45,16 +45,6 @@ class ExprBuiltinHandle(BaseHandle):
return None
FuncName: str = Node.func.id
# Two-arg scalar alias form (int(v, CPtr) / char / bool / float / double)
# is a pointer wrap, not a scalar cast: route it to the same exit as the
# attribute form CInt(v, CPtr). Ignoring the CPtr mark would degrade
# it to a bare trunc, e.g. includes/argparse.vp get_bool() reading a
# pointer's low 32 bits instead of the stored value.
if (len(Node.args) >= 2 and FuncName in ('int', 'char', 'bool', 'float', 'double')
and self.Trans.ExprCallHandle._IsCPtrMark(Node.args[1])):
PtrCastAttr: str = 'C' + FuncName[0].upper() + FuncName[1:]
return self.Trans.TSpecialCallHandle._HandleTPtrCastLlvm(Node, PtrCastAttr)
if FuncName == 'print':
return self._HandlePrintLlvm(Node)
elif FuncName == 'len':
-3
View File
@@ -3253,9 +3253,6 @@ class ExprCallHandle(BaseHandle):
if FuncMeta.CLASS_METHOD in SymInfo.MetaList:
return self._HandleStaticMethodCallLlvm(Node, ClassName, MethodName)
if isinstance(Node.func.value, ast.Name) :
result = self.Trans.TSpecialCallHandle._HandleTSpecialCallLlvm(Node)
if result is not None:
return result
ctype_cls = CTypeRegistry.GetClassByName(MethodName)
if ctype_cls is not None:
try:
+28 -175
View File
@@ -1,175 +1,28 @@
from __future__ import annotations
from typing import TYPE_CHECKING
import vast as 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
from lib.core.TypeSystem import CTypeRegistry
from lib.core.VLogger import get_logger as _vlog
from lib.constants.config import mode as _config_mode
class CSpecialCallHandle(BaseHandle):
def EmitRawCopyLlvm(self, DstPtr: ir.Value, SrcPtr: ir.Value, Gen: LlvmGeneratorMixin,
NamePrefix: str = "rawcopy") -> bool:
"""Emit `*dst = *src` as a raw byte copy (Load semantics); False if unusable.
The width comes from the destination pointee and the source pointer is
bitcast to it, so this reinterprets memory instead of converting values
(e.g. `*&bits = *&dbl` must keep the IEEE bits, not fptosi).
"""
if not isinstance(DstPtr.type, ir.PointerType) or not isinstance(SrcPtr.type, ir.PointerType):
return False
Pointee: ir.Type = DstPtr.type.pointee
if isinstance(Pointee, ir.VoidType):
return False
TargetPtrTy: ir.PointerType = ir.PointerType(Pointee)
SrcCast: ir.Value = SrcPtr if SrcPtr.type == TargetPtrTy else Gen.builder.bitcast(SrcPtr, TargetPtrTy, name=f"{NamePrefix}_src_cast")
Loaded: ir.Value | None = Gen._load(SrcCast, name=f"{NamePrefix}_loaded")
if Loaded is None:
return False
DstCast: ir.Value = DstPtr if DstPtr.type == TargetPtrTy else Gen.builder.bitcast(DstPtr, TargetPtrTy, name=f"{NamePrefix}_dst_cast")
Gen._store(Loaded, DstCast)
return True
def _ResolveTAttrToCName(attr: str) -> str | None:
ctype_cls: type | None = CTypeRegistry.GetClassByName(attr)
if ctype_cls is not None:
try:
inst = ctype_cls()
cname = type(inst).__name__
if cname:
return cname
except Exception as _e:
if _config_mode == "strict":
raise
_vlog().warning(f"处理函数调用失败: {_e}", "Exception")
return None
def _HandleTSpecialCallLlvm(self, Node: ast.Call) -> ir.Value | None:
Gen: LlvmGeneratorMixin = self.Trans.LlvmGen
if not Node.args:
return None
attr: str = Node.func.attr
if attr == 'CType':
return self._HandleCTypeLlvm(Node)
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.Name) and second_arg.id == 'CPtr':
IsPtr_cast = True
if IsPtr_cast:
return self._HandleTPtrCastLlvm(Node, attr)
if target_type == 'void':
target_type = 'void *'
return self.Trans.ExprCallHandle._HandleTypeCastLlvm(Node.args[0], target_type)
return None
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: str = 'unsigned long long'
if len(Node.args) >= 2:
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.Name):
type_attr = type_arg.id
_PREFIX_MAP: dict[str, str] = {
'CUnsigned': 'unsigned', 'CSigned': 'signed',
'CConst': 'const', 'CVolatile': 'volatile',
}
if type_attr in _PREFIX_MAP:
type_parts.append(_PREFIX_MAP[type_attr])
elif type_attr in ('CPtr', 'CArrayPtr'):
ptr_count += 1
else:
resolved = self._ResolveTAttrToCName(type_attr)
if resolved is not None:
type_parts.append(resolved)
if type_parts:
target_type_str = ' '.join(type_parts)
if ptr_count > 0:
target_type_str += ' ' + '*' * ptr_count
if isinstance(arg_val.type, ir.PointerType):
int_val = Gen.builder.ptrtoint(arg_val, ir.IntType(64), name="ptr_to_int")
return int_val
return self.Trans.ExprCallHandle._HandleTypeCastLlvm(Node.args[0], target_type_str)
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.Name) and first_arg.func.id == '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")
expr_val = self.HandleExprLlvm(Node.args[0])
if isinstance(expr_val.type, ir.IntType) and expr_val.type.width == 8:
var = Gen._alloca(ir.ArrayType(ir.IntType(8), 2), name=f"c{attr.lower()}_ptr")
zero = ir.Constant(ir.IntType(32), 0)
char_ptr = Gen.builder.gep(var, [zero, zero], name="char_ptr")
Gen._store(expr_val, char_ptr)
null_char = ir.Constant(ir.IntType(8), 0)
null_ptr = Gen.builder.gep(var, [zero, ir.Constant(ir.IntType(32), 1)], name="null_ptr")
Gen._store(null_char, null_ptr)
return char_ptr
elif isinstance(expr_val.type, ir.PointerType):
if isinstance(expr_val.type.pointee, ir.PointerType):
Loaded_ptr = Gen._load(expr_val, name="load_ptr")
if isinstance(Loaded_ptr.type, ir.PointerType) and isinstance(Loaded_ptr.type.pointee, ir.IntType) and Loaded_ptr.type.pointee.width == 8:
return Loaded_ptr
if isinstance(expr_val.type.pointee, ir.IntType) and expr_val.type.pointee.width == 8:
return expr_val
return Gen.builder.bitcast(expr_val, ir.PointerType(ir.IntType(8)), name="cast_to_char_ptr")
elif isinstance(expr_val.type, ir.IntType):
if expr_val.type.width == 32:
expr_val = Gen.builder.zext(expr_val, ir.IntType(64), name="zext_to_64")
return Gen.builder.inttoptr(expr_val, ir.PointerType(ir.IntType(8)), name=f"inttoptr_c{attr.lower()}")
return Gen.emit_constant(0, 'int')
elif attr == 'CVoid':
return self.Trans.ExprCallHandle._HandleTypeCastLlvm(Node.args[0], 'void *')
elif attr == 'CInt':
expr_val = self.HandleExprLlvm(Node.args[0])
if expr_val:
if isinstance(expr_val.type, ir.IntType):
if expr_val.type.width < 64:
expr_val = Gen.builder.zext(expr_val, ir.IntType(64), name="zext_to_64")
return Gen.builder.inttoptr(expr_val, ir.PointerType(ir.IntType(32)), name="cint_ptr")
return Gen.builder.bitcast(expr_val, ir.PointerType(ir.IntType(32)), name="cint_ptr")
else:
ctype_cls = CTypeRegistry.GetClassByName(attr)
if ctype_cls is not None:
llvm_str = CTypeRegistry.CTypeToLLVM(ctype_cls)
target_type = Gen._type_str_to_llvm(llvm_str)
if target_type:
# 基础类型 (int/float) → 加一层指针 → T*
if isinstance(target_type, (ir.IntType, ir.FloatType, ir.DoubleType)):
target_ptr_type = ir.PointerType(target_type)
expr_val = self.HandleExprLlvm(Node.args[0])
if expr_val:
if isinstance(expr_val.type, ir.IntType):
if expr_val.type.width < 64:
expr_val = Gen.builder.zext(expr_val, ir.IntType(64), name="zext_to_64")
return Gen.builder.inttoptr(expr_val, target_ptr_type, name=f"{attr.lower()}_ptr")
return Gen.builder.bitcast(expr_val, target_ptr_type, name=f"{attr.lower()}_ptr")
# 指针类型 (如 CPtr → i8*) → 再加一层指针 → i8**
elif isinstance(target_type, ir.PointerType):
target_ptr_type = ir.PointerType(target_type)
expr_val = self.HandleExprLlvm(Node.args[0])
if expr_val:
if isinstance(expr_val.type, ir.IntType):
if expr_val.type.width < 64:
expr_val = Gen.builder.zext(expr_val, ir.IntType(64), name="zext_to_64")
return Gen.builder.inttoptr(expr_val, target_ptr_type, name=f"{attr.lower()}_ptr")
return Gen.builder.bitcast(expr_val, target_ptr_type, name=f"{attr.lower()}_ptr")
return None
from __future__ import annotations
from typing import TYPE_CHECKING
import llvmlite.ir as ir
if TYPE_CHECKING:
from lib.core.Translator.LlvmGenerator import LlvmGeneratorMixin
def EmitRawCopyLlvm(DstPtr: ir.Value, SrcPtr: ir.Value, Gen: LlvmGeneratorMixin,
NamePrefix: str = "rawcopy") -> bool:
"""Emit `*dst = *src` as a raw byte copy (Load semantics); False if unusable.
The width comes from the destination pointee and the source pointer is
bitcast to it, so this reinterprets memory instead of converting values
(e.g. `*&bits = *&dbl` must keep the IEEE bits, not fptosi).
"""
if not isinstance(DstPtr.type, ir.PointerType) or not isinstance(SrcPtr.type, ir.PointerType):
return False
Pointee: ir.Type = DstPtr.type.pointee
if isinstance(Pointee, ir.VoidType):
return False
TargetPtrTy: ir.PointerType = ir.PointerType(Pointee)
SrcCast: ir.Value = SrcPtr if SrcPtr.type == TargetPtrTy else Gen.builder.bitcast(SrcPtr, TargetPtrTy, name=f"{NamePrefix}_src_cast")
Loaded: ir.Value | None = Gen._load(SrcCast, name=f"{NamePrefix}_loaded")
if Loaded is None:
return False
DstCast: ir.Value = DstPtr if DstPtr.type == TargetPtrTy else Gen.builder.bitcast(DstPtr, TargetPtrTy, name=f"{NamePrefix}_dst_cast")
Gen._store(Loaded, DstCast)
return True
-1
View File
@@ -16,7 +16,6 @@ from .HandlesExprAsm import ExprAsmHandle
from .HandlesExprFormat import ExprFormatHandle
from .HandlesExprLambda import ExprLambdaHandle
from .HandlesExprCall import ExprCallHandle
from .HandlesSpecialCall import CSpecialCallHandle, TSpecialCallHandle
from .HandlesBody import BodyHandle
from .HandlesReturn import ReturnHandle
from .HandlesAssign import AssignHandle
-3
View File
@@ -16,7 +16,6 @@ from lib.core.Handles import (
WithHandle, TryHandle, AssertHandle, RaiseHandle, MatchHandle,
ExprUtils, ExprOpsHandle, ExprAttrHandle, ExprBuiltinHandle,
ExprAsmHandle, ExprFormatHandle, ExprLambdaHandle, ExprCallHandle,
CSpecialCallHandle, TSpecialCallHandle,
ClassHandle,
FunctionHandle,
ImportHandle,
@@ -107,8 +106,6 @@ class BaseTranslatorMixin:
self.ExprFormatHandle = ExprFormatHandle(self)
self.ExprLambdaHandle = ExprLambdaHandle(self)
self.ExprCallHandle = ExprCallHandle(self)
self.CSpecialCallHandle = CSpecialCallHandle(self)
self.TSpecialCallHandle = TSpecialCallHandle(self)
self.ClassHandler = ClassHandle(self)
self.FunctionHandler = FunctionHandle(self)
self.ImportHandler = ImportHandle(self)