Skip to content

Commit 9ffa29f

Browse files
committed
fix(rt): handle typed closure setup and fun-type zero-size decode
1 parent cf54fdd commit 9ffa29f

3 files changed

Lines changed: 83 additions & 7 deletions

File tree

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

Lines changed: 77 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,20 +581,89 @@ 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))))
584588
andBool lookupTy({pointeeTy(lookupTy(tyOfLocal({LOCALS[CLOSURE]}:>TypedLocal)))}:>Ty) ==K typeInfoVoidType
585589
[priority(45), preserves-definedness]
586590
591+
// Closure-call setup for typed closure environments.
592+
// When closure pointee type is known (`typeInfoFunType`), unpack tuple args into `_2 .. _n`.
593+
rule [setupCalleeClosure3]: <k> #setUpCalleeData(
594+
monoItemFn(_, _, someBody(body((FIRST:BasicBlock _) #as BLOCKS, NEWLOCALS, _, _, _, _))),
595+
operandMove(place(local(CLOSURE:Int), .ProjectionElems))
596+
operandMove(place(local(TUPLE), .ProjectionElems))
597+
.Operands,
598+
_SPAN
599+
)
600+
=>
601+
#setLocalValue(place(local(1), .ProjectionElems), #incrementRef(getValue(LOCALS, CLOSURE)))
602+
~> #setTupleArgs(2, getValue(LOCALS, TUPLE))
603+
~> #execBlock(FIRST)
604+
// arguments are tuple components, stored as _2 .. _n
605+
...
606+
</k>
607+
<currentFrame>
608+
<currentBody> _ => toKList(BLOCKS) </currentBody>
609+
<locals> LOCALS => #reserveFor(NEWLOCALS) </locals>
610+
<stack>
611+
(ListItem(CALLERFRAME => #updateStackLocal(#updateStackLocal(CALLERFRAME, TUPLE, Moved), CLOSURE, Moved)))
612+
_:List
613+
</stack>
614+
...
615+
</currentFrame>
616+
requires 0 <=Int CLOSURE andBool CLOSURE <Int size(LOCALS)
617+
andBool 0 <=Int TUPLE andBool TUPLE <Int size(LOCALS)
618+
andBool isTypedValue(LOCALS[TUPLE])
619+
andBool isTupleType(lookupTy(tyOfLocal({LOCALS[TUPLE]}:>TypedLocal)))
620+
andBool isTypedValue(LOCALS[CLOSURE])
621+
andBool isRefType(lookupTy(tyOfLocal({LOCALS[CLOSURE]}:>TypedLocal)))
622+
andBool isFunType(#lookupMaybeTy(pointeeTy(lookupTy(tyOfLocal({LOCALS[CLOSURE]}:>TypedLocal)))))
623+
[priority(46), preserves-definedness]
624+
625+
// Stable MIR may expose closures as direct `typeInfoFunType` values instead of references.
626+
// In that case we still need to unpack the tuple argument payload into `_2 .. _n`.
627+
rule [setupCalleeClosure4]: <k> #setUpCalleeData(
628+
monoItemFn(_, _, someBody(body((FIRST:BasicBlock _) #as BLOCKS, NEWLOCALS, _, _, _, _))),
629+
operandMove(place(local(CLOSURE:Int), .ProjectionElems))
630+
operandMove(place(local(TUPLE), .ProjectionElems))
631+
.Operands,
632+
_SPAN
633+
)
634+
=>
635+
#setLocalValue(place(local(1), .ProjectionElems), getValue(LOCALS, CLOSURE))
636+
~> #setTupleArgs(2, getValue(LOCALS, TUPLE))
637+
~> #execBlock(FIRST)
638+
...
639+
</k>
640+
<currentFrame>
641+
<currentBody> _ => toKList(BLOCKS) </currentBody>
642+
<locals> LOCALS => #reserveFor(NEWLOCALS) </locals>
643+
<stack>
644+
(ListItem(CALLERFRAME => #updateStackLocal(#updateStackLocal(CALLERFRAME, TUPLE, Moved), CLOSURE, Moved)))
645+
_:List
646+
</stack>
647+
...
648+
</currentFrame>
649+
requires 0 <=Int CLOSURE andBool CLOSURE <Int size(LOCALS)
650+
andBool 0 <=Int TUPLE andBool TUPLE <Int size(LOCALS)
651+
andBool isTypedValue(LOCALS[TUPLE])
652+
andBool isTupleType(lookupTy(tyOfLocal({LOCALS[TUPLE]}:>TypedLocal)))
653+
andBool isTypedValue(LOCALS[CLOSURE])
654+
andBool isFunType(lookupTy(tyOfLocal({LOCALS[CLOSURE]}:>TypedLocal)))
655+
[priority(47), preserves-definedness]
656+
587657
syntax Bool ::= isTupleType ( TypeInfo ) [function, total]
588658
| isRefType ( TypeInfo ) [function, total]
659+
| isFunType ( TypeInfo ) [function, total]
589660
// -------------------------------------------------------
590661
rule isTupleType(typeInfoTupleType(_, _)) => true
591662
rule isTupleType( _ ) => false [owise]
592663
rule isRefType(typeInfoRefType(_)) => true
593664
rule isRefType( _ ) => false [owise]
665+
rule isFunType(typeInfoFunType(_)) => true
666+
rule isFunType( _ ) => false [owise]
594667
595668
syntax KItem ::= #setTupleArgs ( Int , Value )
596669
| #setTupleArgs ( Int , List )

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-
│ (1060 steps)
6+
│ (1062 steps)
77
└─ 3 (stuck, leaf)
8-
ListItem ( thunk ( operandConstant ( constOperand ( ... span: span ( 137 ) , use
9-
span: 137
8+
ListItem ( thunk ( #decodeConstant ( constantKindZeroSized , ty ( 88 ) , typeInf
9+
span: 273
1010

1111

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

0 commit comments

Comments
 (0)