1111// 帧模型(Link P4):
1212//
1313// callPC 调用指令绝对路径,作为帧根
14- // callPC/_fn 软链接 → /func/<pkg>/<name>(只读指令)
14+ // callPC/.fn 软链接 → /func/<pkg>/<name>(只读指令)
1515// callPC/<param> 参数(本帧局部变量,不经过链接)
1616// callPC/.callpc 存储 callPC 自身,供 HandleReturn 恢复
17- // callPC/.ret0 调用方的写槽(return 时写入父帧)
1817// callPC/.rootfunc 根函数名(TCO 不更新,供 resolveLabel 使用)
18+ //
19+ // 写槽(读写码语义):
20+ //
21+ // kvlang 只有读写码,函数调用 `add(x,y) -> ./s` 的 `-> ./s` 是**调用方指定的写目标**。
22+ // 写槽路径已存在调用指令 [addr0,1], [addr0,2],... 中,HandleReturn 直接从 .callpc
23+ // 推导路径读取,无需在子帧额外存储——没有"返回值",只有写槽绑定。
1924package layoutcode
2025
2126import (
@@ -67,10 +72,10 @@ func writeStmt(kv kvspace.KVSpace, st ast.Stmt, prefix string, idx *int) {
6772 }
6873}
6974
70- // HandleCall 执行 CALL:链接函数指令树,绑定参数,存储返回槽 。
75+ // HandleCall 执行 CALL:链接函数指令树,绑定参数,存储写槽 。
7176//
72- // pc 为调用指令的绝对路径(如 /vthread/42/_fn /[3,0])。
73- // tail=true 时执行 TCO:复用当前帧,仅重链 _fn (br/goto 路径)。
77+ // pc 为调用指令的绝对路径(如 /vthread/42/.fn /[3,0])。
78+ // tail=true 时执行 TCO:复用当前帧,仅重链 .fn (br/goto 路径)。
7479// 返回被调帧第一条指令的绝对 PC;失败时返回 ""(不再返回 pc,避免"PC == 失败"歧义)。
7580func HandleCall (ctx context.Context , kv kvspace.KVSpace , pc string , inst * op.Instruction , tail bool ) string {
7681 vtid := keytree .VtidFromPC (pc )
@@ -91,7 +96,7 @@ func HandleCall(ctx context.Context, kv kvspace.KVSpace, pc string, inst *op.Ins
9196 }
9297 funcSig := parser .ParseFuncSig (sigVal .Str ())
9398
94- // TCO:复用当前帧,仅重链 _fn 到目标块代码区(.rootfunc 不更新,保持根函数名)
99+ // TCO:复用当前帧,仅重链 .fn 到目标块代码区(.rootfunc 不更新,保持根函数名)
95100 if tail {
96101 frameRoot := keytree .FrameRoot (pc )
97102 kv .Unlink (keytree .FnCode (frameRoot ))
@@ -106,7 +111,7 @@ func HandleCall(ctx context.Context, kv kvspace.KVSpace, pc string, inst *op.Ins
106111 callerFrameRoot := keytree .FrameRoot (pc )
107112 frameRoot := keytree .ChildFrameRoot (pc )
108113
109- // 链接只读指令区:frameRoot/_fn → /func/<pkg>/<name>
114+ // 链接只读指令区:frameRoot/.fn → /func/<pkg>/<name>
110115 if err := kv .Link (funcKey , keytree .FnCode (frameRoot )); err != nil {
111116 vthread .SetError (ctx , kv , vtid , pc , "link failed: " + err .Error ())
112117 return ""
@@ -123,19 +128,15 @@ func HandleCall(ctx context.Context, kv kvspace.KVSpace, pc string, inst *op.Ins
123128 }
124129 }
125130
126- // 存储调用方写槽(return 时写入父帧)
127- for i := range funcSig .ReturnNames () {
128- if i < len (inst .Writes ) {
129- kv .Set (fmt .Sprintf ("%s/.ret%d" , frameRoot , i ), kvspace .Str (inst .Writes [i ]))
130- }
131- }
131+ // 写槽路径已在调用指令 [addr0,1], [addr0,2], ... 中,HandleReturn 从 .callpc 直接读,
132+ // 无需在子帧额外存 .w{N} 冗余键。
132133
133134 return keytree .FnCode (frameRoot ) + "/[0,0]"
134135}
135136
136- // HandleReturn 处理 RETURN:回传值 ,清理帧,恢复父帧 PC。
137+ // HandleReturn 处理 RETURN:将被调方输出写入父帧写槽 ,清理帧,恢复父帧 PC。
137138//
138- // pc 为 return 指令的绝对路径(如 /vthread/42/[3,0]/_fn /[1,0])。
139+ // pc 为 return 指令的绝对路径(如 /vthread/42/[3,0]/.fn /[1,0])。
139140// 返回值:
140141//
141142// ("", retVal) — 顶层 return(frameRoot == vthreadRoot);retVal 供 vthread.SetDone
@@ -162,21 +163,24 @@ func HandleReturn(ctx context.Context, kv kvspace.KVSpace, pc string, inst *op.I
162163 callPCVal , _ := kv .Get (frameRoot + "/.callpc" )
163164 callPC := callPCVal .Str ()
164165
165- // 将所有返回值写入父帧的对应写槽(.ret0, .ret1, ...)
166+ // 将被调方输出写入父帧的写槽。
167+ // 读写码语义:写槽路径直接从调用指令 [callPC addr0, i+1] 读取——
168+ // callPC = /vthread/42/.fn/[3,0] → 第 i 个写槽在 /vthread/42/.fn/[3, i+1]。
169+ // 父帧在子帧执行期间保持挂起,父帧 .fn 链接不变,路径可靠解析。
166170 if callPC != "" {
167171 parentFrameRoot := keytree .FrameRoot (callPC )
168172 for i , read := range inst .Reads {
169- retKey := fmt . Sprintf ( "%s/.ret%d" , frameRoot , i )
170- retTargetVal , _ := kv .Get (retKey )
171- retTarget := retTargetVal .Str ()
172- if strings .HasPrefix (retTarget , "./" ) {
173+ wSlotPath := op . WriteSlotPC ( callPC , i )
174+ wTargetVal , _ := kv .Get (wSlotPath )
175+ wTarget := wTargetVal .Str ()
176+ if strings .HasPrefix (wTarget , "./" ) {
173177 v , _ := kv .Get (frameRoot + "/" + read [2 :])
174- kv .Set (parentFrameRoot + "/" + retTarget [2 :], v )
178+ kv .Set (parentFrameRoot + "/" + wTarget [2 :], v )
175179 }
176180 }
177181 }
178182
179- // 清理帧:先 Unlink 代码区,再 DelTree 帧根(params / .ret0 / . callpc / .rootfunc)
183+ // 清理帧:先 Unlink 代码区,再 DelTree 帧根(params / .callpc / .rootfunc)
180184 kv .Unlink (keytree .FnCode (frameRoot ))
181185 kv .DelTree (frameRoot )
182186
@@ -205,7 +209,7 @@ func RegisterBlocks(kv kvspace.KVSpace, pkg, parent string, body []ast.Stmt) {
205209// 顶层帧的特征:frameRoot == vthreadRoot → HandleReturn 识别为顶层 return → SetDone。
206210//
207211// args 为按序传入的参数值(对应 funcSig.ParamNames()),可为空。
208- // 成功返回第一条指令的绝对 PC(vthreadRoot/_fn /[0,0]);失败返回 ""。
212+ // 成功返回第一条指令的绝对 PC(vthreadRoot/.fn /[0,0]);失败返回 ""。
209213func Bootstrap (ctx context.Context , kv kvspace.KVSpace , vtid , funcName string , args []string ) string {
210214 pkgVal , err := kv .Get (keytree .FuncIdx (funcName ))
211215 pkg := pkgVal .Str ()
0 commit comments