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

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

@@ -2,13 +2,18 @@ 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
from lib.core.Translator.LlvmGenerator import LlvmGeneratorMixin
import ast
import llvmlite.ir as ir
from lib.core.Handles.HandlesBase import BaseHandle
from lib.core.VLogger import get_logger as _vlog
from lib.constants.config import mode as _config_mode
from lib.includes.t import CTypeRegistry
from lib.core.SymbolUtils import IsTModule, ExtractTypeNameFromBinOp
class ExprBuiltinHandle(BaseHandle):
_C_LIB_FUNCS = {
_C_LIB_FUNCS: dict[str, object] = {
'strlen': lambda: (ir.IntType(64), [ir.PointerType(ir.IntType(8))]),
'strlength': lambda: (ir.IntType(64), [ir.PointerType(ir.IntType(8))]),
'memset': lambda: (ir.PointerType(ir.IntType(8)), [ir.PointerType(ir.IntType(8)), ir.IntType(32), ir.IntType(64)]),
@@ -27,11 +32,11 @@ class ExprBuiltinHandle(BaseHandle):
'labs': lambda: (ir.IntType(64), [ir.IntType(64)]),
}
def _HandleBuiltinCallLlvm(self, Node):
Gen = self.Trans.LlvmGen
def _HandleBuiltinCallLlvm(self, Node: ast.Call) -> ir.Value | None:
Gen: LlvmGeneratorMixin = self.Trans.LlvmGen
if not isinstance(Node.func, ast.Name):
return None
FuncName = Node.func.id
FuncName: str = Node.func.id
if FuncName == 'print':
return self._HandlePrintLlvm(Node)
@@ -145,6 +150,19 @@ class ExprBuiltinHandle(BaseHandle):
return arg_val
return self._EmitStringFromValue(arg_val)
return ir.Constant(ir.IntType(8).as_pointer(), None)
elif FuncName == 'bytes':
# bytes() — 类型转换为 i8* 指针 (等同于 t.CPtr / str)
# bytes(int_addr) → inttoptr; bytes(ptr) → bitcast
if Node.args:
arg_val = self.HandleExprLlvm(Node.args[0])
if arg_val:
if isinstance(arg_val.type, ir.PointerType):
if isinstance(arg_val.type.pointee, ir.IntType) and arg_val.type.pointee.width == 8:
return arg_val
return Gen.builder.bitcast(arg_val, ir.IntType(8).as_pointer(), name="bytes_cast")
if isinstance(arg_val.type, ir.IntType):
return Gen.builder.inttoptr(arg_val, ir.IntType(8).as_pointer(), name="bytes_int2ptr")
return ir.Constant(ir.IntType(8).as_pointer(), None)
elif FuncName == 'input':
return self._HandleInputLlvm(Node)
elif FuncName == 'ord':
@@ -177,22 +195,22 @@ class ExprBuiltinHandle(BaseHandle):
return self._HandleTypeLlvm(Node)
return None
def _HandlePrintLlvm(self, Node):
Gen = self.Trans.LlvmGen
printf_func = Gen.get_or_declare_c_func('printf', ir.FunctionType(ir.IntType(32), [ir.PointerType(ir.IntType(8))], var_arg=True))
args = Node.args
end_arg = None
sep_arg = None
def _HandlePrintLlvm(self, Node: ast.Call) -> ir.Value | None:
Gen: LlvmGeneratorMixin = self.Trans.LlvmGen
printf_func: ir.Function = Gen.get_or_declare_c_func('printf', ir.FunctionType(ir.IntType(32), [ir.PointerType(ir.IntType(8))], var_arg=True))
args: list[ast.expr] = Node.args
end_arg: ast.expr | None = None
sep_arg: ast.expr | None = None
if Node.keywords:
for kw in Node.keywords:
if kw.arg == 'end':
end_arg = kw.value
elif kw.arg == 'sep':
sep_arg = kw.value
sep_str = ' '
sep_str: str = ' '
if sep_arg and isinstance(sep_arg, ast.Constant) and isinstance(sep_arg.value, str):
sep_str = sep_arg.value
end_str = '\n'
end_str: str = '\n'
if end_arg:
if isinstance(end_arg, ast.Constant) and isinstance(end_arg.value, str):
end_str = end_arg.value
@@ -202,11 +220,10 @@ class ExprBuiltinHandle(BaseHandle):
if end_str:
nl_fmt = Gen.emit_constant(end_str, 'string')
Gen.builder.call(printf_func, [nl_fmt], name="print_nl")
return
return ir.Constant(ir.IntType(32), 0)
has_fstring = any(isinstance(arg, ast.JoinedStr) for arg in args)
if has_fstring:
self._HandlePrintWithFString(Node, printf_func, args, sep_str, end_str)
return
return self._HandlePrintWithFString(Node, printf_func, args, sep_str, end_str)
fmt_parts = []
fmt_args = []
for i, arg in enumerate(args):
@@ -288,25 +305,20 @@ class ExprBuiltinHandle(BaseHandle):
fmt_parts.append('(unknown)')
fmt_parts.append(end_str)
fmt_str = ''.join(fmt_parts)
fmt_bytes = fmt_str.encode('utf-8') + b'\x00'
fmt_type = ir.ArrayType(ir.IntType(8), len(fmt_bytes))
fmt_const = ir.Constant(fmt_type, bytearray(fmt_bytes))
fmt_gvar = ir.GlobalVariable(Gen.module, fmt_type, name=f"str_const_{Gen.string_const_counter}")
Gen.string_const_counter += 1
fmt_gvar.initializer = fmt_const
fmt_gvar.linkage = 'internal'
fmt_ptr = Gen.builder.bitcast(fmt_gvar, ir.PointerType(ir.IntType(8)), name="print_fmt")
fmt_ptr = Gen._create_string_global(fmt_str)
call_args = [fmt_ptr] + fmt_args
return Gen.builder.call(printf_func, call_args, name="print_call")
def _HandlePrintWithFString(self, Node, printf_func, args, sep_str, end_str):
Gen = self.Trans.LlvmGen
def _HandlePrintWithFString(self, Node: ast.Call, printf_func: ir.Function, args: list[ast.expr], sep_str: str, end_str: str) -> ir.Value | None:
Gen: LlvmGeneratorMixin = self.Trans.LlvmGen
for i, arg in enumerate(args):
if i > 0:
sep_const = Gen.emit_constant(sep_str, 'string')
Gen.builder.call(printf_func, [sep_const], name="print_sep")
if isinstance(arg, ast.JoinedStr):
self.HandleExprLlvm(arg)
str_val = self.HandleExprLlvm(arg)
if str_val:
Gen._emit_printf([str_val], unsigned_flags=[False], sep=None, end=None)
else:
ClassName = self.Trans.ExprHandler._get_var_class(arg, Gen)
if ClassName and Gen._has_function(f'{ClassName}.__str__'):
@@ -327,7 +339,7 @@ class ExprBuiltinHandle(BaseHandle):
try:
val = Gen._load(val, name="print_Load")
except Exception as _e:
if __import__('lib.constants.config', fromlist=['mode']).mode == "strict":
if _config_mode == "strict":
self.Trans.LogWarning(f"异常被忽略: {_e}")
is_u = Gen._check_node_unsigned(arg)
if not is_u and id(val) in Gen._unsigned_results:
@@ -338,7 +350,7 @@ class ExprBuiltinHandle(BaseHandle):
Gen.builder.call(printf_func, [end_const], name="print_end")
return ir.Constant(ir.IntType(32), 0)
def _is_char_type(self, arg_node):
def _is_char_type(self, arg_node: ast.AST) -> bool:
if isinstance(arg_node, ast.Call):
if isinstance(arg_node.func, ast.Name):
return arg_node.func.id in ('CChar', 'CUInt8T', 'CInt8T')
@@ -346,11 +358,11 @@ class ExprBuiltinHandle(BaseHandle):
return arg_node.func.attr in ('CChar', 'CUInt8T', 'CInt8T')
return False
def _is_val_unsigned(self, arg_node, val):
Gen = self.Trans.LlvmGen
def _is_val_unsigned(self, arg_node: ast.AST, val: ir.Value) -> bool:
Gen: LlvmGeneratorMixin = self.Trans.LlvmGen
if isinstance(arg_node, ast.Name):
var_name = arg_node.id
signedness = Gen.var_signedness.get(var_name)
var_name: str = arg_node.id
signedness: object = Gen.var_signedness.get(var_name)
if signedness:
if isinstance(signedness, bool):
return signedness
@@ -359,17 +371,19 @@ class ExprBuiltinHandle(BaseHandle):
return False
return False
def _try_declare_c_lib_func(self, func_name, Gen):
def _try_declare_c_lib_func(self, func_name: str, Gen: LlvmGeneratorMixin) -> ir.Function | None:
if func_name not in self._C_LIB_FUNCS:
return None
ret_type: ir.Type
param_types: list[ir.Type]
ret_type, param_types = self._C_LIB_FUNCS[func_name]()
func_type = ir.FunctionType(ret_type, param_types)
func = ir.Function(Gen.module, func_type, name=func_name)
func_type: ir.FunctionType = ir.FunctionType(ret_type, param_types)
func: ir.Function = ir.Function(Gen.module, func_type, name=func_name)
Gen.functions[func_name] = func
return func
def _HandleLenLlvm(self, arg_node):
Gen = self.Trans.LlvmGen
def _HandleLenLlvm(self, arg_node: ast.AST) -> ir.Value | None:
Gen: LlvmGeneratorMixin = self.Trans.LlvmGen
if isinstance(arg_node, ast.Attribute) and isinstance(arg_node.value, ast.Name) and arg_node.value.id == 'self':
attr_name = arg_node.attr
len_member = f'{attr_name}__len'
@@ -415,7 +429,7 @@ class ExprBuiltinHandle(BaseHandle):
strlen_func = ir.Function(Gen.module, correct_strlen_type, name='strlen')
Gen.functions['strlen'] = strlen_func
except Exception as _e:
if __import__('lib.constants.config', fromlist=['mode']).mode == "strict":
if _config_mode == "strict":
self.Trans.LogWarning(f"异常被忽略: {_e}")
if strlen_func:
result = Gen.builder.call(strlen_func, [val], name="strlen_call")
@@ -424,8 +438,39 @@ class ExprBuiltinHandle(BaseHandle):
return ir.Constant(ir.IntType(64), val.type.count)
return ir.Constant(ir.IntType(64), 0)
def _HandleSizeofLlvm(self, Node):
Gen = self.Trans.LlvmGen
def _resolve_nested_opaque_structs(self, struct_type: ir.Type, Gen: LlvmGeneratorMixin, visited: set | None = None) -> None:
"""递归解析嵌套的 opaque struct从 stub 文件中加载其定义"""
if visited is None:
visited = set()
if isinstance(struct_type, ir.PointerType):
self._resolve_nested_opaque_structs(struct_type.pointee, Gen, visited)
return
if not isinstance(struct_type, ir.IdentifiedStructType):
return
if struct_type in visited:
return
visited.add(struct_type)
if struct_type.elements is None or len(struct_type.elements) == 0:
# 尝试从 stub 加载 opaque struct
try:
st_name = struct_type.name
except Exception:
st_name = None
if st_name:
# 提取短名称(去掉模块前缀)
if '.' in st_name:
short_name = st_name.split('.', 1)[1]
else:
short_name = st_name
self.Trans.ImportHandler._TryLoadStructFromStub(short_name, Gen)
return
# 递归解析嵌套的 struct 成员
for elem in struct_type.elements:
self._resolve_nested_opaque_structs(elem, Gen, visited)
def _HandleSizeofLlvm(self, Node: ast.AST) -> ir.Value:
Gen: LlvmGeneratorMixin = self.Trans.LlvmGen
type_name: str | None
if isinstance(Node, ast.Name):
type_name = Node.id
elif isinstance(Node, ast.Attribute):
@@ -434,7 +479,9 @@ class ExprBuiltinHandle(BaseHandle):
return ir.Constant(ir.IntType(64), 0)
if type_name not in Gen.structs:
from lib.includes.t import CTypeRegistry
# str/bytes 是指针类型 (char*/void*)sizeof = 指针大小
if type_name in ('str', 'bytes'):
return ir.Constant(ir.IntType(64), 8)
ctype_cls = CTypeRegistry.GetClassByName(type_name)
if ctype_cls is not None:
try:
@@ -443,8 +490,6 @@ class ExprBuiltinHandle(BaseHandle):
size_bytes = size_bits // 8
return ir.Constant(ir.IntType(64), size_bytes)
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")
@@ -459,8 +504,6 @@ class ExprBuiltinHandle(BaseHandle):
size_bytes = 8
return ir.Constant(ir.IntType(64), size_bytes)
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")
@@ -472,14 +515,16 @@ class ExprBuiltinHandle(BaseHandle):
if isinstance(struct_type, ir.IdentifiedStructType) and (struct_type.elements is None or len(struct_type.elements) == 0):
self.Trans.ImportHandler._TryLoadStructFromStub(type_name, Gen)
struct_type = Gen.structs.get(type_name, struct_type)
# 递归解析所有嵌套的 opaque struct确保 sizeof 计算正确
self._resolve_nested_opaque_structs(struct_type, Gen)
size = Gen._get_struct_size(struct_type)
if size > 0:
return ir.Constant(ir.IntType(64), size)
return ir.Constant(ir.IntType(64), 0)
def _HandleAbsLlvm(self, arg_node):
Gen = self.Trans.LlvmGen
val = self.HandleExprLlvm(arg_node)
def _HandleAbsLlvm(self, arg_node: ast.AST) -> ir.Value | None:
Gen: LlvmGeneratorMixin = self.Trans.LlvmGen
val: ir.Value | None = self.HandleExprLlvm(arg_node)
if not val:
return None
if isinstance(val.type, ir.PointerType):
@@ -502,19 +547,20 @@ class ExprBuiltinHandle(BaseHandle):
return Gen.builder.select(is_neg, neg_val, val, name="fabs_result")
return None
def _HandleDirLlvm(self, Node):
Gen = self.Trans.LlvmGen
def _HandleDirLlvm(self, Node: ast.Call) -> ir.Value:
Gen: LlvmGeneratorMixin = self.Trans.LlvmGen
return ir.Constant(ir.IntType(8).as_pointer(), None)
def _HandleTypeLlvm(self, Node):
Gen = self.Trans.LlvmGen
def _HandleTypeLlvm(self, Node: ast.Call) -> ir.Value:
Gen: LlvmGeneratorMixin = self.Trans.LlvmGen
type_str: str
if not Node.args:
type_str = "<class 'unknown' size=0 signed=false, ptr=false>"
else:
arg = Node.args[0]
enum_type_name = None
def _get_attr_path(node):
def _get_attr_path(node: ast.AST) -> str | None:
if isinstance(node, ast.Name):
return node.id
elif isinstance(node, ast.Attribute):
@@ -578,8 +624,8 @@ class ExprBuiltinHandle(BaseHandle):
type_str = f"<class '{type_info['name']}' size={type_info['size']} signed={str(type_info['signed']).lower()}, ptr={str(type_info['ptr']).lower()}>"
return Gen.emit_constant(type_str, 'string')
def _HandleInputLlvm(self, Node):
Gen = self.Trans.LlvmGen
def _HandleInputLlvm(self, Node: ast.Call) -> ir.Value:
Gen: LlvmGeneratorMixin = self.Trans.LlvmGen
if Node.args and isinstance(Node.args[0], ast.Constant) and isinstance(Node.args[0].value, str):
prompt = Node.args[0].value
prompt_ptr = Gen.emit_constant(prompt, 'string')
@@ -590,29 +636,29 @@ class ExprBuiltinHandle(BaseHandle):
result = Gen.builder.call(scanf_func, [Gen.emit_constant("%255s", 'string'), input_buffer])
return Gen.builder.gep(input_buffer, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), 0)], name="input_result")
def _HandleAtoiLlvm(self, str_ptr):
Gen = self.Trans.LlvmGen
atoi_func = Gen.get_or_declare_c_func('atoi', ir.FunctionType(ir.IntType(32), [ir.PointerType(ir.IntType(8))]))
def _HandleAtoiLlvm(self, str_ptr: ir.Value) -> ir.Value:
Gen: LlvmGeneratorMixin = self.Trans.LlvmGen
atoi_func: ir.Function = Gen.get_or_declare_c_func('atoi', ir.FunctionType(ir.IntType(32), [ir.PointerType(ir.IntType(8))]))
return Gen.builder.call(atoi_func, [str_ptr], name="atoi_result")
def _HandleOrdLlvm(self, expr_node):
Gen = self.Trans.LlvmGen
val = self.HandleExprLlvm(expr_node)
def _HandleOrdLlvm(self, expr_node: ast.AST) -> ir.Value:
Gen: LlvmGeneratorMixin = self.Trans.LlvmGen
val: ir.Value | None = self.HandleExprLlvm(expr_node)
if val and isinstance(val.type, ir.PointerType) and isinstance(val.type.pointee, ir.IntType) and val.type.pointee.width == 8:
return Gen._load(val, name="ord_result")
return ir.Constant(ir.IntType(32), 0)
def _HandleChrLlvm(self, expr_node):
Gen = self.Trans.LlvmGen
val = self.HandleExprLlvm(expr_node)
def _HandleChrLlvm(self, expr_node: ast.AST) -> ir.Value:
Gen: LlvmGeneratorMixin = self.Trans.LlvmGen
val: ir.Value | None = self.HandleExprLlvm(expr_node)
if val:
char_ptr = Gen._alloca(ir.IntType(8), name="chr_char")
Gen.builder.store(Gen.builder.trunc(val, ir.IntType(8), name="trunc_chr"), char_ptr)
return Gen.builder.gep(char_ptr, [ir.Constant(ir.IntType(32), 0)], name="chr_result")
return ir.Constant(ir.IntType(8).as_pointer(), None)
def _EmitStringFromValue(self, val):
Gen = self.Trans.LlvmGen
def _EmitStringFromValue(self, val: ir.Value) -> ir.Value:
Gen: LlvmGeneratorMixin = self.Trans.LlvmGen
if isinstance(val.type, ir.IntType):
if val.type.width == 8:
buf = Gen._alloca(ir.IntType(8), name="str_buf", size=ir.Constant(ir.IntType(32), 2))
@@ -631,12 +677,12 @@ class ExprBuiltinHandle(BaseHandle):
return Gen.builder.gep(buf, [ir.Constant(ir.IntType(32), 0)], name="str_result")
return ir.Constant(ir.IntType(8).as_pointer(), None)
def _HandleMallocLlvm(self, args):
Gen = self.Trans.LlvmGen
malloc_type = ir.FunctionType(ir.PointerType(ir.IntType(8)), [ir.IntType(64)])
malloc_func = Gen._get_or_declare_func('malloc', malloc_type)
param_type = malloc_func.type.pointee.args[0]
size_val = None
def _HandleMallocLlvm(self, args: list[ast.expr]) -> ir.Value:
Gen: LlvmGeneratorMixin = self.Trans.LlvmGen
malloc_type: ir.FunctionType = ir.FunctionType(ir.PointerType(ir.IntType(8)), [ir.IntType(64)])
malloc_func: ir.Function = Gen._get_or_declare_func('malloc', malloc_type)
param_type: ir.Type = malloc_func.type.pointee.args[0]
size_val: ir.Value | None = None
if args:
size_val = self.HandleExprLlvm(args[0])
if size_val and isinstance(size_val.type, ir.IntType):
@@ -647,16 +693,16 @@ class ExprBuiltinHandle(BaseHandle):
size_val = Gen.builder.trunc(size_val, param_type, name="trunc_malloc_size")
if not size_val:
size_val = ir.Constant(param_type, 1)
result = Gen.builder.call(malloc_func, [size_val], name="malloc_result")
result: ir.Value = Gen.builder.call(malloc_func, [size_val], name="malloc_result")
return Gen.builder.bitcast(result, ir.IntType(8).as_pointer(), name="malloc_cast")
def _HandleReallocLlvm(self, args):
Gen = self.Trans.LlvmGen
realloc_type = ir.FunctionType(ir.PointerType(ir.IntType(8)), [ir.PointerType(ir.IntType(8)), ir.IntType(64)])
realloc_func = Gen._get_or_declare_func('realloc', realloc_type)
size_param_type = realloc_func.type.pointee.args[1]
ptr_val = None
size_val = None
def _HandleReallocLlvm(self, args: list[ast.expr]) -> ir.Value:
Gen: LlvmGeneratorMixin = self.Trans.LlvmGen
realloc_type: ir.FunctionType = ir.FunctionType(ir.PointerType(ir.IntType(8)), [ir.PointerType(ir.IntType(8)), ir.IntType(64)])
realloc_func: ir.Function = Gen._get_or_declare_func('realloc', realloc_type)
size_param_type: ir.Type = realloc_func.type.pointee.args[1]
ptr_val: ir.Value | None = None
size_val: ir.Value | None = None
if len(args) >= 2:
ptr_val = self.HandleExprLlvm(args[0])
size_val = self.HandleExprLlvm(args[1])
@@ -674,18 +720,18 @@ class ExprBuiltinHandle(BaseHandle):
size_val = Gen.builder.trunc(size_val, size_param_type, name="trunc_realloc_size")
if not size_val:
size_val = ir.Constant(size_param_type, 0)
result = Gen.builder.call(realloc_func, [ptr_val, size_val], name="realloc_result")
result: ir.Value = Gen.builder.call(realloc_func, [ptr_val, size_val], name="realloc_result")
return Gen.builder.bitcast(result, ir.IntType(8).as_pointer(), name="realloc_cast")
def _HandleFreeLlvm(self, args):
Gen = self.Trans.LlvmGen
free_type = ir.FunctionType(ir.VoidType(), [ir.PointerType(ir.IntType(8))])
free_func = Gen._get_or_declare_func('free', free_type)
def _HandleFreeLlvm(self, args: list[ast.expr]) -> ir.Value:
Gen: LlvmGeneratorMixin = self.Trans.LlvmGen
free_type: ir.FunctionType = ir.FunctionType(ir.VoidType(), [ir.PointerType(ir.IntType(8))])
free_func: ir.Function = Gen._get_or_declare_func('free', free_type)
if args:
var_name = None
var_name: str | None = None
if isinstance(args[0], ast.Name):
var_name = args[0].id
ptr_val = self.HandleExprLlvm(args[0])
ptr_val: ir.Value | None = self.HandleExprLlvm(args[0])
if ptr_val is not None:
if var_name and hasattr(Gen, '_var_to_heap_ptr') and var_name in Gen._var_to_heap_ptr:
registered_val = Gen._var_to_heap_ptr[var_name]
@@ -701,17 +747,17 @@ class ExprBuiltinHandle(BaseHandle):
Gen.builder.call(free_func, [ptr_val], name="free_call")
return ir.Constant(ir.IntType(32), 0)
def _HandleMemcpyLlvm(self, args):
Gen = self.Trans.LlvmGen
def _HandleMemcpyLlvm(self, args: list[ast.expr]) -> ir.Value:
Gen: LlvmGeneratorMixin = self.Trans.LlvmGen
if 'llvm.memcpy' not in Gen.functions:
memcpy_type = ir.FunctionType(ir.VoidType(), [ir.PointerType(ir.IntType(8)), ir.PointerType(ir.IntType(8)), ir.IntType(64), ir.IntType(1)])
memcpy_type: ir.FunctionType = ir.FunctionType(ir.VoidType(), [ir.PointerType(ir.IntType(8)), ir.PointerType(ir.IntType(8)), ir.IntType(64), ir.IntType(1)])
Gen.functions['llvm.memcpy'] = ir.Function(Gen.module, memcpy_type, name='llvm.memcpy')
if len(args) >= 3:
dst = self.HandleExprLlvm(args[0])
src = self.HandleExprLlvm(args[1])
size = self.HandleExprLlvm(args[2])
dst: ir.Value | None = self.HandleExprLlvm(args[0])
src: ir.Value | None = self.HandleExprLlvm(args[1])
size: ir.Value | None = self.HandleExprLlvm(args[2])
if dst and src and size:
i8ptr = ir.PointerType(ir.IntType(8))
i8ptr: ir.PointerType = ir.PointerType(ir.IntType(8))
if isinstance(dst.type, ir.PointerType) and dst.type != i8ptr:
dst = Gen.builder.bitcast(dst, i8ptr, name="memcpy_dst_cast")
elif isinstance(dst.type, ir.IntType):
@@ -726,17 +772,17 @@ class ExprBuiltinHandle(BaseHandle):
src = Gen.builder.inttoptr(src, i8ptr, name="src_int2ptr")
if isinstance(size.type, ir.IntType) and size.type.width < 64:
size = Gen.builder.zext(size, ir.IntType(64), name="zext_memcpy_size")
isvolatile = ir.Constant(ir.IntType(1), 0)
isvolatile: ir.Constant = ir.Constant(ir.IntType(1), 0)
Gen.builder.call(Gen.functions['llvm.memcpy'], [dst, src, size, isvolatile], name="memcpy_call")
return ir.Constant(ir.IntType(32), 0)
def _HandleMemsetLlvm(self, args):
Gen = self.Trans.LlvmGen
memset_func = Gen.get_or_declare_c_func('memset', ir.FunctionType(ir.PointerType(ir.IntType(8)), [ir.PointerType(ir.IntType(8)), ir.IntType(32), ir.IntType(64)]))
def _HandleMemsetLlvm(self, args: list[ast.expr]) -> ir.Value:
Gen: LlvmGeneratorMixin = self.Trans.LlvmGen
memset_func: ir.Function = Gen.get_or_declare_c_func('memset', ir.FunctionType(ir.PointerType(ir.IntType(8)), [ir.PointerType(ir.IntType(8)), ir.IntType(32), ir.IntType(64)]))
if len(args) >= 3:
dst = self.HandleExprLlvm(args[0])
val = self.HandleExprLlvm(args[1])
size = self.HandleExprLlvm(args[2])
dst: ir.Value | None = self.HandleExprLlvm(args[0])
val: ir.Value | None = self.HandleExprLlvm(args[1])
size: ir.Value | None = self.HandleExprLlvm(args[2])
if dst and val is not None and size:
if isinstance(dst.type, ir.PointerType) and not (isinstance(dst.type.pointee, ir.IntType) and dst.type.pointee.width == 8):
dst = Gen.builder.bitcast(dst, ir.PointerType(ir.IntType(8)), name="memset_dst_cast")
@@ -758,34 +804,33 @@ class ExprBuiltinHandle(BaseHandle):
Gen.builder.call(memset_func, [dst, val, size], name="memset_call")
return ir.Constant(ir.IntType(32), 0)
def _HandleVaStartLlvm(self, args):
Gen = self.Trans.LlvmGen
def _HandleVaStartLlvm(self, args: list[ast.expr]) -> ir.Value:
Gen: LlvmGeneratorMixin = self.Trans.LlvmGen
return ir.Constant(ir.IntType(32), 0)
def _HandleVaEndLlvm(self, args):
Gen = self.Trans.LlvmGen
def _HandleVaEndLlvm(self, args: list[ast.expr]) -> ir.Value:
Gen: LlvmGeneratorMixin = self.Trans.LlvmGen
return ir.Constant(ir.IntType(32), 0)
def _HandleArgLlvm(self, args, CallNode=None):
Gen = self.Trans.LlvmGen
va_list_ptr = None
variadic_info = getattr(Gen, '_va_arg_info', None)
def _HandleArgLlvm(self, args: list[ast.expr], CallNode: ast.Call | None = None) -> ir.Value | None:
Gen: LlvmGeneratorMixin = self.Trans.LlvmGen
va_list_ptr: ir.Value | None = None
variadic_info: dict | None = getattr(Gen, '_va_arg_info', None)
if not variadic_info:
variadic_info = getattr(Gen, '_variadic_info', None)
if variadic_info:
va_list_ptr = variadic_info.get('va_list_ptr')
if not va_list_ptr:
vararg_name = variadic_info.get('vararg_name', 'args') if variadic_info else 'args'
vararg_name: str = variadic_info.get('vararg_name', 'args') if variadic_info else 'args'
if vararg_name in Gen.variables:
va_list_ptr = Gen.variables[vararg_name]
if not va_list_ptr:
return ir.Constant(ir.IntType(32), 0)
target_type = ir.IntType(32)
target_type: ir.Type = ir.IntType(32)
if args:
type_arg = args[0]
type_arg: ast.expr = args[0]
if isinstance(type_arg, ast.Name):
type_name = type_arg.id
from lib.includes.t import CTypeRegistry
type_name: str = type_arg.id
if type_name in ('str', 'bytes'):
target_type = ir.PointerType(ir.IntType(8))
elif type_name == 'CPtr':
@@ -793,19 +838,19 @@ class ExprBuiltinHandle(BaseHandle):
elif type_name in Gen.structs:
target_type = ir.PointerType(Gen.structs[type_name])
else:
ctype_cls = CTypeRegistry.GetClassByName(type_name)
ctype_cls: type | None = CTypeRegistry.GetClassByName(type_name)
if ctype_cls is not None:
llvm_str = CTypeRegistry.CTypeToLLVM(ctype_cls)
resolved = Gen._type_str_to_llvm(llvm_str)
llvm_str: str | None = CTypeRegistry.CTypeToLLVM(ctype_cls)
resolved: ir.Type | None = Gen._type_str_to_llvm(llvm_str)
if resolved:
target_type = resolved
else:
resolved = CTypeRegistry.ResolveName(type_name)
resolved: tuple | None = CTypeRegistry.ResolveName(type_name)
if resolved is not None:
ctype_cls, ptr_level = resolved
llvm_str = CTypeRegistry.CTypeToLLVM(ctype_cls)
if llvm_str:
base = Gen._type_str_to_llvm(llvm_str)
base: ir.Type | None = Gen._type_str_to_llvm(llvm_str)
if base is not None:
for _ in range(ptr_level):
if isinstance(base, ir.VoidType):
@@ -814,37 +859,31 @@ class ExprBuiltinHandle(BaseHandle):
base = ir.PointerType(base)
target_type = base
elif isinstance(type_arg, ast.Attribute):
if isinstance(type_arg.value, ast.Name) and type_arg.value.id == 't':
attr_name = type_arg.attr
from lib.includes.t import CTypeRegistry
ctype_cls = CTypeRegistry.GetClassByName(attr_name)
if isinstance(type_arg.value, ast.Name) and IsTModule(type_arg.value.id, self.Trans.SymbolTable):
attr_name: str = type_arg.attr
ctype_cls: type | None = CTypeRegistry.GetClassByName(attr_name)
if ctype_cls is not None:
llvm_str = CTypeRegistry.CTypeToLLVM(ctype_cls)
resolved = Gen._type_str_to_llvm(llvm_str)
llvm_str: str | None = CTypeRegistry.CTypeToLLVM(ctype_cls)
resolved: ir.Type | None = Gen._type_str_to_llvm(llvm_str)
if resolved:
target_type = resolved
else:
assign_node = getattr(self.Trans, '_current_assign_node', None)
assign_node: ast.AST | None = getattr(self.Trans, '_current_assign_node', None)
if assign_node:
ann = getattr(assign_node, 'annotation', None)
ann: ast.AST | None = getattr(assign_node, 'annotation', None)
if ann:
ann_name = 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):
left = ann.left
if isinstance(left, ast.Name):
ann_name = left.id
elif isinstance(left, ast.Attribute):
ann_name = left.attr
ann_name = ExtractTypeNameFromBinOp(ann)
if ann_name:
from lib.includes.t import CTypeRegistry
ctype_cls = CTypeRegistry.GetClassByName(ann_name)
ctype_cls: type | None = CTypeRegistry.GetClassByName(ann_name)
if ctype_cls is not None:
llvm_str = CTypeRegistry.CTypeToLLVM(ctype_cls)
resolved = Gen._type_str_to_llvm(llvm_str)
llvm_str: str | None = CTypeRegistry.CTypeToLLVM(ctype_cls)
resolved: ir.Type | None = Gen._type_str_to_llvm(llvm_str)
if resolved:
target_type = resolved
elif ann_name in Gen.structs:
@@ -852,11 +891,11 @@ class ExprBuiltinHandle(BaseHandle):
if not getattr(Gen, '_va_arg_counter', None):
Gen._va_arg_counter = 0
Gen._va_arg_counter += 1
result = Gen.emit_va_arg(va_list_ptr, target_type)
result: ir.Value | None = Gen.emit_va_arg(va_list_ptr, target_type)
if result is not None and getattr(result, 'name', None):
result.name = f"va_arg_result_{Gen._va_arg_counter}"
return result
def _HandleVaArgLlvm(self, args):
Gen = self.Trans.LlvmGen
def _HandleVaArgLlvm(self, args: list[ast.expr]) -> ir.Value:
Gen: LlvmGeneratorMixin = self.Trans.LlvmGen
return ir.Constant(ir.IntType(32), 0)