|
|
@ -41,7 +41,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms |
|
|
|
block.Instructions.RemoveAt(i); |
|
|
|
block.Instructions.RemoveAt(i); |
|
|
|
continue; |
|
|
|
continue; |
|
|
|
} |
|
|
|
} |
|
|
|
if (TransformInlineAssignmentStObj(block, i)) |
|
|
|
if (TransformInlineAssignmentStObj(block, i) || TransformInlineAssignmentLocal(block, i)) |
|
|
|
continue; |
|
|
|
continue; |
|
|
|
if (TransformInlineCompoundAssignmentCall(block, i)) |
|
|
|
if (TransformInlineCompoundAssignmentCall(block, i)) |
|
|
|
continue; |
|
|
|
continue; |
|
|
@ -59,13 +59,17 @@ namespace ICSharpCode.Decompiler.IL.Transforms |
|
|
|
/// -->
|
|
|
|
/// -->
|
|
|
|
/// stloc l(stobj (..., value))
|
|
|
|
/// stloc l(stobj (..., value))
|
|
|
|
/// </code>
|
|
|
|
/// </code>
|
|
|
|
|
|
|
|
/// e.g. used for inline assignment to instance field
|
|
|
|
|
|
|
|
///
|
|
|
|
/// -or-
|
|
|
|
/// -or-
|
|
|
|
|
|
|
|
///
|
|
|
|
/// <code>
|
|
|
|
/// <code>
|
|
|
|
/// stloc s(value)
|
|
|
|
/// stloc s(value)
|
|
|
|
/// stobj (..., ldloc s)
|
|
|
|
/// stobj (..., ldloc s)
|
|
|
|
/// -->
|
|
|
|
/// -->
|
|
|
|
/// stloc s(stobj (..., value))
|
|
|
|
/// stloc s(stobj (..., value))
|
|
|
|
/// </code>
|
|
|
|
/// </code>
|
|
|
|
|
|
|
|
/// e.g. used for inline assignment to static field
|
|
|
|
bool TransformInlineAssignmentStObj(Block block, int i) |
|
|
|
bool TransformInlineAssignmentStObj(Block block, int i) |
|
|
|
{ |
|
|
|
{ |
|
|
|
var inst = block.Instructions[i] as StLoc; |
|
|
|
var inst = block.Instructions[i] as StLoc; |
|
|
@ -76,27 +80,28 @@ namespace ICSharpCode.Decompiler.IL.Transforms |
|
|
|
ILInstruction replacement; |
|
|
|
ILInstruction replacement; |
|
|
|
StObj fieldStore; |
|
|
|
StObj fieldStore; |
|
|
|
ILVariable local; |
|
|
|
ILVariable local; |
|
|
|
if (nextInst is StLoc) { // instance fields
|
|
|
|
if (nextInst is StLoc localStore) { // with extra local
|
|
|
|
var localStore = (StLoc)nextInst; |
|
|
|
if (localStore.Variable.Kind != VariableKind.Local || !localStore.Value.MatchLdLoc(inst.Variable)) |
|
|
|
if (localStore.Variable.Kind == VariableKind.StackSlot || !localStore.Value.MatchLdLoc(inst.Variable)) |
|
|
|
return false; |
|
|
|
|
|
|
|
if (!(inst.Variable.IsSingleDefinition && inst.Variable.LoadCount == 2)) |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
var memberStore = block.Instructions.ElementAtOrDefault(i + 2); |
|
|
|
var memberStore = block.Instructions.ElementAtOrDefault(i + 2); |
|
|
|
if (memberStore is StObj) { |
|
|
|
if (memberStore is StObj) { |
|
|
|
fieldStore = memberStore as StObj; |
|
|
|
fieldStore = memberStore as StObj; |
|
|
|
if (!fieldStore.Value.MatchLdLoc(inst.Variable)) |
|
|
|
if (!fieldStore.Value.MatchLdLoc(inst.Variable) || localStore.Variable.IsUsedWithin(fieldStore.Target)) |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
replacement = new StObj(fieldStore.Target, inst.Value, fieldStore.Type); |
|
|
|
replacement = new StObj(fieldStore.Target, inst.Value, fieldStore.Type); |
|
|
|
} else { // otherwise it must be local
|
|
|
|
} else { |
|
|
|
return TransformInlineAssignmentLocal(block, i); |
|
|
|
return false; |
|
|
|
} |
|
|
|
} |
|
|
|
context.Step("Inline assignment to instance field", fieldStore); |
|
|
|
context.Step("Inline assignment stobj (with extra local)", fieldStore); |
|
|
|
local = localStore.Variable; |
|
|
|
local = localStore.Variable; |
|
|
|
block.Instructions.RemoveAt(i + 1); |
|
|
|
block.Instructions.RemoveAt(i + 1); |
|
|
|
} else if (nextInst is StObj) { // static fields
|
|
|
|
} else if (nextInst is StObj) { // without extra local
|
|
|
|
fieldStore = (StObj)nextInst; |
|
|
|
fieldStore = (StObj)nextInst; |
|
|
|
if (!fieldStore.Value.MatchLdLoc(inst.Variable) || (fieldStore.Target.MatchLdFlda(out var target, out _) && target.MatchLdLoc(inst.Variable))) |
|
|
|
if (!fieldStore.Value.MatchLdLoc(inst.Variable) || inst.Variable.IsUsedWithin(fieldStore.Target)) |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
context.Step("Inline assignment to static field", fieldStore); |
|
|
|
context.Step("Inline assignment stobj", fieldStore); |
|
|
|
local = inst.Variable; |
|
|
|
local = inst.Variable; |
|
|
|
replacement = new StObj(fieldStore.Target, inst.Value, fieldStore.Type); |
|
|
|
replacement = new StObj(fieldStore.Target, inst.Value, fieldStore.Type); |
|
|
|
} else { |
|
|
|
} else { |
|
|
@ -246,7 +251,9 @@ namespace ICSharpCode.Decompiler.IL.Transforms |
|
|
|
var nextInst = block.Instructions.ElementAtOrDefault(i + 1) as StLoc; |
|
|
|
var nextInst = block.Instructions.ElementAtOrDefault(i + 1) as StLoc; |
|
|
|
if (inst == null || nextInst == null) |
|
|
|
if (inst == null || nextInst == null) |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
if (nextInst.Variable.Kind == VariableKind.StackSlot || !nextInst.Value.MatchLdLoc(inst.Variable)) |
|
|
|
if (inst.Variable.Kind != VariableKind.StackSlot) |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
if (nextInst.Variable.Kind != VariableKind.Local || !nextInst.Value.MatchLdLoc(inst.Variable)) |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
context.Step("Inline assignment to local variable", inst); |
|
|
|
context.Step("Inline assignment to local variable", inst); |
|
|
|
var value = inst.Value; |
|
|
|
var value = inst.Value; |
|
|
|