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,195 @@
//
// BlockBuilder.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.AST.Visitors;
using Mono.CodeContracts.Static.ControlFlow.Blocks;
using Mono.CodeContracts.Static.DataStructures;
namespace Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders {
class BlockBuilder<TLabel> : ILVisitorBase<TLabel, Dummy, Dummy, BlockWithLabels<TLabel>, bool>,
IAggregateVisitor<TLabel, BlockWithLabels<TLabel>, bool> {
private readonly SubroutineBuilder<TLabel> builder;
private BlockWithLabels<TLabel> current_block;
private BlockBuilder (SubroutineBuilder<TLabel> builder)
{
this.builder = builder;
}
private SubroutineBase<TLabel> CurrentSubroutine
{
get { return this.builder.CurrentSubroutine; }
}
#region IAggregateVisitor<Label,BlockWithLabels<Label>,bool> Members
public override bool Branch (TLabel pc, TLabel target, bool leavesExceptionBlock, BlockWithLabels<TLabel> currentBlock)
{
currentBlock.AddLabel (pc);
CurrentSubroutine.AddSuccessor (currentBlock, EdgeTag.Branch, CurrentSubroutine.GetTargetBlock (target));
return true;
}
public override bool BranchCond (TLabel pc, TLabel target, BranchOperator bop, Dummy value1, Dummy value2, BlockWithLabels<TLabel> currentBlock)
{
return HandleConditionalBranch (pc, target, true, currentBlock);
}
public override bool BranchFalse (TLabel pc, TLabel target, Dummy cond, BlockWithLabels<TLabel> currentBlock)
{
return HandleConditionalBranch (pc, target, false, currentBlock);
}
public override bool BranchTrue (TLabel pc, TLabel target, Dummy cond, BlockWithLabels<TLabel> currentBlock)
{
return HandleConditionalBranch (pc, target, true, currentBlock);
}
public override bool Throw (TLabel pc, Dummy exception, BlockWithLabels<TLabel> currentBlock)
{
currentBlock.AddLabel (pc);
return true;
}
public override bool Rethrow (TLabel pc, BlockWithLabels<TLabel> currentBlock)
{
currentBlock.AddLabel (pc);
return true;
}
public override bool EndFinally (TLabel pc, BlockWithLabels<TLabel> currentBlock)
{
currentBlock.AddLabel (pc);
CurrentSubroutine.AddSuccessor (currentBlock, EdgeTag.EndSubroutine, CurrentSubroutine.Exit);
return true;
}
public override bool Return (TLabel pc, Dummy source, BlockWithLabels<TLabel> currentBlock)
{
currentBlock.AddLabel (pc);
CurrentSubroutine.AddSuccessor (currentBlock, EdgeTag.Return, CurrentSubroutine.Exit);
CurrentSubroutine.AddReturnBlock (currentBlock);
return true;
}
public override bool Nop (TLabel pc, BlockWithLabels<TLabel> currentBlock)
{
return false;
}
public override bool LoadField (TLabel pc, Field field, Dummy dest, Dummy obj, BlockWithLabels<TLabel> data)
{
if (CurrentSubroutine.IsMethod) {
var methodInfo = (IMethodInfo) CurrentSubroutine;
Property property;
if (this.builder.MetaDataProvider.IsPropertyGetter (methodInfo.Method, out property))
this.builder.SubroutineFacade.AddReads (methodInfo.Method, field);
}
this.current_block.AddLabel (pc);
return false;
}
public override bool StoreField (TLabel pc, Field field, Dummy obj, Dummy value, BlockWithLabels<TLabel> data)
{
if (CurrentSubroutine.IsMethod) {
var methodInfo = (IMethodInfo) CurrentSubroutine;
Property property;
if (this.builder.MetaDataProvider.IsPropertySetter (methodInfo.Method, out property))
this.builder.SubroutineFacade.AddReads (methodInfo.Method, field);
}
this.current_block.AddLabel (pc);
return false;
}
public override bool EndOld (TLabel pc, TLabel matchingBegin, TypeNode type, Dummy dest, Dummy source, BlockWithLabels<TLabel> data)
{
this.current_block.AddLabel (pc);
CurrentSubroutine.AddSuccessor (this.current_block, EdgeTag.EndOld, CurrentSubroutine.Exit);
return false;
}
public bool Aggregate (TLabel pc, TLabel aggregateStart, bool canBeTargetOfBranch, BlockWithLabels<TLabel> data)
{
TraceAggregateSequentally (aggregateStart);
return false;
}
#endregion
public static BlockWithLabels<TLabel> BuildBlocks (TLabel entry, SubroutineBuilder<TLabel> subroutineBuilder)
{
var blockBuilder = new BlockBuilder<TLabel> (subroutineBuilder);
blockBuilder.TraceAggregateSequentally (entry);
if (blockBuilder.current_block == null)
return null;
SubroutineBase<TLabel> subroutine = blockBuilder.CurrentSubroutine;
subroutine.AddSuccessor (blockBuilder.current_block, EdgeTag.FallThroughReturn, subroutine.Exit);
subroutine.AddReturnBlock (blockBuilder.current_block);
return blockBuilder.current_block;
}
private void TraceAggregateSequentally (TLabel currentLabel)
{
do {
if (this.builder.IsBlockStart (currentLabel))
this.current_block = this.builder.RecordInformationForNewBlock (currentLabel, this.current_block);
if (this.builder.CodeProvider.Decode<BlockBuilder<TLabel>, BlockWithLabels<TLabel>, bool> (currentLabel, this, this.current_block))
this.current_block = null;
} while (this.builder.CodeProvider.Next (currentLabel, out currentLabel));
}
public override bool DefaultVisit (TLabel pc, BlockWithLabels<TLabel> currentBlock)
{
currentBlock.AddLabel (pc);
return false;
}
private bool HandleConditionalBranch (TLabel pc, TLabel target, bool isTrueBranch, BlockWithLabels<TLabel> currentBlock)
{
currentBlock.AddLabel (pc);
EdgeTag trueTag = isTrueBranch ? EdgeTag.True : EdgeTag.False;
EdgeTag falseTag = isTrueBranch ? EdgeTag.False : EdgeTag.True;
AssumeBlock<TLabel> trueBlock = CurrentSubroutine.NewAssumeBlock (pc, trueTag);
this.builder.RecordInformationSameAsOtherBlock (trueBlock, this.current_block);
CurrentSubroutine.AddSuccessor (currentBlock, trueTag, trueBlock);
CurrentSubroutine.AddSuccessor (trueBlock, EdgeTag.FallThrough, CurrentSubroutine.GetTargetBlock (target));
AssumeBlock<TLabel> falseBlock = CurrentSubroutine.NewAssumeBlock (pc, falseTag);
this.builder.RecordInformationSameAsOtherBlock (falseBlock, this.current_block);
CurrentSubroutine.AddSuccessor (currentBlock, falseTag, falseBlock);
this.current_block = falseBlock;
return false;
}
}
}

View File

@ -0,0 +1,164 @@
//
// BlockStartGatherer.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.AST.Visitors;
using Mono.CodeContracts.Static.DataStructures;
using Mono.CodeContracts.Static.Providers;
namespace Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders {
class BlockStartGatherer<Label> : ILVisitorBase<Label, Dummy, Dummy, Dummy, bool>,
IAggregateVisitor<Label, Dummy, bool> {
private readonly SubroutineBuilder<Label> parent;
public BlockStartGatherer (SubroutineBuilder<Label> parent)
{
this.parent = parent;
}
#region IAggregateVisitor<Label,Dummy,bool> Members
public override bool Branch (Label pc, Label target, bool leavesExceptionBlock, Dummy data)
{
AddTargetLabel (target);
return true;
}
public override bool BranchCond (Label pc, Label target, BranchOperator bop, Dummy value1, Dummy value2, Dummy data)
{
AddTargetLabel (target);
return true;
}
public override bool BranchFalse (Label pc, Label target, Dummy cond, Dummy data)
{
AddTargetLabel (target);
return true;
}
public override bool BranchTrue (Label pc, Label target, Dummy cond, Dummy data)
{
AddTargetLabel (target);
return true;
}
public override bool EndFinally (Label pc, Dummy data)
{
return true;
}
public override bool Return (Label pc, Dummy source, Dummy data)
{
return true;
}
public override bool Rethrow (Label pc, Dummy data)
{
return true;
}
public override bool Throw (Label pc, Dummy exception, Dummy data)
{
return true;
}
public override bool Call<TypeList, ArgList> (Label pc, Method method, bool virt, TypeList extraVarargs, Dummy dest, ArgList args, Dummy data)
{
return CallHelper (pc, method, false, virt);
}
public override bool ConstrainedCallvirt<TypeList, ArgList> (Label pc, Method method, TypeNode constraint, TypeList extraVarargs, Dummy dest, ArgList args, Dummy data)
{
return CallHelper (pc, method, false, true);
}
public override bool NewObj<ArgList> (Label pc, Method ctor, Dummy dest, ArgList args, Dummy data)
{
return CallHelper (pc, ctor, true, false);
}
public override bool BeginOld (Label pc, Label matchingEnd, Dummy data)
{
AddTargetLabel (pc);
this.parent.BeginOldHook (pc);
return false;
}
public override bool EndOld (Label pc, Label matchingBegin, TypeNode type, Dummy dest, Dummy source, Dummy data)
{
this.parent.EndOldHook (pc);
return true;
}
public bool Aggregate (Label pc, Label aggregateStart, bool canBeTargetOfBranch, Dummy data)
{
return TraceAggregateSequentally (aggregateStart);
}
#endregion
public override bool DefaultVisit (Label pc, Dummy data)
{
return false;
}
private bool CallHelper (Label pc, Method method, bool isNewObj, bool isVirtual)
{
AddBlockStart (pc);
if (isNewObj)
this.parent.AddNewObjSite (pc, method);
else
this.parent.AddMethodCallSite (pc, new Pair<Method, bool> (method, isVirtual));
return true;
}
public bool TraceAggregateSequentally (Label current)
{
bool isCurrentBranches;
bool isCurrentHasSuccessor;
do {
ICodeProvider<Label> codeProvider = this.parent.CodeProvider;
isCurrentBranches = codeProvider.Decode<BlockStartGatherer<Label>, Dummy, bool> (current, this, Dummy.Value);
isCurrentHasSuccessor = codeProvider.Next (current, out current);
if (isCurrentBranches && isCurrentHasSuccessor)
AddBlockStart (current);
} while (isCurrentHasSuccessor);
return isCurrentBranches;
}
private void AddBlockStart (Label target)
{
this.parent.AddBlockStart (target);
}
private void AddTargetLabel (Label target)
{
this.parent.AddTargetLabel (target);
}
}
}

View File

@ -0,0 +1,73 @@
//
// EnsuresFactory.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.DataStructures;
namespace Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders {
class EnsuresFactory : SubroutineFactory<Method, Pair<Method, IImmutableSet<Subroutine>>> {
public EnsuresFactory (SubroutineFacade subroutineFacade) : base (subroutineFacade)
{
}
#region Overrides of SubroutineFactory<Method,Pair<Method,IImmutableSet<Subroutine>>>
protected override Subroutine BuildNewSubroutine (Method method)
{
if (ContractProvider != null) {
IImmutableSet<Subroutine> inheritedEnsures = GetInheritedEnsures (method);
if (ContractProvider.HasEnsures (method))
return ContractProvider.AccessEnsures (method, this, new Pair<Method, IImmutableSet<Subroutine>> (method, inheritedEnsures));
if (inheritedEnsures.Count > 0) {
if (inheritedEnsures.Count > 1)
return new EnsuresSubroutine<Dummy> (this.SubroutineFacade, method, inheritedEnsures);
return inheritedEnsures.Any;
}
}
return new EnsuresSubroutine<Dummy> (this.SubroutineFacade, method, null);
}
private IImmutableSet<Subroutine> GetInheritedEnsures (Method method)
{
IImmutableSet<Subroutine> result = ImmutableSet<Subroutine>.Empty ();
if (MetaDataProvider.IsVirtual (method) && ContractProvider.CanInheritContracts (method)) {
foreach (Method implementedMethod in MetaDataProvider.OverridenAndImplementedMethods (method)) {
Subroutine subroutine = Get (MetaDataProvider.Unspecialized (implementedMethod));
if (subroutine != null)
result = result.Add (subroutine);
}
}
return result;
}
protected override Subroutine Factory<Label> (SimpleSubroutineBuilder<Label> builder, Label entry, Pair<Method, IImmutableSet<Subroutine>> data)
{
return new EnsuresSubroutine<Label> (this.SubroutineFacade, data.Key, builder, entry, data.Value);
}
#endregion
}
}

View File

@ -0,0 +1,83 @@
//
// RequiresFactory.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.DataStructures;
namespace Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders {
class RequiresFactory : SubroutineFactory<Method, Pair<Method, IImmutableSet<Subroutine>>> {
public RequiresFactory (SubroutineFacade subroutineFacade)
: base (subroutineFacade)
{
}
#region Overrides of SubroutineFactory<Method,Pair<Method,IImmutableSet<Subroutine>>>
protected override Subroutine BuildNewSubroutine (Method method)
{
if (ContractProvider != null) {
IImmutableSet<Subroutine> inheritedRequires = GetInheritedRequires (method);
if (ContractProvider.HasRequires (method))
return ContractProvider.AccessRequires (method, this, new Pair<Method, IImmutableSet<Subroutine>> (method, inheritedRequires));
if (inheritedRequires.Count > 0) {
if (inheritedRequires.Count == 1)
return inheritedRequires.Any;
return new RequiresSubroutine<Dummy> (this.SubroutineFacade, method, inheritedRequires);
}
}
return null;
}
private IImmutableSet<Subroutine> GetInheritedRequires (Method method)
{
IImmutableSet<Subroutine> result = ImmutableSet<Subroutine>.Empty ();
if (MetaDataProvider.IsVirtual (method) && ContractProvider.CanInheritContracts (method)) {
Method rootMethod;
if (MetaDataProvider.TryGetRootMethod (method, out rootMethod)) {
Subroutine sub = Get (MetaDataProvider.Unspecialized (method));
if (sub != null)
result = result.Add (sub);
}
foreach (Method implMethod in MetaDataProvider.ImplementedMethods (method)) {
Subroutine sub = Get (MetaDataProvider.Unspecialized (implMethod));
if (sub != null)
result = result.Add (sub);
}
}
return result;
}
protected override Subroutine Factory<Label> (SimpleSubroutineBuilder<Label> builder, Label entry, Pair<Method, IImmutableSet<Subroutine>> data)
{
return new RequiresSubroutine<Label> (this.SubroutineFacade, data.Key, builder, entry, data.Value);
}
#endregion
}
}

View File

@ -0,0 +1,100 @@
//
// SimpleSubroutineBuilder.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.ControlFlow.Blocks;
using Mono.CodeContracts.Static.Providers;
namespace Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders {
class SimpleSubroutineBuilder<TLabel> : SubroutineBuilder<TLabel> {
private readonly HashSet<TLabel> begin_old_start = new HashSet<TLabel> ();
private readonly HashSet<TLabel> end_old_start = new HashSet<TLabel> ();
private BlockWithLabels<TLabel> block_prior_to_old;
private OldValueSubroutine<TLabel> current_old_subroutine;
private SubroutineBase<TLabel> current_subroutine;
public SimpleSubroutineBuilder (ICodeProvider<TLabel> codeProvider,
SubroutineFacade subroutineFacade,
TLabel entry)
: base (codeProvider, subroutineFacade, entry)
{
Initialize (entry);
}
public override SubroutineBase<TLabel> CurrentSubroutine
{
get
{
if (this.current_old_subroutine != null)
return this.current_old_subroutine;
return this.current_subroutine;
}
}
public BlockWithLabels<TLabel> BuildBlocks (TLabel entry, SubroutineBase<TLabel> subroutine)
{
this.current_subroutine = subroutine;
return base.BuildBlocks (entry);
}
public override BlockWithLabels<TLabel> RecordInformationForNewBlock (TLabel currentLabel, BlockWithLabels<TLabel> previousBlock)
{
TLabel label;
if (previousBlock != null && previousBlock.TryGetLastLabel (out label) && this.end_old_start.Contains (label)) {
OldValueSubroutine<TLabel> oldValueSubroutine = this.current_old_subroutine;
oldValueSubroutine.Commit (previousBlock);
this.current_old_subroutine = null;
BlockWithLabels<TLabel> result = base.RecordInformationForNewBlock (currentLabel, this.block_prior_to_old);
CurrentSubroutine.AddEdgeSubroutine (this.block_prior_to_old, result, oldValueSubroutine, EdgeTag.Old);
return result;
}
if (!this.begin_old_start.Contains (currentLabel))
return base.RecordInformationForNewBlock (currentLabel, previousBlock);
this.current_old_subroutine = new OldValueSubroutine<TLabel> (this.SubroutineFacade,
((MethodContractSubroutine<TLabel>) this.current_subroutine).Method,
this, currentLabel);
this.block_prior_to_old = previousBlock;
BlockWithLabels<TLabel> newBlock = base.RecordInformationForNewBlock (currentLabel, null);
this.current_old_subroutine.RegisterBeginBlock (newBlock);
return newBlock;
}
public override void BeginOldHook (TLabel label)
{
this.begin_old_start.Add (label);
}
public override void EndOldHook (TLabel label)
{
this.end_old_start.Add (label);
}
}
}

View File

@ -0,0 +1,193 @@
//
// SubroutineBuilder.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.ControlFlow.Blocks;
using Mono.CodeContracts.Static.DataStructures;
using Mono.CodeContracts.Static.Providers;
namespace Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders {
abstract class SubroutineBuilder<Label> {
public readonly SubroutineFacade SubroutineFacade;
private readonly Dictionary<Label, Pair<Method, bool>> labels_for_call_sites = new Dictionary<Label, Pair<Method, bool>> ();
private readonly Dictionary<Label, Method> labels_for_new_obj_sites = new Dictionary<Label, Method> ();
private readonly HashSet<Label> labels_starting_blocks = new HashSet<Label> ();
private readonly HashSet<Label> target_labels = new HashSet<Label> ();
protected SubroutineBuilder (ICodeProvider<Label> codeProvider,
SubroutineFacade subroutineFacade,
Label entry)
{
this.SubroutineFacade = subroutineFacade;
CodeProvider = codeProvider;
AddTargetLabel (entry);
}
public ICodeProvider<Label> CodeProvider { get; private set; }
public abstract SubroutineBase<Label> CurrentSubroutine { get; }
public IMetaDataProvider MetaDataProvider
{
get { return this.SubroutineFacade.MetaDataProvider; }
}
protected IContractProvider ContractProvider
{
get { return this.SubroutineFacade.ContractProvider; }
}
public void AddTargetLabel (Label target)
{
AddBlockStart (target);
this.target_labels.Add (target);
}
public void AddBlockStart (Label target)
{
this.labels_starting_blocks.Add (target);
}
protected void Initialize (Label entry)
{
new BlockStartGatherer<Label> (this).TraceAggregateSequentally (entry);
}
public bool IsBlockStart (Label label)
{
return this.labels_starting_blocks.Contains (label);
}
public bool IsTargetLabel (Label label)
{
return this.target_labels.Contains (label);
}
public bool IsMethodCallSite (Label label, out Pair<Method, bool> methodVirtPair)
{
return this.labels_for_call_sites.TryGetValue (label, out methodVirtPair);
}
public bool IsNewObjSite (Label label, out Method constructor)
{
return this.labels_for_new_obj_sites.TryGetValue (label, out constructor);
}
protected BlockWithLabels<Label> BuildBlocks (Label entry)
{
return BlockBuilder<Label>.BuildBlocks (entry, this);
}
public virtual void RecordInformationSameAsOtherBlock (BlockWithLabels<Label> newBlock, BlockWithLabels<Label> currentBlock)
{
}
public virtual BlockWithLabels<Label> RecordInformationForNewBlock (Label currentLabel, BlockWithLabels<Label> previousBlock)
{
BlockWithLabels<Label> block = CurrentSubroutine.GetBlock (currentLabel);
if (previousBlock != null) {
BlockWithLabels<Label> newBlock = block;
BlockWithLabels<Label> prevBlock = previousBlock;
if (block is MethodCallBlock<Label> && previousBlock is MethodCallBlock<Label>) {
BlockWithLabels<Label> ab = CurrentSubroutine.NewBlock ();
RecordInformationSameAsOtherBlock (ab, previousBlock);
newBlock = ab;
prevBlock = ab;
CurrentSubroutine.AddSuccessor (previousBlock, EdgeTag.FallThrough, ab);
CurrentSubroutine.AddSuccessor (ab, EdgeTag.FallThrough, block);
} else
CurrentSubroutine.AddSuccessor (previousBlock, EdgeTag.FallThrough, block);
InsertPostConditionEdges (previousBlock, newBlock);
InsertPreConditionEdges (prevBlock, block);
}
return block;
}
protected void InsertPreConditionEdges (BlockWithLabels<Label> previousBlock, BlockWithLabels<Label> newBlock)
{
var methodCallBlock = newBlock as MethodCallBlock<Label>;
if (methodCallBlock == null || CurrentSubroutine.IsContract || CurrentSubroutine.IsOldValue)
return;
if (CurrentSubroutine.IsMethod) {
var methodInfo = CurrentSubroutine as IMethodInfo;
Property property;
if (methodInfo != null && MetaDataProvider.IsConstructor (methodInfo.Method)
&& MetaDataProvider.IsPropertySetter (methodCallBlock.CalledMethod, out property)
&& MetaDataProvider.IsAutoPropertyMember (methodCallBlock.CalledMethod))
return;
}
EdgeTag callTag = methodCallBlock.IsNewObj ? EdgeTag.BeforeNewObj : EdgeTag.BeforeCall;
Subroutine requires = this.SubroutineFacade.GetRequires (methodCallBlock.CalledMethod);
CurrentSubroutine.AddEdgeSubroutine (previousBlock, newBlock, requires, callTag);
}
protected void InsertPostConditionEdges (BlockWithLabels<Label> previousBlock, BlockWithLabels<Label> newBlock)
{
var methodCallBlock = previousBlock as MethodCallBlock<Label>;
if (methodCallBlock == null)
return;
if (CurrentSubroutine.IsMethod) {
var methodInfo = CurrentSubroutine as IMethodInfo;
Property property;
if (methodInfo != null && MetaDataProvider.IsConstructor (methodInfo.Method)
&& MetaDataProvider.IsPropertyGetter (methodCallBlock.CalledMethod, out property)
&& MetaDataProvider.IsAutoPropertyMember (methodCallBlock.CalledMethod))
return;
}
EdgeTag callTag = methodCallBlock.IsNewObj ? EdgeTag.AfterNewObj : EdgeTag.AfterCall;
Subroutine ensures = this.SubroutineFacade.GetEnsures (methodCallBlock.CalledMethod);
CurrentSubroutine.AddEdgeSubroutine (previousBlock, newBlock, ensures, callTag);
}
public virtual void BeginOldHook (Label label)
{
}
public virtual void EndOldHook (Label label)
{
}
public void AddMethodCallSite (Label pc, Pair<Method, bool> methodVirtPair)
{
this.labels_for_call_sites [pc] = methodVirtPair;
}
public void AddNewObjSite (Label pc, Method method)
{
this.labels_for_new_obj_sites [pc] = method;
}
}
}

View File

@ -0,0 +1,76 @@
//
// SubroutineFactory.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.Visitors;
using Mono.CodeContracts.Static.Providers;
namespace Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders {
abstract class SubroutineFactory<Key, Data> : ICodeConsumer<Data, Subroutine> {
protected readonly SubroutineFacade SubroutineFacade;
private readonly Dictionary<Key, Subroutine> cache = new Dictionary<Key, Subroutine> ();
protected SubroutineFactory (SubroutineFacade subroutineFacade)
{
this.SubroutineFacade = subroutineFacade;
}
protected IContractProvider ContractProvider
{
get { return this.SubroutineFacade.ContractProvider; }
}
protected IMetaDataProvider MetaDataProvider
{
get { return this.SubroutineFacade.MetaDataProvider; }
}
#region ICodeConsumer<Data,Subroutine> Members
public Subroutine Accept<Label> (ICodeProvider<Label> codeProvider, Label entryPoint, Data data)
{
return Factory (new SimpleSubroutineBuilder<Label> (codeProvider, this.SubroutineFacade, entryPoint), entryPoint, data);
}
#endregion
public Subroutine Get (Key key)
{
if (this.cache.ContainsKey (key))
return this.cache [key];
Subroutine sub = BuildNewSubroutine (key);
this.cache.Add (key, sub);
if (sub != null)
sub.Initialize ();
return sub;
}
protected abstract Subroutine BuildNewSubroutine (Key key);
protected abstract Subroutine Factory<Label> (SimpleSubroutineBuilder<Label> builder, Label entry, Data data);
}
}

View File

@ -0,0 +1,221 @@
//
// SubroutineWithHandlersBuilder.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.DataStructures;
using Mono.CodeContracts.Static.Providers;
namespace Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders {
class SubroutineWithHandlersBuilder<Label, Handler> : SubroutineBuilder<Label> {
private readonly Dictionary<Label, Handler> handler_starting_at = new Dictionary<Label, Handler> ();
private readonly Method method;
private readonly Dictionary<Label, Queue<Handler>> subroutine_handler_end_list = new Dictionary<Label, Queue<Handler>> ();
private readonly Dictionary<Label, Queue<Handler>> try_end_list = new Dictionary<Label, Queue<Handler>> ();
private readonly Dictionary<Label, Stack<Handler>> try_start_list = new Dictionary<Label, Stack<Handler>> ();
private Sequence<SubroutineWithHandlers<Label, Handler>> subroutine_stack;
public SubroutineWithHandlersBuilder (IMethodCodeProvider<Label, Handler> codeProvider,
SubroutineFacade subroutineFacade,
Method method,
Label entry)
: base (codeProvider, subroutineFacade, entry)
{
this.method = method;
ComputeTryBlockStartAndEndInfo (this.method);
Initialize (entry);
}
private new IMethodCodeProvider<Label, Handler> CodeProvider
{
get { return (IMethodCodeProvider<Label, Handler>) base.CodeProvider; }
}
protected SubroutineWithHandlers<Label, Handler> CurrentSubroutineWithHandlers
{
get { return this.subroutine_stack.Head; }
}
private Sequence<Handler> CurrentProtectingHanlders
{
get { return CurrentSubroutineWithHandlers.CurrentProtectingHandlers; }
set { CurrentSubroutineWithHandlers.CurrentProtectingHandlers = value; }
}
public override SubroutineBase<Label> CurrentSubroutine
{
get { return this.subroutine_stack.Head; }
}
private void ComputeTryBlockStartAndEndInfo (Method method)
{
foreach (Handler handler in CodeProvider.GetTryBlocks (method)) {
if (CodeProvider.IsFilterHandler (handler))
AddTargetLabel (CodeProvider.FilterExpressionStart (handler));
AddTargetLabel (CodeProvider.HandlerStart (handler));
AddTargetLabel (CodeProvider.HandlerEnd (handler));
AddTryStart (handler);
AddTryEnd (handler);
AddHandlerEnd (handler);
this.handler_starting_at.Add (CodeProvider.HandlerStart (handler), handler);
}
}
private void AddHandlerEnd (Handler handler)
{
if (!IsFaultOrFinally (handler))
return;
Label handlerEnd = CodeProvider.HandlerEnd (handler);
Queue<Handler> queue;
this.subroutine_handler_end_list.TryGetValue (handlerEnd, out queue);
if (queue == null) {
queue = new Queue<Handler> ();
this.subroutine_handler_end_list [handlerEnd] = queue;
}
queue.Enqueue (handler);
AddTargetLabel (handlerEnd);
}
private void AddTryEnd (Handler handler)
{
Label tryEnd = CodeProvider.TryEnd (handler);
Queue<Handler> queue;
this.try_end_list.TryGetValue (tryEnd, out queue);
if (queue == null) {
queue = new Queue<Handler> ();
this.try_end_list [tryEnd] = queue;
}
queue.Enqueue (handler);
AddTargetLabel (tryEnd);
}
private void AddTryStart (Handler handler)
{
Label tryStart = CodeProvider.TryStart (handler);
Stack<Handler> stack;
this.try_start_list.TryGetValue (tryStart, out stack);
if (stack == null) {
stack = new Stack<Handler> ();
this.try_start_list [tryStart] = stack;
}
stack.Push (handler);
AddTargetLabel (tryStart);
}
public CFGBlock BuildBlocks (Label entry, SubroutineWithHandlers<Label, Handler> subroutine)
{
this.subroutine_stack = Sequence<SubroutineWithHandlers<Label, Handler>>.Cons (subroutine, null);
return base.BuildBlocks (entry);
}
public override void RecordInformationSameAsOtherBlock (BlockWithLabels<Label> newBlock, BlockWithLabels<Label> currentBlock)
{
Sequence<Handler> list;
if (!CurrentSubroutineWithHandlers.ProtectingHandlers.TryGetValue (currentBlock, out list))
return;
CurrentSubroutineWithHandlers.ProtectingHandlers.Add (newBlock, list);
}
public override BlockWithLabels<Label> RecordInformationForNewBlock (Label currentLabel, BlockWithLabels<Label> previousBlock)
{
BlockWithLabels<Label> result = null;
Queue<Handler> handlerEnd = GetHandlerEnd (currentLabel);
if (handlerEnd != null) {
foreach (Handler handler in handlerEnd) {
this.subroutine_stack.Head.Commit ();
this.subroutine_stack = this.subroutine_stack.Tail;
previousBlock = null;
}
}
Queue<Handler> tryEnd = GetTryEnd (currentLabel);
if (tryEnd != null) {
foreach (Handler handler in tryEnd) {
if (!Equals (handler, CurrentProtectingHanlders.Head))
throw new InvalidOperationException ("wrong handler");
CurrentProtectingHanlders = CurrentProtectingHanlders.Tail;
}
}
Handler handler1;
if (IsHandlerStart (currentLabel, out handler1)) {
if (IsFaultOrFinally (handler1)) {
SubroutineWithHandlers<Label, Handler> sub = !CodeProvider.IsFaultHandler (handler1)
? new FinallySubroutine<Label, Handler> (this.SubroutineFacade, currentLabel, this)
: (FaultFinallySubroutineBase<Label, Handler>) new FaultSubroutine<Label, Handler> (this.SubroutineFacade, currentLabel, this);
CurrentSubroutineWithHandlers.FaultFinallySubroutines.Add (handler1, sub);
this.subroutine_stack = this.subroutine_stack.Cons (sub);
previousBlock = null;
} else
result = CurrentSubroutineWithHandlers.CreateCatchFilterHeader (handler1, currentLabel);
}
if (result == null)
result = base.RecordInformationForNewBlock (currentLabel, previousBlock);
Stack<Handler> tryStart = GetTryStart (currentLabel);
if (tryStart != null) {
foreach (Handler handler in tryStart)
CurrentProtectingHanlders = CurrentProtectingHanlders.Cons (handler);
}
CurrentSubroutineWithHandlers.ProtectingHandlers.Add (result, CurrentProtectingHanlders);
return result;
}
private bool IsFaultOrFinally (Handler handler)
{
return CodeProvider.IsFaultHandler (handler) || CodeProvider.IsFinallyHandler (handler);
}
private bool IsHandlerStart (Label currentLabel, out Handler handler)
{
return this.handler_starting_at.TryGetValue (currentLabel, out handler);
}
private Stack<Handler> GetTryStart (Label currentLabel)
{
Stack<Handler> queue;
this.try_start_list.TryGetValue (currentLabel, out queue);
return queue;
}
private Queue<Handler> GetTryEnd (Label currentLabel)
{
Queue<Handler> queue;
this.try_end_list.TryGetValue (currentLabel, out queue);
return queue;
}
private Queue<Handler> GetHandlerEnd (Label currentLabel)
{
Queue<Handler> queue;
this.subroutine_handler_end_list.TryGetValue (currentLabel, out queue);
return queue;
}
}
}