fix(compiler): storage vtable 初始化改完整 struct 初始化器(LLVM 拒绝部分初始化)
llc 报 initializer has wrong # elements。__vtable__ 字段(索引 0)= i8* @vtable,其余用户字段按类型生成零值(Ptr→null/Int→0/Float→0.0/Array→zeroinitializer),列全 FieldCount 字段。
This commit is contained in:
1 parent
fa4c69f95d
commit
23e7f5b1fb
1 file changed
+53
-6
@@ -439,6 +439,32 @@ class TranslatorGenMixin:
|
||||
str_len + 1, str_len + 1, str_name_buf)
|
||||
return init_buf
|
||||
|
||||
def _stg_field_zero_text(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
fty: llvmlite.LLVMType | t.CPtr,
|
||||
ty_str: str) -> str:
|
||||
"""按 LLVM 类型生成 storage struct 字段的零值初始化器文本
|
||||
|
||||
LLVM struct 初始化器必须列全所有字段(部分初始化 llc 报
|
||||
"initializer with struct type has wrong # elements")。
|
||||
Ptr→null、Int→0、Float→0.0、Array/Struct→zeroinitializer。
|
||||
"""
|
||||
if fty is None or ty_str is None:
|
||||
return None
|
||||
buf: str = pool.alloc(160)
|
||||
if buf is None:
|
||||
return None
|
||||
match fty:
|
||||
case llvmlite.LLVMType.Ptr(_):
|
||||
viperlib.snprintf(buf, 160, "%s null", ty_str)
|
||||
case llvmlite.LLVMType.Int(_):
|
||||
viperlib.snprintf(buf, 160, "%s 0", ty_str)
|
||||
case llvmlite.LLVMType.Float(_):
|
||||
viperlib.snprintf(buf, 160, "%s 0.0", ty_str)
|
||||
case _:
|
||||
# Array / Struct 等 aggregate → zeroinitializer
|
||||
viperlib.snprintf(buf, 160, "%s zeroinitializer", ty_str)
|
||||
return buf
|
||||
|
||||
# ============================================================
|
||||
# handle_module_level_var - 模块级变量声明 → 创建 LLVM 全局变量
|
||||
#
|
||||
@@ -682,14 +708,35 @@ class TranslatorGenMixin:
|
||||
viperlib.snprintf(vt_name_buf, 128, "%s.vtable", resolved_stg_entry.Name)
|
||||
vt_mangled: str = self.Gen.FuncGenBase._mangle_name(trans, vt_name_buf)
|
||||
if vt_mangled is not None:
|
||||
vt_init_len: t.CSizeT = t.CSizeT(string.strlen(vt_mangled)) + 32
|
||||
vt_init_buf: str = pool.alloc(vt_init_len)
|
||||
if vt_init_buf is not None:
|
||||
# 完整 struct 初始化器(LLVM 拒绝部分初始化):
|
||||
# 字段 0 = __vtable__(i8* @vtable),其余用户字段按类型零值。
|
||||
init_full_len: t.CSizeT = 16384
|
||||
init_full: str = pool.alloc(init_full_len)
|
||||
if init_full is not None:
|
||||
written_v: t.CInt = viperlib.snprintf(init_full, init_full_len, "{ ")
|
||||
pos_v: t.CSizeT = t.CSizeT(written_v)
|
||||
if self.Gen.ClassGenVTable._vtable_name_needs_quote(vt_mangled) != 0:
|
||||
viperlib.snprintf(vt_init_buf, vt_init_len, "{ i8* @\"%s\" }", vt_mangled)
|
||||
written_v = viperlib.snprintf(init_full + pos_v, init_full_len - pos_v, "i8* @\"%s\"", vt_mangled)
|
||||
else:
|
||||
viperlib.snprintf(vt_init_buf, vt_init_len, "{ i8* @%s }", vt_mangled)
|
||||
stg_init_text = vt_init_buf
|
||||
written_v = viperlib.snprintf(init_full + pos_v, init_full_len - pos_v, "i8* @%s", vt_mangled)
|
||||
pos_v += t.CSizeT(written_v)
|
||||
fc_v: int = resolved_stg_entry.FieldCount
|
||||
for fi_v in range(1, fc_v):
|
||||
fe_v: GenTypes.FieldEntry | t.CPtr = self.Gen.StructGen._get_field_entry(
|
||||
resolved_stg_entry, fi_v)
|
||||
if fe_v is None or fe_v.Ty is None:
|
||||
continue
|
||||
ty_buf_v: str = pool.alloc(128)
|
||||
if ty_buf_v is None:
|
||||
continue
|
||||
llvmlite.TypePrint(ty_buf_v, 128, fe_v.Ty, pool)
|
||||
zero_v: str = self._stg_field_zero_text(pool, fe_v.Ty, ty_buf_v)
|
||||
if zero_v is None:
|
||||
continue
|
||||
written_v = viperlib.snprintf(init_full + pos_v, init_full_len - pos_v, ", %s", zero_v)
|
||||
pos_v += t.CSizeT(written_v)
|
||||
viperlib.snprintf(init_full + pos_v, init_full_len - pos_v, " }")
|
||||
stg_init_text = init_full
|
||||
stg_name_len: t.CSizeT = t.CSizeT(string.strlen(mangled_name)) + 8
|
||||
stg_name_buf: str = pool.alloc(stg_name_len)
|
||||
if stg_name_buf is not None:
|
||||
|
||||
Reference in new issue
Block a user