diff --git a/App/lib/core/Gen/AssignGenMixin.vp b/App/lib/core/Gen/AssignGenMixin.vp index 6c7dc32..4bc7b7d 100644 --- a/App/lib/core/Gen/AssignGenMixin.vp +++ b/App/lib/core/Gen/AssignGenMixin.vp @@ -1363,6 +1363,19 @@ class AssignGenMixin: if val_nm.id is not None: if self.Gen.AsyncGen.is_async_func(trans, val_nm.id) != 0: self.Gen.AsyncGen.register_coro_var(trans, nm.id, val_nm.id) + # c.Addr(async_call):tt: Coroutine = c.Addr(task()) 就地解读 + elif val_cl.func is not None and val_cl.func.kind() == ast.ASTKind.Attribute: + val_at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(val_cl.func) + if val_at.attr is not None and string.strcmp(val_at.attr, "Addr") == 0 \ + and val_cl.args is not None and len(val_cl.args) >= 1: + icall: ast.AST | t.CPtr = val_cl.args.get(0) + if icall is not None and icall.kind() == ast.ASTKind.Call: + icl2: ast.Call | t.CPtr = (ast.Call | t.CPtr)(icall) + if icl2.func is not None and icl2.func.kind() == ast.ASTKind.Name: + inm2: ast.Name | t.CPtr = (ast.Name | t.CPtr)(icl2.func) + if inm2.id is not None: + if self.Gen.AsyncGen.is_async_func(trans, inm2.id) != 0: + self.Gen.AsyncGen.register_coro_var(trans, nm.id, inm2.id) # 局部数组:列表字面量 → 逐元素 GEP + store 初始化 # 修复:此前局部 CArray[...] = [x, y] 会走 translate_list_literal, # 错误触发 list[T] 泛型特化(堆对象)导致崩溃(如 this.vp 的 diff --git a/App/lib/core/Gen/AsyncGenMixin.vp b/App/lib/core/Gen/AsyncGenMixin.vp index d7137d8..ea67792 100644 --- a/App/lib/core/Gen/AsyncGenMixin.vp +++ b/App/lib/core/Gen/AsyncGenMixin.vp @@ -2203,12 +2203,8 @@ class AsyncGenMixin(CallGenBase.CallGenBase): if frame_ty is None: return llvmlite.const_int32(pool, 0) frame_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, frame_ty) - frame_val: llvmlite.Value | t.CPtr = self.Gen.ExprGen.translate_value( - builder, pool, mod, cl.args.get(0), None, 0, trans) - if frame_val is None: - return llvmlite.const_int32(pool, 0) - frame_ptr: llvmlite.Value | t.CPtr = llvmlite.build_bitcast( - builder, frame_val, frame_ptr_ty) + frame_ptr: llvmlite.Value | t.CPtr = self._coro_frame_ptr_from_arg( + builder, pool, mod, trans, cl.args.get(0), frame_ptr_ty) if frame_ptr is None: return llvmlite.const_int32(pool, 0) # 回池:帧首 8 字节存旧池头;池头 = 本帧(i64) @@ -2248,12 +2244,8 @@ class AsyncGenMixin(CallGenBase.CallGenBase): if frame_ty is None: return llvmlite.const_int32(pool, 0) frame_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, frame_ty) - frame_val: llvmlite.Value | t.CPtr = self.Gen.ExprGen.translate_value( - builder, pool, mod, cl.args.get(0), None, 0, trans) - if frame_val is None: - return llvmlite.const_int32(pool, 0) - frame_ptr: llvmlite.Value | t.CPtr = llvmlite.build_bitcast( - builder, frame_val, frame_ptr_ty) + frame_ptr: llvmlite.Value | t.CPtr = self._coro_frame_ptr_from_arg( + builder, pool, mod, trans, cl.args.get(0), frame_ptr_ty) if frame_ptr is None: return llvmlite.const_int32(pool, 0) exc_ptr: llvmlite.Value | t.CPtr = llvmlite.build_gep_struct( @@ -2278,12 +2270,8 @@ class AsyncGenMixin(CallGenBase.CallGenBase): if frame_ty is None: return llvmlite.ConstNull(pool, i8_ptr_ty, "null") frame_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, frame_ty) - frame_val: llvmlite.Value | t.CPtr = self.Gen.ExprGen.translate_value( - builder, pool, mod, cl.args.get(0), None, 0, trans) - if frame_val is None: - return llvmlite.ConstNull(pool, i8_ptr_ty, "null") - frame_ptr: llvmlite.Value | t.CPtr = llvmlite.build_bitcast( - builder, frame_val, frame_ptr_ty) + frame_ptr: llvmlite.Value | t.CPtr = self._coro_frame_ptr_from_arg( + builder, pool, mod, trans, cl.args.get(0), frame_ptr_ty) if frame_ptr is None: return llvmlite.ConstNull(pool, i8_ptr_ty, "null") msg_ptr: llvmlite.Value | t.CPtr = llvmlite.build_gep_struct( @@ -2311,12 +2299,8 @@ class AsyncGenMixin(CallGenBase.CallGenBase): if frame_ty is None: continue frame_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, frame_ty) - frame_val: llvmlite.Value | t.CPtr = self.Gen.ExprGen.translate_value( - builder, pool, mod, arg0, None, 0, trans) - if frame_val is None: - continue - frame_ptr: llvmlite.Value | t.CPtr = llvmlite.build_bitcast( - builder, frame_val, frame_ptr_ty) + frame_ptr: llvmlite.Value | t.CPtr = self._coro_frame_ptr_from_arg( + builder, pool, mod, trans, arg0, frame_ptr_ty) if frame_ptr is None: continue rn_buf: str = pool.alloc(64) @@ -2344,6 +2328,47 @@ class AsyncGenMixin(CallGenBase.CallGenBase): llvmlite.position_at_end(builder, after_bb) return llvmlite.const_int32(pool, 0) + def _coro_frame_ptr_from_arg(self, builder: llvmlite.IRBuilder | t.CPtr, + pool: memhub.MemBuddy | t.CPtr, + mod: llvmlite.LLVMModule | t.CPtr, + trans: HT.Translator | t.CPtr, + arg0: ast.AST | t.CPtr, + frame_ptr_ty: llvmlite.LLVMType | t.CPtr + ) -> llvmlite.Value | t.CPtr: + """协程参数节点 → 帧指针 Ptr(帧): + - 普通指针(t.CPtr / 帧指针):直接 bitcast(既有路径) + - Coroutine 结构体变量(tt: Coroutine = c.Addr(task()) 就地解读): + translate_value 按"对象即指针"返回 alloca 地址(ExprGenName 对 + pointee=Struct 不 load),故 pointee 是结构体时 GEP __ptr__(index 0) + load 帧指针——bitcast 聚合地址→帧指针会写越界,必须经字段提取。 + """ + if arg0 is None or frame_ptr_ty is None: + return None + frame_val: llvmlite.Value | t.CPtr = self.Gen.ExprGen.translate_value( + builder, pool, mod, arg0, None, 0, trans) + if frame_val is None or frame_val.Ty is None: + return None + if self.Gen.ExprGenBase.is_ptr_type(frame_val.Ty) != 0: + pointee: llvmlite.LLVMType | t.CPtr = frame_val.Ty.Pointee + if pointee is not None: + match pointee: + case llvmlite.LLVMType.Struct(_, _, _): + i8_ptr_ty_t: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr( + pool, llvmlite.Int8(pool)) + ptr_field: llvmlite.Value | t.CPtr = llvmlite.build_gep_struct( + builder, pointee, i8_ptr_ty_t, frame_val, 0) + if ptr_field is None: + return None + raw_ptr: llvmlite.Value | t.CPtr = llvmlite.build_load( + builder, i8_ptr_ty_t, ptr_field) + if raw_ptr is None: + return None + return llvmlite.build_bitcast( + builder, raw_ptr, frame_ptr_ty) + case _: + pass + return llvmlite.build_bitcast(builder, frame_val, frame_ptr_ty) + def _var_to_async(self, trans: HT.Translator | t.CPtr, arg0: ast.AST | t.CPtr) -> str: """变量节点 → async 函数名(_coro_var_async 反查),未命中返回 None""" @@ -2523,13 +2548,9 @@ class AsyncGenMixin(CallGenBase.CallGenBase): return llvmlite.const_int32(pool, 0) frame_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, frame_ty) - # 帧变量值(i8* / Ptr(帧))→ bitcast 到 Ptr(帧) - frame_val: llvmlite.Value | t.CPtr = self.Gen.ExprGen.translate_value( - builder, pool, mod, arg0, None, 0, trans) - if frame_val is None: - return llvmlite.const_int32(pool, 0) - frame_ptr: llvmlite.Value | t.CPtr = llvmlite.build_bitcast( - builder, frame_val, frame_ptr_ty) + # 帧变量值(i8* / Ptr(帧) / Coroutine 结构体)→ Ptr(帧) + frame_ptr: llvmlite.Value | t.CPtr = self._coro_frame_ptr_from_arg( + builder, pool, mod, trans, arg0, frame_ptr_ty) if frame_ptr is None: return llvmlite.const_int32(pool, 0) diff --git a/App/lib/core/Gen/CallGenCBuiltin.vp b/App/lib/core/Gen/CallGenCBuiltin.vp index 37e3285..7ebaa18 100644 --- a/App/lib/core/Gen/CallGenCBuiltin.vp +++ b/App/lib/core/Gen/CallGenCBuiltin.vp @@ -454,7 +454,22 @@ class CallGenCBuiltin(CallGenBase.CallGenBase): pass return None - # 其他 arg0 形式(非 Name/Attribute/Subscript):真实掉出函数末尾, + # Call 形式: c.Addr(expr) → 求值 expr 存临时槽(entry alloca),返回槽地址 + # 供就地解读使用:tt: Coroutine = c.Addr(task()) —— coerce 指针→结构体时 + # 从槽地址 load(target 是 NoVTable 结构体,如 Coroutine={__ptr__} 8 字节)。 + if arg0.kind() == ast.ASTKind.Call: + call_val: llvmlite.Value | t.CPtr = self.Gen.ExprGen.translate_value( + builder, pool, mod, arg0, None, 0, trans) + if call_val is None or call_val.Ty is None: + return None + tmp_slot: llvmlite.Value | t.CPtr = llvmlite.build_alloca_at_entry( + builder, call_val.Ty) + if tmp_slot is None: + return None + llvmlite.build_store(builder, call_val, tmp_slot) + return tmp_slot + + # 其他 arg0 形式(非 Name/Attribute/Subscript/Call):真实掉出函数末尾, # 补显式 return None(fail-fast 不允许流程掉出末尾) return None