예제 #1
0
        private List <AccessRecord> GetArrayAccesses(AssignCmd assign)
        {
            List <AccessRecord> accesses = new List <AccessRecord>();
            ReadCollector       rc       = new ReadCollector(this.verifier.KernelArrayInfo);
            WriteCollector      wc       = new WriteCollector(this.verifier.KernelArrayInfo);

            foreach (var rhs in assign.Rhss)
            {
                rc.Visit(rhs);
            }
            foreach (AccessRecord ar in rc.nonPrivateAccesses.Union(rc.privateAccesses))
            {
                accesses.Add(ar);
            }

            foreach (var lhs in assign.Lhss)
            {
                wc.Visit(lhs);
            }
            if (wc.FoundNonPrivateWrite() || wc.FoundPrivateWrite())
            {
                accesses.Add(wc.GetAccess());
            }

            return(accesses);
        }
예제 #2
0
        private List <Cmd> AddNoAccessAssumes(List <Cmd> cs)
        {
            var result = new List <Cmd>();

            foreach (Cmd c in cs)
            {
                result.Add(c);
                if (c is AssignCmd)
                {
                    AssignCmd assign = c as AssignCmd;

                    ReadCollector rc = new ReadCollector(stateToCheck);
                    foreach (var rhs in assign.Rhss)
                    {
                        rc.Visit(rhs);
                    }
                    if (rc.NonPrivateAccesses.Count > 0)
                    {
                        foreach (AccessRecord ar in rc.NonPrivateAccesses)
                        {
                            AddNoAccessAssumes(result, ar);
                        }
                    }

                    foreach (var lhsRhs in assign.Lhss.Zip(assign.Rhss))
                    {
                        WriteCollector wc = new WriteCollector(stateToCheck);
                        wc.Visit(lhsRhs.Item1);
                        if (wc.FoundNonPrivateWrite())
                        {
                            AddNoAccessAssumes(result, wc.GetAccess());
                        }
                    }
                }
            }

            return(result);
        }
예제 #3
0
        private static bool AccessesGlobalArrayOrUnsafeBarrier(Cmd c, GPUVerifier verifier)
        {
            var stateToCheck = verifier.KernelArrayInfo;

            if (c is CallCmd)
            {
                // Speculate invariants if we see atomics, async_work_group_copy, and
                // wait_group_events, which relate to race checking
                CallCmd call = c as CallCmd;
                if (QKeyValue.FindBoolAttribute(call.Attributes, "atomic"))
                {
                    return(true);
                }

                if (QKeyValue.FindBoolAttribute(call.Attributes, "async_work_group_copy"))
                {
                    return(true);
                }

                if (QKeyValue.FindBoolAttribute(call.Attributes, "wait_group_events"))
                {
                    return(true);
                }

                // Speculate invariants if we see an unsafe barrier,
                // which we need to check for barrier divergence
                if (GPUVerifier.IsBarrier(call.Proc) &&
                    !QKeyValue.FindBoolAttribute(call.Proc.Attributes, "safe_barrier"))
                {
                    return(true);
                }

                // Speculate invariants if we see a call to a procedure that has a non-local array
                // or constant array in its modset
                List <Variable> vars = new List <Variable>();
                call.AddAssignedVariables(vars);
                foreach (Variable v in vars)
                {
                    if (stateToCheck.GetGlobalAndGroupSharedArrays(false).Contains(v))
                    {
                        return(true);
                    }

                    if (stateToCheck.GetConstantArrays().Contains(v))
                    {
                        return(true);
                    }
                }
            }

            // Speculate invariants if race instrumentation or a constant write
            // instrumentation will occur
            if (c is AssignCmd)
            {
                AssignCmd assign = c as AssignCmd;

                ReadCollector rc = new ReadCollector(stateToCheck);
                foreach (var rhs in assign.Rhss)
                {
                    rc.Visit(rhs);
                }
                foreach (var access in rc.NonPrivateAccesses)
                {
                    // Ignore disabled arrays
                    if (stateToCheck.GetGlobalAndGroupSharedArrays(false).Contains(access.V))
                    {
                        // Ignore read-only arrays (whether or not they are disabled)
                        if (!stateToCheck.GetReadOnlyGlobalAndGroupSharedArrays(true).Contains(access.V))
                        {
                            return(true);
                        }
                    }
                }

                foreach (var lhsRhs in assign.Lhss.Zip(assign.Rhss))
                {
                    WriteCollector wc = new WriteCollector(stateToCheck);
                    wc.Visit(lhsRhs.Item1);
                    if (wc.FoundNonPrivateWrite())
                    {
                        // Ignore disabled arrays
                        if (stateToCheck.GetGlobalAndGroupSharedArrays(false).Contains(wc.GetAccess().V))
                        {
                            return(true);
                        }
                    }
                }

                foreach (var lhsRhs in assign.Lhss.Zip(assign.Rhss))
                {
                    ConstantWriteCollector cwc = new ConstantWriteCollector(stateToCheck);
                    cwc.Visit(lhsRhs.Item1);
                    if (cwc.FoundWrite())
                    {
                        // Ignore disabled arrays
                        if (stateToCheck.GetGlobalAndGroupSharedArrays(false).Contains(cwc.GetAccess().V))
                        {
                            return(true);
                        }
                    }
                }
            }

            // Speculate invariants if we see an assert that is not a sourceloc or
            // block_sourceloc assert; such asserts is likely user supplied.
            if (c is AssertCmd)
            {
                AssertCmd assertion = c as AssertCmd;
                if (!QKeyValue.FindBoolAttribute(assertion.Attributes, "sourceloc") &&
                    !QKeyValue.FindBoolAttribute(assertion.Attributes, "block_sourceloc") &&
                    !assertion.Expr.Equals(Expr.True))
                {
                    return(true);
                }
            }

            // Speculate invariants if we see an assume that is not a partition; such
            // an assume is likely user supplied.
            if (c is AssumeCmd)
            {
                AssumeCmd assumption = c as AssumeCmd;
                if (!QKeyValue.FindBoolAttribute(assumption.Attributes, "partition"))
                {
                    return(true);
                }
            }

            return(false);
        }
예제 #4
0
        private Block Abstract(Block b)
        {
            var newCmds = new List <Cmd>();

            foreach (Cmd c in b.Cmds)
            {
                if (c is CallCmd)
                {
                    var call = c as CallCmd;

                    if (QKeyValue.FindBoolAttribute(call.Attributes, "atomic"))
                    {
                        // Discard the call
                        Debug.Assert(call.Ins.Count >= 1);
                        var ie = call.Ins[0] as IdentifierExpr;
                        Debug.Assert(ie != null);
                        Debug.Assert(verifier.ArrayModelledAdversarially(ie.Decl));
                        continue;
                    }

                    for (int i = 0; i < call.Ins.Count; i++)
                    {
                        ReadCollector rc = new ReadCollector(verifier.KernelArrayInfo);
                        rc.Visit(call.Ins[i]);
                        bool foundAdversarial = false;
                        foreach (AccessRecord ar in rc.NonPrivateAccesses)
                        {
                            if (verifier.ArrayModelledAdversarially(ar.V))
                            {
                                foundAdversarial = true;
                                break;
                            }
                        }

                        if (foundAdversarial)
                        {
                            LocalVariable lv = new LocalVariable(
                                Token.NoToken,
                                new TypedIdent(Token.NoToken, "_abstracted_call_arg_" + abstractedCallArgCounter, call.Ins[i].Type));
                            abstractedCallArgCounter++;
                            newLocalVars.Add(lv);
                            newCmds.Add(new HavocCmd(
                                            Token.NoToken,
                                            new List <IdentifierExpr>(new IdentifierExpr[] { new IdentifierExpr(Token.NoToken, lv) })));
                            call.Ins[i] = new IdentifierExpr(Token.NoToken, lv);
                        }
                    }
                }

                if (c is AssignCmd)
                {
                    AssignCmd assign = c as AssignCmd;

                    var lhss = new List <AssignLhs>();
                    var rhss = new List <Expr>();

                    foreach (var lhsRhs in assign.Lhss.Zip(assign.Rhss))
                    {
                        AssignLhs     lhs = lhsRhs.Item1;
                        Expr          rhs = lhsRhs.Item2;
                        ReadCollector rc  = new ReadCollector(verifier.KernelArrayInfo);
                        rc.Visit(rhs);

                        bool foundAdversarial = false;
                        foreach (AccessRecord ar in rc.NonPrivateAccesses)
                        {
                            if (verifier.ArrayModelledAdversarially(ar.V))
                            {
                                foundAdversarial = true;
                                break;
                            }
                        }

                        if (foundAdversarial)
                        {
                            Debug.Assert(lhs is SimpleAssignLhs);
                            newCmds.Add(new HavocCmd(c.tok, new List <IdentifierExpr>(new IdentifierExpr[] { (lhs as SimpleAssignLhs).AssignedVariable })));
                            continue;
                        }

                        WriteCollector wc = new WriteCollector(verifier.KernelArrayInfo);
                        wc.Visit(lhs);
                        if (wc.FoundNonPrivateWrite())
                        {
                            if (verifier.ArrayModelledAdversarially(wc.GetAccess().V))
                            {
                                continue; // Just remove the write
                            }
                        }

                        lhss.Add(lhs);
                        rhss.Add(rhs);
                    }

                    if (lhss.Count != 0)
                    {
                        newCmds.Add(new AssignCmd(assign.tok, lhss, rhss));
                    }

                    continue;
                }

                newCmds.Add(c);
            }

            b.Cmds = newCmds;
            return(b);
        }