feat(gen): 裸类形参按值物化(值语义),调用方 ABI 不变
This commit is contained in:
1 parent
d7a5f7e68b
commit
87914b0a51
3 files changed
+56
-8
No files matched your search
@@ -726,6 +726,8 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase):
|
||||
arg2: ast.Arg* = ast.Arg*(alist2.get(ai2))
|
||||
if arg2 is not None and arg2.arg is not None:
|
||||
param_ty2: mlirlite.LLVMType* = i32_ty
|
||||
# 裸类形参=按值:slot_ty2 非空表示该形参按值物化(槽取 struct 展开,入口 load 一份)
|
||||
slot_ty2: mlirlite.LLVMType* = None
|
||||
if arg2.annotation is not None:
|
||||
resolved2: mlirlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(pool, arg2.annotation, imported_modules, from_imports, trans, 0)
|
||||
if resolved2 is None:
|
||||
@@ -741,11 +743,14 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase):
|
||||
return 0
|
||||
case mlirlite.LLVMType.Struct(_, _, _):
|
||||
param_ty2 = mlirlite.Ptr(pool, resolved2)
|
||||
slot_ty2 = resolved2
|
||||
case mlirlite.LLVMType.Array(aelem_ty2, _):
|
||||
param_ty2 = mlirlite.Ptr(pool, aelem_ty2)
|
||||
case _:
|
||||
param_ty2 = resolved2
|
||||
alloca: mlirlite.Value* = mlirlite.build_alloca(func_builder, param_ty2)
|
||||
pslot_ty2: mlirlite.LLVMType* = param_ty2
|
||||
if slot_ty2 is not None: pslot_ty2 = slot_ty2
|
||||
alloca: mlirlite.Value* = mlirlite.build_alloca(func_builder, pslot_ty2)
|
||||
if alloca is not None:
|
||||
self.Gen.VarGen.define_var(trans.SymTab, arg2.arg, alloca)
|
||||
# Store the raw annotation class name (call detection falls back from Ptr(i8) to a class-name lookup).
|
||||
@@ -755,7 +760,12 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase):
|
||||
pname2: str = pool.alloc(32)
|
||||
if pname2 is not None: viperlib.snprintf(pname2, 32, "%%%s", arg2.arg)
|
||||
param_val: mlirlite.Value* = mlirlite.SSAValue(pool, param_ty2, pname2)
|
||||
mlirlite.build_store(func_builder, param_val, alloca)
|
||||
if slot_ty2 is not None:
|
||||
# 裸类形参=按值语义:调用方传的是对象地址,入口 load 一份 Aggregate 存入值槽(C:传 struct 即拷贝)
|
||||
pv_cp2: mlirlite.Value* = mlirlite.build_load(func_builder, slot_ty2, param_val)
|
||||
if pv_cp2 is not None: mlirlite.build_store(func_builder, pv_cp2, alloca)
|
||||
else:
|
||||
mlirlite.build_store(func_builder, param_val, alloca)
|
||||
|
||||
# OOP iter protocol: initialize __next__'s stop-flag (store 0) and save the pointer to trans
|
||||
# so raise StopIteration writes 1; the name must match add_param's "%__stop_iter_flag__".
|
||||
|
||||
@@ -650,6 +650,8 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase):
|
||||
if arg2.annotation is not None:
|
||||
if self.Gen.TypeGenResolve._is_t_attr(arg2.annotation, "CVoid", imported_modules) != 0: continue
|
||||
param_ty2: mlirlite.LLVMType* = i32_ty
|
||||
# 裸类形参=按值:slot_ty2 非空表示该形参按值物化(槽取 struct 展开,入口 load 一份)
|
||||
slot_ty2: mlirlite.LLVMType* = None
|
||||
if arg2.annotation is not None:
|
||||
resolved2: mlirlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(pool, arg2.annotation, imported_modules, from_imports, trans, 0)
|
||||
if resolved2 is None:
|
||||
@@ -666,11 +668,14 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase):
|
||||
return 0
|
||||
case mlirlite.LLVMType.Struct(_, _, _):
|
||||
param_ty2 = mlirlite.Ptr(pool, resolved2)
|
||||
slot_ty2 = resolved2
|
||||
case mlirlite.LLVMType.Array(aelem_ty2, _):
|
||||
param_ty2 = mlirlite.Ptr(pool, aelem_ty2)
|
||||
case _:
|
||||
param_ty2 = resolved2
|
||||
alloca: mlirlite.Value* = mlirlite.build_alloca(func_builder, param_ty2)
|
||||
pslot_ty2: mlirlite.LLVMType* = param_ty2
|
||||
if slot_ty2 is not None: pslot_ty2 = slot_ty2
|
||||
alloca: mlirlite.Value* = mlirlite.build_alloca(func_builder, pslot_ty2)
|
||||
if alloca is not None:
|
||||
self.Gen.VarGen.define_var(trans.SymTab, arg2.arg, alloca)
|
||||
# Store the original annotation's class name (method-call detection falls back from Ptr(i8) to the class).
|
||||
@@ -692,7 +697,12 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase):
|
||||
if pname2 is not None: viperlib.snprintf(pname2, 32, "%%%s", arg2.arg)
|
||||
param_val: mlirlite.Value* = mlirlite.SSAValue(pool, param_ty2, pname2)
|
||||
vol_p2: int = self.Gen.VarGen.var_is_volatile(self.Gen.VarGen.lookup_var_entry(trans.SymTab, arg2.arg))
|
||||
mlirlite.build_store(func_builder, param_val, alloca, vol_p2)
|
||||
if slot_ty2 is not None:
|
||||
# 裸类形参=按值语义:入口从对象地址 load 一份 Aggregate 存入值槽(C:传 struct 即拷贝)
|
||||
pv_cp2: mlirlite.Value* = mlirlite.build_load(func_builder, slot_ty2, param_val)
|
||||
if pv_cp2 is not None: mlirlite.build_store(func_builder, pv_cp2, alloca, vol_p2)
|
||||
else:
|
||||
mlirlite.build_store(func_builder, param_val, alloca, vol_p2)
|
||||
|
||||
# *args variadic: allocate a 24-byte va_list buffer, bitcast to i8*, call @llvm.va_start, register in the symbol table.
|
||||
# Must be inside the param alloca section but outside the EH block, or args is unregistered (NameError: 'args').
|
||||
|
||||
@@ -156,7 +156,14 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase):
|
||||
ty_slot_n: str* = (str*)(ty_addr_n)
|
||||
pty2_n = (mlirlite.LLVMType*)(ty_slot_n[0])
|
||||
if pty2_n is None: pty2_n = i32_ty
|
||||
p_alloca: mlirlite.Value* = mlirlite.build_alloca(func_builder, pty2_n)
|
||||
# 裸类形参=按值:注解解析为 struct 时按值物化(槽取 struct 展开,入口 load 一份)
|
||||
slot_ty_n: mlirlite.LLVMType* = None
|
||||
if arg_p.annotation is not None:
|
||||
rv_n: mlirlite.LLVMType* = self.Gen.TypeGenResolve.resolve_annotation_type(pool, arg_p.annotation, imported_modules, trans._from_imports, trans, 0)
|
||||
if rv_n is not None and rv_n.kind() == mlirlite.LLVMType.Struct: slot_ty_n = rv_n
|
||||
pslot_ty_n: mlirlite.LLVMType* = pty2_n
|
||||
if slot_ty_n is not None: pslot_ty_n = slot_ty_n
|
||||
p_alloca: mlirlite.Value* = mlirlite.build_alloca(func_builder, pslot_ty_n)
|
||||
if p_alloca is not None:
|
||||
self.Gen.VarGen.define_var(trans.SymTab, arg_p.arg, p_alloca)
|
||||
if arg_p.annotation is not None:
|
||||
@@ -175,7 +182,12 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase):
|
||||
if pname2_n is not None: viperlib.snprintf(pname2_n, 32, "%%%s", arg_p.arg)
|
||||
p_val: mlirlite.Value* = mlirlite.SSAValue(pool, pty2_n, pname2_n)
|
||||
vol_pn: int = self.Gen.VarGen.var_is_volatile(self.Gen.VarGen.lookup_var_entry(trans.SymTab, arg_p.arg))
|
||||
mlirlite.build_store(func_builder, p_val, p_alloca, vol_pn)
|
||||
if slot_ty_n is not None:
|
||||
# 裸类形参=按值语义:入口从对象地址 load 一份 Aggregate 存入值槽
|
||||
pv_n: mlirlite.Value* = mlirlite.build_load(func_builder, slot_ty_n, p_val)
|
||||
if pv_n is not None: mlirlite.build_store(func_builder, pv_n, p_alloca, vol_pn)
|
||||
else:
|
||||
mlirlite.build_store(func_builder, p_val, p_alloca, vol_pn)
|
||||
idx_p += 1
|
||||
|
||||
# 6. Save the parent function scope state (variable-table independent)
|
||||
@@ -898,6 +910,10 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase):
|
||||
param_tys: t.CPtr = pool.alloc(8 * 64) # LLVMType pointer slots
|
||||
if param_tys is None: return None
|
||||
string.memset(param_tys, 0, 8 * 64)
|
||||
# 裸类形参=按值:值槽类型(struct 展开);空槽=与 ABI 同型(按原样存)
|
||||
param_vtys: t.CPtr = pool.alloc(8 * 64)
|
||||
if param_vtys is None: return None
|
||||
string.memset(param_vtys, 0, 8 * 64)
|
||||
param_count: int = 0
|
||||
if lam.args is not None:
|
||||
ags: ast.Arguments* = ast.Arguments*(lam.args)
|
||||
@@ -920,6 +936,8 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase):
|
||||
match resolved:
|
||||
case mlirlite.LLVMType.Struct(_, _, _):
|
||||
p_ty = mlirlite.Ptr(pool, resolved)
|
||||
vt_slot_p: str* = str*(uint64(param_vtys) + param_count * 8)
|
||||
vt_slot_p[0] = resolved
|
||||
case mlirlite.LLVMType.Array(aelem_ty_l, _):
|
||||
p_ty = mlirlite.Ptr(pool, aelem_ty_l)
|
||||
case _:
|
||||
@@ -1029,13 +1047,23 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase):
|
||||
# fail-fast: lambda param type slot missing (inconsistent state); do not keep i32
|
||||
self.Gen.TypeGenErr.fatal_error(lam, f"lambda param '{param_names + pi3 * 32}' type info missing", "InternalCompilerError")
|
||||
p_ty3 = i32_ty # unreachable (fatal_error already exited)
|
||||
vt_addr4: uint64 = uint64(param_vtys) + pi3 * 8
|
||||
vt_slot4: str* = (str*)(vt_addr4)
|
||||
p_vty3: mlirlite.LLVMType* = (mlirlite.LLVMType*)(vt_slot4[0])
|
||||
p_slot3: mlirlite.LLVMType* = p_ty3
|
||||
if p_vty3 is not None: p_slot3 = p_vty3
|
||||
pname_ref: str = pool.alloc(32)
|
||||
if pname_ref is not None:
|
||||
viperlib.snprintf(pname_ref, 32, "%%%s", param_names + pi3 * 32)
|
||||
param_ref: mlirlite.Value* = mlirlite.SSAValue(pool, p_ty3, pname_ref)
|
||||
arg_alloca: mlirlite.Value* = mlirlite.build_alloca(func_builder, p_ty3)
|
||||
arg_alloca: mlirlite.Value* = mlirlite.build_alloca(func_builder, p_slot3)
|
||||
if arg_alloca is not None:
|
||||
mlirlite.build_store(func_builder, param_ref, arg_alloca)
|
||||
if p_vty3 is not None:
|
||||
# 裸类形参=按值语义:入口从对象地址 load 一份 Aggregate 存入值槽
|
||||
pv3: mlirlite.Value* = mlirlite.build_load(func_builder, p_vty3, param_ref)
|
||||
if pv3 is not None: mlirlite.build_store(func_builder, pv3, arg_alloca)
|
||||
else:
|
||||
mlirlite.build_store(func_builder, param_ref, arg_alloca)
|
||||
self.Gen.VarGen.define_var(trans.SymTab, param_names + pi3 * 32, arg_alloca)
|
||||
|
||||
# 11. Translate the body expression and return it.
|
||||
|
||||
Reference in new issue
Block a user