diff --git a/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs b/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs
index 5f762dd2e..2109bad73 100644
--- a/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs
+++ b/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs
@@ -1063,25 +1063,25 @@ namespace ICSharpCode.Decompiler.CSharp
return Assignment(result, value).WithILInstruction(inst);
}
- protected internal override TranslatedExpression VisitLdFld(LdFld inst)
- {
- return ConvertField(inst.Field, inst.Target).WithILInstruction(inst);
- }
-
- protected internal override TranslatedExpression VisitStFld(StFld inst)
- {
- return Assignment(ConvertField(inst.Field, inst.Target).WithoutILInstruction(), Translate(inst.Value)).WithILInstruction(inst);
- }
-
- protected internal override TranslatedExpression VisitLdsFld(LdsFld inst)
- {
- return ConvertField(inst.Field).WithILInstruction(inst);
- }
-
- protected internal override TranslatedExpression VisitStsFld(StsFld inst)
- {
- return Assignment(ConvertField(inst.Field).WithoutILInstruction(), Translate(inst.Value)).WithILInstruction(inst);
- }
+// protected internal override TranslatedExpression VisitLdFld(LdFld inst)
+// {
+// return ConvertField(inst.Field, inst.Target).WithILInstruction(inst);
+// }
+//
+// protected internal override TranslatedExpression VisitStFld(StFld inst)
+// {
+// return Assignment(ConvertField(inst.Field, inst.Target).WithoutILInstruction(), Translate(inst.Value)).WithILInstruction(inst);
+// }
+//
+// protected internal override TranslatedExpression VisitLdsFld(LdsFld inst)
+// {
+// return ConvertField(inst.Field).WithILInstruction(inst);
+// }
+//
+// protected internal override TranslatedExpression VisitStsFld(StsFld inst)
+// {
+// return Assignment(ConvertField(inst.Field).WithoutILInstruction(), Translate(inst.Value)).WithILInstruction(inst);
+// }
protected internal override TranslatedExpression VisitLdLen(LdLen inst)
{
diff --git a/ICSharpCode.Decompiler/IL/ILReader.cs b/ICSharpCode.Decompiler/IL/ILReader.cs
index cfa1a8578..e4bf3d963 100644
--- a/ICSharpCode.Decompiler/IL/ILReader.cs
+++ b/ICSharpCode.Decompiler/IL/ILReader.cs
@@ -720,26 +720,32 @@ namespace ICSharpCode.Decompiler.IL
case ILOpCode.Ldelema:
return Push(new LdElema(indices: Pop(), array: Pop(), type: ReadAndDecodeTypeReference()));
case ILOpCode.Ldfld:
- return Push(new LdFld(Pop(), ReadAndDecodeFieldReference()));
+ {
+ var field = ReadAndDecodeFieldReference();
+ return Push(new LdObj(new LdFlda(Pop(), field) { DelayExceptions = true }, field.Type));
+ }
case ILOpCode.Ldflda:
return Push(new LdFlda(Pop(), ReadAndDecodeFieldReference()));
case ILOpCode.Stfld:
{
var field = ReadAndDecodeFieldReference();
- return new StFld(value: Pop(field.Type.GetStackType()), target: Pop(), field: field);
+ return new StObj(value: Pop(field.Type.GetStackType()), target: new LdFlda(Pop(), field) { DelayExceptions = true }, type: field.Type);
}
case ILOpCode.Ldlen:
return Push(new LdLen(StackType.I, Pop()));
case ILOpCode.Ldobj:
return Push(new LdObj(PopPointer(), ReadAndDecodeTypeReference()));
case ILOpCode.Ldsfld:
- return Push(new LdsFld(ReadAndDecodeFieldReference()));
+ {
+ var field = ReadAndDecodeFieldReference();
+ return Push(new LdObj(new LdsFlda(field), field.Type));
+ }
case ILOpCode.Ldsflda:
return Push(new LdsFlda(ReadAndDecodeFieldReference()));
case ILOpCode.Stsfld:
{
var field = ReadAndDecodeFieldReference();
- return new StsFld(Pop(field.Type.GetStackType()), field);
+ return new StObj(value: Pop(field.Type.GetStackType()), target: new LdsFlda(field), type: field.Type);
}
case ILOpCode.Ldtoken:
return Push(LdToken(ReadAndDecodeMetadataToken()));
diff --git a/ICSharpCode.Decompiler/IL/Instructions.cs b/ICSharpCode.Decompiler/IL/Instructions.cs
index c7e8cb131..23715522b 100644
--- a/ICSharpCode.Decompiler/IL/Instructions.cs
+++ b/ICSharpCode.Decompiler/IL/Instructions.cs
@@ -129,18 +129,10 @@ namespace ICSharpCode.Decompiler.IL
Shl,
/// Shift right
Shr,
- /// Load instance field
- LdFld,
/// Load address of instance field
LdFlda,
- /// Store value to instance field
- StFld,
- /// Load static field
- LdsFld,
/// Load static field address
LdsFlda,
- /// Store value to static field
- StsFld,
/// Casts an object to a class.
CastClass,
/// Test if object is instance of class or interface.
@@ -2027,101 +2019,6 @@ namespace ICSharpCode.Decompiler.IL
}
}
- /// Load instance field
- public sealed partial class LdFld : ILInstruction, ISupportsVolatilePrefix, ISupportsUnalignedPrefix, IInstructionWithFieldOperand
- {
- public LdFld(ILInstruction target, IField field) : base(OpCode.LdFld)
- {
- this.Target = target;
- this.field = field;
- }
- public static readonly SlotInfo TargetSlot = new SlotInfo("Target", canInlineInto: true);
- ILInstruction target;
- public ILInstruction Target {
- get { return this.target; }
- set {
- ValidateChild(value);
- SetChildInstruction(ref this.target, value, 0);
- }
- }
- protected sealed override int GetChildCount()
- {
- return 1;
- }
- protected sealed override ILInstruction GetChild(int index)
- {
- switch (index) {
- case 0:
- return this.target;
- default:
- throw new IndexOutOfRangeException();
- }
- }
- protected sealed override void SetChild(int index, ILInstruction value)
- {
- switch (index) {
- case 0:
- this.Target = value;
- break;
- default:
- throw new IndexOutOfRangeException();
- }
- }
- protected sealed override SlotInfo GetChildSlot(int index)
- {
- switch (index) {
- case 0:
- return TargetSlot;
- default:
- throw new IndexOutOfRangeException();
- }
- }
- public sealed override ILInstruction Clone()
- {
- var clone = (LdFld)ShallowClone();
- clone.Target = this.target.Clone();
- return clone;
- }
- /// Gets/Sets whether the memory access is volatile.
- public bool IsVolatile { get; set; }
- /// Returns the alignment specified by the 'unaligned' prefix; or 0 if there was no 'unaligned' prefix.
- public byte UnalignedPrefix { get; set; }
- readonly IField field;
- /// Returns the field operand.
- public IField Field { get { return field; } }
- public override StackType ResultType { get { return field.Type.GetStackType(); } }
- protected override InstructionFlags ComputeFlags()
- {
- return target.Flags | InstructionFlags.SideEffect | InstructionFlags.MayThrow;
- }
- public override InstructionFlags DirectFlags {
- get {
- return InstructionFlags.SideEffect | InstructionFlags.MayThrow;
- }
- }
- public override void WriteTo(ITextOutput output)
- {
- if (IsVolatile)
- output.Write("volatile.");
- if (UnalignedPrefix > 0)
- output.Write("unaligned(" + UnalignedPrefix + ").");
- output.Write(OpCode);
- output.Write(' ');
- Disassembler.DisassemblerHelpers.WriteOperand(output, field);
- output.Write('(');
- this.target.WriteTo(output);
- output.Write(')');
- }
- public override void AcceptVisitor(ILVisitor visitor)
- {
- visitor.VisitLdFld(this);
- }
- public override T AcceptVisitor(ILVisitor visitor)
- {
- return visitor.VisitLdFld(this);
- }
- }
-
/// Load address of instance field
public sealed partial class LdFlda : ILInstruction, IInstructionWithFieldOperand
{
@@ -2210,165 +2107,6 @@ namespace ICSharpCode.Decompiler.IL
}
}
- /// Store value to instance field
- public sealed partial class StFld : ILInstruction, ISupportsVolatilePrefix, ISupportsUnalignedPrefix, IInstructionWithFieldOperand
- {
- public StFld(ILInstruction target, ILInstruction value, IField field) : base(OpCode.StFld)
- {
- this.Target = target;
- this.Value = value;
- this.field = field;
- }
- public static readonly SlotInfo TargetSlot = new SlotInfo("Target", canInlineInto: true);
- ILInstruction target;
- public ILInstruction Target {
- get { return this.target; }
- set {
- ValidateChild(value);
- SetChildInstruction(ref this.target, value, 0);
- }
- }
- public static readonly SlotInfo ValueSlot = new SlotInfo("Value", canInlineInto: true);
- ILInstruction value;
- public ILInstruction Value {
- get { return this.value; }
- set {
- ValidateChild(value);
- SetChildInstruction(ref this.value, value, 1);
- }
- }
- protected sealed override int GetChildCount()
- {
- return 2;
- }
- protected sealed override ILInstruction GetChild(int index)
- {
- switch (index) {
- case 0:
- return this.target;
- case 1:
- return this.value;
- default:
- throw new IndexOutOfRangeException();
- }
- }
- protected sealed override void SetChild(int index, ILInstruction value)
- {
- switch (index) {
- case 0:
- this.Target = value;
- break;
- case 1:
- this.Value = value;
- break;
- default:
- throw new IndexOutOfRangeException();
- }
- }
- protected sealed override SlotInfo GetChildSlot(int index)
- {
- switch (index) {
- case 0:
- return TargetSlot;
- case 1:
- return ValueSlot;
- default:
- throw new IndexOutOfRangeException();
- }
- }
- public sealed override ILInstruction Clone()
- {
- var clone = (StFld)ShallowClone();
- clone.Target = this.target.Clone();
- clone.Value = this.value.Clone();
- return clone;
- }
- /// Gets/Sets whether the memory access is volatile.
- public bool IsVolatile { get; set; }
- /// Returns the alignment specified by the 'unaligned' prefix; or 0 if there was no 'unaligned' prefix.
- public byte UnalignedPrefix { get; set; }
- readonly IField field;
- /// Returns the field operand.
- public IField Field { get { return field; } }
- public override StackType ResultType { get { return field.Type.GetStackType(); } }
- protected override InstructionFlags ComputeFlags()
- {
- return target.Flags | value.Flags | InstructionFlags.SideEffect | InstructionFlags.MayThrow;
- }
- public override InstructionFlags DirectFlags {
- get {
- return InstructionFlags.SideEffect | InstructionFlags.MayThrow;
- }
- }
- public override void WriteTo(ITextOutput output)
- {
- if (IsVolatile)
- output.Write("volatile.");
- if (UnalignedPrefix > 0)
- output.Write("unaligned(" + UnalignedPrefix + ").");
- output.Write(OpCode);
- output.Write(' ');
- Disassembler.DisassemblerHelpers.WriteOperand(output, field);
- output.Write('(');
- this.target.WriteTo(output);
- output.Write(", ");
- this.value.WriteTo(output);
- output.Write(')');
- }
- public override void AcceptVisitor(ILVisitor visitor)
- {
- visitor.VisitStFld(this);
- }
- public override T AcceptVisitor(ILVisitor visitor)
- {
- return visitor.VisitStFld(this);
- }
- }
-
- /// Load static field
- public sealed partial class LdsFld : SimpleInstruction, ISupportsVolatilePrefix, ISupportsUnalignedPrefix, IInstructionWithFieldOperand
- {
- public LdsFld(IField field) : base(OpCode.LdsFld)
- {
- this.field = field;
- }
- /// Gets/Sets whether the memory access is volatile.
- public bool IsVolatile { get; set; }
- /// Returns the alignment specified by the 'unaligned' prefix; or 0 if there was no 'unaligned' prefix.
- public byte UnalignedPrefix { get; set; }
- readonly IField field;
- /// Returns the field operand.
- public IField Field { get { return field; } }
- public override StackType ResultType { get { return field.Type.GetStackType(); } }
- protected override InstructionFlags ComputeFlags()
- {
- return InstructionFlags.SideEffect;
- }
- public override InstructionFlags DirectFlags {
- get {
- return InstructionFlags.SideEffect;
- }
- }
- public override void WriteTo(ITextOutput output)
- {
- if (IsVolatile)
- output.Write("volatile.");
- if (UnalignedPrefix > 0)
- output.Write("unaligned(" + UnalignedPrefix + ").");
- output.Write(OpCode);
- output.Write(' ');
- Disassembler.DisassemblerHelpers.WriteOperand(output, field);
- }
- public override void AcceptVisitor(ILVisitor visitor)
- {
- visitor.VisitLdsFld(this);
- }
- public override T AcceptVisitor(ILVisitor visitor)
- {
- return visitor.VisitLdsFld(this);
- }
- }
-
/// Load static field address
public sealed partial class LdsFlda : SimpleInstruction, IInstructionWithFieldOperand
{
@@ -2396,101 +2134,6 @@ namespace ICSharpCode.Decompiler.IL
}
}
- /// Store value to static field
- public sealed partial class StsFld : ILInstruction, ISupportsVolatilePrefix, ISupportsUnalignedPrefix, IInstructionWithFieldOperand
- {
- public StsFld(ILInstruction value, IField field) : base(OpCode.StsFld)
- {
- this.Value = value;
- this.field = field;
- }
- public static readonly SlotInfo ValueSlot = new SlotInfo("Value", canInlineInto: true);
- ILInstruction value;
- public ILInstruction Value {
- get { return this.value; }
- set {
- ValidateChild(value);
- SetChildInstruction(ref this.value, value, 0);
- }
- }
- protected sealed override int GetChildCount()
- {
- return 1;
- }
- protected sealed override ILInstruction GetChild(int index)
- {
- switch (index) {
- case 0:
- return this.value;
- default:
- throw new IndexOutOfRangeException();
- }
- }
- protected sealed override void SetChild(int index, ILInstruction value)
- {
- switch (index) {
- case 0:
- this.Value = value;
- break;
- default:
- throw new IndexOutOfRangeException();
- }
- }
- protected sealed override SlotInfo GetChildSlot(int index)
- {
- switch (index) {
- case 0:
- return ValueSlot;
- default:
- throw new IndexOutOfRangeException();
- }
- }
- public sealed override ILInstruction Clone()
- {
- var clone = (StsFld)ShallowClone();
- clone.Value = this.value.Clone();
- return clone;
- }
- /// Gets/Sets whether the memory access is volatile.
- public bool IsVolatile { get; set; }
- /// Returns the alignment specified by the 'unaligned' prefix; or 0 if there was no 'unaligned' prefix.
- public byte UnalignedPrefix { get; set; }
- readonly IField field;
- /// Returns the field operand.
- public IField Field { get { return field; } }
- public override StackType ResultType { get { return field.Type.GetStackType(); } }
- protected override InstructionFlags ComputeFlags()
- {
- return value.Flags | InstructionFlags.SideEffect;
- }
- public override InstructionFlags DirectFlags {
- get {
- return InstructionFlags.SideEffect;
- }
- }
- public override void WriteTo(ITextOutput output)
- {
- if (IsVolatile)
- output.Write("volatile.");
- if (UnalignedPrefix > 0)
- output.Write("unaligned(" + UnalignedPrefix + ").");
- output.Write(OpCode);
- output.Write(' ');
- Disassembler.DisassemblerHelpers.WriteOperand(output, field);
- output.Write('(');
- this.value.WriteTo(output);
- output.Write(')');
- }
- public override void AcceptVisitor(ILVisitor visitor)
- {
- visitor.VisitStsFld(this);
- }
- public override T AcceptVisitor(ILVisitor visitor)
- {
- return visitor.VisitStsFld(this);
- }
- }
-
/// Casts an object to a class.
public sealed partial class CastClass : UnaryInstruction
{
@@ -3639,30 +3282,14 @@ namespace ICSharpCode.Decompiler.IL
{
Default(inst);
}
- protected internal virtual void VisitLdFld(LdFld inst)
- {
- Default(inst);
- }
protected internal virtual void VisitLdFlda(LdFlda inst)
{
Default(inst);
}
- protected internal virtual void VisitStFld(StFld inst)
- {
- Default(inst);
- }
- protected internal virtual void VisitLdsFld(LdsFld inst)
- {
- Default(inst);
- }
protected internal virtual void VisitLdsFlda(LdsFlda inst)
{
Default(inst);
}
- protected internal virtual void VisitStsFld(StsFld inst)
- {
- Default(inst);
- }
protected internal virtual void VisitCastClass(CastClass inst)
{
Default(inst);
@@ -3949,30 +3576,14 @@ namespace ICSharpCode.Decompiler.IL
{
return Default(inst);
}
- protected internal virtual T VisitLdFld(LdFld inst)
- {
- return Default(inst);
- }
protected internal virtual T VisitLdFlda(LdFlda inst)
{
return Default(inst);
}
- protected internal virtual T VisitStFld(StFld inst)
- {
- return Default(inst);
- }
- protected internal virtual T VisitLdsFld(LdsFld inst)
- {
- return Default(inst);
- }
protected internal virtual T VisitLdsFlda(LdsFlda inst)
{
return Default(inst);
}
- protected internal virtual T VisitStsFld(StsFld inst)
- {
- return Default(inst);
- }
protected internal virtual T VisitCastClass(CastClass inst)
{
return Default(inst);
@@ -4146,12 +3757,8 @@ namespace ICSharpCode.Decompiler.IL
"ret",
"shl",
"shr",
- "ldfld",
"ldflda",
- "stfld",
- "ldsfld",
"ldsflda",
- "stsfld",
"castclass",
"isinst",
"ldobj",
@@ -4538,18 +4145,6 @@ namespace ICSharpCode.Decompiler.IL
right = default(ILInstruction);
return false;
}
- public bool MatchLdFld(out ILInstruction target, out IField field)
- {
- var inst = this as LdFld;
- if (inst != null) {
- target = inst.Target;
- field = inst.Field;
- return true;
- }
- target = default(ILInstruction);
- field = default(IField);
- return false;
- }
public bool MatchLdFlda(out ILInstruction target, out IField field)
{
var inst = this as LdFlda;
@@ -4562,30 +4157,6 @@ namespace ICSharpCode.Decompiler.IL
field = default(IField);
return false;
}
- public bool MatchStFld(out ILInstruction target, out ILInstruction value, out IField field)
- {
- var inst = this as StFld;
- if (inst != null) {
- target = inst.Target;
- value = inst.Value;
- field = inst.Field;
- return true;
- }
- target = default(ILInstruction);
- value = default(ILInstruction);
- field = default(IField);
- return false;
- }
- public bool MatchLdsFld(out IField field)
- {
- var inst = this as LdsFld;
- if (inst != null) {
- field = inst.Field;
- return true;
- }
- field = default(IField);
- return false;
- }
public bool MatchLdsFlda(out IField field)
{
var inst = this as LdsFlda;
@@ -4596,18 +4167,6 @@ namespace ICSharpCode.Decompiler.IL
field = default(IField);
return false;
}
- public bool MatchStsFld(out ILInstruction value, out IField field)
- {
- var inst = this as StsFld;
- if (inst != null) {
- value = inst.Value;
- field = inst.Field;
- return true;
- }
- value = default(ILInstruction);
- field = default(IField);
- return false;
- }
public bool MatchCastClass(out ILInstruction argument, out IType type)
{
var inst = this as CastClass;
diff --git a/ICSharpCode.Decompiler/IL/Instructions.tt b/ICSharpCode.Decompiler/IL/Instructions.tt
index 15e50b638..8f745e076 100644
--- a/ICSharpCode.Decompiler/IL/Instructions.tt
+++ b/ICSharpCode.Decompiler/IL/Instructions.tt
@@ -146,24 +146,10 @@
new OpCode("shl", "Shift left", BinaryNumeric),
new OpCode("shr", "Shift right", BinaryNumeric),
- new OpCode("ldfld", "Load instance field",
- CustomClassName("LdFld"), CustomArguments("target"), MemoryAccess, SupportsVolatilePrefix, SupportsUnalignedPrefix, MayThrow,
- HasFieldOperand, ResultType("field.Type.GetStackType()")),
new OpCode("ldflda", "Load address of instance field",
CustomClassName("LdFlda"), CustomArguments("target"), MayThrowIfNotDelayed, HasFieldOperand, ResultType("Ref")),
- new OpCode("stfld", "Store value to instance field",
- CustomClassName("StFld"), CustomArguments("target", "value"),
- MemoryAccess, SupportsVolatilePrefix, SupportsUnalignedPrefix, MayThrow, HasFieldOperand,
- ResultType("field.Type.GetStackType()")),
- new OpCode("ldsfld", "Load static field",
- CustomClassName("LdsFld"), NoArguments, MemoryAccess, SupportsVolatilePrefix, SupportsUnalignedPrefix,
- HasFieldOperand, ResultType("field.Type.GetStackType()")),
new OpCode("ldsflda", "Load static field address",
CustomClassName("LdsFlda"), NoArguments, ResultType("Ref"), HasFieldOperand),
- new OpCode("stsfld", "Store value to static field",
- CustomClassName("StsFld"), CustomArguments("value"),
- MemoryAccess, SupportsVolatilePrefix, SupportsUnalignedPrefix, HasFieldOperand,
- ResultType("field.Type.GetStackType()")),
new OpCode("castclass", "Casts an object to a class.",
CustomClassName("CastClass"), Unary, HasTypeOperand, MayThrow, ResultType("type.GetStackType()")),
diff --git a/ICSharpCode.Decompiler/IL/Instructions/BinaryNumericInstruction.cs b/ICSharpCode.Decompiler/IL/Instructions/BinaryNumericInstruction.cs
index 42eab1d86..9be3a53c8 100644
--- a/ICSharpCode.Decompiler/IL/Instructions/BinaryNumericInstruction.cs
+++ b/ICSharpCode.Decompiler/IL/Instructions/BinaryNumericInstruction.cs
@@ -61,8 +61,6 @@ namespace ICSharpCode.Decompiler.IL
{
switch (inst.OpCode) {
case OpCode.LdLoc:
- case OpCode.LdFld:
- case OpCode.LdsFld:
case OpCode.LdObj:
return true;
case OpCode.Call:
diff --git a/ICSharpCode.Decompiler/IL/Instructions/PatternMatching.cs b/ICSharpCode.Decompiler/IL/Instructions/PatternMatching.cs
index 22a57fddb..128b525da 100644
--- a/ICSharpCode.Decompiler/IL/Instructions/PatternMatching.cs
+++ b/ICSharpCode.Decompiler/IL/Instructions/PatternMatching.cs
@@ -17,6 +17,7 @@
// DEALINGS IN THE SOFTWARE.
using System;
+using ICSharpCode.NRefactory.TypeSystem;
namespace ICSharpCode.Decompiler.IL
{
@@ -167,6 +168,40 @@ namespace ICSharpCode.Decompiler.IL
return false;
}
+ public bool MatchLdsFld(IField field)
+ {
+ LdsFlda ldsflda = (this as LdObj)?.Target as LdsFlda;
+ if (ldsflda != null) {
+ return field.Equals(ldsflda.Field);
+ }
+ return false;
+ }
+
+ public bool MatchLdsFld(out IField field)
+ {
+ LdsFlda ldsflda = (this as LdObj)?.Target as LdsFlda;
+ if (ldsflda != null) {
+ field = ldsflda.Field;
+ return true;
+ }
+ field = null;
+ return false;
+ }
+
+ public bool MatchStsFld(out ILInstruction value, out IField field)
+ {
+ var stobj = this as StObj;
+ LdsFlda ldsflda = stobj?.Target as LdsFlda;
+ if (ldsflda != null) {
+ value = stobj.Value;
+ field = ldsflda.Field;
+ return true;
+ }
+ value = null;
+ field = null;
+ return false;
+ }
+
///
/// If this instruction is a conversion of the specified kind, return its argument.
/// Otherwise, return the instruction itself.
diff --git a/ICSharpCode.Decompiler/IL/Transforms/CopyPropagation.cs b/ICSharpCode.Decompiler/IL/Transforms/CopyPropagation.cs
index b38bb6a96..3e1a66b58 100644
--- a/ICSharpCode.Decompiler/IL/Transforms/CopyPropagation.cs
+++ b/ICSharpCode.Decompiler/IL/Transforms/CopyPropagation.cs
@@ -62,7 +62,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
}
block.Instructions.RemoveAt(i);
int c = new ILInlining().InlineInto(block, i, aggressive: false);
- i -= uninlinedArgs.Length + c + 1;
+ i -= c + 1;
}
}
}
@@ -73,8 +73,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms
{
switch (value.OpCode) {
case OpCode.LdLoca:
- case OpCode.LdElema:
- case OpCode.LdFlda:
+// case OpCode.LdElema:
+// case OpCode.LdFlda:
case OpCode.LdsFlda:
// All address-loading instructions always return the same value for a given operand/argument combination,
// so they can be safely copied.
diff --git a/ICSharpCode.Decompiler/IL/Transforms/DelegateConstruction.cs b/ICSharpCode.Decompiler/IL/Transforms/DelegateConstruction.cs
index 06dc621c9..1e9ee239f 100644
--- a/ICSharpCode.Decompiler/IL/Transforms/DelegateConstruction.cs
+++ b/ICSharpCode.Decompiler/IL/Transforms/DelegateConstruction.cs
@@ -170,7 +170,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
var nextInstruction = inst.Parent.Children.ElementAtOrDefault(inst.ChildIndex + 1);
if (nextInstruction == null)
return false;
- var usages = nextInstruction.Descendants.OfType().Where(i => i.Field.Equals(field)).ToArray();
+ var usages = nextInstruction.Descendants.Where(i => i.MatchLdsFld(field)).ToArray();
if (usages.Length != 1)
return false;
usages[0].ReplaceWith(value);
diff --git a/ICSharpCode.Decompiler/IL/Transforms/ILInlining.cs b/ICSharpCode.Decompiler/IL/Transforms/ILInlining.cs
index 631759e11..4e6e2cf66 100644
--- a/ICSharpCode.Decompiler/IL/Transforms/ILInlining.cs
+++ b/ICSharpCode.Decompiler/IL/Transforms/ILInlining.cs
@@ -192,17 +192,13 @@ namespace ICSharpCode.Decompiler.IL.Transforms
switch (inlinedExpression.OpCode) {
case OpCode.LdLoc:
case OpCode.StLoc:
- case OpCode.LdElema:
return false;
- case OpCode.LdFld:
- case OpCode.StFld:
- case OpCode.LdsFld:
- case OpCode.StsFld:
+ case OpCode.LdObj:
// allow inlining field access only if it's a readonly field
- IField f = ((IInstructionWithFieldOperand)inlinedExpression).Field;
- if (!f.IsReadOnly)
- return false;
- break;
+ IField f = (((LdObj)inlinedExpression).Target as IInstructionWithFieldOperand)?.Field;
+ if (f != null && f.IsReadOnly)
+ return true;
+ return f != null && f.IsReadOnly;
case OpCode.Call:
var m = ((CallInstruction)inlinedExpression).Method;
// ensure that it's not an multi-dimensional array getter
@@ -233,8 +229,6 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return !((Call)parent).Method.IsStatic;
case OpCode.CallVirt:
return !((CallVirt)parent).Method.IsStatic;
- case OpCode.StFld:
- case OpCode.LdFld:
case OpCode.LdFlda:
// TODO : Reimplement Await
//case OpCode.Await:
diff --git a/ICSharpCode.Decompiler/IL/Transforms/TransformInlineAssignment.cs b/ICSharpCode.Decompiler/IL/Transforms/TransformInlineAssignment.cs
index 2c7366642..96a858d54 100644
--- a/ICSharpCode.Decompiler/IL/Transforms/TransformInlineAssignment.cs
+++ b/ICSharpCode.Decompiler/IL/Transforms/TransformInlineAssignment.cs
@@ -36,20 +36,52 @@ namespace ICSharpCode.Decompiler.IL.Transforms
this.context = context;
foreach (var block in function.Descendants.OfType()) {
for (int i = block.Instructions.Count - 1; i >= 0; i--) {
- var inst = block.Instructions[i] as StLoc;
- var nextInst = block.Instructions.ElementAtOrDefault(i + 1) as StLoc;
- ILVariable localVariable;
- // stloc s(value)
- // stloc l(ldloc s)
- // -->
- // stloc s(stloc l(value))
- if (inst != null && nextInst != null && nextInst.Variable.Kind != VariableKind.StackSlot && nextInst.Value.MatchLdLoc(inst.Variable)) {
- block.Instructions.RemoveAt(i + 1);
- var value = inst.Value.Clone();
- inst.Value.ReplaceWith(new StLoc(nextInst.Variable, value));
- }
+ TransformInlineAssignmentFields(block, i);
+ TransformInlineAssignmentLocal(block, i);
}
}
}
+
+ ///
+ /// stloc s(value)
+ /// stloc l(ldloc s)
+ /// -->
+ /// stloc s(stloc l(value))
+ ///
+ static void TransformInlineAssignmentLocal(Block block, int i)
+ {
+ var inst = block.Instructions[i] as StLoc;
+ var nextInst = block.Instructions.ElementAtOrDefault(i + 1) as StLoc;
+ if (inst == null || nextInst == null)
+ return;
+ if (nextInst.Variable.Kind == VariableKind.StackSlot || !nextInst.Value.MatchLdLoc(inst.Variable))
+ return;
+ block.Instructions.RemoveAt(i + 1);
+ var value = inst.Value.Clone();
+ inst.Value.ReplaceWith(new StLoc(nextInst.Variable, value));
+ }
+
+ ///
+ /// stloc s(value)
+ /// stloc l(ldloc s)
+ /// stfld f(..., ldloc s)
+ /// -->
+ /// stloc l(stfld f(..., value))
+ ///
+ static void TransformInlineAssignmentFields(Block block, int i)
+ {
+// var inst = block.Instructions[i] as StLoc;
+// var nextInst = block.Instructions.ElementAtOrDefault(i + 1) as StLoc;
+// var fieldStore = block.Instructions.ElementAtOrDefault(i + 2) as StObj;
+// if (inst == null || nextInst == null || fieldStore == null)
+// return;
+// if (nextInst.Variable.Kind == VariableKind.StackSlot || !nextInst.Value.MatchLdLoc(inst.Variable) || !fieldStore.Value.MatchLdLoc(inst.Variable))
+// return;
+// var value = inst.Value.Clone();
+// var locVar = nextInst.Variable;
+// block.Instructions.RemoveAt(i + 1);
+// block.Instructions.RemoveAt(i + 1);
+// inst.ReplaceWith(new StLoc(locVar, new StObj(fieldStore.Target, value, fieldStore.Field)));
+ }
}
}
diff --git a/ICSharpCode.Decompiler/Tests/TestCases/Pretty/InlineAssignmentTest.cs b/ICSharpCode.Decompiler/Tests/TestCases/Pretty/InlineAssignmentTest.cs
index f12f9b289..40ae049ab 100644
--- a/ICSharpCode.Decompiler/Tests/TestCases/Pretty/InlineAssignmentTest.cs
+++ b/ICSharpCode.Decompiler/Tests/TestCases/Pretty/InlineAssignmentTest.cs
@@ -22,6 +22,9 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{
public class InlineAssignmentTest
{
+ private int field1;
+ private InlineAssignmentTest field2;
+
public static void Main()
{
@@ -36,5 +39,19 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
Console.WriteLine((object)(V_1 = new InlineAssignmentTest()));
Console.WriteLine((object)V_1);
}
+
+ public void SimpleInlineWithFields()
+ {
+ Console.WriteLine(this.field1 = 5);
+ Console.WriteLine((object)(this.field2 = new InlineAssignmentTest()));
+ }
+
+ public void SimpleInlineWithFields2()
+ {
+ Console.WriteLine(this.field1 = 5);
+ Console.WriteLine(this.field1);
+ Console.WriteLine((object)(this.field2 = new InlineAssignmentTest()));
+ Console.WriteLine((object)this.field2);
+ }
}
}
diff --git a/ICSharpCode.Decompiler/Tests/TestCases/Pretty/InlineAssignmentTest.il b/ICSharpCode.Decompiler/Tests/TestCases/Pretty/InlineAssignmentTest.il
index f437b793d..580d0b79c 100644
--- a/ICSharpCode.Decompiler/Tests/TestCases/Pretty/InlineAssignmentTest.il
+++ b/ICSharpCode.Decompiler/Tests/TestCases/Pretty/InlineAssignmentTest.il
@@ -10,7 +10,7 @@
.publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
.ver 4:0:0:0
}
-.assembly '3cbicayo'
+.assembly '3z5tjxm2'
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 )
.custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78 // ....T..WrapNonEx
@@ -20,15 +20,15 @@
.hash algorithm 0x00008004
.ver 0:0:0:0
}
-.module '3cbicayo.exe'
-// MVID: {3A96AD80-B3A9-47A7-82A9-A9BE249D0492}
+.module '3z5tjxm2.exe'
+// MVID: {3B1EB063-50AF-4CD4-83C3-9D26A66D9510}
.custom instance void [mscorlib]System.Security.UnverifiableCodeAttribute::.ctor() = ( 01 00 00 00 )
.imagebase 0x00400000
.file alignment 0x00000200
.stackreserve 0x00100000
.subsystem 0x0003 // WINDOWS_CUI
.corflags 0x00000001 // ILONLY
-// Image base: 0x01100000
+// Image base: 0x011D0000
// =============== CLASS MEMBERS DECLARATION ===================
@@ -36,6 +36,8 @@
.class public auto ansi beforefieldinit ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest
extends [mscorlib]System.Object
{
+ .field private int32 field1
+ .field private class ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest field2
.method public hidebysig static void Main() cil managed
{
.entrypoint
@@ -72,6 +74,68 @@
IL_0025: ret
} // end of method InlineAssignmentTest::SimpleInlineWithLocals
+ .method public hidebysig instance void
+ SimpleInlineWithFields() cil managed
+ {
+ // Code size 38 (0x26)
+ .maxstack 3
+ .locals init (int32 V_0,
+ class ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest V_1)
+ IL_0000: nop
+ IL_0001: ldarg.0
+ IL_0002: ldc.i4.5
+ IL_0003: dup
+ IL_0004: stloc.0
+ IL_0005: stfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::field1
+ IL_000a: ldloc.0
+ IL_000b: call void [mscorlib]System.Console::WriteLine(int32)
+ IL_0010: nop
+ IL_0011: ldarg.0
+ IL_0012: newobj instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::.ctor()
+ IL_0017: dup
+ IL_0018: stloc.1
+ IL_0019: stfld class ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::field2
+ IL_001e: ldloc.1
+ IL_001f: call void [mscorlib]System.Console::WriteLine(object)
+ IL_0024: nop
+ IL_0025: ret
+ } // end of method InlineAssignmentTest::SimpleInlineWithFields
+
+ .method public hidebysig instance void
+ SimpleInlineWithFields2() cil managed
+ {
+ // Code size 62 (0x3e)
+ .maxstack 3
+ .locals init (int32 V_0,
+ class ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest V_1)
+ IL_0000: nop
+ IL_0001: ldarg.0
+ IL_0002: ldc.i4.5
+ IL_0003: dup
+ IL_0004: stloc.0
+ IL_0005: stfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::field1
+ IL_000a: ldloc.0
+ IL_000b: call void [mscorlib]System.Console::WriteLine(int32)
+ IL_0010: nop
+ IL_0011: ldarg.0
+ IL_0012: ldfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::field1
+ IL_0017: call void [mscorlib]System.Console::WriteLine(int32)
+ IL_001c: nop
+ IL_001d: ldarg.0
+ IL_001e: newobj instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::.ctor()
+ IL_0023: dup
+ IL_0024: stloc.1
+ IL_0025: stfld class ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::field2
+ IL_002a: ldloc.1
+ IL_002b: call void [mscorlib]System.Console::WriteLine(object)
+ IL_0030: nop
+ IL_0031: ldarg.0
+ IL_0032: ldfld class ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::field2
+ IL_0037: call void [mscorlib]System.Console::WriteLine(object)
+ IL_003c: nop
+ IL_003d: ret
+ } // end of method InlineAssignmentTest::SimpleInlineWithFields2
+
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{