public virtual AssignLhs VisitSimpleAssignLhs(SimpleAssignLhs node) { Contract.Requires(node != null); Contract.Ensures(Contract.Result <AssignLhs>() != null); node.AssignedVariable = (IdentifierExpr)this.VisitIdentifierExpr(node.AssignedVariable); return(node); }
public override AssignLhs VisitSimpleAssignLhs(SimpleAssignLhs node) { var e = VisitIdentifierExpr(node.AssignedVariable); if (!(e is IdentifierExpr)) { throw new InvalidExpressionException("lhs must be an identifier, also after substitution --> malformed property??"); } return(new SimpleAssignLhs(node.tok, (IdentifierExpr)e)); }
public override AssignLhs VisitSimpleAssignLhs(SimpleAssignLhs node) { if (boogieVarTranslation.VarTranslation.TryTranslateVariableId(node.AssignedVariable.Decl, out var varId, out _)) { ReturnResult(varId); return(node); } throw new ProofGenUnexpectedStateException(GetType(), "Cannot extract id from variable " + node.AssignedVariable.Name); }
void AddAssignment(IRegion region, VarDefMap multiDefMap, SimpleAssignLhs lhs, Expr rhs) { if (lhs == null) { return; } var variable = lhs.DeepAssignedVariable; if (!multiDefMap.ContainsKey(variable)) { multiDefMap[variable] = new List <Tuple <IRegion, Expr> >(); } multiDefMap[variable].Add(new Tuple <IRegion, Expr>(region, rhs)); }
public override Cmd VisitAssignCmd(AssignCmd node) { HashSet <Variable> rhsVars = new HashSet <Variable>(); for (int i = 0; i < node.Lhss.Count; i++) { AssignLhs lhs = node.Lhss[i]; Variable lhsVar = lhs.DeepAssignedVariable; string domainName = FindDomainName(lhsVar); if (domainName == null) { continue; } SimpleAssignLhs salhs = lhs as SimpleAssignLhs; if (salhs == null) { Error(node, string.Format("Only simple assignment allowed on linear variable {0}", lhsVar.Name)); continue; } IdentifierExpr rhs = node.Rhss[i] as IdentifierExpr; if (rhs == null) { Error(node, string.Format("Only variable can be assigned to linear variable {0}", lhsVar.Name)); continue; } string rhsDomainName = FindDomainName(rhs.Decl); if (rhsDomainName == null) { Error(node, string.Format("Only linear variable can be assigned to linear variable {0}", lhsVar.Name)); continue; } if (domainName != rhsDomainName) { Error(node, string.Format("Linear variable of domain {0} cannot be assigned to linear variable of domain {1}", rhsDomainName, domainName)); continue; } if (rhsVars.Contains(rhs.Decl)) { Error(node, string.Format("Linear variable {0} can occur only once in the right-hand-side of an assignment", rhs.Decl.Name)); continue; } rhsVars.Add(rhs.Decl); } return(base.VisitAssignCmd(node)); }
/// <summary> /// Apply the assignments in the form of assign statements. /// </summary> /// <param name="implementation">The implementation.</param> /// <param name="assignments">The assignments provided by the solver.</param> private void ApplyAssignments(Implementation implementation, Dictionary <string, bool> assignments) { foreach (KeyValuePair <string, bool> assignment in assignments) { IdentifierExpr expr = new IdentifierExpr(Token.NoToken, assignment.Key, Type.Bool); Expr literal = new LiteralExpr(Token.NoToken, assignment.Value); SimpleAssignLhs assign = new SimpleAssignLhs(Token.NoToken, expr); AssignCmd command = new AssignCmd(Token.NoToken, new List <AssignLhs> { assign }, new List <Expr> { literal }); implementation.Blocks[0].Cmds.Insert(0, command); } }
// Return the variable that is being assigned to in the LHS of an assignment. // id := ... then id // m[...] := ... then m private static IdentifierExpr getAssignedVariable(AssignLhs lhs) { if (lhs is SimpleAssignLhs) { SimpleAssignLhs sl = (SimpleAssignLhs)lhs; return(sl.AssignedVariable); } else if (lhs is MapAssignLhs) { MapAssignLhs ml = (MapAssignLhs)lhs; return(getAssignedVariable(ml.Map)); } else { lhs.Emit(new TokenTextWriter(Console.Out)); throw new InternalError("Unknown type of AssignLhs"); } }
//TODO: review conditions for multiple assignments to the same array, e.g., M[i], M[j] := x, y; // This transformation will not work in that case(maybe)? public override Block VisitBlock(Block node) { foreach (Cmd cmd in node.cmds) { if (cmd is AssignCmd) { var assign = cmd as AssignCmd; List <AssignLhs> newLhs = new List <AssignLhs>(); List <Expr> newRhs = new List <Expr>(); for (int i = 0; i < assign.Lhss.Count; i++) { var lhsi = assign.Lhss[i].AsExpr as NAryExpr; if (lhsi != null && lhsi.Fun is MapSelect) { var rhsi = assign.Rhss[i]; Debug.Assert(lhsi.Args.Count.Equals(2)); var index = lhsi.Args[1]; var arr = lhsi.Args[0]; Debug.Assert(arr is IdentifierExpr); var newLhsi = new SimpleAssignLhs(Token.NoToken, arr as IdentifierExpr); var newRhsi = new NAryExpr(Token.NoToken, new MapStore(Token.NoToken, 1), new List <Expr>() { arr, index, rhsi }); newLhs.Add(newLhsi); newRhs.Add(newRhsi); } else { newLhs.Add(assign.Lhss[i]); newRhs.Add(assign.Rhss[i]); } } assign.Rhss = newRhs; assign.Lhss = newLhs; } } return(base.VisitBlock(node)); }
///////////////////////////////////////////////////////////////////////////////////// private Expression getAssignmentSourceExpression(SimpleAssignLhs target, Expression source) { return(source); }
private void Analyse(Implementation impl, List <Cmd> cs) { foreach (var c in cs) { if (c is AssignCmd) { AssignCmd assignCmd = c as AssignCmd; for (int i = 0; i != assignCmd.Lhss.Count; i++) { if (assignCmd.Lhss[i] is SimpleAssignLhs) { SimpleAssignLhs lhs = assignCmd.Lhss[i] as SimpleAssignLhs; Expr rhs = assignCmd.Rhss[i]; VariablesOccurringInExpressionVisitor visitor = new VariablesOccurringInExpressionVisitor(); visitor.VisitExpr(rhs); foreach (Variable v in visitor.GetVariables()) { if (!mayBeDerivedFrom[impl.Name].ContainsKey(v.Name)) { continue; } foreach (string s in mayBeDerivedFrom[impl.Name][v.Name]) { if (mayBeDerivedFrom[impl.Name].ContainsKey(lhs.AssignedVariable.Name) && !mayBeDerivedFrom[impl.Name][lhs.AssignedVariable.Name].Contains(s)) { SetMayBeDerivedFrom(impl.Name, lhs.AssignedVariable.Name, s); } } } } } } else if (c is CallCmd) { CallCmd callCmd = c as CallCmd; if (QKeyValue.FindBoolAttribute(callCmd.Proc.Attributes, "barrier_invariant") || QKeyValue.FindBoolAttribute(callCmd.Proc.Attributes, "binary_barrier_invariant")) { foreach (Expr param in callCmd.Ins) { ExprMayAffectControlFlow(impl.Name, param); } } else if (!GPUVerifier.IsBarrier(callCmd.Proc)) { Implementation CalleeImplementation = verifier.GetImplementation(callCmd.callee); if (CalleeImplementation != null) { for (int i = 0; i < CalleeImplementation.InParams.Count(); i++) { VariablesOccurringInExpressionVisitor visitor = new VariablesOccurringInExpressionVisitor(); visitor.VisitExpr(callCmd.Ins[i]); foreach (Variable v in visitor.GetVariables()) { if (!mayBeDerivedFrom[impl.Name].ContainsKey(v.Name)) { continue; } foreach (string s in mayBeDerivedFrom[impl.Name][v.Name]) { if (!mayBeDerivedFrom[callCmd.callee][CalleeImplementation.InParams[i].Name].Contains(s)) { SetMayBeDerivedFrom(callCmd.callee, CalleeImplementation.InParams[i].Name, s); } } } } for (int i = 0; i < CalleeImplementation.OutParams.Count(); i++) { foreach (string s in mayBeDerivedFrom[callCmd.callee][CalleeImplementation.OutParams[i].Name]) { if (!mayBeDerivedFrom[impl.Name][callCmd.Outs[i].Name].Contains(s)) { SetMayBeDerivedFrom(impl.Name, callCmd.Outs[i].Name, s); } } } } } } else if (c is AssumeCmd) { var assumeCmd = c as AssumeCmd; ExprMayAffectControlFlow(impl.Name, assumeCmd.Expr); } else if (c is AssertCmd) { var assertCmd = c as AssertCmd; ExprMayAffectControlFlow(impl.Name, assertCmd.Expr); } } }
public override Cmd VisitCallCmd(CallCmd node) { var result = base.VisitCallCmd(node); var oldProc = programInCachedSnapshot.FindProcedure(node.Proc.Name); if (oldProc != null && oldProc.DependencyChecksum != node.Proc.DependencyChecksum && node.AssignedAssumptionVariable == null) { var before = new List <Cmd>(); var beforePreconditionCheck = new List <Cmd>(); var after = new List <Cmd>(); var axioms = new List <Axiom>(); Expr assumedExpr = new LiteralExpr(Token.NoToken, false); // TODO(wuestholz): Try out two alternatives: only do this for low priority implementations or not at all. var canUseSpecs = DependencyCollector.CanExpressOldSpecs(oldProc, Program); if (canUseSpecs && oldProc.SignatureEquals(node.Proc)) { var desugaring = node.Desugaring; Contract.Assert(desugaring != null); var precond = node.CheckedPrecondition(oldProc, Program, e => FunctionExtractor.Extract(e, Program, axioms)); if (precond != null) { var assume = new AssumeCmd(node.tok, precond, new QKeyValue(Token.NoToken, "precondition_previous_snapshot", new List <object>(), null)); assume.IrrelevantForChecksumComputation = true; beforePreconditionCheck.Add(assume); } var unmods = node.UnmodifiedBefore(oldProc); var eqs = new List <Expr>(); foreach (var unmod in unmods) { var oldUnmod = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, string.Format("{0}##old##{1}", unmod.Name, FreshTemporaryVariableName), unmod.Type)); var lhs = new SimpleAssignLhs(Token.NoToken, new IdentifierExpr(Token.NoToken, oldUnmod)); var rhs = new IdentifierExpr(Token.NoToken, unmod.Decl); var cmd = new AssignCmd(Token.NoToken, new List <AssignLhs> { lhs }, new List <Expr> { rhs }); cmd.IrrelevantForChecksumComputation = true; before.Add(cmd); var eq = LiteralExpr.Eq(new IdentifierExpr(Token.NoToken, oldUnmod), new IdentifierExpr(Token.NoToken, unmod.Decl)); eq.Type = Type.Bool; eq.TypeParameters = SimpleTypeParamInstantiation.EMPTY; eqs.Add(eq); } var mods = node.ModifiedBefore(oldProc); var oldSubst = new Dictionary <Variable, Expr>(); foreach (var mod in mods) { var oldMod = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, string.Format("{0}##old##{1}", mod.Name, FreshTemporaryVariableName), mod.Type)); oldSubst[mod.Decl] = new IdentifierExpr(Token.NoToken, oldMod); var lhs = new SimpleAssignLhs(Token.NoToken, new IdentifierExpr(Token.NoToken, oldMod)); var rhs = new IdentifierExpr(Token.NoToken, mod.Decl); var cmd = new AssignCmd(Token.NoToken, new List <AssignLhs> { lhs }, new List <Expr> { rhs }); cmd.IrrelevantForChecksumComputation = true; before.Add(cmd); } assumedExpr = node.Postcondition(oldProc, eqs, oldSubst, Program, e => FunctionExtractor.Extract(e, Program, axioms)); if (assumedExpr == null) { assumedExpr = new LiteralExpr(Token.NoToken, true); } } if (assumedExpr != null) { var lv = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, string.Format("a##cached##{0}", FreshAssumptionVariableName), Type.Bool), new QKeyValue(Token.NoToken, "assumption", new List <object>(), null)); node.AssignedAssumptionVariable = lv; currentImplementation.InjectAssumptionVariable(lv, !canUseSpecs); var lhs = new SimpleAssignLhs(Token.NoToken, new IdentifierExpr(Token.NoToken, lv)); var rhs = LiteralExpr.And(new IdentifierExpr(Token.NoToken, lv), assumedExpr); var assumed = new AssignCmd(node.tok, new List <AssignLhs> { lhs }, new List <Expr> { rhs }); assumed.IrrelevantForChecksumComputation = true; after.Add(assumed); } node.ExtendDesugaring(before, beforePreconditionCheck, after); if (CommandLineOptions.Clo.TraceCachingForTesting || CommandLineOptions.Clo.TraceCachingForBenchmarking) { using (var tokTxtWr = new TokenTextWriter("<console>", Console.Out, false, false)) { var loc = node.tok != null && node.tok != Token.NoToken ? string.Format("{0}({1},{2})", node.tok.filename, node.tok.line, node.tok.col) : "<unknown location>"; Console.Out.WriteLine("Processing call to procedure {0} in implementation {1} (at {2}):", node.Proc.Name, currentImplementation.Name, loc); foreach (var a in axioms) { Console.Out.Write(" >>> added axiom: "); a.Expr.Emit(tokTxtWr); Console.Out.WriteLine(); } foreach (var b in before) { Console.Out.Write(" >>> added before: "); b.Emit(tokTxtWr, 0); } foreach (var b in beforePreconditionCheck) { Console.Out.Write(" >>> added before precondition check: "); b.Emit(tokTxtWr, 0); } foreach (var a in after) { Console.Out.Write(" >>> added after: "); a.Emit(tokTxtWr, 0); } } } } return(result); }
public Implementation Inject(Implementation implementation, Program programInCachedSnapshot) { Contract.Requires(implementation != null && programInCachedSnapshot != null); this.programInCachedSnapshot = programInCachedSnapshot; assumptionVariableCount = 0; temporaryVariableCount = 0; currentImplementation = implementation; #region Introduce explict assumption about the precondition. var oldProc = programInCachedSnapshot.FindProcedure(currentImplementation.Proc.Name); if (oldProc != null && oldProc.DependencyChecksum != currentImplementation.Proc.DependencyChecksum && currentImplementation.ExplicitAssumptionAboutCachedPrecondition == null) { var axioms = new List <Axiom>(); var after = new List <Cmd>(); Expr assumedExpr = new LiteralExpr(Token.NoToken, false); var canUseSpecs = DependencyCollector.CanExpressOldSpecs(oldProc, Program, true); if (canUseSpecs && oldProc.SignatureEquals(currentImplementation.Proc)) { var always = Substituter.SubstitutionFromHashtable(currentImplementation.GetImplFormalMap(), true, currentImplementation.Proc); var forOld = Substituter.SubstitutionFromHashtable(new Dictionary <Variable, Expr>()); var clauses = oldProc.Requires.Select(r => Substituter.FunctionCallReresolvingApply(always, forOld, r.Condition, Program)); var conj = Expr.And(clauses, true); assumedExpr = conj != null ? FunctionExtractor.Extract(conj, Program, axioms) : new LiteralExpr(Token.NoToken, true); } if (assumedExpr != null) { var lv = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, string.Format("a##cached##{0}", FreshAssumptionVariableName), Type.Bool), new QKeyValue(Token.NoToken, "assumption", new List <object>(), null)); currentImplementation.InjectAssumptionVariable(lv, !canUseSpecs); var lhs = new SimpleAssignLhs(Token.NoToken, new IdentifierExpr(Token.NoToken, lv)); var rhs = LiteralExpr.And(new IdentifierExpr(Token.NoToken, lv), assumedExpr); var assumed = new AssignCmd(currentImplementation.tok, new List <AssignLhs> { lhs }, new List <Expr> { rhs }); assumed.IrrelevantForChecksumComputation = true; currentImplementation.ExplicitAssumptionAboutCachedPrecondition = assumed; after.Add(assumed); } if (CommandLineOptions.Clo.TraceCachingForTesting || CommandLineOptions.Clo.TraceCachingForBenchmarking) { using (var tokTxtWr = new TokenTextWriter("<console>", Console.Out, false, false)) { var loc = currentImplementation.tok != null && currentImplementation.tok != Token.NoToken ? string.Format("{0}({1},{2})", currentImplementation.tok.filename, currentImplementation.tok.line, currentImplementation.tok.col) : "<unknown location>"; Console.Out.WriteLine("Processing implementation {0} (at {1}):", currentImplementation.Name, loc); foreach (var a in axioms) { Console.Out.Write(" >>> added axiom: "); a.Expr.Emit(tokTxtWr); Console.Out.WriteLine(); } foreach (var b in after) { Console.Out.Write(" >>> added after assuming the current precondition: "); b.Emit(tokTxtWr, 0); } } } } #endregion var result = VisitImplementation(currentImplementation); currentImplementation = null; this.programInCachedSnapshot = null; return(result); }
public override AssignLhs VisitSimpleAssignLhs(SimpleAssignLhs node) { add(node); return(base.VisitSimpleAssignLhs(node)); }
public override AssignLhs VisitSimpleAssignLhs(SimpleAssignLhs node) { return(base.VisitSimpleAssignLhs((SimpleAssignLhs)node.Clone())); }
private bool Analyse(Implementation impl, List<Cmd> cmdSeq, bool ControlFlowIsUniform) { foreach (Cmd c in cmdSeq) { if (c is AssignCmd) { AssignCmd assignCmd = c as AssignCmd; foreach (var a in assignCmd.Lhss.Zip(assignCmd.Rhss)) { if (a.Item1 is SimpleAssignLhs) { SimpleAssignLhs lhs = a.Item1 as SimpleAssignLhs; Expr rhs = a.Item2; if (IsUniform(impl.Name, lhs.AssignedVariable.Name) && (!ControlFlowIsUniform || !IsUniform(impl.Name, rhs))) { SetNonUniform(impl.Name, lhs.AssignedVariable.Name); } } } } else if (c is HavocCmd) { HavocCmd havocCmd = c as HavocCmd; foreach(IdentifierExpr ie in havocCmd.Vars) { if(IsUniform(impl.Name, ie.Decl.Name)) { SetNonUniform(impl.Name, ie.Decl.Name); } } } else if (c is CallCmd) { CallCmd callCmd = c as CallCmd; DeclWithFormals Callee = GetProcedure(callCmd.callee); Debug.Assert(Callee != null); if (!ControlFlowIsUniform) { if (IsUniform(callCmd.callee)) { SetNonUniform(callCmd.callee); } } for (int i = 0; i < Callee.InParams.Count; i++) { if (IsUniform(callCmd.callee, Callee.InParams[i].Name) && !IsUniform(impl.Name, callCmd.Ins[i])) { SetNonUniform(callCmd.callee, Callee.InParams[i].Name); } } for (int i = 0; i < Callee.OutParams.Count; i++) { if (IsUniform(impl.Name, callCmd.Outs[i].Name) && !IsUniform(callCmd.callee, Callee.OutParams[i].Name)) { SetNonUniform(impl.Name, callCmd.Outs[i].Name); } } } else if (c is AssumeCmd) { var ac = (AssumeCmd)c; if (ControlFlowIsUniform && QKeyValue.FindBoolAttribute(ac.Attributes, "partition") && !IsUniform(impl.Name, ac.Expr)) { ControlFlowIsUniform = false; } } } return ControlFlowIsUniform; }
public override AssignLhs VisitSimpleAssignLhs(SimpleAssignLhs node) { return(node); }
//////////////////////////////////////////////////////////////////////////////////// internal ReferenceExpression makeReferenceExpression(SimpleAssignLhs assignLhs) { return(new Programs.Terms.Basic.ProgramVariable(scope.findVariable(assignLhs.AssignedVariable.Decl.Name))); }
// perform in place update of liveSet public static void Propagate(Cmd cmd, HashSet <Variable /*!*/> /*!*/ liveSet, bool allGlobalsAreLive) { Contract.Requires(cmd != null); Contract.Requires(cce.NonNullElements(liveSet)); if (cmd is AssignCmd) { AssignCmd /*!*/ assignCmd = (AssignCmd)cce.NonNull(cmd); // I must first iterate over all the targets and remove the live ones. // After the removals are done, I must add the variables referred on // the right side of the removed targets AssignCmd simpleAssignCmd = assignCmd.AsSimpleAssignCmd; HashSet <int> indexSet = new HashSet <int>(); int index = 0; foreach (AssignLhs /*!*/ lhs in simpleAssignCmd.Lhss) { Contract.Assert(lhs != null); SimpleAssignLhs salhs = lhs as SimpleAssignLhs; Contract.Assert(salhs != null); Variable var = salhs.DeepAssignedVariable; if (var != null && (liveSet.Contains(var) || (allGlobalsAreLive && var is GlobalVariable))) { indexSet.Add(index); liveSet.Remove(var); } index++; } index = 0; foreach (Expr /*!*/ expr in simpleAssignCmd.Rhss) { Contract.Assert(expr != null); if (indexSet.Contains(index)) { VariableCollector /*!*/ collector = new VariableCollector(); collector.Visit(expr); if (allGlobalsAreLive) { liveSet.UnionWith(collector.usedVars.Where(v => v is LocalVariable || v is Formal)); } else { liveSet.UnionWith(collector.usedVars); } } index++; } } else if (cmd is HavocCmd) { HavocCmd /*!*/ havocCmd = (HavocCmd)cmd; foreach (IdentifierExpr /*!*/ expr in havocCmd.Vars) { Contract.Assert(expr != null); if (expr.Decl != null) { liveSet.Remove(expr.Decl); } } } else if (cmd is PredicateCmd) { Contract.Assert((cmd is AssertCmd || cmd is AssumeCmd)); PredicateCmd /*!*/ predicateCmd = (PredicateCmd)cce.NonNull(cmd); if (predicateCmd.Expr is LiteralExpr) { LiteralExpr le = (LiteralExpr)predicateCmd.Expr; if (le.IsFalse) { liveSet.Clear(); } } else { VariableCollector /*!*/ collector = new VariableCollector(); collector.Visit(predicateCmd.Expr); if (allGlobalsAreLive) { liveSet.UnionWith(collector.usedVars.Where(v => v is LocalVariable || v is Formal)); } else { liveSet.UnionWith(collector.usedVars); } } } else if (cmd is CommentCmd) { // comments are just for debugging and don't affect verification } else if (cmd is SugaredCmd) { SugaredCmd /*!*/ sugCmd = (SugaredCmd)cce.NonNull(cmd); Propagate(sugCmd.Desugaring, liveSet, allGlobalsAreLive); } else if (cmd is StateCmd) { StateCmd /*!*/ stCmd = (StateCmd)cce.NonNull(cmd); List <Cmd> /*!*/ cmds = cce.NonNull(stCmd.Cmds); int len = cmds.Count; for (int i = len - 1; i >= 0; i--) { Propagate(cmds[i], liveSet, allGlobalsAreLive); } foreach (Variable /*!*/ v in stCmd.Locals) { Contract.Assert(v != null); liveSet.Remove(v); } } else { { Contract.Assert(false); throw new cce.UnreachableException(); } } }
public override AssignLhs VisitSimpleAssignLhs(SimpleAssignLhs node) { //Contract.Requires(node != null); Contract.Ensures(Contract.Result <AssignLhs>() != null); return(base.VisitSimpleAssignLhs((SimpleAssignLhs)node.Clone())); }
private void MakeDual(List <Cmd> cs, Cmd c) { if (c is CallCmd) { CallCmd call = c as CallCmd; if (QKeyValue.FindBoolAttribute(call.Proc.Attributes, "barrier_invariant")) { // There may be a predicate, and there must be an invariant expression and at least one instantiation Debug.Assert(call.Ins.Count >= (2 + (Verifier.UniformityAnalyser.IsUniform(call.callee) ? 0 : 1))); var biDescriptor = new UnaryBarrierInvariantDescriptor( Verifier.UniformityAnalyser.IsUniform(call.callee) ? Expr.True : call.Ins[0], Expr.Neq(call.Ins[Verifier.UniformityAnalyser.IsUniform(call.callee) ? 0 : 1], Verifier.IntRep.GetZero(Verifier.IntRep.GetIntType(1))), call.Attributes, this, procName, Verifier); for (var i = 1 + (Verifier.UniformityAnalyser.IsUniform(call.callee) ? 0 : 1); i < call.Ins.Count; i++) { biDescriptor.AddInstantiationExpr(call.Ins[i]); } barrierInvariantDescriptors.Add(biDescriptor); return; } if (QKeyValue.FindBoolAttribute(call.Proc.Attributes, "binary_barrier_invariant")) { // There may be a predicate, and there must be an invariant expression and at least one pair of // instantiation expressions Debug.Assert(call.Ins.Count >= (3 + (Verifier.UniformityAnalyser.IsUniform(call.callee) ? 0 : 1))); var biDescriptor = new BinaryBarrierInvariantDescriptor( Verifier.UniformityAnalyser.IsUniform(call.callee) ? Expr.True : call.Ins[0], Expr.Neq(call.Ins[Verifier.UniformityAnalyser.IsUniform(call.callee) ? 0 : 1], Verifier.IntRep.GetZero(Verifier.IntRep.GetIntType(1))), call.Attributes, this, procName, Verifier); for (var i = 1 + (Verifier.UniformityAnalyser.IsUniform(call.callee) ? 0 : 1); i < call.Ins.Count; i += 2) { biDescriptor.AddInstantiationExprPair(call.Ins[i], call.Ins[i + 1]); } barrierInvariantDescriptors.Add(biDescriptor); return; } if (GPUVerifier.IsBarrier(call.Proc)) { // Assert barrier invariants foreach (var biIDescriptor in barrierInvariantDescriptors) { QKeyValue sourceLocationInfo = biIDescriptor.GetSourceLocationInfo(); cs.Add(biIDescriptor.GetAssertCmd()); var vd = new VariableDualiser(1, Verifier, procName); if (GPUVerifyVCGenCommandLineOptions.BarrierAccessChecks) { foreach (Expr accessExpr in biIDescriptor.GetAccessedExprs()) { var assert = new AssertCmd(Token.NoToken, accessExpr, MakeThreadSpecificAttributes(sourceLocationInfo, 1)); assert.Attributes = new QKeyValue( Token.NoToken, "barrier_invariant_access_check", new List <object> { Expr.True }, assert.Attributes); cs.Add(vd.VisitAssertCmd(assert)); } } } } List <Expr> uniformNewIns = new List <Expr>(); List <Expr> nonUniformNewIns = new List <Expr>(); for (int i = 0; i < call.Ins.Count; i++) { if (Verifier.UniformityAnalyser.knowsOf(call.callee) && Verifier.UniformityAnalyser.IsUniform(call.callee, Verifier.UniformityAnalyser.GetInParameter(call.callee, i))) { uniformNewIns.Add(call.Ins[i]); } else if (!Verifier.OnlyThread2.Contains(call.callee)) { nonUniformNewIns.Add(new VariableDualiser(1, Verifier, procName).VisitExpr(call.Ins[i])); } } for (int i = 0; i < call.Ins.Count; i++) { if (!(Verifier.UniformityAnalyser.knowsOf(call.callee) && Verifier.UniformityAnalyser.IsUniform(call.callee, Verifier.UniformityAnalyser.GetInParameter(call.callee, i))) && !Verifier.OnlyThread1.Contains(call.callee)) { nonUniformNewIns.Add(new VariableDualiser(2, Verifier, procName).VisitExpr(call.Ins[i])); } } List <Expr> newIns = uniformNewIns; newIns.AddRange(nonUniformNewIns); List <IdentifierExpr> uniformNewOuts = new List <IdentifierExpr>(); List <IdentifierExpr> nonUniformNewOuts = new List <IdentifierExpr>(); for (int i = 0; i < call.Outs.Count; i++) { if (Verifier.UniformityAnalyser.knowsOf(call.callee) && Verifier.UniformityAnalyser.IsUniform(call.callee, Verifier.UniformityAnalyser.GetOutParameter(call.callee, i))) { uniformNewOuts.Add(call.Outs[i]); } else { nonUniformNewOuts.Add(new VariableDualiser(1, Verifier, procName).VisitIdentifierExpr(call.Outs[i].Clone() as IdentifierExpr) as IdentifierExpr); } } for (int i = 0; i < call.Outs.Count; i++) { if (!(Verifier.UniformityAnalyser.knowsOf(call.callee) && Verifier.UniformityAnalyser.IsUniform(call.callee, Verifier.UniformityAnalyser.GetOutParameter(call.callee, i)))) { nonUniformNewOuts.Add(new VariableDualiser(2, Verifier, procName).VisitIdentifierExpr(call.Outs[i].Clone() as IdentifierExpr) as IdentifierExpr); } } List <IdentifierExpr> newOuts = uniformNewOuts; newOuts.AddRange(nonUniformNewOuts); CallCmd newCallCmd = new CallCmd(call.tok, call.callee, newIns, newOuts); newCallCmd.Proc = call.Proc; newCallCmd.Attributes = call.Attributes; if (newCallCmd.callee.StartsWith("_LOG_ATOMIC")) { QKeyValue curr = newCallCmd.Attributes; if (curr.Key.StartsWith("arg")) { newCallCmd.Attributes = new QKeyValue(Token.NoToken, curr.Key, new List <object>(new object[] { Dualise(curr.Params[0] as Expr, 1) }), curr.Next); } for (curr = newCallCmd.Attributes; curr.Next != null; curr = curr.Next) { if (curr.Next.Key.StartsWith("arg")) { curr.Next = new QKeyValue(Token.NoToken, curr.Next.Key, new List <object>(new object[] { Dualise(curr.Next.Params[0] as Expr, 1) }), curr.Next.Next); } } } else if (newCallCmd.callee.StartsWith("_CHECK_ATOMIC")) { QKeyValue curr = newCallCmd.Attributes; if (curr.Key.StartsWith("arg")) { newCallCmd.Attributes = new QKeyValue(Token.NoToken, curr.Key, new List <object>(new object[] { Dualise(curr.Params[0] as Expr, 2) }), curr.Next); } for (curr = newCallCmd.Attributes; curr.Next != null; curr = curr.Next) { if (curr.Next.Key.StartsWith("arg")) { curr.Next = new QKeyValue(Token.NoToken, curr.Next.Key, new List <object>(new object[] { Dualise(curr.Next.Params[0] as Expr, 2) }), curr.Next.Next); } } } cs.Add(newCallCmd); if (GPUVerifier.IsBarrier(call.Proc)) { foreach (var biDescriptor in barrierInvariantDescriptors) { foreach (var instantiation in biDescriptor.GetInstantiationCmds()) { cs.Add(instantiation); } } barrierInvariantDescriptors.Clear(); } } else if (c is AssignCmd) { AssignCmd assign = c as AssignCmd; var vd1 = new VariableDualiser(1, Verifier, procName); var vd2 = new VariableDualiser(2, Verifier, procName); List <AssignLhs> lhss1 = new List <AssignLhs>(); List <AssignLhs> lhss2 = new List <AssignLhs>(); List <Expr> rhss1 = new List <Expr>(); List <Expr> rhss2 = new List <Expr>(); foreach (var pair in assign.Lhss.Zip(assign.Rhss)) { if (pair.Item1 is SimpleAssignLhs && Verifier.UniformityAnalyser.IsUniform( procName, (pair.Item1 as SimpleAssignLhs).AssignedVariable.Name)) { lhss1.Add(pair.Item1); rhss1.Add(pair.Item2); } else { lhss1.Add(vd1.Visit(pair.Item1.Clone() as AssignLhs) as AssignLhs); lhss2.Add(vd2.Visit(pair.Item1.Clone() as AssignLhs) as AssignLhs); rhss1.Add(vd1.VisitExpr(pair.Item2.Clone() as Expr)); rhss2.Add(vd2.VisitExpr(pair.Item2.Clone() as Expr)); } } Debug.Assert(lhss1.Count > 0); cs.Add(new AssignCmd(Token.NoToken, lhss1, rhss1)); if (lhss2.Count > 0) { cs.Add(new AssignCmd(Token.NoToken, lhss2, rhss2)); } } else if (c is HavocCmd) { HavocCmd havoc = c as HavocCmd; Debug.Assert(havoc.Vars.Count() == 1); HavocCmd newHavoc; var idents = new List <IdentifierExpr> { (IdentifierExpr) new VariableDualiser(1, Verifier, procName).VisitIdentifierExpr(havoc.Vars[0].Clone() as IdentifierExpr), (IdentifierExpr) new VariableDualiser(2, Verifier, procName).VisitIdentifierExpr(havoc.Vars[0].Clone() as IdentifierExpr) }; newHavoc = new HavocCmd(havoc.tok, idents); cs.Add(newHavoc); } else if (c is AssertCmd) { AssertCmd a = c as AssertCmd; if (QKeyValue.FindBoolAttribute(a.Attributes, "sourceloc") || QKeyValue.FindBoolAttribute(a.Attributes, "block_sourceloc") || QKeyValue.FindBoolAttribute(a.Attributes, "array_bounds")) { // This is just a location marker, so we do not dualise it cs.Add(new AssertCmd( Token.NoToken, new VariableDualiser(1, Verifier, procName).VisitExpr(a.Expr.Clone() as Expr), (QKeyValue)a.Attributes.Clone())); } else { var isUniform = Verifier.UniformityAnalyser.IsUniform(procName, a.Expr); cs.Add(MakeThreadSpecificAssert(a, 1)); if (!GPUVerifyVCGenCommandLineOptions.AsymmetricAsserts && !ContainsAsymmetricExpression(a.Expr) && !isUniform) { cs.Add(MakeThreadSpecificAssert(a, 2)); } } } else if (c is AssumeCmd) { AssumeCmd ass = c as AssumeCmd; if (QKeyValue.FindStringAttribute(ass.Attributes, "captureState") != null) { cs.Add(c); } else if (QKeyValue.FindBoolAttribute(ass.Attributes, "backedge")) { AssumeCmd newAss = new AssumeCmd( c.tok, Expr.Or( new VariableDualiser(1, Verifier, procName).VisitExpr(ass.Expr.Clone() as Expr), new VariableDualiser(2, Verifier, procName).VisitExpr(ass.Expr.Clone() as Expr))); newAss.Attributes = ass.Attributes; cs.Add(newAss); } else if (QKeyValue.FindBoolAttribute(ass.Attributes, "atomic_refinement")) { // Generate the following: // havoc v$1, v$2; // assume !_USED[offset$1][v$1]; // _USED[offset$1][v$1] := true; // assume !_USED[offset$2][v$2]; // _USED[offset$2][v$2] := true; Expr variable = QKeyValue.FindExprAttribute(ass.Attributes, "variable"); Expr offset = QKeyValue.FindExprAttribute(ass.Attributes, "offset"); List <Expr> offsets = Enumerable.Range(1, 2).Select(x => new VariableDualiser(x, Verifier, procName).VisitExpr(offset.Clone() as Expr)).ToList(); List <Expr> vars = Enumerable.Range(1, 2).Select(x => new VariableDualiser(x, Verifier, procName).VisitExpr(variable.Clone() as Expr)).ToList(); IdentifierExpr arrayRef = new IdentifierExpr(Token.NoToken, Verifier.FindOrCreateUsedMap(QKeyValue.FindStringAttribute(ass.Attributes, "arrayref"), vars[0].Type)); bool isShared = QKeyValue.FindBoolAttribute(arrayRef.Decl.Attributes, "atomic_group_shared"); foreach (int i in Enumerable.Range(0, 2)) { Expr assumeSelect = arrayRef; if (isShared && !GPUVerifyVCGenCommandLineOptions.OnlyIntraGroupRaceChecking) { assumeSelect = new NAryExpr( Token.NoToken, new MapSelect(Token.NoToken, 1), new List <Expr> { assumeSelect, Verifier.GroupSharedIndexingExpr(i + 1) }); } assumeSelect = new NAryExpr( Token.NoToken, new MapSelect(Token.NoToken, 1), new List <Expr> { assumeSelect, offsets[i] }); assumeSelect = new NAryExpr( Token.NoToken, new MapSelect(Token.NoToken, 1), new List <Expr> { assumeSelect, vars[i] }); AssumeCmd newAssume = new AssumeCmd(c.tok, Expr.Not(assumeSelect)); cs.Add(newAssume); AssignLhs lhs = new SimpleAssignLhs(Token.NoToken, arrayRef); if (isShared && !GPUVerifyVCGenCommandLineOptions.OnlyIntraGroupRaceChecking) { lhs = new MapAssignLhs( Token.NoToken, lhs, new List <Expr> { Verifier.GroupSharedIndexingExpr(i + 1) }); } lhs = new MapAssignLhs( Token.NoToken, lhs, new List <Expr> { offsets[i] }); lhs = new MapAssignLhs( Token.NoToken, lhs, new List <Expr> { vars[i] }); AssignCmd assign = new AssignCmd( c.tok, new List <AssignLhs> { lhs }, new List <Expr> { Expr.True }); cs.Add(assign); } } else { var isUniform = Verifier.UniformityAnalyser.IsUniform(procName, ass.Expr); AssumeCmd newAss = new AssumeCmd(c.tok, new VariableDualiser(1, Verifier, procName).VisitExpr(ass.Expr.Clone() as Expr)); if (!ContainsAsymmetricExpression(ass.Expr) && !isUniform) { newAss.Expr = Expr.And(newAss.Expr, new VariableDualiser(2, Verifier, procName).VisitExpr(ass.Expr.Clone() as Expr)); } newAss.Attributes = ass.Attributes; cs.Add(newAss); } } else { Debug.Assert(false); } }