fix(gen): 补全新语法 &/* 的取地址与解引用路径
(*p).attr 属性基址:_get_cderef_attr_base 增加 UnaryOp(Deref) 分支(读写都要求 GEP 指针本身,而非加载后的结构体值)。_is_addrlike_call 增加 AddrOf/Deref 分支:指针型右值不应走模块全局的『静态存储对象拷贝』分支。
This commit is contained in:
1 parent
df2de5ecfa
commit
374921623b
2 files changed
+24
-4
No files matched your search
@@ -562,8 +562,17 @@ novirtual class AssignGenMixin:
|
||||
return 1 if string.strcmp(buf_a, buf_b) == 0 else 0
|
||||
|
||||
def _is_addrlike_call(self, node: ast.AST*) -> int:
|
||||
"""Return 1 if the rhs is an explicit c.Addr/c.Deref-style pointer call."""
|
||||
if node is None or node.kind() != ast.ASTKind.Call: return 0
|
||||
"""Return 1 if the rhs is an explicit pointer expression (c.Addr/c.Deref/c.Cast/c.Ptr call, or new-syntax `&x` / `*p`)."""
|
||||
if node is None: return 0
|
||||
# New syntax (R3/R4): `&x` and `*p` parse as UnaryOp(AddrOf) / UnaryOp(Deref) and replace the
|
||||
# c.Addr / c.Deref call forms. A pointer-valued RHS must not take the module-global
|
||||
# "object with static storage -> copy the object" branch, so both forms count as addrlike.
|
||||
if node.kind() == ast.ASTKind.UnaryOp:
|
||||
uo_al: ast.UnaryOp* = ast.UnaryOp*(node)
|
||||
if uo_al.op == ast.OpKind.AddrOf: return 1
|
||||
if uo_al.op == ast.OpKind.Deref: return 1
|
||||
return 0
|
||||
if node.kind() != ast.ASTKind.Call: return 0
|
||||
cl: ast.Call* = ast.Call*(node)
|
||||
if cl.func is None or cl.func.kind() != ast.ASTKind.Attribute: return 0
|
||||
at: ast.Attribute* = ast.Attribute*(cl.func)
|
||||
|
||||
@@ -236,8 +236,19 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase):
|
||||
# _get_cderef_attr_base - base pointer of a c.Deref(ptr).attr access (like *p.a → p->a): return the ptr
|
||||
# itself, not the loaded struct value; None for non-c.Deref forms (_deref_if_ptr_ptr resolves the level).
|
||||
def _get_cderef_attr_base(self, builder: mlirlite.IRBuilder*, pool: memhub.MemBuddy*, mod: mlirlite.LLVMModule*, at_value: ast.AST*, trans: HT.Translator* = None) -> mlirlite.Value*:
|
||||
"""Return the ptr itself if at.value is a c.Deref(ptr) call, else None (no load)."""
|
||||
if at_value is None or at_value.kind() != ast.ASTKind.Call: return None
|
||||
"""Return the ptr itself for a dereferenced attribute base (`c.Deref(ptr).attr` / `(*ptr).attr`), else None (no load)."""
|
||||
if at_value is None: return None
|
||||
# New syntax form: `(*ptr).attr` is AST UnaryOp(OpKind.Deref) — identical semantics to the legacy
|
||||
# `c.Deref(ptr).attr`. Without this branch the attribute write path sees a *loaded struct value*
|
||||
# as the base and fails with "base=非指针类型,无法做属性写入"; the read path silently does an
|
||||
# extra struct load. Both must GEP the pointer itself (R4 migration of `c.Deref` -> `*`).
|
||||
if at_value.kind() == ast.ASTKind.UnaryOp:
|
||||
uo_cd: ast.UnaryOp* = ast.UnaryOp*(at_value)
|
||||
if uo_cd.op != ast.OpKind.Deref or uo_cd.operand is None: return None
|
||||
inner_uo: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, uo_cd.operand, None, 0, trans)
|
||||
if inner_uo is not None and self.is_ptr_type(inner_uo.Ty) != 0: return inner_uo
|
||||
return None
|
||||
if at_value.kind() != ast.ASTKind.Call: return None
|
||||
cl_cd: ast.Call* = ast.Call*(at_value)
|
||||
if cl_cd.func is None or cl_cd.func.kind() != ast.ASTKind.Attribute: return None
|
||||
f_cd: ast.Attribute* = ast.Attribute*(cl_cd.func)
|
||||
|
||||
Reference in new issue
Block a user