Browse Source

Redesign of UsingInstruction.

pull/877/head
Siegfried Pammer 8 years ago
parent
commit
d1a514b451
  1. 54
      ICSharpCode.Decompiler/IL/Instructions.cs
  2. 2
      ICSharpCode.Decompiler/IL/Instructions.tt
  3. 14
      ICSharpCode.Decompiler/IL/Instructions/LockInstruction.cs
  4. 16
      ICSharpCode.Decompiler/IL/Transforms/UsingTransform.cs

54
ICSharpCode.Decompiler/IL/Instructions.cs

@ -1701,13 +1701,53 @@ namespace ICSharpCode.Decompiler.IL @@ -1701,13 +1701,53 @@ namespace ICSharpCode.Decompiler.IL
namespace ICSharpCode.Decompiler.IL
{
/// <summary>Using statement</summary>
public sealed partial class UsingInstruction : ILInstruction
public sealed partial class UsingInstruction : ILInstruction, IStoreInstruction
{
public UsingInstruction(ILInstruction resourceExpression, ILInstruction body) : base(OpCode.UsingInstruction)
public UsingInstruction(ILVariable variable, ILInstruction resourceExpression, ILInstruction body) : base(OpCode.UsingInstruction)
{
Debug.Assert(variable != null);
this.variable = variable;
this.ResourceExpression = resourceExpression;
this.Body = body;
}
ILVariable variable;
public ILVariable Variable {
get { return variable; }
set {
Debug.Assert(value != null);
if (IsConnected)
variable.RemoveStoreInstruction(this);
variable = value;
if (IsConnected)
variable.AddStoreInstruction(this);
}
}
public int IndexInStoreInstructionList { get; set; } = -1;
int IInstructionWithVariableOperand.IndexInVariableInstructionMapping {
get { return ((IStoreInstruction)this).IndexInStoreInstructionList; }
set { ((IStoreInstruction)this).IndexInStoreInstructionList = value; }
}
protected override void Connected()
{
base.Connected();
variable.AddStoreInstruction(this);
}
protected override void Disconnected()
{
variable.RemoveStoreInstruction(this);
base.Disconnected();
}
internal override void CheckInvariant(ILPhase phase)
{
base.CheckInvariant(phase);
Debug.Assert(phase <= ILPhase.InILReader || this.IsDescendantOf(variable.Function));
Debug.Assert(phase <= ILPhase.InILReader || variable.Function.Variables[variable.IndexInFunction] == variable);
}
public static readonly SlotInfo ResourceExpressionSlot = new SlotInfo("ResourceExpression", canInlineInto: true);
ILInstruction resourceExpression;
public ILInstruction ResourceExpression {
@ -1775,11 +1815,11 @@ namespace ICSharpCode.Decompiler.IL @@ -1775,11 +1815,11 @@ namespace ICSharpCode.Decompiler.IL
public override StackType ResultType { get { return StackType.Void; } }
protected override InstructionFlags ComputeFlags()
{
return resourceExpression.Flags | body.Flags | InstructionFlags.ControlFlow | InstructionFlags.SideEffect;
return InstructionFlags.MayWriteLocals | resourceExpression.Flags | body.Flags | InstructionFlags.ControlFlow | InstructionFlags.SideEffect;
}
public override InstructionFlags DirectFlags {
get {
return InstructionFlags.ControlFlow | InstructionFlags.SideEffect;
return InstructionFlags.MayWriteLocals | InstructionFlags.ControlFlow | InstructionFlags.SideEffect;
}
}
public override void AcceptVisitor(ILVisitor visitor)
@ -1797,7 +1837,7 @@ namespace ICSharpCode.Decompiler.IL @@ -1797,7 +1837,7 @@ namespace ICSharpCode.Decompiler.IL
protected internal override bool PerformMatch(ILInstruction other, ref Patterns.Match match)
{
var o = other as UsingInstruction;
return o != null && this.resourceExpression.PerformMatch(o.resourceExpression, ref match) && this.body.PerformMatch(o.body, ref match);
return o != null && variable == o.variable && this.resourceExpression.PerformMatch(o.resourceExpression, ref match) && this.body.PerformMatch(o.body, ref match);
}
}
}
@ -5337,14 +5377,16 @@ namespace ICSharpCode.Decompiler.IL @@ -5337,14 +5377,16 @@ namespace ICSharpCode.Decompiler.IL
body = default(ILInstruction);
return false;
}
public bool MatchUsingInstruction(out ILInstruction resourceExpression, out ILInstruction body)
public bool MatchUsingInstruction(out ILVariable variable, out ILInstruction resourceExpression, out ILInstruction body)
{
var inst = this as UsingInstruction;
if (inst != null) {
variable = inst.Variable;
resourceExpression = inst.ResourceExpression;
body = inst.Body;
return true;
}
variable = default(ILVariable);
resourceExpression = default(ILInstruction);
body = default(ILInstruction);
return false;

2
ICSharpCode.Decompiler/IL/Instructions.tt

@ -119,7 +119,7 @@ @@ -119,7 +119,7 @@
new ArgumentInfo("onExpression"),
new ChildInfo("body")
}), CustomWriteTo, ControlFlow, SideEffect, ResultType("Void")),
new OpCode("using", "Using statement", CustomClassName("UsingInstruction"),
new OpCode("using", "Using statement", CustomClassName("UsingInstruction"), HasVariableOperand("Store"),
CustomChildren(new [] {
new ArgumentInfo("resourceExpression"),
new ChildInfo("body")

14
ICSharpCode.Decompiler/IL/Instructions/LockInstruction.cs

@ -39,11 +39,25 @@ namespace ICSharpCode.Decompiler.IL @@ -39,11 +39,25 @@ namespace ICSharpCode.Decompiler.IL
}
}
/// <summary>
/// IL using instruction.
/// Equivalent to:
/// <code>
/// stloc v(resourceExpression)
/// try {
/// body
/// } finally {
/// v?.Dispose();
/// }
/// </code>
/// </summary>
partial class UsingInstruction
{
public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
{
output.Write("using (");
Variable.WriteTo(output);
output.Write(" = ");
ResourceExpression.WriteTo(output, options);
output.WriteLine(") {");
output.Indent();

16
ICSharpCode.Decompiler/IL/Transforms/UsingTransform.cs

@ -76,23 +76,9 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -76,23 +76,9 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return false;
if (!(body.FinallyBlock is BlockContainer container) || !MatchDisposeBlock(container, storeInst.Variable, storeInst.Value.MatchLdNull()))
return false;
ILInstruction resourceExpression;
if (storeInst.Variable.Type.IsReferenceType != false) {
if (storeInst.Variable.IsSingleDefinition && storeInst.Variable.LoadCount <= 2) {
resourceExpression = storeInst.Value;
} else {
resourceExpression = storeInst;
}
} else {
if (storeInst.Variable.StoreCount == 1 && storeInst.Variable.LoadCount == 0 && storeInst.Variable.AddressCount == 1) {
resourceExpression = storeInst.Value;
} else {
resourceExpression = storeInst;
}
}
context.Step("UsingTransform", body);
block.Instructions.RemoveAt(i);
block.Instructions[i - 1] = new UsingInstruction(resourceExpression, body.TryBlock);
block.Instructions[i - 1] = new UsingInstruction(storeInst.Variable, storeInst.Value, body.TryBlock);
return true;
}

Loading…
Cancel
Save