@@ -1131,6 +1131,13 @@ data SimplImpl ps_in ps_out where
1131
1131
(1 <= w , KnownNat w ) => ExprVar (LLVMPointerType w ) -> LLVMBlockPerm w ->
1132
1132
SimplImpl (RNil :> LLVMPointerType w ) (RNil :> LLVMPointerType w )
1133
1133
1134
+ -- | Eliminate a block of shape @falsesh@ to @false@
1135
+ --
1136
+ -- > x:memblock(..., falsesh) -o x:false
1137
+ SImpl_ElimLLVMBlockFalse ::
1138
+ (1 <= w , KnownNat w ) => ExprVar (LLVMPointerType w ) -> LLVMBlockPerm w ->
1139
+ SimplImpl (RNil :> LLVMPointerType w ) (RNil :> LLVMPointerType w )
1140
+
1134
1141
-- | Fold a named permission (other than an opaque permission):
1135
1142
--
1136
1143
-- > x:(unfold P args) -o x:P<args>
@@ -1278,6 +1285,12 @@ data PermImpl1 ps_in ps_outs where
1278
1285
Binding tp (ValuePerm a ) ->
1279
1286
PermImpl1 (ps :> a ) (RNil :> '(RNil :> tp , ps :> a ))
1280
1287
1288
+ -- | Eliminate a @false@ permission on the top of the stack, which is a
1289
+ -- contradiction and so has no output disjuncts
1290
+ --
1291
+ -- > ps * x:false -o .
1292
+ Impl1_ElimFalse :: ExprVar a -> PermImpl1 (ps :> a ) RNil
1293
+
1281
1294
-- | Apply a 'SimplImpl'
1282
1295
Impl1_Simpl :: SimplImpl ps_in ps_out -> Proxy ps ->
1283
1296
PermImpl1 (ps :++: ps_in ) (RNil :> '(RNil , ps :++: ps_out ))
@@ -1622,6 +1635,7 @@ permImplSucceeds (PermImpl_Step (Impl1_ElimOr _ _ _)
1622
1635
permImplSucceeds (PermImpl_Step (Impl1_ElimExists _ _)
1623
1636
(MbPermImpls_Cons _ _ mb_impl)) =
1624
1637
mbLift $ fmap permImplSucceeds mb_impl
1638
+ permImplSucceeds (PermImpl_Step (Impl1_ElimFalse _) _) = 2
1625
1639
permImplSucceeds (PermImpl_Step (Impl1_Simpl _ _)
1626
1640
(MbPermImpls_Cons _ _ mb_impl)) =
1627
1641
mbLift $ fmap permImplSucceeds mb_impl
@@ -1949,6 +1963,8 @@ simplImplIn (SImpl_IntroLLVMBlockEx x bp) =
1949
1963
error " simplImplIn: SImpl_IntroLLVMBlockEx: non-existential shape"
1950
1964
simplImplIn (SImpl_ElimLLVMBlockEx x bp) =
1951
1965
distPerms1 x (ValPerm_LLVMBlock bp)
1966
+ simplImplIn (SImpl_ElimLLVMBlockFalse x bp) =
1967
+ distPerms1 x (ValPerm_LLVMBlock bp)
1952
1968
simplImplIn (SImpl_FoldNamed x np args off) =
1953
1969
distPerms1 x (unfoldPerm np args off)
1954
1970
simplImplIn (SImpl_UnfoldNamed x np args off) =
@@ -2295,6 +2311,11 @@ simplImplOut (SImpl_ElimLLVMBlockEx x bp) =
2295
2311
ValPerm_LLVMBlock (bp { llvmBlockShape = sh }))
2296
2312
_ ->
2297
2313
error " simplImplOut: SImpl_ElimLLVMBlockEx: non-existential shape"
2314
+ simplImplOut (SImpl_ElimLLVMBlockFalse x bp) =
2315
+ case llvmBlockShape bp of
2316
+ PExpr_FalseShape ->
2317
+ distPerms1 x ValPerm_False
2318
+ _ -> error " simplImplOut: SImpl_ElimLLVMBlockFalse: non-false shape"
2298
2319
simplImplOut (SImpl_FoldNamed x np args off) =
2299
2320
distPerms1 x (ValPerm_Named (namedPermName np) args off)
2300
2321
simplImplOut (SImpl_UnfoldNamed x np args off) =
@@ -2396,6 +2417,11 @@ applyImpl1 _ (Impl1_ElimExists x p_body) ps =
2396
2417
mbPermSets1 (fmap (\ p -> set (topDistPerm x) p ps) p_body)
2397
2418
else
2398
2419
error " applyImpl1: Impl1_ElimExists: unexpected permission"
2420
+ applyImpl1 _ (Impl1_ElimFalse x) ps =
2421
+ if ps ^. topDistPerm x == ValPerm_False then
2422
+ MbPermSets_Nil
2423
+ else
2424
+ error " applyImpl1: Impl1_ElimFalse: unexpected permission"
2399
2425
applyImpl1 pp_info (Impl1_Simpl simpl prx) ps =
2400
2426
mbPermSets1 $ emptyMb $ applySimplImpl pp_info prx simpl ps
2401
2427
applyImpl1 _ (Impl1_LetBind tp e) ps =
@@ -2776,6 +2802,8 @@ instance SubstVar PermVarSubst m =>
2776
2802
SImpl_IntroLLVMBlockEx <$> genSubst s x <*> genSubst s bp
2777
2803
[nuMP | SImpl_ElimLLVMBlockEx x bp |] ->
2778
2804
SImpl_ElimLLVMBlockEx <$> genSubst s x <*> genSubst s bp
2805
+ [nuMP | SImpl_ElimLLVMBlockFalse x bp |] ->
2806
+ SImpl_ElimLLVMBlockFalse <$> genSubst s x <*> genSubst s bp
2779
2807
[nuMP | SImpl_FoldNamed x np args off |] ->
2780
2808
SImpl_FoldNamed <$> genSubst s x <*> genSubst s np <*> genSubst s args
2781
2809
<*> genSubst s off
@@ -2822,6 +2850,8 @@ instance SubstVar PermVarSubst m =>
2822
2850
Impl1_ElimOr <$> genSubst s x <*> genSubst s p1 <*> genSubst s p2
2823
2851
[nuMP | Impl1_ElimExists x p_body |] ->
2824
2852
Impl1_ElimExists <$> genSubst s x <*> genSubst s p_body
2853
+ [nuMP | Impl1_ElimFalse x |] ->
2854
+ Impl1_ElimFalse <$> genSubst s x
2825
2855
[nuMP | Impl1_Simpl simpl prx |] ->
2826
2856
Impl1_Simpl <$> genSubst s simpl <*> return (mbLift prx)
2827
2857
[nuMP | Impl1_LetBind tp e |] ->
@@ -3405,6 +3435,12 @@ implElimExistsM x p =
3405
3435
implApplyImpl1 (Impl1_ElimExists x p)
3406
3436
(MNil :>: Impl1Cont (const $ pure () ))
3407
3437
3438
+ -- | Eliminate a false permission in the current permission set
3439
+ implElimFalseM :: NuMatchingAny1 r => ExprVar a ->
3440
+ ImplM vars s r ps_any (ps :> a ) ()
3441
+ implElimFalseM x =
3442
+ implApplyImpl1 (Impl1_ElimFalse x) MNil
3443
+
3408
3444
-- | Apply a simple implication rule to the top permissions on the stack
3409
3445
implSimplM :: HasCallStack => NuMatchingAny1 r => Proxy ps ->
3410
3446
SimplImpl ps_in ps_out ->
@@ -4704,6 +4740,10 @@ implElimLLVMBlock x bp@(LLVMBlockPerm { llvmBlockShape =
4704
4740
PExpr_ExShape _mb_sh }) =
4705
4741
implSimplM Proxy (SImpl_ElimLLVMBlockEx x bp)
4706
4742
4743
+ implElimLLVMBlock x bp@ (LLVMBlockPerm { llvmBlockShape =
4744
+ PExpr_FalseShape }) =
4745
+ implSimplM Proxy (SImpl_ElimLLVMBlockFalse x bp)
4746
+
4707
4747
-- If none of the above cases matched, we cannot eliminate, so fail
4708
4748
implElimLLVMBlock _ bp =
4709
4749
implTraceM (\ i -> pretty " Could not eliminate permission" <+>
@@ -4967,6 +5007,7 @@ recombinePermExpl x x_p p =
4967
5007
recombinePerm' :: NuMatchingAny1 r => ExprVar a -> ValuePerm a -> ValuePerm a ->
4968
5008
ImplM vars s r as (as :> a ) ()
4969
5009
recombinePerm' x _ p@ ValPerm_True = implDropM x p
5010
+ recombinePerm' x _ ValPerm_False = implElimFalseM x
4970
5011
recombinePerm' x _ p@ (ValPerm_Eq (PExpr_Var y)) | y == x = implDropM x p
4971
5012
recombinePerm' x ValPerm_True (ValPerm_Eq e) =
4972
5013
simplEqPerm x e >>>= \ e' -> implPopM x (ValPerm_Eq e')
@@ -5090,6 +5131,12 @@ recombinePermConj x x_ps (Perm_LLVMBlock bp)
5090
5131
getTopDistPerm x >>>= \ p ->
5091
5132
recombinePerm x p
5092
5133
5134
+ -- If p is a memblock permission on the false shape, eliminate the block to
5135
+ -- a false permission (and eliminate the false permission itself)
5136
+ recombinePermConj x _ (Perm_LLVMBlock bp)
5137
+ | PExpr_FalseShape <- llvmBlockShape bp
5138
+ = implElimLLVMBlock x bp >>> implElimFalseM x
5139
+
5093
5140
-- Default case: insert p at the end of the x_ps
5094
5141
recombinePermConj x x_ps p =
5095
5142
implPushM x (ValPerm_Conj x_ps) >>>
0 commit comments