refactor(struct): AST vtable 拷贝改为按 uint64 槽显式读写
原写法 *dst_c = vt_ptr_c 把 i8* 赋给结构体类型的左值,TPC 会以「非基本类型禁止指针隐式转值类型」报错。新增 _copy_ast_vtable(src, dst):把两侧 AST 节点都视作一个 uint64 槽(src_vt[0] -> dst_vt[0]),语义不变(只复制首字段 vptr),Constant 与 List 两条深拷贝路径统一调用它。
This commit is contained in:
1 parent
3e1e1fc1b3
commit
d46fdf152a
1 file changed
+20
-10
@@ -1,4 +1,3 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import memhub
|
||||
import string
|
||||
@@ -2498,6 +2497,20 @@ novirtual class StructGenMixin:
|
||||
struct_entry.FieldCount = idx + 1
|
||||
return idx
|
||||
|
||||
def _copy_ast_vtable(self, src: ast.AST*, dst: ast.AST*) -> None:
|
||||
"""Copy the vtable word (field 0) from one AST node to another.
|
||||
|
||||
AST classes are @t.CVTable: virtual calls such as kind() dispatch through the first
|
||||
field. Both nodes are viewed as a single uint64 slot, which reads better than assigning
|
||||
a pointer to a struct-typed lvalue (TPC rejects that implicit pointer -> struct value
|
||||
conversion; it also once emitted no load/store at all, leaving vptr=0 and crashing
|
||||
kind() with `load i8*, i8** [0 + 0]`).
|
||||
"""
|
||||
if src is None or dst is None: return
|
||||
src_vt: uint64* = (uint64*)(src)
|
||||
dst_vt: uint64* = (uint64*)(dst)
|
||||
dst_vt[0] = src_vt[0]
|
||||
|
||||
def _deep_copy_default_ast(self, pool: memhub.MemBuddy*, default_val: ast.AST*) -> ast.AST*:
|
||||
"""Deep-copy a field default AST (constants and lists) into the perm pool."""
|
||||
if default_val is None: return None
|
||||
@@ -2507,10 +2520,8 @@ novirtual class StructGenMixin:
|
||||
dst_c: ast.Constant* = ast.Constant*(pool.alloc_tagged(ast.Constant.__sizeof__(), memhub.DETSITE_STRUCTGENMIXIN_641))
|
||||
if dst_c is None: return None
|
||||
string.memset(dst_c, 0, ast.Constant.__sizeof__())
|
||||
# Copy the vtable pointer (AST is @t.CVTable; kind() virtual calls depend on the first-field vptr); must match _deep_copy_list_ast (c.Deref read + c.DerefAs write).
|
||||
# The old form silently failed under TPC: no load-vptr instruction and no store emitted, leaving vptr=0, so a later node.kind() reads `load i8*, i8** [0 + 0]` -> ASan READ at 0x0. Evidence: ViperC\output\b5883dc9c114a604.ll:10382-10384.
|
||||
vt_ptr_c: t.CPtr = t.CPtr(*((uint64*)(default_val)))
|
||||
c.DerefAs(dst_c, vt_ptr_c)
|
||||
# Copy the vtable pointer (AST is @t.CVTable; virtual kind() dispatches through field 0).
|
||||
self._copy_ast_vtable(default_val, dst_c)
|
||||
# Copy position fields (for error location).
|
||||
dst_c.lineno = src_c.lineno
|
||||
dst_c.col_offset = src_c.col_offset
|
||||
@@ -2534,9 +2545,8 @@ novirtual class StructGenMixin:
|
||||
dst_l: ast.List* = ast.List*(pool.alloc(ast.List.__sizeof__()))
|
||||
if dst_l is None: return None
|
||||
string.memset(dst_l, 0, ast.List.__sizeof__())
|
||||
# Copy the vtable pointer (AST is @t.CVTable; kind() virtual calls depend on the first-field vptr).
|
||||
vt_l: t.CPtr = t.CPtr(*((uint64*)(default_val)))
|
||||
c.DerefAs(dst_l, vt_l)
|
||||
# Copy the vtable pointer (same requirement as the Constant copy above).
|
||||
self._copy_ast_vtable(default_val, dst_l)
|
||||
# Copy position fields and ctx.
|
||||
dst_l.lineno = src_l.lineno
|
||||
dst_l.col_offset = src_l.col_offset
|
||||
@@ -2547,7 +2557,7 @@ novirtual class StructGenMixin:
|
||||
src_elts_l: list[ast.AST*]* = src_l.elts
|
||||
if src_elts_l is not None:
|
||||
cnt_l: sizet = len(src_elts_l)
|
||||
lst_copy_l: list[ast.AST*]* = (list[ast.AST*] | t.CPtr)(pool.alloc_tagged(list[ast.AST*].__sizeof__(), memhub.DETSITE_STRUCTGENMIXIN_693))
|
||||
lst_copy_l: list[ast.AST*]* = list[ast.AST*]*(pool.alloc_tagged(list[ast.AST*].__sizeof__(), memhub.DETSITE_STRUCTGENMIXIN_693))
|
||||
if lst_copy_l is not None:
|
||||
string.memset(lst_copy_l, 0, list[ast.AST*].__sizeof__())
|
||||
# The count must never be fixed from the source count up front; it must be settled by the actual written slot count (written_l below).
|
||||
@@ -2557,7 +2567,7 @@ novirtual class StructGenMixin:
|
||||
elem_sz_l: sizet = 8
|
||||
lst_copy_l.__elem_size__ = elem_sz_l
|
||||
lst_copy_l.__pool__ = None
|
||||
data_l: t.CPtr = pool.alloc_tagged(cnt_l * elem_sz_l, memhub.DETSITE_STRUCTGENMIXIN_698)
|
||||
data_l: rawptr = pool.alloc_tagged(cnt_l * elem_sz_l, memhub.DETSITE_STRUCTGENMIXIN_698)
|
||||
if data_l is not None:
|
||||
string.memset(data_l, 0, cnt_l * elem_sz_l)
|
||||
lst_copy_l.__data__ = data_l
|
||||
|
||||
Reference in new issue
Block a user