feat(tpv): 支持 coro.Coroutine = c.Addr(task()) 就地解读句柄赋值
- c.Addr(Call) 分支:求值存临时槽(entry alloca)返回槽地址,
供 coerce 指针→结构体 load 就地解读(Coroutine={__ptr__} 8 字节)
- 协程登记扩展:c.Addr(async_call) 也登记 _coro_var_async
- 新增 _coro_frame_ptr_from_arg 统一提取帧指针:pointee 是 Struct
(Coroutine 变量,translate_value 返回 alloca 地址)GEP __ptr__ load,
普通指针 bitcast 直通;5 处拦截函数(run/destroy/exception/msg/gather)替换
This commit is contained in:
1 parent
609635c73e
commit
e18609e184
3 files changed
+81
-32
No files matched your search
@@ -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 的
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
Reference in new issue
Block a user