Skip to content

Commit 761dbc0

Browse files
committed
fix(rt): handle typed closure setup and fun-type zero-size decode
1 parent 6d5eaba commit 761dbc0

3 files changed

Lines changed: 80 additions & 7 deletions

File tree

kmir/src/kmir/kdist/mir-semantics/kmir.md

Lines changed: 74 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -530,7 +530,9 @@ Therefore a heuristics is used here:
530530
_SPAN
531531
)
532532
=>
533-
#setTupleArgs(2, getValue(LOCALS, TUPLE)) ~> #execBlock(FIRST)
533+
#setLocalValue(place(local(1), .ProjectionElems), #incrementRef(getValue(LOCALS, CLOSURE)))
534+
~> #setTupleArgs(2, getValue(LOCALS, TUPLE))
535+
~> #execBlock(FIRST)
534536
// arguments are tuple components, stored as _2 .. _n
535537
...
536538
</k>
@@ -547,7 +549,7 @@ Therefore a heuristics is used here:
547549
andBool 0 <=Int TUPLE andBool TUPLE <Int size(LOCALS)
548550
andBool isTypedValue(LOCALS[TUPLE])
549551
andBool isTupleType(lookupTy(tyOfLocal({LOCALS[TUPLE]}:>TypedLocal)))
550-
andBool isTypedLocal(LOCALS[CLOSURE])
552+
andBool isTypedValue(LOCALS[CLOSURE])
551553
andBool typeInfoVoidType ==K lookupTy(tyOfLocal({LOCALS[CLOSURE]}:>TypedLocal))
552554
// either the closure ref type is missing from type table
553555
[priority(40), preserves-definedness]
@@ -560,7 +562,9 @@ Therefore a heuristics is used here:
560562
_SPAN
561563
)
562564
=>
563-
#setTupleArgs(2, getValue(LOCALS, TUPLE)) ~> #execBlock(FIRST)
565+
#setLocalValue(place(local(1), .ProjectionElems), #incrementRef(getValue(LOCALS, CLOSURE)))
566+
~> #setTupleArgs(2, getValue(LOCALS, TUPLE))
567+
~> #execBlock(FIRST)
564568
// arguments are tuple components, stored as _2 .. _n
565569
...
566570
</k>
@@ -577,7 +581,7 @@ Therefore a heuristics is used here:
577581
andBool 0 <=Int TUPLE andBool TUPLE <Int size(LOCALS)
578582
andBool isTypedValue(LOCALS[TUPLE])
579583
andBool isTupleType(lookupTy(tyOfLocal({LOCALS[TUPLE]}:>TypedLocal)))
580-
andBool isTypedLocal(LOCALS[CLOSURE])
584+
andBool isTypedValue(LOCALS[CLOSURE])
581585
// or the closure ref type pointee is missing from the type table
582586
andBool isRefType(lookupTy(tyOfLocal({LOCALS[CLOSURE]}:>TypedLocal)))
583587
andBool isTy(pointeeTy(lookupTy(tyOfLocal({LOCALS[CLOSURE]}:>TypedLocal))))
@@ -587,6 +591,72 @@ Therefore a heuristics is used here:
587591
)
588592
[priority(45), preserves-definedness]
589593
594+
// Closure-call setup for typed closure environments.
595+
// When closure pointee type is known (`typeInfoFunType`), unpack tuple args into `_2 .. _n`.
596+
rule [setupCalleeClosure3]: <k> #setUpCalleeData(
597+
monoItemFn(_, _, someBody(body((FIRST:BasicBlock _) #as BLOCKS, NEWLOCALS, _, _, _, _))),
598+
operandMove(place(local(CLOSURE:Int), .ProjectionElems))
599+
operandMove(place(local(TUPLE), .ProjectionElems))
600+
.Operands,
601+
_SPAN
602+
)
603+
=>
604+
#setLocalValue(place(local(1), .ProjectionElems), #incrementRef(getValue(LOCALS, CLOSURE)))
605+
~> #setTupleArgs(2, getValue(LOCALS, TUPLE))
606+
~> #execBlock(FIRST)
607+
// arguments are tuple components, stored as _2 .. _n
608+
...
609+
</k>
610+
<currentFrame>
611+
<currentBody> _ => toKList(BLOCKS) </currentBody>
612+
<locals> LOCALS => #reserveFor(NEWLOCALS) </locals>
613+
<stack>
614+
(ListItem(CALLERFRAME => #updateStackLocal(#updateStackLocal(CALLERFRAME, TUPLE, Moved), CLOSURE, Moved)))
615+
_:List
616+
</stack>
617+
...
618+
</currentFrame>
619+
requires 0 <=Int CLOSURE andBool CLOSURE <Int size(LOCALS)
620+
andBool 0 <=Int TUPLE andBool TUPLE <Int size(LOCALS)
621+
andBool isTypedValue(LOCALS[TUPLE])
622+
andBool isTupleType(lookupTy(tyOfLocal({LOCALS[TUPLE]}:>TypedLocal)))
623+
andBool isTypedValue(LOCALS[CLOSURE])
624+
andBool isRefType(lookupTy(tyOfLocal({LOCALS[CLOSURE]}:>TypedLocal)))
625+
andBool isFunType(#lookupMaybeTy(pointeeTy(lookupTy(tyOfLocal({LOCALS[CLOSURE]}:>TypedLocal)))))
626+
[priority(46), preserves-definedness]
627+
628+
// Stable MIR may expose closures as direct `typeInfoFunType` values instead of references.
629+
// In that case we still need to unpack the tuple argument payload into `_2 .. _n`.
630+
rule [setupCalleeClosure4]: <k> #setUpCalleeData(
631+
monoItemFn(_, _, someBody(body((FIRST:BasicBlock _) #as BLOCKS, NEWLOCALS, _, _, _, _))),
632+
operandMove(place(local(CLOSURE:Int), .ProjectionElems))
633+
operandMove(place(local(TUPLE), .ProjectionElems))
634+
.Operands,
635+
_SPAN
636+
)
637+
=>
638+
#setLocalValue(place(local(1), .ProjectionElems), getValue(LOCALS, CLOSURE))
639+
~> #setTupleArgs(2, getValue(LOCALS, TUPLE))
640+
~> #execBlock(FIRST)
641+
...
642+
</k>
643+
<currentFrame>
644+
<currentBody> _ => toKList(BLOCKS) </currentBody>
645+
<locals> LOCALS => #reserveFor(NEWLOCALS) </locals>
646+
<stack>
647+
(ListItem(CALLERFRAME => #updateStackLocal(#updateStackLocal(CALLERFRAME, TUPLE, Moved), CLOSURE, Moved)))
648+
_:List
649+
</stack>
650+
...
651+
</currentFrame>
652+
requires 0 <=Int CLOSURE andBool CLOSURE <Int size(LOCALS)
653+
andBool 0 <=Int TUPLE andBool TUPLE <Int size(LOCALS)
654+
andBool isTypedValue(LOCALS[TUPLE])
655+
andBool isTupleType(lookupTy(tyOfLocal({LOCALS[TUPLE]}:>TypedLocal)))
656+
andBool isTypedValue(LOCALS[CLOSURE])
657+
andBool isFunType(lookupTy(tyOfLocal({LOCALS[CLOSURE]}:>TypedLocal)))
658+
[priority(47), preserves-definedness]
659+
590660
syntax Bool ::= isTupleType ( TypeInfo ) [function, total]
591661
| isRefType ( TypeInfo ) [function, total]
592662
| isFunType ( TypeInfo ) [function, total]

kmir/src/kmir/kdist/mir-semantics/rt/data.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1858,6 +1858,9 @@ Zero-sized types can be decoded trivially into their respective representation.
18581858
// zero-sized array
18591859
rule <k> #decodeConstant(constantKindZeroSized, _TY, typeInfoArrayType(_, _))
18601860
=> Range(.List) ... </k>
1861+
// zero-sized closure/function-like value (opaque fun type in SMIR metadata)
1862+
rule <k> #decodeConstant(constantKindZeroSized, _TY, typeInfoFunType(_))
1863+
=> Aggregate(variantIdx(0), .List) ... </k>
18611864
```
18621865

18631866
Allocated constants of reference type with a single provenance map entry are decoded as references

kmir/src/tests/integration/data/prove-rs/show/iter-eq-copied-take-dereftruncate-fail.repro.expected

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@
33
│ #execTerminator ( terminator ( ... kind: terminatorKindCall ( ... func: operandC
44
│ span: 0
55
6-
│ (1947 steps)
6+
│ (5553 steps)
77
└─ 3 (stuck, leaf)
8-
#traverseProjection ( toLocal ( 1 ) , thunk ( operandCopy ( place ( ... local: l
9-
span: 30
8+
#traverseProjection ( toLocal ( 12 ) , thunk ( #decodeConstant ( constantKindAll
9+
span: 282
1010

1111

1212
┌─ 2 (root, leaf, target, terminal)

0 commit comments

Comments
 (0)