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); }
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); }
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); }
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); }