Imported Upstream version 3.6.0

Former-commit-id: da6be194a6b1221998fc28233f2503bd61dd9d14
This commit is contained in:
Jo Shields
2014-08-13 10:39:27 +01:00
commit a575963da9
50588 changed files with 8155799 additions and 0 deletions

View File

@@ -0,0 +1,289 @@
//
// APC.cs
//
// Authors:
// Alexander Chebaturkin (chebaturkin@gmail.com)
//
// Copyright (C) 2011 Alexander Chebaturkin
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Collections.Generic;
using System.Text;
using Mono.CodeContracts.Static.AST;
using Mono.CodeContracts.Static.DataStructures;
namespace Mono.CodeContracts.Static.ControlFlow {
struct APC : IEquatable<APC> {
public static readonly APC Dummy = new APC (null, 0, null);
public readonly CFGBlock Block;
public readonly int Index;
public readonly Sequence<Edge<CFGBlock, EdgeTag>> SubroutineContext;
public APC (CFGBlock block, int index, Sequence<Edge<CFGBlock, EdgeTag>> subroutineContext)
{
this.Block = block;
this.Index = index;
this.SubroutineContext = subroutineContext;
}
public IEnumerable<APC> Successors
{
get { return this.Block.Subroutine.Successors (this); }
}
public bool InsideContract
{
get
{
Subroutine sub = this.Block.Subroutine;
return sub.IsContract || sub.IsOldValue;
}
}
public bool InsideConstructor
{
get
{
Sequence<Edge<CFGBlock, EdgeTag>> ctx = this.SubroutineContext;
CFGBlock block = this.Block;
while (block != null) {
Subroutine subroutine = block.Subroutine;
if (subroutine.IsConstructor)
return true;
if (subroutine.IsMethod)
return false;
if (ctx != null) {
block = ctx.Head.From;
ctx = ctx.Tail;
} else
block = null;
}
return false;
}
}
public bool InsideEnsuresInMethod
{
get
{
if (!this.Block.Subroutine.IsEnsuresOrOldValue || this.SubroutineContext == null)
return false;
foreach (var edge in this.SubroutineContext.AsEnumerable ()) {
if (edge.Tag == EdgeTag.Exit || edge.Tag == EdgeTag.Entry || edge.Tag.Is (EdgeTag.AfterMask))
return true;
}
return false;
}
}
public bool InsideRequiresAtCall
{
get
{
if (!this.Block.Subroutine.IsRequires || this.SubroutineContext == null)
return false;
foreach (var edge in this.SubroutineContext.AsEnumerable ()) {
if (edge.Tag == EdgeTag.Entry)
return false;
if (edge.Tag.Is (EdgeTag.BeforeMask))
return true;
}
return false;
}
}
public bool InsideEnsuresAtCall
{
get
{
if (!this.Block.Subroutine.IsRequires || this.SubroutineContext == null)
return false;
foreach (var edge in this.SubroutineContext.AsEnumerable ()) {
if (edge.Tag == EdgeTag.Exit)
return false;
if (edge.Tag.Is (EdgeTag.BeforeMask))
return true;
}
return false;
}
}
public bool InsideInvariantOnExit
{
get
{
if (!this.Block.Subroutine.IsInvariant || this.SubroutineContext == null)
return false;
foreach (var edge in this.SubroutineContext.AsEnumerable ()) {
if (edge.Tag == EdgeTag.Exit)
return true;
if (edge.Tag == EdgeTag.Entry || edge.Tag.Is (EdgeTag.AfterMask))
return false;
}
return false;
}
}
public bool InsideInvariantInMethod
{
get
{
if (!this.Block.Subroutine.IsInvariant || this.SubroutineContext == null)
return false;
foreach (var edge in this.SubroutineContext.AsEnumerable ()) {
if (edge.Tag == EdgeTag.Exit || edge.Tag == EdgeTag.Entry || edge.Tag.Is (EdgeTag.AfterMask))
return true;
}
return false;
}
}
public bool InsideInvariantAtCall
{
get
{
if (!this.Block.Subroutine.IsInvariant || this.SubroutineContext == null)
return false;
foreach (var edge in this.SubroutineContext.AsEnumerable ()) {
if (edge.Tag == EdgeTag.Exit || edge.Tag == EdgeTag.Entry)
return false;
if (edge.Tag.Is (EdgeTag.AfterMask))
return true;
}
return false;
}
}
public bool InsideOldManifestation
{
get { throw new NotImplementedException (); }
}
public bool InsideRequiresAtCallInsideContract
{
get
{
if (!this.Block.Subroutine.IsRequires || this.SubroutineContext == null)
return false;
for (Sequence<Edge<CFGBlock, EdgeTag>> list = this.SubroutineContext; list != null; list = list.Tail) {
if (list.Head.Tag == EdgeTag.Entry)
return false;
if (list.Head.Tag.Is (EdgeTag.BeforeMask)) {
Subroutine sub = list.Head.From.Subroutine;
return sub.IsEnsuresOrOldValue || sub.IsRequires || sub.IsInvariant;
}
}
throw new InvalidOperationException ("Should not happen");
}
}
#region IEquatable<APC> Members
public bool Equals (APC other)
{
return (this.Block == other.Block && this.Index == other.Index && this.SubroutineContext == other.SubroutineContext);
}
#endregion
public APC Next ()
{
if (this.Index < this.Block.Count)
return new APC (this.Block, this.Index + 1, this.SubroutineContext);
return this;
}
public static APC ForEnd (CFGBlock block, Sequence<Edge<CFGBlock, EdgeTag>> subroutineContext)
{
return new APC (block, block.Count, subroutineContext);
}
public static APC ForStart (CFGBlock block, Sequence<Edge<CFGBlock, EdgeTag>> subroutineContext)
{
return new APC (block, 0, subroutineContext);
}
public APC LastInBlock ()
{
return ForEnd (this.Block, this.SubroutineContext);
}
public bool TryGetContainingMethod (out Method method)
{
Sequence<Edge<CFGBlock, EdgeTag>> list = this.SubroutineContext;
CFGBlock block = this.Block;
while (block != null) {
var mi = block.Subroutine as IMethodInfo;
if (mi != null) {
method = mi.Method;
return true;
}
if (list != null) {
block = list.Head.From;
list = list.Tail;
} else
block = null;
}
method = default(Method);
return false;
}
static void ToString (StringBuilder sb, Sequence<Edge<CFGBlock, EdgeTag>> context)
{
bool wasFirst = false;
for (; context != null; context = context.Tail) {
if (!wasFirst) {
sb.Append ("{");
wasFirst = true;
} else
sb.Append (",");
Edge<CFGBlock, EdgeTag> head = context.Head;
sb.AppendFormat ("(SR{2} {0},{1}) [{3}]", head.From.Index, head.To.Index, head.From.Subroutine.Id, head.Tag);
}
if (!wasFirst)
return;
sb.Append ("}");
}
public override string ToString ()
{
var sb = new StringBuilder ();
sb.Append ("[");
sb.AppendFormat ("SR{2} {0},{1}", this.Block.Index, this.Index, this.Block.Subroutine.Id);
ToString (sb, this.SubroutineContext);
sb.Append ("]");
return sb.ToString ();
}
}
}

View File

@@ -0,0 +1,101 @@
//
// APCDecoder.cs
//
// Authors:
// Alexander Chebaturkin (chebaturkin@gmail.com)
//
// Copyright (C) 2011 Alexander Chebaturkin
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System.Collections.Generic;
using Mono.CodeContracts.Static.AST;
using Mono.CodeContracts.Static.AST.Visitors;
using Mono.CodeContracts.Static.Analysis;
using Mono.CodeContracts.Static.ControlFlow.Subroutines;
using Mono.CodeContracts.Static.DataStructures;
using Mono.CodeContracts.Static.Providers;
namespace Mono.CodeContracts.Static.ControlFlow {
class APCDecoder : IILDecoder<APC, Dummy, Dummy, IMethodContextProvider, Dummy>, IMethodContextProvider, IMethodContext {
private readonly SubroutineFacade subroutine_facade;
private readonly ControlFlowGraph cfg;
private readonly IMetaDataProvider meta_data_provider;
public APCDecoder (ControlFlowGraph underlyingCFG,
IMetaDataProvider metaDataProvider,
SubroutineFacade subroutineFacade)
{
this.cfg = underlyingCFG;
this.meta_data_provider = metaDataProvider;
this.subroutine_facade = subroutineFacade;
}
#region IILDecoder<APC,Dummy,Dummy,IMethodContextProvider,Dummy> Members
public IMethodContextProvider ContextProvider
{
get { return this; }
}
public TResult ForwardDecode<TData, TResult, TVisitor> (APC pc, TVisitor visitor, TData data)
where TVisitor : IILVisitor<APC, Dummy, Dummy, TData, TResult>
{
return this.subroutine_facade.ForwardDecode<TData, TResult, RemoveBranchDelegator<TData, TResult, TVisitor>>
(pc, new RemoveBranchDelegator<TData, TResult, TVisitor> (visitor, this.meta_data_provider), data);
}
public bool IsUnreachable (APC pc)
{
return false;
}
public Dummy EdgeData (APC from, APC to)
{
return Dummy.Value;
}
#endregion
public IMethodContext MethodContext
{
get { return this; }
}
public Method CurrentMethod
{
get { return this.cfg.CFGMethod; }
}
public ICFG CFG
{
get { return this.cfg; }
}
public IEnumerable<Field> Modifies (Method method)
{
return this.subroutine_facade.GetModifies (method);
}
public IEnumerable<Method> AffectedGetters (Field field)
{
return this.subroutine_facade.GetAffectedGetters (field);
}
}
}

View File

@@ -0,0 +1,83 @@
//
// CFGBlock.cs
//
// Authors:
// Alexander Chebaturkin (chebaturkin@gmail.com)
//
// Copyright (C) 2011 Alexander Chebaturkin
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System.Collections.Generic;
using Mono.CodeContracts.Static.DataStructures;
namespace Mono.CodeContracts.Static.ControlFlow {
abstract class CFGBlock {
public int Index;
protected CFGBlock (Subroutine subroutine, ref int idGen)
{
this.Index = idGen++;
Subroutine = subroutine;
}
public abstract int Count { get; }
public Subroutine Subroutine { get; private set; }
public int ReversePostOrderIndex { get; set; }
public APC First
{
get { return APC.ForStart (this, null); }
}
public APC Last
{
get { return APC.ForEnd (this, null); }
}
public virtual bool IsMethodCallBlock<TMethod> (out TMethod calledMethod, out bool isNewObj, out bool isVirtual)
{
calledMethod = default(TMethod);
isNewObj = false;
isVirtual = false;
return false;
}
public void Renumber (ref int idGen)
{
this.Index = idGen++;
}
public abstract int GetILOffset (APC pc);
public IEnumerable<APC> APCs ()
{
return APCs (null);
}
private IEnumerable<APC> APCs (Sequence<Edge<CFGBlock, EdgeTag>> context)
{
for (int i = 0; i < Count; i++)
yield return new APC (this, i, context);
}
}
}

View File

@@ -0,0 +1,170 @@
//
// ContractFilteredCFG.cs
//
// Authors:
// Alexander Chebaturkin (chebaturkin@gmail.com)
//
// Copyright (C) 2011 Alexander Chebaturkin
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Collections.Generic;
using System.IO;
using Mono.CodeContracts.Static.Analysis;
using Mono.CodeContracts.Static.DataStructures;
using Mono.CodeContracts.Static.Providers;
namespace Mono.CodeContracts.Static.ControlFlow {
class ContractFilteredCFG : ICFG, IEdgeSubroutineAdaptor {
readonly ICFG underlying;
public ContractFilteredCFG (ICFG cfg)
{
this.underlying = cfg;
}
#region ICFG Members
public APC Entry { get { return this.underlying.Entry; } }
public APC EntryAfterRequires { get { return this.underlying.EntryAfterRequires; } }
public APC NormalExit { get { return this.underlying.NormalExit; } }
public APC ExceptionExit { get { return this.underlying.ExceptionExit; } }
public Subroutine Subroutine { get { return this.underlying.Subroutine; } }
public APC Next (APC pc)
{
return this.underlying.Next (pc);
}
public bool HasSingleSuccessor (APC pc, out APC ifFound)
{
DecoratorHelper.Push<IEdgeSubroutineAdaptor> (this);
try {
return this.underlying.HasSingleSuccessor (pc, out ifFound);
}
finally {
DecoratorHelper.Pop ();
}
}
public IEnumerable<APC> Successors (APC pc)
{
DecoratorHelper.Push<IEdgeSubroutineAdaptor> (this);
try {
return this.underlying.Successors (pc);
}
finally {
DecoratorHelper.Pop ();
}
}
public bool HasSinglePredecessor (APC pc, out APC ifFound)
{
DecoratorHelper.Push<IEdgeSubroutineAdaptor> (this);
try {
return this.underlying.HasSinglePredecessor (pc, out ifFound);
}
finally {
DecoratorHelper.Pop ();
}
}
public IEnumerable<APC> Predecessors (APC pc)
{
DecoratorHelper.Push<IEdgeSubroutineAdaptor> (this);
try {
return this.underlying.Predecessors (pc);
}
finally {
DecoratorHelper.Pop ();
}
}
public bool IsJoinPoint (APC pc)
{
return this.underlying.IsJoinPoint (pc);
}
public bool IsSplitPoint (APC pc)
{
return this.underlying.IsSplitPoint (pc);
}
public bool IsBlockStart (APC pc)
{
return this.underlying.IsBlockStart (pc);
}
public bool IsBlockEnd (APC pc)
{
return this.underlying.IsBlockEnd (pc);
}
public APC Post (APC pc)
{
return this.underlying.Post (pc);
}
public IILDecoder<APC, Dummy, Dummy, IMethodContextProvider, Dummy> GetDecoder (
IMetaDataProvider metaDataProvider)
{
return this.underlying.GetDecoder (metaDataProvider);
}
public void Print (TextWriter tw, ILPrinter<APC> printer,
Func<CFGBlock, IEnumerable<Sequence<Edge<CFGBlock, EdgeTag>>>> contextLookup,
Sequence<Edge<CFGBlock, EdgeTag>> context)
{
DecoratorHelper.Push<IEdgeSubroutineAdaptor> (this);
try {
this.underlying.Print (tw, printer, contextLookup, context);
}
finally {
DecoratorHelper.Pop ();
}
}
public bool IsForwardBackEdge (APC @from, APC to)
{
return underlying.IsForwardBackEdge (from, to);
}
#endregion
#region Implementation of IEdgeSubroutineAdaptor
Sequence<Pair<EdgeTag, Subroutine>> IEdgeSubroutineAdaptor.GetOrdinaryEdgeSubroutinesInternal (
CFGBlock @from, CFGBlock to,
Sequence<Edge<CFGBlock, EdgeTag>> context)
{
return DecoratorHelper.Inner<IEdgeSubroutineAdaptor> (this)
.GetOrdinaryEdgeSubroutinesInternal (from, to, context).Where (
(pair) => !pair.Value.IsContract && !pair.Value.IsOldValue);
}
#endregion
}
}

View File

@@ -0,0 +1,199 @@
//
// ControlFlowGraph.cs
//
// Authors:
// Alexander Chebaturkin (chebaturkin@gmail.com)
//
// Copyright (C) 2011 Alexander Chebaturkin
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Collections.Generic;
using System.IO;
using Mono.CodeContracts.Static.AST;
using Mono.CodeContracts.Static.Analysis;
using Mono.CodeContracts.Static.ControlFlow.Subroutines;
using Mono.CodeContracts.Static.DataStructures;
using Mono.CodeContracts.Static.Providers;
namespace Mono.CodeContracts.Static.ControlFlow {
class ControlFlowGraph : ICFG {
readonly SubroutineFacade method_repository;
readonly Subroutine method_subroutine;
public ControlFlowGraph (Subroutine subroutine, SubroutineFacade methodRepository)
{
this.method_subroutine = subroutine;
this.method_repository = methodRepository;
}
CFGBlock EntryBlock { get { return this.method_subroutine.Entry; } }
CFGBlock ExitBlock { get { return this.method_subroutine.Exit; } }
CFGBlock ExceptionExitBlock { get { return this.method_subroutine.ExceptionExit; } }
public Method CFGMethod
{
get
{
var methodInfo = this.method_subroutine as IMethodInfo;
if (methodInfo != null)
return methodInfo.Method;
throw new InvalidOperationException ("CFG has bad subroutine that is not a method");
}
}
#region ICFG Members
public APC Entry { get { return new APC (this.EntryBlock, 0, null); } }
public APC EntryAfterRequires { get { return new APC (this.method_subroutine.EntryAfterRequires, 0, null); } }
public APC NormalExit { get { return new APC (this.ExitBlock, 0, null); } }
public APC ExceptionExit { get { return new APC (this.ExceptionExitBlock, 0, null); } }
public Subroutine Subroutine { get { return this.method_subroutine; } }
public APC Next (APC pc)
{
APC next;
if (this.HasSingleSuccessor (pc, out next))
return next;
return pc;
}
public bool HasSingleSuccessor (APC pc, out APC ifFound)
{
return pc.Block.Subroutine.HasSingleSuccessor (pc, out ifFound);
}
public IEnumerable<APC> Successors (APC pc)
{
return pc.Block.Subroutine.Successors (pc);
}
public bool HasSinglePredecessor (APC pc, out APC ifFound)
{
return pc.Block.Subroutine.HasSinglePredecessor (pc, out ifFound);
}
public IEnumerable<APC> Predecessors (APC pc)
{
return pc.Block.Subroutine.Predecessors (pc);
}
public bool IsJoinPoint (APC pc)
{
if (pc.Index != 0)
return false;
return IsJoinPoint (pc.Block);
}
public bool IsSplitPoint (APC pc)
{
if (pc.Index != pc.Block.Count)
return false;
return IsSplitPoint (pc.Block);
}
public bool IsBlockStart (APC pc)
{
return pc.Index == 0;
}
public bool IsBlockEnd (APC pc)
{
return pc.Index == pc.Block.Count;
}
public IILDecoder<APC, Dummy, Dummy, IMethodContextProvider, Dummy> GetDecoder (
IMetaDataProvider metaDataProvider)
{
return new APCDecoder (this, metaDataProvider, this.method_repository);
}
public void Print (TextWriter tw, ILPrinter<APC> printer,
Func<CFGBlock, IEnumerable<Sequence<Edge<CFGBlock, EdgeTag>>>> contextLookup,
Sequence<Edge<CFGBlock, EdgeTag>> context)
{
var set = new HashSet<Pair<Subroutine, Sequence<Edge<CFGBlock, EdgeTag>>>> ();
this.method_subroutine.Print (tw, printer, contextLookup, context, set);
}
public bool IsForwardBackEdge (APC @from, APC to)
{
if (to.Index != 0)
return false;
return this.IsForwardBackEdgeHelper (from, to);
}
public APC Post (APC pc)
{
APC next;
return this.HasSingleSuccessor (pc, out next) ? next : pc;
}
#endregion
bool IsForwardBackEdgeHelper (APC @from, APC to)
{
if (to.Block.Subroutine.EdgeInfo.IsBackEdge (from.Block, Dummy.Value, to.Block))
return true;
if (from.SubroutineContext.IsEmpty () || from.SubroutineContext.Tail != to.SubroutineContext)
return false;
Edge<CFGBlock, EdgeTag> edge = @from.SubroutineContext.Head;
return edge.To.Subroutine.EdgeInfo.IsBackEdge (edge.From, Dummy.Value, edge.To);
}
bool IsJoinPoint (CFGBlock block)
{
return block.Subroutine.IsJoinPoint (block);
}
bool IsSplitPoint (CFGBlock block)
{
return block.Subroutine.IsSplitPoint (block);
}
public IGraph<APC, Dummy> AsForwardGraph ()
{
return new GraphWrapper<APC, Dummy> (new APC[0], (pc) => this.SuccessorsEdges (pc));
}
IEnumerable<Pair<Dummy, APC>> SuccessorsEdges (APC pc)
{
APC last = pc.LastInBlock ();
foreach (APC succ in this.Successors (last))
yield return new Pair<Dummy, APC> (Dummy.Value, succ);
}
}
}

View File

@@ -0,0 +1,52 @@
//
// Edge.cs
//
// Authors:
// Alexander Chebaturkin (chebaturkin@gmail.com)
//
// Copyright (C) 2011 Alexander Chebaturkin
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
namespace Mono.CodeContracts.Static.ControlFlow {
struct Edge<TNode, TTag> {
public TNode From;
public TTag Tag;
public TNode To;
public Edge (TNode from, TNode to, TTag tag)
{
this.From = from;
this.To = to;
this.Tag = tag;
}
public override string ToString ()
{
return string.Format ("({0} --'{1}'--> {2})", this.From, this.Tag, this.To);
}
public Edge<TNode, TTag> Reversed ()
{
return new Edge<TNode, TTag> (this.To, this.From, this.Tag);
}
}
}

View File

@@ -0,0 +1,222 @@
//
// EdgeMap.cs
//
// Authors:
// Alexander Chebaturkin (chebaturkin@gmail.com)
//
// Copyright (C) 2011 Alexander Chebaturkin
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Mono.CodeContracts.Static.DataStructures;
namespace Mono.CodeContracts.Static.ControlFlow {
class EdgeMap<Tag> : IEnumerable<Edge<CFGBlock, Tag>>, IGraph<CFGBlock, Tag> {
private readonly List<Edge<CFGBlock, Tag>> edges;
public EdgeMap (List<Edge<CFGBlock, Tag>> edges)
{
this.edges = edges;
Resort ();
}
public ICollection<Pair<Tag, CFGBlock>> this [CFGBlock node]
{
get { return new Successors (this, FindStartIndex (node)); }
}
#region IEnumerable<Edge<CFGBlock,Tag>> Members
public IEnumerator<Edge<CFGBlock, Tag>> GetEnumerator ()
{
return this.edges.GetEnumerator ();
}
IEnumerator IEnumerable.GetEnumerator ()
{
return GetEnumerator ();
}
#endregion
#region IGraph<CFGBlock,Tag> Members
IEnumerable<CFGBlock> IGraph<CFGBlock, Tag>.Nodes
{
get { throw new InvalidOperationException(); }
}
IEnumerable<Pair<Tag, CFGBlock>> IGraph<CFGBlock, Tag>.Successors (CFGBlock node)
{
return this [node];
}
#endregion
public EdgeMap<Tag> Reverse ()
{
var newEdges = new List<Edge<CFGBlock, Tag>> (this.edges.Count);
newEdges.AddRange (this.edges.Select (edge => edge.Reversed ()));
return new EdgeMap<Tag> (newEdges);
}
private static int CompareFirstBlockIndex (Edge<CFGBlock, Tag> edge1, Edge<CFGBlock, Tag> edge2)
{
int cmp = edge1.From.Index - edge2.From.Index;
if (cmp == 0)
cmp = edge1.To.Index - edge2.To.Index;
return cmp;
}
private int FindStartIndex (CFGBlock from)
{
//binary search
int l = 0;
int r = this.edges.Count;
while (l < r) {
int median = (l + r)/2;
int medianBlockIndex = this.edges [median].From.Index;
if (medianBlockIndex == from.Index) {
while (median > 0 && this.edges [median - 1].From.Index == medianBlockIndex)
--median;
return median;
}
if (medianBlockIndex < from.Index)
l = median + 1;
else
r = median;
}
return this.edges.Count;
}
public void Filter (Predicate<Edge<CFGBlock, Tag>> keep)
{
var notKeepEdges = new List<int> ();
for (int i = 0; i < this.edges.Count; i++) {
if (!keep (this.edges [i]))
notKeepEdges.Add (i);
}
if (notKeepEdges.Count == 0)
return;
int ix = 0;
foreach (int i in notKeepEdges) {
this.edges.RemoveAt (i - ix);
ix++;
}
}
public void Resort ()
{
this.edges.Sort (CompareFirstBlockIndex);
}
#region Nested type: Successors
private struct Successors : ICollection<Pair<Tag, CFGBlock>> {
private readonly int start_index;
private readonly EdgeMap<Tag> underlying;
public Successors (EdgeMap<Tag> underlying, int startIndex)
{
this.underlying = underlying;
this.start_index = startIndex;
}
#region ICollection<Pair<Tag,CFGBlock>> Members
public IEnumerator<Pair<Tag, CFGBlock>> GetEnumerator ()
{
List<Edge<CFGBlock, Tag>> edges = this.underlying.edges;
if (this.start_index < edges.Count) {
int index = this.start_index;
int blockIndex = edges [index].From.Index;
do {
yield return new Pair<Tag, CFGBlock> (edges [index].Tag, edges [index].To);
++index;
} while (index < edges.Count && edges [index].From.Index == blockIndex);
}
}
IEnumerator IEnumerable.GetEnumerator ()
{
return GetEnumerator ();
}
public void Add (Pair<Tag, CFGBlock> item)
{
throw new InvalidOperationException ();
}
public void Clear ()
{
throw new InvalidOperationException ();
}
public bool Contains (Pair<Tag, CFGBlock> item)
{
throw new NotImplementedException ();
}
public void CopyTo (Pair<Tag, CFGBlock>[] array, int arrayIndex)
{
throw new NotImplementedException ();
}
public bool Remove (Pair<Tag, CFGBlock> item)
{
throw new InvalidOperationException ();
}
public int Count
{
get
{
int index = this.start_index;
List<Edge<CFGBlock, Tag>> edges = this.underlying.edges;
if (index >= edges.Count)
return 0;
int blockIndex = edges [index].From.Index;
int count = 0;
do {
++count;
++index;
} while (index < edges.Count && edges [index].From.Index == blockIndex);
return count;
}
}
public bool IsReadOnly
{
get { return true; }
}
#endregion
}
#endregion
}
}

View File

@@ -0,0 +1,64 @@
//
// EdgeTag.cs
//
// Authors:
// Alexander Chebaturkin (chebaturkin@gmail.com)
//
// Copyright (C) 2011 Alexander Chebaturkin
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
namespace Mono.CodeContracts.Static.ControlFlow {
[Flags]
enum EdgeTag : uint {
None = 0,
FallThroughReturn = 1,
Branch = 1 << 1,
Return = 1 << 2,
EndSubroutine = 1 << 3,
True = 1 << 4,
False = 1 << 5,
FallThrough = 1 << 6,
Entry = 1 << 7,
AfterNewObj = 1 << 8 | AfterMask,
AfterCall = 1 << 9 | AfterMask,
Exit = 1 << 10,
Finally = 1 << 11,
Inherited = 1 << 12 | InheritedMask,
BeforeCall = 1 << 13 | BeforeMask,
BeforeNewObj = 1 << 14 | BeforeMask,
Requires = 1 << 15,
Assume = 1 << 16,
Assert = 1 << 17,
Invariant = 1 << 18,
OldManifest = 1 << 19 | OldMask,
Old = 1 << 20 | OldMask,
EndOld = 1 << 21,
BeforeMask = 1 << 22,
AfterMask = 1 << 23,
InheritedMask = 1 << 24,
ExtraMask = 1 << 25,
OldMask = 1 << 26,
}
}

View File

@@ -0,0 +1,36 @@
//
// EdgeTagExtensions.cs
//
// Authors:
// Alexander Chebaturkin (chebaturkin@gmail.com)
//
// Copyright (C) 2011 Alexander Chebaturkin
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
namespace Mono.CodeContracts.Static.ControlFlow {
static class EdgeTagExtensions {
public static bool Is (this EdgeTag current, EdgeTag mask)
{
return (current & mask) != EdgeTag.None;
}
}
}

View File

@@ -0,0 +1,32 @@
//
// EdgeVisitor.cs
//
// Authors:
// Alexander Chebaturkin (chebaturkin@gmail.com)
//
// Copyright (C) 2011 Alexander Chebaturkin
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
namespace Mono.CodeContracts.Static.ControlFlow
{
delegate void EdgeVisitor<Node, Info>(Node source, Info info, Node target);
}

View File

@@ -0,0 +1,67 @@
//
// ICFG.cs
//
// Authors:
// Alexander Chebaturkin (chebaturkin@gmail.com)
//
// Copyright (C) 2011 Alexander Chebaturkin
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Collections.Generic;
using System.IO;
using Mono.CodeContracts.Static.Analysis;
using Mono.CodeContracts.Static.DataStructures;
using Mono.CodeContracts.Static.Providers;
namespace Mono.CodeContracts.Static.ControlFlow {
interface ICFG {
APC Entry { get; }
APC EntryAfterRequires { get; }
APC NormalExit { get; }
APC ExceptionExit { get; }
Subroutine Subroutine { get; }
APC Next (APC pc);
IEnumerable<APC> Successors (APC pc);
bool HasSingleSuccessor (APC pc, out APC ifFound);
IEnumerable<APC> Predecessors (APC pc);
bool HasSinglePredecessor (APC pc, out APC ifFound);
bool IsJoinPoint (APC pc);
bool IsSplitPoint (APC pc);
bool IsBlockStart (APC pc);
bool IsBlockEnd (APC pc);
IILDecoder<APC, Dummy, Dummy, IMethodContextProvider, Dummy> GetDecoder (IMetaDataProvider metaDataProvider);
void Print (TextWriter tw, ILPrinter<APC> printer,
Func<CFGBlock, IEnumerable<Sequence<Edge<CFGBlock, EdgeTag>>>> contextLookup,
Sequence<Edge<CFGBlock, EdgeTag>> context);
bool IsForwardBackEdge (APC @from, APC to);
APC Post (APC pc);
}
}

View File

@@ -0,0 +1,35 @@
//
// IConstantInfo.cs
//
// Authors:
// Alexander Chebaturkin (chebaturkin@gmail.com)
//
// Copyright (C) 2011 Alexander Chebaturkin
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using Mono.CodeContracts.Static.DataStructures;
namespace Mono.CodeContracts.Static.ControlFlow {
interface IEdgeSubroutineAdaptor {
Sequence<Pair<EdgeTag, Subroutine>> GetOrdinaryEdgeSubroutinesInternal (CFGBlock @from, CFGBlock to, Sequence<Edge<CFGBlock, EdgeTag>> context);
}
}

View File

@@ -0,0 +1,36 @@
//
// IHandlerFilter.cs
//
// Authors:
// Alexander Chebaturkin (chebaturkin@gmail.com)
//
// Copyright (C) 2011 Alexander Chebaturkin
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using Mono.CodeContracts.Static.AST;
namespace Mono.CodeContracts.Static.ControlFlow {
interface IHandlerFilter<Data> {
bool Catch (Data data, TypeNode exception, out bool stopPropagation);
bool Filter (Data data, APC filterCode, out bool stopPropagation);
}
}

View File

@@ -0,0 +1,35 @@
//
// IMethodInfo.cs
//
// Authors:
// Alexander Chebaturkin (chebaturkin@gmail.com)
//
// Copyright (C) 2011 Alexander Chebaturkin
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using Mono.CodeContracts.Static.AST;
namespace Mono.CodeContracts.Static.ControlFlow {
interface IMethodInfo {
Method Method { get; }
}
}

View File

@@ -0,0 +1,33 @@
//
// IStackInfo.cs
//
// Authors:
// Alexander Chebaturkin (chebaturkin@gmail.com)
//
// Copyright (C) 2011 Alexander Chebaturkin
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
namespace Mono.CodeContracts.Static.ControlFlow {
interface IStackInfo {
bool IsCallOnThis (APC pc);
}
}

View File

@@ -0,0 +1,420 @@
//
// RemoveBranchDelegator.cs
//
// Authors:
// Alexander Chebaturkin (chebaturkin@gmail.com)
//
// Copyright (C) 2011 Alexander Chebaturkin
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System.Collections.Generic;
using Mono.CodeContracts.Static.AST;
using Mono.CodeContracts.Static.AST.Visitors;
using Mono.CodeContracts.Static.DataStructures;
using Mono.CodeContracts.Static.Providers;
namespace Mono.CodeContracts.Static.ControlFlow {
/// <summary>
/// This class wraps underlying visitor.
/// Replaces: branches to nop; branchCond to binary.
///
/// EdgeTag.Requires: (inside method) => assume, (outside method) => assert
/// EdgeTag.Ensures: (inside method) => assert, (outside method) => assume
/// </summary>
struct RemoveBranchDelegator<Data, Result, Visitor> : IILVisitor<APC, Dummy, Dummy, Data, Result>
where Visitor : IILVisitor<APC, Dummy, Dummy, Data, Result> {
private readonly IMetaDataProvider meta_data_provider;
private readonly Visitor visitor;
public RemoveBranchDelegator (Visitor visitor,
IMetaDataProvider metaDataProvider)
{
this.visitor = visitor;
this.meta_data_provider = metaDataProvider;
}
#region IILVisitor<APC,Dummy,Dummy,Data,Result> Members
public Result Binary (APC pc, BinaryOperator op, Dummy dest, Dummy operand1, Dummy operand2, Data data)
{
return this.visitor.Binary (pc, op, dest, operand1, operand2, data);
}
public Result Isinst (APC pc, TypeNode type, Dummy dest, Dummy obj, Data data)
{
return this.visitor.Isinst (pc, type, dest, obj, data);
}
public Result LoadNull (APC pc, Dummy dest, Data polarity)
{
return this.visitor.LoadNull (pc, dest, polarity);
}
public Result LoadConst (APC pc, TypeNode type, object constant, Dummy dest, Data data)
{
return this.visitor.LoadConst (pc, type, constant, dest, data);
}
public Result Sizeof (APC pc, TypeNode type, Dummy dest, Data data)
{
return this.visitor.Sizeof (pc, type, dest, data);
}
public Result Unary (APC pc, UnaryOperator op, bool unsigned, Dummy dest, Dummy source, Data data)
{
return this.visitor.Unary (pc, op, unsigned, dest, source, data);
}
public Result Entry (APC pc, Method method, Data data)
{
return this.visitor.Entry (pc, method, data);
}
public Result Assume (APC pc, EdgeTag tag, Dummy condition, Data data)
{
if (tag == EdgeTag.Requires && pc.InsideRequiresAtCall || tag == EdgeTag.Invariant && pc.InsideInvariantOnExit)
return this.visitor.Assert (pc, tag, condition, data);
return this.visitor.Assume (pc, tag, condition, data);
}
public Result Assert (APC pc, EdgeTag tag, Dummy condition, Data data)
{
if (pc.InsideEnsuresAtCall)
return this.visitor.Assume (pc, tag, condition, data);
return this.visitor.Assert (pc, tag, condition, data);
}
public Result BeginOld (APC pc, APC matchingEnd, Data data)
{
return this.visitor.BeginOld (pc, matchingEnd, data);
}
public Result EndOld (APC pc, APC matchingBegin, TypeNode type, Dummy dest, Dummy source, Data data)
{
return this.visitor.EndOld (pc, matchingBegin, type, dest, source, data);
}
public Result LoadStack (APC pc, int offset, Dummy dest, Dummy source, bool isOld, Data data)
{
return this.visitor.LoadStack (pc, offset, dest, source, isOld, data);
}
public Result LoadStackAddress (APC pc, int offset, Dummy dest, Dummy source, TypeNode type, bool isOld, Data data)
{
return this.visitor.LoadStackAddress (pc, offset, dest, source, type, isOld, data);
}
public Result LoadResult (APC pc, TypeNode type, Dummy dest, Dummy source, Data data)
{
return this.visitor.LoadResult (pc, type, dest, source, data);
}
public Result Arglist (APC pc, Dummy dest, Data data)
{
return this.visitor.Arglist (pc, dest, data);
}
public Result Branch (APC pc, APC target, bool leavesExceptionBlock, Data data)
{
return this.visitor.Nop (pc, data);
}
public Result BranchCond (APC pc, APC target, BranchOperator bop, Dummy value1, Dummy value2, Data data)
{
Dummy dest = Dummy.Value;
switch (bop) {
case BranchOperator.Beq:
return this.visitor.Binary (pc, BinaryOperator.Ceq, dest, value1, value2, data);
case BranchOperator.Bge:
return this.visitor.Binary (pc, BinaryOperator.Cge, dest, value1, value2, data);
case BranchOperator.Bge_Un:
return this.visitor.Binary (pc, BinaryOperator.Cge_Un, dest, value1, value2, data);
case BranchOperator.Bgt:
return this.visitor.Binary (pc, BinaryOperator.Cgt, dest, value1, value2, data);
case BranchOperator.Bgt_Un:
return this.visitor.Binary (pc, BinaryOperator.Cgt_Un, dest, value1, value2, data);
case BranchOperator.Ble:
return this.visitor.Binary (pc, BinaryOperator.Cle, dest, value1, value2, data);
case BranchOperator.Ble_Un:
return this.visitor.Binary (pc, BinaryOperator.Cle_Un, dest, value1, value2, data);
case BranchOperator.Blt:
return this.visitor.Binary (pc, BinaryOperator.Clt, dest, value1, value2, data);
case BranchOperator.Blt_Un:
return this.visitor.Binary (pc, BinaryOperator.Clt_Un, dest, value1, value2, data);
case BranchOperator.Bne_un:
return this.visitor.Binary (pc, BinaryOperator.Cne_Un, dest, value1, value2, data);
default:
return this.visitor.Nop (pc, data);
}
}
public Result BranchTrue (APC pc, APC target, Dummy cond, Data data)
{
return this.visitor.Nop (pc, data);
}
public Result BranchFalse (APC pc, APC target, Dummy cond, Data data)
{
return this.visitor.Nop (pc, data);
}
public Result Break (APC pc, Data data)
{
return this.visitor.Break (pc, data);
}
public Result Call<TypeList, ArgList> (APC pc, Method method, bool virt, TypeList extraVarargs, Dummy dest, ArgList args, Data data)
where TypeList : IIndexable<TypeNode>
where ArgList : IIndexable<Dummy>
{
TypeNode declaringType = this.meta_data_provider.DeclaringType (method);
if (MethodIsReferenceEquals (method, args, declaringType))
return this.visitor.Binary (pc, BinaryOperator.Ceq, dest, args [0], args [1], data);
return this.visitor.Call (pc, method, virt, extraVarargs, dest, args, data);
}
public Result Calli<TypeList, ArgList> (APC pc, TypeNode returnType, TypeList argTypes, bool instance, Dummy dest, Dummy functionPointer, ArgList args, Data data)
where TypeList : IIndexable<TypeNode>
where ArgList : IIndexable<Dummy>
{
return this.visitor.Calli (pc, returnType, argTypes, instance, dest, functionPointer, args, data);
}
public Result CheckFinite (APC pc, Dummy dest, Dummy source, Data data)
{
return this.visitor.CheckFinite (pc, dest, source, data);
}
public Result CopyBlock (APC pc, Dummy destAddress, Dummy srcAddress, Dummy len, Data data)
{
return this.visitor.CopyBlock (pc, destAddress, srcAddress, len, data);
}
public Result EndFilter (APC pc, Dummy decision, Data data)
{
return this.visitor.EndFilter (pc, decision, data);
}
public Result EndFinally (APC pc, Data data)
{
return this.visitor.EndFinally (pc, data);
}
public Result Jmp (APC pc, Method method, Data data)
{
return this.visitor.Jmp (pc, method, data);
}
public Result LoadArg (APC pc, Parameter argument, bool isOld, Dummy dest, Data data)
{
return this.visitor.LoadArg (pc, argument, isOld, dest, data);
}
public Result LoadArgAddress (APC pc, Parameter argument, bool isOld, Dummy dest, Data data)
{
return this.visitor.LoadArgAddress (pc, argument, isOld, dest, data);
}
public Result LoadLocal (APC pc, Local local, Dummy dest, Data data)
{
return this.visitor.LoadLocal (pc, local, dest, data);
}
public Result LoadLocalAddress (APC pc, Local local, Dummy dest, Data data)
{
return this.visitor.LoadLocalAddress (pc, local, dest, data);
}
public Result LoadElement (APC pc, TypeNode type, Dummy dest, Dummy array, Dummy index, Data data)
{
return this.visitor.LoadElement (pc, type, dest, array, index, data);
}
public Result LoadField (APC pc, Field field, Dummy dest, Dummy obj, Data data)
{
return this.visitor.LoadField (pc, field, dest, obj, data);
}
public Result LoadFieldAddress (APC pc, Field field, Dummy dest, Dummy obj, Data data)
{
return this.visitor.LoadFieldAddress (pc, field, dest, obj, data);
}
public Result LoadLength (APC pc, Dummy dest, Dummy array, Data data)
{
return this.visitor.LoadLength (pc, dest, array, data);
}
public Result LoadStaticField (APC pc, Field field, Dummy dest, Data data)
{
return this.visitor.LoadStaticField (pc, field, dest, data);
}
public Result LoadStaticFieldAddress (APC pc, Field field, Dummy dest, Data data)
{
return this.visitor.LoadStaticFieldAddress (pc, field, dest, data);
}
public Result LoadTypeToken (APC pc, TypeNode type, Dummy dest, Data data)
{
return this.visitor.LoadTypeToken (pc, type, dest, data);
}
public Result LoadFieldToken (APC pc, Field type, Dummy dest, Data data)
{
return this.visitor.LoadFieldToken (pc, type, dest, data);
}
public Result LoadMethodToken (APC pc, Method type, Dummy dest, Data data)
{
return this.visitor.LoadMethodToken (pc, type, dest, data);
}
public Result Nop (APC pc, Data data)
{
return this.visitor.Nop (pc, data);
}
public Result Pop (APC pc, Dummy source, Data data)
{
return this.visitor.Pop (pc, source, data);
}
public Result Return (APC pc, Dummy source, Data data)
{
return this.visitor.Return (pc, source, data);
}
public Result StoreArg (APC pc, Parameter argument, Dummy source, Data data)
{
return this.visitor.StoreArg (pc, argument, source, data);
}
public Result StoreLocal (APC pc, Local local, Dummy source, Data data)
{
return this.visitor.StoreLocal (pc, local, source, data);
}
public Result StoreElement (APC pc, TypeNode type, Dummy array, Dummy index, Dummy value, Data data)
{
return this.visitor.StoreElement (pc, type, array, index, value, data);
}
public Result StoreField (APC pc, Field field, Dummy obj, Dummy value, Data data)
{
return this.visitor.StoreField (pc, field, obj, value, data);
}
public Result StoreStaticField (APC pc, Field field, Dummy value, Data data)
{
return this.visitor.StoreStaticField (pc, field, value, data);
}
public Result Switch (APC pc, TypeNode type, IEnumerable<Pair<object, APC>> cases, Dummy value, Data data)
{
return this.visitor.Nop (pc, data);
}
public Result Box (APC pc, TypeNode type, Dummy dest, Dummy source, Data data)
{
return this.visitor.Box (pc, type, dest, source, data);
}
public Result ConstrainedCallvirt<TypeList, ArgList> (APC pc, Method method, TypeNode constraint, TypeList extraVarargs, Dummy dest, ArgList args, Data data)
where TypeList : IIndexable<TypeNode>
where ArgList : IIndexable<Dummy>
{
return this.visitor.ConstrainedCallvirt (pc, method, constraint, extraVarargs, dest, args, data);
}
public Result CastClass (APC pc, TypeNode type, Dummy dest, Dummy obj, Data data)
{
return this.visitor.CastClass (pc, type, dest, obj, data);
}
public Result CopyObj (APC pc, TypeNode type, Dummy destPtr, Dummy sourcePtr, Data data)
{
return this.visitor.CopyObj (pc, type, destPtr, sourcePtr, data);
}
public Result Initobj (APC pc, TypeNode type, Dummy ptr, Data data)
{
return this.visitor.Initobj (pc, type, ptr, data);
}
public Result NewArray<ArgList> (APC pc, TypeNode type, Dummy dest, ArgList lengths, Data data) where ArgList : IIndexable<Dummy>
{
return this.visitor.NewArray (pc, type, dest, lengths, data);
}
public Result NewObj<ArgList> (APC pc, Method ctor, Dummy dest, ArgList args, Data data) where ArgList : IIndexable<Dummy>
{
return this.visitor.NewObj (pc, ctor, dest, args, data);
}
public Result MkRefAny (APC pc, TypeNode type, Dummy dest, Dummy obj, Data data)
{
return this.visitor.MkRefAny (pc, type, dest, obj, data);
}
public Result RefAnyType (APC pc, Dummy dest, Dummy source, Data data)
{
return this.visitor.RefAnyType (pc, dest, source, data);
}
public Result RefAnyVal (APC pc, TypeNode type, Dummy dest, Dummy source, Data data)
{
return this.visitor.RefAnyVal (pc, type, dest, source, data);
}
public Result Rethrow (APC pc, Data data)
{
return this.visitor.Rethrow (pc, data);
}
public Result Throw (APC pc, Dummy exception, Data data)
{
return this.visitor.Throw (pc, exception, data);
}
public Result Unbox (APC pc, TypeNode type, Dummy dest, Dummy obj, Data data)
{
return this.visitor.Unbox (pc, type, dest, obj, data);
}
public Result UnboxAny (APC pc, TypeNode type, Dummy dest, Dummy obj, Data data)
{
return this.visitor.UnboxAny (pc, type, dest, obj, data);
}
#endregion
private bool MethodIsReferenceEquals<ArgList> (Method method, ArgList args, TypeNode declaringType)
where ArgList : IIndexable<Dummy>
{
return args.Count == 2 && this.meta_data_provider.IsStatic (method)
&& this.meta_data_provider.Equal (declaringType, this.meta_data_provider.System_Object)
&& this.meta_data_provider.Name (method) == "ReferenceEquals";
}
}
}

View File

@@ -0,0 +1,186 @@
//
// Subroutine.cs
//
// Authors:
// Alexander Chebaturkin (chebaturkin@gmail.com)
//
// Copyright (C) 2011 Alexander Chebaturkin
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Collections.Generic;
using System.IO;
using Mono.CodeContracts.Static.Analysis;
using Mono.CodeContracts.Static.DataStructures;
namespace Mono.CodeContracts.Static.ControlFlow {
abstract class Subroutine : IPropertyCollection, IEquatable<Subroutine> {
private static int _subroutineIdGenerator;
private readonly PropertyCollection properties = new PropertyCollection ();
private readonly int subroutine_id = _subroutineIdGenerator++;
public virtual SubroutineKind Kind
{
get { return SubroutineKind.Unknown; }
}
public int Id
{
get { return this.subroutine_id; }
}
public abstract CFGBlock Entry { get; }
public abstract CFGBlock EntryAfterRequires { get; }
public abstract CFGBlock Exit { get; }
public abstract CFGBlock ExceptionExit { get; }
public abstract string Name { get; }
public abstract int BlockCount { get; }
public abstract IEnumerable<CFGBlock> Blocks { get; }
public virtual bool IsRequires
{
get { return false; }
}
public virtual bool IsEnsures
{
get { return false; }
}
public virtual bool IsOldValue
{
get { return false; }
}
public virtual bool IsMethod
{
get { return false; }
}
public virtual bool IsConstructor
{
get { return false; }
}
public virtual bool IsInvariant
{
get { return false; }
}
public virtual bool IsContract
{
get { return false; }
}
public bool IsEnsuresOrOldValue
{
get { return IsEnsures || IsOldValue; }
}
public abstract EdgeMap<EdgeTag> SuccessorEdges { get; }
public abstract EdgeMap<EdgeTag> PredecessorEdges { get; }
public abstract DepthFirst.Visitor<CFGBlock, Dummy> EdgeInfo { get; }
public virtual bool IsFaultFinally
{
get { return false; }
}
public abstract bool HasReturnValue { get; }
public abstract bool HasContextDependentStackDepth { get; }
public abstract int StackDelta { get; }
#region IPropertyCollection Members
public bool TryGetValue<T> (TypedKey key, out T value)
{
return this.properties.TryGetValue (key, out value);
}
#endregion
#region Implementation of IPropertyCollection
public bool Contains (TypedKey key)
{
return this.properties.Contains (key);
}
public void Add<T> (TypedKey key, T value)
{
this.properties.Add (key, value);
}
#endregion
public override string ToString ()
{
return string.Format ("SR {0}: BlockCount:{1}, Kind:{2}", Id, BlockCount, Kind);
}
public abstract IEnumerable<CFGBlock> SuccessorBlocks (CFGBlock block);
public IEnumerable<Pair<EdgeTag, CFGBlock>> SuccessorEdgesFor (CFGBlock block)
{
return SuccessorEdges [block];
}
public abstract IEnumerable<CFGBlock> PredecessorBlocks (CFGBlock block);
public abstract bool IsJoinPoint (CFGBlock block);
public abstract bool IsSplitPoint (CFGBlock block);
public abstract bool HasSingleSuccessor (APC point, out APC ifFound);
public abstract bool HasSinglePredecessor (APC point, out APC ifFound);
public abstract void AddEdgeSubroutine (CFGBlock from, CFGBlock to, Subroutine subroutine, EdgeTag tag);
public abstract IEnumerable<APC> Successors (APC pc);
public abstract IEnumerable<APC> Predecessors (APC pc);
public abstract bool IsSubroutineEnd (CFGBlock block);
public abstract bool IsSubroutineStart (CFGBlock block);
public abstract bool IsCatchFilterHeader (CFGBlock block);
public abstract APC ComputeTargetFinallyContext (APC pc, CFGBlock succ);
public abstract Sequence<Pair<EdgeTag, Subroutine>> EdgeSubroutinesOuterToInner (CFGBlock current, CFGBlock succ, out bool isExceptionHandlerEdge, Sequence<Edge<CFGBlock, EdgeTag>> context);
public abstract Sequence<Pair<EdgeTag, Subroutine>> GetOrdinaryEdgeSubroutines (CFGBlock current, CFGBlock succ, Sequence<Edge<CFGBlock, EdgeTag>> context);
public abstract void Initialize ();
public abstract IEnumerable<Subroutine> UsedSubroutines (HashSet<int> alreadySeen);
public IEnumerable<Subroutine> UsedSubroutines ()
{
return UsedSubroutines (new HashSet<int> ());
}
public abstract IEnumerable<CFGBlock> ExceptionHandlers<Data, Type> (CFGBlock block, Subroutine innerSubroutine,
Data data, IHandlerFilter<Data> handlerPredicate);
public abstract void Print (TextWriter tw, ILPrinter<APC> printer,
Func<CFGBlock, IEnumerable<Sequence<Edge<CFGBlock, EdgeTag>>>> contextLookup,
Sequence<Edge<CFGBlock, EdgeTag>> context,
HashSet<Pair<Subroutine, Sequence<Edge<CFGBlock, EdgeTag>>>> set);
#region Implementation of IEquatable<Subroutine>
public bool Equals (Subroutine other)
{
return Id == other.Id;
}
#endregion
}
}

View File

@@ -0,0 +1,41 @@
//
// SubroutineKind.cs
//
// Authors:
// Alexander Chebaturkin (chebaturkin@gmail.com)
//
// Copyright (C) 2011 Alexander Chebaturkin
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
namespace Mono.CodeContracts.Static.ControlFlow {
enum SubroutineKind {
Unknown,
Requires,
Ensures,
Method,
Entry,
Fault,
Finally,
Simple,
Old
}
}