修复了大量存在的问题,增加了假鸭子类型等等机制
This commit is contained in:
@@ -1,13 +1,15 @@
|
||||
from __future__ import annotations
|
||||
from typing import Any, Callable
|
||||
import re
|
||||
import ast
|
||||
import llvmlite.ir as ir
|
||||
from llvmlite.ir.values import _Undefined
|
||||
from lib.includes import t as _t
|
||||
|
||||
|
||||
class StructGenMixin:
|
||||
|
||||
def _get_align(self, llvm_type):
|
||||
def _get_align(self, llvm_type: ir.Type) -> int:
|
||||
if isinstance(llvm_type, ir.IntType):
|
||||
return max(1, llvm_type.width // 8)
|
||||
if isinstance(llvm_type, ir.FloatType):
|
||||
@@ -28,7 +30,53 @@ class StructGenMixin:
|
||||
return 0
|
||||
return 4
|
||||
|
||||
def _get_struct_size(self, llvm_type):
|
||||
def _resolve_opaque_struct(self, llvm_type: ir.Type) -> ir.Type:
|
||||
"""尝试从 Gen.structs 中查找已解析的同名 struct,解决跨模块 struct 类型对象不一致的问题"""
|
||||
if not isinstance(llvm_type, ir.IdentifiedStructType):
|
||||
return llvm_type
|
||||
if llvm_type.elements is not None and len(llvm_type.elements) > 0:
|
||||
return llvm_type
|
||||
# opaque struct,尝试通过名称在 Gen.structs 中查找已解析的版本
|
||||
st_name: str
|
||||
try:
|
||||
st_name = llvm_type.name
|
||||
except Exception:
|
||||
return llvm_type
|
||||
if not st_name:
|
||||
return llvm_type
|
||||
# 提取短名称
|
||||
short_name: str = st_name
|
||||
if '.' in st_name:
|
||||
short_name = st_name.split('.', 1)[1]
|
||||
# 尝试短名称查找
|
||||
if short_name in self.structs:
|
||||
resolved: ir.IdentifiedStructType = self.structs[short_name]
|
||||
if isinstance(resolved, ir.IdentifiedStructType) and resolved.elements is not None and len(resolved.elements) > 0:
|
||||
return resolved
|
||||
# 尝试全名查找
|
||||
if st_name in self.structs:
|
||||
resolved: ir.IdentifiedStructType = self.structs[st_name]
|
||||
if isinstance(resolved, ir.IdentifiedStructType) and resolved.elements is not None and len(resolved.elements) > 0:
|
||||
return resolved
|
||||
# 尝试通过导入处理器从 stub 文件加载 struct 定义
|
||||
import_handler: Any = getattr(self, '_import_handler_ref', None)
|
||||
if import_handler is not None:
|
||||
try:
|
||||
import_handler._TryLoadStructFromStub(short_name, self)
|
||||
except Exception:
|
||||
pass
|
||||
# 加载后再次查找
|
||||
if short_name in self.structs:
|
||||
resolved = self.structs[short_name]
|
||||
if isinstance(resolved, ir.IdentifiedStructType) and resolved.elements is not None and len(resolved.elements) > 0:
|
||||
return resolved
|
||||
if st_name in self.structs:
|
||||
resolved = self.structs[st_name]
|
||||
if isinstance(resolved, ir.IdentifiedStructType) and resolved.elements is not None and len(resolved.elements) > 0:
|
||||
return resolved
|
||||
return llvm_type
|
||||
|
||||
def _get_struct_size(self, llvm_type: ir.Type) -> int:
|
||||
if isinstance(llvm_type, ir.IntType):
|
||||
return max(1, llvm_type.width // 8)
|
||||
if isinstance(llvm_type, ir.FloatType):
|
||||
@@ -40,11 +88,11 @@ class StructGenMixin:
|
||||
if isinstance(llvm_type, ir.ArrayType):
|
||||
return self._get_struct_size(llvm_type.element) * llvm_type.count
|
||||
if isinstance(llvm_type, ir.LiteralStructType):
|
||||
total = 0
|
||||
max_align = 1
|
||||
total: int = 0
|
||||
max_align: int = 1
|
||||
for f in llvm_type.fields:
|
||||
fa = self._get_align(f)
|
||||
fs = self._get_struct_size(f)
|
||||
fa: int = self._get_align(f)
|
||||
fs: int = self._get_struct_size(f)
|
||||
max_align = max(max_align, fa)
|
||||
if fa > 1:
|
||||
total = (total + fa - 1) // fa * fa
|
||||
@@ -53,13 +101,15 @@ class StructGenMixin:
|
||||
total = (total + max_align - 1) // max_align * max_align
|
||||
return total
|
||||
if isinstance(llvm_type, ir.IdentifiedStructType):
|
||||
# 尝试解析 opaque struct 为已注册的版本
|
||||
llvm_type = self._resolve_opaque_struct(llvm_type)
|
||||
if llvm_type.elements is None or len(llvm_type.elements) == 0:
|
||||
return self.ptr_size # opaque struct, assume pointer size
|
||||
total = 0
|
||||
max_align = 1
|
||||
total: int = 0
|
||||
max_align: int = 1
|
||||
for f in llvm_type.elements:
|
||||
fa = self._get_align(f)
|
||||
fs = self._get_struct_size(f)
|
||||
fa: int = self._get_align(f)
|
||||
fs: int = self._get_struct_size(f)
|
||||
max_align = max(max_align, fa)
|
||||
if fa > 1:
|
||||
total = (total + fa - 1) // fa * fa
|
||||
@@ -70,10 +120,10 @@ class StructGenMixin:
|
||||
return 4
|
||||
|
||||
@staticmethod
|
||||
def _strip_unnecessary_quotes(ir_str):
|
||||
def _unquote(m):
|
||||
prefix = m.group(1)
|
||||
name = m.group(2)
|
||||
def _strip_unnecessary_quotes(ir_str: str) -> str:
|
||||
def _unquote(m: re.Match) -> str:
|
||||
prefix: str = m.group(1)
|
||||
name: str = m.group(2)
|
||||
if '.' in name:
|
||||
return m.group(0)
|
||||
if re.match(r'^[a-zA-Z_$][a-zA-Z0-9_$]*$', name):
|
||||
@@ -81,9 +131,10 @@ class StructGenMixin:
|
||||
return m.group(0)
|
||||
return re.sub(r'([@%])"([^"]+)"', _unquote, ir_str)
|
||||
|
||||
def finalize(self):
|
||||
def finalize(self) -> str:
|
||||
self._set_Vtable_initializers()
|
||||
self._fix_global_var_init()
|
||||
ir_text: str
|
||||
try:
|
||||
ir_text = str(self.module)
|
||||
except TypeError as e:
|
||||
@@ -96,11 +147,12 @@ class StructGenMixin:
|
||||
pass
|
||||
raise
|
||||
ir_text = self._strip_unnecessary_quotes(ir_text)
|
||||
struct_defs = []
|
||||
struct_names = set()
|
||||
struct_defs: list[str] = []
|
||||
struct_names: set[str] = set()
|
||||
for ClassName, struct_type in self.structs.items():
|
||||
if isinstance(struct_type, ir.IdentifiedStructType):
|
||||
sname = struct_type.name
|
||||
sname: str = struct_type.name
|
||||
sname_ir: str
|
||||
if sname[0].isdigit() or '.' in sname or not sname.replace('_', '').replace('.', '').isalnum():
|
||||
sname_ir = f'%"{sname}"'
|
||||
else:
|
||||
@@ -110,19 +162,20 @@ class StructGenMixin:
|
||||
struct_names.add(sname)
|
||||
struct_defs.append(f'{sname_ir} = type opaque')
|
||||
continue
|
||||
elems = ', '.join(str(e) for e in struct_type.elements)
|
||||
elems: str = ', '.join(str(e) for e in struct_type.elements)
|
||||
if struct_type.packed:
|
||||
struct_defs.append(f'{sname_ir} = type <{{ {elems} }}>')
|
||||
else:
|
||||
struct_defs.append(f'{sname_ir} = type {{ {elems} }}')
|
||||
struct_names.add(sname)
|
||||
if struct_defs:
|
||||
lines = ir_text.split('\n')
|
||||
filtered = []
|
||||
lines: list[str] = ir_text.split('\n')
|
||||
filtered: list[str] = []
|
||||
for line in lines:
|
||||
stripped = line.strip()
|
||||
skip = False
|
||||
stripped: str = line.strip()
|
||||
skip: bool = False
|
||||
for name in struct_names:
|
||||
patterns: list[str]
|
||||
if name[0].isdigit() or '.' in name or not name.replace('_', '').replace('.', '').isalnum():
|
||||
patterns = [f'%"{name}" = type', f'%"{name}"=type', f'%{name} = type', f'%{name}=type']
|
||||
else:
|
||||
@@ -136,17 +189,17 @@ class StructGenMixin:
|
||||
if not skip:
|
||||
filtered.append(line)
|
||||
ir_text = '\n'.join(filtered)
|
||||
header_end = ir_text.find('\ndefine')
|
||||
header_end: int = ir_text.find('\ndefine')
|
||||
if header_end == -1:
|
||||
header_end = ir_text.find('\ndeclare')
|
||||
if header_end == -1:
|
||||
header_end = ir_text.find('\n@')
|
||||
if header_end == -1:
|
||||
header_end = len(ir_text)
|
||||
insert_pos = ir_text.rfind('\n', 0, header_end)
|
||||
insert_pos: int = ir_text.rfind('\n', 0, header_end)
|
||||
if insert_pos == -1:
|
||||
insert_pos = header_end
|
||||
struct_block = '\n'.join(struct_defs) + '\n'
|
||||
struct_block: str = '\n'.join(struct_defs) + '\n'
|
||||
ir_text = ir_text[:insert_pos + 1] + struct_block + ir_text[insert_pos + 1:]
|
||||
for name in struct_names:
|
||||
if name[0].isdigit() or '.' in name:
|
||||
@@ -158,13 +211,13 @@ class StructGenMixin:
|
||||
|
||||
return ir_text
|
||||
|
||||
def _collect_classes_and_methods(self, ast_nodes, parent=None):
|
||||
current_class = None
|
||||
def _collect_classes_and_methods(self, ast_nodes: list[ast.AST], parent: ast.AST | None = None) -> None:
|
||||
current_class: str | None = None
|
||||
for node in ast_nodes:
|
||||
if isinstance(node, str):
|
||||
continue
|
||||
node.parent = parent
|
||||
node_type = type(node).__name__
|
||||
node_type: str = type(node).__name__
|
||||
if node_type == 'Struct':
|
||||
if hasattr(node, 'name'):
|
||||
current_class = node.name
|
||||
@@ -173,11 +226,11 @@ class StructGenMixin:
|
||||
if hasattr(node, 'decls') and node.decls:
|
||||
for decl in node.decls:
|
||||
if type(decl).__name__ == 'Decl' and hasattr(decl, 'name'):
|
||||
member_type = self._get_type(decl.type) if hasattr(decl, 'type') else ir.IntType(32)
|
||||
member_type: ir.Type = self._get_type(decl.type) if hasattr(decl, 'type') else ir.IntType(32)
|
||||
self.class_members[current_class].append((decl.name, member_type))
|
||||
elif node_type == 'FuncDef':
|
||||
if current_class and current_class in self.class_methods:
|
||||
MethodName = node.decl.name if hasattr(node.decl, 'name') else 'unknown_method'
|
||||
MethodName: str = node.decl.name if hasattr(node.decl, 'name') else 'unknown_method'
|
||||
if not MethodName.startswith(f"{current_class}."):
|
||||
MethodName = f"{current_class}.{MethodName}"
|
||||
self.class_methods[current_class].append(MethodName)
|
||||
@@ -186,10 +239,10 @@ class StructGenMixin:
|
||||
elif hasattr(node, 'BlockItems') and node.BlockItems:
|
||||
self._collect_classes_and_methods(node.BlockItems, parent=node)
|
||||
|
||||
def _generate_structs(self):
|
||||
all_classes = set(self.class_methods.keys()) | set(self.class_members.keys())
|
||||
def _generate_structs(self) -> None:
|
||||
all_classes: set[str] = set(self.class_methods.keys()) | set(self.class_members.keys())
|
||||
|
||||
preserved_structs = {}
|
||||
preserved_structs: dict[str, ir.IdentifiedStructType] = {}
|
||||
for name, st in self.structs.items():
|
||||
if name not in all_classes:
|
||||
preserved_structs[name] = st
|
||||
@@ -204,25 +257,24 @@ class StructGenMixin:
|
||||
# Step 1: 先为所有类创建空的 struct,确保后面可以正确引用
|
||||
all_classes = set(self.class_methods.keys()) | set(self.class_members.keys())
|
||||
for ClassName in all_classes:
|
||||
is_packed = ClassName in self.class_packed
|
||||
if hasattr(self, 'SymbolTable') and self.SymbolTable and self.SymbolTable.has(ClassName):
|
||||
Entry = self.SymbolTable[ClassName]
|
||||
if Entry.IsExceptionClass:
|
||||
is_packed: bool = ClassName in self.class_packed
|
||||
if hasattr(self, 'SymbolTable') and self.SymbolTable:
|
||||
Entry = self.SymbolTable.lookup(ClassName)
|
||||
if Entry and Entry.IsExceptionClass:
|
||||
continue
|
||||
if Entry.IsEnum:
|
||||
if Entry and Entry.IsEnum:
|
||||
if not Entry.IsRenum:
|
||||
continue
|
||||
if Entry.IsTypedef:
|
||||
if Entry and Entry.IsTypedef:
|
||||
if Entry.BaseType and not isinstance(Entry.BaseType, (type(None),)):
|
||||
import lib.includes.t as _t
|
||||
if not isinstance(Entry.BaseType, (_t._CTypedef,)):
|
||||
continue
|
||||
if ClassName in self.structs:
|
||||
if is_packed:
|
||||
self.structs[ClassName].packed = True
|
||||
continue
|
||||
mangled_name = self._mangle_name(ClassName)
|
||||
struct_type = ir.IdentifiedStructType(self.module, mangled_name, packed=is_packed)
|
||||
mangled_name: str = self._mangle_name(ClassName)
|
||||
struct_type: ir.IdentifiedStructType = ir.IdentifiedStructType(self.module, mangled_name, packed=is_packed)
|
||||
self.structs[ClassName] = struct_type
|
||||
|
||||
# Step 2: 解析跨模块的成员类型
|
||||
@@ -231,30 +283,30 @@ class StructGenMixin:
|
||||
continue
|
||||
for i, (member_name, member_type) in enumerate(self.class_members[ClassName]):
|
||||
if member_name in annotations:
|
||||
annotation = annotations[member_name]
|
||||
ResolvedType = None
|
||||
annotation: Any = annotations[member_name]
|
||||
ResolvedType: ir.Type | None = None
|
||||
|
||||
if isinstance(annotation, ast.Attribute):
|
||||
ClassTypeName = annotation.attr
|
||||
ClassTypeName: str = annotation.attr
|
||||
if ClassTypeName in self.structs:
|
||||
ResolvedType = self.structs[ClassTypeName]
|
||||
elif isinstance(annotation, ast.BinOp) and isinstance(annotation.op, ast.BitOr):
|
||||
left = annotation.left
|
||||
left: Any = annotation.left
|
||||
if isinstance(left, ast.Attribute):
|
||||
ClassTypeName = left.attr
|
||||
ClassTypeName: str = left.attr
|
||||
if ClassTypeName in self.structs:
|
||||
ResolvedType = self.structs[ClassTypeName]
|
||||
|
||||
if ResolvedType:
|
||||
self.class_members[ClassName][i] = (member_name, ResolvedType)
|
||||
|
||||
struct_name_map = {}
|
||||
struct_name_map: dict[str, ir.IdentifiedStructType] = {}
|
||||
for struct_name, struct in self.structs.items():
|
||||
try:
|
||||
struct_name_map[struct.name] = struct
|
||||
except AssertionError:
|
||||
struct_name_map[struct_name] = struct
|
||||
orig = getattr(struct, '_original_name', None)
|
||||
orig: Any = getattr(struct, '_original_name', None)
|
||||
if orig:
|
||||
struct_name_map[orig] = struct
|
||||
|
||||
@@ -264,81 +316,85 @@ class StructGenMixin:
|
||||
continue
|
||||
for i, (member_name, member_type) in enumerate(self.class_members[ClassName]):
|
||||
if isinstance(member_type, ir.PointerType):
|
||||
pointee = member_type.pointee
|
||||
pointee: ir.Type = member_type.pointee
|
||||
if isinstance(pointee, ir.IdentifiedStructType):
|
||||
pname: str | None
|
||||
try:
|
||||
pname = pointee.name
|
||||
except AssertionError:
|
||||
pname = None
|
||||
struct = struct_name_map.get(pname) if pname else None
|
||||
struct: ir.IdentifiedStructType | None = struct_name_map.get(pname) if pname else None
|
||||
if struct is None:
|
||||
orig = getattr(pointee, '_original_name', None)
|
||||
orig: Any = getattr(pointee, '_original_name', None)
|
||||
struct = struct_name_map.get(orig) if orig else None
|
||||
if struct is not None:
|
||||
self.class_members[ClassName][i] = (member_name, ir.PointerType(struct))
|
||||
else:
|
||||
raw_name = pname or ''
|
||||
raw_name: str = pname or ''
|
||||
if raw_name.startswith('struct.'):
|
||||
raw_name = raw_name[7:]
|
||||
new_struct = self._get_or_create_struct(raw_name)
|
||||
new_struct: ir.IdentifiedStructType = self._get_or_create_struct(raw_name)
|
||||
self.class_members[ClassName][i] = (member_name, ir.PointerType(new_struct))
|
||||
elif isinstance(member_type, ir.IdentifiedStructType):
|
||||
mname: str | None
|
||||
try:
|
||||
mname = member_type.name
|
||||
except AssertionError:
|
||||
mname = None
|
||||
struct = struct_name_map.get(mname) if mname else None
|
||||
struct: ir.IdentifiedStructType | None = struct_name_map.get(mname) if mname else None
|
||||
if struct is None:
|
||||
orig = getattr(member_type, '_original_name', None)
|
||||
orig: Any = getattr(member_type, '_original_name', None)
|
||||
struct = struct_name_map.get(orig) if orig else None
|
||||
if struct is not None:
|
||||
self.class_members[ClassName][i] = (member_name, struct)
|
||||
else:
|
||||
raw_name = mname or ''
|
||||
raw_name: str = mname or ''
|
||||
if raw_name.startswith('struct.'):
|
||||
raw_name = raw_name[7:]
|
||||
new_struct = self._get_or_create_struct(raw_name)
|
||||
new_struct: ir.IdentifiedStructType = self._get_or_create_struct(raw_name)
|
||||
self.class_members[ClassName][i] = (member_name, new_struct)
|
||||
|
||||
# Step 4: 创建最终的 structs 并设置正确的成员类型
|
||||
for ClassName in all_classes:
|
||||
if hasattr(self, 'SymbolTable') and self.SymbolTable and self.SymbolTable.has(ClassName):
|
||||
Entry = self.SymbolTable[ClassName]
|
||||
if Entry.IsExceptionClass:
|
||||
if hasattr(self, 'SymbolTable') and self.SymbolTable:
|
||||
Entry = self.SymbolTable.lookup(ClassName)
|
||||
if Entry and Entry.IsExceptionClass:
|
||||
continue
|
||||
if Entry.IsEnum:
|
||||
if Entry and Entry.IsEnum:
|
||||
if not Entry.IsRenum:
|
||||
continue
|
||||
existing_st = self.structs.get(ClassName)
|
||||
existing_st: ir.IdentifiedStructType | None = self.structs.get(ClassName)
|
||||
if isinstance(existing_st, ir.IdentifiedStructType) and existing_st.elements is not None and len(existing_st.elements) > 0:
|
||||
# 即使 struct 已有元素,也需要修正 packed 属性
|
||||
if ClassName in self.class_packed and not existing_st.packed:
|
||||
existing_st.packed = True
|
||||
continue
|
||||
has_vtable = ClassName in self.class_vtable or ClassName in self._cross_module_vtable_classes
|
||||
has_vtable: bool = ClassName in self.class_vtable or ClassName in self._cross_module_vtable_classes
|
||||
if not has_vtable:
|
||||
p = self.class_parent.get(ClassName)
|
||||
p: str | None = self.class_parent.get(ClassName)
|
||||
while p:
|
||||
if p in self.class_vtable or p in self._cross_module_vtable_classes:
|
||||
has_vtable = True
|
||||
self.class_vtable.add(ClassName)
|
||||
break
|
||||
p = self.class_parent.get(p)
|
||||
has_bitfield = ClassName in self.class_member_bitfields and any(
|
||||
has_bitfield: bool = ClassName in self.class_member_bitfields and any(
|
||||
self.class_member_bitfields[ClassName].get(name, 0) > 0
|
||||
for name, _ in self.class_members.get(ClassName, [])
|
||||
)
|
||||
all_members = self.class_members.get(ClassName, [])
|
||||
all_bitfield = all(
|
||||
all_members: list[tuple[str, ir.Type]] = self.class_members.get(ClassName, [])
|
||||
all_bitfield: bool = all(
|
||||
self.class_member_bitfields.get(ClassName, {}).get(name, 0) > 0
|
||||
for name, _ in all_members
|
||||
) if all_members else False
|
||||
|
||||
mangled_name = self._mangle_name(ClassName)
|
||||
mangled_name: str = self._mangle_name(ClassName)
|
||||
|
||||
member_types: list[ir.Type]
|
||||
if has_bitfield and all_bitfield:
|
||||
total_bits = sum(self.class_member_bitfields.get(ClassName, {}).get(name, 0)
|
||||
total_bits: int = sum(self.class_member_bitfields.get(ClassName, {}).get(name, 0)
|
||||
for name, _ in all_members)
|
||||
storage_type: ir.IntType
|
||||
if total_bits <= 8:
|
||||
storage_type = ir.IntType(8)
|
||||
elif total_bits <= 16:
|
||||
@@ -348,10 +404,10 @@ class StructGenMixin:
|
||||
else:
|
||||
storage_type = ir.IntType(64)
|
||||
member_types = [storage_type]
|
||||
bitfield_offsets = {}
|
||||
current_bit_offset = 0
|
||||
bitfield_offsets: dict[str, int] = {}
|
||||
current_bit_offset: int = 0
|
||||
for name, _ in all_members:
|
||||
bit_width = self.class_member_bitfields.get(ClassName, {}).get(name, 0)
|
||||
bit_width: int = self.class_member_bitfields.get(ClassName, {}).get(name, 0)
|
||||
bitfield_offsets[name] = current_bit_offset
|
||||
current_bit_offset += bit_width
|
||||
self.class_member_bitoffsets[ClassName] = bitfield_offsets
|
||||
@@ -368,14 +424,14 @@ class StructGenMixin:
|
||||
member_types = [ir.IntType(8)]
|
||||
|
||||
# 获取之前创建的 struct 并设置成员
|
||||
struct_type = self.structs[ClassName]
|
||||
struct_type: ir.IdentifiedStructType = self.structs[ClassName]
|
||||
if ClassName in self.class_packed:
|
||||
struct_type.packed = True
|
||||
# 只在未设置 body 时设置,避免重复定义错误
|
||||
if struct_type.elements is None:
|
||||
struct_type.set_body(*member_types)
|
||||
|
||||
def _create_Vtable_globals(self):
|
||||
def _create_Vtable_globals(self) -> None:
|
||||
for ClassName, methods in self.class_methods.items():
|
||||
if ClassName in self.Vtables:
|
||||
continue
|
||||
@@ -383,19 +439,19 @@ class StructGenMixin:
|
||||
continue
|
||||
if ClassName not in self.class_vtable and ClassName not in self._cross_module_vtable_classes:
|
||||
continue
|
||||
VtableType = ir.ArrayType(ir.PointerType(ir.IntType(8)), len(methods))
|
||||
Vtable = ir.GlobalVariable(self.module, VtableType, name=self._mangle_name(f"{ClassName}_Vtable"))
|
||||
VtableType: ir.ArrayType = ir.ArrayType(ir.PointerType(ir.IntType(8)), len(methods))
|
||||
Vtable: ir.GlobalVariable = ir.GlobalVariable(self.module, VtableType, name=self._mangle_name(f"{ClassName}_Vtable"))
|
||||
Vtable.initializer = ir.Constant(VtableType, [ir.Constant(ir.PointerType(ir.IntType(8)), None)] * len(methods))
|
||||
Vtable.linkage = 'internal'
|
||||
self.Vtables[ClassName] = Vtable
|
||||
|
||||
def _fix_global_var_init(self):
|
||||
def _fix_global_var_init(self) -> None:
|
||||
for gv_name, gv in list(self.module.globals.items()):
|
||||
if not isinstance(gv, ir.GlobalVariable):
|
||||
continue
|
||||
if gv.linkage in ('external', 'extern_weak'):
|
||||
continue
|
||||
needs_fix = False
|
||||
needs_fix: bool = False
|
||||
if gv.initializer is None:
|
||||
needs_fix = True
|
||||
elif hasattr(gv.initializer, 'constant') and isinstance(gv.initializer.constant, _Undefined):
|
||||
@@ -410,48 +466,27 @@ class StructGenMixin:
|
||||
if gv_name.startswith('str_const_') or gv_name.endswith('_Vtable') or gv_name.endswith('_str'):
|
||||
gv.linkage = 'internal'
|
||||
|
||||
def _zero_value_for_type(self, var_type):
|
||||
if isinstance(var_type, ir.IntType):
|
||||
return ir.Constant(var_type, 0)
|
||||
elif isinstance(var_type, (ir.FloatType, ir.DoubleType)):
|
||||
return ir.Constant(var_type, 0.0)
|
||||
elif isinstance(var_type, ir.PointerType):
|
||||
return ir.Constant(var_type, None)
|
||||
elif isinstance(var_type, ir.ArrayType):
|
||||
elem_zv = self._zero_value_for_type(var_type.element)
|
||||
if elem_zv is None:
|
||||
return None
|
||||
return ir.Constant(var_type, [elem_zv] * var_type.count)
|
||||
elif isinstance(var_type, ir.BaseStructType):
|
||||
if var_type.elements is not None and len(var_type.elements) > 0:
|
||||
elem_zvs = [self._zero_value_for_type(m) for m in var_type.elements]
|
||||
if any(zv is None for zv in elem_zvs):
|
||||
return None
|
||||
return ir.Constant(var_type, elem_zvs)
|
||||
return None
|
||||
return None
|
||||
|
||||
def _set_Vtable_initializers(self):
|
||||
def _set_Vtable_initializers(self) -> None:
|
||||
for ClassName, methods in self.class_methods.items():
|
||||
if ClassName not in self.Vtables:
|
||||
continue
|
||||
if not methods:
|
||||
continue
|
||||
struct_type = self.structs.get(ClassName)
|
||||
struct_type: ir.IdentifiedStructType | None = self.structs.get(ClassName)
|
||||
if not struct_type:
|
||||
continue
|
||||
Vtable = self.Vtables[ClassName]
|
||||
Vtable_entries = []
|
||||
Vtable: ir.GlobalVariable = self.Vtables[ClassName]
|
||||
Vtable_entries: list[ir.Constant] = []
|
||||
for MethodName in methods:
|
||||
short_name = MethodName.split('.')[-1] if '.' in MethodName else MethodName
|
||||
full_MethodName = f"{ClassName}.{short_name}"
|
||||
func = None
|
||||
short_name: str = MethodName.split('.')[-1] if '.' in MethodName else MethodName
|
||||
full_MethodName: str = f"{ClassName}.{short_name}"
|
||||
func: ir.Function | None = None
|
||||
if full_MethodName in self.functions:
|
||||
func = self.functions[full_MethodName]
|
||||
if func is None:
|
||||
parent_cls = self.class_parent.get(ClassName)
|
||||
parent_cls: str | None = self.class_parent.get(ClassName)
|
||||
while parent_cls:
|
||||
parent_full = f"{parent_cls}.{short_name}"
|
||||
parent_full: str = f"{parent_cls}.{short_name}"
|
||||
if parent_full in self.functions:
|
||||
func = self.functions[parent_full]
|
||||
break
|
||||
@@ -460,4 +495,4 @@ class StructGenMixin:
|
||||
Vtable_entries.append(ir.Constant(ir.PointerType(ir.IntType(8)), None))
|
||||
continue
|
||||
Vtable_entries.append(func.bitcast(ir.PointerType(ir.IntType(8))))
|
||||
Vtable.initializer = ir.Constant(Vtable.type.pointee, Vtable_entries)
|
||||
Vtable.initializer = ir.Constant(Vtable.type.pointee, Vtable_entries)
|
||||
Reference in New Issue
Block a user