c.py 删除 CElif/CElse/CEndif 三个类及其 Library_C 登记;HandlesSpecialCall 删除无人调用的 _HandleCIfLlvm;_REMOVED_CIF_CALL_MSG 的报文补齐 CElif/CElse/CEndif 六个拼写。Converter.py 去掉已无意义的注释掉守卫与 c.CIfndef/c.CEndif 时代注释,示例改为仍在用的 c.CUndef/c.CPragma;ExprParser/ConstEvaluator/HandlesIf 的注释把内部标记统一写成 c.@CIfdef 与 cif 标记。
411 lines
25 KiB
Python
411 lines
25 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.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 _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]
|
||
if isinstance(Arg, ast.Call):
|
||
ClassName = None
|
||
if isinstance(Arg.func, ast.Name):
|
||
ClassName = Arg.func.id
|
||
elif isinstance(Arg.func, ast.Attribute):
|
||
ClassName = Arg.func.attr
|
||
if ClassName and ClassName in Gen.structs:
|
||
StructType = Gen.structs[ClassName]
|
||
if isinstance(StructType, ir.PointerType):
|
||
StructType = StructType.pointee
|
||
ObjPtr = Gen._allocaEntry(StructType, name=f"{ClassName}_obj")
|
||
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]
|
||
InitArgs = [ObjPtr]
|
||
for carg in Arg.args:
|
||
ArgVal = self.HandleExprLlvm(carg)
|
||
if ArgVal:
|
||
InitArgs.append(ArgVal)
|
||
for kw in Arg.keywords:
|
||
ArgVal = self.HandleExprLlvm(kw.value)
|
||
if ArgVal:
|
||
InitArgs.append(ArgVal)
|
||
if hasattr(self.Trans.ExprCallHandle, '_append_eh_msg_out_arg'):
|
||
self.Trans.ExprCallHandle._append_eh_msg_out_arg(InitArgs, func, Gen)
|
||
adjusted = Gen._adjust_args(InitArgs, func)
|
||
Gen.builder.call(func, adjusted, name=f"{ClassName}_construct")
|
||
return Gen.builder.bitcast(ObjPtr, ir.IntType(8).as_pointer(), name=f"{ClassName}_as_i8ptr")
|
||
if isinstance(Arg, ast.Subscript):
|
||
SubPtr = self.Trans.ExprAttrHandle.HandleSubscriptPtrLlvm(Arg)
|
||
if SubPtr and isinstance(SubPtr.type, ir.PointerType):
|
||
return Gen.builder.bitcast(SubPtr, ir.IntType(8).as_pointer(), name="addr_subscript_as_i8ptr")
|
||
if isinstance(Arg, ast.Attribute):
|
||
AttrPtr = self.Trans.ExprAttrHandle._get_attr_ptr(Arg)
|
||
if AttrPtr and isinstance(AttrPtr.type, ir.PointerType):
|
||
return Gen.builder.bitcast(AttrPtr, ir.IntType(8).as_pointer(), name="addr_attr_as_i8ptr")
|
||
if isinstance(Arg, ast.Name):
|
||
VarName = Arg.id
|
||
if VarName in Gen.functions:
|
||
func = Gen.functions[VarName]
|
||
return Gen.builder.bitcast(func, ir.IntType(8).as_pointer(), name="addr_func_as_i8ptr")
|
||
if VarName in Gen.variables and Gen.variables[VarName] is not None:
|
||
var_ptr = Gen.variables[VarName]
|
||
if isinstance(var_ptr.type, ir.PointerType):
|
||
# For pointer-to-pointer allocas (var_ptr is T**):
|
||
# - If T is a named struct (@t.Object class), the variable semantically
|
||
# IS the struct, so c.Addr should return the struct pointer value.
|
||
# - If T is a primitive pointer type (e.g., i8*), the variable semantically
|
||
# holds a pointer, so c.Addr should return &var (alloca address).
|
||
if isinstance(var_ptr.type.pointee, ir.PointerType):
|
||
pointee = var_ptr.type.pointee.pointee
|
||
if isinstance(pointee, ir.IdentifiedStructType):
|
||
# @t.Object class variable — return Loaded struct pointer
|
||
ArgVal = self.HandleExprLlvm(Arg)
|
||
if ArgVal and isinstance(ArgVal.type, ir.PointerType):
|
||
return Gen.builder.bitcast(ArgVal, ir.IntType(8).as_pointer(), name="addr_as_i8ptr")
|
||
# Pointer-type variable — return alloca address (&var)
|
||
return Gen.builder.bitcast(var_ptr, ir.IntType(8).as_pointer(), name="addr_as_i8ptr")
|
||
return Gen.builder.bitcast(var_ptr, ir.IntType(8).as_pointer(), name="addr_as_i8ptr")
|
||
ArgVal = self.HandleExprLlvm(Arg)
|
||
if ArgVal:
|
||
if isinstance(ArgVal.type, ir.IntType):
|
||
alloca = Gen._alloca(ArgVal.type, name="addr_tmp")
|
||
Gen._store(ArgVal, alloca)
|
||
return Gen.builder.bitcast(alloca, ir.IntType(8).as_pointer(), name="addr_as_i8ptr")
|
||
elif isinstance(ArgVal.type, ir.PointerType):
|
||
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: ast.Call) -> ir.Value:
|
||
Gen: LlvmGeneratorMixin = self.Trans.LlvmGen
|
||
if len(Node.args) >= 2:
|
||
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:
|
||
deref_arg = target_arg.args[0]
|
||
if isinstance(deref_arg, ast.Name) and deref_arg.id in Gen.variables and Gen.variables[deref_arg.id] is not None:
|
||
target_ptr = Gen._load(Gen.variables[deref_arg.id], name="deref_load_ptr")
|
||
else:
|
||
inner_value = self.HandleExprLlvm(deref_arg)
|
||
if inner_value:
|
||
if isinstance(inner_value.type, ir.PointerType):
|
||
if isinstance(inner_value.type.pointee, ir.PointerType):
|
||
inner_value = Gen._load(inner_value, name="cast_deref")
|
||
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 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:
|
||
inner_val = self.HandleExprLlvm(target_arg.args[0])
|
||
if inner_val and isinstance(inner_val.type, ir.PointerType):
|
||
target_llvm_type = Gen._basic_type_to_llvm(resolved_cname)
|
||
if target_llvm_type:
|
||
target_ptr = Gen.builder.bitcast(inner_val, ir.PointerType(target_llvm_type), name="tcast_ptr")
|
||
if not target_ptr:
|
||
if isinstance(target_arg, ast.Subscript):
|
||
target_ptr = self.Trans.ExprAttrHandle.HandleSubscriptPtrLlvm(target_arg)
|
||
else:
|
||
target_ptr = self.HandleExprLlvm(target_arg)
|
||
Val = self.HandleExprLlvm(value_arg)
|
||
if target_ptr and Val:
|
||
if isinstance(target_ptr.type, ir.PointerType):
|
||
ValToStore = Val
|
||
pointee = target_ptr.type.pointee
|
||
if isinstance(pointee, ir.PointerType) and isinstance(pointee.pointee, ir.IntType) and pointee.pointee.width == 8:
|
||
if isinstance(Val.type, ir.PointerType) and isinstance(Val.type.pointee, ir.IntType) and Val.type.pointee.width == 8:
|
||
ValToStore = Val
|
||
elif isinstance(Val.type, ir.IntType):
|
||
ValToStore = Gen.builder.inttoptr(Val, pointee, name="int_to_ptr_set")
|
||
elif isinstance(pointee, ir.IntType):
|
||
if isinstance(Val.type, ir.ArrayType) and isinstance(Val.type.element, ir.IntType) and Val.type.element.width == 8:
|
||
zero = ir.Constant(ir.IntType(32), 0)
|
||
value_ptr = Gen.builder.gep(Val, [zero, zero], name="value_ptr")
|
||
ValToStore = Gen._load(value_ptr, name="Load_value")
|
||
elif isinstance(Val.type, ir.PointerType) and isinstance(Val.type.pointee, ir.IntType) and Val.type.pointee.width == 8:
|
||
ValToStore = Gen._load(Val, name="Load_char_value")
|
||
if isinstance(ValToStore.type, ir.IntType) and isinstance(pointee, ir.IntType):
|
||
if ValToStore.type.width < pointee.width:
|
||
ValToStore = Gen.builder.zext(ValToStore, pointee, name="zext_set")
|
||
elif ValToStore.type.width > pointee.width:
|
||
ValToStore = Gen.builder.trunc(ValToStore, pointee, name="trunc_set")
|
||
elif Val.type != pointee:
|
||
if isinstance(pointee, ir.PointerType) and isinstance(Val.type, ir.PointerType):
|
||
ValToStore = Gen.builder.bitcast(Val, pointee, name="bitcast_set")
|
||
Gen._store(ValToStore, target_ptr)
|
||
return ir.Constant(ir.IntType(32), 1)
|
||
|
||
def EmitRawCopyLlvm(self, DstPtr: ir.Value, SrcPtr: ir.Value, Gen: LlvmGeneratorMixin,
|
||
NamePrefix: str = "rawcopy") -> bool:
|
||
"""Emit `*dst = *src` as a raw byte copy (c.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 _HandleCLoadLlvm(self, Node: ast.Call) -> ir.Value:
|
||
Gen: LlvmGeneratorMixin = self.Trans.LlvmGen
|
||
if len(Node.args) < 2:
|
||
return ir.Constant(ir.IntType(32), 0)
|
||
# c.Load(a, b) 语义: *a = *b(a 是目标,b 是源)
|
||
# wiki 文档: c.Load(ptr, value) -> *ptr = *value;
|
||
dst_val: ir.Value | None = self.HandleExprLlvm(Node.args[0])
|
||
src_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):
|
||
return ir.Constant(ir.IntType(32), 0)
|
||
pointee = dst_val.type.pointee
|
||
# c.Addr 统一返回 i8* 通用指针,丢失原始类型信息。
|
||
# 若 dst 是 c.Addr(var),从 var 的 alloca 类型推断真实 pointee(如 i64),
|
||
# 否则 c.Load 只会按 i8 加载 1 字节(IEEE 754 double→u64 位重解释 bug)。
|
||
if (isinstance(pointee, ir.IntType) and pointee.width == 8
|
||
and isinstance(Node.args[0], ast.Call)
|
||
and isinstance(Node.args[0].func, ast.Attribute)
|
||
and Node.args[0].func.attr == 'Addr'
|
||
and Node.args[0].args
|
||
and isinstance(Node.args[0].args[0], ast.Name)):
|
||
var_name = Node.args[0].args[0].id
|
||
if var_name in Gen.variables and Gen.variables[var_name] is not None:
|
||
var_ptr = Gen.variables[var_name]
|
||
if isinstance(var_ptr.type, ir.PointerType):
|
||
pointee = var_ptr.type.pointee
|
||
TargetPtrTy: ir.PointerType = ir.PointerType(pointee)
|
||
DstPtr: ir.Value = dst_val if dst_val.type == TargetPtrTy else Gen.builder.bitcast(dst_val, TargetPtrTy, name="cLoad_dst_cast")
|
||
return ir.Constant(ir.IntType(32), 1 if self.EmitRawCopyLlvm(DstPtr, src_val, Gen, "cLoad") else 0)
|
||
|
||
def _HandleCDerefLlvm(self, Node: ast.Call) -> ir.Value:
|
||
Gen: LlvmGeneratorMixin = self.Trans.LlvmGen
|
||
if not Node.args:
|
||
return ir.Constant(ir.IntType(64), 0)
|
||
# 检测嵌套 c.Deref(c.Deref(...)):设置标志让内层 Deref 加载为指针
|
||
IsNestedDeref: bool = (
|
||
isinstance(Node.args[0], ast.Call)
|
||
and isinstance(Node.args[0].func, ast.Attribute)
|
||
and Node.args[0].func.attr == 'Deref'
|
||
)
|
||
if IsNestedDeref:
|
||
Gen._nested_deref_load_ptr = True
|
||
try:
|
||
arg_val: ir.Value | None = self.HandleExprLlvm(Node.args[0])
|
||
finally:
|
||
if IsNestedDeref:
|
||
Gen._nested_deref_load_ptr = False
|
||
if arg_val is None:
|
||
return ir.Constant(ir.IntType(32), 0)
|
||
if isinstance(arg_val.type, ir.PointerType):
|
||
# 嵌套 Deref 的内层:加载为指针 (i8*),不推断目标类型
|
||
# 因为结果会被外层 Deref 再次解引用
|
||
NestedLoadPtr: bool = getattr(Gen, '_nested_deref_load_ptr', False)
|
||
if NestedLoadPtr:
|
||
PtrType: ir.Type = ir.PointerType(ir.IntType(8))
|
||
casted: ir.Value = Gen.builder.bitcast(arg_val, ir.PointerType(PtrType), name="deref_cast")
|
||
Loaded = Gen._load(casted, name="deref")
|
||
if Loaded is not None:
|
||
return Loaded
|
||
# 读取宽度只由指针的 pointee 类型决定(_load 按 arg_val.type.pointee
|
||
# 加载一个元素):pointee 是 i8(t.CPtr / void* / str / bytes)即恒读
|
||
# 1 字节,不再按赋值目标注解反推宽度——那会让同一处 c.Deref(i8*) 的
|
||
# 读取宽度取决于它是否恰好出现在带注解赋值的 RHS 里。需要 4/8 字节等
|
||
# 更宽读取时,由调用点显式给出元素类型指针后再解引用
|
||
# (c.Deref((int | t.CPtr)(p)) / c.Deref(t.CUInt64T(p, t.CPtr)))。
|
||
Loaded = Gen._load(arg_val, name="deref")
|
||
if Loaded is not None:
|
||
return Loaded
|
||
return arg_val
|
||
|
||
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: 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):
|
||
return Gen.builder.ptrtoint(arg_val, ir.IntType(64), name="ptrtoint_result")
|
||
if isinstance(arg_val.type, ir.IntType):
|
||
if arg_val.type.width < 64:
|
||
return Gen.builder.zext(arg_val, ir.IntType(64), name="zext_ptrtoint")
|
||
elif arg_val.type.width > 64:
|
||
return Gen.builder.trunc(arg_val, ir.IntType(64), name="trunc_ptrtoint")
|
||
return arg_val
|
||
return ir.Constant(ir.IntType(64), 0)
|
||
|
||
|
||
class TSpecialCallHandle(BaseHandle):
|
||
|
||
@staticmethod
|
||
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.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
|
||
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.Attribute) and isinstance(type_arg.value, ast.Name) and IsTModule(type_arg.value.id, self.Trans.SymbolTable):
|
||
type_attr = type_arg.attr
|
||
_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.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")
|
||
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
|