private void TranslateDelegateCreation(IMethodReference methodToCall, ITypeReference type, IExpression creationAST) { Bpl.IToken cloc = creationAST.Token(); var a = this.sink.CreateFreshLocal(creationAST.Type); ITypeDefinition unspecializedType = Microsoft.Cci.MutableContracts.ContractHelper.Unspecialized(type.ResolvedType).ResolvedType; IMethodDefinition unspecializedMethod = ResolveUnspecializedMethodOrThrow(methodToCall); sink.AddDelegate(unspecializedType, unspecializedMethod); Bpl.Constant constant = sink.FindOrCreateDelegateMethodConstant(unspecializedMethod); Bpl.Expr methodExpr = Bpl.Expr.Ident(constant); Bpl.Expr instanceExpr = TranslatedExpressions.Pop(); List<Bpl.Expr> typeParameterExprs = new List<Bpl.Expr>(); if (unspecializedMethod.IsStatic) { List<ITypeReference> consolidatedTypeArguments = new List<ITypeReference>(); Sink.GetConsolidatedTypeArguments(consolidatedTypeArguments, methodToCall.ContainingType); foreach (ITypeReference typeReference in consolidatedTypeArguments) { typeParameterExprs.Add(this.sink.FindOrCreateTypeReferenceInCodeContext(typeReference)); } } IGenericMethodInstanceReference methodInstanceReference = methodToCall as IGenericMethodInstanceReference; if (methodInstanceReference != null) { foreach (ITypeReference typeReference in methodInstanceReference.GenericArguments) { typeParameterExprs.Add(this.sink.FindOrCreateTypeReferenceInCodeContext(typeReference)); } } Bpl.Expr typeParameterExpr = new Bpl.NAryExpr(Bpl.Token.NoToken, new Bpl.FunctionCall(this.sink.FindOrCreateNaryTypeFunction(typeParameterExprs.Count)), typeParameterExprs); this.StmtTraverser.StmtBuilder.Add( new Bpl.CallCmd(cloc, this.sink.DelegateCreate(unspecializedType), new List<Bpl.Expr>(new Bpl.Expr[] {methodExpr, instanceExpr, typeParameterExpr}), new List<Bpl.IdentifierExpr>(new Bpl.IdentifierExpr[] {Bpl.Expr.Ident(a)}))); TranslatedExpressions.Push(Bpl.Expr.Ident(a)); }
private void VisitAssignment(ITargetExpression target, IExpression source, SourceTraverser sourceTraverser, bool treatAsStatement, bool pushTargetRValue, bool resultIsInitialTargetRValue) { Contract.Requires(target != null); Contract.Requires(source != null); Contract.Requires(sourceTraverser != null); Contract.Requires(!resultIsInitialTargetRValue || pushTargetRValue); Contract.Requires(!pushTargetRValue || source is IBinaryOperation); var tok = source.Token(); var typ = source.Type; var structCopy = TranslationHelper.IsStruct(typ) && !(source is IDefaultValue); // then a struct value of type S is being assigned: "lhs := s" // model this as the statement "call lhs := S..#copy_ctor(s)" that does the bit-wise copying Bpl.DeclWithFormals proc = null; if (structCopy) { proc = this.sink.FindOrCreateProcedureForStructCopy(typ); } object container = target.Definition; Top: ILocalDefinition/*?*/ local = container as ILocalDefinition; if (local != null) { if (source is IDefaultValue && !local.Type.ResolvedType.IsReferenceType) { // this.LoadAddressOf(local, null); // this.generator.Emit(OperationCode.Initobj, local.Type); // if (!treatAsStatement) this.LoadLocal(local); } else { Bpl.IdentifierExpr temp = null; var bplLocal = Bpl.Expr.Ident(this.sink.FindOrCreateLocalVariable(local)); if (pushTargetRValue) { this.TranslatedExpressions.Push(bplLocal); if (!treatAsStatement && resultIsInitialTargetRValue) { var loc = this.sink.CreateFreshLocal(source.Type); temp = Bpl.Expr.Ident(loc); var e3 = this.TranslatedExpressions.Pop(); var cmd3 = Bpl.Cmd.SimpleAssign(tok, temp, e3); this.StmtTraverser.StmtBuilder.Add(cmd3); this.TranslatedExpressions.Push(temp); } } sourceTraverser(source); var e = this.TranslatedExpressions.Pop(); if (temp != null) this.TranslatedExpressions.Push(temp); Bpl.Cmd cmd; if (structCopy) { cmd = new Bpl.CallCmd(tok, proc.Name, new List<Bpl.Expr> { e, }, new List<Bpl.IdentifierExpr> { bplLocal, }); } else { cmd = Bpl.Cmd.SimpleAssign(tok, bplLocal, e); } StmtTraverser.StmtBuilder.Add(cmd); if (!treatAsStatement && !resultIsInitialTargetRValue) { this.TranslatedExpressions.Push(bplLocal); } } return; } IParameterDefinition/*?*/ parameter = container as IParameterDefinition; if (parameter != null) { if (source is IDefaultValue && !parameter.Type.ResolvedType.IsReferenceType) { //this.LoadAddressOf(parameter, null); //this.generator.Emit(OperationCode.Initobj, parameter.Type); //if (!treatAsStatement) this.LoadParameter(parameter); } else { Bpl.IdentifierExpr temp = null; if (pushTargetRValue) { this.LoadParameter(parameter); if (!treatAsStatement && resultIsInitialTargetRValue) { var loc = this.sink.CreateFreshLocal(source.Type); temp = Bpl.Expr.Ident(loc); var e3 = this.TranslatedExpressions.Pop(); var cmd3 = Bpl.Cmd.SimpleAssign(tok, temp, e3); this.StmtTraverser.StmtBuilder.Add(cmd3); this.TranslatedExpressions.Push(temp); } } sourceTraverser(source); var e = this.TranslatedExpressions.Pop(); if (temp != null) this.TranslatedExpressions.Push(temp); var bplParam = Bpl.Expr.Ident(this.sink.FindParameterVariable(parameter, this.contractContext)); Bpl.Cmd cmd; if (structCopy) { cmd = new Bpl.CallCmd(tok, proc.Name, new List<Bpl.Expr> { e, bplParam, }, new List<Bpl.IdentifierExpr>()); } else { cmd = Bpl.Cmd.SimpleAssign(tok, bplParam, e); } StmtTraverser.StmtBuilder.Add(cmd); if (!treatAsStatement && !resultIsInitialTargetRValue) { this.LoadParameter(parameter); } } return; } IFieldReference/*?*/ field = container as IFieldReference; if (field != null) { var f = Bpl.Expr.Ident(this.sink.FindOrCreateFieldVariable(field)); var boogieTypeOfField = sink.CciTypeToBoogie(field.Type); if (source is IDefaultValue && !field.Type.ResolvedType.IsReferenceType) { //this.LoadAddressOf(field, target.Instance); //if (!treatAsStatement) { // this.generator.Emit(OperationCode.Dup); // this.StackSize++; //} //this.generator.Emit(OperationCode.Initobj, field.Type); //if (!treatAsStatement) // this.generator.Emit(OperationCode.Ldobj, field.Type); //else // this.StackSize--; } else { Bpl.Expr x = null; Bpl.IdentifierExpr temp = null; if (pushTargetRValue) { if (target.Instance != null) { this.Traverse(target.Instance); x = this.TranslatedExpressions.Pop(); AssertOrAssumeNonNull(tok, x); var e2 = this.sink.Heap.ReadHeap(x, f, TranslationHelper.IsStruct(field.ContainingType) ? AccessType.Struct : AccessType.Heap, boogieTypeOfField); this.TranslatedExpressions.Push(e2); } else { TranslatedExpressions.Push(f); } if (!treatAsStatement && resultIsInitialTargetRValue) { var loc = this.sink.CreateFreshLocal(source.Type); temp = Bpl.Expr.Ident(loc); var e3 = this.TranslatedExpressions.Pop(); var cmd = Bpl.Cmd.SimpleAssign(tok, temp, e3); this.StmtTraverser.StmtBuilder.Add(cmd); this.TranslatedExpressions.Push(temp); } } sourceTraverser(source); if (!treatAsStatement && !resultIsInitialTargetRValue) { var loc = this.sink.CreateFreshLocal(source.Type); temp = Bpl.Expr.Ident(loc); var e3 = this.TranslatedExpressions.Pop(); var cmd = Bpl.Cmd.SimpleAssign(tok, temp, e3); this.StmtTraverser.StmtBuilder.Add(cmd); this.TranslatedExpressions.Push(temp); } var e = this.TranslatedExpressions.Pop(); if (temp != null) this.TranslatedExpressions.Push(temp); if (target.Instance == null) { // static fields are not kept in the heap StmtTraverser.StmtBuilder.Add(Bpl.Cmd.SimpleAssign(tok, f, e)); } else { this.sink.Heap.WriteHeap(tok, x, f, e, field.ResolvedField.ContainingType.ResolvedType.IsStruct ? AccessType.Struct : AccessType.Heap, boogieTypeOfField, StmtTraverser.StmtBuilder); } } return; } VisitArrayIndexer: IArrayIndexer/*?*/ arrayIndexer = container as IArrayIndexer; if (arrayIndexer != null) { Contract.Assume(arrayIndexer.Indices.Count() == 1); // BUG: deal with multi-dimensional arrays if (source is IDefaultValue && !arrayIndexer.Type.ResolvedType.IsReferenceType) { // this.LoadAddressOf(arrayIndexer, target.Instance); // if (!treatAsStatement) { // this.generator.Emit(OperationCode.Dup); // this.StackSize++; // } // this.generator.Emit(OperationCode.Initobj, arrayIndexer.Type); // if (!treatAsStatement) // this.generator.Emit(OperationCode.Ldobj, arrayIndexer.Type); // else // this.StackSize--; } else { Bpl.IdentifierExpr/*?*/ temp = null; this.Traverse(arrayIndexer.IndexedObject); var arrayExpr = this.TranslatedExpressions.Peek(); this.Traverse(arrayIndexer.Indices); var indexExpr = this.TranslatedExpressions.Peek(); if (pushTargetRValue) { AssertOrAssumeNonNull(tok, arrayExpr); var e2 = this.sink.Heap.ReadHeap(arrayExpr, indexExpr, AccessType.Array, this.sink.CciTypeToBoogie(arrayIndexer.Type)); this.TranslatedExpressions.Push(e2); if (!treatAsStatement && resultIsInitialTargetRValue) { var loc = this.sink.CreateFreshLocal(source.Type); temp = Bpl.Expr.Ident(loc); var e3 = this.TranslatedExpressions.Pop(); var cmd = Bpl.Cmd.SimpleAssign(tok, temp, e3); this.StmtTraverser.StmtBuilder.Add(cmd); this.TranslatedExpressions.Push(temp); } } sourceTraverser(source); var e = this.TranslatedExpressions.Pop(); var indices_prime = this.TranslatedExpressions.Pop(); var x = this.TranslatedExpressions.Pop(); sink.Heap.WriteHeap(Bpl.Token.NoToken, x, indices_prime, e, AccessType.Array, sink.CciTypeToBoogie(arrayIndexer.Type), StmtTraverser.StmtBuilder); if (!treatAsStatement && !resultIsInitialTargetRValue) { AssertOrAssumeNonNull(tok, arrayExpr); var e2 = this.sink.Heap.ReadHeap(arrayExpr, indexExpr, AccessType.Array, this.sink.CciTypeToBoogie(arrayIndexer.Type)); this.TranslatedExpressions.Push(e2); } else { if (temp != null) this.TranslatedExpressions.Push(temp); } } return; } IAddressDereference/*?*/ addressDereference = container as IAddressDereference; if (addressDereference != null) { var addrOf = addressDereference.Address as IAddressOf; if (addrOf != null) { var arrayIndexer2 = addrOf.Expression.Definition as IArrayIndexer; if (arrayIndexer2 != null) { container = arrayIndexer2; goto VisitArrayIndexer; } } var be = addressDereference.Address as IBoundExpression; if (be != null) { container = be.Definition; goto Top; } this.Traverse(addressDereference.Address); if (source is IDefaultValue && !addressDereference.Type.ResolvedType.IsReferenceType) { //if (!treatAsStatement) { // this.generator.Emit(OperationCode.Dup); // this.StackSize++; //} //this.generator.Emit(OperationCode.Initobj, addressDereference.Type); //if (!treatAsStatement) // this.generator.Emit(OperationCode.Ldobj, addressDereference.Type); //else // this.StackSize--; } else if (source is IAddressDereference) { //if (!treatAsStatement) { // this.generator.Emit(OperationCode.Dup); // this.StackSize++; //} //this.Traverse(((IAddressDereference)source).Address); //this.generator.Emit(OperationCode.Cpobj, addressDereference.Type); //this.StackSize -= 2; //if (!treatAsStatement) // this.generator.Emit(OperationCode.Ldobj, addressDereference.Type); } else { Bpl.IdentifierExpr/*?*/ temp = null; if (pushTargetRValue) { this.TranslatedExpressions.Push(this.TranslatedExpressions.Peek()); if (!treatAsStatement && resultIsInitialTargetRValue) { this.TranslatedExpressions.Push(this.TranslatedExpressions.Peek()); var loc = this.sink.CreateFreshLocal(source.Type); temp = Bpl.Expr.Ident(loc); var e3 = this.TranslatedExpressions.Pop(); var cmd = Bpl.Cmd.SimpleAssign(tok, temp, e3); this.StmtTraverser.StmtBuilder.Add(cmd); this.TranslatedExpressions.Push(temp); } } sourceTraverser(source); if (!treatAsStatement && !resultIsInitialTargetRValue) { this.TranslatedExpressions.Push(this.TranslatedExpressions.Peek()); var loc = this.sink.CreateFreshLocal(source.Type); temp = Bpl.Expr.Ident(loc); var e3 = this.TranslatedExpressions.Pop(); var cmd = Bpl.Cmd.SimpleAssign(tok, temp, e3); this.StmtTraverser.StmtBuilder.Add(cmd); this.TranslatedExpressions.Push(temp); } //this.VisitAssignmentTo(addressDereference); if (temp != null) this.TranslatedExpressions.Push(temp); } return; } IPropertyDefinition/*?*/ propertyDefinition = container as IPropertyDefinition; if (propertyDefinition != null) { Contract.Assume(propertyDefinition.Getter != null && propertyDefinition.Setter != null); if (!propertyDefinition.IsStatic) { this.Traverse(target.Instance); } Bpl.IdentifierExpr temp = null; var token = Bpl.Token.NoToken; if (pushTargetRValue) { List<Bpl.Expr> inexpr; List<Bpl.IdentifierExpr> outvars; Bpl.IdentifierExpr thisExpr; Dictionary<Bpl.IdentifierExpr, Tuple<Bpl.IdentifierExpr, bool>> toBoxed; var proc2 = TranslateArgumentsAndReturnProcedure(token, propertyDefinition.Getter, propertyDefinition.Getter.ResolvedMethod, target.Instance, Enumerable<IExpression>.Empty, out inexpr, out outvars, out thisExpr, out toBoxed); EmitLineDirective(token); this.StmtTraverser.StmtBuilder.Add(new Bpl.CallCmd(token, proc2.Name, inexpr, outvars)); if (!treatAsStatement && resultIsInitialTargetRValue) { //var //this.generator.Emit(OperationCode.Dup); //this.StackSize++; //temp = new TemporaryVariable(source.Type, this.method); //this.VisitAssignmentTo(temp); } } sourceTraverser(source); if (!treatAsStatement && !resultIsInitialTargetRValue) { var e3 = this.TranslatedExpressions.Pop(); var loc = this.sink.CreateFreshLocal(source.Type); temp = Bpl.Expr.Ident(loc); var cmd = Bpl.Cmd.SimpleAssign(tok, temp, e3); this.StmtTraverser.StmtBuilder.Add(cmd); this.TranslatedExpressions.Push(temp); } var setterArgs = new List<Bpl.Expr>(); var setterArg = this.TranslatedExpressions.Pop(); if (!propertyDefinition.IsStatic) setterArgs.Add(this.TranslatedExpressions.Pop()); setterArgs.Add(setterArg); var setterProc = this.sink.FindOrCreateProcedure(propertyDefinition.Setter.ResolvedMethod); EmitLineDirective(token); this.StmtTraverser.StmtBuilder.Add(new Bpl.CallCmd(token, setterProc.Decl.Name, setterArgs, new List<Bpl.IdentifierExpr>())); if (temp != null) this.TranslatedExpressions.Push(temp); return; } Contract.Assume(false); }