diff --git a/App/lib/core/Gen/Class/ClassGenVTable.vp b/App/lib/core/Gen/Class/ClassGenVTable.vp index 851ca9c..1b9a97b 100644 --- a/App/lib/core/Gen/Class/ClassGenVTable.vp +++ b/App/lib/core/Gen/Class/ClassGenVTable.vp @@ -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__". diff --git a/App/lib/core/Gen/Func/FuncGenDef.vp b/App/lib/core/Gen/Func/FuncGenDef.vp index 0a7b230..4b2bb7a 100644 --- a/App/lib/core/Gen/Func/FuncGenDef.vp +++ b/App/lib/core/Gen/Func/FuncGenDef.vp @@ -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'). diff --git a/App/lib/core/Gen/Func/FuncGenMixin.vp b/App/lib/core/Gen/Func/FuncGenMixin.vp index 3d4f73e..08a0666 100644 --- a/App/lib/core/Gen/Func/FuncGenMixin.vp +++ b/App/lib/core/Gen/Func/FuncGenMixin.vp @@ -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.