diff --git a/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj b/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj
index e3e43be69..51d24fc07 100644
--- a/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj
+++ b/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj
@@ -42,13 +42,13 @@
-
-
+
+
-
-
+
+
diff --git a/ICSharpCode.Decompiler/IL/ILInstructionExtensions.cs b/ICSharpCode.Decompiler/IL/ILInstructionExtensions.cs
index 222d82daa..32310150c 100644
--- a/ICSharpCode.Decompiler/IL/ILInstructionExtensions.cs
+++ b/ICSharpCode.Decompiler/IL/ILInstructionExtensions.cs
@@ -18,5 +18,14 @@ namespace ICSharpCode.Decompiler.IL
target.AddILRange(range);
return target;
}
+
+ public static ILInstruction GetNextSibling(this ILInstruction instruction)
+ {
+ if (instruction?.Parent == null)
+ return null;
+ if (instruction.ChildIndex + 1 >= instruction.Parent.Children.Count)
+ return null;
+ return instruction.Parent.Children[instruction.ChildIndex + 1];
+ }
}
}
diff --git a/ICSharpCode.Decompiler/IL/Instructions/Block.cs b/ICSharpCode.Decompiler/IL/Instructions/Block.cs
index ab04f550e..dcaa0b580 100644
--- a/ICSharpCode.Decompiler/IL/Instructions/Block.cs
+++ b/ICSharpCode.Decompiler/IL/Instructions/Block.cs
@@ -43,11 +43,11 @@ namespace ICSharpCode.Decompiler.IL
{
public static readonly SlotInfo InstructionSlot = new SlotInfo("Instruction", isCollection: true);
public static readonly SlotInfo FinalInstructionSlot = new SlotInfo("FinalInstruction");
-
+
public readonly BlockKind Kind;
public readonly InstructionCollection Instructions;
ILInstruction finalInstruction;
-
+
///
/// For blocks in a block container, this field holds
/// the number of incoming control flow edges to this block.
@@ -77,21 +77,21 @@ namespace ICSharpCode.Decompiler.IL
SetChildInstruction(ref finalInstruction, value, Instructions.Count);
}
}
-
+
protected internal override void InstructionCollectionUpdateComplete()
{
base.InstructionCollectionUpdateComplete();
if (finalInstruction.Parent == this)
finalInstruction.ChildIndex = Instructions.Count;
}
-
+
public Block(BlockKind kind = BlockKind.ControlFlow) : base(OpCode.Block)
{
this.Kind = kind;
this.Instructions = new InstructionCollection(this, 0);
this.FinalInstruction = new Nop();
}
-
+
public override ILInstruction Clone()
{
Block clone = new Block(Kind);
@@ -100,7 +100,7 @@ namespace ICSharpCode.Decompiler.IL
clone.FinalInstruction = this.FinalInstruction.Clone();
return clone;
}
-
+
internal override void CheckInvariant(ILPhase phase)
{
base.CheckInvariant(phase);
@@ -133,18 +133,17 @@ namespace ICSharpCode.Decompiler.IL
break;
}
}
-
+
public override StackType ResultType {
get {
return finalInstruction.ResultType;
}
}
-
+
///
/// Gets the name of this block.
///
- public string Label
- {
+ public string Label {
get { return Disassembler.DisassemblerHelpers.OffsetToString(this.StartILOffset); }
}
@@ -179,19 +178,19 @@ namespace ICSharpCode.Decompiler.IL
output.Write("}");
output.MarkFoldEnd();
}
-
+
protected override int GetChildCount()
{
return Instructions.Count + 1;
}
-
+
protected override ILInstruction GetChild(int index)
{
if (index == Instructions.Count)
return finalInstruction;
return Instructions[index];
}
-
+
protected override void SetChild(int index, ILInstruction value)
{
if (index == Instructions.Count)
@@ -199,7 +198,7 @@ namespace ICSharpCode.Decompiler.IL
else
Instructions[index] = value;
}
-
+
protected override SlotInfo GetChildSlot(int index)
{
if (index == Instructions.Count)
@@ -207,7 +206,7 @@ namespace ICSharpCode.Decompiler.IL
else
return InstructionSlot;
}
-
+
protected override InstructionFlags ComputeFlags()
{
var flags = InstructionFlags.None;
@@ -217,7 +216,7 @@ namespace ICSharpCode.Decompiler.IL
flags |= FinalInstruction.Flags;
return flags;
}
-
+
public override InstructionFlags DirectFlags {
get {
return InstructionFlags.None;
@@ -280,6 +279,21 @@ namespace ICSharpCode.Decompiler.IL
return inst;
}
+ ///
+ /// Gets the closest parent Block.
+ /// Returns null, if the instruction is not a descendant of a Block.
+ ///
+ public static Block FindClosestBlock(ILInstruction inst)
+ {
+ var curr = inst;
+ while (curr != null) {
+ if (curr is Block)
+ return (Block)curr;
+ curr = curr.Parent;
+ }
+ return null;
+ }
+
public bool MatchInlineAssignBlock(out CallInstruction call, out ILInstruction value)
{
call = null;
diff --git a/ICSharpCode.Decompiler/IL/Transforms/ExpressionTransforms.cs b/ICSharpCode.Decompiler/IL/Transforms/ExpressionTransforms.cs
index 05f7d2f5f..0a19dd86a 100644
--- a/ICSharpCode.Decompiler/IL/Transforms/ExpressionTransforms.cs
+++ b/ICSharpCode.Decompiler/IL/Transforms/ExpressionTransforms.cs
@@ -271,6 +271,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
}
Block block;
if (TransformSpanTCtorContainingStackAlloc(inst, out ILInstruction locallocSpan)) {
+ context.Step("new Span(stackalloc) -> stackalloc Span", inst);
inst.ReplaceWith(locallocSpan);
block = null;
ILInstruction stmt = locallocSpan;
@@ -281,7 +282,9 @@ namespace ICSharpCode.Decompiler.IL.Transforms
}
stmt = stmt.Parent;
}
- //ILInlining.InlineIfPossible(block, stmt.ChildIndex - 1, context);
+ // Special case to eliminate extra store
+ if (stmt.GetNextSibling() is StLoc)
+ ILInlining.InlineIfPossible(block, stmt.ChildIndex, context);
return;
}
if (TransformArrayInitializers.TransformSpanTArrayInitialization(inst, context, out block)) {
diff --git a/ILSpy.BamlDecompiler.Tests/ILSpy.BamlDecompiler.Tests.csproj b/ILSpy.BamlDecompiler.Tests/ILSpy.BamlDecompiler.Tests.csproj
index 0f4829272..1958ed447 100644
--- a/ILSpy.BamlDecompiler.Tests/ILSpy.BamlDecompiler.Tests.csproj
+++ b/ILSpy.BamlDecompiler.Tests/ILSpy.BamlDecompiler.Tests.csproj
@@ -31,7 +31,7 @@
-
+
diff --git a/ILSpy.BamlDecompiler.Tests/app.config b/ILSpy.BamlDecompiler.Tests/app.config
index 5095b0e47..8eaf7eb82 100644
--- a/ILSpy.BamlDecompiler.Tests/app.config
+++ b/ILSpy.BamlDecompiler.Tests/app.config
@@ -7,8 +7,14 @@
+
+
+
+
+
+
-
+