Files
TransPyC/lib/core/Handles/HandlesSpecialCall.py
T
TermiNexus c94cdd7174 refactor(c): 删除 c.* 及对应的裸名语法糖处理分支
移除 c.CIf 判断、Addr/Load/Deref/DerefAs/PtrToInt 裸名分支及 _HandleC* 处理函数;c. 前缀退役后不再保留任何处理路径。
2026-10-18 21:48:37 +08:00

176 lines
9.6 KiB
Python

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