summaryrefslogtreecommitdiff
path: root/Source/GPUVerify/GPUVerifier.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Source/GPUVerify/GPUVerifier.cs')
-rw-r--r--Source/GPUVerify/GPUVerifier.cs4465
1 files changed, 2272 insertions, 2193 deletions
diff --git a/Source/GPUVerify/GPUVerifier.cs b/Source/GPUVerify/GPUVerifier.cs
index d2ae0ad8..216954c5 100644
--- a/Source/GPUVerify/GPUVerifier.cs
+++ b/Source/GPUVerify/GPUVerifier.cs
@@ -1,2205 +1,2284 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.IO;
-using System.Diagnostics;
-using System.Diagnostics.Contracts;
-using Microsoft.Boogie;
-using Microsoft.Basetypes;
-
-namespace GPUVerify
-{
- class GPUVerifier : CheckingContext
- {
- public string outputFilename;
- public Program Program;
- public ResolutionContext ResContext;
-
- public Procedure KernelProcedure;
- public Implementation KernelImplementation;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.IO;
+using System.Diagnostics;
+using System.Diagnostics.Contracts;
+using Microsoft.Boogie;
+using Microsoft.Basetypes;
+
+namespace GPUVerify
+{
+ class GPUVerifier : CheckingContext
+ {
+ public string outputFilename;
+ public Program Program;
+ public ResolutionContext ResContext;
+
+ public Procedure KernelProcedure;
+ public Implementation KernelImplementation;
public Procedure BarrierProcedure;
-
- public IKernelArrayInfo KernelArrayInfo = new KernelArrayInfoLists();
-
- private HashSet<string> ReservedNames = new HashSet<string>();
-
- internal HashSet<string> OnlyThread1 = new HashSet<string>();
- internal HashSet<string> OnlyThread2 = new HashSet<string>();
-
- private int TempCounter = 0;
-
- internal const string LOCAL_ID_X_STRING = "local_id_x";
- internal const string LOCAL_ID_Y_STRING = "local_id_y";
- internal const string LOCAL_ID_Z_STRING = "local_id_z";
-
- internal static Constant _X = null;
- internal static Constant _Y = null;
- internal static Constant _Z = null;
-
- internal const string GROUP_SIZE_X_STRING = "group_size_x";
- internal const string GROUP_SIZE_Y_STRING = "group_size_y";
- internal const string GROUP_SIZE_Z_STRING = "group_size_z";
-
- internal static Constant _GROUP_SIZE_X = null;
- internal static Constant _GROUP_SIZE_Y = null;
- internal static Constant _GROUP_SIZE_Z = null;
-
- internal const string GROUP_ID_X_STRING = "group_id_x";
- internal const string GROUP_ID_Y_STRING = "group_id_y";
- internal const string GROUP_ID_Z_STRING = "group_id_z";
-
- internal static Constant _GROUP_X = null;
- internal static Constant _GROUP_Y = null;
- internal static Constant _GROUP_Z = null;
-
- internal const string NUM_GROUPS_X_STRING = "num_groups_x";
- internal const string NUM_GROUPS_Y_STRING = "num_groups_y";
- internal const string NUM_GROUPS_Z_STRING = "num_groups_z";
-
- internal static Constant _NUM_GROUPS_X = null;
- internal static Constant _NUM_GROUPS_Y = null;
- internal static Constant _NUM_GROUPS_Z = null;
-
- public IRaceInstrumenter RaceInstrumenter;
-
- public UniformityAnalyser uniformityAnalyser;
- public MayBePowerOfTwoAnalyser mayBePowerOfTwoAnalyser;
- public LiveVariableAnalyser liveVariableAnalyser;
- public ArrayControlFlowAnalyser arrayControlFlowAnalyser;
- public Dictionary<Implementation, VariableDefinitionAnalysis> varDefAnalyses;
- public Dictionary<Implementation, ReducedStrengthAnalysis> reducedStrengthAnalyses;
-
- public GPUVerifier(string filename, Program program, ResolutionContext rc, IRaceInstrumenter raceInstrumenter) : this(filename, program, rc, raceInstrumenter, false)
- {
- }
-
- public GPUVerifier(string filename, Program program, ResolutionContext rc, IRaceInstrumenter raceInstrumenter, bool skipCheck)
- : base((IErrorSink)null)
- {
- this.outputFilename = filename;
- this.Program = program;
- this.ResContext = rc;
- this.RaceInstrumenter = raceInstrumenter;
- if(!skipCheck)
- CheckWellFormedness();
- }
-
- public void setRaceInstrumenter(IRaceInstrumenter ri)
- {
- this.RaceInstrumenter = ri;
- }
-
- private void CheckWellFormedness()
- {
- int errorCount = Check();
- if (errorCount != 0)
- {
- Console.WriteLine("{0} GPUVerify format errors detected in {1}", errorCount, CommandLineOptions.inputFiles[CommandLineOptions.inputFiles.Count - 1]);
- Environment.Exit(1);
- }
- }
-
- private Procedure CheckExactlyOneKernelProcedure()
- {
- var p = CheckSingleInstanceOfAttributedProcedure("kernel");
- if (p == null)
- {
- Error(Program, "\"kernel\" attribute has not been specified for any procedure. You must mark exactly one procedure with this attribute");
- }
-
- return p;
- }
-
- private Procedure FindOrCreateBarrierProcedure()
- {
- var p = CheckSingleInstanceOfAttributedProcedure("barrier");
- if (p == null)
- {
- p = new Procedure(Token.NoToken, "barrier", new TypeVariableSeq(),
- new VariableSeq(new Variable[] {
- new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "__local_fence", new BvType(1)), true),
- new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "__global_fence", new BvType(1)), true) }),
- new VariableSeq(),
- new RequiresSeq(), new IdentifierExprSeq(),
- new EnsuresSeq(),
- new QKeyValue(Token.NoToken, "barrier", new List<object>(), null));
- Program.TopLevelDeclarations.Add(p);
- ResContext.AddProcedure(p);
- }
- return p;
- }
-
- private Procedure CheckSingleInstanceOfAttributedProcedure(string attribute)
- {
- Procedure attributedProcedure = null;
-
- foreach (Declaration decl in Program.TopLevelDeclarations)
- {
- if (!QKeyValue.FindBoolAttribute(decl.Attributes, attribute))
- {
- continue;
- }
-
- if (decl is Implementation)
- {
- continue;
- }
-
- if (decl is Procedure)
- {
- if (attributedProcedure == null)
- {
- attributedProcedure = decl as Procedure;
- }
- else
- {
- Error(decl, "\"{0}\" attribute specified for procedure {1}, but it has already been specified for procedure {2}", attribute, (decl as Procedure).Name, attributedProcedure.Name);
- }
-
- }
- else
- {
- Error(decl, "\"{0}\" attribute can only be applied to a procedure", attribute);
- }
- }
-
- return attributedProcedure;
- }
-
- private void CheckLocalVariables()
- {
- foreach (LocalVariable LV in KernelImplementation.LocVars)
- {
- if (QKeyValue.FindBoolAttribute(LV.Attributes, "group_shared"))
- {
- Error(LV.tok, "Local variable must not be marked 'group_shared' -- promote the variable to global scope");
- }
- }
- }
-
-
- private void ReportMultipleAttributeError(string attribute, IToken first, IToken second)
- {
- Error(
- second,
- "Can only have one {0} attribute, but previously saw this attribute at ({1}, {2})",
- attribute,
- first.filename,
- first.line, first.col - 1);
- }
-
- private bool setConstAttributeField(Constant constInProgram, string attr, ref Constant constFieldRef)
- {
- if (QKeyValue.FindBoolAttribute(constInProgram.Attributes, attr))
- {
- if (constFieldRef != null)
- {
- ReportMultipleAttributeError(attr, constFieldRef.tok, constInProgram.tok);
- return false;
- }
- CheckSpecialConstantType(constInProgram);
- constFieldRef = constInProgram;
- }
- return true;
- }
-
- private void MaybeCreateAttributedConst(string attr, ref Constant constFieldRef)
- {
- if (constFieldRef == null)
- {
- constFieldRef = new Constant(Token.NoToken, new TypedIdent(Token.NoToken, attr, Microsoft.Boogie.Type.GetBvType(32)), /*unique=*/false);
- constFieldRef.AddAttribute(attr);
- Program.TopLevelDeclarations.Add(constFieldRef);
- }
- }
-
- private bool FindNonLocalVariables()
- {
- bool success = true;
- foreach (Declaration D in Program.TopLevelDeclarations)
- {
- if (D is Variable &&
- (D as Variable).IsMutable &&
- (D as Variable).TypedIdent.Type is MapType &&
- !ReservedNames.Contains((D as Variable).Name))
- {
- if (QKeyValue.FindBoolAttribute(D.Attributes, "group_shared"))
- {
- KernelArrayInfo.getGroupSharedArrays().Add(D as Variable);
- }
- else if (QKeyValue.FindBoolAttribute(D.Attributes, "global"))
- {
- KernelArrayInfo.getGlobalArrays().Add(D as Variable);
- }
- else
- {
- KernelArrayInfo.getPrivateArrays().Add(D as Variable);
- }
- }
- else if (D is Constant)
- {
- Constant C = D as Constant;
-
- success &= setConstAttributeField(C, LOCAL_ID_X_STRING, ref _X);
- success &= setConstAttributeField(C, LOCAL_ID_Y_STRING, ref _Y);
- success &= setConstAttributeField(C, LOCAL_ID_Z_STRING, ref _Z);
-
- success &= setConstAttributeField(C, GROUP_SIZE_X_STRING, ref _GROUP_SIZE_X);
- success &= setConstAttributeField(C, GROUP_SIZE_Y_STRING, ref _GROUP_SIZE_Y);
- success &= setConstAttributeField(C, GROUP_SIZE_Z_STRING, ref _GROUP_SIZE_Z);
-
- success &= setConstAttributeField(C, GROUP_ID_X_STRING, ref _GROUP_X);
- success &= setConstAttributeField(C, GROUP_ID_Y_STRING, ref _GROUP_Y);
- success &= setConstAttributeField(C, GROUP_ID_Z_STRING, ref _GROUP_Z);
-
- success &= setConstAttributeField(C, NUM_GROUPS_X_STRING, ref _NUM_GROUPS_X);
- success &= setConstAttributeField(C, NUM_GROUPS_Y_STRING, ref _NUM_GROUPS_Y);
- success &= setConstAttributeField(C, NUM_GROUPS_Z_STRING, ref _NUM_GROUPS_Z);
-
-
- }
- }
-
- MaybeCreateAttributedConst(LOCAL_ID_X_STRING, ref _X);
- MaybeCreateAttributedConst(LOCAL_ID_Y_STRING, ref _Y);
- MaybeCreateAttributedConst(LOCAL_ID_Z_STRING, ref _Z);
-
- MaybeCreateAttributedConst(GROUP_SIZE_X_STRING, ref _GROUP_SIZE_X);
- MaybeCreateAttributedConst(GROUP_SIZE_Y_STRING, ref _GROUP_SIZE_Y);
- MaybeCreateAttributedConst(GROUP_SIZE_Z_STRING, ref _GROUP_SIZE_Z);
-
- MaybeCreateAttributedConst(GROUP_ID_X_STRING, ref _GROUP_X);
- MaybeCreateAttributedConst(GROUP_ID_Y_STRING, ref _GROUP_Y);
- MaybeCreateAttributedConst(GROUP_ID_Z_STRING, ref _GROUP_Z);
-
- MaybeCreateAttributedConst(NUM_GROUPS_X_STRING, ref _NUM_GROUPS_X);
- MaybeCreateAttributedConst(NUM_GROUPS_Y_STRING, ref _NUM_GROUPS_Y);
- MaybeCreateAttributedConst(NUM_GROUPS_Z_STRING, ref _NUM_GROUPS_Z);
-
- return success;
- }
-
- private void CheckSpecialConstantType(Constant C)
- {
- if (!(C.TypedIdent.Type.Equals(Microsoft.Boogie.Type.Int) || C.TypedIdent.Type.Equals(Microsoft.Boogie.Type.GetBvType(32))))
- {
- Error(C.tok, "Special constant '" + C.Name + "' must have type 'int' or 'bv32'");
- }
- }
-
- private void GetKernelImplementation()
- {
- foreach (Declaration decl in Program.TopLevelDeclarations)
- {
- if (!(decl is Implementation))
- {
- continue;
- }
-
- Implementation Impl = decl as Implementation;
-
- if (Impl.Proc == KernelProcedure)
- {
- KernelImplementation = Impl;
- break;
- }
-
- }
-
- if (KernelImplementation == null)
- {
- Error(Token.NoToken, "*** Error: no implementation of kernel procedure");
- }
- }
-
-
-
-
- protected virtual void CheckKernelImplementation()
- {
- CheckKernelParameters();
- GetKernelImplementation();
-
- if (KernelImplementation == null)
- {
- return;
- }
-
- CheckLocalVariables();
- CheckNoReturns();
- }
-
- private void CheckNoReturns()
- {
- // TODO!
- }
-
- internal void preProcess()
- {
- RemoveRedundantReturns();
-
- RemoveElseIfs();
-
- PullOutNonLocalAccesses();
- }
-
- private void MergeBlocksIntoPredecessors()
- {
- foreach (var impl in Program.TopLevelDeclarations.OfType<Implementation>())
- VC.VCGen.MergeBlocksIntoPredecessors(Program, impl);
- }
-
- internal void doit()
- {
- File.Delete(Path.GetFileNameWithoutExtension(CommandLineOptions.inputFiles[0]) + ".loc");
- if (CommandLineOptions.Unstructured)
- {
- Microsoft.Boogie.CommandLineOptions.Clo.PrintUnstructured = 2;
- }
-
- if (CommandLineOptions.ShowStages)
- {
- emitProgram(outputFilename + "_original");
- }
-
- preProcess();
-
- if (CommandLineOptions.ShowStages) {
- emitProgram(outputFilename + "_preprocessed");
- }
-
- DoLiveVariableAnalysis();
-
- DoUniformityAnalysis();
-
- DoVariableDefinitionAnalysis();
-
- DoReducedStrengthAnalysis();
-
- DoMayBePowerOfTwoAnalysis();
-
- DoArrayControlFlowAnalysis();
-
- if (CommandLineOptions.Inference)
- {
- foreach (var impl in Program.TopLevelDeclarations.OfType<Implementation>().ToList())
- {
- LoopInvariantGenerator.PreInstrument(this, impl);
- }
-
- if (CommandLineOptions.ShowStages) {
- emitProgram(outputFilename + "_pre_inference");
- }
-
- }
-
- RaceInstrumenter.AddRaceCheckingInstrumentation();
-
- if (CommandLineOptions.ShowStages)
- {
- emitProgram(outputFilename + "_instrumented");
- }
-
- AbstractSharedState();
-
- if (CommandLineOptions.ShowStages)
- {
- emitProgram(outputFilename + "_abstracted");
- }
-
- MergeBlocksIntoPredecessors();
-
- if (CommandLineOptions.ShowStages)
- {
- emitProgram(outputFilename + "_merged_pre_predication");
- }
-
- MakeKernelPredicated();
-
- if (CommandLineOptions.ShowStages)
- {
- emitProgram(outputFilename + "_predicated");
- }
-
- MergeBlocksIntoPredecessors();
-
- if (CommandLineOptions.ShowStages)
- {
- emitProgram(outputFilename + "_merged_post_predication");
- }
-
- MakeKernelDualised();
-
- if (CommandLineOptions.ShowStages)
- {
- emitProgram(outputFilename + "_dualised");
- }
-
- RaceInstrumenter.AddRaceCheckingDeclarations();
-
- GenerateBarrierImplementation();
-
- GenerateStandardKernelContract();
-
- if (CommandLineOptions.ShowStages)
- {
- emitProgram(outputFilename + "_ready_to_verify");
- }
-
- if (CommandLineOptions.Inference)
- {
- ComputeInvariant();
- }
-
- emitProgram(outputFilename);
-
- }
-
- private void DoMayBePowerOfTwoAnalysis()
- {
- mayBePowerOfTwoAnalyser = new MayBePowerOfTwoAnalyser(this);
- mayBePowerOfTwoAnalyser.Analyse();
- }
-
- private void DoArrayControlFlowAnalysis()
- {
- arrayControlFlowAnalyser = new ArrayControlFlowAnalyser(this);
- arrayControlFlowAnalyser.Analyse();
- }
-
- private void DoUniformityAnalysis()
- {
- uniformityAnalyser = new UniformityAnalyser(this);
- uniformityAnalyser.Analyse();
- }
-
- private void DoLiveVariableAnalysis()
- {
- liveVariableAnalyser = new LiveVariableAnalyser(this);
- liveVariableAnalyser.Analyse();
- }
-
- private void DoVariableDefinitionAnalysis()
- {
- varDefAnalyses = Program.TopLevelDeclarations
- .OfType<Implementation>()
- .ToDictionary(i => i, i => VariableDefinitionAnalysis.Analyse(this, i));
- }
-
- private void DoReducedStrengthAnalysis()
- {
- reducedStrengthAnalyses = Program.TopLevelDeclarations
- .OfType<Implementation>()
- .ToDictionary(i => i, i => ReducedStrengthAnalysis.Analyse(this, i));
- }
-
- private void emitProgram(string filename)
- {
- using (TokenTextWriter writer = new TokenTextWriter(filename + ".bpl"))
- {
- Program.Emit(writer);
- }
- }
-
- private void ComputeInvariant()
- {
- for (int i = 0; i < Program.TopLevelDeclarations.Count; i++)
- {
- if (Program.TopLevelDeclarations[i] is Implementation)
- {
-
- Implementation Impl = Program.TopLevelDeclarations[i] as Implementation;
-
- List<Expr> UserSuppliedInvariants = GetUserSuppliedInvariants(Impl.Name);
-
- LoopInvariantGenerator.PostInstrument(this, Impl, UserSuppliedInvariants);
-
- Procedure Proc = Impl.Proc;
-
- if (QKeyValue.FindIntAttribute(Proc.Attributes, "inline", -1) == 1)
- {
- continue;
- }
-
- if (Proc == KernelProcedure)
- {
- continue;
- }
-
- AddCandidateRequires(Proc);
- RaceInstrumenter.AddRaceCheckingCandidateRequires(Proc);
- AddUserSuppliedCandidateRequires(Proc, UserSuppliedInvariants);
-
- AddCandidateEnsures(Proc);
- RaceInstrumenter.AddRaceCheckingCandidateEnsures(Proc);
- AddUserSuppliedCandidateEnsures(Proc, UserSuppliedInvariants);
-
- }
-
-
- }
-
- }
-
- private void AddCandidateEnsures(Procedure Proc)
- {
- HashSet<string> names = new HashSet<String>();
- foreach (Variable v in Proc.OutParams)
- {
- names.Add(StripThreadIdentifier(v.Name));
- }
-
- foreach (string name in names)
- {
- if (!uniformityAnalyser.IsUniform(Proc.Name, name))
- {
- AddEqualityCandidateEnsures(Proc, new LocalVariable(Proc.tok, new TypedIdent(Proc.tok, name, Microsoft.Boogie.Type.Int)));
- }
- }
-
- }
-
- private void AddCandidateRequires(Procedure Proc)
- {
- HashSet<string> names = new HashSet<String>();
- foreach (Variable v in Proc.InParams)
- {
- names.Add(StripThreadIdentifier(v.Name));
- }
-
- foreach (string name in names)
- {
-
- if (IsPredicateOrTemp(name))
- {
- Debug.Assert(name.Equals("_P"));
- Debug.Assert(!uniformityAnalyser.IsUniform(Proc.Name));
- AddCandidateRequires(Proc, Expr.Eq(
- new IdentifierExpr(Proc.tok, new LocalVariable(Proc.tok, new TypedIdent(Proc.tok, name + "$1", Microsoft.Boogie.Type.Bool))),
- new IdentifierExpr(Proc.tok, new LocalVariable(Proc.tok, new TypedIdent(Proc.tok, name + "$2", Microsoft.Boogie.Type.Bool)))
- ));
- }
- else
- {
- if (!uniformityAnalyser.IsUniform(Proc.Name, name))
- {
- if (!uniformityAnalyser.IsUniform(Proc.Name))
- {
- AddPredicatedEqualityCandidateRequires(Proc, new LocalVariable(Proc.tok, new TypedIdent(Proc.tok, name, Microsoft.Boogie.Type.Int)));
- }
- AddEqualityCandidateRequires(Proc, new LocalVariable(Proc.tok, new TypedIdent(Proc.tok, name, Microsoft.Boogie.Type.Int)));
- }
- }
- }
-
- }
-
- private void AddPredicatedEqualityCandidateRequires(Procedure Proc, Variable v)
- {
- AddCandidateRequires(Proc, Expr.Imp(
- Expr.And(
- new IdentifierExpr(Proc.tok, new LocalVariable(Proc.tok, new TypedIdent(Proc.tok, "_P$1", Microsoft.Boogie.Type.Bool))),
- new IdentifierExpr(Proc.tok, new LocalVariable(Proc.tok, new TypedIdent(Proc.tok, "_P$2", Microsoft.Boogie.Type.Bool)))
- ),
- Expr.Eq(
- new IdentifierExpr(Proc.tok, new VariableDualiser(1, uniformityAnalyser, Proc.Name).VisitVariable(v.Clone() as Variable)),
- new IdentifierExpr(Proc.tok, new VariableDualiser(2, uniformityAnalyser, Proc.Name).VisitVariable(v.Clone() as Variable))
- )
- ));
- }
-
- private void AddEqualityCandidateRequires(Procedure Proc, Variable v)
- {
- AddCandidateRequires(Proc,
- Expr.Eq(
- new IdentifierExpr(Proc.tok, new VariableDualiser(1, uniformityAnalyser, Proc.Name).VisitVariable(v.Clone() as Variable)),
- new IdentifierExpr(Proc.tok, new VariableDualiser(2, uniformityAnalyser, Proc.Name).VisitVariable(v.Clone() as Variable))
- )
- );
- }
-
- private void AddEqualityCandidateEnsures(Procedure Proc, Variable v)
- {
- AddCandidateEnsures(Proc,
- Expr.Eq(
- new IdentifierExpr(Proc.tok, new VariableDualiser(1, uniformityAnalyser, Proc.Name).VisitVariable(v.Clone() as Variable)),
- new IdentifierExpr(Proc.tok, new VariableDualiser(2, uniformityAnalyser, Proc.Name).VisitVariable(v.Clone() as Variable))
- ));
- }
-
-
- private void AddUserSuppliedCandidateRequires(Procedure Proc, List<Expr> UserSuppliedInvariants)
- {
- foreach (Expr e in UserSuppliedInvariants)
- {
- Requires r = new Requires(false, e);
- Proc.Requires.Add(r);
- bool OK = ProgramIsOK(Proc);
- Proc.Requires.Remove(r);
- if (OK)
- {
- AddCandidateRequires(Proc, e);
- }
- }
- }
-
- private void AddUserSuppliedCandidateEnsures(Procedure Proc, List<Expr> UserSuppliedInvariants)
- {
- foreach (Expr e in UserSuppliedInvariants)
- {
- Ensures ens = new Ensures(false, e);
- Proc.Ensures.Add(ens);
- bool OK = ProgramIsOK(Proc);
- Proc.Ensures.Remove(ens);
- if (OK)
- {
- AddCandidateEnsures(Proc, e);
- }
- }
- }
-
-
-
- internal void AddCandidateRequires(Procedure Proc, Expr e)
- {
- Constant ExistentialBooleanConstant = Program.MakeExistentialBoolean();
- IdentifierExpr ExistentialBoolean = new IdentifierExpr(Proc.tok, ExistentialBooleanConstant);
- Proc.Requires.Add(new Requires(false, Expr.Imp(ExistentialBoolean, e)));
- }
-
- internal void AddCandidateEnsures(Procedure Proc, Expr e)
- {
- Constant ExistentialBooleanConstant = Program.MakeExistentialBoolean();
- IdentifierExpr ExistentialBoolean = new IdentifierExpr(Proc.tok, ExistentialBooleanConstant);
- Proc.Ensures.Add(new Ensures(false, Expr.Imp(ExistentialBoolean, e)));
- }
-
- private List<Expr> GetUserSuppliedInvariants(string ProcedureName)
- {
- List<Expr> result = new List<Expr>();
-
- if (CommandLineOptions.invariantsFile == null)
- {
- return result;
- }
-
- StreamReader sr = new StreamReader(new FileStream(CommandLineOptions.invariantsFile, FileMode.Open, FileAccess.Read));
- string line;
- int lineNumber = 1;
- while ((line = sr.ReadLine()) != null)
- {
- string[] components = line.Split(':');
-
- if (components.Length != 1 && components.Length != 2)
- {
- Console.WriteLine("Ignoring badly formed candidate invariant '" + line + "' at '" + CommandLineOptions.invariantsFile + "' line " + lineNumber);
- continue;
- }
-
- if (components.Length == 2)
- {
- if (!components[0].Trim().Equals(ProcedureName))
- {
- continue;
- }
-
- line = components[1];
- }
-
- string temp_program_text = "axiom (" + line + ");";
- TokenTextWriter writer = new TokenTextWriter("temp_out.bpl");
- writer.WriteLine(temp_program_text);
- writer.Close();
-
- Program temp_program = GPUVerify.ParseBoogieProgram(new List<string>(new string[] { "temp_out.bpl" }), false);
-
- if (null == temp_program)
- {
- Console.WriteLine("Ignoring badly formed candidate invariant '" + line + "' at '" + CommandLineOptions.invariantsFile + "' line " + lineNumber);
- }
- else
- {
- Debug.Assert(temp_program.TopLevelDeclarations[0] is Axiom);
- result.Add((temp_program.TopLevelDeclarations[0] as Axiom).Expr);
- }
-
- lineNumber++;
- }
-
- return result;
- }
-
- internal bool ContainsNamedVariable(HashSet<Variable> variables, string name)
- {
- foreach(Variable v in variables)
- {
- if(StripThreadIdentifier(v.Name) == name)
- {
- return true;
- }
- }
- return false;
- }
-
- internal static bool IsPredicate(string v) {
- if (v.Length < 2) {
- return false;
- }
- if (!v.Substring(0, 1).Equals("p")) {
- return false;
- }
- for (int i = 1; i < v.Length; i++) {
- if (!Char.IsDigit(v.ToCharArray()[i])) {
- return false;
- }
+
+ public IKernelArrayInfo KernelArrayInfo = new KernelArrayInfoLists();
+
+ private HashSet<string> ReservedNames = new HashSet<string>();
+
+ internal HashSet<string> OnlyThread1 = new HashSet<string>();
+ internal HashSet<string> OnlyThread2 = new HashSet<string>();
+
+ private int TempCounter = 0;
+
+ internal const string LOCAL_ID_X_STRING = "local_id_x";
+ internal const string LOCAL_ID_Y_STRING = "local_id_y";
+ internal const string LOCAL_ID_Z_STRING = "local_id_z";
+
+ internal static Constant _X = null;
+ internal static Constant _Y = null;
+ internal static Constant _Z = null;
+
+ internal const string GROUP_SIZE_X_STRING = "group_size_x";
+ internal const string GROUP_SIZE_Y_STRING = "group_size_y";
+ internal const string GROUP_SIZE_Z_STRING = "group_size_z";
+
+ internal static Constant _GROUP_SIZE_X = null;
+ internal static Constant _GROUP_SIZE_Y = null;
+ internal static Constant _GROUP_SIZE_Z = null;
+
+ internal const string GROUP_ID_X_STRING = "group_id_x";
+ internal const string GROUP_ID_Y_STRING = "group_id_y";
+ internal const string GROUP_ID_Z_STRING = "group_id_z";
+
+ internal static Constant _GROUP_X = null;
+ internal static Constant _GROUP_Y = null;
+ internal static Constant _GROUP_Z = null;
+
+ internal const string NUM_GROUPS_X_STRING = "num_groups_x";
+ internal const string NUM_GROUPS_Y_STRING = "num_groups_y";
+ internal const string NUM_GROUPS_Z_STRING = "num_groups_z";
+
+ internal static Constant _NUM_GROUPS_X = null;
+ internal static Constant _NUM_GROUPS_Y = null;
+ internal static Constant _NUM_GROUPS_Z = null;
+
+ public IRaceInstrumenter RaceInstrumenter;
+
+ public UniformityAnalyser uniformityAnalyser;
+ public MayBePowerOfTwoAnalyser mayBePowerOfTwoAnalyser;
+ public LiveVariableAnalyser liveVariableAnalyser;
+ public ArrayControlFlowAnalyser arrayControlFlowAnalyser;
+ public Dictionary<Implementation, VariableDefinitionAnalysis> varDefAnalyses;
+ public Dictionary<Implementation, ReducedStrengthAnalysis> reducedStrengthAnalyses;
+
+ public GPUVerifier(string filename, Program program, ResolutionContext rc, IRaceInstrumenter raceInstrumenter) : this(filename, program, rc, raceInstrumenter, false)
+ {
+ }
+
+ public GPUVerifier(string filename, Program program, ResolutionContext rc, IRaceInstrumenter raceInstrumenter, bool skipCheck)
+ : base((IErrorSink)null)
+ {
+ this.outputFilename = filename;
+ this.Program = program;
+ this.ResContext = rc;
+ this.RaceInstrumenter = raceInstrumenter;
+ if(!skipCheck)
+ CheckWellFormedness();
+ }
+
+ public void setRaceInstrumenter(IRaceInstrumenter ri)
+ {
+ this.RaceInstrumenter = ri;
+ }
+
+ private void CheckWellFormedness()
+ {
+ int errorCount = Check();
+ if (errorCount != 0)
+ {
+ Console.WriteLine("{0} GPUVerify format errors detected in {1}", errorCount, CommandLineOptions.inputFiles[CommandLineOptions.inputFiles.Count - 1]);
+ Environment.Exit(1);
+ }
+ }
+
+ private Procedure CheckExactlyOneKernelProcedure()
+ {
+ var p = CheckSingleInstanceOfAttributedProcedure("kernel");
+ if (p == null)
+ {
+ Error(Program, "\"kernel\" attribute has not been specified for any procedure. You must mark exactly one procedure with this attribute");
+ }
+
+ return p;
+ }
+
+ private Procedure FindOrCreateBarrierProcedure()
+ {
+ var p = CheckSingleInstanceOfAttributedProcedure("barrier");
+ if (p == null)
+ {
+ p = new Procedure(Token.NoToken, "barrier", new TypeVariableSeq(),
+ new VariableSeq(new Variable[] {
+ new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "__local_fence", new BvType(1)), true),
+ new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "__global_fence", new BvType(1)), true) }),
+ new VariableSeq(),
+ new RequiresSeq(), new IdentifierExprSeq(),
+ new EnsuresSeq(),
+ new QKeyValue(Token.NoToken, "barrier", new List<object>(), null));
+ Program.TopLevelDeclarations.Add(p);
+ ResContext.AddProcedure(p);
+ }
+ return p;
+ }
+
+ private Procedure FindOrCreateBarrierInvariantProcedure() {
+ var p = CheckSingleInstanceOfAttributedProcedure("barrier_invariant");
+ if (p == null) {
+ p = new Procedure(Token.NoToken, "barrier_invariant", new TypeVariableSeq(),
+ new VariableSeq(new Variable[] {
+ new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "__cond",
+ Microsoft.Boogie.Type.Bool), true)
+ }),
+ new VariableSeq(), new RequiresSeq(), new IdentifierExprSeq(),
+ new EnsuresSeq(),
+ new QKeyValue(Token.NoToken, "barrier_invariant", new List<object>(), null));
+ Program.TopLevelDeclarations.Add(p);
+ ResContext.AddProcedure(p);
}
- return true;
- }
-
- internal static bool IsPredicateOrTemp(string lv) {
-
- // We should improve this by having a general convention
- // for names of temporary or predicate variables
-
- if (lv.Length >= 2) {
- if (lv.Substring(0, 1).Equals("p") || lv.Substring(0, 1).Equals("v")) {
- for (int i = 1; i < lv.Length; i++) {
- if (!Char.IsDigit(lv.ToCharArray()[i])) {
- return false;
- }
- }
- return true;
- }
-
+ return p;
+ }
+
+ private Procedure FindOrCreateBarrierInvariantInstantiationProcedure() {
+ var p = CheckSingleInstanceOfAttributedProcedure("barrier_invariant_instantiation");
+ if (p == null) {
+ p = new Procedure(Token.NoToken, "barrier_invariant_instantiation", new TypeVariableSeq(),
+ new VariableSeq(new Variable[] {
+ new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "__t1",
+ new BvType(32)), true),
+ new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "__t2",
+ new BvType(32)), true)
+ }),
+ new VariableSeq(), new RequiresSeq(), new IdentifierExprSeq(),
+ new EnsuresSeq(),
+ new QKeyValue(Token.NoToken, "barrier_invariant_instantiation", new List<object>(), null));
+ Program.TopLevelDeclarations.Add(p);
+ ResContext.AddProcedure(p);
}
+ return p;
+ }
+
+ private Procedure CheckSingleInstanceOfAttributedProcedure(string attribute)
+ {
+ Procedure attributedProcedure = null;
+
+ foreach (Declaration decl in Program.TopLevelDeclarations)
+ {
+ if (!QKeyValue.FindBoolAttribute(decl.Attributes, attribute))
+ {
+ continue;
+ }
+
+ if (decl is Implementation)
+ {
+ continue;
+ }
+
+ if (decl is Procedure)
+ {
+ if (attributedProcedure == null)
+ {
+ attributedProcedure = decl as Procedure;
+ }
+ else
+ {
+ Error(decl, "\"{0}\" attribute specified for procedure {1}, but it has already been specified for procedure {2}", attribute, (decl as Procedure).Name, attributedProcedure.Name);
+ }
+
+ }
+ else
+ {
+ Error(decl, "\"{0}\" attribute can only be applied to a procedure", attribute);
+ }
+ }
+
+ return attributedProcedure;
+ }
+
+ private void CheckLocalVariables()
+ {
+ foreach (LocalVariable LV in KernelImplementation.LocVars)
+ {
+ if (QKeyValue.FindBoolAttribute(LV.Attributes, "group_shared"))
+ {
+ Error(LV.tok, "Local variable must not be marked 'group_shared' -- promote the variable to global scope");
+ }
+ }
+ }
+
+
+ private void ReportMultipleAttributeError(string attribute, IToken first, IToken second)
+ {
+ Error(
+ second,
+ "Can only have one {0} attribute, but previously saw this attribute at ({1}, {2})",
+ attribute,
+ first.filename,
+ first.line, first.col - 1);
+ }
+
+ private bool setConstAttributeField(Constant constInProgram, string attr, ref Constant constFieldRef)
+ {
+ if (QKeyValue.FindBoolAttribute(constInProgram.Attributes, attr))
+ {
+ if (constFieldRef != null)
+ {
+ ReportMultipleAttributeError(attr, constFieldRef.tok, constInProgram.tok);
+ return false;
+ }
+ CheckSpecialConstantType(constInProgram);
+ constFieldRef = constInProgram;
+ }
+ return true;
+ }
+
+ private void MaybeCreateAttributedConst(string attr, ref Constant constFieldRef)
+ {
+ if (constFieldRef == null)
+ {
+ constFieldRef = new Constant(Token.NoToken, new TypedIdent(Token.NoToken, attr, Microsoft.Boogie.Type.GetBvType(32)), /*unique=*/false);
+ constFieldRef.AddAttribute(attr);
+ Program.TopLevelDeclarations.Add(constFieldRef);
+ }
+ }
+
+ private bool FindNonLocalVariables()
+ {
+ bool success = true;
+ foreach (Declaration D in Program.TopLevelDeclarations)
+ {
+ if (D is Variable &&
+ (D as Variable).IsMutable &&
+ (D as Variable).TypedIdent.Type is MapType &&
+ !ReservedNames.Contains((D as Variable).Name))
+ {
+ if (QKeyValue.FindBoolAttribute(D.Attributes, "group_shared"))
+ {
+ KernelArrayInfo.getGroupSharedArrays().Add(D as Variable);
+ }
+ else if (QKeyValue.FindBoolAttribute(D.Attributes, "global"))
+ {
+ KernelArrayInfo.getGlobalArrays().Add(D as Variable);
+ }
+ else
+ {
+ KernelArrayInfo.getPrivateArrays().Add(D as Variable);
+ }
+ }
+ else if (D is Constant)
+ {
+ Constant C = D as Constant;
+
+ success &= setConstAttributeField(C, LOCAL_ID_X_STRING, ref _X);
+ success &= setConstAttributeField(C, LOCAL_ID_Y_STRING, ref _Y);
+ success &= setConstAttributeField(C, LOCAL_ID_Z_STRING, ref _Z);
+
+ success &= setConstAttributeField(C, GROUP_SIZE_X_STRING, ref _GROUP_SIZE_X);
+ success &= setConstAttributeField(C, GROUP_SIZE_Y_STRING, ref _GROUP_SIZE_Y);
+ success &= setConstAttributeField(C, GROUP_SIZE_Z_STRING, ref _GROUP_SIZE_Z);
+
+ success &= setConstAttributeField(C, GROUP_ID_X_STRING, ref _GROUP_X);
+ success &= setConstAttributeField(C, GROUP_ID_Y_STRING, ref _GROUP_Y);
+ success &= setConstAttributeField(C, GROUP_ID_Z_STRING, ref _GROUP_Z);
+
+ success &= setConstAttributeField(C, NUM_GROUPS_X_STRING, ref _NUM_GROUPS_X);
+ success &= setConstAttributeField(C, NUM_GROUPS_Y_STRING, ref _NUM_GROUPS_Y);
+ success &= setConstAttributeField(C, NUM_GROUPS_Z_STRING, ref _NUM_GROUPS_Z);
+
+
+ }
+ }
+
+ MaybeCreateAttributedConst(LOCAL_ID_X_STRING, ref _X);
+ MaybeCreateAttributedConst(LOCAL_ID_Y_STRING, ref _Y);
+ MaybeCreateAttributedConst(LOCAL_ID_Z_STRING, ref _Z);
+
+ MaybeCreateAttributedConst(GROUP_SIZE_X_STRING, ref _GROUP_SIZE_X);
+ MaybeCreateAttributedConst(GROUP_SIZE_Y_STRING, ref _GROUP_SIZE_Y);
+ MaybeCreateAttributedConst(GROUP_SIZE_Z_STRING, ref _GROUP_SIZE_Z);
+
+ MaybeCreateAttributedConst(GROUP_ID_X_STRING, ref _GROUP_X);
+ MaybeCreateAttributedConst(GROUP_ID_Y_STRING, ref _GROUP_Y);
+ MaybeCreateAttributedConst(GROUP_ID_Z_STRING, ref _GROUP_Z);
+
+ MaybeCreateAttributedConst(NUM_GROUPS_X_STRING, ref _NUM_GROUPS_X);
+ MaybeCreateAttributedConst(NUM_GROUPS_Y_STRING, ref _NUM_GROUPS_Y);
+ MaybeCreateAttributedConst(NUM_GROUPS_Z_STRING, ref _NUM_GROUPS_Z);
+
+ return success;
+ }
+
+ private void CheckSpecialConstantType(Constant C)
+ {
+ if (!(C.TypedIdent.Type.Equals(Microsoft.Boogie.Type.Int) || C.TypedIdent.Type.Equals(Microsoft.Boogie.Type.GetBvType(32))))
+ {
+ Error(C.tok, "Special constant '" + C.Name + "' must have type 'int' or 'bv32'");
+ }
+ }
+
+ private void GetKernelImplementation()
+ {
+ foreach (Declaration decl in Program.TopLevelDeclarations)
+ {
+ if (!(decl is Implementation))
+ {
+ continue;
+ }
+
+ Implementation Impl = decl as Implementation;
+
+ if (Impl.Proc == KernelProcedure)
+ {
+ KernelImplementation = Impl;
+ break;
+ }
+
+ }
+
+ if (KernelImplementation == null)
+ {
+ Error(Token.NoToken, "*** Error: no implementation of kernel procedure");
+ }
+ }
+
+
+
+
+ protected virtual void CheckKernelImplementation()
+ {
+ CheckKernelParameters();
+ GetKernelImplementation();
+
+ if (KernelImplementation == null)
+ {
+ return;
+ }
+
+ CheckLocalVariables();
+ CheckNoReturns();
+ }
+
+ private void CheckNoReturns()
+ {
+ // TODO!
+ }
+
+ internal void preProcess()
+ {
+ RemoveRedundantReturns();
+
+ RemoveElseIfs();
+
+ PullOutNonLocalAccesses();
+ }
+
+ private void MergeBlocksIntoPredecessors()
+ {
+ foreach (var impl in Program.TopLevelDeclarations.OfType<Implementation>())
+ VC.VCGen.MergeBlocksIntoPredecessors(Program, impl, uniformityAnalyser);
+ }
+
+ internal void doit()
+ {
+ File.Delete(Path.GetFileNameWithoutExtension(CommandLineOptions.inputFiles[0]) + ".loc");
+ if (CommandLineOptions.Unstructured)
+ {
+ Microsoft.Boogie.CommandLineOptions.Clo.PrintUnstructured = 2;
+ }
+
+ if (CommandLineOptions.ShowStages)
+ {
+ emitProgram(outputFilename + "_original");
+ }
+
+ preProcess();
+
+ if (CommandLineOptions.ShowStages) {
+ emitProgram(outputFilename + "_preprocessed");
+ }
+
+ DoLiveVariableAnalysis();
+
+ DoUniformityAnalysis();
- if (lv.Contains("_HAVOC_")) {
- return true;
+ DoVariableDefinitionAnalysis();
+
+ DoReducedStrengthAnalysis();
+
+ DoMayBePowerOfTwoAnalysis();
+
+ DoArrayControlFlowAnalysis();
+
+ if (CommandLineOptions.Inference)
+ {
+ foreach (var proc in Program.TopLevelDeclarations.OfType<Procedure>().ToList())
+ {
+ RaceInstrumenter.DoHoudiniPointerAnalysis(proc);
+ }
+
+ foreach (var impl in Program.TopLevelDeclarations.OfType<Implementation>().ToList())
+ {
+ LoopInvariantGenerator.PreInstrument(this, impl);
+ }
+
+ if (CommandLineOptions.ShowStages) {
+ emitProgram(outputFilename + "_pre_inference");
+ }
+
+ }
+
+ RaceInstrumenter.AddRaceCheckingInstrumentation();
+
+ if (CommandLineOptions.ShowStages)
+ {
+ emitProgram(outputFilename + "_instrumented");
+ }
+
+ AbstractSharedState();
+
+ if (CommandLineOptions.ShowStages)
+ {
+ emitProgram(outputFilename + "_abstracted");
+ }
+
+ MergeBlocksIntoPredecessors();
+
+ if (CommandLineOptions.ShowStages)
+ {
+ emitProgram(outputFilename + "_merged_pre_predication");
+ }
+
+ MakeKernelPredicated();
+
+ if (CommandLineOptions.ShowStages)
+ {
+ emitProgram(outputFilename + "_predicated");
+ }
+
+ MergeBlocksIntoPredecessors();
+
+ if (CommandLineOptions.ShowStages)
+ {
+ emitProgram(outputFilename + "_merged_post_predication");
+ }
+
+ MakeKernelDualised();
+
+ if (CommandLineOptions.ShowStages)
+ {
+ emitProgram(outputFilename + "_dualised");
+ }
+
+ RaceInstrumenter.AddRaceCheckingDeclarations();
+
+ GenerateBarrierImplementation();
+
+ GenerateStandardKernelContract();
+
+ if (CommandLineOptions.ShowStages)
+ {
+ emitProgram(outputFilename + "_ready_to_verify");
+ }
+
+ if (CommandLineOptions.Inference)
+ {
+ ComputeInvariant();
+ }
+
+ emitProgram(outputFilename);
+
+ }
+
+ private void DoMayBePowerOfTwoAnalysis()
+ {
+ mayBePowerOfTwoAnalyser = new MayBePowerOfTwoAnalyser(this);
+ mayBePowerOfTwoAnalyser.Analyse();
+ }
+
+ private void DoArrayControlFlowAnalysis()
+ {
+ arrayControlFlowAnalyser = new ArrayControlFlowAnalyser(this);
+ arrayControlFlowAnalyser.Analyse();
+ }
+
+ private void DoUniformityAnalysis()
+ {
+ var entryPoints = new HashSet<Implementation>();
+ if (CommandLineOptions.DoUniformityAnalysis) {
+ entryPoints.Add(KernelImplementation);
+ }
+
+ var nonUniformVars = new Variable[] { _X, _Y, _Z, _GROUP_X, _GROUP_Y, _GROUP_Z };
+
+ uniformityAnalyser = new UniformityAnalyser(Program, CommandLineOptions.DoUniformityAnalysis, CommandLineOptions.Unstructured,
+ entryPoints, nonUniformVars);
+ uniformityAnalyser.Analyse();
+ }
+
+ private void DoLiveVariableAnalysis()
+ {
+ liveVariableAnalyser = new LiveVariableAnalyser(this);
+ liveVariableAnalyser.Analyse();
+ }
+
+ private void DoVariableDefinitionAnalysis()
+ {
+ varDefAnalyses = Program.TopLevelDeclarations
+ .OfType<Implementation>()
+ .ToDictionary(i => i, i => VariableDefinitionAnalysis.Analyse(this, i));
+ }
+
+ private void DoReducedStrengthAnalysis()
+ {
+ reducedStrengthAnalyses = Program.TopLevelDeclarations
+ .OfType<Implementation>()
+ .ToDictionary(i => i, i => ReducedStrengthAnalysis.Analyse(this, i));
+ }
+
+ private void emitProgram(string filename)
+ {
+ using (TokenTextWriter writer = new TokenTextWriter(filename + ".bpl"))
+ {
+ Program.Emit(writer);
+ }
+ }
+
+ private void ComputeInvariant()
+ {
+ for (int i = 0; i < Program.TopLevelDeclarations.Count; i++)
+ {
+ if (Program.TopLevelDeclarations[i] is Implementation)
+ {
+
+ Implementation Impl = Program.TopLevelDeclarations[i] as Implementation;
+
+ List<Expr> UserSuppliedInvariants = GetUserSuppliedInvariants(Impl.Name);
+
+ LoopInvariantGenerator.PostInstrument(this, Impl, UserSuppliedInvariants);
+
+ Procedure Proc = Impl.Proc;
+
+ if (QKeyValue.FindIntAttribute(Proc.Attributes, "inline", -1) == 1)
+ {
+ continue;
+ }
+
+ if (Proc == KernelProcedure)
+ {
+ continue;
+ }
+
+ AddCandidateRequires(Proc);
+ RaceInstrumenter.AddRaceCheckingCandidateRequires(Proc);
+ AddUserSuppliedCandidateRequires(Proc, UserSuppliedInvariants);
+
+ AddCandidateEnsures(Proc);
+ RaceInstrumenter.AddRaceCheckingCandidateEnsures(Proc);
+ AddUserSuppliedCandidateEnsures(Proc, UserSuppliedInvariants);
+
+ }
+
+
+ }
+
+ }
+
+ private void AddCandidateEnsures(Procedure Proc)
+ {
+ HashSet<string> names = new HashSet<String>();
+ foreach (Variable v in Proc.OutParams)
+ {
+ names.Add(StripThreadIdentifier(v.Name));
+ }
+
+ foreach (string name in names)
+ {
+ if (!uniformityAnalyser.IsUniform(Proc.Name, name))
+ {
+ AddEqualityCandidateEnsures(Proc, new LocalVariable(Proc.tok, new TypedIdent(Proc.tok, name, Microsoft.Boogie.Type.Int)));
+ }
+ }
+
+ }
+
+ private void AddCandidateRequires(Procedure Proc)
+ {
+ HashSet<string> names = new HashSet<String>();
+ foreach (Variable v in Proc.InParams)
+ {
+ names.Add(StripThreadIdentifier(v.Name));
+ }
+
+ foreach (string name in names)
+ {
+
+ if (IsPredicateOrTemp(name))
+ {
+ Debug.Assert(name.Equals("_P"));
+ Debug.Assert(!uniformityAnalyser.IsUniform(Proc.Name));
+ AddCandidateRequires(Proc, Expr.Eq(
+ new IdentifierExpr(Proc.tok, new LocalVariable(Proc.tok, new TypedIdent(Proc.tok, name + "$1", Microsoft.Boogie.Type.Bool))),
+ new IdentifierExpr(Proc.tok, new LocalVariable(Proc.tok, new TypedIdent(Proc.tok, name + "$2", Microsoft.Boogie.Type.Bool)))
+ ));
+ }
+ else
+ {
+ if (!uniformityAnalyser.IsUniform(Proc.Name, name))
+ {
+ if (!uniformityAnalyser.IsUniform(Proc.Name))
+ {
+ AddPredicatedEqualityCandidateRequires(Proc, new LocalVariable(Proc.tok, new TypedIdent(Proc.tok, name, Microsoft.Boogie.Type.Int)));
+ }
+ AddEqualityCandidateRequires(Proc, new LocalVariable(Proc.tok, new TypedIdent(Proc.tok, name, Microsoft.Boogie.Type.Int)));
+ }
+ }
+ }
+
+ }
+
+ private void AddPredicatedEqualityCandidateRequires(Procedure Proc, Variable v)
+ {
+ AddCandidateRequires(Proc, Expr.Imp(
+ Expr.And(
+ new IdentifierExpr(Proc.tok, new LocalVariable(Proc.tok, new TypedIdent(Proc.tok, "_P$1", Microsoft.Boogie.Type.Bool))),
+ new IdentifierExpr(Proc.tok, new LocalVariable(Proc.tok, new TypedIdent(Proc.tok, "_P$2", Microsoft.Boogie.Type.Bool)))
+ ),
+ Expr.Eq(
+ new IdentifierExpr(Proc.tok, new VariableDualiser(1, uniformityAnalyser, Proc.Name).VisitVariable(v.Clone() as Variable)),
+ new IdentifierExpr(Proc.tok, new VariableDualiser(2, uniformityAnalyser, Proc.Name).VisitVariable(v.Clone() as Variable))
+ )
+ ));
+ }
+
+ private void AddEqualityCandidateRequires(Procedure Proc, Variable v)
+ {
+ AddCandidateRequires(Proc,
+ Expr.Eq(
+ new IdentifierExpr(Proc.tok, new VariableDualiser(1, uniformityAnalyser, Proc.Name).VisitVariable(v.Clone() as Variable)),
+ new IdentifierExpr(Proc.tok, new VariableDualiser(2, uniformityAnalyser, Proc.Name).VisitVariable(v.Clone() as Variable))
+ )
+ );
+ }
+
+ private void AddEqualityCandidateEnsures(Procedure Proc, Variable v)
+ {
+ AddCandidateEnsures(Proc,
+ Expr.Eq(
+ new IdentifierExpr(Proc.tok, new VariableDualiser(1, uniformityAnalyser, Proc.Name).VisitVariable(v.Clone() as Variable)),
+ new IdentifierExpr(Proc.tok, new VariableDualiser(2, uniformityAnalyser, Proc.Name).VisitVariable(v.Clone() as Variable))
+ ));
+ }
+
+
+ private void AddUserSuppliedCandidateRequires(Procedure Proc, List<Expr> UserSuppliedInvariants)
+ {
+ foreach (Expr e in UserSuppliedInvariants)
+ {
+ Requires r = new Requires(false, e);
+ Proc.Requires.Add(r);
+ bool OK = ProgramIsOK(Proc);
+ Proc.Requires.Remove(r);
+ if (OK)
+ {
+ AddCandidateRequires(Proc, e);
+ }
+ }
+ }
+
+ private void AddUserSuppliedCandidateEnsures(Procedure Proc, List<Expr> UserSuppliedInvariants)
+ {
+ foreach (Expr e in UserSuppliedInvariants)
+ {
+ Ensures ens = new Ensures(false, e);
+ Proc.Ensures.Add(ens);
+ bool OK = ProgramIsOK(Proc);
+ Proc.Ensures.Remove(ens);
+ if (OK)
+ {
+ AddCandidateEnsures(Proc, e);
+ }
+ }
+ }
+
+
+
+ internal void AddCandidateRequires(Procedure Proc, Expr e)
+ {
+ Constant ExistentialBooleanConstant = Program.MakeExistentialBoolean();
+ IdentifierExpr ExistentialBoolean = new IdentifierExpr(Proc.tok, ExistentialBooleanConstant);
+ Proc.Requires.Add(new Requires(false, Expr.Imp(ExistentialBoolean, e)));
+ }
+
+ internal void AddCandidateEnsures(Procedure Proc, Expr e)
+ {
+ Constant ExistentialBooleanConstant = Program.MakeExistentialBoolean();
+ IdentifierExpr ExistentialBoolean = new IdentifierExpr(Proc.tok, ExistentialBooleanConstant);
+ Proc.Ensures.Add(new Ensures(false, Expr.Imp(ExistentialBoolean, e)));
+ }
+
+ private List<Expr> GetUserSuppliedInvariants(string ProcedureName)
+ {
+ List<Expr> result = new List<Expr>();
+
+ if (CommandLineOptions.invariantsFile == null)
+ {
+ return result;
+ }
+
+ StreamReader sr = new StreamReader(new FileStream(CommandLineOptions.invariantsFile, FileMode.Open, FileAccess.Read));
+ string line;
+ int lineNumber = 1;
+ while ((line = sr.ReadLine()) != null)
+ {
+ string[] components = line.Split(':');
+
+ if (components.Length != 1 && components.Length != 2)
+ {
+ Console.WriteLine("Ignoring badly formed candidate invariant '" + line + "' at '" + CommandLineOptions.invariantsFile + "' line " + lineNumber);
+ continue;
+ }
+
+ if (components.Length == 2)
+ {
+ if (!components[0].Trim().Equals(ProcedureName))
+ {
+ continue;
+ }
+
+ line = components[1];
+ }
+
+ string temp_program_text = "axiom (" + line + ");";
+ TokenTextWriter writer = new TokenTextWriter("temp_out.bpl");
+ writer.WriteLine(temp_program_text);
+ writer.Close();
+
+ Program temp_program = GPUVerify.ParseBoogieProgram(new List<string>(new string[] { "temp_out.bpl" }), false);
+
+ if (null == temp_program)
+ {
+ Console.WriteLine("Ignoring badly formed candidate invariant '" + line + "' at '" + CommandLineOptions.invariantsFile + "' line " + lineNumber);
+ }
+ else
+ {
+ Debug.Assert(temp_program.TopLevelDeclarations[0] is Axiom);
+ result.Add((temp_program.TopLevelDeclarations[0] as Axiom).Expr);
+ }
+
+ lineNumber++;
+ }
+
+ return result;
+ }
+
+ internal bool ContainsNamedVariable(HashSet<Variable> variables, string name)
+ {
+ foreach(Variable v in variables)
+ {
+ if(StripThreadIdentifier(v.Name) == name)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ internal static bool IsPredicate(string v) {
+ if (v.Length < 2) {
+ return false;
+ }
+ if (!v.Substring(0, 1).Equals("p")) {
+ return false;
+ }
+ for (int i = 1; i < v.Length; i++) {
+ if (!Char.IsDigit(v.ToCharArray()[i])) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ internal static bool IsPredicateOrTemp(string lv) {
+
+ // We should improve this by having a general convention
+ // for names of temporary or predicate variables
+
+ if (lv.Length >= 2) {
+ if (lv.Substring(0, 1).Equals("p") || lv.Substring(0, 1).Equals("v")) {
+ for (int i = 1; i < lv.Length; i++) {
+ if (!Char.IsDigit(lv.ToCharArray()[i])) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ }
+
+ if (lv.Contains("_HAVOC_")) {
+ return true;
+ }
+
+ return (lv.Length >= 2 && lv.Substring(0,2).Equals("_P")) ||
+ (lv.Length > 3 && lv.Substring(0,3).Equals("_LC")) ||
+ (lv.Length > 5 && lv.Substring(0,5).Equals("_temp"));
+ }
+
+
+
+
+ internal bool ProgramIsOK(Declaration d)
+ {
+ Debug.Assert(d is Procedure || d is Implementation);
+ TokenTextWriter writer = new TokenTextWriter("temp_out.bpl");
+ List<Declaration> RealDecls = Program.TopLevelDeclarations;
+ List<Declaration> TempDecls = new List<Declaration>();
+ foreach (Declaration d2 in RealDecls)
+ {
+ if (d is Procedure)
+ {
+ if ((d == d2) || !(d2 is Implementation || d2 is Procedure))
+ {
+ TempDecls.Add(d2);
+ }
+ }
+ else if (d is Implementation)
+ {
+ if ((d == d2) || !(d2 is Implementation))
+ {
+ TempDecls.Add(d2);
+ }
+ }
+ }
+ Program.TopLevelDeclarations = TempDecls;
+ Program.Emit(writer);
+ writer.Close();
+ Program.TopLevelDeclarations = RealDecls;
+ Program temp_program = GPUVerify.ParseBoogieProgram(new List<string>(new string[] { "temp_out.bpl" }), false);
+
+ if (temp_program == null)
+ {
+ return false;
+ }
+
+ if (temp_program.Resolve() != 0)
+ {
+ return false;
+ }
+
+ if (temp_program.Typecheck() != 0)
+ {
+ return false;
+ }
+ return true;
+ }
+
+
+
+ public static Microsoft.Boogie.Type GetTypeOfIdX()
+ {
+ Contract.Requires(_X != null);
+ return _X.TypedIdent.Type;
+ }
+
+ public static Microsoft.Boogie.Type GetTypeOfIdY()
+ {
+ Contract.Requires(_Y != null);
+ return _Y.TypedIdent.Type;
+ }
+
+ public static Microsoft.Boogie.Type GetTypeOfIdZ()
+ {
+ Contract.Requires(_Z != null);
+ return _Z.TypedIdent.Type;
+ }
+
+ public static Microsoft.Boogie.Type GetTypeOfId(string dimension)
+ {
+ Contract.Requires(dimension.Equals("X") || dimension.Equals("Y") || dimension.Equals("Z"));
+ if (dimension.Equals("X")) return GetTypeOfIdX();
+ if (dimension.Equals("Y")) return GetTypeOfIdY();
+ if (dimension.Equals("Z")) return GetTypeOfIdZ();
+ Debug.Assert(false);
+ return null;
+ }
+
+ public bool KernelHasIdX()
+ {
+ return _X != null;
+ }
+
+ public bool KernelHasIdY()
+ {
+ return _Y != null;
+ }
+
+ public bool KernelHasIdZ()
+ {
+ return _Z != null;
+ }
+
+ public bool KernelHasGroupIdX()
+ {
+ return _GROUP_X != null;
+ }
+
+ public bool KernelHasGroupIdY()
+ {
+ return _GROUP_Y != null;
+ }
+
+ public bool KernelHasGroupIdZ()
+ {
+ return _GROUP_Z != null;
+ }
+
+ public bool KernelHasNumGroupsX()
+ {
+ return _NUM_GROUPS_X != null;
+ }
+
+ public bool KernelHasNumGroupsY()
+ {
+ return _NUM_GROUPS_Y != null;
+ }
+
+ public bool KernelHasNumGroupsZ()
+ {
+ return _NUM_GROUPS_Z != null;
+ }
+
+ public bool KernelHasGroupSizeX()
+ {
+ return _GROUP_SIZE_X != null;
+ }
+
+ public bool KernelHasGroupSizeY()
+ {
+ return _GROUP_SIZE_Y != null;
+ }
+
+ public bool KernelHasGroupSizeZ()
+ {
+ return _GROUP_SIZE_Z != null;
+ }
+
+ internal static string StripThreadIdentifier(string p, out int id)
+ {
+ if (p.EndsWith("$1"))
+ {
+ id = 1;
+ return p.Substring(0, p.Length - 2);
+ }
+ if (p.EndsWith("$2"))
+ {
+ id = 2;
+ return p.Substring(0, p.Length - 2);
+ }
+
+ id = 0;
+ return p;
+ }
+
+ internal static string StripThreadIdentifier(string p)
+ {
+ int id;
+ return StripThreadIdentifier(p, out id);
+ }
+
+ private void GenerateStandardKernelContract()
+ {
+ RaceInstrumenter.AddKernelPrecondition();
+
+ IToken tok = KernelImplementation.tok;
+
+ GeneratePreconditionsForDimension(tok, "X");
+ GeneratePreconditionsForDimension(tok, "Y");
+ GeneratePreconditionsForDimension(tok, "Z");
+
+ RaceInstrumenter.AddStandardSourceVariablePreconditions();
+ RaceInstrumenter.AddStandardSourceVariablePostconditions();
+
+ foreach (Declaration D in Program.TopLevelDeclarations)
+ {
+ if (!(D is Procedure))
+ {
+ continue;
+ }
+ Procedure Proc = D as Procedure;
+ if (QKeyValue.FindIntAttribute(Proc.Attributes, "inline", -1) == 1)
+ {
+ continue;
+ }
+
+ Expr DistinctLocalIds =
+ Expr.Or(
+ Expr.Or(
+ Expr.Neq(
+ new IdentifierExpr(tok, MakeThreadId("X", 1)),
+ new IdentifierExpr(tok, MakeThreadId("X", 2))
+ ),
+ Expr.Neq(
+ new IdentifierExpr(tok, MakeThreadId("Y", 1)),
+ new IdentifierExpr(tok, MakeThreadId("Y", 2))
+ )
+ ),
+ Expr.Neq(
+ new IdentifierExpr(tok, MakeThreadId("Z", 1)),
+ new IdentifierExpr(tok, MakeThreadId("Z", 2))
+ )
+ );
+
+ Proc.Requires.Add(new Requires(false, Expr.Imp(ThreadsInSameGroup(), DistinctLocalIds)));
+
+ if (CommandLineOptions.OnlyIntraGroupRaceChecking)
+ {
+ Proc.Requires.Add(new Requires(false, ThreadsInSameGroup()));
+ }
+
+ if (Proc == KernelProcedure)
+ {
+ bool foundNonUniform = false;
+ int indexOfFirstNonUniformParameter;
+ for (indexOfFirstNonUniformParameter = 0; indexOfFirstNonUniformParameter < Proc.InParams.Length; indexOfFirstNonUniformParameter++)
+ {
+ if (!uniformityAnalyser.IsUniform(Proc.Name, StripThreadIdentifier(Proc.InParams[indexOfFirstNonUniformParameter].Name)))
+ {
+ foundNonUniform = true;
+ break;
+ }
+ }
+
+ if (foundNonUniform)
+ {
+ // I have a feeling this will never be reachable!!!
+ int numberOfNonUniformParameters = (Proc.InParams.Length - indexOfFirstNonUniformParameter) / 2;
+ for (int i = indexOfFirstNonUniformParameter; i < numberOfNonUniformParameters; i++)
+ {
+ Proc.Requires.Add(new Requires(false,
+ Expr.Eq(new IdentifierExpr(Proc.InParams[i].tok, Proc.InParams[i]),
+ new IdentifierExpr(Proc.InParams[i + numberOfNonUniformParameters].tok, Proc.InParams[i + numberOfNonUniformParameters]))));
+ }
+ }
+ }
+
+ }
+
+ foreach (Declaration D in Program.TopLevelDeclarations)
+ {
+ if (!(D is Implementation))
+ {
+ continue;
+ }
+ Implementation Impl = D as Implementation;
+
+ foreach (IRegion subregion in RootRegion(Impl).SubRegions())
+ {
+ RaceInstrumenter.AddSourceLocationLoopInvariants(Impl, subregion);
+ }
+ }
+
+ foreach (Declaration D in Program.TopLevelDeclarations)
+ {
+ if (!(D is Implementation))
+ {
+ continue;
+ }
+ Implementation Impl = D as Implementation;
+
+ if (QKeyValue.FindIntAttribute(Impl.Proc.Attributes, "inline", -1) == 1)
+ {
+ continue;
+ }
+ if (Impl.Proc == KernelProcedure)
+ {
+ continue;
+ }
+
+ new EnsureDisabledThreadHasNoEffectInstrumenter(this, Impl).instrument();
+
+ }
+
+ }
+
+ internal static Expr ThreadsInSameGroup()
+ {
+ return Expr.And(
+ Expr.And(
+ Expr.Eq(
+ new IdentifierExpr(Token.NoToken, MakeGroupId("X", 1)),
+ new IdentifierExpr(Token.NoToken, MakeGroupId("X", 2))
+ ),
+ Expr.Eq(
+ new IdentifierExpr(Token.NoToken, MakeGroupId("Y", 1)),
+ new IdentifierExpr(Token.NoToken, MakeGroupId("Y", 2))
+ )
+ ),
+ Expr.Eq(
+ new IdentifierExpr(Token.NoToken, MakeGroupId("Z", 1)),
+ new IdentifierExpr(Token.NoToken, MakeGroupId("Z", 2))
+ )
+ );
+ }
+
+ internal static void AddInvariantToAllLoops(Expr Invariant, StmtList stmtList)
+ {
+ foreach (BigBlock bb in stmtList.BigBlocks)
+ {
+ AddInvariantToAllLoops(Invariant, bb);
+ }
+ }
+
+ internal static void AddInvariantToAllLoops(Expr Invariant, BigBlock bb)
+ {
+ if (bb.ec is WhileCmd)
+ {
+ WhileCmd wc = bb.ec as WhileCmd;
+ wc.Invariants.Add(new AssertCmd(wc.tok, Invariant));
+ AddInvariantToAllLoops(Invariant, wc.Body);
+ }
+ Debug.Assert(!(bb.ec is IfCmd));
+ }
+
+ internal static int GetThreadSuffix(string p)
+ {
+ return Int32.Parse(p.Substring(p.IndexOf("$") + 1, p.Length - (p.IndexOf("$") + 1)));
+ }
+
+ private void GeneratePreconditionsForDimension(IToken tok, String dimension)
+ {
+ foreach (Declaration D in Program.TopLevelDeclarations.ToList())
+ {
+ if (!(D is Procedure))
+ {
+ continue;
+ }
+ Procedure Proc = D as Procedure;
+ if (QKeyValue.FindIntAttribute(Proc.Attributes, "inline", -1) == 1)
+ {
+ continue;
+ }
+
+ Expr GroupSizePositive;
+ Expr NumGroupsPositive;
+ Expr GroupIdNonNegative;
+ Expr GroupIdLessThanNumGroups;
+
+ if (GetTypeOfId(dimension).Equals(Microsoft.Boogie.Type.GetBvType(32)))
+ {
+ GroupSizePositive = MakeBVSgt(new IdentifierExpr(tok, GetGroupSize(dimension)), ZeroBV());
+ NumGroupsPositive = MakeBVSgt(new IdentifierExpr(tok, GetNumGroups(dimension)), ZeroBV());
+ GroupIdNonNegative = MakeBVSge(new IdentifierExpr(tok, GetGroupId(dimension)), ZeroBV());
+ GroupIdLessThanNumGroups = MakeBVSlt(new IdentifierExpr(tok, GetGroupId(dimension)), new IdentifierExpr(tok, GetNumGroups(dimension)));
+ }
+ else
+ {
+ GroupSizePositive = Expr.Gt(new IdentifierExpr(tok, GetGroupSize(dimension)), Zero());
+ NumGroupsPositive = Expr.Gt(new IdentifierExpr(tok, GetNumGroups(dimension)), Zero());
+ GroupIdNonNegative = Expr.Ge(new IdentifierExpr(tok, GetGroupId(dimension)), Zero());
+ GroupIdLessThanNumGroups = Expr.Lt(new IdentifierExpr(tok, GetGroupId(dimension)), new IdentifierExpr(tok, GetNumGroups(dimension)));
+ }
+
+ Proc.Requires.Add(new Requires(false, GroupSizePositive));
+ Proc.Requires.Add(new Requires(false, NumGroupsPositive));
+ Proc.Requires.Add(new Requires(false, new VariableDualiser(1, null, null).VisitExpr(GroupIdNonNegative)));
+ Proc.Requires.Add(new Requires(false, new VariableDualiser(2, null, null).VisitExpr(GroupIdNonNegative)));
+ Proc.Requires.Add(new Requires(false, new VariableDualiser(1, null, null).VisitExpr(GroupIdLessThanNumGroups)));
+ Proc.Requires.Add(new Requires(false, new VariableDualiser(2, null, null).VisitExpr(GroupIdLessThanNumGroups)));
+
+ Expr ThreadIdNonNegative =
+ GetTypeOfId(dimension).Equals(Microsoft.Boogie.Type.GetBvType(32)) ?
+ MakeBVSge(new IdentifierExpr(tok, MakeThreadId(dimension)), ZeroBV())
+ :
+ Expr.Ge(new IdentifierExpr(tok, MakeThreadId(dimension)), Zero());
+ Expr ThreadIdLessThanGroupSize =
+ GetTypeOfId(dimension).Equals(Microsoft.Boogie.Type.GetBvType(32)) ?
+ MakeBVSlt(new IdentifierExpr(tok, MakeThreadId(dimension)), new IdentifierExpr(tok, GetGroupSize(dimension)))
+ :
+ Expr.Lt(new IdentifierExpr(tok, MakeThreadId(dimension)), new IdentifierExpr(tok, GetGroupSize(dimension)));
+
+ Proc.Requires.Add(new Requires(false, new VariableDualiser(1, null, null).VisitExpr(ThreadIdNonNegative)));
+ Proc.Requires.Add(new Requires(false, new VariableDualiser(2, null, null).VisitExpr(ThreadIdNonNegative)));
+ Proc.Requires.Add(new Requires(false, new VariableDualiser(1, null, null).VisitExpr(ThreadIdLessThanGroupSize)));
+ Proc.Requires.Add(new Requires(false, new VariableDualiser(2, null, null).VisitExpr(ThreadIdLessThanGroupSize)));
+
+ }
+
+ }
+
+ private Function GetOrCreateBVFunction(string functionName, string smtName, Microsoft.Boogie.Type resultType, params Microsoft.Boogie.Type[] argTypes)
+ {
+ Function f = (Function)ResContext.LookUpProcedure(functionName);
+ if (f != null)
+ return f;
+
+ f = new Function(Token.NoToken, functionName,
+ new VariableSeq(argTypes.Select(t => new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, "", t))).ToArray()),
+ new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, "", resultType)));
+ f.AddAttribute("bvbuiltin", smtName);
+ Program.TopLevelDeclarations.Add(f);
+ ResContext.AddProcedure(f);
+ return f;
+ }
+
+ private Expr MakeBVFunctionCall(string functionName, string smtName, Microsoft.Boogie.Type resultType, params Expr[] args)
+ {
+ Function f = GetOrCreateBVFunction(functionName, smtName, resultType, args.Select(a => a.Type).ToArray());
+ var e = new NAryExpr(Token.NoToken, new FunctionCall(f), new ExprSeq(args));
+ e.Type = resultType;
+ return e;
+ }
+
+ private Expr MakeBitVectorBinaryBoolean(string suffix, string smtName, Expr lhs, Expr rhs)
+ {
+ return MakeBVFunctionCall("BV" + lhs.Type.BvBits + "_" + suffix, smtName, Microsoft.Boogie.Type.Bool, lhs, rhs);
+ }
+
+ private Expr MakeBitVectorBinaryBitVector(string suffix, string smtName, Expr lhs, Expr rhs)
+ {
+ return MakeBVFunctionCall("BV" + lhs.Type.BvBits + "_" + suffix, smtName, lhs.Type, lhs, rhs);
+ }
+
+ internal Expr MakeBVSlt(Expr lhs, Expr rhs) { return MakeBitVectorBinaryBoolean("SLT", "bvslt", lhs, rhs); }
+ internal Expr MakeBVSgt(Expr lhs, Expr rhs) { return MakeBitVectorBinaryBoolean("SGT", "bvsgt", lhs, rhs); }
+ internal Expr MakeBVSge(Expr lhs, Expr rhs) { return MakeBitVectorBinaryBoolean("SGE", "bvsge", lhs, rhs); }
+
+ internal Expr MakeBVAnd(Expr lhs, Expr rhs) { return MakeBitVectorBinaryBitVector("AND", "bvand", lhs, rhs); }
+ internal Expr MakeBVAdd(Expr lhs, Expr rhs) { return MakeBitVectorBinaryBitVector("ADD", "bvadd", lhs, rhs); }
+ internal Expr MakeBVSub(Expr lhs, Expr rhs) { return MakeBitVectorBinaryBitVector("SUB", "bvsub", lhs, rhs); }
+ internal Expr MakeBVMul(Expr lhs, Expr rhs) { return MakeBitVectorBinaryBitVector("MUL", "bvmul", lhs, rhs); }
+ internal Expr MakeBVURem(Expr lhs, Expr rhs) { return MakeBitVectorBinaryBitVector("UREM", "bvurem", lhs, rhs); }
+
+ internal static Expr MakeBitVectorBinaryBoolean(string functionName, Expr lhs, Expr rhs)
+ {
+ return new NAryExpr(lhs.tok, new FunctionCall(new Function(lhs.tok, functionName, new VariableSeq(new Variable[] {
+ new LocalVariable(lhs.tok, new TypedIdent(lhs.tok, "arg1", Microsoft.Boogie.Type.GetBvType(32))),
+ new LocalVariable(lhs.tok, new TypedIdent(lhs.tok, "arg2", Microsoft.Boogie.Type.GetBvType(32)))
+ }), new LocalVariable(lhs.tok, new TypedIdent(lhs.tok, "result", Microsoft.Boogie.Type.Bool)))), new ExprSeq(new Expr[] { lhs, rhs }));
+ }
+
+ internal static Expr MakeBitVectorBinaryBitVector(string functionName, Expr lhs, Expr rhs)
+ {
+ return new NAryExpr(lhs.tok, new FunctionCall(new Function(lhs.tok, functionName, new VariableSeq(new Variable[] {
+ new LocalVariable(lhs.tok, new TypedIdent(lhs.tok, "arg1", Microsoft.Boogie.Type.GetBvType(32))),
+ new LocalVariable(lhs.tok, new TypedIdent(lhs.tok, "arg2", Microsoft.Boogie.Type.GetBvType(32)))
+ }), new LocalVariable(lhs.tok, new TypedIdent(lhs.tok, "result", Microsoft.Boogie.Type.GetBvType(32))))), new ExprSeq(new Expr[] { lhs, rhs }));
+ }
+
+ private static bool IsBVFunctionCall(Expr e, string smtName, out ExprSeq args)
+ {
+ args = null;
+ var ne = e as NAryExpr;
+ if (ne == null)
+ return false;
+
+ var fc = ne.Fun as FunctionCall;
+ if (fc == null)
+ return false;
+
+ string bvBuiltin = QKeyValue.FindStringAttribute(fc.Func.Attributes, "bvbuiltin");
+ if (bvBuiltin == smtName)
+ {
+ args = ne.Args;
+ return true;
+ }
+
+ return false;
+ }
+
+ private static bool IsBVFunctionCall(Expr e, string smtName, out Expr lhs, out Expr rhs)
+ {
+ ExprSeq es;
+ if (IsBVFunctionCall(e, smtName, out es))
+ {
+ lhs = es[0]; rhs = es[1];
+ return true;
+ }
+ lhs = null; rhs = null;
+ return false;
+ }
+
+ internal static bool IsBVAdd(Expr e, out Expr lhs, out Expr rhs) { return IsBVFunctionCall(e, "bvadd", out lhs, out rhs); }
+ internal static bool IsBVMul(Expr e, out Expr lhs, out Expr rhs) { return IsBVFunctionCall(e, "bvmul", out lhs, out rhs); }
+
+ internal Constant GetGroupSize(string dimension)
+ {
+ Contract.Requires(dimension.Equals("X") || dimension.Equals("Y") || dimension.Equals("Z"));
+ if (dimension.Equals("X")) return _GROUP_SIZE_X;
+ if (dimension.Equals("Y")) return _GROUP_SIZE_Y;
+ if (dimension.Equals("Z")) return _GROUP_SIZE_Z;
+ Debug.Assert(false);
+ return null;
+ }
+
+ internal Constant GetNumGroups(string dimension)
+ {
+ Contract.Requires(dimension.Equals("X") || dimension.Equals("Y") || dimension.Equals("Z"));
+ if (dimension.Equals("X")) return _NUM_GROUPS_X;
+ if (dimension.Equals("Y")) return _NUM_GROUPS_Y;
+ if (dimension.Equals("Z")) return _NUM_GROUPS_Z;
+ Debug.Assert(false);
+ return null;
+ }
+
+ internal static Constant MakeThreadId(string dimension)
+ {
+ Contract.Requires(dimension.Equals("X") || dimension.Equals("Y") || dimension.Equals("Z"));
+ string name = null;
+ if (dimension.Equals("X")) name = _X.Name;
+ if (dimension.Equals("Y")) name = _Y.Name;
+ if (dimension.Equals("Z")) name = _Z.Name;
+ Debug.Assert(name != null);
+ return new Constant(Token.NoToken, new TypedIdent(Token.NoToken, name, GetTypeOfId(dimension)));
+ }
+
+ internal static Constant MakeThreadId(string dimension, int number)
+ {
+ Constant resultWithoutThreadId = MakeThreadId(dimension);
+ return new Constant(Token.NoToken, new TypedIdent(
+ Token.NoToken, resultWithoutThreadId.Name + "$" + number, GetTypeOfId(dimension)));
+ }
+
+ internal static Constant GetGroupId(string dimension)
+ {
+ Contract.Requires(dimension.Equals("X") || dimension.Equals("Y") || dimension.Equals("Z"));
+ if (dimension.Equals("X")) return _GROUP_X;
+ if (dimension.Equals("Y")) return _GROUP_Y;
+ if (dimension.Equals("Z")) return _GROUP_Z;
+ Debug.Assert(false);
+ return null;
+ }
+
+ internal static Constant MakeGroupId(string dimension, int number)
+ {
+ Constant resultWithoutThreadId = GetGroupId(dimension);
+ return new Constant(Token.NoToken, new TypedIdent(Token.NoToken, resultWithoutThreadId.Name + "$" + number, GetTypeOfId(dimension)));
+ }
+
+ private static LiteralExpr Zero()
+ {
+ return new LiteralExpr(Token.NoToken, BigNum.FromInt(0));
+ }
+
+ internal static LiteralExpr ZeroBV()
+ {
+ return new LiteralExpr(Token.NoToken, BigNum.FromInt(0), 32);
+ }
+
+
+
+ private void GenerateBarrierImplementation()
+ {
+ IToken tok = BarrierProcedure.tok;
+
+ List<BigBlock> bigblocks = new List<BigBlock>();
+ BigBlock barrierEntryBlock = new BigBlock(tok, "__BarrierImpl", new CmdSeq(), null, null);
+ bigblocks.Add(barrierEntryBlock);
+
+ Debug.Assert((BarrierProcedure.InParams.Length % 2) == 0);
+ int paramsPerThread = BarrierProcedure.InParams.Length / 2;
+ IdentifierExpr P1 = new IdentifierExpr(tok, new LocalVariable(tok, BarrierProcedure.InParams[0].TypedIdent));
+ IdentifierExpr P2 = new IdentifierExpr(tok, new LocalVariable(tok, BarrierProcedure.InParams[paramsPerThread].TypedIdent));
+
+ Expr LocalFence1 = MakeFenceExpr(BarrierProcedure.InParams[1]);
+ Expr LocalFence2 = MakeFenceExpr(BarrierProcedure.InParams[paramsPerThread + 1]);
+
+ Expr GlobalFence1 = MakeFenceExpr(BarrierProcedure.InParams[2]);
+ Expr GlobalFence2 = MakeFenceExpr(BarrierProcedure.InParams[paramsPerThread + 2]);
+
+ Expr DivergenceCondition = Expr.Imp(ThreadsInSameGroup(), Expr.Eq(P1, P2));
+
+ Requires nonDivergenceRequires = new Requires(false, DivergenceCondition);
+ nonDivergenceRequires.Attributes = new QKeyValue(Token.NoToken, "barrier_divergence",
+ new List<object>(new object[] { }), null);
+ BarrierProcedure.Requires.Add(nonDivergenceRequires);
+
+ if (!CommandLineOptions.OnlyDivergence)
+ {
+ List<BigBlock> returnbigblocks = new List<BigBlock>();
+ returnbigblocks.Add(new BigBlock(tok, "__Disabled", new CmdSeq(), null, new ReturnCmd(tok)));
+ StmtList returnstatement = new StmtList(returnbigblocks, BarrierProcedure.tok);
+
+ Expr IfGuard = Expr.Or(Expr.And(Expr.Not(P1), Expr.Not(P2)), Expr.And(ThreadsInSameGroup(), Expr.Or(Expr.Not(P1), Expr.Not(P2))));
+ barrierEntryBlock.ec = new IfCmd(tok, IfGuard, returnstatement, null, null);
+ }
+
+ if(KernelArrayInfo.getGroupSharedArrays().Count > 0) {
+
+ bigblocks.AddRange(
+ MakeResetBlocks(Expr.And(P1, LocalFence1), KernelArrayInfo.getGroupSharedArrays()));
+
+ // This could be relaxed to take into account whether the threads are in different
+ // groups, but for now we keep it relatively simple
+
+ Expr AtLeastOneEnabledWithLocalFence =
+ Expr.Or(Expr.And(P1, LocalFence1), Expr.And(P2, LocalFence2));
+
+ if (SomeArrayModelledNonAdversarially(KernelArrayInfo.getGroupSharedArrays())) {
+ bigblocks.Add(new BigBlock(Token.NoToken, null, new CmdSeq(),
+ new IfCmd(Token.NoToken,
+ AtLeastOneEnabledWithLocalFence,
+ new StmtList(MakeHavocBlocks(KernelArrayInfo.getGroupSharedArrays()), Token.NoToken), null, null), null));
+ }
+ }
+
+ if (KernelArrayInfo.getGlobalArrays().Count > 0)
+ {
+ Expr IfGuard1 = Expr.And(P1, GlobalFence1);
+ Expr IfGuard2 = Expr.And(P2, GlobalFence2);
+
+ bigblocks.AddRange(
+ MakeResetBlocks(Expr.And(P1, GlobalFence1), KernelArrayInfo.getGlobalArrays()));
+
+ Expr ThreadsInSameGroup_BothEnabled_AtLeastOneGlobalFence =
+ Expr.And(Expr.And(GPUVerifier.ThreadsInSameGroup(), Expr.And(P1, P2)), Expr.Or(GlobalFence1, GlobalFence2));
+
+ if (SomeArrayModelledNonAdversarially(KernelArrayInfo.getGlobalArrays())) {
+ bigblocks.Add(new BigBlock(Token.NoToken, null, new CmdSeq(),
+ new IfCmd(Token.NoToken,
+ ThreadsInSameGroup_BothEnabled_AtLeastOneGlobalFence,
+ new StmtList(MakeHavocBlocks(KernelArrayInfo.getGlobalArrays()), Token.NoToken), null, null), null));
+ }
+ }
+
+ StmtList statements = new StmtList(bigblocks, BarrierProcedure.tok);
+ Implementation BarrierImplementation =
+ new Implementation(BarrierProcedure.tok, BarrierProcedure.Name, new TypeVariableSeq(),
+ BarrierProcedure.InParams, BarrierProcedure.OutParams, new VariableSeq(), statements);
+
+ if (CommandLineOptions.Unstructured)
+ BarrierImplementation.Resolve(ResContext);
+
+ BarrierImplementation.AddAttribute("inline", new object[] { new LiteralExpr(tok, BigNum.FromInt(1)) });
+ BarrierProcedure.AddAttribute("inline", new object[] { new LiteralExpr(tok, BigNum.FromInt(1)) });
+
+ BarrierImplementation.Proc = BarrierProcedure;
+
+ Program.TopLevelDeclarations.Add(BarrierImplementation);
+ }
+
+ private static NAryExpr MakeFenceExpr(Variable v) {
+ return Expr.Eq(new IdentifierExpr(Token.NoToken, new LocalVariable(Token.NoToken, v.TypedIdent)),
+ new LiteralExpr(Token.NoToken, BigNum.FromInt(1), 1));
+ }
+
+ private static Expr flagIsSet(Expr Flags, int flag)
+ {
+ return Expr.Eq(new BvExtractExpr(
+ Token.NoToken, Flags, flag, flag - 1),
+ new LiteralExpr(Token.NoToken, BigNum.FromInt(1), 1));
+ }
+
+ private List<BigBlock> MakeResetBlocks(Expr ResetCondition, ICollection<Variable> variables)
+ {
+ Debug.Assert(variables.Count > 0);
+ List<BigBlock> result = new List<BigBlock>();
+ foreach (Variable v in variables)
+ {
+ result.Add(RaceInstrumenter.MakeResetReadWriteSetStatements(v, ResetCondition));
+ }
+ Debug.Assert(result.Count > 0);
+ return result;
+ }
+
+ private List<BigBlock> MakeHavocBlocks(ICollection<Variable> variables) {
+ Debug.Assert(variables.Count > 0);
+ List<BigBlock> result = new List<BigBlock>();
+ foreach (Variable v in variables) {
+ if (!ArrayModelledAdversarially(v)) {
+ result.Add(HavocSharedArray(v));
+ }
}
-
- return (lv.Length >= 2 && lv.Substring(0,2).Equals("_P")) ||
- (lv.Length > 3 && lv.Substring(0,3).Equals("_LC")) ||
- (lv.Length > 5 && lv.Substring(0,5).Equals("_temp"));
- }
-
-
-
-
- internal bool ProgramIsOK(Declaration d)
- {
- Debug.Assert(d is Procedure || d is Implementation);
- TokenTextWriter writer = new TokenTextWriter("temp_out.bpl");
- List<Declaration> RealDecls = Program.TopLevelDeclarations;
- List<Declaration> TempDecls = new List<Declaration>();
- foreach (Declaration d2 in RealDecls)
- {
- if (d is Procedure)
- {
- if ((d == d2) || !(d2 is Implementation || d2 is Procedure))
- {
- TempDecls.Add(d2);
- }
- }
- else if (d is Implementation)
- {
- if ((d == d2) || !(d2 is Implementation))
- {
- TempDecls.Add(d2);
- }
- }
- }
- Program.TopLevelDeclarations = TempDecls;
- Program.Emit(writer);
- writer.Close();
- Program.TopLevelDeclarations = RealDecls;
- Program temp_program = GPUVerify.ParseBoogieProgram(new List<string>(new string[] { "temp_out.bpl" }), false);
-
- if (temp_program == null)
- {
- return false;
- }
-
- if (temp_program.Resolve() != 0)
- {
- return false;
- }
-
- if (temp_program.Typecheck() != 0)
- {
- return false;
- }
- return true;
- }
-
-
-
- public Microsoft.Boogie.Type GetTypeOfIdX()
- {
- Contract.Requires(_X != null);
- return _X.TypedIdent.Type;
- }
-
- public Microsoft.Boogie.Type GetTypeOfIdY()
- {
- Contract.Requires(_Y != null);
- return _Y.TypedIdent.Type;
- }
-
- public Microsoft.Boogie.Type GetTypeOfIdZ()
- {
- Contract.Requires(_Z != null);
- return _Z.TypedIdent.Type;
- }
-
- public Microsoft.Boogie.Type GetTypeOfId(string dimension)
- {
- Contract.Requires(dimension.Equals("X") || dimension.Equals("Y") || dimension.Equals("Z"));
- if (dimension.Equals("X")) return GetTypeOfIdX();
- if (dimension.Equals("Y")) return GetTypeOfIdY();
- if (dimension.Equals("Z")) return GetTypeOfIdZ();
- Debug.Assert(false);
- return null;
- }
-
- public bool KernelHasIdX()
- {
- return _X != null;
- }
-
- public bool KernelHasIdY()
- {
- return _Y != null;
- }
-
- public bool KernelHasIdZ()
- {
- return _Z != null;
- }
-
- public bool KernelHasGroupIdX()
- {
- return _GROUP_X != null;
- }
-
- public bool KernelHasGroupIdY()
- {
- return _GROUP_Y != null;
- }
-
- public bool KernelHasGroupIdZ()
- {
- return _GROUP_Z != null;
- }
-
- public bool KernelHasNumGroupsX()
- {
- return _NUM_GROUPS_X != null;
- }
-
- public bool KernelHasNumGroupsY()
- {
- return _NUM_GROUPS_Y != null;
- }
-
- public bool KernelHasNumGroupsZ()
- {
- return _NUM_GROUPS_Z != null;
- }
-
- public bool KernelHasGroupSizeX()
- {
- return _GROUP_SIZE_X != null;
- }
-
- public bool KernelHasGroupSizeY()
- {
- return _GROUP_SIZE_Y != null;
- }
-
- public bool KernelHasGroupSizeZ()
- {
- return _GROUP_SIZE_Z != null;
- }
-
- internal static string StripThreadIdentifier(string p, out int id)
- {
- if (p.EndsWith("$1"))
- {
- id = 1;
- return p.Substring(0, p.Length - 2);
- }
- if (p.EndsWith("$2"))
- {
- id = 2;
- return p.Substring(0, p.Length - 2);
- }
-
- id = 0;
- return p;
- }
-
- internal static string StripThreadIdentifier(string p)
- {
- int id;
- return StripThreadIdentifier(p, out id);
- }
-
- private void GenerateStandardKernelContract()
- {
- RaceInstrumenter.AddKernelPrecondition();
-
- IToken tok = KernelImplementation.tok;
-
- GeneratePreconditionsForDimension(tok, "X");
- GeneratePreconditionsForDimension(tok, "Y");
- GeneratePreconditionsForDimension(tok, "Z");
-
- foreach (Declaration D in Program.TopLevelDeclarations)
- {
- if (!(D is Procedure))
- {
- continue;
- }
- Procedure Proc = D as Procedure;
- if (QKeyValue.FindIntAttribute(Proc.Attributes, "inline", -1) == 1)
- {
- continue;
- }
-
- Expr DistinctLocalIds =
- Expr.Or(
- Expr.Or(
- Expr.Neq(
- new IdentifierExpr(tok, MakeThreadId(tok, "X", 1)),
- new IdentifierExpr(tok, MakeThreadId(tok, "X", 2))
- ),
- Expr.Neq(
- new IdentifierExpr(tok, MakeThreadId(tok, "Y", 1)),
- new IdentifierExpr(tok, MakeThreadId(tok, "Y", 2))
- )
- ),
- Expr.Neq(
- new IdentifierExpr(tok, MakeThreadId(tok, "Z", 1)),
- new IdentifierExpr(tok, MakeThreadId(tok, "Z", 2))
- )
- );
-
- Proc.Requires.Add(new Requires(false, Expr.Imp(ThreadsInSameGroup(), DistinctLocalIds)));
-
- if (CommandLineOptions.OnlyIntraGroupRaceChecking)
- {
- Proc.Requires.Add(new Requires(false, ThreadsInSameGroup()));
- }
-
- if (Proc == KernelProcedure)
- {
- bool foundNonUniform = false;
- int indexOfFirstNonUniformParameter;
- for (indexOfFirstNonUniformParameter = 0; indexOfFirstNonUniformParameter < Proc.InParams.Length; indexOfFirstNonUniformParameter++)
- {
- if (!uniformityAnalyser.IsUniform(Proc.Name, StripThreadIdentifier(Proc.InParams[indexOfFirstNonUniformParameter].Name)))
- {
- foundNonUniform = true;
- break;
- }
- }
-
- if (foundNonUniform)
- {
- // I have a feeling this will never be reachable!!!
- int numberOfNonUniformParameters = (Proc.InParams.Length - indexOfFirstNonUniformParameter) / 2;
- for (int i = indexOfFirstNonUniformParameter; i < numberOfNonUniformParameters; i++)
- {
- Proc.Requires.Add(new Requires(false,
- Expr.Eq(new IdentifierExpr(Proc.InParams[i].tok, Proc.InParams[i]),
- new IdentifierExpr(Proc.InParams[i + numberOfNonUniformParameters].tok, Proc.InParams[i + numberOfNonUniformParameters]))));
- }
- }
- }
-
- }
-
- foreach (Declaration D in Program.TopLevelDeclarations)
- {
- if (!(D is Implementation))
- {
- continue;
- }
- Implementation Impl = D as Implementation;
-
- foreach (IRegion subregion in RootRegion(Impl).SubRegions())
- {
- RaceInstrumenter.AddSourceLocationLoopInvariants(Impl, subregion);
- }
- }
-
- foreach (Declaration D in Program.TopLevelDeclarations)
- {
- if (!(D is Implementation))
- {
- continue;
- }
- Implementation Impl = D as Implementation;
-
- if (QKeyValue.FindIntAttribute(Impl.Proc.Attributes, "inline", -1) == 1)
- {
- continue;
- }
- if (Impl.Proc == KernelProcedure)
- {
- continue;
- }
-
- new EnsureDisabledThreadHasNoEffectInstrumenter(this, Impl).instrument();
-
- }
-
- }
-
- internal Expr ThreadsInSameGroup()
- {
- return Expr.And(
- Expr.And(
- Expr.Eq(
- new IdentifierExpr(Token.NoToken, MakeGroupId("X", 1)),
- new IdentifierExpr(Token.NoToken, MakeGroupId("X", 2))
- ),
- Expr.Eq(
- new IdentifierExpr(Token.NoToken, MakeGroupId("Y", 1)),
- new IdentifierExpr(Token.NoToken, MakeGroupId("Y", 2))
- )
- ),
- Expr.Eq(
- new IdentifierExpr(Token.NoToken, MakeGroupId("Z", 1)),
- new IdentifierExpr(Token.NoToken, MakeGroupId("Z", 2))
- )
- );
- }
-
- internal static void AddInvariantToAllLoops(Expr Invariant, StmtList stmtList)
- {
- foreach (BigBlock bb in stmtList.BigBlocks)
- {
- AddInvariantToAllLoops(Invariant, bb);
- }
- }
-
- internal static void AddInvariantToAllLoops(Expr Invariant, BigBlock bb)
- {
- if (bb.ec is WhileCmd)
- {
- WhileCmd wc = bb.ec as WhileCmd;
- wc.Invariants.Add(new AssertCmd(wc.tok, Invariant));
- AddInvariantToAllLoops(Invariant, wc.Body);
- }
- Debug.Assert(!(bb.ec is IfCmd));
+ Debug.Assert(result.Count > 0);
+ return result;
}
- internal static int GetThreadSuffix(string p)
- {
- return Int32.Parse(p.Substring(p.IndexOf("$") + 1, p.Length - (p.IndexOf("$") + 1)));
- }
-
- private void GeneratePreconditionsForDimension(IToken tok, String dimension)
- {
- foreach (Declaration D in Program.TopLevelDeclarations.ToList())
- {
- if (!(D is Procedure))
- {
- continue;
- }
- Procedure Proc = D as Procedure;
- if (QKeyValue.FindIntAttribute(Proc.Attributes, "inline", -1) == 1)
- {
- continue;
- }
-
- Expr GroupSizePositive;
- Expr NumGroupsPositive;
- Expr GroupIdNonNegative;
- Expr GroupIdLessThanNumGroups;
-
- if (GetTypeOfId(dimension).Equals(Microsoft.Boogie.Type.GetBvType(32)))
- {
- GroupSizePositive = MakeBVSgt(new IdentifierExpr(tok, GetGroupSize(dimension)), ZeroBV());
- NumGroupsPositive = MakeBVSgt(new IdentifierExpr(tok, GetNumGroups(dimension)), ZeroBV());
- GroupIdNonNegative = MakeBVSge(new IdentifierExpr(tok, GetGroupId(dimension)), ZeroBV());
- GroupIdLessThanNumGroups = MakeBVSlt(new IdentifierExpr(tok, GetGroupId(dimension)), new IdentifierExpr(tok, GetNumGroups(dimension)));
- }
- else
- {
- GroupSizePositive = Expr.Gt(new IdentifierExpr(tok, GetGroupSize(dimension)), Zero());
- NumGroupsPositive = Expr.Gt(new IdentifierExpr(tok, GetNumGroups(dimension)), Zero());
- GroupIdNonNegative = Expr.Ge(new IdentifierExpr(tok, GetGroupId(dimension)), Zero());
- GroupIdLessThanNumGroups = Expr.Lt(new IdentifierExpr(tok, GetGroupId(dimension)), new IdentifierExpr(tok, GetNumGroups(dimension)));
- }
-
- Proc.Requires.Add(new Requires(false, GroupSizePositive));
- Proc.Requires.Add(new Requires(false, NumGroupsPositive));
- Proc.Requires.Add(new Requires(false, new VariableDualiser(1, null, null).VisitExpr(GroupIdNonNegative)));
- Proc.Requires.Add(new Requires(false, new VariableDualiser(2, null, null).VisitExpr(GroupIdNonNegative)));
- Proc.Requires.Add(new Requires(false, new VariableDualiser(1, null, null).VisitExpr(GroupIdLessThanNumGroups)));
- Proc.Requires.Add(new Requires(false, new VariableDualiser(2, null, null).VisitExpr(GroupIdLessThanNumGroups)));
-
- Expr ThreadIdNonNegative =
- GetTypeOfId(dimension).Equals(Microsoft.Boogie.Type.GetBvType(32)) ?
- MakeBVSge(new IdentifierExpr(tok, MakeThreadId(tok, dimension)), ZeroBV())
- :
- Expr.Ge(new IdentifierExpr(tok, MakeThreadId(tok, dimension)), Zero());
- Expr ThreadIdLessThanGroupSize =
- GetTypeOfId(dimension).Equals(Microsoft.Boogie.Type.GetBvType(32)) ?
- MakeBVSlt(new IdentifierExpr(tok, MakeThreadId(tok, dimension)), new IdentifierExpr(tok, GetGroupSize(dimension)))
- :
- Expr.Lt(new IdentifierExpr(tok, MakeThreadId(tok, dimension)), new IdentifierExpr(tok, GetGroupSize(dimension)));
-
- Proc.Requires.Add(new Requires(false, new VariableDualiser(1, null, null).VisitExpr(ThreadIdNonNegative)));
- Proc.Requires.Add(new Requires(false, new VariableDualiser(2, null, null).VisitExpr(ThreadIdNonNegative)));
- Proc.Requires.Add(new Requires(false, new VariableDualiser(1, null, null).VisitExpr(ThreadIdLessThanGroupSize)));
- Proc.Requires.Add(new Requires(false, new VariableDualiser(2, null, null).VisitExpr(ThreadIdLessThanGroupSize)));
-
- }
-
- }
-
- private Function GetOrCreateBVFunction(string functionName, string smtName, Microsoft.Boogie.Type resultType, params Microsoft.Boogie.Type[] argTypes)
- {
- Function f = (Function)ResContext.LookUpProcedure(functionName);
- if (f != null)
- return f;
-
- f = new Function(Token.NoToken, functionName,
- new VariableSeq(argTypes.Select(t => new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, "", t))).ToArray()),
- new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, "", resultType)));
- f.AddAttribute("bvbuiltin", smtName);
- Program.TopLevelDeclarations.Add(f);
- ResContext.AddProcedure(f);
- return f;
- }
-
- private Expr MakeBVFunctionCall(string functionName, string smtName, Microsoft.Boogie.Type resultType, params Expr[] args)
- {
- Function f = GetOrCreateBVFunction(functionName, smtName, resultType, args.Select(a => a.Type).ToArray());
- var e = new NAryExpr(Token.NoToken, new FunctionCall(f), new ExprSeq(args));
- e.Type = resultType;
- return e;
- }
-
- private Expr MakeBitVectorBinaryBoolean(string suffix, string smtName, Expr lhs, Expr rhs)
- {
- return MakeBVFunctionCall("BV" + lhs.Type.BvBits + "_" + suffix, smtName, Microsoft.Boogie.Type.Bool, lhs, rhs);
- }
-
- private Expr MakeBitVectorBinaryBitVector(string suffix, string smtName, Expr lhs, Expr rhs)
- {
- return MakeBVFunctionCall("BV" + lhs.Type.BvBits + "_" + suffix, smtName, lhs.Type, lhs, rhs);
- }
-
- internal Expr MakeBVSlt(Expr lhs, Expr rhs) { return MakeBitVectorBinaryBoolean("SLT", "bvslt", lhs, rhs); }
- internal Expr MakeBVSgt(Expr lhs, Expr rhs) { return MakeBitVectorBinaryBoolean("SGT", "bvsgt", lhs, rhs); }
- internal Expr MakeBVSge(Expr lhs, Expr rhs) { return MakeBitVectorBinaryBoolean("SGE", "bvsge", lhs, rhs); }
-
- internal Expr MakeBVAnd(Expr lhs, Expr rhs) { return MakeBitVectorBinaryBitVector("AND", "bvand", lhs, rhs); }
- internal Expr MakeBVAdd(Expr lhs, Expr rhs) { return MakeBitVectorBinaryBitVector("ADD", "bvadd", lhs, rhs); }
- internal Expr MakeBVSub(Expr lhs, Expr rhs) { return MakeBitVectorBinaryBitVector("SUB", "bvsub", lhs, rhs); }
- internal Expr MakeBVMul(Expr lhs, Expr rhs) { return MakeBitVectorBinaryBitVector("MUL", "bvmul", lhs, rhs); }
- internal Expr MakeBVURem(Expr lhs, Expr rhs) { return MakeBitVectorBinaryBitVector("UREM", "bvurem", lhs, rhs); }
-
- internal static Expr MakeBitVectorBinaryBoolean(string functionName, Expr lhs, Expr rhs)
- {
- return new NAryExpr(lhs.tok, new FunctionCall(new Function(lhs.tok, functionName, new VariableSeq(new Variable[] {
- new LocalVariable(lhs.tok, new TypedIdent(lhs.tok, "arg1", Microsoft.Boogie.Type.GetBvType(32))),
- new LocalVariable(lhs.tok, new TypedIdent(lhs.tok, "arg2", Microsoft.Boogie.Type.GetBvType(32)))
- }), new LocalVariable(lhs.tok, new TypedIdent(lhs.tok, "result", Microsoft.Boogie.Type.Bool)))), new ExprSeq(new Expr[] { lhs, rhs }));
- }
-
- internal static Expr MakeBitVectorBinaryBitVector(string functionName, Expr lhs, Expr rhs)
- {
- return new NAryExpr(lhs.tok, new FunctionCall(new Function(lhs.tok, functionName, new VariableSeq(new Variable[] {
- new LocalVariable(lhs.tok, new TypedIdent(lhs.tok, "arg1", Microsoft.Boogie.Type.GetBvType(32))),
- new LocalVariable(lhs.tok, new TypedIdent(lhs.tok, "arg2", Microsoft.Boogie.Type.GetBvType(32)))
- }), new LocalVariable(lhs.tok, new TypedIdent(lhs.tok, "result", Microsoft.Boogie.Type.GetBvType(32))))), new ExprSeq(new Expr[] { lhs, rhs }));
- }
-
- private static bool IsBVFunctionCall(Expr e, string smtName, out ExprSeq args)
- {
- args = null;
- var ne = e as NAryExpr;
- if (ne == null)
- return false;
-
- var fc = ne.Fun as FunctionCall;
- if (fc == null)
- return false;
-
- string bvBuiltin = QKeyValue.FindStringAttribute(fc.Func.Attributes, "bvbuiltin");
- if (bvBuiltin == smtName)
- {
- args = ne.Args;
- return true;
- }
-
- return false;
- }
-
- private static bool IsBVFunctionCall(Expr e, string smtName, out Expr lhs, out Expr rhs)
- {
- ExprSeq es;
- if (IsBVFunctionCall(e, smtName, out es))
- {
- lhs = es[0]; rhs = es[1];
- return true;
- }
- lhs = null; rhs = null;
- return false;
- }
-
- internal static bool IsBVAdd(Expr e, out Expr lhs, out Expr rhs) { return IsBVFunctionCall(e, "bvadd", out lhs, out rhs); }
- internal static bool IsBVMul(Expr e, out Expr lhs, out Expr rhs) { return IsBVFunctionCall(e, "bvmul", out lhs, out rhs); }
-
- internal Constant GetGroupSize(string dimension)
- {
- Contract.Requires(dimension.Equals("X") || dimension.Equals("Y") || dimension.Equals("Z"));
- if (dimension.Equals("X")) return _GROUP_SIZE_X;
- if (dimension.Equals("Y")) return _GROUP_SIZE_Y;
- if (dimension.Equals("Z")) return _GROUP_SIZE_Z;
- Debug.Assert(false);
- return null;
- }
-
- internal Constant GetNumGroups(string dimension)
- {
- Contract.Requires(dimension.Equals("X") || dimension.Equals("Y") || dimension.Equals("Z"));
- if (dimension.Equals("X")) return _NUM_GROUPS_X;
- if (dimension.Equals("Y")) return _NUM_GROUPS_Y;
- if (dimension.Equals("Z")) return _NUM_GROUPS_Z;
- Debug.Assert(false);
- return null;
- }
-
- internal Constant MakeThreadId(IToken tok, string dimension)
- {
- Contract.Requires(dimension.Equals("X") || dimension.Equals("Y") || dimension.Equals("Z"));
- string name = null;
- if (dimension.Equals("X")) name = _X.Name;
- if (dimension.Equals("Y")) name = _Y.Name;
- if (dimension.Equals("Z")) name = _Z.Name;
- Debug.Assert(name != null);
- return new Constant(tok, new TypedIdent(tok, name, GetTypeOfId(dimension)));
- }
-
- internal Constant MakeThreadId(IToken tok, string dimension, int number)
- {
- Constant resultWithoutThreadId = MakeThreadId(tok, dimension);
- return new Constant(tok, new TypedIdent(tok, resultWithoutThreadId.Name + "$" + number, GetTypeOfId(dimension)));
- }
-
- internal Constant GetGroupId(string dimension)
- {
- Contract.Requires(dimension.Equals("X") || dimension.Equals("Y") || dimension.Equals("Z"));
- if (dimension.Equals("X")) return _GROUP_X;
- if (dimension.Equals("Y")) return _GROUP_Y;
- if (dimension.Equals("Z")) return _GROUP_Z;
- Debug.Assert(false);
- return null;
- }
-
- internal Constant MakeGroupId(string dimension, int number)
- {
- Constant resultWithoutThreadId = GetGroupId(dimension);
- return new Constant(Token.NoToken, new TypedIdent(Token.NoToken, resultWithoutThreadId.Name + "$" + number, GetTypeOfId(dimension)));
- }
-
- private static LiteralExpr Zero()
- {
- return new LiteralExpr(Token.NoToken, BigNum.FromInt(0));
- }
-
- internal static LiteralExpr ZeroBV()
- {
- return new LiteralExpr(Token.NoToken, BigNum.FromInt(0), 32);
- }
-
-
-
- private void GenerateBarrierImplementation()
- {
- IToken tok = BarrierProcedure.tok;
-
- List<BigBlock> bigblocks = new List<BigBlock>();
- BigBlock barrierEntryBlock = new BigBlock(tok, "__BarrierImpl", new CmdSeq(), null, null);
- bigblocks.Add(barrierEntryBlock);
-
- Debug.Assert((BarrierProcedure.InParams.Length % 2) == 0);
- int paramsPerThread = BarrierProcedure.InParams.Length / 2;
- IdentifierExpr P1 = new IdentifierExpr(tok, new LocalVariable(tok, BarrierProcedure.InParams[0].TypedIdent));
- IdentifierExpr P2 = new IdentifierExpr(tok, new LocalVariable(tok, BarrierProcedure.InParams[paramsPerThread].TypedIdent));
-
- Expr LocalFence1 = MakeFenceExpr(BarrierProcedure.InParams[1]);
- Expr LocalFence2 = MakeFenceExpr(BarrierProcedure.InParams[paramsPerThread + 1]);
-
- Expr GlobalFence1 = MakeFenceExpr(BarrierProcedure.InParams[2]);
- Expr GlobalFence2 = MakeFenceExpr(BarrierProcedure.InParams[paramsPerThread + 2]);
-
- Expr DivergenceCondition = Expr.Imp(ThreadsInSameGroup(), Expr.Eq(P1, P2));
-
- Requires nonDivergenceRequires = new Requires(false, DivergenceCondition);
- nonDivergenceRequires.Attributes = new QKeyValue(Token.NoToken, "barrier_divergence",
- new List<object>(new object[] { }), null);
- BarrierProcedure.Requires.Add(nonDivergenceRequires);
-
- if (!CommandLineOptions.OnlyDivergence)
- {
- List<BigBlock> returnbigblocks = new List<BigBlock>();
- returnbigblocks.Add(new BigBlock(tok, "__Disabled", new CmdSeq(), null, new ReturnCmd(tok)));
- StmtList returnstatement = new StmtList(returnbigblocks, BarrierProcedure.tok);
-
- Expr IfGuard = Expr.Or(Expr.And(Expr.Not(P1), Expr.Not(P2)), Expr.And(ThreadsInSameGroup(), Expr.Or(Expr.Not(P1), Expr.Not(P2))));
- barrierEntryBlock.ec = new IfCmd(tok, IfGuard, returnstatement, null, null);
- }
-
- if(KernelArrayInfo.getGroupSharedArrays().Count > 0) {
-
- Expr IfGuard1 = Expr.And(P1, LocalFence1);
- Expr IfGuard2 = Expr.And(P2, LocalFence2);
-
- bigblocks.Add(new BigBlock(Token.NoToken, null, new CmdSeq(),
- new IfCmd(Token.NoToken, IfGuard1, new StmtList(MakeResetAndHavocBlocks(1, KernelArrayInfo.getGroupSharedArrays()), Token.NoToken), null, null),
- null));
- bigblocks.Add(new BigBlock(Token.NoToken, null, new CmdSeq(),
- new IfCmd(Token.NoToken, IfGuard2, new StmtList(MakeResetAndHavocBlocks(2, KernelArrayInfo.getGroupSharedArrays()), Token.NoToken), null, null),
- null));
- }
-
- if (KernelArrayInfo.getGlobalArrays().Count > 0)
- {
- Expr IfGuard1 = Expr.And(P1, GlobalFence1);
- Expr IfGuard2 = Expr.And(P2, GlobalFence2);
-
- bigblocks.Add(new BigBlock(Token.NoToken, null, new CmdSeq(),
- new IfCmd(Token.NoToken, IfGuard1, new StmtList(MakeResetAndHavocBlocks(1, KernelArrayInfo.getGlobalArrays()), Token.NoToken), null, null),
- null));
- bigblocks.Add(new BigBlock(Token.NoToken, null, new CmdSeq(),
- new IfCmd(Token.NoToken, IfGuard2, new StmtList(MakeResetAndHavocBlocks(2, KernelArrayInfo.getGlobalArrays()), Token.NoToken), null, null),
- null));
- }
-
- foreach (Variable v in KernelArrayInfo.getAllNonLocalArrays())
- {
- if (!ArrayModelledAdversarially(v))
- {
- bigblocks.Add(AssumeEqualityBetweenSharedArrays(v, P1, P2, LocalFence1, LocalFence2, GlobalFence1, GlobalFence2));
- }
- }
-
- StmtList statements = new StmtList(bigblocks, BarrierProcedure.tok);
- Implementation BarrierImplementation =
- new Implementation(BarrierProcedure.tok, BarrierProcedure.Name, new TypeVariableSeq(),
- BarrierProcedure.InParams, BarrierProcedure.OutParams, new VariableSeq(), statements);
-
- if (CommandLineOptions.Unstructured)
- BarrierImplementation.Resolve(ResContext);
-
- BarrierImplementation.AddAttribute("inline", new object[] { new LiteralExpr(tok, BigNum.FromInt(1)) });
- BarrierProcedure.AddAttribute("inline", new object[] { new LiteralExpr(tok, BigNum.FromInt(1)) });
-
- BarrierImplementation.Proc = BarrierProcedure;
-
- Program.TopLevelDeclarations.Add(BarrierImplementation);
- }
-
- private static NAryExpr MakeFenceExpr(Variable v) {
- return Expr.Eq(new IdentifierExpr(Token.NoToken, new LocalVariable(Token.NoToken, v.TypedIdent)),
- new LiteralExpr(Token.NoToken, BigNum.FromInt(1), 1));
- }
-
- private static Expr flagIsSet(Expr Flags, int flag)
- {
- return Expr.Eq(new BvExtractExpr(
- Token.NoToken, Flags, flag, flag - 1),
- new LiteralExpr(Token.NoToken, BigNum.FromInt(1), 1));
- }
-
- private List<BigBlock> MakeResetAndHavocBlocks(int Thread, ICollection<Variable> variables)
- {
- Debug.Assert(variables.Count > 0);
- List<BigBlock> ResetAndHavocBlocks = new List<BigBlock>();
- foreach (Variable v in variables)
- {
- ResetAndHavocBlocks.Add(RaceInstrumenter.MakeResetReadWriteSetStatements(v, Thread));
- if (!ArrayModelledAdversarially(v))
- {
- ResetAndHavocBlocks.Add(HavocSharedArray(v, Thread));
- }
- }
- Debug.Assert(ResetAndHavocBlocks.Count > 0);
- return ResetAndHavocBlocks;
- }
-
-
- public static bool HasZDimension(Variable v)
- {
- if (v.TypedIdent.Type is MapType)
- {
- MapType mt = v.TypedIdent.Type as MapType;
-
- if (mt.Result is MapType)
- {
- MapType mt2 = mt.Result as MapType;
- if (mt2.Result is MapType)
- {
- Debug.Assert(!((mt2.Result as MapType).Result is MapType));
- return true;
- }
- }
- }
- return false;
- }
-
- private BigBlock HavocSharedArray(Variable v, int thread)
- {
- IdentifierExpr vForThread = new IdentifierExpr(Token.NoToken, new VariableDualiser(thread, null, null).VisitVariable(v.Clone() as Variable));
- return new BigBlock(Token.NoToken, null, new CmdSeq(new Cmd[] { new HavocCmd(Token.NoToken, new IdentifierExprSeq(new IdentifierExpr[] { vForThread })) }), null, null);
- }
-
- private BigBlock AssumeEqualityBetweenSharedArrays(Variable v, Expr P1, Expr P2, Expr LocalFence1, Expr LocalFence2, Expr GlobalFence1, Expr GlobalFence2)
- {
- IdentifierExpr v1 = new IdentifierExpr(Token.NoToken, new VariableDualiser(1, null, null).VisitVariable(v.Clone() as Variable));
- IdentifierExpr v2 = new IdentifierExpr(Token.NoToken, new VariableDualiser(2, null, null).VisitVariable(v.Clone() as Variable));
-
- Expr AssumeGuard = Expr.Eq(v1, v2);
-
- Expr EqualityCondition = ThreadsInSameGroup();
-
- if (KernelArrayInfo.getGroupSharedArrays().Contains(v))
- {
- EqualityCondition = Expr.And(EqualityCondition,
- Expr.And(LocalFence1, LocalFence2));
- }
- else if (KernelArrayInfo.getGlobalArrays().Contains(v))
- {
- EqualityCondition = Expr.And(EqualityCondition,
- Expr.And(GlobalFence1, GlobalFence2));
- }
-
- AssumeGuard = Expr.Imp(EqualityCondition, AssumeGuard);
-
- return new BigBlock(Token.NoToken, null, new CmdSeq(new Cmd[] { new AssumeCmd(Token.NoToken, AssumeGuard) }), null, null);
- }
-
-
- internal static bool ModifiesSetContains(IdentifierExprSeq Modifies, IdentifierExpr v)
- {
- foreach (IdentifierExpr ie in Modifies)
- {
- if (ie.Name.Equals(v.Name))
- {
- return true;
- }
- }
- return false;
- }
-
- private void AbstractSharedState()
- {
- new AdversarialAbstraction(this).Abstract();
- }
-
- internal static string MakeOffsetVariableName(string Name, string AccessType)
- {
- return "_" + AccessType + "_OFFSET_" + Name;
- }
-
- internal static GlobalVariable MakeOffsetVariable(string Name, string ReadOrWrite)
- {
- return new GlobalVariable(Token.NoToken, new TypedIdent(Token.NoToken, MakeOffsetVariableName(Name, ReadOrWrite),
- Microsoft.Boogie.Type.GetBvType(32)));
- }
-
- internal static string MakeSourceVariableName(string Name, string AccessType)
- {
- return "_" + AccessType + "_SOURCE_" + Name;
- }
-
- internal static GlobalVariable MakeSourceVariable(string name, string ReadOrWrite)
- {
- return new GlobalVariable(Token.NoToken, new TypedIdent(Token.NoToken, MakeSourceVariableName(name, ReadOrWrite),
- Microsoft.Boogie.Type.GetBvType(32)));
- }
-
- internal GlobalVariable FindOrCreateAccessHasOccurredVariable(string varName, string accessType)
- {
- string name = MakeAccessHasOccurredVariableName(varName, accessType) + "$1";
- foreach(Declaration D in Program.TopLevelDeclarations)
- {
- if(D is GlobalVariable && ((GlobalVariable)D).Name.Equals(name))
- {
- return D as GlobalVariable;
- }
- }
-
- GlobalVariable result = new VariableDualiser(1, null, null).VisitVariable(
- MakeAccessHasOccurredVariable(varName, accessType)) as GlobalVariable;
-
- Program.TopLevelDeclarations.Add(result);
- return result;
-
- }
-
- internal GlobalVariable FindOrCreateOffsetVariable(string varName, string accessType)
- {
- string name = MakeOffsetVariableName(varName, accessType) + "$1";
- foreach (Declaration D in Program.TopLevelDeclarations)
- {
- if (D is GlobalVariable && ((GlobalVariable)D).Name.Equals(name))
- {
- return D as GlobalVariable;
- }
- }
-
- GlobalVariable result = new VariableDualiser(1, null, null).VisitVariable(
- MakeOffsetVariable(varName, accessType)) as GlobalVariable;
-
- Program.TopLevelDeclarations.Add(result);
- return result;
-
- }
-
- internal GlobalVariable FindOrCreateSourceVariable(string varName, string accessType) {
- string name = MakeSourceVariableName(varName, accessType) + "$1";
- foreach (Declaration D in Program.TopLevelDeclarations) {
- if (D is GlobalVariable && ((GlobalVariable)D).Name.Equals(name)) {
- return D as GlobalVariable;
+ private bool SomeArrayModelledNonAdversarially(ICollection<Variable> variables) {
+ Debug.Assert(variables.Count > 0);
+ foreach (Variable v in variables) {
+ if (!ArrayModelledAdversarially(v)) {
+ return true;
}
}
-
- GlobalVariable result = new VariableDualiser(1, null, null).VisitVariable(
- MakeSourceVariable(varName, accessType)) as GlobalVariable;
-
- Program.TopLevelDeclarations.Add(result);
- return result;
-
- }
-
- internal static GlobalVariable MakeAccessHasOccurredVariable(string varName, string accessType)
- {
- return new GlobalVariable(Token.NoToken, new TypedIdent(Token.NoToken, MakeAccessHasOccurredVariableName(varName, accessType), Microsoft.Boogie.Type.Bool));
- }
-
- internal static string MakeAccessHasOccurredVariableName(string varName, string accessType)
- {
- return "_" + accessType + "_HAS_OCCURRED_" + varName;
- }
-
- internal static IdentifierExpr MakeAccessHasOccurredExpr(string varName, string accessType)
- {
- return new IdentifierExpr(Token.NoToken, MakeAccessHasOccurredVariable(varName, accessType));
- }
-
- internal static bool IsIntOrBv32(Microsoft.Boogie.Type type)
- {
- return type.Equals(Microsoft.Boogie.Type.Int) || type.Equals(Microsoft.Boogie.Type.GetBvType(32));
- }
-
- private void PullOutNonLocalAccesses()
- {
- foreach (Declaration d in Program.TopLevelDeclarations)
- {
- if (d is Implementation)
- {
- (d as Implementation).StructuredStmts = PullOutNonLocalAccesses((d as Implementation).StructuredStmts, (d as Implementation));
- }
- }
- }
-
- private void RemoveElseIfs()
- {
- foreach (Declaration d in Program.TopLevelDeclarations)
- {
- if (d is Implementation)
- {
- (d as Implementation).StructuredStmts = RemoveElseIfs((d as Implementation).StructuredStmts);
- }
- }
- }
-
- private void RemoveRedundantReturns()
- {
- foreach (Declaration d in Program.TopLevelDeclarations)
- {
- if (d is Implementation)
- {
- RemoveRedundantReturns((d as Implementation).StructuredStmts);
- }
- }
- }
-
- private StmtList RemoveElseIfs(StmtList stmtList)
- {
- Contract.Requires(stmtList != null);
-
- StmtList result = new StmtList(new List<BigBlock>(), stmtList.EndCurly);
-
- foreach (BigBlock bodyBlock in stmtList.BigBlocks)
- {
- result.BigBlocks.Add(RemoveElseIfs(bodyBlock));
- }
-
- return result;
- }
-
- private void RemoveRedundantReturns(StmtList stmtList)
- {
- Contract.Requires(stmtList != null);
-
- BigBlock bb = stmtList.BigBlocks[stmtList.BigBlocks.Count - 1];
-
- if (bb.tc is ReturnCmd)
- {
- bb.tc = null;
- }
- }
-
- private BigBlock RemoveElseIfs(BigBlock bb)
- {
- BigBlock result = bb;
- if (bb.ec is IfCmd)
- {
- IfCmd IfCommand = bb.ec as IfCmd;
-
- Debug.Assert(IfCommand.elseIf == null || IfCommand.elseBlock == null);
-
- if (IfCommand.elseIf != null)
- {
- IfCommand.elseBlock = new StmtList(new List<BigBlock>(new BigBlock[] {
- new BigBlock(bb.tok, null, new CmdSeq(), IfCommand.elseIf, null)
- }), bb.tok);
- IfCommand.elseIf = null;
- }
-
- IfCommand.thn = RemoveElseIfs(IfCommand.thn);
- if (IfCommand.elseBlock != null)
- {
- IfCommand.elseBlock = RemoveElseIfs(IfCommand.elseBlock);
- }
-
- }
- else if (bb.ec is WhileCmd)
- {
- (bb.ec as WhileCmd).Body = RemoveElseIfs((bb.ec as WhileCmd).Body);
- }
-
- return result;
- }
-
- private StmtList PullOutNonLocalAccesses(StmtList stmtList, Implementation impl)
- {
- Contract.Requires(stmtList != null);
-
- StmtList result = new StmtList(new List<BigBlock>(), stmtList.EndCurly);
-
- foreach (BigBlock bodyBlock in stmtList.BigBlocks)
- {
- result.BigBlocks.Add(PullOutNonLocalAccesses(bodyBlock, impl));
- }
-
- return result;
- }
-
- private BigBlock PullOutNonLocalAccesses(BigBlock bb, Implementation impl)
- {
-
- BigBlock result = new BigBlock(bb.tok, bb.LabelName, new CmdSeq(), null, bb.tc);
-
- foreach (Cmd c in bb.simpleCmds)
- {
-
- if (c is CallCmd)
- {
+ return false;
+ }
+
+ public static bool HasZDimension(Variable v)
+ {
+ if (v.TypedIdent.Type is MapType)
+ {
+ MapType mt = v.TypedIdent.Type as MapType;
+
+ if (mt.Result is MapType)
+ {
+ MapType mt2 = mt.Result as MapType;
+ if (mt2.Result is MapType)
+ {
+ Debug.Assert(!((mt2.Result as MapType).Result is MapType));
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ private BigBlock HavocSharedArray(Variable v)
+ {
+ return new BigBlock(Token.NoToken, null,
+ new CmdSeq(new Cmd[] { new HavocCmd(Token.NoToken,
+ new IdentifierExprSeq(new IdentifierExpr[] { new IdentifierExpr(Token.NoToken, v) })) }), null, null);
+ }
+
+ internal static bool ModifiesSetContains(IdentifierExprSeq Modifies, IdentifierExpr v)
+ {
+ foreach (IdentifierExpr ie in Modifies)
+ {
+ if (ie.Name.Equals(v.Name))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private void AbstractSharedState()
+ {
+ new AdversarialAbstraction(this).Abstract();
+ }
+
+ internal static string MakeOffsetVariableName(string Name, string AccessType)
+ {
+ return "_" + AccessType + "_OFFSET_" + Name;
+ }
+
+ internal static GlobalVariable MakeOffsetVariable(string Name, string ReadOrWrite)
+ {
+ return new GlobalVariable(Token.NoToken, new TypedIdent(Token.NoToken, MakeOffsetVariableName(Name, ReadOrWrite),
+ Microsoft.Boogie.Type.GetBvType(32)));
+ }
+
+ internal static string MakeSourceVariableName(string Name, string AccessType)
+ {
+ return "_" + AccessType + "_SOURCE_" + Name;
+ }
+
+ internal static GlobalVariable MakeSourceVariable(string name, string ReadOrWrite)
+ {
+ return new GlobalVariable(Token.NoToken, new TypedIdent(Token.NoToken, MakeSourceVariableName(name, ReadOrWrite),
+ Microsoft.Boogie.Type.GetBvType(32)));
+ }
+
+ internal GlobalVariable FindOrCreateAccessHasOccurredVariable(string varName, string accessType)
+ {
+ string name = MakeAccessHasOccurredVariableName(varName, accessType) + "$1";
+ foreach(Declaration D in Program.TopLevelDeclarations)
+ {
+ if(D is GlobalVariable && ((GlobalVariable)D).Name.Equals(name))
+ {
+ return D as GlobalVariable;
+ }
+ }
+
+ GlobalVariable result = new VariableDualiser(1, null, null).VisitVariable(
+ MakeAccessHasOccurredVariable(varName, accessType)) as GlobalVariable;
+
+ Program.TopLevelDeclarations.Add(result);
+ return result;
+
+ }
+
+ internal GlobalVariable FindOrCreateOffsetVariable(string varName, string accessType)
+ {
+ string name = MakeOffsetVariableName(varName, accessType) + "$1";
+ foreach (Declaration D in Program.TopLevelDeclarations)
+ {
+ if (D is GlobalVariable && ((GlobalVariable)D).Name.Equals(name))
+ {
+ return D as GlobalVariable;
+ }
+ }
+
+ GlobalVariable result = new VariableDualiser(1, null, null).VisitVariable(
+ MakeOffsetVariable(varName, accessType)) as GlobalVariable;
+
+ Program.TopLevelDeclarations.Add(result);
+ return result;
+
+ }
+
+ internal GlobalVariable FindOrCreateSourceVariable(string varName, string accessType) {
+ string name = MakeSourceVariableName(varName, accessType) + "$1";
+ foreach (Declaration D in Program.TopLevelDeclarations) {
+ if (D is GlobalVariable && ((GlobalVariable)D).Name.Equals(name)) {
+ return D as GlobalVariable;
+ }
+ }
+
+ GlobalVariable result = new VariableDualiser(1, null, null).VisitVariable(
+ MakeSourceVariable(varName, accessType)) as GlobalVariable;
+
+ Program.TopLevelDeclarations.Add(result);
+ return result;
+
+ }
+
+ internal static GlobalVariable MakeAccessHasOccurredVariable(string varName, string accessType)
+ {
+ return new GlobalVariable(Token.NoToken, new TypedIdent(Token.NoToken, MakeAccessHasOccurredVariableName(varName, accessType), Microsoft.Boogie.Type.Bool));
+ }
+
+ internal static string MakeAccessHasOccurredVariableName(string varName, string accessType)
+ {
+ return "_" + accessType + "_HAS_OCCURRED_" + varName;
+ }
+
+ internal static IdentifierExpr MakeAccessHasOccurredExpr(string varName, string accessType)
+ {
+ return new IdentifierExpr(Token.NoToken, MakeAccessHasOccurredVariable(varName, accessType));
+ }
+
+ internal static bool IsIntOrBv32(Microsoft.Boogie.Type type)
+ {
+ return type.Equals(Microsoft.Boogie.Type.Int) || type.Equals(Microsoft.Boogie.Type.GetBvType(32));
+ }
+
+ private void PullOutNonLocalAccesses()
+ {
+ foreach (Declaration d in Program.TopLevelDeclarations)
+ {
+ if (d is Implementation)
+ {
+ (d as Implementation).StructuredStmts = PullOutNonLocalAccesses((d as Implementation).StructuredStmts, (d as Implementation));
+ }
+ }
+ }
+
+ private void RemoveElseIfs()
+ {
+ foreach (Declaration d in Program.TopLevelDeclarations)
+ {
+ if (d is Implementation)
+ {
+ (d as Implementation).StructuredStmts = RemoveElseIfs((d as Implementation).StructuredStmts);
+ }
+ }
+ }
+
+ private void RemoveRedundantReturns()
+ {
+ foreach (Declaration d in Program.TopLevelDeclarations)
+ {
+ if (d is Implementation)
+ {
+ RemoveRedundantReturns((d as Implementation).StructuredStmts);
+ }
+ }
+ }
+
+ private StmtList RemoveElseIfs(StmtList stmtList)
+ {
+ Contract.Requires(stmtList != null);
+
+ StmtList result = new StmtList(new List<BigBlock>(), stmtList.EndCurly);
+
+ foreach (BigBlock bodyBlock in stmtList.BigBlocks)
+ {
+ result.BigBlocks.Add(RemoveElseIfs(bodyBlock));
+ }
+
+ return result;
+ }
+
+ private void RemoveRedundantReturns(StmtList stmtList)
+ {
+ Contract.Requires(stmtList != null);
+
+ BigBlock bb = stmtList.BigBlocks[stmtList.BigBlocks.Count - 1];
+
+ if (bb.tc is ReturnCmd)
+ {
+ bb.tc = null;
+ }
+ }
+
+ private BigBlock RemoveElseIfs(BigBlock bb)
+ {
+ BigBlock result = bb;
+ if (bb.ec is IfCmd)
+ {
+ IfCmd IfCommand = bb.ec as IfCmd;
+
+ Debug.Assert(IfCommand.elseIf == null || IfCommand.elseBlock == null);
+
+ if (IfCommand.elseIf != null)
+ {
+ IfCommand.elseBlock = new StmtList(new List<BigBlock>(new BigBlock[] {
+ new BigBlock(bb.tok, null, new CmdSeq(), IfCommand.elseIf, null)
+ }), bb.tok);
+ IfCommand.elseIf = null;
+ }
+
+ IfCommand.thn = RemoveElseIfs(IfCommand.thn);
+ if (IfCommand.elseBlock != null)
+ {
+ IfCommand.elseBlock = RemoveElseIfs(IfCommand.elseBlock);
+ }
+
+ }
+ else if (bb.ec is WhileCmd)
+ {
+ (bb.ec as WhileCmd).Body = RemoveElseIfs((bb.ec as WhileCmd).Body);
+ }
+
+ return result;
+ }
+
+ private StmtList PullOutNonLocalAccesses(StmtList stmtList, Implementation impl)
+ {
+ Contract.Requires(stmtList != null);
+
+ StmtList result = new StmtList(new List<BigBlock>(), stmtList.EndCurly);
+
+ foreach (BigBlock bodyBlock in stmtList.BigBlocks)
+ {
+ result.BigBlocks.Add(PullOutNonLocalAccesses(bodyBlock, impl));
+ }
+
+ return result;
+ }
+
+ private BigBlock PullOutNonLocalAccesses(BigBlock bb, Implementation impl)
+ {
+
+ BigBlock result = new BigBlock(bb.tok, bb.LabelName, new CmdSeq(), null, bb.tc);
+
+ foreach (Cmd c in bb.simpleCmds)
+ {
+
+ if (c is CallCmd)
+ {
CallCmd call = c as CallCmd;
- List<Expr> newIns = new List<Expr>();
-
- for (int i = 0; i < call.Ins.Count; i++)
- {
- Expr e = call.Ins[i];
-
- while (NonLocalAccessCollector.ContainsNonLocalAccess(e, KernelArrayInfo))
- {
- AssignCmd assignToTemp;
- LocalVariable tempDecl;
- e = ExtractLocalAccessToTemp(e, out assignToTemp, out tempDecl);
- result.simpleCmds.Add(assignToTemp);
- impl.LocVars.Add(tempDecl);
- }
-
- newIns.Add(e);
-
- }
-
- CallCmd newCall = new CallCmd(call.tok, call.callee, newIns, call.Outs);
- newCall.Proc = call.Proc;
- result.simpleCmds.Add(newCall);
- }
- else if (c is AssignCmd)
- {
- AssignCmd assign = c as AssignCmd;
-
- if (assign.Lhss.Zip(assign.Rhss, (lhs, rhs) =>
- !NonLocalAccessCollector.ContainsNonLocalAccess(rhs, KernelArrayInfo) ||
- (!NonLocalAccessCollector.ContainsNonLocalAccess(lhs, KernelArrayInfo) &&
- NonLocalAccessCollector.IsNonLocalAccess(rhs, KernelArrayInfo))).All(b => b))
- {
- result.simpleCmds.Add(c);
- }
- else
- {
- Debug.Assert(assign.Lhss.Count == 1 && assign.Rhss.Count == 1);
- AssignLhs lhs = assign.Lhss.ElementAt(0);
- Expr rhs = assign.Rhss.ElementAt(0);
- rhs = PullOutNonLocalAccessesIntoTemps(result, rhs, impl);
- List<AssignLhs> newLhss = new List<AssignLhs>();
- newLhss.Add(lhs);
- List<Expr> newRhss = new List<Expr>();
- newRhss.Add(rhs);
- result.simpleCmds.Add(new AssignCmd(assign.tok, newLhss, newRhss));
- }
-
- }
- else if (c is HavocCmd)
- {
- result.simpleCmds.Add(c);
- }
- else if (c is AssertCmd)
- {
- result.simpleCmds.Add(new AssertCmd(c.tok, PullOutNonLocalAccessesIntoTemps(result, (c as AssertCmd).Expr, impl)));
- }
- else if (c is AssumeCmd)
- {
- result.simpleCmds.Add(new AssumeCmd(c.tok, PullOutNonLocalAccessesIntoTemps(result, (c as AssumeCmd).Expr, impl)));
- }
- else
- {
- Console.WriteLine(c);
- Debug.Assert(false);
- }
- }
-
- if (bb.ec is WhileCmd)
- {
- WhileCmd WhileCommand = bb.ec as WhileCmd;
- while (NonLocalAccessCollector.ContainsNonLocalAccess(WhileCommand.Guard, KernelArrayInfo))
- {
- AssignCmd assignToTemp;
- LocalVariable tempDecl;
- WhileCommand.Guard = ExtractLocalAccessToTemp(WhileCommand.Guard, out assignToTemp, out tempDecl);
- result.simpleCmds.Add(assignToTemp);
- impl.LocVars.Add(tempDecl);
- }
- result.ec = new WhileCmd(WhileCommand.tok, WhileCommand.Guard, WhileCommand.Invariants, PullOutNonLocalAccesses(WhileCommand.Body, impl));
- }
- else if (bb.ec is IfCmd)
- {
- IfCmd IfCommand = bb.ec as IfCmd;
- Debug.Assert(IfCommand.elseIf == null); // "else if" must have been eliminated by this phase
- while (NonLocalAccessCollector.ContainsNonLocalAccess(IfCommand.Guard, KernelArrayInfo))
- {
- AssignCmd assignToTemp;
- LocalVariable tempDecl;
- IfCommand.Guard = ExtractLocalAccessToTemp(IfCommand.Guard, out assignToTemp, out tempDecl);
- result.simpleCmds.Add(assignToTemp);
- impl.LocVars.Add(tempDecl);
- }
- result.ec = new IfCmd(IfCommand.tok, IfCommand.Guard, PullOutNonLocalAccesses(IfCommand.thn, impl), IfCommand.elseIf, IfCommand.elseBlock != null ? PullOutNonLocalAccesses(IfCommand.elseBlock, impl) : null);
- }
- else if (bb.ec is BreakCmd)
- {
- result.ec = bb.ec;
- }
- else
- {
- Debug.Assert(bb.ec == null);
- }
-
- return result;
-
- }
-
- private Expr PullOutNonLocalAccessesIntoTemps(BigBlock result, Expr e, Implementation impl)
- {
- while (NonLocalAccessCollector.ContainsNonLocalAccess(e, KernelArrayInfo))
- {
- AssignCmd assignToTemp;
- LocalVariable tempDecl;
- e = ExtractLocalAccessToTemp(e, out assignToTemp, out tempDecl);
- result.simpleCmds.Add(assignToTemp);
- impl.LocVars.Add(tempDecl);
- }
- return e;
- }
-
- private Expr ExtractLocalAccessToTemp(Expr rhs, out AssignCmd tempAssignment, out LocalVariable tempDeclaration)
- {
- NonLocalAccessExtractor extractor = new NonLocalAccessExtractor(TempCounter, KernelArrayInfo);
- TempCounter++;
- rhs = extractor.VisitExpr(rhs);
- tempAssignment = extractor.Assignment;
- tempDeclaration = extractor.Declaration;
- return rhs;
- }
-
- private void MakeKernelDualised()
- {
-
- List<Declaration> NewTopLevelDeclarations = new List<Declaration>();
-
- foreach (Declaration d in Program.TopLevelDeclarations)
- {
- if (d is Procedure)
- {
-
- new KernelDualiser(this).DualiseProcedure(d as Procedure);
-
- NewTopLevelDeclarations.Add(d as Procedure);
-
- continue;
-
- }
-
- if (d is Implementation)
- {
-
- new KernelDualiser(this).DualiseImplementation(d as Implementation, CommandLineOptions.Unstructured);
-
- NewTopLevelDeclarations.Add(d as Implementation);
-
- continue;
-
- }
-
- if (d is Variable && ((d as Variable).IsMutable || IsThreadLocalIdConstant(d as Variable)
- || IsGroupIdConstant(d as Variable) ))
- {
- NewTopLevelDeclarations.Add(new VariableDualiser(1, null, null).VisitVariable((Variable)d.Clone()));
- if (!QKeyValue.FindBoolAttribute(d.Attributes, "race_checking"))
- {
- NewTopLevelDeclarations.Add(new VariableDualiser(2, null, null).VisitVariable((Variable)d.Clone()));
- }
-
- continue;
- }
-
- NewTopLevelDeclarations.Add(d);
-
- }
-
- Program.TopLevelDeclarations = NewTopLevelDeclarations;
-
- }
-
- private void MakeKernelPredicated()
- {
- if (CommandLineOptions.Unstructured)
- {
- if (CommandLineOptions.SmartPredication)
- {
- SmartBlockPredicator.Predicate(Program);
- }
- else
- {
- BlockPredicator.Predicate(Program, /*createCandidateInvariants=*/CommandLineOptions.Inference);
- }
- return;
- }
-
- foreach (Declaration d in Program.TopLevelDeclarations)
- {
- if (d is Procedure)
- {
- Procedure proc = d as Procedure;
- IdentifierExpr enabled = new IdentifierExpr(proc.tok,
- new LocalVariable(proc.tok, new TypedIdent(proc.tok, "_P", Microsoft.Boogie.Type.Bool)));
- Expr predicateExpr;
- if (!uniformityAnalyser.IsUniform(proc.Name))
- {
- // Add predicate to start of parameter list
- VariableSeq NewIns = new VariableSeq();
- NewIns.Add(enabled.Decl);
- foreach (Variable v in proc.InParams)
- {
- NewIns.Add(v);
- }
- proc.InParams = NewIns;
- predicateExpr = enabled;
- }
- else
- {
- predicateExpr = Expr.True;
- }
-
- RequiresSeq newRequires = new RequiresSeq();
- foreach (Requires r in proc.Requires)
- {
- newRequires.Add(new Requires(r.Free, Predicator.ProcessEnabledIntrinsics(r.Condition, predicateExpr)));
- }
- proc.Requires = newRequires;
-
- EnsuresSeq newEnsures = new EnsuresSeq();
- foreach (Ensures e in proc.Ensures)
- {
- newEnsures.Add(new Ensures(e.Free, Predicator.ProcessEnabledIntrinsics(e.Condition, predicateExpr)));
- }
- proc.Ensures = newEnsures;
-
- }
- else if (d is Implementation)
- {
- Implementation impl = d as Implementation;
- new Predicator(this, !uniformityAnalyser.IsUniform(impl.Name)).transform
- (impl);
- }
- }
-
- }
-
- private void CheckKernelParameters()
- {
- if (KernelProcedure.OutParams.Length != 0)
- {
- Error(KernelProcedure.tok, "Kernel should not take return anything");
- }
- }
-
-
- private int Check()
- {
+ if (QKeyValue.FindBoolAttribute(call.Proc.Attributes, "barrier_invariant") ||
+ QKeyValue.FindBoolAttribute(call.Proc.Attributes, "binary_barrier_invariant")) {
+ // Do not pull non-local accesses out of barrier invariants
+ continue;
+ }
+
+ List<Expr> newIns = new List<Expr>();
+
+ for (int i = 0; i < call.Ins.Count; i++)
+ {
+ Expr e = call.Ins[i];
+
+ while (NonLocalAccessCollector.ContainsNonLocalAccess(e, KernelArrayInfo))
+ {
+ AssignCmd assignToTemp;
+ LocalVariable tempDecl;
+ e = ExtractLocalAccessToTemp(e, out assignToTemp, out tempDecl);
+ result.simpleCmds.Add(assignToTemp);
+ impl.LocVars.Add(tempDecl);
+ }
+
+ newIns.Add(e);
+
+ }
+
+ CallCmd newCall = new CallCmd(call.tok, call.callee, newIns, call.Outs);
+ newCall.Proc = call.Proc;
+ result.simpleCmds.Add(newCall);
+ }
+ else if (c is AssignCmd)
+ {
+ AssignCmd assign = c as AssignCmd;
+
+ if (assign.Lhss.Zip(assign.Rhss, (lhs, rhs) =>
+ !NonLocalAccessCollector.ContainsNonLocalAccess(rhs, KernelArrayInfo) ||
+ (!NonLocalAccessCollector.ContainsNonLocalAccess(lhs, KernelArrayInfo) &&
+ NonLocalAccessCollector.IsNonLocalAccess(rhs, KernelArrayInfo))).All(b => b))
+ {
+ result.simpleCmds.Add(c);
+ }
+ else
+ {
+ Debug.Assert(assign.Lhss.Count == 1 && assign.Rhss.Count == 1);
+ AssignLhs lhs = assign.Lhss.ElementAt(0);
+ Expr rhs = assign.Rhss.ElementAt(0);
+ rhs = PullOutNonLocalAccessesIntoTemps(result, rhs, impl);
+ List<AssignLhs> newLhss = new List<AssignLhs>();
+ newLhss.Add(lhs);
+ List<Expr> newRhss = new List<Expr>();
+ newRhss.Add(rhs);
+ result.simpleCmds.Add(new AssignCmd(assign.tok, newLhss, newRhss));
+ }
+
+ }
+ else if (c is HavocCmd)
+ {
+ result.simpleCmds.Add(c);
+ }
+ else if (c is AssertCmd)
+ {
+ // Do not pull non-local accesses out of assert commands
+ continue;
+ }
+ else if (c is AssumeCmd)
+ {
+ result.simpleCmds.Add(new AssumeCmd(c.tok, PullOutNonLocalAccessesIntoTemps(result, (c as AssumeCmd).Expr, impl)));
+ }
+ else
+ {
+ Console.WriteLine(c);
+ Debug.Assert(false);
+ }
+ }
+
+ if (bb.ec is WhileCmd)
+ {
+ WhileCmd WhileCommand = bb.ec as WhileCmd;
+ while (NonLocalAccessCollector.ContainsNonLocalAccess(WhileCommand.Guard, KernelArrayInfo))
+ {
+ AssignCmd assignToTemp;
+ LocalVariable tempDecl;
+ WhileCommand.Guard = ExtractLocalAccessToTemp(WhileCommand.Guard, out assignToTemp, out tempDecl);
+ result.simpleCmds.Add(assignToTemp);
+ impl.LocVars.Add(tempDecl);
+ }
+ result.ec = new WhileCmd(WhileCommand.tok, WhileCommand.Guard, WhileCommand.Invariants, PullOutNonLocalAccesses(WhileCommand.Body, impl));
+ }
+ else if (bb.ec is IfCmd)
+ {
+ IfCmd IfCommand = bb.ec as IfCmd;
+ Debug.Assert(IfCommand.elseIf == null); // "else if" must have been eliminated by this phase
+ while (NonLocalAccessCollector.ContainsNonLocalAccess(IfCommand.Guard, KernelArrayInfo))
+ {
+ AssignCmd assignToTemp;
+ LocalVariable tempDecl;
+ IfCommand.Guard = ExtractLocalAccessToTemp(IfCommand.Guard, out assignToTemp, out tempDecl);
+ result.simpleCmds.Add(assignToTemp);
+ impl.LocVars.Add(tempDecl);
+ }
+ result.ec = new IfCmd(IfCommand.tok, IfCommand.Guard, PullOutNonLocalAccesses(IfCommand.thn, impl), IfCommand.elseIf, IfCommand.elseBlock != null ? PullOutNonLocalAccesses(IfCommand.elseBlock, impl) : null);
+ }
+ else if (bb.ec is BreakCmd)
+ {
+ result.ec = bb.ec;
+ }
+ else
+ {
+ Debug.Assert(bb.ec == null);
+ }
+
+ return result;
+
+ }
+
+ private Expr PullOutNonLocalAccessesIntoTemps(BigBlock result, Expr e, Implementation impl)
+ {
+ while (NonLocalAccessCollector.ContainsNonLocalAccess(e, KernelArrayInfo))
+ {
+ AssignCmd assignToTemp;
+ LocalVariable tempDecl;
+ e = ExtractLocalAccessToTemp(e, out assignToTemp, out tempDecl);
+ result.simpleCmds.Add(assignToTemp);
+ impl.LocVars.Add(tempDecl);
+ }
+ return e;
+ }
+
+ private Expr ExtractLocalAccessToTemp(Expr rhs, out AssignCmd tempAssignment, out LocalVariable tempDeclaration)
+ {
+ NonLocalAccessExtractor extractor = new NonLocalAccessExtractor(TempCounter, KernelArrayInfo);
+ TempCounter++;
+ rhs = extractor.VisitExpr(rhs);
+ tempAssignment = extractor.Assignment;
+ tempDeclaration = extractor.Declaration;
+ return rhs;
+ }
+
+ private void MakeKernelDualised()
+ {
+
+ List<Declaration> NewTopLevelDeclarations = new List<Declaration>();
+
+ for(int i = 0; i < Program.TopLevelDeclarations.Count; i++)
+ {
+ Declaration d = Program.TopLevelDeclarations[i];
+
+ if (d is Procedure)
+ {
+
+ new KernelDualiser(this).DualiseProcedure(d as Procedure);
+
+ NewTopLevelDeclarations.Add(d as Procedure);
+
+ continue;
+
+ }
+
+ if (d is Implementation)
+ {
+
+ new KernelDualiser(this).DualiseImplementation(d as Implementation, CommandLineOptions.Unstructured);
+
+ NewTopLevelDeclarations.Add(d as Implementation);
+
+ continue;
+
+ }
+
+ if (d is Variable && ((d as Variable).IsMutable ||
+ IsThreadLocalIdConstant(d as Variable) ||
+ IsGroupIdConstant(d as Variable))) {
+ var v = d as Variable;
+
+ if (KernelArrayInfo.getGlobalArrays().Contains(v)) {
+ NewTopLevelDeclarations.Add(v);
+ continue;
+ }
+
+ if (KernelArrayInfo.getGroupSharedArrays().Contains(v)) {
+ Variable newV = new GlobalVariable(Token.NoToken, new TypedIdent(Token.NoToken,
+ v.Name, new MapType(Token.NoToken, new TypeVariableSeq(),
+ new TypeSeq(new Microsoft.Boogie.Type[] { Microsoft.Boogie.Type.Bool }),
+ v.TypedIdent.Type)));
+ newV.Attributes = v.Attributes;
+ NewTopLevelDeclarations.Add(newV);
+ continue;
+ }
+
+ NewTopLevelDeclarations.Add(new VariableDualiser(1, null, null).VisitVariable((Variable)v.Clone()));
+ if (!QKeyValue.FindBoolAttribute(v.Attributes, "race_checking")) {
+ NewTopLevelDeclarations.Add(new VariableDualiser(2, null, null).VisitVariable((Variable)v.Clone()));
+ }
+
+ continue;
+ }
+
+ NewTopLevelDeclarations.Add(d);
+
+ }
+
+ Program.TopLevelDeclarations = NewTopLevelDeclarations;
+
+ }
+
+ private void MakeKernelPredicated()
+ {
+ if (CommandLineOptions.Unstructured)
+ {
+ if (CommandLineOptions.SmartPredication)
+ {
+ SmartBlockPredicator.Predicate(Program, proc => true, uniformityAnalyser);
+ }
+ else
+ {
+ BlockPredicator.Predicate(Program, /*createCandidateInvariants=*/CommandLineOptions.Inference);
+ }
+ return;
+ }
+
+ foreach (Declaration d in Program.TopLevelDeclarations)
+ {
+ if (d is Procedure)
+ {
+ Procedure proc = d as Procedure;
+ IdentifierExpr enabled = new IdentifierExpr(proc.tok,
+ new LocalVariable(proc.tok, new TypedIdent(proc.tok, "_P", Microsoft.Boogie.Type.Bool)));
+ Expr predicateExpr;
+ if (!uniformityAnalyser.IsUniform(proc.Name))
+ {
+ // Add predicate to start of parameter list
+ VariableSeq NewIns = new VariableSeq();
+ NewIns.Add(enabled.Decl);
+ foreach (Variable v in proc.InParams)
+ {
+ NewIns.Add(v);
+ }
+ proc.InParams = NewIns;
+ predicateExpr = enabled;
+ }
+ else
+ {
+ predicateExpr = Expr.True;
+ }
+
+ RequiresSeq newRequires = new RequiresSeq();
+ foreach (Requires r in proc.Requires)
+ {
+ newRequires.Add(new Requires(r.Free, Predicator.ProcessEnabledIntrinsics(r.Condition, predicateExpr)));
+ }
+ proc.Requires = newRequires;
+
+ EnsuresSeq newEnsures = new EnsuresSeq();
+ foreach (Ensures e in proc.Ensures)
+ {
+ newEnsures.Add(new Ensures(e.Free, Predicator.ProcessEnabledIntrinsics(e.Condition, predicateExpr)));
+ }
+ proc.Ensures = newEnsures;
+
+ }
+ else if (d is Implementation)
+ {
+ Implementation impl = d as Implementation;
+ new Predicator(this, !uniformityAnalyser.IsUniform(impl.Name)).transform
+ (impl);
+ }
+ }
+
+ }
+
+ private void CheckKernelParameters()
+ {
+ if (KernelProcedure.OutParams.Length != 0)
+ {
+ Error(KernelProcedure.tok, "Kernel should not take return anything");
+ }
+ }
+
+
+ private int Check()
+ {
BarrierProcedure = FindOrCreateBarrierProcedure();
- KernelProcedure = CheckExactlyOneKernelProcedure();
-
- if (ErrorCount > 0)
- {
- return ErrorCount;
- }
-
- if (BarrierProcedure.InParams.Length != 2)
- {
- Error(BarrierProcedure, "Barrier procedure must take exactly two arguments");
- }
- else if (!BarrierProcedure.InParams[0].TypedIdent.Type.Equals(new BvType(1)))
- {
- Error(BarrierProcedure, "First argument to barrier procedure must have type bv1");
- }
- else if (!BarrierProcedure.InParams[1].TypedIdent.Type.Equals(new BvType(1))) {
- Error(BarrierProcedure, "Second argument to barrier procedure must have type bv1");
- }
-
- if (BarrierProcedure.OutParams.Length != 0)
- {
- Error(BarrierProcedure, "Barrier procedure must not return any results");
- }
-
- if (!FindNonLocalVariables())
- {
- return ErrorCount;
- }
-
- CheckKernelImplementation();
- return ErrorCount;
- }
-
- public static bool IsThreadLocalIdConstant(Variable variable)
- {
- return variable.Name.Equals(_X.Name) || variable.Name.Equals(_Y.Name) || variable.Name.Equals(_Z.Name);
- }
-
- public static bool IsGroupIdConstant(Variable variable)
- {
- return variable.Name.Equals(_GROUP_X.Name) || variable.Name.Equals(_GROUP_Y.Name) || variable.Name.Equals(_GROUP_Z.Name);
- }
-
- internal void AddCandidateInvariant(IRegion region, Expr e, string tag)
- {
- region.AddInvariant(Program.CreateCandidateInvariant(e, tag));
- }
-
- internal Implementation GetImplementation(string procedureName)
- {
- foreach (Declaration D in Program.TopLevelDeclarations)
- {
- if (D is Implementation && ((D as Implementation).Name == procedureName))
- {
- return D as Implementation;
- }
- }
- Debug.Assert(false);
- return null;
- }
-
-
- internal bool ContainsBarrierCall(IRegion loop)
- {
- foreach (Cmd c in loop.Cmds())
- {
- if (c is CallCmd && ((c as CallCmd).Proc == BarrierProcedure))
- {
- return true;
- }
- }
-
- return false;
- }
-
-
-
- internal bool ArrayModelledAdversarially(Variable v)
- {
- if (CommandLineOptions.AdversarialAbstraction)
- {
- return true;
- }
- if (CommandLineOptions.EqualityAbstraction)
- {
- return false;
- }
- return !arrayControlFlowAnalyser.MayAffectControlFlow(v.Name);
- }
-
- internal Expr GlobalIdExpr(string dimension)
- {
- return MakeBVAdd(MakeBVMul(
- new IdentifierExpr(Token.NoToken, GetGroupId(dimension)), new IdentifierExpr(Token.NoToken, GetGroupSize(dimension))),
- new IdentifierExpr(Token.NoToken, MakeThreadId(Token.NoToken, dimension)));
- }
-
- internal IRegion RootRegion(Implementation Impl)
- {
- if (CommandLineOptions.Unstructured)
- return new UnstructuredRegion(Program, Impl);
- else
- return new StructuredRegion(Impl);
- }
-
-
- public static bool IsGivenConstant(Expr e, Constant c)
- {
- if (!(e is IdentifierExpr))
- return false;
-
- var varName = ((IdentifierExpr)e).Decl.Name;
- return (StripThreadIdentifier(varName) == StripThreadIdentifier(c.Name));
- }
-
- public bool SubstIsGivenConstant(Implementation impl, Expr e, Constant c)
- {
- if (!(e is IdentifierExpr))
- return false;
- e = varDefAnalyses[impl].SubstDefinitions(e, impl.Name);
- return IsGivenConstant(e, c);
- }
-
- public Constant GetLocalIdConst(int dim)
- {
- switch (dim)
- {
- case 0: return _X;
- case 1: return _Y;
- case 2: return _Z;
- default: Debug.Assert(false);
- return null;
- }
- }
-
- public Constant GetGroupIdConst(int dim)
- {
- switch (dim)
- {
- case 0: return _GROUP_X;
- case 1: return _GROUP_Y;
- case 2: return _GROUP_Z;
- default: Debug.Assert(false);
- return null;
- }
- }
-
- public Constant GetGroupSizeConst(int dim)
- {
- switch (dim)
- {
- case 0: return _GROUP_SIZE_X;
- case 1: return _GROUP_SIZE_Y;
- case 2: return _GROUP_SIZE_Z;
- default: Debug.Assert(false);
- return null;
- }
- }
-
- public bool IsLocalId(Expr e, int dim, Implementation impl)
- {
- return SubstIsGivenConstant(impl, e, GetLocalIdConst(dim));
- }
-
- public bool IsGlobalId(Expr e, int dim, Implementation impl)
- {
- e = varDefAnalyses[impl].SubstDefinitions(e, impl.Name);
-
- if (e is NAryExpr && (e as NAryExpr).Fun.FunctionName.Equals("BV32_ADD"))
- {
- NAryExpr nary = e as NAryExpr;
- Constant localId = GetLocalIdConst(dim);
-
- if (IsGivenConstant(nary.Args[1], localId))
- {
- return IsGroupIdTimesGroupSize(nary.Args[0], dim);
- }
-
- if (IsGivenConstant(nary.Args[0], localId))
- {
- return IsGroupIdTimesGroupSize(nary.Args[1], dim);
- }
- }
-
- return false;
- }
-
- private bool IsGroupIdTimesGroupSize(Expr expr, int dim)
- {
- if (expr is NAryExpr && (expr as NAryExpr).Fun.FunctionName.Equals("BV32_MUL"))
- {
- NAryExpr innerNary = expr as NAryExpr;
-
- if (IsGroupIdAndSize(dim, innerNary.Args[0], innerNary.Args[1]))
- {
- return true;
- }
-
- if (IsGroupIdAndSize(dim, innerNary.Args[1], innerNary.Args[0]))
- {
- return true;
- }
- }
- return false;
- }
-
- private bool IsGroupIdAndSize(int dim, Expr maybeGroupId, Expr maybeGroupSize)
- {
- return IsGivenConstant(maybeGroupId, GetGroupIdConst(dim)) &&
- IsGivenConstant(maybeGroupSize, GetGroupSizeConst(dim));
- }
-
- internal Expr MaybeDualise(Expr e, int id, string procName)
- {
- if (id == 0)
- return e;
- else
- return (Expr)new VariableDualiser(id, uniformityAnalyser, procName).Visit(e.Clone());
- }
-
- internal static bool IsConstantInCurrentRegion(IdentifierExpr expr) {
- return (expr.Decl is Constant) ||
- (expr.Decl is Formal && ((Formal)expr.Decl).InComing);
- }
-
- }
-
-
-}
+ KernelProcedure = CheckExactlyOneKernelProcedure();
+
+ if (ErrorCount > 0)
+ {
+ return ErrorCount;
+ }
+
+ if (BarrierProcedure.InParams.Length != 2)
+ {
+ Error(BarrierProcedure, "Barrier procedure must take exactly two arguments");
+ }
+ else if (!BarrierProcedure.InParams[0].TypedIdent.Type.Equals(new BvType(1)))
+ {
+ Error(BarrierProcedure, "First argument to barrier procedure must have type bv1");
+ }
+ else if (!BarrierProcedure.InParams[1].TypedIdent.Type.Equals(new BvType(1))) {
+ Error(BarrierProcedure, "Second argument to barrier procedure must have type bv1");
+ }
+
+ if (BarrierProcedure.OutParams.Length != 0)
+ {
+ Error(BarrierProcedure, "Barrier procedure must not return any results");
+ }
+
+ if (!FindNonLocalVariables())
+ {
+ return ErrorCount;
+ }
+
+ CheckKernelImplementation();
+ return ErrorCount;
+ }
+
+ public static bool IsThreadLocalIdConstant(Variable variable)
+ {
+ return variable.Name.Equals(_X.Name) || variable.Name.Equals(_Y.Name) || variable.Name.Equals(_Z.Name);
+ }
+
+ public static bool IsGroupIdConstant(Variable variable)
+ {
+ return variable.Name.Equals(_GROUP_X.Name) || variable.Name.Equals(_GROUP_Y.Name) || variable.Name.Equals(_GROUP_Z.Name);
+ }
+
+ internal void AddCandidateInvariant(IRegion region, Expr e, string tag)
+ {
+ region.AddInvariant(Program.CreateCandidateInvariant(e, tag));
+ }
+
+ internal Implementation GetImplementation(string procedureName)
+ {
+ foreach (Declaration D in Program.TopLevelDeclarations)
+ {
+ if (D is Implementation && ((D as Implementation).Name == procedureName))
+ {
+ return D as Implementation;
+ }
+ }
+ Error(Token.NoToken, "No implementation found for procedure \"" + procedureName + "\"");
+ Environment.Exit(1);
+ return null;
+ }
+
+
+ internal bool ContainsBarrierCall(IRegion loop)
+ {
+ foreach (Cmd c in loop.Cmds())
+ {
+ if (c is CallCmd && ((c as CallCmd).Proc == BarrierProcedure))
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+
+
+ internal bool ArrayModelledAdversarially(Variable v)
+ {
+ if (CommandLineOptions.AdversarialAbstraction)
+ {
+ return true;
+ }
+ if (CommandLineOptions.EqualityAbstraction)
+ {
+ return false;
+ }
+ return !arrayControlFlowAnalyser.MayAffectControlFlow(v.Name);
+ }
+
+ internal Expr GlobalIdExpr(string dimension)
+ {
+ return MakeBVAdd(MakeBVMul(
+ new IdentifierExpr(Token.NoToken, GetGroupId(dimension)), new IdentifierExpr(Token.NoToken, GetGroupSize(dimension))),
+ new IdentifierExpr(Token.NoToken, MakeThreadId(dimension)));
+ }
+
+ internal IRegion RootRegion(Implementation Impl)
+ {
+ if (CommandLineOptions.Unstructured)
+ return new UnstructuredRegion(Program, Impl);
+ else
+ return new StructuredRegion(Impl);
+ }
+
+
+ public static bool IsGivenConstant(Expr e, Constant c)
+ {
+ if (!(e is IdentifierExpr))
+ return false;
+
+ var varName = ((IdentifierExpr)e).Decl.Name;
+ return (StripThreadIdentifier(varName) == StripThreadIdentifier(c.Name));
+ }
+
+ public bool SubstIsGivenConstant(Implementation impl, Expr e, Constant c)
+ {
+ if (!(e is IdentifierExpr))
+ return false;
+ e = varDefAnalyses[impl].SubstDefinitions(e, impl.Name);
+ return IsGivenConstant(e, c);
+ }
+
+ public Constant GetLocalIdConst(int dim)
+ {
+ switch (dim)
+ {
+ case 0: return _X;
+ case 1: return _Y;
+ case 2: return _Z;
+ default: Debug.Assert(false);
+ return null;
+ }
+ }
+
+ public Constant GetGroupIdConst(int dim)
+ {
+ switch (dim)
+ {
+ case 0: return _GROUP_X;
+ case 1: return _GROUP_Y;
+ case 2: return _GROUP_Z;
+ default: Debug.Assert(false);
+ return null;
+ }
+ }
+
+ public Constant GetGroupSizeConst(int dim)
+ {
+ switch (dim)
+ {
+ case 0: return _GROUP_SIZE_X;
+ case 1: return _GROUP_SIZE_Y;
+ case 2: return _GROUP_SIZE_Z;
+ default: Debug.Assert(false);
+ return null;
+ }
+ }
+
+ public bool IsLocalId(Expr e, int dim, Implementation impl)
+ {
+ return SubstIsGivenConstant(impl, e, GetLocalIdConst(dim));
+ }
+
+ public bool IsGlobalId(Expr e, int dim, Implementation impl)
+ {
+ e = varDefAnalyses[impl].SubstDefinitions(e, impl.Name);
+
+ if (e is NAryExpr && (e as NAryExpr).Fun.FunctionName.Equals("BV32_ADD"))
+ {
+ NAryExpr nary = e as NAryExpr;
+ Constant localId = GetLocalIdConst(dim);
+
+ if (IsGivenConstant(nary.Args[1], localId))
+ {
+ return IsGroupIdTimesGroupSize(nary.Args[0], dim);
+ }
+
+ if (IsGivenConstant(nary.Args[0], localId))
+ {
+ return IsGroupIdTimesGroupSize(nary.Args[1], dim);
+ }
+ }
+
+ return false;
+ }
+
+ private bool IsGroupIdTimesGroupSize(Expr expr, int dim)
+ {
+ if (expr is NAryExpr && (expr as NAryExpr).Fun.FunctionName.Equals("BV32_MUL"))
+ {
+ NAryExpr innerNary = expr as NAryExpr;
+
+ if (IsGroupIdAndSize(dim, innerNary.Args[0], innerNary.Args[1]))
+ {
+ return true;
+ }
+
+ if (IsGroupIdAndSize(dim, innerNary.Args[1], innerNary.Args[0]))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private bool IsGroupIdAndSize(int dim, Expr maybeGroupId, Expr maybeGroupSize)
+ {
+ return IsGivenConstant(maybeGroupId, GetGroupIdConst(dim)) &&
+ IsGivenConstant(maybeGroupSize, GetGroupSizeConst(dim));
+ }
+
+ internal Expr MaybeDualise(Expr e, int id, string procName)
+ {
+ if (id == 0)
+ return e;
+ else
+ return (Expr)new VariableDualiser(id, uniformityAnalyser, procName).Visit(e.Clone());
+ }
+
+ internal static bool IsConstantInCurrentRegion(IdentifierExpr expr) {
+ return (expr.Decl is Constant) ||
+ (expr.Decl is Formal && ((Formal)expr.Decl).InComing);
+ }
+
+ internal static Expr GroupSharedIndexingExpr(int Thread) {
+ return Thread == 1 ? Expr.True : ThreadsInSameGroup();
+ }
+
+ }
+
+
+}