5 // Alexander Chebaturkin (chebaturkin@gmail.com)
7 // Copyright (C) 2011 Alexander Chebaturkin
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 using System.Collections.Generic;
32 using Mono.CodeContracts.Static.AST;
33 using Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths;
34 using Mono.CodeContracts.Static.Analysis.HeapAnalysis.SymbolicGraph;
35 using Mono.CodeContracts.Static.ControlFlow;
36 using Mono.CodeContracts.Static.DataStructures;
37 using Mono.CodeContracts.Static.Lattices;
38 using Mono.CodeContracts.Static.Providers;
40 namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis {
41 class Domain : IAbstractDomain<Domain> {
42 private static Domain BottomValue;
43 public readonly FunctionsTable Functions;
44 private readonly Dictionary<APC, Domain> begin_old_saved_states;
45 private readonly SymGraph<SymFunction, AbstractType> egraph;
46 private readonly HeapAnalysis parent;
47 private TypeCache IEnumerable1Type = new TypeCache (@"System.Collections.IEnumerable`1");
48 private TypeCache IEnumerableType = new TypeCache (@"System.Collections.IEnumerable");
50 public IImmutableSet<SymValue> ModifiedAtCall;
51 private IImmutableMap<SymValue, SymFunction> constantLookup;
52 private IImmutableSet<SymValue> unmodifiedFieldsSinceEntry;
53 private IImmutableSet<SymValue> unmodifiedSinceEntry;
55 private Domain (SymGraph<SymFunction, AbstractType> newEgraph,
56 IImmutableMap<SymValue, SymFunction> constantMap,
57 IImmutableSet<SymValue> unmodifiedSinceEntry, IImmutableSet<SymValue> unmodifiedFieldsSinceEntry, IImmutableSet<SymValue> modifiedAtCall,
58 Domain from, Domain oldDomain)
60 this.egraph = newEgraph;
61 this.Functions = from.Functions;
62 this.parent = from.parent;
63 this.begin_old_saved_states = from.begin_old_saved_states;
64 this.constantLookup = constantMap;
65 this.unmodifiedSinceEntry = unmodifiedSinceEntry;
66 this.unmodifiedFieldsSinceEntry = unmodifiedFieldsSinceEntry;
67 this.ModifiedAtCall = modifiedAtCall;
68 this.InsideOld = from.InsideOld;
69 OldDomain = oldDomain;
70 BeginOldPC = from.BeginOldPC;
73 public Domain (HeapAnalysis parent)
76 this.egraph = new SymGraph<SymFunction, AbstractType> (AbstractType.TopValue, AbstractType.BottomValue);
77 this.constantLookup = ImmutableIntKeyMap<SymValue, SymFunction>.Empty (SymValue.GetUniqueKey);
78 this.unmodifiedSinceEntry = ImmutableSet<SymValue>.Empty (SymValue.GetUniqueKey);
79 this.unmodifiedFieldsSinceEntry = ImmutableSet<SymValue>.Empty (SymValue.GetUniqueKey);
80 this.ModifiedAtCall = ImmutableSet<SymValue>.Empty (SymValue.GetUniqueKey);
81 this.Functions = new FunctionsTable (parent.MetaDataProvider);
82 this.begin_old_saved_states = new Dictionary<APC, Domain> ();
84 SymValue nullValue = this.egraph.FreshSymbol ();
85 this.egraph [this.Functions.NullValue] = nullValue;
86 this.egraph [nullValue] = AbstractType.BottomValue;
87 this.egraph [ConstantValue (0, MetaDataProvider.System_Int32)] = new AbstractType (MetaDataProvider.System_Int32, true);
90 public Domain OldDomain { get; set; }
91 public APC BeginOldPC { get; set; }
93 public SymValue Globals
95 get { return this.egraph.ConstRoot; }
100 get { return this.egraph [this.Functions.NullValue]; }
103 private SymValue Zero
105 get { return this.egraph [this.Functions.ZeroValue]; }
108 public SymValue VoidAddr
110 get { return this.egraph [this.Functions.VoidAddr]; }
113 private IMetaDataProvider MetaDataProvider
115 get { return this.parent.MetaDataProvider; }
118 public IEnumerable<SymValue> Variables
120 get { return this.egraph.Variables; }
123 #region IAbstractDomain<Domain> Members
124 public void Dump (TextWriter tw)
126 this.egraph.Dump (tw);
127 tw.WriteLine ("Unmodified locations:");
128 foreach (SymValue sv in this.unmodifiedSinceEntry.Elements)
129 tw.Write ("{0} ", sv);
132 tw.WriteLine ("Unmodified locations for fields:");
133 foreach (SymValue sv in this.unmodifiedFieldsSinceEntry.Elements)
134 tw.Write ("{0} ", sv);
137 if (this.ModifiedAtCall != null) {
138 tw.WriteLine ("Modified locations at last call");
139 foreach (SymValue sv in this.ModifiedAtCall.Elements)
140 tw.Write ("{0} ", sv);
143 if (OldDomain == null)
146 tw.WriteLine ("## has old domain ##");
147 OldDomain.egraph.Dump (tw);
148 tw.WriteLine ("## end old domain ##");
151 public Domain Clone ()
153 return new Domain (this.egraph.Clone (), this.constantLookup, this.unmodifiedSinceEntry, this.unmodifiedFieldsSinceEntry, this.ModifiedAtCall, this, OldDomain == null ? null : OldDomain.Clone ());
157 public static bool IsRootedInParameter (Sequence<PathElement> path)
159 return path.Head is PathElement<Parameter>;
162 public SymValue Address (Local local)
164 SymFunction function = this.Functions.For (local);
165 SymValue sv = this.egraph.TryLookup (function);
167 sv = this.egraph [function];
168 SetType (sv, MetaDataProvider.ManagedPointer (MetaDataProvider.LocalType (local)));
173 public SymValue Address (Parameter v)
175 SymFunction function = this.Functions.For (v);
176 SymValue sv = this.egraph.TryLookup (function);
178 sv = this.egraph [function];
179 SetType (sv, MetaDataProvider.ManagedPointer (MetaDataProvider.ParameterType (v)));
184 public SymValue Address (SymFunction v)
186 return this.egraph [v];
189 public SymValue Address (int v)
191 return Address (this.Functions.For (v));
194 public void AssignConst (int dest, TypeNode type, object constant)
196 AssignConst (Address (this.Functions.For (dest)), type, constant);
199 public void AssignConst (SymValue address, TypeNode type, object constant)
201 SymValue value = ConstantValue (constant, type);
202 SetType (address, MetaDataProvider.ManagedPointer (type));
203 this.egraph [this.Functions.ValueOf, address] = value;
205 var str = constant as string;
207 this.egraph [this.Functions.Length, value] = ConstantValue (str.Length, MetaDataProvider.System_Int32);
210 public void AssignValue (int dest, FlatDomain<TypeNode> type)
212 AssignValue (Address (this.Functions.For (dest)), type);
215 private void AssignValue (SymValue address, FlatDomain<TypeNode> type)
218 SetType (address, type.IsNormal() ? MetaDataProvider.ManagedPointer (type.Value) : type);
219 if (IsStructWithFields (type))
222 SymValue fresh = this.egraph.FreshSymbol ();
223 SetType (fresh, type);
224 this.egraph [this.Functions.ValueOf, address] = fresh;
226 if (!type.IsNormal())
229 if (NeedsArrayLengthManifested (type.Value))
230 ManifestArrayLength (fresh);
233 public void AssignNull (int addr)
235 AssignNull (Address (this.Functions.For (addr)));
238 public void AssignNull (SymValue addr)
241 this.egraph [this.Functions.ValueOf, addr] = Null;
244 private void AssignZero (SymValue addr)
246 this.egraph [this.Functions.ValueOf, addr] = Zero;
249 public void AssignZeroEquivalent (SymValue addr, TypeNode t)
251 if (MetaDataProvider.IsReferenceType (t))
253 else if (MetaDataProvider.HasValueRepresentation (t))
257 public void AssignSpecialUnary (int dest, SymFunction op, int source, FlatDomain<TypeNode> typeOfValue)
259 SymValue specialUnary = GetSpecialUnary (op, source, typeOfValue);
260 AssignSpecialUnary (dest, specialUnary, typeOfValue);
263 public void AssignSpecialUnary (int dest, SymValue result, FlatDomain<TypeNode> typeOfValue)
265 SymValue address = Address (dest);
266 AssignValue (address, typeOfValue);
267 this.egraph [this.Functions.ValueOf, address] = result;
270 public void AssignPureBinary (int dest, BinaryOperator op, FlatDomain<TypeNode> typeOpt, int op1, int op2)
272 var args = new[] {Value (op1), Value (op2)};
273 SymFunction c = this.Functions.For (op);
274 TypeNode type = !typeOpt.IsNormal() ? MetaDataProvider.System_Int32 : typeOpt.Value;
278 SymValue pointerValue = LookupAddressAndManifestType (args, c, type, out fresh);
279 SymValue destAddr = Address (dest);
281 SetType (destAddr, MetaDataProvider.ManagedPointer (type));
282 this.egraph [this.Functions.ValueOf, destAddr] = pointerValue;
285 public void AssignPureUnary (int dest, UnaryOperator op, FlatDomain<TypeNode> typeOpt, int operand)
287 SymFunction c = this.Functions.For (op);
288 TypeNode type = !typeOpt.IsNormal() ? MetaDataProvider.System_Int32 : typeOpt.Value;
290 SymValue unaryOperand = this.egraph [c, Value (operand)];
291 SymValue sv = Address (dest);
293 SetType (sv, MetaDataProvider.ManagedPointer (type));
294 this.egraph [this.Functions.ValueOf, sv] = unaryOperand;
297 private SymValue ConstantValue (object constant, TypeNode type)
299 SymFunction symFunction = this.Functions.ForConstant (constant, type);
300 SymValue sv = this.egraph.TryLookup (symFunction);
302 sv = this.egraph [symFunction];
304 this.constantLookup = this.constantLookup.Add (sv, symFunction);
309 public void Havoc (int i)
314 public void Havoc (SymValue addr)
316 this.egraph.EliminateAll (addr);
319 private void HavocIfStruct (SymValue address)
321 AbstractType aType = this.egraph [address];
322 if (aType.IsBottom || (aType.IsNormal() && MetaDataProvider.IsStruct (aType.ConcreteType)))
326 private void HavocMutableFields (SymFunction except, SymValue address, ref IImmutableSet<SymValue> havoced)
328 HavocFields (except, address, ref havoced, false);
331 private void HavocFields (SymFunction except, SymValue address, ref IImmutableSet<SymValue> havoced, bool havocImmutable)
333 if (havoced.Contains (address))
336 havoced = havoced.Add (address);
337 MakeTotallyModified (address);
338 foreach (SymFunction c in this.egraph.Functions (address))
339 HavocConstructor (except, address, c, ref havoced, havocImmutable);
342 private void HavocConstructor (SymFunction except, SymValue address, SymFunction c, ref IImmutableSet<SymValue> havoced, bool havocImmutable)
344 if (c == this.Functions.ValueOf)
345 this.egraph [this.Functions.OldValueOf, address] = this.egraph [c, address];
346 if (c == this.Functions.ValueOf || c == this.Functions.ObjectVersion || c == this.Functions.StructId) {
347 this.egraph.Eliminate (c, address);
348 havoced = havoced.Add (address);
350 var fieldWrapper = c as Wrapper<Field>;
351 if (fieldWrapper != null && fieldWrapper != except) {
352 if (havocImmutable || !MetaDataProvider.IsReadonly (fieldWrapper.Item))
353 HavocFields (except, this.egraph [c, address], ref havoced, havocImmutable);
358 var methodWrapper = c as Wrapper<Method>;
359 if (methodWrapper != null && methodWrapper != except)
360 HavocFields (except, this.egraph [c, address], ref havoced, havocImmutable);
364 public void HavocPseudoFields (SymValue address)
366 IImmutableSet<SymValue> havoced = ImmutableSet<SymValue>.Empty (SymValue.GetUniqueKey);
367 HavocPseudoFields (null, address, ref havoced);
370 private void HavocPseudoFields (SymFunction except, SymValue address, ref IImmutableSet<SymValue> havoced)
372 if (havoced.Contains (address))
374 havoced = havoced.Add (address);
375 if (IsUnmodified (address)) {
376 MakeModified (address);
377 MakeUnmodifiedField (address);
379 this.egraph.Eliminate (this.Functions.ObjectVersion, address);
380 this.egraph.Eliminate (this.Functions.StructId, address);
381 foreach (SymFunction c in this.egraph.Functions (address)) {
382 if (c != except && c is Wrapper<Method>)
383 HavocMutableFields (except, this.egraph [c, address], ref havoced);
387 private void HavocPseudoFields (SymFunction except, IEnumerable<Method> getters, SymValue address, ref IImmutableSet<SymValue> havoced)
389 if (havoced.Contains (address))
391 havoced = havoced.Add (address);
392 if (IsUnmodified (address)) {
393 MakeModified (address);
394 MakeUnmodifiedField (address);
396 this.egraph.Eliminate (this.Functions.ObjectVersion, address);
397 this.egraph.Eliminate (this.Functions.StructId, address);
398 foreach (Method m in getters)
399 HavocMutableFields (except, this.egraph [this.Functions.For (m), address], ref havoced);
402 public void HavocPseudoFields (IEnumerable<Method> getters, SymValue address)
404 IImmutableSet<SymValue> havoced = ImmutableSet<SymValue>.Empty (SymValue.GetUniqueKey);
405 HavocPseudoFields (null, getters, address, ref havoced);
408 private void MakeUnmodifiedField (SymValue address)
410 this.unmodifiedFieldsSinceEntry = this.unmodifiedFieldsSinceEntry.Add (address);
413 private void MakeModified (SymValue address)
415 this.unmodifiedSinceEntry = this.unmodifiedSinceEntry.Remove (address);
418 public void CopyValue (SymValue destAddr, SymValue sourceAddr)
420 AbstractType type = this.egraph [sourceAddr];
421 CopyValue (destAddr, sourceAddr, type.Type);
424 public void CopyValue (SymValue destAddr, SymValue sourceAddr, FlatDomain<TypeNode> addrType)
426 CopyValue (destAddr, sourceAddr, addrType, true, false);
429 private void CopyValue (SymValue destAddr, SymValue sourceAddr, FlatDomain<TypeNode> addrType, bool setTargetAddrType, bool cast)
431 MakeTotallyModified (destAddr);
432 if (destAddr != sourceAddr)
433 HavocIfStruct (destAddr);
434 if (setTargetAddrType)
435 SetType (destAddr, addrType);
437 SetValue (destAddr, sourceAddr, addrType, cast);
440 public void CopyOldValue (APC pc, int dest, int source, Domain target, bool atEndOld)
442 CopyOldValue (pc, target.Address (dest), Address (source), target, atEndOld);
445 public void CopyOldValue (APC pc, SymValue destAddr, SymValue srcAddr, Domain target, bool atEndOld)
447 AbstractType abstractType = this.egraph [srcAddr];
448 CopyOldValue (pc, destAddr, srcAddr, abstractType.Type, target, atEndOld);
451 private void CopyOldValue (APC pc, SymValue destAddr, SymValue srcAddr, FlatDomain<TypeNode> addrType, Domain target, bool atEndOld)
453 CopyOldValue (pc, destAddr, srcAddr, addrType, true, atEndOld, target);
456 private void CopyOldValue (APC pc, SymValue destAddr, SymValue srcAddr, FlatDomain<TypeNode> addrType, bool setTargetAddrType, bool atEndOld, Domain target)
458 target.MakeTotallyModified (destAddr);
459 if (destAddr != srcAddr)
460 target.HavocIfStruct (destAddr);
461 if (setTargetAddrType)
462 target.SetType (destAddr, addrType);
464 FlatDomain<TypeNode> targetType = TargetType (addrType);
466 if (IsStructWithFields (targetType))
467 CopyOldStructValue (pc, destAddr, srcAddr, targetType.Value, target, atEndOld);
468 else if (atEndOld && targetType.IsNormal() && MetaDataProvider.IsManagedPointer (targetType.Value)) {
469 srcAddr = TryValue (srcAddr);
472 destAddr = target.Value (destAddr);
473 CopyOldValue (pc, destAddr, srcAddr, targetType, setTargetAddrType, atEndOld, target);
475 SymValue source = this.egraph.TryLookup (this.Functions.ValueOf, srcAddr);
476 if (source == null) {
477 if (this.egraph.IsImmutable)
479 source = this.egraph [this.Functions.ValueOf, srcAddr];
481 CopyOldValueToDest (pc, destAddr, source, addrType, target);
485 public void CopyOldValueToDest (APC pc, SymValue destAddr, SymValue source, FlatDomain<TypeNode> addrType, Domain target)
487 if (pc.InsideEnsuresAtCall) {
491 if (IsConstant (source, out type, out constant)) {
492 SymValue sv = target.ConstantValue (constant, type);
493 target.CopyNonStructWithFieldValue (destAddr, sv, addrType);
497 foreach (var sv in GetAccessPathsRaw (source, AccessPathFilter<Method>.NoFilter, false))
498 throw new NotImplementedException ();
502 private IEnumerable<Sequence<PathElementBase>> GetAccessPathsRaw (SymValue sv, AccessPathFilter<Method> filter, bool compress)
504 var visited = new HashSet<SymValue> ();
505 return GetAccessPathsRaw (sv, null, visited, filter, compress);
508 private IEnumerable<Sequence<PathElementBase>> GetAccessPathsRaw (SymValue sv, Sequence<PathElementBase> path, HashSet<SymValue> visited, AccessPathFilter<Method> filter, bool compress)
510 if (sv == this.egraph.ConstRoot)
512 else if (!visited.Contains (sv)) {
514 foreach (var term in this.egraph.EqTerms (sv)) {
515 if (!(term.Function is Wrapper<object>) && !(term.Function is Wrapper<int>)) {
516 PathElementBase next = term.Function.ToPathElement (compress);
517 if (next != null && !filter.FilterOutPathElement (term.Function)) {
518 Sequence<PathElementBase> newPath;
520 if (path == null || !compress || (!(next is PathElement<Method>)))
521 newPath = path.Cons (next);
523 newPath = path.Tail.Cons (next);
525 foreach (var item in GetAccessPathsRaw (term.Args [0], newPath, visited, filter, compress))
533 private Sequence<PathElementBase> GetBestAccessPath (SymValue sv, AccessPathFilter<Method> filter, bool compress, bool allowLocal, bool preferLocal)
535 Sequence<PathElementBase> bestParameterPath = null;
536 Sequence<PathElementBase> bestLocalPath = null;
537 Sequence<PathElementBase> bestFieldMethodPath = null;
539 foreach (var path in GetAccessPathsFiltered (sv, filter, compress)) {
541 if (path.Head is PathElement<Parameter>) {
542 if (bestParameterPath == null || bestParameterPath.Length () > path.Length ())
543 bestParameterPath = path;
544 } else if (filter.AllowLocal && allowLocal && path.Head is PathElement<Local>) {
545 if (!path.Head.ToString ().Contains ("$") && (bestLocalPath == null || bestLocalPath.Length () > path.Length ()))
546 bestLocalPath = path;
547 } else if (path.Head is PathElement<Field> && path.Head.Func.IsStatic) {
548 if (bestFieldMethodPath == null || bestFieldMethodPath.Length () > path.Length ())
549 bestFieldMethodPath = path;
550 } else if (path.Head is PathElement<Method> && path.Head.Func.IsStatic) {
551 if (bestFieldMethodPath == null || bestFieldMethodPath.Length () > path.Length ())
552 bestFieldMethodPath = path;
556 if (preferLocal && bestLocalPath != null)
557 return bestLocalPath;
558 if (bestParameterPath != null)
559 return bestParameterPath;
560 if (allowLocal && bestLocalPath != null)
561 return bestLocalPath;
563 return bestFieldMethodPath;
566 public IEnumerable<Sequence<PathElementBase>> GetAccessPathsFiltered (SymValue sv, AccessPathFilter<Method> filter, bool compress)
568 return GetAccessPathsTyped (sv, filter, compress).Where (path => PathIsVisibleAccordingToFilter (path, filter));
571 private bool PathIsVisibleAccordingToFilter (Sequence<PathElementBase> path, AccessPathFilter<Method> filter)
573 if (path.Length () == 0 || !filter.HasVisibilityMember)
576 Method visibilityMember = filter.VisibilityMember;
577 TypeNode t = MetaDataProvider.DeclaringType (visibilityMember);
578 TypeNode type = default(TypeNode);
580 while (path != null) {
581 PathElement pathElement = path.Head;
582 if (!pathElement.TryGetResultType (out type))
584 while (MetaDataProvider.IsManagedPointer (type))
585 type = MetaDataProvider.ElementType (type);
586 if ("this" != pathElement.ToString ()) {
587 var peMethod = pathElement as PathElement<Method>;
588 if (peMethod != null) {
589 Method method = peMethod.Element;
590 if (!MetaDataProvider.IsVisibleFrom (method, t))
594 var peProperty = pathElement as PathElement<Property>;
595 if (peProperty != null) {
596 Property property = peProperty.Element;
598 if (!MetaDataProvider.HasGetter (property, out method))
599 MetaDataProvider.HasSetter (property, out method);
601 if (!MetaDataProvider.IsVisibleFrom (method, t))
605 var peField = pathElement as PathElement<Field>;
606 if (peField != null) {
607 Field field = peField.Element;
608 if (!MetaDataProvider.IsVisibleFrom (field, t))
617 private bool TryPropagateTypeInfo (Sequence<PathElementBase> path, out Sequence<PathElementBase> result)
623 PathElementBase head = path.Head;
625 if (!head.TrySetType (MetaDataProvider.System_IntPtr, MetaDataProvider, out prevType)) {
630 Sequence<PathElementBase> result1;
631 if (!TryPropagateTypeInfoRecurse (path.Tail, prevType, out result1)) {
635 if (head.IsAddressOf && head is PathElement<Parameter> && result1 != null && result1.Head.IsDeref) {
636 var pathElement = (PathElement<Parameter>) head;
637 result = result1.Tail.Cons (new ParameterPathElement (pathElement.Element, pathElement.Description, pathElement.Func, MetaDataProvider));
641 result = result1.Cons (head);
645 private bool TryPropagateTypeInfoRecurse (Sequence<PathElementBase> path, TypeNode prevType, out Sequence<PathElementBase> result)
651 PathElementBase head = path.Head;
652 if (head.TrySetType (prevType, MetaDataProvider, out prevType)) {
653 Sequence<PathElementBase> updatedPath;
654 if (TryPropagateTypeInfoRecurse (path.Tail, prevType, out updatedPath)) {
655 result = updatedPath.Cons (head);
664 private IEnumerable<Sequence<PathElementBase>> GetAccessPathsTyped (SymValue sv, AccessPathFilter<Method> filter, bool compress)
666 var visited = new HashSet<SymValue> ();
667 foreach (var path in GetAccessPathsRaw (sv, null, visited, filter, compress)) {
668 Sequence<PathElementBase> result;
669 if (TryPropagateTypeInfo (path, out result))
674 private void CopyNonStructWithFieldValue (SymValue destAddr, SymValue sv, FlatDomain<TypeNode> addrType)
676 this.egraph [this.Functions.ValueOf, destAddr] = sv;
677 SetType (destAddr, addrType);
680 public bool IsConstant (SymValue source, out TypeNode type, out object constant)
682 SymFunction c = this.constantLookup [source];
684 return this.Functions.IsConstant (c, out type, out constant);
686 type = default(TypeNode);
691 private void CopyOldStructValue (APC pc, SymValue destAddr, SymValue srcAddr, TypeNode type, Domain target, bool atEndOld)
693 throw new NotImplementedException ();
696 public void SetValue (SymValue destAddr, SymValue sourceAddr, FlatDomain<TypeNode> addrType, bool cast)
698 FlatDomain<TypeNode> type = TargetType (addrType);
699 if (IsStructWithFields (type))
700 CopyStructValue (destAddr, sourceAddr, type.Value);
702 CopyPrimValue (destAddr, sourceAddr, cast, type);
705 private void CopyPrimValue (SymValue destAddr, SymValue sourceAddr, bool cast, FlatDomain<TypeNode> elementType)
707 SymValue value = this.egraph [this.Functions.ValueOf, sourceAddr];
709 SetType (value, elementType);
711 SetTypeIfUnknown (value, elementType);
713 if (elementType.IsNormal()) {
714 if (NeedsArrayLengthManifested (elementType.Value))
715 ManifestArrayLength (value);
718 this.egraph [this.Functions.ValueOf, destAddr] = value;
721 public void CopyValueToOldState (APC pc, TypeNode type, int dest, int source, Domain target)
723 SymValue destAddress = target.Address (dest);
724 SymValue srcAddress = Address (source);
726 AbstractType aType = GetType (srcAddress);
727 TypeNode addrType = aType.IsNormal() ? aType.ConcreteType : MetaDataProvider.ManagedPointer (type);
728 CopyValueToOldState (pc, addrType, destAddress, srcAddress, target);
731 private void CopyValueToOldState (APC pc, TypeNode addrType, SymValue destAddress, SymValue srcAddress, Domain target)
733 target.MakeTotallyModified (destAddress);
734 if (destAddress != srcAddress)
735 target.HavocIfStruct (destAddress);
736 target.SetType (destAddress, addrType);
737 FlatDomain<TypeNode> targetType = TargetType (addrType);
738 if (IsStructWithFields (targetType))
739 CopyStructValueToOldState (pc, destAddress, srcAddress, targetType, target);
741 SymValue sv = this.egraph.TryLookup (this.Functions.ValueOf, srcAddress);
743 if (this.egraph.IsImmutable)
745 sv = this.egraph [this.Functions.ValueOf, srcAddress];
747 CopyPrimitiveValueToOldState (pc, addrType, destAddress, sv, target);
751 private void CopyPrimitiveValueToOldState (APC pc, TypeNode addrType, SymValue destAddress, SymValue sv, Domain target)
753 if (target.IsValidSymbol (sv))
754 target.CopyNonStructWithFieldValue (destAddress, sv, addrType);
756 target.Assign (destAddress, addrType);
759 private bool IsValidSymbol (SymValue sv)
761 return this.egraph.IsValidSymbol (sv);
764 private void Assign (SymValue destAddress, TypeNode addrType)
767 SetType (destAddress, addrType);
768 FlatDomain<TypeNode> targetType = TargetType (addrType);
769 if (IsStructWithFields (targetType))
772 SymValue fresh = this.egraph.FreshSymbol ();
773 SetType (fresh, targetType);
774 this.egraph [this.Functions.ValueOf, destAddress] = fresh;
775 if (!targetType.IsNormal())
778 if (NeedsArrayLengthManifested (targetType.Value))
779 ManifestArrayLength (fresh);
782 private void CopyStructValueToOldState (APC pc, SymValue destAddress, SymValue srcAddress, FlatDomain<TypeNode> targetType, Domain target)
784 throw new NotImplementedException ();
787 public void ManifestArrayLength (SymValue arrayValue)
789 SetType (this.egraph [this.Functions.Length, arrayValue], MetaDataProvider.System_Int32);
792 public bool NeedsArrayLengthManifested (TypeNode type)
794 return MetaDataProvider.IsArray (type) || MetaDataProvider.System_String.Equals (type);
797 public void CopyStructValue (SymValue destAddr, SymValue sourceAddr, TypeNode type)
799 if (destAddr == null)
801 this.egraph [this.Functions.StructId, destAddr] = this.egraph [this.Functions.StructId, sourceAddr];
802 foreach (SymFunction function in this.egraph.Functions (sourceAddr)) {
803 if (function.ActsAsField) {
804 TypeNode functionType = function.FieldAddressType ();
805 CopyValue (this.egraph [function, destAddr], this.egraph [function, sourceAddr], functionType);
810 public SymValue OldValueAddress (Parameter p)
812 return Address (OldValueParameterConstructor (p));
815 private SymFunction OldValueParameterConstructor (Parameter argument)
817 return this.Functions.For ("$OldParameter_" + MetaDataProvider.Name (argument));
820 public void CopyParameterIntoShadow (Parameter p)
822 CopyValue (Address (OldValueParameterConstructor (p)), Address (this.Functions.For (p)));
825 public void Copy (int dest, int source)
827 CopyValue (Address (this.Functions.For (dest)), Address (this.Functions.For (source)));
830 private bool IsIEnumerable (TypeNode type)
832 TypeNode ienumerableType;
833 return (this.IEnumerable1Type.TryGet (MetaDataProvider, out ienumerableType) && MetaDataProvider.DerivesFrom (type, ienumerableType)
834 || this.IEnumerableType.TryGet (MetaDataProvider, out ienumerableType) && MetaDataProvider.DerivesFrom (type, ienumerableType));
837 public SymValue GetSpecialUnary (SymFunction op, int source, FlatDomain<TypeNode> type)
839 SymValue value = Value (source);
840 SymValue sv = this.egraph [op, value];
845 private SymValue LookupAddressAndManifestType (SymValue[] args, SymFunction op, TypeNode type, out bool fresh)
847 SymValue sv = this.egraph.TryLookup (op, args);
853 sv = this.egraph [op, args];
858 public bool IsZero (SymValue symValue)
860 return this.egraph [symValue].IsZero;
863 public SymValue Value (int v)
865 return Value (Address (this.Functions.For (v)));
868 public SymValue Value (SymValue address)
871 SymValue symbol = this.egraph.LookupOrManifest (this.Functions.ValueOf, address, out fresh);
873 if (fresh && IsUnmodified (address))
874 MakeUnmodified (symbol);
879 public SymValue Value (Parameter p)
881 return Value (Address (this.Functions.For (p)));
884 public void MakeUnmodified (SymValue value)
886 this.unmodifiedSinceEntry = this.unmodifiedSinceEntry.Add (value);
889 private bool IsUnmodified (SymValue value)
891 return this.unmodifiedSinceEntry.Contains (value);
894 public AbstractType CurrentType (int stackPos)
896 return CurrentType (Value (Address (this.Functions.For (stackPos))));
899 private AbstractType CurrentType (SymValue address)
901 return this.egraph [address];
904 public Domain Assume (int t, bool truth)
906 return Assume (Value (t), truth);
909 private Domain Assume (SymValue sv, bool truth)
914 this.egraph [sv] = this.egraph [sv].ButZero;
915 foreach (var term in this.egraph.EqTerms (sv)) {
916 if (term.Function == this.Functions.UnaryNot || term.Function == this.Functions.NeZero)
917 return Assume (term.Args [0], true);
920 if (this.egraph [sv].IsZero)
922 foreach (var term in this.egraph.EqTerms (sv)) {
923 if (term.Function == this.Functions.UnaryNot || term.Function == this.Functions.NeZero)
924 return Assume (term.Args [0], false);
931 private bool IsNonZero (SymValue sv)
933 foreach (var term in this.egraph.EqTerms (sv)) {
934 var wrapper = term.Function as Wrapper<object>;
935 if (wrapper != null && wrapper.Item is int && (int) wrapper.Item != 0)
941 public FlatDomain<TypeNode> BinaryResultType (BinaryOperator op, AbstractType t1, AbstractType t2)
944 case BinaryOperator.Add:
945 case BinaryOperator.Add_Ovf:
946 case BinaryOperator.Add_Ovf_Un:
950 case BinaryOperator.Sub:
951 case BinaryOperator.Sub_Ovf:
952 case BinaryOperator.Sub_Ovf_Un:
954 case BinaryOperator.Ceq:
955 case BinaryOperator.Cobjeq:
956 case BinaryOperator.Cne_Un:
957 case BinaryOperator.Cge:
958 case BinaryOperator.Cge_Un:
959 case BinaryOperator.Cgt:
960 case BinaryOperator.Cgt_Un:
961 case BinaryOperator.Cle:
962 case BinaryOperator.Cle_Un:
963 case BinaryOperator.Clt:
964 case BinaryOperator.Clt_Un:
965 return MetaDataProvider.System_Boolean;
971 private bool IsStructWithFields (FlatDomain<TypeNode> type)
973 if (!type.IsNormal())
976 return !MetaDataProvider.HasValueRepresentation (type.Value);
979 private FlatDomain<TypeNode> TargetType (FlatDomain<TypeNode> type)
981 if (!type.IsNormal())
984 TypeNode normalType = type.Value;
985 if (MetaDataProvider.IsManagedPointer (normalType))
986 return MetaDataProvider.ElementType (normalType);
988 return FlatDomain<TypeNode>.TopValue;
991 public void SetType (SymValue sv, FlatDomain<TypeNode> type)
993 AbstractType abstractType = this.egraph [sv];
994 if (abstractType.IsZero)
997 this.egraph [sv] = abstractType.With (type);
1000 private void SetTypeIfUnknown (SymValue sv, FlatDomain<TypeNode> type)
1002 AbstractType abstractType = this.egraph [sv];
1004 if (!abstractType.IsZero && (!abstractType.Type.IsNormal() || abstractType.Type.Equals (MetaDataProvider.System_IntPtr)))
1005 this.egraph [sv] = abstractType.With (type);
1008 private void MakeTotallyModified (SymValue dest)
1010 this.unmodifiedSinceEntry = this.unmodifiedSinceEntry.Remove (dest);
1011 this.unmodifiedFieldsSinceEntry = this.unmodifiedFieldsSinceEntry.Remove (dest);
1014 private bool AreUnmodified (IEnumerable<SymValue> values)
1016 return values.All (IsUnmodified);
1019 private bool AnyAreModifiedAtCall (IEnumerable<SymValue> values)
1021 return values.Any (IsModifiedAtCall);
1024 private bool IsModifiedAtCall (SymValue sv)
1026 return (this.ModifiedAtCall != null && this.ModifiedAtCall.Contains (sv));
1029 public Domain GetStateAt (APC pc)
1032 this.parent.PreStateLookup (pc, out ifFound);
1037 public bool TryGetCorrespondingValueAbstraction (int v, out SymbolicValue sv)
1039 return TryGetCorrespondingValueAbstraction (this.Functions.For (v), out sv);
1042 private bool TryGetCorrespondingValueAbstraction (SymFunction v, out SymbolicValue sv)
1045 SymValue loc = TryAddress (v);
1047 SymValue symbol = TryCorrespondingValue (loc);
1048 if (symbol != null) {
1049 sv = new SymbolicValue (symbol);
1055 sv = default(SymbolicValue);
1059 private SymValue TryCorrespondingValue (SymValue address)
1061 if (IsStructAddress (this.egraph [address]))
1064 return TryValue (address);
1067 private bool IsStructAddress (AbstractType abstractType)
1069 if (!abstractType.IsNormal())
1072 TypeNode normalType = abstractType.ConcreteType;
1073 if (MetaDataProvider.IsManagedPointer (normalType))
1074 return !MetaDataProvider.HasValueRepresentation (MetaDataProvider.ElementType (normalType));
1079 private SymValue TryAddress (SymFunction c)
1081 return this.egraph.TryLookup (c);
1084 public bool TryGetCorrespondingValueAbstraction (Local v, out SymbolicValue sv)
1086 return TryGetCorrespondingValueAbstraction (this.Functions.For (v), out sv);
1089 public bool TryGetUnboxedValue (int source, out SymbolicValue sv)
1091 return TryGetUnboxedValue (TryValue (Address (source)), out sv);
1094 private bool TryGetUnboxedValue (SymValue box, out SymbolicValue sv)
1097 SymValue symbol = TryValue (box);
1098 if (symbol != null && this.egraph.TryLookup (this.Functions.BoxOperator, symbol) == box) {
1099 sv = new SymbolicValue (symbol);
1103 sv = new SymbolicValue ();
1107 public SymValue TryValue (SymValue address)
1109 return this.egraph.TryLookup (this.Functions.ValueOf, address);
1112 public AbstractType GetType (SymValue symbol)
1114 return this.egraph [symbol];
1117 public SymValue CreateObject (TypeNode type)
1119 SymValue sv = this.egraph.FreshSymbol ();
1124 public SymValue CreateValue (TypeNode type)
1126 SymValue sv = this.egraph.FreshSymbol ();
1127 SetType (sv, MetaDataProvider.ManagedPointer (type));
1131 public void HavocArrayAtIndex (SymValue arrayValue, SymValue indexValue)
1133 this.egraph.Eliminate (this.Functions.ElementAddress, arrayValue);
1136 public SymValue CreateArray (TypeNode type, SymValue len)
1138 SymValue sv = this.egraph.FreshSymbol ();
1139 this.egraph [this.Functions.Length, sv] = len;
1140 SetType (sv, MetaDataProvider.ArrayType (type, 1));
1144 public SymValue ElementAddress (SymValue array, SymValue index, TypeNode elementAddressType)
1146 SymValue objVersion = this.egraph [this.Functions.ObjectVersion, array];
1147 SymValue sv = this.egraph.TryLookup (this.Functions.ElementAddress, objVersion, index);
1149 sv = this.egraph [this.Functions.ElementAddress, objVersion, index];
1150 SetType (sv, elementAddressType);
1151 this.egraph [this.Functions.ResultOfLoadElement, sv] = Zero;
1156 public void CopyValueAndCast (SymValue destAddr, SymValue srcAddr, TypeNode addrType)
1158 CopyValue (destAddr, srcAddr, addrType, true, true);
1161 public void HavocObjectAtCall (SymValue obj, ref IImmutableSet<SymValue> havoced, bool havocFields, bool havocReadonlyFields)
1163 HavocFields (null, obj, ref havoced, havocReadonlyFields);
1164 HavocUp (obj, ref havoced, havocFields);
1167 public bool IsThis (Method currentMethod, int i)
1169 if (MetaDataProvider.IsStatic (currentMethod))
1171 return Value (MetaDataProvider.This (currentMethod)) == Value (i);
1174 public void AssignValueAndNullnessAtConv_IU (int dest, int source, bool unsigned)
1176 AbstractType aType = CurrentType (source);
1177 AssignValueAndNullnessAtConv_IU (Address (this.Functions.For (dest)), unsigned, aType);
1180 private void AssignValueAndNullnessAtConv_IU (SymValue address, bool unsigned, AbstractType aType)
1183 FlatDomain<TypeNode> type = aType.Type;
1184 if (!IsStructWithFields (type)) {
1185 SymValue ptrValue = this.egraph.FreshSymbol ();
1186 if (type.IsNormal())
1187 aType = new AbstractType (!unsigned ? MetaDataProvider.System_IntPtr : MetaDataProvider.System_UIntPtr, aType.IsZero);
1188 SetType (address, type.IsNormal() ? MetaDataProvider.ManagedPointer (type.Value) : type);
1189 this.egraph [ptrValue] = aType;
1190 this.egraph [this.Functions.ValueOf, address] = ptrValue;
1192 SetType (address, type.IsNormal() ? MetaDataProvider.ManagedPointer (type.Value) : type);
1195 public TypeNode UnaryResultType (UnaryOperator op, AbstractType type)
1198 case UnaryOperator.Conv_i1:
1199 return MetaDataProvider.System_Int8;
1200 case UnaryOperator.Conv_i2:
1201 return MetaDataProvider.System_Int16;
1202 case UnaryOperator.Conv_i4:
1203 return MetaDataProvider.System_Int32;
1204 case UnaryOperator.Conv_i8:
1205 return MetaDataProvider.System_Int64;
1206 case UnaryOperator.Conv_u1:
1207 return MetaDataProvider.System_UInt8;
1208 case UnaryOperator.Conv_u2:
1209 return MetaDataProvider.System_UInt16;
1210 case UnaryOperator.Conv_u4:
1211 return MetaDataProvider.System_UInt32;
1212 case UnaryOperator.Conv_u8:
1213 return MetaDataProvider.System_UInt64;
1215 if (type.IsNormal())
1216 return type.ConcreteType;
1217 return MetaDataProvider.System_Int32;
1221 public void CopyStackAddress (SymValue destAddr, int temporaryForWhichAddressIsTaken)
1223 SymValue srcAddr = Address (temporaryForWhichAddressIsTaken);
1224 this.egraph [this.Functions.ValueOf, destAddr] = srcAddr;
1225 AbstractType aType = CurrentType (srcAddr);
1226 FlatDomain<TypeNode> t = !aType.IsNormal() ? new FlatDomain<TypeNode> () : MetaDataProvider.ManagedPointer (aType.Type.Value);
1227 SetType (destAddr, t);
1230 public SymValue PseudoFieldAddress (SymValue ptr, Method getter)
1232 TypeNode pseudoFieldAddressType;
1233 return PseudoFieldAddress (ptr, getter, out pseudoFieldAddressType, false);
1236 public SymValue PseudoFieldAddress (SymValue sv, Method m, out TypeNode pseudoFieldAddressType, bool materialize)
1238 pseudoFieldAddressType = MetaDataProvider.ManagedPointer (MetaDataProvider.ReturnType (m));
1239 m = MetaDataProvider.Unspecialized (m);
1241 SymValue elem = LookupAddressAndManifestType (sv, this.Functions.For (m), pseudoFieldAddressType, out fresh);
1243 if (IsUnmodified (sv))
1244 MakeModified (elem);
1245 if (IsModifiedAtCall (sv))
1246 this.ModifiedAtCall = this.ModifiedAtCall.Add (elem);
1248 MaterializeAccordingToType (elem, pseudoFieldAddressType, 0);
1253 public SymValue FieldAddress (SymValue ptr, Field field)
1255 TypeNode fieldAddressType;
1256 return FieldAddress (ptr, field, out fieldAddressType);
1259 public SymValue FieldAddress (SymValue ptr, Field field, out TypeNode fieldAddressType)
1261 fieldAddressType = MetaDataProvider.ManagedPointer (MetaDataProvider.FieldType (field));
1263 SymValue sv = LookupAddressAndManifestType (ptr, this.Functions.For (field), fieldAddressType, out fresh);
1265 if (IsUnmodifiedForFields (ptr) || MetaDataProvider.IsReadonly (field))
1266 MakeUnmodified (sv);
1267 if (IsModifiedAtCall (ptr))
1268 this.ModifiedAtCall = this.ModifiedAtCall.Add (sv);
1273 public void Assign (Parameter parameter, TypeNode type)
1275 AssignValue (Address (this.Functions.For (parameter)), type);
1278 public SymValue PseudoFieldAddressOfOutParameter (int index, SymValue fieldAddr, TypeNode pType)
1280 SymValue sv = this.egraph [this.Functions.ForConstant (index, MetaDataProvider.System_Int32), fieldAddr];
1281 MaterializeAccordingToType (sv, pType, 2);
1285 public SymValue ObjectVersion (SymValue sv)
1287 return this.egraph [this.Functions.ObjectVersion, sv];
1290 public SymValue PseudoFieldAddress (SymValue[] args, Method method, out TypeNode pseudoFieldAddressType, bool materialize)
1292 if (args.Length == 0 || args.Length == 1)
1293 return PseudoFieldAddress (Globals, method, out pseudoFieldAddressType, materialize);
1294 pseudoFieldAddressType = MetaDataProvider.ManagedPointer (MetaDataProvider.ReturnType (method));
1295 method = MetaDataProvider.Unspecialized (method);
1298 SymValue sv = LookupAddressAndManifestType (args, this.Functions.For (method), pseudoFieldAddressType, out fresh);
1300 if (AreUnmodified (args))
1301 MakeUnmodified (sv);
1302 if (AnyAreModifiedAtCall (args))
1303 this.ModifiedAtCall = this.ModifiedAtCall.Add (sv);
1305 MaterializeAccordingToType (sv, pseudoFieldAddressType, 0);
1310 public void AssignReturnValue (int dest, TypeNode type)
1312 AssignValue (dest, type);
1313 if (MetaDataProvider.HasValueRepresentation (type))
1314 this.egraph [this.Functions.ResultOfCall, Value (dest)] = Zero;
1316 MaterializeAccordingToType (Address (dest), MetaDataProvider.ManagedPointer (type), 0);
1319 public void MaterializeAccordingToType (SymValue sv, TypeNode type, int depth)
1325 if (MetaDataProvider.IsManagedPointer (type)) {
1326 TypeNode elementType = MetaDataProvider.ElementType (type);
1327 if (!MetaDataProvider.HasValueRepresentation (elementType)) {
1328 ManifestStructId (sv);
1329 foreach (Field field in MetaDataProvider.Fields (elementType)) {
1330 if (!MetaDataProvider.IsStatic (field)) {
1331 TypeNode fieldAddressType;
1332 MaterializeAccordingToType (FieldAddress (sv, field, out fieldAddressType), fieldAddressType, depth + 1);
1335 foreach (Property property in MetaDataProvider.Properties (elementType)) {
1337 if (!MetaDataProvider.IsStatic (property) && MetaDataProvider.HasGetter (property, out getter)) {
1338 TypeNode pseudoFieldAddressType;
1339 MaterializeAccordingToType (PseudoFieldAddress (sv, getter, out pseudoFieldAddressType, false), pseudoFieldAddressType, depth + 1);
1343 MaterializeAccordingToType (Value (sv), elementType, depth + 1);
1347 public void ManifestStructId (SymValue sv)
1352 public SymValue StructId (SymValue sv)
1354 return this.egraph [this.Functions.StructId, sv];
1357 private SymValue LookupAddressAndManifestType (SymValue sv, SymFunction c, TypeNode type, out bool fresh)
1359 SymValue value = this.egraph.TryLookup (c, sv);
1360 if (value != null) {
1366 value = this.egraph [c, sv];
1367 SetType (value, type);
1372 public void HavocFields (SymValue sv, IEnumerable<Field> fields, ref IImmutableSet<SymValue> havoced)
1374 foreach (Field f in fields)
1375 HavocConstructor (null, sv, this.Functions.For (f), ref havoced, false);
1378 private bool IsUnmodifiedForFields (SymValue sv)
1380 return this.unmodifiedFieldsSinceEntry.Contains (sv);
1383 public void HavocUp (SymValue srcAddr, ref IImmutableSet<SymValue> havocedAtCall, bool havocFields)
1385 foreach (var term in this.egraph.EqTerms (srcAddr)) {
1386 if (term.Function == this.Functions.ValueOf)
1387 HavocUpField (term.Args [0], ref havocedAtCall, havocFields);
1391 private void HavocUpField (SymValue sv, ref IImmutableSet<SymValue> havocedAtCall, bool havocFields)
1393 foreach (var term in this.egraph.EqTerms (sv)) {
1394 SymFunction accessedVia = term.Function;
1395 if (accessedVia is Wrapper<Field>)
1396 HavocUpObjectVersion (accessedVia, term.Args [0], ref havocedAtCall, havocFields);
1398 var methodWrapper = accessedVia as Wrapper<Method>;
1400 if (methodWrapper != null && !MetaDataProvider.IsStatic (methodWrapper.Item) && MetaDataProvider.IsPropertyGetter (methodWrapper.Item, out property))
1401 HavocUpObjectVersion (accessedVia, term.Args [0], ref havocedAtCall, havocFields);
1406 private void HavocUpObjectVersion (SymFunction accessedVia, SymValue sv, ref IImmutableSet<SymValue> havocedAtCall, bool havocFields)
1408 if (havocedAtCall.Contains (sv))
1410 this.egraph.Eliminate (this.Functions.ObjectVersion, sv);
1412 HavocMutableFields (accessedVia, sv, ref havocedAtCall);
1414 HavocPseudoFields (accessedVia, sv, ref havocedAtCall);
1416 HavocUp (sv, ref havocedAtCall, false);
1419 public void CopyAddress (SymValue destAddr, SymValue srcAddr, TypeNode type)
1421 this.egraph [this.Functions.ValueOf, destAddr] = srcAddr;
1422 SetType (destAddr, MetaDataProvider.ManagedPointer (type));
1425 public void AssignArrayLength (SymValue destAddr, SymValue array)
1427 SymValue length = this.egraph [this.Functions.Length, array];
1428 SetType (length, MetaDataProvider.System_Int32);
1429 this.egraph [this.Functions.ValueOf, destAddr] = length;
1430 SetType (destAddr, MetaDataProvider.ManagedPointer (MetaDataProvider.System_Int32));
1433 public void ResetModifiedAtCall ()
1435 this.ModifiedAtCall = ImmutableSet<SymValue>.Empty (SymValue.GetUniqueKey);
1438 public SymValue LoadValue (int source)
1440 return Value (source);
1443 public SymbolicValue TryLoadValue (SymValue addr)
1445 return new SymbolicValue (Value (addr));
1448 public bool TryGetArrayLength (SymValue arrayValue, out SymValue length)
1450 length = this.egraph.TryLookup (this.Functions.Length, arrayValue);
1451 return length != null;
1454 public bool TryGetCorrespondingValueAbstraction (Parameter p, out SymbolicValue sv)
1456 return TryGetCorrespondingValueAbstraction (this.Functions.For (p), out sv);
1459 public string GetAccessPath (SymValue sv)
1461 Sequence<PathElementBase> bestAccessPath = GetBestAccessPath (sv, AccessPathFilter<Method>.NoFilter, true, true, false);
1462 if (bestAccessPath == null)
1465 return bestAccessPath.Select (i => (PathElement) i).ToCodeString ();
1468 public Sequence<PathElement> GetAccessPathList (SymValue symbol, AccessPathFilter<Method> filter, bool allowLocal, bool preferLocal)
1470 return GetBestAccessPath (symbol, filter, true, allowLocal, preferLocal).Coerce<PathElementBase, PathElement> ();
1473 public bool LessEqual (Domain that, out IImmutableMap<SymValue, Sequence<SymValue>> forward, out IImmutableMap<SymValue, SymValue> backward)
1475 return this.egraph.LessEqual (that.egraph, out forward, out backward);
1478 public bool IsResultEGraph (IMergeInfo mi)
1480 return mi.IsResultGraph (this.egraph);
1483 public bool IsGraph1 (IMergeInfo mi)
1485 return mi.IsGraph1 (this.egraph);
1488 public bool IsGraph2 (IMergeInfo mi)
1490 return mi.IsGraph2 (this.egraph);
1493 public IImmutableMap<SymValue, Sequence<SymValue>> GetForwardIdentityMap ()
1495 return this.egraph.GetForwardIdentityMap ();
1498 public Domain Join (Domain that, bool widening, out bool weaker, out IMergeInfo mergeInfo)
1500 SymGraph<SymFunction, AbstractType> graph = this.egraph.Join (that.egraph, out mergeInfo, widening);
1501 weaker = mergeInfo.Changed;
1503 IImmutableSet<SymValue> resultUnmodifiedSinceEntry;
1504 IImmutableSet<SymValue> resultUnmodifiedFieldsSinceEntry;
1505 IImmutableSet<SymValue> resultModifiedAtCall;
1507 ComputeJoinOfSets (mergeInfo, this, that, out resultUnmodifiedSinceEntry, out resultUnmodifiedFieldsSinceEntry, out resultModifiedAtCall, ref weaker);
1508 Domain oldDomain = null;
1509 if (OldDomain != null) {
1511 IMergeInfo oldMergeInfo;
1512 oldDomain = OldDomain.Join (that.OldDomain, widening, out oldWeaker, out oldMergeInfo);
1515 return new Domain (graph, RecomputeConstantMap (graph), resultUnmodifiedSinceEntry, resultUnmodifiedFieldsSinceEntry, resultModifiedAtCall, this, oldDomain);
1518 private IImmutableMap<SymValue, SymFunction> RecomputeConstantMap (SymGraph<SymFunction, AbstractType> graph)
1520 IImmutableMap<SymValue, SymFunction> result = ImmutableIntKeyMap<SymValue, SymFunction>.Empty (SymValue.GetUniqueKey);
1521 foreach (SymFunction constant in graph.Constants) {
1522 if (this.Functions.IsConstantOrMethod (constant))
1523 result.Add (graph [constant], constant);
1528 private void ComputeJoinOfSets (IMergeInfo mergeInfo, Domain domain, Domain that,
1529 out IImmutableSet<SymValue> resultUnmodifiedSinceEntry,
1530 out IImmutableSet<SymValue> resultUnmodifiedFieldsSinceEntry,
1531 out IImmutableSet<SymValue> resultModifiedAtCall, ref bool weaker)
1533 resultUnmodifiedSinceEntry = ImmutableSet<SymValue>.Empty (SymValue.GetUniqueKey);
1534 resultUnmodifiedFieldsSinceEntry = ImmutableSet<SymValue>.Empty (SymValue.GetUniqueKey);
1535 resultModifiedAtCall = ImmutableSet<SymValue>.Empty (SymValue.GetUniqueKey);
1537 foreach (var tuple in mergeInfo.MergeTriples) {
1538 SymValue symValue1 = tuple.Item1;
1539 SymValue symValue2 = tuple.Item2;
1540 SymValue elem = tuple.Item3;
1542 bool unmodifiedSinceEntryContains = domain.unmodifiedSinceEntry.ContainsSafe (symValue1);
1543 bool modifiedAtCallContains = domain.ModifiedAtCall.ContainsSafe (symValue1);
1545 if (unmodifiedSinceEntryContains) {
1546 if (that.unmodifiedSinceEntry.ContainsSafe (symValue2))
1547 resultUnmodifiedSinceEntry = resultUnmodifiedSinceEntry.Add (elem);
1548 else if (that.unmodifiedFieldsSinceEntry.ContainsSafe (symValue2))
1549 resultUnmodifiedFieldsSinceEntry = resultUnmodifiedFieldsSinceEntry.Add (elem);
1552 if (modifiedAtCallContains)
1553 resultModifiedAtCall = resultModifiedAtCall.Add (elem);
1556 if (that.unmodifiedSinceEntry.Count () > resultUnmodifiedSinceEntry.Count ()) {
1558 if (DebugOptions.Debug)
1559 Console.WriteLine ("---Result changed due to fewer unmodified locations since entry");
1561 if (that.unmodifiedFieldsSinceEntry.Count () > resultUnmodifiedFieldsSinceEntry.Count ()) {
1563 if (DebugOptions.Debug)
1564 Console.WriteLine ("---Result changed due to fewer unmodified locations for fields since entry");
1569 #region Implementation of IAbstractDomain<Domain>
1574 return new Domain (this.egraph.Top, ImmutableIntKeyMap<SymValue, SymFunction>.Empty (SymValue.GetUniqueKey), ImmutableSet<SymValue>.Empty (SymValue.GetUniqueKey),
1575 ImmutableSet<SymValue>.Empty (SymValue.GetUniqueKey), ImmutableSet<SymValue>.Empty (SymValue.GetUniqueKey), this, null);
1579 public Domain Bottom
1583 if (BottomValue == null) {
1584 BottomValue = new Domain (this.egraph.Bottom, ImmutableIntKeyMap<SymValue, SymFunction>.Empty (SymValue.GetUniqueKey), ImmutableSet<SymValue>.Empty (SymValue.GetUniqueKey),
1585 ImmutableSet<SymValue>.Empty (SymValue.GetUniqueKey), ImmutableSet<SymValue>.Empty (SymValue.GetUniqueKey),
1587 BottomValue.ImmutableVersion ();
1595 get { return this.egraph.IsTop; }
1598 public bool IsBottom
1602 if (this == BottomValue || this.egraph.IsBottom)
1604 if (OldDomain != null)
1605 return OldDomain.IsBottom;
1611 public Domain Join(Domain that)
1613 throw new NotImplementedException();
1616 public Domain Join (Domain that, bool widening, out bool weaker)
1618 IMergeInfo mergeInfo;
1619 return Join (that, widening, out weaker, out mergeInfo);
1622 public Domain Widen(Domain that)
1624 throw new NotImplementedException();
1627 public Domain Meet (Domain that)
1629 SymGraph<SymFunction, AbstractType> graph = this.egraph.Meet (that.egraph);
1630 return new Domain (graph, RecomputeConstantMap (graph), this.unmodifiedSinceEntry, this.unmodifiedFieldsSinceEntry, null, this, OldDomain);
1633 public bool LessEqual (Domain that)
1635 return this.egraph.LessEqual (that.egraph);
1638 public Domain ImmutableVersion ()
1640 this.egraph.ImmutableVersion ();