summaryrefslogtreecommitdiff
path: root/Source/GPUVerify/EnsureDisabledThreadHasNoEffectInstrumenter.cs
blob: 32dde50755556383e47de49d8294c82a02fd3a52 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Boogie;
using System.Diagnostics;

namespace GPUVerify
{
    class EnsureDisabledThreadHasNoEffectInstrumenter
    {

        private GPUVerifier verifier;
        private Implementation Impl;

        public EnsureDisabledThreadHasNoEffectInstrumenter(GPUVerifier verifier, Implementation Impl)
        {
            this.verifier = verifier;
            this.Impl = Impl;
        }

        internal void instrument()
        {

            if (verifier.uniformityAnalyser.IsUniform(Impl.Name))
            {
                return;
            }

            foreach (IdentifierExpr iex in Impl.Proc.Modifies)
            {
                // For some reason, this does not work well with maps
                if (iex.Decl.TypedIdent.Type is MapType)
                {
                    continue;
                }

                Expr NoEffectExpr = Expr.Imp(
                        Expr.Not(new IdentifierExpr(iex.tok, new LocalVariable(iex.tok, new TypedIdent(iex.tok, "_P$" + 
                            GPUVerifier.GetThreadSuffix(iex.Name), Microsoft.Boogie.Type.Bool)))),
                        Expr.Eq(iex, new OldExpr(iex.tok, iex))
                    );

                Impl.Proc.Ensures.Add(new Ensures(false,
                    NoEffectExpr
                ));

                GPUVerifier.AddInvariantToAllLoops(NoEffectExpr, Impl.StructuredStmts);

            }

            AddEnablednessInvariantToAllLoops(Impl.StructuredStmts);
        }

        private void AddEnablednessInvariantToAllLoops(StmtList stmtList)
        {
            foreach (BigBlock bb in stmtList.BigBlocks)
            {
                AddEnablednessInvariantToAllLoops(bb);
            }
        }

        private void AddEnablednessInvariantToAllLoops(BigBlock bb)
        {
            if (bb.ec is WhileCmd)
            {
                WhileCmd wc = bb.ec as WhileCmd;
                Debug.Assert(wc.Guard is NAryExpr);
                Debug.Assert((wc.Guard as NAryExpr).Fun is BinaryOperator);
                Debug.Assert((wc.Guard as NAryExpr).Args[0] is IdentifierExpr);
                string LoopPredicate = ((wc.Guard as NAryExpr).Args[0] as IdentifierExpr).Name;
                LoopPredicate = GPUVerifier.StripThreadIdentifier(LoopPredicate);

                wc.Invariants.Add(
                    new AssertCmd(wc.tok,
                        Expr.Imp(
                            Expr.Not(new IdentifierExpr(wc.tok, new LocalVariable(wc.tok, new TypedIdent(wc.tok, "_P$1", Microsoft.Boogie.Type.Bool)))),
                            Expr.Not(new IdentifierExpr(wc.tok, new LocalVariable(wc.tok, new TypedIdent(wc.tok, LoopPredicate + "$1", Microsoft.Boogie.Type.Bool))))
                    )));

                wc.Invariants.Add(
                    new AssertCmd(wc.tok,
                        Expr.Imp(
                            Expr.Not(new IdentifierExpr(wc.tok, new LocalVariable(wc.tok, new TypedIdent(wc.tok, "_P$2", Microsoft.Boogie.Type.Bool)))),
                            Expr.Not(new IdentifierExpr(wc.tok, new LocalVariable(wc.tok, new TypedIdent(wc.tok, LoopPredicate + "$2", Microsoft.Boogie.Type.Bool))))
                    )));

                AddEnablednessInvariantToAllLoops(wc.Body);
            }

        }
    
    }
}