Fixed some bugs and tried to maintain the bootstrap
This commit is contained in:
@@ -818,7 +818,7 @@ def _translate_enum_def(trans: HT.Translator | t.CPtr,
|
||||
# 用于联合体确定最大字段大小
|
||||
# ============================================================
|
||||
def _get_type_size(ty: llvmlite.LLVMType | t.CPtr) -> int:
|
||||
"""计算 LLVM 类型的字节大小"""
|
||||
"""计算 LLVM 类型的字节大小(含对齐 padding)"""
|
||||
if ty is None:
|
||||
return 0
|
||||
match ty:
|
||||
@@ -831,20 +831,79 @@ def _get_type_size(ty: llvmlite.LLVMType | t.CPtr) -> int:
|
||||
case llvmlite.LLVMType.Array(elem_ty, count):
|
||||
return _get_type_size(elem_ty) * count
|
||||
case llvmlite.LLVMType.Struct(fields, fcount, name):
|
||||
# 计算结构体大小,考虑字段对齐 padding
|
||||
# 规则: 每个字段的对齐 = 该字段类型的自然对齐
|
||||
# 指针/i64 → 8, i32 → 4, i16 → 2, i8 → 1
|
||||
# 结构体总大小需对齐到最大字段对齐的倍数
|
||||
total: int = 0
|
||||
max_align: int = 1
|
||||
cur: llvmlite.ParamNode | t.CPtr = fields
|
||||
i: int = 0
|
||||
while cur is not None and i < fcount:
|
||||
if cur.Ty is not None:
|
||||
fty: llvmlite.LLVMType | t.CPtr = (llvmlite.LLVMType | t.CPtr)(cur.Ty)
|
||||
total += _get_type_size(fty)
|
||||
fsize: int = _get_type_size(fty)
|
||||
falign: int = _get_type_align(fty)
|
||||
# 对齐当前偏移到字段对齐边界
|
||||
if falign > 0:
|
||||
rem: int = total % falign
|
||||
if rem != 0:
|
||||
total += falign - rem
|
||||
total += fsize
|
||||
if falign > max_align:
|
||||
max_align = falign
|
||||
cur = cur.Next
|
||||
i += 1
|
||||
# 结构体总大小对齐到最大字段对齐的倍数
|
||||
rem2: int = total % max_align
|
||||
if rem2 != 0:
|
||||
total += max_align - rem2
|
||||
return total
|
||||
case _:
|
||||
return 8
|
||||
|
||||
|
||||
def _get_type_align(ty: llvmlite.LLVMType | t.CPtr) -> int:
|
||||
"""返回类型的自然对齐(字节)"""
|
||||
if ty is None:
|
||||
return 1
|
||||
match ty:
|
||||
case llvmlite.LLVMType.Int(bits):
|
||||
if bits <= 8:
|
||||
return 1
|
||||
elif bits <= 16:
|
||||
return 2
|
||||
elif bits <= 32:
|
||||
return 4
|
||||
else:
|
||||
return 8
|
||||
case llvmlite.LLVMType.Float(bits):
|
||||
if bits <= 32:
|
||||
return 4
|
||||
else:
|
||||
return 8
|
||||
case llvmlite.LLVMType.Ptr(pointee):
|
||||
return 8
|
||||
case llvmlite.LLVMType.Array(elem_ty, count):
|
||||
return _get_type_align(elem_ty)
|
||||
case llvmlite.LLVMType.Struct(fields, fcount, name):
|
||||
# 结构体的对齐 = 最大字段对齐
|
||||
max_align: int = 1
|
||||
cur: llvmlite.ParamNode | t.CPtr = fields
|
||||
i: int = 0
|
||||
while cur is not None and i < fcount:
|
||||
if cur.Ty is not None:
|
||||
fty: llvmlite.LLVMType | t.CPtr = (llvmlite.LLVMType | t.CPtr)(cur.Ty)
|
||||
fa: int = _get_type_align(fty)
|
||||
if fa > max_align:
|
||||
max_align = fa
|
||||
cur = cur.Next
|
||||
i += 1
|
||||
return max_align
|
||||
case _:
|
||||
return 8
|
||||
|
||||
|
||||
# ============================================================
|
||||
# _translate_union_def — 翻译联合体定义
|
||||
#
|
||||
@@ -3003,6 +3062,8 @@ def _translate_method(trans: HT.Translator | t.CPtr,
|
||||
return 0
|
||||
|
||||
# 提取默认参数信息(方法的 args[0] 是 self,不含在 param_count 中)
|
||||
# 注意: 必须先把属性赋给显式类型为 list[...] | t.CPtr 的局部变量再调用 __len__(),
|
||||
# 否则编译器无法识别属性返回的 list 类型,GEP base 会变成 i32 0 导致 llc 报错
|
||||
md_defaults: t.CVoid | t.CPtr = None
|
||||
md_default_count: int = 0
|
||||
md_param_count: int = 0
|
||||
@@ -3010,10 +3071,12 @@ def _translate_method(trans: HT.Translator | t.CPtr,
|
||||
if md_args_node is not None:
|
||||
md_ags: ast.Arguments | t.CPtr = (ast.Arguments | t.CPtr)(md_args_node)
|
||||
if md_ags.args is not None:
|
||||
md_param_count = md_ags.args.__len__() - 1
|
||||
md_alist: list[ast.AST | t.CPtr] | t.CPtr = md_ags.args
|
||||
md_param_count = md_alist.__len__() - 1
|
||||
if md_ags.defaults is not None:
|
||||
md_defaults = md_ags.defaults
|
||||
md_default_count = md_ags.defaults.__len__()
|
||||
md_dlist: list[ast.AST | t.CPtr] | t.CPtr = md_ags.defaults
|
||||
md_defaults = md_dlist
|
||||
md_default_count = md_dlist.__len__()
|
||||
|
||||
# 注册到函数表(用 ClassName.method_name 作为查找名,支持后缀匹配)
|
||||
max_funcs: int = 256
|
||||
@@ -3059,12 +3122,16 @@ def _translate_method(trans: HT.Translator | t.CPtr,
|
||||
# 进入函数作用域
|
||||
HandlesVar.enter_scope(trans.SymTab, SCOPE_FUNCTION)
|
||||
|
||||
# 注册 self 为 SSA 值(不创建 alloca,不 store)
|
||||
# 这样 self.field 通过 lookup_var 获取 Ptr(struct_ty) 后直接 GEP
|
||||
self_val: llvmlite.Value | t.CPtr = llvmlite.SSAValue(pool, self_ptr_ty, "%self")
|
||||
HandlesVar.define_var(trans.SymTab, "self", self_val)
|
||||
# 设置 self 的类型注解类名(属性访问 lookup_field 回退查找用)
|
||||
HandlesVar.set_var_annot_class_name(trans.SymTab, "self", class_name)
|
||||
# 为 self 创建 alloca 并 store(与其他参数一致)
|
||||
# 修复: 之前 self 注册为 SSA 值导致 translate_name_value 错误地 load 一次
|
||||
# 将 Ptr(struct_ty) 变成 struct 值,引发变参函数 ABI 不匹配崩溃
|
||||
self_alloca: llvmlite.Value | t.CPtr = llvmlite.build_alloca(func_builder, self_ptr_ty)
|
||||
if self_alloca is not None:
|
||||
HandlesVar.define_var(trans.SymTab, "self", self_alloca)
|
||||
# 设置 self 的类型注解类名(属性访问 lookup_field 回退查找用)
|
||||
HandlesVar.set_var_annot_class_name(trans.SymTab, "self", class_name)
|
||||
self_val: llvmlite.Value | t.CPtr = llvmlite.SSAValue(pool, self_ptr_ty, "%self")
|
||||
llvmlite.build_store(func_builder, self_val, self_alloca)
|
||||
|
||||
# 为其他参数创建 alloca 并 store(与普通函数一致,跳过索引 0 的 self 参数)
|
||||
if args_node is not None:
|
||||
|
||||
Reference in New Issue
Block a user