fix(gen): 值语义聚合槽允许隐式值拷贝,修 self.field = param 的 Foo* -> Foo 误报
This commit is contained in:
1 parent
3384941cd1
commit
7c11c589f7
1 file changed
+26
-3
@@ -455,7 +455,7 @@ novirtual class ExprGenBase:
|
||||
if callee is None: return None
|
||||
ent: GenTypes.StructEntry* = self.Gen.StructGen.find_struct(callee)
|
||||
if ent is not None and ent.Ty is not None: return ent.Ty
|
||||
# REnum variant ctor `EnumType.Variant(...)`: the callee is not a struct
|
||||
# REnum variant ctor `EnumType.Variant(...)`: the callee is not a struct
|
||||
# name, but materializes the base enum, so return that aggregate type.
|
||||
if cl.func.kind() == ast.ASTKind.Attribute:
|
||||
# Take the segment left of the variant name as the enum class name
|
||||
@@ -474,6 +474,24 @@ novirtual class ExprGenBase:
|
||||
"""Are a and b the same aggregate type; 1=yes / 0=no."""
|
||||
if a is None or b is None: return 0
|
||||
return self.Gen.AssignGen._stg_ty_equal(pool, a, b)
|
||||
# _agg_value_slot_ty - 值语义槽:源表达式的变量槽**自身**持有聚合物(`x: Foo`,Spec.PtrLevel == 0)。
|
||||
# 形参按「聚合一律按指针传」的 ABI 到达,但它在被调者里同样物化在自己的槽中,读槽即值拷贝;
|
||||
# 真·指针值(`p: Foo*`,Spec.PtrLevel >= 1)返回 None,仍必须显式解引用(c.deref(p) / *p)。
|
||||
# 返回该聚合类型;不适用时 None。
|
||||
def _agg_value_slot_ty(self, node: ast.AST*, val: mlirlite.Value*, trans: HT.Translator*) -> mlirlite.LLVMType*:
|
||||
"""Aggregate type when the source is a variable slot holding the aggregate by value; else None."""
|
||||
n: ast.AST* = self._value_node_of(node)
|
||||
if n is None or n.kind() != ast.ASTKind.Name: return None
|
||||
nm: str = (ast.Name*(n)).id
|
||||
if nm is None or trans is None: return None
|
||||
ve: GenTypes.VarEntry* = self.Gen.VarGen.lookup_var_entry(trans.SymTab, nm)
|
||||
if ve is None or ve.Alloca is None or ve.Spec is None: return None
|
||||
# 必须是槽本身(若已被加载成指针值,说明源本来就是个指针,不豁免)。
|
||||
if ve.Alloca is not val: return None
|
||||
# 声明的就是 T*(PtrLevel>=1):真指针,必须显式解引用。
|
||||
if ve.Spec.PtrLevel != 0: return None
|
||||
if self.is_ptr_type(ve.Alloca.Ty) == 0: return None
|
||||
return ve.Alloca.Ty.Pointee
|
||||
# Type coercion: int sext/trunc, float fpext/fptrunc, int<->float si2fp/fp2si.
|
||||
def coerce_to_type(self, builder: mlirlite.IRBuilder*, val: mlirlite.Value*, target_ty: mlirlite.LLVMType*, node: ast.AST* = None, trans: HT.Translator* = None) -> mlirlite.Value*:
|
||||
"""Coerce val to target_ty: int sext/trunc, float fpext/fptrunc, int/float conversions."""
|
||||
@@ -564,7 +582,7 @@ novirtual class ExprGenBase:
|
||||
if val_bits != 0 and target_fbits != 0: return mlirlite.build_si2fp(builder, val, target_ty)
|
||||
# float -> int
|
||||
if val_fbits != 0 and target_bits != 0: return mlirlite.build_fp2si(builder, val, target_ty)
|
||||
# Aggregate value -> pointer: spill a temp to the entry block and pass its
|
||||
# Aggregate value -> pointer: spill a temp to the entry block and pass its
|
||||
# address (TPV never passes aggregates by value).
|
||||
if self.is_ptr_type(val.Ty) == 0 and self.is_ptr_type(target_ty) != 0:
|
||||
vk_agg: int = val.Ty.kind()
|
||||
@@ -596,6 +614,11 @@ novirtual class ExprGenBase:
|
||||
# Rule 3: implicit ptr -> value for non-basic types (Foo* -> Foo) is
|
||||
# forbidden, except "construction materialization" (see _ctor_call_agg_ty).
|
||||
ctor_p2v: mlirlite.LLVMType* = self._ctor_call_agg_ty(node)
|
||||
# 值语义槽豁免:源是变量槽自身持有聚合物(`x: Foo`;形参虽按「聚合按指针传」的
|
||||
# ABI 到达,也物化在自己的槽中)时,读槽 = 值拷贝(`self.f = elem` 这类写法)。
|
||||
slot_p2v: mlirlite.LLVMType* = self._agg_value_slot_ty(node, val, trans)
|
||||
if self._same_agg_ty(builder.Pool, slot_p2v, target_ty) != 0:
|
||||
return mlirlite.build_load(builder, target_ty, val)
|
||||
if self._same_agg_ty(builder.Pool, ctor_p2v, target_ty) == 0:
|
||||
m_p2v: str = "implicit value/pointer conversion for non-basic types is forbidden (except construction materialization): a pointer type cannot be implicitly converted to a non-basic value (Foo* -> Foo); to dereference use c.deref(p) / *p explicitly, or cast explicitly"
|
||||
p2v_txt: str = GenApi.escape_fstring_copy(f"; source type {self._type_text(builder.Pool, val.Ty)} -> target value type {self._type_text(builder.Pool, target_ty)}")
|
||||
@@ -620,7 +643,7 @@ novirtual class ExprGenBase:
|
||||
if val is None or val.Ty is None: return 0
|
||||
return self.Gen.ExprGenOps.should_zext_widen(pool, val, None, node, trans)
|
||||
|
||||
# translate_ptr_arith: ptr +/- int via getelementptr (index scaled by pointee
|
||||
# translate_ptr_arith: ptr +/- int via getelementptr (index scaled by pointee
|
||||
# size); array pointees ([N x ty]*) decay to element pointers first.
|
||||
def translate_ptr_arith(self, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, ptr_val: mlirlite.Value*, int_val: mlirlite.Value*, op: int) -> mlirlite.Value*:
|
||||
"""Pointer arithmetic: ptr +/- int via GEP with the index scaled by element size."""
|
||||
|
||||
Reference in new issue
Block a user