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,152 @@
//
// EnsuresSubroutine.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 Mono.CodeContracts.Static.AST;
using Mono.CodeContracts.Static.ControlFlow.Blocks;
using Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders;
using Mono.CodeContracts.Static.DataStructures;
namespace Mono.CodeContracts.Static.ControlFlow.Subroutines {
sealed class EnsuresSubroutine<Label> : MethodContractSubroutine<Label>, IEquatable<EnsuresSubroutine<Label>> {
private readonly Dictionary<int, Pair<CFGBlock, TypeNode>> inferred_old_label_reverse_map;
public EnsuresSubroutine (SubroutineFacade subroutineFacade,
Method method, IImmutableSet<Subroutine> inherited) : base (subroutineFacade, method)
{
this.inferred_old_label_reverse_map = new Dictionary<int, Pair<CFGBlock, TypeNode>> ();
AddSuccessor (Entry, EdgeTag.Entry, Exit);
AddBaseEnsures (Entry, Exit, inherited);
Commit ();
}
public EnsuresSubroutine (SubroutineFacade subroutineFacade,
Method method,
SimpleSubroutineBuilder<Label> builder, Label startLabel, IImmutableSet<Subroutine> inherited)
: base (subroutineFacade, method, builder, startLabel)
{
this.inferred_old_label_reverse_map = new Dictionary<int, Pair<CFGBlock, TypeNode>> ();
AddBaseEnsures (Entry, GetTargetBlock (startLabel), inherited);
}
public override SubroutineKind Kind
{
get { return SubroutineKind.Ensures; }
}
public override bool IsEnsures
{
get { return true; }
}
public override bool IsContract
{
get { return true; }
}
#region IEquatable<EnsuresSubroutine<Label>> Members
public bool Equals (EnsuresSubroutine<Label> other)
{
return Id == other.Id;
}
#endregion
private void AddBaseEnsures (CFGBlock from, CFGBlock to, IImmutableSet<Subroutine> inherited)
{
if (inherited == null)
return;
foreach (Subroutine subroutine in inherited.Elements)
AddEdgeSubroutine (from, to, subroutine, EdgeTag.Inherited);
}
public override void Initialize ()
{
if (Builder == null)
return;
Builder.BuildBlocks (this.StartLabel, this);
Commit ();
Builder = null;
}
public override BlockWithLabels<Label> NewBlock ()
{
return new EnsuresBlock<Label> (this, ref this.BlockIdGenerator);
}
public override void Commit ()
{
base.Commit ();
var visitor = new OldScanStateMachine<Label> (this);
EnsuresBlock<Label> priorBlock = null;
foreach (CFGBlock block in Blocks) {
var ensuresBlock = block as EnsuresBlock<Label>;
if (ensuresBlock != null) {
priorBlock = ensuresBlock;
int count = ensuresBlock.Count;
visitor.StartBlock (ensuresBlock);
for (int i = 0; i < count; i++) {
if (ensuresBlock.OriginalForwardDecode<int, Boolean, OldScanStateMachine<Label>> (i, visitor, i))
ensuresBlock.AddInstruction (i);
}
} else
visitor.HandlePotentialCallBlock (block as MethodCallBlock<Label>, priorBlock);
foreach (CFGBlock succ in SuccessorBlocks (block))
visitor.SetStartState (succ);
}
}
public void AddInferredOldMap (int blockIndex, int instructionIndex, CFGBlock otherBlock, TypeNode endOldType)
{
this.inferred_old_label_reverse_map.Add (OverlayInstructionKey (blockIndex, instructionIndex), new Pair<CFGBlock, TypeNode> (otherBlock, endOldType));
}
private static int OverlayInstructionKey (int blockIndex, int instructionIndex)
{
return (instructionIndex << 16) + blockIndex;
}
public CFGBlock InferredBeginEndBijection (APC pc)
{
TypeNode endOldType;
return InferredBeginEndBijection (pc, out endOldType);
}
public CFGBlock InferredBeginEndBijection (APC pc, out TypeNode endOldType)
{
Pair<CFGBlock, TypeNode> pair;
if (!this.inferred_old_label_reverse_map.TryGetValue (OverlayInstructionKey (pc.Block.Index, pc.Index), out pair))
throw new InvalidOperationException ("Fatal bug in ensures CFG begin/end old map");
endOldType = pair.Value;
return pair.Key;
}
}
}

View File

@@ -0,0 +1,52 @@
//
// FaultFinallySubroutineBase.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.ControlFlow.Subroutines.Builders;
namespace Mono.CodeContracts.Static.ControlFlow.Subroutines {
abstract class FaultFinallySubroutineBase<Label, Handler> : SubroutineWithHandlers<Label, Handler> {
protected FaultFinallySubroutineBase (SubroutineFacade subroutineFacade, Label startLabel, SubroutineBuilder<Label> builder)
: base (subroutineFacade, startLabel, builder)
{
}
public override bool HasContextDependentStackDepth
{
get { return false; }
}
public override bool IsFaultFinally
{
get { return true; }
}
public override void Initialize ()
{
}
}
}

View File

@@ -0,0 +1,43 @@
//
// FaultSubroutine.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.ControlFlow.Subroutines.Builders;
namespace Mono.CodeContracts.Static.ControlFlow.Subroutines {
class FaultSubroutine<Label, Handler> : FaultFinallySubroutineBase<Label, Handler> {
public FaultSubroutine (SubroutineFacade subroutineFacade, Label startLabel,
SubroutineBuilder<Label> builder) : base (subroutineFacade, startLabel, builder)
{
}
public override SubroutineKind Kind
{
get { return SubroutineKind.Fault; }
}
}
}

View File

@@ -0,0 +1,43 @@
//
// FinallySubroutine.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.ControlFlow.Subroutines.Builders;
namespace Mono.CodeContracts.Static.ControlFlow.Subroutines {
class FinallySubroutine<Label, Handler> : FaultFinallySubroutineBase<Label, Handler> {
public FinallySubroutine (SubroutineFacade subroutineFacade, Label startLabel, SubroutineBuilder<Label> builder)
: base (subroutineFacade, startLabel, builder)
{
}
public override SubroutineKind Kind
{
get { return SubroutineKind.Finally; }
}
}
}

View File

@@ -0,0 +1,63 @@
//
// MethodContractSubroutine.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;
using Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders;
namespace Mono.CodeContracts.Static.ControlFlow.Subroutines {
abstract class MethodContractSubroutine<TLabel> : SubroutineBase<TLabel>, IMethodInfo {
private readonly Method method;
protected MethodContractSubroutine (SubroutineFacade subroutineFacade,
Method method) : base (subroutineFacade)
{
this.method = method;
}
protected MethodContractSubroutine (SubroutineFacade subroutineFacade,
Method method,
SimpleSubroutineBuilder<TLabel> builder,
TLabel startLabel) : base (subroutineFacade, startLabel, builder)
{
this.method = method;
}
protected new SimpleSubroutineBuilder<TLabel> Builder
{
get { return (SimpleSubroutineBuilder<TLabel>) base.Builder; }
set { base.Builder = value; }
}
#region IMethodInfo Members
public Method Method
{
get { return this.method; }
}
#endregion
}
}

View File

@@ -0,0 +1,136 @@
//
// MethodSubroutine.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 Mono.CodeContracts.Static.AST;
using Mono.CodeContracts.Static.ControlFlow.Blocks;
using Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders;
using Mono.CodeContracts.Static.Providers;
namespace Mono.CodeContracts.Static.ControlFlow.Subroutines {
class MethodSubroutine<Label, Handler> : SubroutineWithHandlers<Label, Handler>, IMethodInfo {
private readonly Method method;
private HashSet<BlockWithLabels<Label>> blocks_ending_in_return_point;
public MethodSubroutine (SubroutineFacade subroutineFacade, Method method)
: base (subroutineFacade)
{
this.method = method;
}
public MethodSubroutine (SubroutineFacade SubroutineFacade,
Method method, Label startLabel,
SubroutineWithHandlersBuilder<Label, Handler> builder) : base (SubroutineFacade, startLabel, builder)
{
this.method = method;
IMetaDataProvider metaDataProvider = this.SubroutineFacade.MetaDataProvider;
builder.BuildBlocks (startLabel, this);
BlockWithLabels<Label> targetBlock = GetTargetBlock (startLabel);
Commit ();
TypeNode type = metaDataProvider.DeclaringType (method);
Subroutine invariant = this.SubroutineFacade.GetInvariant (type);
if (invariant != null && !metaDataProvider.IsConstructor (method) && !metaDataProvider.IsStatic (method)) {
AddEdgeSubroutine (Entry, targetBlock, invariant, EdgeTag.Entry);
Subroutine requires = this.SubroutineFacade.GetRequires (method);
if (requires != null)
AddEdgeSubroutine (Entry, targetBlock, requires, EdgeTag.Entry);
} else
AddEdgeSubroutine (Entry, targetBlock, this.SubroutineFacade.GetRequires (method), EdgeTag.Entry);
if (this.blocks_ending_in_return_point == null)
return;
Subroutine ensures = this.SubroutineFacade.GetEnsures (method);
bool putInvariantAfterExit = !metaDataProvider.IsStatic (method)
&& !metaDataProvider.IsFinalizer (method) && !metaDataProvider.IsDispose (method);
foreach (var block in this.blocks_ending_in_return_point) {
if (putInvariantAfterExit)
AddEdgeSubroutine (block, Exit, invariant, EdgeTag.Exit);
AddEdgeSubroutine (block, Exit, ensures, EdgeTag.Exit);
}
if (ensures != null) {
throw new NotImplementedException();
}
this.blocks_ending_in_return_point = null;
}
#region Overrides of Subroutine
public override void Initialize ()
{
}
#endregion
#region Overrides of SubroutineBase<Label>
public override void AddReturnBlock (BlockWithLabels<Label> block)
{
if (this.blocks_ending_in_return_point == null)
this.blocks_ending_in_return_point = new HashSet<BlockWithLabels<Label>> ();
this.blocks_ending_in_return_point.Add (block);
base.AddReturnBlock (block);
}
#endregion
#region Implementation of IMethodInfo<Method>
public Method Method
{
get { return this.method; }
}
#endregion
public override SubroutineKind Kind
{
get { return SubroutineKind.Method; }
}
public override bool HasReturnValue
{
get { return !this.SubroutineFacade.MetaDataProvider.IsVoidMethod (this.method); }
}
public override bool IsMethod
{
get { return true; }
}
public override bool IsConstructor
{
get { return this.SubroutineFacade.MetaDataProvider.IsConstructor (this.method); }
}
public override string Name
{
get { return this.SubroutineFacade.MetaDataProvider.FullName (this.method); }
}
}
}

View File

@@ -0,0 +1,160 @@
//
// OldScanStateMachine.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.ControlFlow.Blocks;
using Mono.CodeContracts.Static.DataStructures;
namespace Mono.CodeContracts.Static.ControlFlow.Subroutines {
class OldScanStateMachine<Label> : ILVisitorBase<Label, Dummy, Dummy, int, bool>,
IAggregateVisitor<Label, int, bool> {
private readonly Dictionary<CFGBlock, ScanState> block_start_state = new Dictionary<CFGBlock, ScanState> ();
private readonly EnsuresSubroutine<Label> subroutine;
private EnsuresBlock<Label> current_block;
private TypeNode next_end_old_type;
private ScanState state;
public OldScanStateMachine (EnsuresSubroutine<Label> ensuresSubroutine)
{
this.subroutine = ensuresSubroutine;
this.state = ScanState.OutsideOld;
}
#region Overrides of ILVisitorBase<Label,Local,Parameter,Method,Field,Type,Dummy,Dummy,int,bool>
public override bool DefaultVisit (Label pc, int index)
{
if (this.state != ScanState.InsertingOld)
return this.current_block.UsesOverriding;
this.state = ScanState.OutsideOld;
this.current_block.EndOldWithoutInstruction (this.subroutine.SubroutineFacade.MetaDataProvider.ManagedPointer (this.next_end_old_type));
return true;
}
#endregion
#region Implementation of ICodeQuery<Label,Local,Parameter,Method,Field,Type,int,bool>
public bool Aggregate (Label pc, Label aggregateStart, bool canBeTargetOfBranch, int data)
{
return Nop (pc, data);
}
#endregion
#region IAggregateVisitor<Label,int,bool> Members
public override bool Nop (Label pc, int data)
{
return this.current_block.UsesOverriding;
}
public override bool BeginOld (Label pc, Label matchingEnd, int data)
{
this.state = ScanState.InsideOld;
return this.current_block.UsesOverriding;
}
public override bool EndOld (Label pc, Label matchingEnd, TypeNode type, Dummy dest, Dummy source, int data)
{
this.state = ScanState.OutsideOld;
return this.current_block.UsesOverriding;
}
public override bool LoadField (Label pc, Field field, Dummy dest, Dummy obj, int data)
{
if (this.state != ScanState.InsertingOld)
return this.current_block.UsesOverriding;
this.state = ScanState.OutsideOld;
this.current_block.EndOld (data, this.subroutine.SubroutineFacade.MetaDataProvider.FieldType (field));
return false;
}
public override bool LoadFieldAddress (Label pc, Field field, Dummy dest, Dummy obj, int data)
{
if (this.state == ScanState.InsertingOld)
this.next_end_old_type = this.subroutine.SubroutineFacade.MetaDataProvider.FieldType (field);
return this.current_block.UsesOverriding;
}
public override bool Call<TypeList, ArgList> (Label pc, Method method, bool virt, TypeList extraVarargs, Dummy dest, ArgList args, int data)
{
return false;
}
#endregion
public void HandlePotentialCallBlock (MethodCallBlock<Label> block, EnsuresBlock<Label> priorBlock)
{
if (block == null || this.state != ScanState.InsertingOld)
return;
int count = this.subroutine.SubroutineFacade.MetaDataProvider.Parameters (block.CalledMethod).Count;
if (!this.subroutine.SubroutineFacade.MetaDataProvider.IsStatic (block.CalledMethod))
++count;
if (count > 1) {
this.state = ScanState.OutsideOld;
TypeNode mp = this.subroutine.SubroutineFacade.MetaDataProvider.ManagedPointer (this.next_end_old_type);
priorBlock.EndOldWithoutInstruction (mp);
} else {
this.state = ScanState.InsertingOldAfterCall;
this.next_end_old_type = this.subroutine.SubroutineFacade.MetaDataProvider.ReturnType (block.CalledMethod);
}
}
public void StartBlock (EnsuresBlock<Label> block)
{
if (!this.block_start_state.TryGetValue (block, out this.state)) {
this.state = ScanState.OutsideOld;
this.block_start_state.Add (block, this.state);
}
if (this.state == ScanState.InsertingOld)
block.StartOverridingLabels ();
if (this.state == ScanState.InsertingOldAfterCall) {
block.StartOverridingLabels ();
block.EndOldWithoutInstruction (this.next_end_old_type);
this.state = ScanState.OutsideOld;
}
this.current_block = block;
}
public void SetStartState (CFGBlock succ)
{
ScanState sstate;
if (!this.block_start_state.TryGetValue (succ, out sstate))
this.block_start_state.Add (succ, this.state);
}
#region Nested type: ScanState
private enum ScanState {
OutsideOld,
InsideOld,
InsertingOld,
InsertingOldAfterCall
}
#endregion
}
}

View File

@@ -0,0 +1,85 @@
//
// OldValueSubroutine.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;
using Mono.CodeContracts.Static.ControlFlow.Blocks;
using Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders;
using Mono.CodeContracts.Static.DataStructures;
namespace Mono.CodeContracts.Static.ControlFlow.Subroutines {
class OldValueSubroutine<TLabel> : MethodContractSubroutine<TLabel> {
private BlockWithLabels<TLabel> begin_old_block;
private BlockWithLabels<TLabel> end_old_block;
public OldValueSubroutine (SubroutineFacade subroutineFacade, Method method,
SimpleSubroutineBuilder<TLabel> builder, TLabel startLabel)
: base (subroutineFacade, method, builder, startLabel)
{
}
public override SubroutineKind Kind
{
get { return SubroutineKind.Old; }
}
public override int StackDelta
{
get { return 1; }
}
public override bool IsOldValue
{
get { return true; }
}
public override void Initialize ()
{
}
public void Commit (BlockWithLabels<TLabel> endOldBlock)
{
this.end_old_block = endOldBlock;
base.Commit ();
}
public void RegisterBeginBlock (BlockWithLabels<TLabel> beginOldBlock)
{
this.begin_old_block = beginOldBlock;
}
public APC BeginOldAPC (Sequence<Edge<CFGBlock, EdgeTag>> context)
{
return new APC (this.begin_old_block, 0, context);
}
public APC EndOldAPC (Sequence<Edge<CFGBlock, EdgeTag>> context)
{
return new APC (this.end_old_block, this.end_old_block.Count - 1, context);
}
}
}

View File

@@ -0,0 +1,84 @@
//
// RequiresSubroutine.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 Mono.CodeContracts.Static.AST;
using Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders;
using Mono.CodeContracts.Static.DataStructures;
namespace Mono.CodeContracts.Static.ControlFlow.Subroutines {
sealed class RequiresSubroutine<TLabel> : MethodContractSubroutine<TLabel>, IEquatable<RequiresSubroutine<TLabel>>
{
public override SubroutineKind Kind { get { return SubroutineKind.Requires; } }
public override bool IsContract { get { return true; } }
public override bool IsRequires { get { return true; } }
public RequiresSubroutine(SubroutineFacade subroutineFacade,
Method method,
IImmutableSet<Subroutine> inherited)
: base(subroutineFacade, method)
{
AddSuccessor(Entry, EdgeTag.Entry, Exit);
AddBaseRequires(Exit, inherited);
Commit();
}
public RequiresSubroutine(SubroutineFacade subroutineFacade,
Method method,
SimpleSubroutineBuilder<TLabel> builder,
TLabel entryLabel,
IImmutableSet<Subroutine> inheritedRequires)
: base(subroutineFacade, method, builder, entryLabel)
{
AddBaseRequires(this.GetTargetBlock(entryLabel), inheritedRequires);
}
public override void Initialize()
{
if (this.Builder == null)
return;
this.Builder.BuildBlocks(this.StartLabel, this);
this.Commit();
this.Builder = null;
}
private void AddBaseRequires(CFGBlock targetOfEntry, IImmutableSet<Subroutine> inherited)
{
foreach (var subroutine in inherited.Elements)
this.AddEdgeSubroutine(this.Entry, targetOfEntry, subroutine, EdgeTag.Inherited);
}
public bool Equals(RequiresSubroutine<TLabel> that)
{
return this.Id == that.Id;
}
}
}

View File

@@ -0,0 +1,58 @@
//
// SimpleSubroutine.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.ControlFlow.Subroutines.Builders;
namespace Mono.CodeContracts.Static.ControlFlow.Subroutines {
class SimpleSubroutine<Label> : SubroutineBase<Label> {
private readonly int stack_delta;
public SimpleSubroutine (int stackDelta, SubroutineFacade subroutineFacade,
Label startLabel, SimpleSubroutineBuilder<Label> builder)
: base (subroutineFacade, startLabel, builder)
{
this.stack_delta = stackDelta;
builder.BuildBlocks (startLabel, this);
Commit ();
}
public override int StackDelta
{
get { return this.stack_delta; }
}
public override SubroutineKind Kind
{
get { return SubroutineKind.Simple; }
}
public override void Initialize ()
{
}
}
}

View File

@@ -0,0 +1,130 @@
//
// SubroutineFacade.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.Linq;
using Mono.CodeContracts.Static.AST;
using Mono.CodeContracts.Static.AST.Visitors;
using Mono.CodeContracts.Static.ControlFlow.Blocks;
using Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders;
using Mono.CodeContracts.Static.DataStructures;
using Mono.CodeContracts.Static.Providers;
namespace Mono.CodeContracts.Static.ControlFlow.Subroutines {
class SubroutineFacade : IMethodCodeConsumer<Dummy, Subroutine> {
public readonly IContractProvider ContractProvider;
public readonly IMetaDataProvider MetaDataProvider;
// private readonly EnsuresFactory ensures_factory;
private readonly Dictionary<Method, ICFG> method_cache = new Dictionary<Method, ICFG> ();
private readonly RequiresFactory requires_factory;
public SubroutineFacade (IMetaDataProvider metaDataProvider,
IContractProvider contractProvider)
{
this.MetaDataProvider = metaDataProvider;
this.ContractProvider = contractProvider;
this.requires_factory = new RequiresFactory (this);
// this.ensures_factory = new EnsuresFactory (this);
}
#region IMethodCodeConsumer<Dummy,Subroutine> Members
Subroutine IMethodCodeConsumer<Dummy, Subroutine>.Accept<Label, Handler> (
IMethodCodeProvider<Label, Handler> codeProvider,
Label entry,
Method method,
Dummy data)
{
var builder = new SubroutineWithHandlersBuilder<Label, Handler> (codeProvider, this, method, entry);
return new MethodSubroutine<Label, Handler> (this, method, entry, builder);
}
#endregion
public TResult ForwardDecode<TData, TResult, TVisitor> (APC pc, TVisitor visitor, TData data)
where TVisitor : IILVisitor<APC, Dummy, Dummy, TData, TResult>
{
var block = pc.Block as BlockBase;
if (block != null)
return block.ForwardDecode<TData, TResult, TVisitor> (pc, visitor, data);
return visitor.Nop (pc, data);
}
public Subroutine GetRequires (Method method)
{
method = this.MetaDataProvider.Unspecialized (method);
return this.requires_factory.Get (method);
}
public Subroutine GetEnsures (Method method)
{
return null;
//todo: implement handling this in MethodSubroutine and uncomment lines below
// method = this.MetaDataProvider.Unspecialized (method);
// return this.ensures_factory.Get (method);
}
public Subroutine GetInvariant (TypeNode type)
{
//todo: implement this
return null;
}
public ICFG GetControlFlowGraph (Method method)
{
if (this.method_cache.ContainsKey (method))
return this.method_cache [method];
if (!this.MetaDataProvider.HasBody (method))
throw new InvalidOperationException ("Method has no body");
return new ControlFlowGraph (this.MetaDataProvider.AccessMethodBody (method, this, Dummy.Value), this);
}
public void AddReads (Method method, Field field)
{
throw new NotImplementedException ();
}
public IEnumerable<Method> GetAffectedGetters (Field field)
{
//todo: implement this
return new Method[0];
}
public IEnumerable<Field> GetModifies (Method method)
{
//todo: implement this
return Enumerable.Empty<Field> ();
}
}
}

View File

@@ -0,0 +1,208 @@
//
// SubroutineWithHandlers.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 System.Linq;
using Mono.CodeContracts.Static.Analysis;
using Mono.CodeContracts.Static.ControlFlow.Blocks;
using Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders;
using Mono.CodeContracts.Static.DataStructures;
using Mono.CodeContracts.Static.Providers;
namespace Mono.CodeContracts.Static.ControlFlow.Subroutines {
abstract class SubroutineWithHandlers<Label, Handler> : SubroutineBase<Label> {
protected readonly Dictionary<Handler, BlockWithLabels<Label>> CatchFilterHeaders = new Dictionary<Handler, BlockWithLabels<Label>> ();
public readonly Dictionary<Handler, Subroutine> FaultFinallySubroutines = new Dictionary<Handler, Subroutine> ();
protected readonly Dictionary<Handler, BlockWithLabels<Label>> FilterCodeBlocks = new Dictionary<Handler, BlockWithLabels<Label>> ();
public readonly Dictionary<CFGBlock, Sequence<Handler>> ProtectingHandlers = new Dictionary<CFGBlock, Sequence<Handler>> ();
public Sequence<Handler> CurrentProtectingHandlers = Sequence<Handler>.Empty;
protected SubroutineWithHandlers (SubroutineFacade subroutineFacade)
: base (subroutineFacade)
{
}
protected SubroutineWithHandlers (SubroutineFacade subroutineFacade,
Label startLabel,
SubroutineBuilder<Label> builder)
: base (subroutineFacade, startLabel, builder)
{
}
protected new IMethodCodeProvider<Label, Handler> CodeProvider
{
get { return (IMethodCodeProvider<Label, Handler>) base.CodeProvider; }
}
private bool IsFault (Handler handler)
{
return CodeProvider.IsFaultHandler (handler);
}
private Sequence<Handler> ProtectingHandlerList (CFGBlock block)
{
Sequence<Handler> list;
this.ProtectingHandlers.TryGetValue (block, out list);
return list;
}
public BlockWithLabels<Label> CreateCatchFilterHeader (Handler handler, Label label)
{
BlockWithLabels<Label> block;
if (!this.LabelsThatStartBlocks.TryGetValue (label, out block)) {
block = new CatchFilterEntryBlock<Label> (this, ref this.BlockIdGenerator);
this.CatchFilterHeaders.Add (handler, block);
this.LabelsThatStartBlocks.Add (label, block);
if (CodeProvider.IsFilterHandler (handler)) {
BlockWithLabels<Label> targetBlock = GetTargetBlock (CodeProvider.FilterExpressionStart (handler));
this.FilterCodeBlocks.Add (handler, targetBlock);
}
}
return block;
}
public override IEnumerable<Subroutine> UsedSubroutines (HashSet<int> alreadySeen)
{
return this.FaultFinallySubroutines.Values.Concat (base.UsedSubroutines (alreadySeen));
}
public override Sequence<Pair<EdgeTag, Subroutine>> EdgeSubroutinesOuterToInner (CFGBlock current, CFGBlock succ,
out bool isExceptionHandlerEdge, Sequence<Edge<CFGBlock, EdgeTag>> context)
{
if (current.Subroutine != this)
return current.Subroutine.EdgeSubroutinesOuterToInner (current, succ, out isExceptionHandlerEdge, context);
Sequence<Handler> l1 = ProtectingHandlerList (current);
Sequence<Handler> l2 = ProtectingHandlerList (succ);
isExceptionHandlerEdge = IsCatchFilterHeader (succ);
Sequence<Pair<EdgeTag, Subroutine>> result = GetOrdinaryEdgeSubroutines (current, succ, context);
while (l1 != l2) {
if (l1.Length () >= l2.Length ()) {
Handler head = l1.Head;
if (IsFaultOrFinally (head) && (!IsFault (head) || isExceptionHandlerEdge))
result = result.Cons (new Pair<EdgeTag, Subroutine> (EdgeTag.Finally, this.FaultFinallySubroutines [head]));
l1 = l1.Tail;
} else
l2 = l2.Tail;
}
return result;
}
private bool IsFaultOrFinally (Handler handler)
{
return CodeProvider.IsFaultHandler (handler) || CodeProvider.IsFinallyHandler (handler);
}
public override IEnumerable<Pair<Dummy, CFGBlock>> Successors (CFGBlock node)
{
foreach (var pair in SuccessorEdges [node])
yield return new Pair<Dummy, CFGBlock> (Dummy.Value, pair.Value);
foreach (Handler handler in ProtectingHandlerList (node).AsEnumerable ()) {
if (!IsFaultOrFinally (handler))
yield return new Pair<Dummy, CFGBlock> (Dummy.Value, this.CatchFilterHeaders [handler]);
}
if (node != ExceptionExit)
yield return new Pair<Dummy, CFGBlock> (Dummy.Value, ExceptionExit);
}
public override IEnumerable<CFGBlock> ExceptionHandlers<Data, TType> (CFGBlock block, Subroutine innerSubroutine,
Data data, IHandlerFilter<Data> handlerPredicate)
{
IHandlerFilter<Data> handleFilter = handlerPredicate;
Sequence<Handler> protectingHandlers = ProtectingHandlerList (block);
if (innerSubroutine != null && innerSubroutine.IsFaultFinally) {
for (; protectingHandlers != null; protectingHandlers = protectingHandlers.Tail) {
if (IsFaultOrFinally (protectingHandlers.Head) && this.FaultFinallySubroutines [protectingHandlers.Head] == innerSubroutine) {
protectingHandlers = protectingHandlers.Tail;
break;
}
}
}
for (; protectingHandlers != null; protectingHandlers = protectingHandlers.Tail) {
Handler handler = protectingHandlers.Head;
if (!IsFaultOrFinally (handler)) {
if (handleFilter != null) {
bool stopPropagation;
if (CodeProvider.IsCatchHandler (handler)) {
if (handleFilter.Catch (data, CodeProvider.CatchType (handler), out stopPropagation))
yield return this.CatchFilterHeaders [handler];
} else if (handleFilter.Filter (data, new APC (this.FilterCodeBlocks [handler], 0, null), out stopPropagation))
yield return this.CatchFilterHeaders [handler];
if (stopPropagation)
yield break;
} else
yield return this.CatchFilterHeaders [handler];
if (CodeProvider.IsCatchAllHandler (handler))
yield break;
}
}
yield return ExceptionExit;
}
protected override void PrintReferencedSubroutines (TextWriter tw, HashSet<Subroutine> subs, ILPrinter<APC> printer,
Func<CFGBlock, IEnumerable<Sequence<Edge<CFGBlock, EdgeTag>>>> contextLookup,
Sequence<Edge<CFGBlock, EdgeTag>> context,
HashSet<Pair<Subroutine, Sequence<Edge<CFGBlock, EdgeTag>>>> printed)
{
foreach (Subroutine sub in this.FaultFinallySubroutines.Values) {
if (contextLookup == null)
sub.Print (tw, printer, contextLookup, context, printed);
else {
foreach (var ctx in contextLookup (sub.Entry))
sub.Print (tw, printer, contextLookup, ctx, printed);
}
}
base.PrintReferencedSubroutines (tw, subs, printer, contextLookup, context, printed);
}
protected override void PrintHandlers (TextWriter tw, BlockWithLabels<Label> block)
{
tw.Write (" Handlers: ");
foreach (Handler handler in ProtectingHandlerList (block).AsEnumerable ()) {
if (IsFaultOrFinally (handler))
tw.Write ("SR{0} ", this.FaultFinallySubroutines [handler].Id);
else
tw.Write ("{0} ", this.CatchFilterHeaders [handler].Index);
}
if (block != ExceptionExit)
tw.Write ("{0} ", ExceptionExit.Index);
tw.WriteLine ();
}
}
}