public override StatementList WriteAddr(Addressable addr, Expression expr) { if (addr is InstanceField instanceField) { var instanceName = instanceField.Instance; var fieldName = FieldTranslator.GetFieldName(instanceField.Field); if (Settings.SplitFieldsEnabled()) { return(SplitFieldUpdate.ForKeyValue(instanceField, expr)); } else { return(HeapUpdate.ForKeyValue(instanceField, expr)); } } else if (addr is StaticField staticField) { var boogieVar = BoogieVariable.From(staticField); return(bg.VariableAssignment(boogieVar, expr)); } else if (addr is DotNetVariable v) { return(BoogieStatement.VariableAssignment(BoogieVariable.FromDotNetVariable(v.Var), expr)); } else { throw new NotImplementedException(); } }
public static void CreateAsyncStartMethod(StreamWriter sw) { StatementList stmts = new StatementList(); var boogieGetTypeRes = BoogieVariable.GetTempVar(Helpers.ObjectType(), null /* need dict with used var names*/, prefix: "asyncType"); var stateMachineVar = BoogieVariable.GetTempVar(Helpers.ObjectType(), null /* need dict with used var names*/, prefix: "stateMachineCopy"); stmts.Add(BoogieStatement.VariableDeclaration(stateMachineVar)); stmts.Add(BoogieStatement.VariableDeclaration(boogieGetTypeRes)); stmts.Add(BoogieStatement.FromString($"{stateMachineVar.Expr} := stateMachine;")); foreach (var asyncMethod in Helpers.asyncMoveNexts) { var asyncType = asyncMethod.ContainingTypeDefinition; var bg = BoogieGenerator.Instance(); stmts.Add(bg.ProcedureCall(BoogieMethod.GetTypeMethod, new List <Expression> { stateMachineVar }, boogieGetTypeRes)); StatementList ifStmts = new StatementList(); ifStmts.Add(BoogieGenerator.Instance().ProcedureCall(BoogieMethod.From(asyncMethod), new List <Expression> { stateMachineVar })); stmts.Add(BoogieStatement.If(Expression.Subtype(boogieGetTypeRes, asyncType), ifStmts)); } stmts.Add(BoogieStatement.FromString($"v0$out := {stateMachineVar.Expr};")); sw.WriteLine(@"procedure {:extern} System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.Start``1$``0$(this : Ref,stateMachine : Ref) returns (v0$out : Ref) {"); foreach (var stmt in stmts) { sw.WriteLine(stmt.Stmt); } sw.WriteLine("}"); }
public override StatementList AllocLocalVariables(IList <IVariable> variables) { StatementList stmts = new StatementList(); // we allocate an address for all local variables // except they are a pointer, we are assuming that you can't take the address of a pointer foreach (var v in variables) { if (!(v.Type is IManagedPointerType)) { stmts.Add(dispatcher.AllocAddr(v)); } } // load values into stack space foreach (var paramVariable in variables.Where(v => v.IsParameter)) { // paramValue are variables in the three address code // however in boogie they are treated as values // those values are loaded into the stack memory space /* * void foo(int x){ * } * * procedure foo(x : int){ * var _x : Addr; // stack space (done in previous loop) * x_ := AllocAddr(); * * data(_x) := x; // we are doing this conceptually * } */ var boogieParamVariable = BoogieParameter.FromDotNetVariable(paramVariable); if (paramVariable.Type is IManagedPointerType) { stmts.Add(BoogieStatement.VariableAssignment(BoogieVariable.AddressVar(paramVariable), boogieParamVariable)); continue; } Addressable paramAddress = dispatcher.AddressOf(paramVariable); // boogie generator knows that must fetch paramVariable's address (_x and not x) stmts.Add(dispatcher.WriteAddr(paramAddress, boogieParamVariable)); if (Helpers.GetBoogieType(paramVariable).Equals(Helpers.BoogieType.Object)) { stmts.Add(BoogieStatement.AllocObjectAxiom(paramVariable)); } else if (Helpers.GetBoogieType(paramVariable).Equals(Helpers.BoogieType.Addr)) { stmts.Add(BoogieStatement.AllocAddrAxiom(paramVariable)); } } return(stmts); }
public override StatementList VariableAssignment(IVariable variableA, IValue value) { Constant cons = value as Constant; BoogieLiteral boogieConstant = null; if (cons != null) { boogieConstant = BoogieLiteral.FromDotNetConstant(cons); } var boogieType = Helpers.GetBoogieType(variableA); if (value is Constant) { if (boogieConstant != null) { return(bg.VariableAssignment(variableA, boogieConstant)); } else { throw new NotImplementedException(); // return WriteAddr(variableA, value.ToString()); } } else if (value is IVariable && !(value.Type is IManagedPointerType)) { // right operand is not a pointer (therefore left operand is not a pointer) return(dispatcher.WriteAddr(dispatcher.AddressOf(variableA), dispatcher.ReadAddr(value as IVariable))); } else if (value is Dereference) { var dereference = value as Dereference; var content = dispatcher.ReadAddr(dereference.Reference); return(dispatcher.WriteAddr(dispatcher.AddressOf(variableA), content)); } else if (value.Type is IManagedPointerType) { // if the right operand is a pointer also the left one is a pointer // there are two cases for value: // 1) value has the form &<something> (in analysis-net this is a Reference object) // 2) value is just a variable (static, instance, local, array element) with pointer type // for 1) we want to take the allocated address of something and assign it to the boogie variable of the left operand // for 2) we just want to make a boogie assignment between the boogie variables of the left and right operands // AddressOf will do the work to separate case 1) and 2) var addr = dispatcher.AddressOf(value) as AddressExpression; Contract.Assume(addr != null); return(BoogieStatement.VariableAssignment(BoogieVariable.AddressVar(variableA), addr.Expr)); } Contract.Assert(false); // This shouldn't be reachable. throw new NotImplementedException(); }
public string SetProcedureStub(IMethodReference method) { FieldTranslator field = new FieldTranslator(); var boogieName = field.BoogieNameForField(method.ContainingType, GetFieldName(method)); var paramType = Helpers.GetBoogieType(method.Parameters.ElementAt(0)); var get = new StatementList(); get.Add(BoogieStatement.FromString(boogieName + "[obj] := " + "val;")); var t = new BoogieProcedureTemplate(BoogieMethod.From(method).Name, "", StatementList.Empty, get, "obj : Ref, val : " + paramType, String.Empty, false); return(t.TransformText()); }
public string GetProcedureStub(IMethodReference method) { FieldTranslator field = new FieldTranslator(); var boogieName = field.BoogieNameForField(method.ContainingType, GetFieldName(method)); var boogieType = Helpers.GetBoogieType(method.Type); var get = new StatementList(); get.Add(BoogieStatement.FromString("$result := " + boogieName + "[obj];")); var t = new BoogieProcedureTemplate(BoogieMethod.From(method).Name, "", StatementList.Empty, get, "obj : Ref", String.Format(" returns ( $result : {0})", boogieType.ToString()), false); return(t.TransformText()); }
public override StatementList DeclareLocalVariables(IList <IVariable> variables, Dictionary <string, BoogieVariable> temporalVariables) { StatementList stmts = new StatementList(); foreach (var v in variables.Where(v => !v.IsParameter)) { stmts.Add(BoogieStatement.VariableDeclaration(v)); } foreach (var kv in temporalVariables) { stmts.Add(BoogieStatement.VariableDeclaration(kv.Value)); } return(stmts); }
// hides implementation in super class //public new string VariableAssignment(string variableA, string expr) //{ // return string.Format("{0} := {1};", variableA, expr); //} public override StatementList DeclareLocalVariables(IList <IVariable> variables, Dictionary <string, BoogieVariable> temporalVariables) { var stmts = new StatementList(); foreach (var v in variables) { stmts.Add(BoogieStatement.VariableDeclaration(BoogieVariable.AddressVar(v))); } foreach (var kv in temporalVariables) { stmts.Add(BoogieStatement.VariableDeclaration(kv.Value)); } return(stmts); }
public override StatementList AllocLocalVariables(IList <IVariable> variables) { StatementList stmts = new StatementList(); // only allocate an address for variables that are referenced foreach (var v in variables) { if (RequiresAllocation(v)) { stmts.Add(AllocAddr(v)); } } foreach (var paramVariable in variables.Where(v => v.IsParameter && (RequiresAllocation(v) || (v.Type is IManagedPointerType)))) { var boogieParamVariable = BoogieParameter.FromDotNetVariable(paramVariable); //if (!RequiresAllocation(paramVariable)) if (paramVariable.Type is IManagedPointerType) { //BoogieVariable target = RequiresAllocation(paramVariable) || (paramVariable.Type is IManagedPointerType) ? // BoogieVariable.AddressVar(paramVariable) : BoogieVariable.FromDotNetVariable(paramVariable); BoogieVariable target = BoogieVariable.AddressVar(paramVariable); stmts.Add(BoogieStatement.VariableAssignment(target, boogieParamVariable)); continue; } Addressable paramAddress = AddressOf(paramVariable); // boogie generator knows that must fetch paramVariable's address (_x and not x) stmts.Add(WriteAddr(paramAddress, boogieParamVariable)); if (Helpers.GetBoogieType(paramVariable).Equals(Helpers.BoogieType.Object)) { stmts.Add(BoogieStatement.AllocObjectAxiom(paramVariable)); } else if (Helpers.GetBoogieType(paramVariable).Equals(Helpers.BoogieType.Addr)) { stmts.Add(BoogieStatement.AllocAddrAxiom(paramVariable)); } } return(stmts); }
public string AsyncStubsScheduleTask(bool genericVersion = false) { StatementList localVars = new StatementList(); localVars.Add(BoogieStatement.FromString("var state : bool;")); StatementList instructions = new StatementList(); var param0 = new BoogieVariable(Helpers.BoogieType.Object, "sm"); var procIsCompleted = genericVersion ? BoogieMethod.AsyncStubsTaskAwaiterIsCompletedGeneric : BoogieMethod.AsyncStubsTaskAwaiterIsCompleted; var awaiterVar = new BoogieVariable(Helpers.BoogieType.Object, "awaiter"); var stateVar = new BoogieVariable(Helpers.BoogieType.Bool, "state"); var argsList = new List <Expression>(); argsList.Add(awaiterVar); var resList = new List <BoogieVariable>(); resList.Add(stateVar); var callIsCompleted = BoogieStatement.ProcedureCall(procIsCompleted, argsList, resList, stateVar); var assume = BoogieStatement.Assume(Expression.BinaryOperationExpression(stateVar, new Expression(Helpers.BoogieType.Bool, "true"), Backend.ThreeAddressCode.Instructions.BinaryOperation.Eq)); var yield = BoogieStatement.FromString("yield;"); // it is crucial to yield before anything else instructions.Add(yield); instructions.Add(callIsCompleted); instructions.Add(assume); var moveNextMethods = stateMachinesTypes.Select(t => t.Members.Where(m => m.Name.Value.Contains("MoveNext")).First()).Cast <IMethodDefinition>(); var ifCases = moveNextMethods.Select(m => Invoke(m, param0)); foreach (var ifCase in ifCases) { instructions.Add(ifCase); } string procedureName = genericVersion ? "$AsyncStubs`1$ScheduleTask" : "$AsyncStubs$ScheduleTask"; var procedureTemplate = new BoogieProcedureTemplate(procedureName, "", localVars, instructions, "awaiter : Object, sm : Object", String.Empty, false); return(procedureTemplate.TransformText()); }
public static void CreateAllAsyncMethods(StreamWriter sw) { StatementList stmts = new StatementList(); Action <StatementList> fStmt = (s => stmts.Add(s)); Action <string> fStr = (s => fStmt(BoogieStatement.FromString(s))); var taskVar = BoogieVariable.GetTempVar(Helpers.ObjectType(), null, "task"); var objectTypeStr = Helpers.ObjectType().FirstUppercase(); fStr($"var resultAsync : [{objectTypeStr}] {objectTypeStr};"); fStr($"var builder2task: [{objectTypeStr}] {objectTypeStr};"); fStr($"procedure {{:extern}} System.Threading.Tasks.Task`1.get_Result(this : {objectTypeStr}) returns ($result : {objectTypeStr}) {{"); fStr("$result := resultAsync[this];"); fStr("}"); fStr(""); fStr($"procedure {{:extern}} System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.Create() returns ($result : {objectTypeStr}) {{"); fStmt(BoogieStatement.VariableDeclaration(taskVar)); var bg = BoogieGenerator.Instance(); fStmt(bg.AllocObject(taskVar)); fStmt(BoogieStatement.Assume(Expression.IsTask(taskVar))); var resultVar = BoogieVariable.ResultVar(Helpers.ObjectType()); fStmt(bg.AllocObject(resultVar)); fStmt(BoogieStatement.Assume(Expression.IsAsyncTaskMethodBuilder(resultVar))); fStr($"builder2task[$result] := {taskVar.Expr};"); fStr("}"); fStr($"procedure {{:extern}} System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.get_Task(this : {objectTypeStr}) returns ($result : {objectTypeStr}) {{"); fStr("$result := builder2task[this];"); fStr("}"); fStr($"procedure {{:extern}} System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.SetResult$`0(this : {objectTypeStr},result : {objectTypeStr}) {{"); fStr($"var task : {objectTypeStr};"); fStr("task := builder2task[this];"); fStr($"resultAsync[task] := result;"); fStr("}"); foreach (var stmt in stmts) { sw.WriteLine(stmt.Stmt); } CreateAsyncStartMethod(sw); }
public override StatementList WriteAddr(Addressable addr, Expression expr) { if (addr is AddressExpression addrExpr) { if (expr.Type.Equals(Helpers.BoogieType.Addr)) { // pointer = pointer does not require map indexing in boogie // it is just a variable assignment BoogieVariable v = new BoogieVariable(expr.Type, addrExpr.Expr.Expr); return(BoogieStatement.VariableAssignment(v, expr)); } return(TypedMemoryMapUpdate.ForKeyValue(addrExpr, expr)); } else { throw new NotImplementedException(); } }
private StatementList Invoke(IMethodDefinition member, BoogieVariable receiver) { Expression receiverObject = receiver; if (receiver.Type.Equals(Helpers.BoogieType.Addr)) { AddressExpression addrExpr = new AddressExpression(member.ContainingType, receiver); receiverObject = BoogieGenerator.Instance().ReadAddr(addrExpr); } Expression subtype = Expression.Subtype(Expression.DynamicType(receiverObject), member.ContainingType); StatementList body = new StatementList(); List <Expression> argumentList = new List <Expression>(); argumentList.Add(receiverObject); body.Add(BoogieGenerator.Instance().ProcedureCall(BoogieMethod.From(member), argumentList)); body.Add(BoogieStatement.ReturnStatement); var ifExpr = BoogieStatement.If(subtype, body); return(ifExpr); }
public override StatementList DeclareLocalVariables(IList <IVariable> variables, Dictionary <string, BoogieVariable> temporalVariables) { var stmts = new StatementList(); foreach (var v in variables) { if (RequiresAllocation(v) || v.Type is IManagedPointerType) { stmts.Add(BoogieStatement.VariableDeclaration(BoogieVariable.AddressVar(v))); } else if (!v.IsParameter) { stmts.Add(BoogieStatement.VariableDeclaration(v)); } } foreach (var kv in temporalVariables) { stmts.Add(BoogieStatement.VariableDeclaration(kv.Value)); } return(stmts); }