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

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

@@ -1,10 +1,13 @@
from __future__ import annotations
from typing import TYPE_CHECKING
from typing import TYPE_CHECKING, Any
import ast
import re
import llvmlite.ir as ir
if TYPE_CHECKING:
from lib.core.translator import Translator
from lib.core.LlvmCodeGenerator import LlvmCodeGenerator
from lib.core.Handles.HandlesBase import BaseHandle
import ast
import llvmlite.ir as ir
from lib.core.SymbolUtils import IsTModule
import t
# 猴子补丁 llvmlite.ir.InlineAsm 以支持 asm_dialect 参数
@@ -37,9 +40,9 @@ if not _InlineAsmPatched:
class ExprAsmHandle(BaseHandle):
@staticmethod
def _format_to_dialect(asm_format):
def _format_to_dialect(asm_format: str | None) -> str | None:
"""将用户指定的 format 参数转换为 LLVM asm_dialect 值"""
fmt = asm_format.lower() if asm_format else 'intel'
fmt: str = asm_format.lower() if asm_format else 'intel'
if fmt == 'att':
return 'att'
elif fmt == 'arm':
@@ -47,13 +50,13 @@ class ExprAsmHandle(BaseHandle):
else:
return 'intel' # 默认 Intel
def _HandleAsmLlvm(self, Node):
Gen = self.Trans.LlvmGen
def _HandleAsmLlvm(self, Node: ast.Call) -> ir.Value | None:
Gen: LlvmCodeGenerator = self.Trans.LlvmGen
op_arg = None
input_arg = None
output_arg = None
asm_format = 'Intel' # 汇编格式: Intel / AT&T / ARM
op_arg: Any = None
input_arg: Any = None
output_arg: Any = None
asm_format: str = 'Intel' # 汇编格式: Intel / AT&T / ARM
for kw in Node.keywords:
if kw.arg == 'op':
op_arg = kw.value
@@ -66,7 +69,7 @@ class ExprAsmHandle(BaseHandle):
asm_format = kw.value.value
if len(Node.args) >= 1:
pos_op = None
pos_op: Any = None
if len(Node.args) >= 2 and op_arg is None:
pos_op = Node.args[1]
return self._HandleAsmWithOpLlvm(Node.args[0], op_arg or pos_op, input_arg, output_arg, asm_format)
@@ -74,90 +77,90 @@ class ExprAsmHandle(BaseHandle):
if len(Node.args) < 2:
return ir.Constant(ir.IntType(32), 1)
args = Node.args
args: list[ast.AST] = Node.args
if len(args) == 4:
output_type_arg = args[0]
asm_template_arg = args[1]
constraint_arg = args[2]
clobber_arg = args[3]
output_type_arg: ast.AST = args[0]
asm_template_arg: ast.AST = args[1]
constraint_arg: ast.AST = args[2]
clobber_arg: ast.AST = args[3]
output_type = self._infer_expr_llvm_type(output_type_arg)
output_type: ir.Type | None = self._infer_expr_llvm_type(output_type_arg)
if not output_type:
output_type = ir.IntType(32)
asm_template = ''
asm_template: str = ''
if isinstance(asm_template_arg, ast.Constant) and isinstance(asm_template_arg.value, str):
asm_template = self._prepare_intel_asm(self._mangle_asm_calls(asm_template_arg.value))
constraint = ''
constraint: str = ''
if isinstance(constraint_arg, ast.Constant) and isinstance(constraint_arg.value, str):
constraint = constraint_arg.value
clobber = ''
clobber: str = ''
if isinstance(clobber_arg, ast.Constant) and isinstance(clobber_arg.value, str):
clobber = clobber_arg.value
full_constraint = constraint
func_type = ir.FunctionType(output_type, [])
asm_dialect = self._format_to_dialect(asm_format)
inline_asm = ir.InlineAsm(func_type, asm_template, constraint, side_effect=True, asm_dialect=asm_dialect)
result = Gen.builder.call(inline_asm, [], name="asm_result")
full_constraint: str = constraint
func_type: ir.FunctionType = ir.FunctionType(output_type, [])
asm_dialect: str | None = self._format_to_dialect(asm_format)
inline_asm: ir.InlineAsm = ir.InlineAsm(func_type, asm_template, constraint, side_effect=True, asm_dialect=asm_dialect)
result: Any = Gen.builder.call(inline_asm, [], name="asm_result")
return result
elif len(args) >= 2:
output_type_arg = args[0]
asm_template_arg = args[1]
output_type_arg: ast.AST = args[0]
asm_template_arg: ast.AST = args[1]
output_type = self._infer_expr_llvm_type(output_type_arg)
output_type: ir.Type | None = self._infer_expr_llvm_type(output_type_arg)
if not output_type:
output_type = ir.IntType(32)
asm_template = ''
asm_template: str = ''
if isinstance(asm_template_arg, ast.Constant) and isinstance(asm_template_arg.value, str):
asm_template = self._prepare_intel_asm(self._mangle_asm_calls(asm_template_arg.value))
output_constraints = []
output_values = []
output_constraints: list[str] = []
output_values: list[Any] = []
if len(args) > 2 and isinstance(args[2], (ast.List, ast.Tuple)):
for item in args[2].elts:
if isinstance(item, (ast.List, ast.Tuple)) and len(item.elts) >= 2:
constraint_node = item.elts[0]
value_node = item.elts[1]
constraint_node: ast.AST = item.elts[0]
value_node: ast.AST = item.elts[1]
if isinstance(constraint_node, ast.Constant) and isinstance(constraint_node.value, str):
output_constraints.append(constraint_node.value)
value = self.HandleExprLlvm(value_node)
value: Any = self.HandleExprLlvm(value_node)
if value:
output_values.append(value)
input_constraints = []
input_values = []
input_constraints: list[str] = []
input_values: list[Any] = []
if len(args) > 3 and isinstance(args[3], (ast.List, ast.Tuple)):
for item in args[3].elts:
if isinstance(item, (ast.List, ast.Tuple)) and len(item.elts) >= 2:
constraint_node = item.elts[0]
value_node = item.elts[1]
constraint_node: ast.AST = item.elts[0]
value_node: ast.AST = item.elts[1]
if isinstance(constraint_node, ast.Constant) and isinstance(constraint_node.value, str):
input_constraints.append(constraint_node.value)
value = self.HandleExprLlvm(value_node)
value: Any = self.HandleExprLlvm(value_node)
if value:
input_values.append(value)
clobbers = []
clobbers: list[str] = []
if len(args) > 4 and isinstance(args[4], (ast.List, ast.Tuple)):
for item in args[4].elts:
if isinstance(item, ast.Constant) and isinstance(item.value, str):
clobbers.append(item.value)
constraint_parts = []
constraint_parts: list[str] = []
for oc in output_constraints:
constraint_parts.append(oc)
input_start_idx = len(output_constraints)
input_start_idx: int = len(output_constraints)
for ic in input_constraints:
constraint_parts.append(ic)
full_constraint = ",".join(constraint_parts)
full_constraint: str = ",".join(constraint_parts)
if clobbers:
if full_constraint:
@@ -165,18 +168,17 @@ class ExprAsmHandle(BaseHandle):
for c in clobbers:
full_constraint += f"~{{{c}}}"
operands = output_values + input_values
param_types = [v.type for v in operands]
func_type = ir.FunctionType(output_type, param_types)
asm_dialect = self._format_to_dialect(asm_format)
inline_asm = ir.InlineAsm(func_type, asm_template, full_constraint, side_effect=False, asm_dialect=asm_dialect)
result = Gen.builder.call(inline_asm, operands, name="asm_result")
operands: list[Any] = output_values + input_values
param_types: list[ir.Type] = [v.type for v in operands]
func_type: ir.FunctionType = ir.FunctionType(output_type, param_types)
asm_dialect: str | None = self._format_to_dialect(asm_format)
inline_asm: ir.InlineAsm = ir.InlineAsm(func_type, asm_template, full_constraint, side_effect=False, asm_dialect=asm_dialect)
result: Any = Gen.builder.call(inline_asm, operands, name="asm_result")
return result
return None
def _prepare_intel_asm(self, template: str) -> str:
import re
template = re.sub(r'%(\d+)', r'$\1', template)
template = re.sub(r'%([a-zA-Z][a-zA-Z0-9]*)', r'\1', template)
return template
@@ -196,26 +198,26 @@ class ExprAsmHandle(BaseHandle):
stripped.append('')
return '\n'.join([first_line] + stripped)
def _process_joined_str_template(self, node, out_input_ops, out_input_constraints,
out_output_ops, out_output_constraints):
def _process_joined_str_template(self, node: ast.AST, out_input_ops: list[Any], out_input_constraints: list[str],
out_output_ops: list[Any], out_output_constraints: list[str]) -> str:
if not isinstance(node, ast.JoinedStr):
if isinstance(node, ast.Constant) and isinstance(node.value, str):
return node.value
return ''
raw_parts = []
raw_parts: list[tuple[str, str | int]] = []
for value in node.values:
if isinstance(value, ast.Constant) and isinstance(value.value, str):
raw_parts.append(('text', value.value))
elif isinstance(value, ast.FormattedValue):
expr = value.value
expr: ast.AST = value.value
if isinstance(expr, ast.Call) and isinstance(expr.func, ast.Attribute):
if isinstance(expr.func.value, ast.Name) and expr.func.value.id == 'c':
if expr.func.attr == 'AsmInp':
if expr.args:
v = self.HandleExprLlvm(expr.args[0])
v: Any = self.HandleExprLlvm(expr.args[0])
if v:
c = 'r'
c: str = 'r'
if len(expr.args) >= 2:
c = self._parse_asm_descr(expr.args[1])
if not c:
@@ -225,13 +227,13 @@ class ExprAsmHandle(BaseHandle):
raw_parts.append(('input', len(out_input_ops) - 1))
elif expr.func.attr == 'AsmOut':
if expr.args:
target_ptr = self._get_var_ptr_for_asm(expr.args[0])
target_ptr: Any = self._get_var_ptr_for_asm(expr.args[0])
if target_ptr:
v = target_ptr
else:
v = self.HandleExprLlvm(expr.args[0])
if v:
c = '=r'
c: str = '=r'
if len(expr.args) >= 2:
c = self._parse_asm_descr(expr.args[1])
if not c:
@@ -242,7 +244,7 @@ class ExprAsmHandle(BaseHandle):
out_output_constraints.append(c)
raw_parts.append(('output', len(out_output_ops) - 1))
else:
fallback = self.HandleExprLlvm(expr)
fallback: Any = self.HandleExprLlvm(expr)
if fallback and isinstance(fallback.type, ir.IntType):
out_input_ops.append(fallback)
out_input_constraints.append('r')
@@ -250,8 +252,8 @@ class ExprAsmHandle(BaseHandle):
else:
raw_parts.append(('text', ''))
num_outputs = len(out_output_ops)
parts = []
num_outputs: int = len(out_output_ops)
parts: list[str] = []
for kind, data in raw_parts:
if kind == 'text':
parts.append(data)
@@ -274,47 +276,46 @@ class ExprAsmHandle(BaseHandle):
})
def _mangle_asm_calls(self, template: str) -> str:
import re
Gen = self.Trans.LlvmGen
sha1 = getattr(Gen, 'module_sha1', '')
Gen: LlvmCodeGenerator = self.Trans.LlvmGen
sha1: str = getattr(Gen, 'module_sha1', '')
if not sha1:
return template
def replace_call(m):
prefix = m.group(1)
func_name = m.group(2)
def replace_call(m: re.Match[str]) -> str:
prefix: str = m.group(1)
func_name: str = m.group(2)
if func_name.lower() in self._X86_REGISTERS:
return m.group(0)
mangled = Gen._mangle_func_name(func_name)
mangled: str = Gen._mangle_func_name(func_name)
if '.' in mangled:
return f'{prefix}\\22{mangled}\\22'
return f"{prefix}{mangled}"
return re.sub(r'(call\s+)(\w+)', replace_call, template)
def _HandleAsmWithOpLlvm(self, asm_template_arg, op_arg, input_arg=None, output_arg=None, asm_format='Intel'):
Gen = self.Trans.LlvmGen
def _HandleAsmWithOpLlvm(self, asm_template_arg: ast.AST, op_arg: ast.AST | None = None, input_arg: ast.AST | None = None, output_arg: ast.AST | None = None, asm_format: str = 'Intel') -> ir.Value:
Gen: LlvmCodeGenerator = self.Trans.LlvmGen
input_ops = []
input_constraints = []
output_ops = []
output_constraints = []
input_ops: list[Any] = []
input_constraints: list[str] = []
output_ops: list[Any] = []
output_constraints: list[str] = []
if output_arg and isinstance(output_arg, (ast.List, ast.Tuple)):
for item in output_arg.elts:
if isinstance(item, ast.Call) and isinstance(item.func, ast.Attribute):
if item.func.value.id == 'c' and item.func.attr == 'AsmOut':
if len(item.args) >= 1:
target_ptr = self._get_var_ptr_for_asm(item.args[0])
target_ptr: Any = self._get_var_ptr_for_asm(item.args[0])
if target_ptr:
output_ops.append(target_ptr)
else:
value = self.HandleExprLlvm(item.args[0])
value: Any = self.HandleExprLlvm(item.args[0])
if value:
output_ops.append(value)
constraint = '=r'
constraint: str = '=r'
if len(item.args) >= 2:
base_constraint = self._parse_asm_descr(item.args[1])
base_constraint: str = self._parse_asm_descr(item.args[1])
if base_constraint:
if base_constraint.startswith('='):
constraint = base_constraint
@@ -322,6 +323,7 @@ class ExprAsmHandle(BaseHandle):
constraint = '=' + base_constraint
output_constraints.append(constraint)
raw_template: str
if isinstance(asm_template_arg, ast.JoinedStr):
raw_template = self._normalize_asm_template(
self._process_joined_str_template(
@@ -334,7 +336,8 @@ class ExprAsmHandle(BaseHandle):
raw_template = ''
raw_template = self._mangle_asm_calls(raw_template)
asm_dialect = self._format_to_dialect(asm_format)
asm_dialect: str | None = self._format_to_dialect(asm_format)
asm_template: str
if asm_format == 'AT&T':
asm_template = raw_template # AT&T 不需要转换
elif asm_format == 'ARM':
@@ -347,36 +350,36 @@ class ExprAsmHandle(BaseHandle):
if isinstance(item, ast.Call) and isinstance(item.func, ast.Attribute):
if item.func.value.id == 'c' and item.func.attr == 'AsmInp':
if len(item.args) >= 1:
value = self.HandleExprLlvm(item.args[0])
value: Any = self.HandleExprLlvm(item.args[0])
if value:
input_ops.append(value)
constraint = 'r'
constraint: str = 'r'
if len(item.args) >= 2:
constraint = self._parse_asm_descr(item.args[1])
if not constraint:
constraint = 'r'
input_constraints.append(constraint)
elif isinstance(item, (ast.List, ast.Tuple)) and len(item.elts) >= 2:
value_node = item.elts[0]
descr_node = item.elts[1]
value = self.HandleExprLlvm(value_node)
value_node: ast.AST = item.elts[0]
descr_node: ast.AST = item.elts[1]
value: Any = self.HandleExprLlvm(value_node)
if value:
input_ops.append(value)
constraint = self._parse_asm_descr(descr_node)
constraint: str = self._parse_asm_descr(descr_node)
if not constraint:
constraint = 'r'
input_constraints.append(constraint)
clobbers = []
clobbers: list[str] = []
if op_arg and isinstance(op_arg, (ast.List, ast.Tuple)):
for item in op_arg.elts:
clobber = self._parse_asm_descr(item)
clobber: str = self._parse_asm_descr(item)
if clobber:
clobbers.append(clobber)
constraint_parts = []
constraint_parts: list[str] = []
for oc in output_constraints:
c = oc if oc.startswith('=') else ('=' + oc)
c: str = oc if oc.startswith('=') else ('=' + oc)
constraint_parts.append(c)
for ic in input_constraints:
if ic in ('d', 'edx', 'rdx'):
@@ -384,31 +387,32 @@ class ExprAsmHandle(BaseHandle):
else:
constraint_parts.append(ic)
full_constraint = ",".join(constraint_parts)
full_constraint: str = ",".join(constraint_parts)
constraint_to_reg = {
constraint_to_reg: dict[str, str] = {
'a': 'rax', 'b': 'rbx', 'c': 'rcx', 'd': 'rdx',
'S': 'rsi', 'D': 'rdi',
'A': 'rax', 'U': 'r8',
}
used_regs = set()
used_regs: set[str] = set()
for ic in input_constraints:
if ic in constraint_to_reg:
used_regs.add(constraint_to_reg[ic])
for oc in output_constraints:
base_oc = oc.lstrip('=').lstrip('+')
base_oc: str = oc.lstrip('=').lstrip('+')
if base_oc in constraint_to_reg:
used_regs.add(constraint_to_reg[base_oc])
if clobbers:
has_memory = 'memory' in clobbers
has_memory: bool = 'memory' in clobbers
if has_memory and output_ops:
clobbers = [c for c in clobbers if c != 'memory']
clobber_final: list[str]
if asm_format == 'ARM':
# ARM 不需要 x86 的 e→r 寄存器名转换
clobber_final = [c for c in clobbers if c not in used_regs]
else:
clobber_64bit = []
clobber_64bit: list[str] = []
for c in clobbers:
if c in ['eax', 'ebx', 'ecx', 'edx', 'esi', 'edi', 'ebp', 'esp']:
clobber_64bit.append(c.replace('e', 'r'))
@@ -421,9 +425,10 @@ class ExprAsmHandle(BaseHandle):
full_constraint += ",".join([f"~{{{c}}}" for c in clobber_final])
if output_ops:
single_out = len(output_ops) == 1
single_out: bool = len(output_ops) == 1
if single_out:
op = output_ops[0]
op: Any = output_ops[0]
ret_type: ir.Type
if isinstance(op, ir.AllocaInstr):
ret_type = op.type.pointee
elif isinstance(op, ir.GlobalVariable):
@@ -433,124 +438,122 @@ class ExprAsmHandle(BaseHandle):
else:
ret_type = op.type
else:
def _get_ret_type(op):
def _get_ret_type(op: Any) -> ir.Type:
if isinstance(op, (ir.AllocaInstr, ir.GlobalVariable)):
return op.type.pointee
return op.type
ret_type = ir.LiteralStructType([_get_ret_type(op) for op in output_ops])
if isinstance(ret_type, ir.PointerType) and isinstance(ret_type.pointee, ir.IdentifiedStructType):
ret_type = ir.IntType(64)
operands = input_ops
param_types = [op.type for op in operands]
func_type = ir.FunctionType(ret_type, param_types)
inline_asm = ir.InlineAsm(func_type, asm_template, full_constraint, side_effect=len(output_ops) == 0, asm_dialect=asm_dialect)
result = Gen.builder.call(inline_asm, operands, name="asm_result")
operands: list[Any] = input_ops
param_types: list[ir.Type] = [op.type for op in operands]
func_type: ir.FunctionType = ir.FunctionType(ret_type, param_types)
inline_asm: ir.InlineAsm = ir.InlineAsm(func_type, asm_template, full_constraint, side_effect=len(output_ops) == 0, asm_dialect=asm_dialect)
result: Any = Gen.builder.call(inline_asm, operands, name="asm_result")
if single_out:
target = output_ops[0]
target: Any = output_ops[0]
if isinstance(target, ir.AllocaInstr):
if target.type.pointee != result.type:
i64t = ir.IntType(64)
iv = Gen.builder.ptrtoint(result, i64t)
ptr = Gen.builder.bitcast(target, ir.PointerType(i64t))
i64t: ir.IntType = ir.IntType(64)
iv: Any = Gen.builder.ptrtoint(result, i64t)
ptr: Any = Gen.builder.bitcast(target, ir.PointerType(i64t))
Gen.builder.store(iv, ptr)
else:
Gen.builder.store(result, target)
elif isinstance(target, (ir.GlobalVariable, ir.GEPInstr, ir.CastInstr)):
target_pointee = target.type.pointee
target_pointee: ir.Type = target.type.pointee
if target_pointee != result.type:
if isinstance(target_pointee, ir.PointerType) and isinstance(result, ir.Instruction) and result.type == ir.IntType(64):
ptr_val = Gen.builder.inttoptr(result, target_pointee)
ptr_val: Any = Gen.builder.inttoptr(result, target_pointee)
Gen.builder.store(ptr_val, target)
else:
i64t = ir.IntType(64)
iv = Gen.builder.ptrtoint(result, i64t)
ptr = Gen.builder.bitcast(target, ir.PointerType(i64t))
i64t: ir.IntType = ir.IntType(64)
iv: Any = Gen.builder.ptrtoint(result, i64t)
ptr: Any = Gen.builder.bitcast(target, ir.PointerType(i64t))
Gen.builder.store(iv, ptr)
else:
Gen.builder.store(result, target)
else:
dst = Gen._allocaEntry(result.type)
dst: Any = Gen._allocaEntry(result.type)
Gen.builder.store(result, dst)
else:
for i, out_op in enumerate(output_ops):
val = Gen.builder.extract_value(result, i, name=f"asm_out_{i}")
target = out_op if isinstance(out_op, ir.AllocaInstr) else Gen._allocaEntry(val.type)
val: Any = Gen.builder.extract_value(result, i, name=f"asm_out_{i}")
target: Any = out_op if isinstance(out_op, ir.AllocaInstr) else Gen._allocaEntry(val.type)
if isinstance(target, ir.AllocaInstr) and target.type.pointee != val.type:
i64t = ir.IntType(64)
iv = Gen.builder.ptrtoint(val, i64t)
ptr = Gen.builder.bitcast(target, ir.PointerType(i64t))
i64t: ir.IntType = ir.IntType(64)
iv: Any = Gen.builder.ptrtoint(val, i64t)
ptr: Any = Gen.builder.bitcast(target, ir.PointerType(i64t))
Gen.builder.store(iv, ptr)
else:
Gen.builder.store(val, target)
else:
operands = input_ops
param_types = [op.type for op in operands]
func_type = ir.FunctionType(ir.VoidType(), param_types)
inline_asm = ir.InlineAsm(func_type, asm_template, full_constraint, side_effect=True, asm_dialect=asm_dialect)
operands: list[Any] = input_ops
param_types: list[ir.Type] = [op.type for op in operands]
func_type: ir.FunctionType = ir.FunctionType(ir.VoidType(), param_types)
inline_asm: ir.InlineAsm = ir.InlineAsm(func_type, asm_template, full_constraint, side_effect=True, asm_dialect=asm_dialect)
Gen.builder.call(inline_asm, operands, name="asm_call")
return ir.Constant(ir.IntType(32), 1)
def _get_var_ptr_for_asm(self, node):
Gen = self.Trans.LlvmGen
def _get_var_ptr_for_asm(self, node: ast.AST) -> ir.Value | None:
Gen: LlvmCodeGenerator = self.Trans.LlvmGen
if isinstance(node, ast.Name):
var_name = node.id
var_name: str = node.id
if var_name in Gen.variables and Gen.variables[var_name] is not None:
ptr = Gen.variables[var_name]
ptr: Any = Gen.variables[var_name]
if isinstance(ptr, ir.AllocaInstr):
return ptr
if isinstance(ptr, ir.GlobalVariable):
return ptr
elif isinstance(node, ast.Attribute):
obj_ptr = self._get_var_ptr_for_asm(node.value)
obj_ptr: Any = self._get_var_ptr_for_asm(node.value)
if obj_ptr is not None:
obj_type = obj_ptr.type.pointee
obj_type: ir.Type = obj_ptr.type.pointee
if isinstance(obj_type, ir.PointerType) and isinstance(obj_type.pointee, ir.IdentifiedStructType):
Loaded = Gen.builder.load(obj_ptr, name="asm_attr_Load")
struct_type = obj_type.pointee
class_name = Gen._resolve_class_for_var(node.value.id) if isinstance(node.value, ast.Name) else None
Loaded: Any = Gen.builder.load(obj_ptr, name="asm_attr_Load")
struct_type: ir.IdentifiedStructType = obj_type.pointee
class_name: str | None = Gen._resolve_class_for_var(node.value.id) if isinstance(node.value, ast.Name) else None
if class_name:
offset = Gen._get_member_offset(node.attr, class_name)
gep = Gen.builder.gep(Loaded, [ir.Constant(ir.IntType(32), 0),
offset: int = Gen._get_member_offset(node.attr, class_name)
gep: Any = Gen.builder.gep(Loaded, [ir.Constant(ir.IntType(32), 0),
ir.Constant(ir.IntType(32), offset)],
inbounds=True)
return gep
for idx, elem_type in enumerate(struct_type.elements):
gep = Gen.builder.gep(Loaded, [ir.Constant(ir.IntType(32), 0),
gep: Any = Gen.builder.gep(Loaded, [ir.Constant(ir.IntType(32), 0),
ir.Constant(ir.IntType(32), idx)],
inbounds=True)
return gep
elif isinstance(obj_type, ir.IdentifiedStructType):
class_name = Gen._resolve_class_for_var(node.value.id) if isinstance(node.value, ast.Name) else None
class_name: str | None = Gen._resolve_class_for_var(node.value.id) if isinstance(node.value, ast.Name) else None
if class_name:
offset = Gen._get_member_offset(node.attr, class_name)
gep = Gen.builder.gep(obj_ptr, [ir.Constant(ir.IntType(32), 0),
offset: int = Gen._get_member_offset(node.attr, class_name)
gep: Any = Gen.builder.gep(obj_ptr, [ir.Constant(ir.IntType(32), 0),
ir.Constant(ir.IntType(32), offset)],
inbounds=True)
return gep
for idx, elem_type in enumerate(obj_type.elements):
gep = Gen.builder.gep(obj_ptr, [ir.Constant(ir.IntType(32), 0),
gep: Any = Gen.builder.gep(obj_ptr, [ir.Constant(ir.IntType(32), 0),
ir.Constant(ir.IntType(32), idx)],
inbounds=True)
return gep
return None
def _parse_asm_descr(self, expr):
from lib.includes import t
def _parse_asm_descr(self, expr: ast.AST) -> str:
if isinstance(expr, ast.BinOp):
left_val = self._parse_asm_descr(expr.left)
right_val = self._parse_asm_descr(expr.right)
left_val: str = self._parse_asm_descr(expr.left)
right_val: str = self._parse_asm_descr(expr.right)
return left_val + right_val
elif isinstance(expr, ast.Attribute):
if isinstance(expr.value, ast.Attribute):
if (isinstance(expr.value.value, ast.Name) and
expr.value.value.id == 't' and
IsTModule(expr.value.value.id, self.Trans.SymbolTable) and
expr.value.attr == 'ASM_DESCR'):
AttrName = expr.attr
AttrName: str = expr.attr
return getattr(t.ASM_DESCR, AttrName, "")
elif isinstance(expr.value, ast.Name) and expr.value.id == 't':
AttrName = expr.attr
elif isinstance(expr.value, ast.Name) and IsTModule(expr.value.id, self.Trans.SymbolTable):
AttrName: str = expr.attr
return getattr(t.ASM_DESCR, AttrName, "")
elif isinstance(expr, ast.Constant):
@@ -558,14 +561,13 @@ class ExprAsmHandle(BaseHandle):
return ""
def _infer_expr_llvm_type(self, expr):
import llvmlite.ir as ir
def _infer_expr_llvm_type(self, expr: ast.AST) -> ir.Type | None:
if isinstance(expr, ast.Name):
type_name = expr.id
type_name: str = expr.id
if hasattr(t, type_name):
ctype = getattr(t, type_name)
ctype: Any = getattr(t, type_name)
if isinstance(ctype, type) and issubclass(ctype, t.CType):
size = getattr(ctype, 'Size', None)
size: Any = getattr(ctype, 'Size', None)
if size is not None:
return ir.IntType(size)
if type_name == 'CFloat':
@@ -573,6 +575,6 @@ class ExprAsmHandle(BaseHandle):
elif type_name == 'CDouble':
return ir.DoubleType()
elif isinstance(expr, ast.Attribute):
if isinstance(expr.value, ast.Name) and expr.value.id == 't':
if isinstance(expr.value, ast.Name) and IsTModule(expr.value.id, self.Trans.SymbolTable):
return self._infer_expr_llvm_type(ast.Name(id=expr.attr, ctx=ast.Load()))
return None