Browse Source

Reset HasInitialValue flag after TransformDisplayClassUsage.

pull/1612/head
Siegfried Pammer 6 years ago
parent
commit
7d62a7e032
  1. 71
      ICSharpCode.Decompiler/FlowAnalysis/DataFlowVisitor.cs
  2. 55
      ICSharpCode.Decompiler/FlowAnalysis/DefiniteAssignmentVisitor.cs
  3. 19
      ICSharpCode.Decompiler/IL/Transforms/RemoveDeadVariableInit.cs
  4. 1
      ICSharpCode.Decompiler/IL/Transforms/TransformDisplayClassUsage.cs

71
ICSharpCode.Decompiler/FlowAnalysis/DataFlowVisitor.cs

@ -222,6 +222,7 @@ namespace ICSharpCode.Decompiler.FlowAnalysis @@ -222,6 +222,7 @@ namespace ICSharpCode.Decompiler.FlowAnalysis
this.bottomState = initialState.Clone();
this.bottomState.ReplaceWithBottom();
Debug.Assert(bottomState.IsBottom);
this.stateOnNullableRewrap = bottomState.Clone();
this.currentStateOnException = state.Clone();
}
@ -254,7 +255,7 @@ namespace ICSharpCode.Decompiler.FlowAnalysis @@ -254,7 +255,7 @@ namespace ICSharpCode.Decompiler.FlowAnalysis
#endif
[Conditional("DEBUG")]
void DebugStartPoint(ILInstruction inst)
protected void DebugStartPoint(ILInstruction inst)
{
#if DEBUG
DebugPoint(debugInputState, inst);
@ -262,7 +263,7 @@ namespace ICSharpCode.Decompiler.FlowAnalysis @@ -262,7 +263,7 @@ namespace ICSharpCode.Decompiler.FlowAnalysis
}
[Conditional("DEBUG")]
void DebugEndPoint(ILInstruction inst)
protected void DebugEndPoint(ILInstruction inst)
{
#if DEBUG
DebugPoint(debugOutputState, inst);
@ -286,7 +287,7 @@ namespace ICSharpCode.Decompiler.FlowAnalysis @@ -286,7 +287,7 @@ namespace ICSharpCode.Decompiler.FlowAnalysis
foreach (var child in inst.Children) {
child.AcceptVisitor(this);
Debug.Assert(state.IsBottom || !child.HasFlag(InstructionFlags.EndPointUnreachable),
"Unreachable code must be in the bottom state.");
"Unreachable code must be in the bottom state.");
}
DebugEndPoint(inst);
@ -611,7 +612,53 @@ namespace ICSharpCode.Decompiler.FlowAnalysis @@ -611,7 +612,53 @@ namespace ICSharpCode.Decompiler.FlowAnalysis
state.JoinWith(afterTrueState);
DebugEndPoint(inst);
}
protected internal override void VisitNullCoalescingInstruction(NullCoalescingInstruction inst)
{
HandleBinaryWithOptionalEvaluation(inst, inst.ValueInst, inst.FallbackInst);
}
protected internal override void VisitDynamicLogicOperatorInstruction(DynamicLogicOperatorInstruction inst)
{
HandleBinaryWithOptionalEvaluation(inst, inst.Left, inst.Right);
}
protected internal override void VisitUserDefinedLogicOperator(UserDefinedLogicOperator inst)
{
HandleBinaryWithOptionalEvaluation(inst, inst.Left, inst.Right);
}
void HandleBinaryWithOptionalEvaluation(ILInstruction parent, ILInstruction left, ILInstruction right)
{
DebugStartPoint(parent);
left.AcceptVisitor(this);
State branchState = state.Clone();
right.AcceptVisitor(this);
state.JoinWith(branchState);
DebugEndPoint(parent);
}
State stateOnNullableRewrap;
protected internal override void VisitNullableRewrap(NullableRewrap inst)
{
DebugStartPoint(inst);
var oldState = stateOnNullableRewrap.Clone();
stateOnNullableRewrap.ReplaceWithBottom();
inst.Argument.AcceptVisitor(this);
state.JoinWith(stateOnNullableRewrap);
stateOnNullableRewrap = oldState;
DebugEndPoint(inst);
}
protected internal override void VisitNullableUnwrap(NullableUnwrap inst)
{
DebugStartPoint(inst);
inst.Argument.AcceptVisitor(this);
stateOnNullableRewrap.JoinWith(state);
DebugEndPoint(inst);
}
protected internal override void VisitSwitchInstruction(SwitchInstruction inst)
{
DebugStartPoint(inst);
@ -635,6 +682,22 @@ namespace ICSharpCode.Decompiler.FlowAnalysis @@ -635,6 +682,22 @@ namespace ICSharpCode.Decompiler.FlowAnalysis
DebugEndPoint(inst);
}
protected internal override void VisitUsingInstruction(UsingInstruction inst)
{
DebugStartPoint(inst);
inst.ResourceExpression.AcceptVisitor(this);
inst.Body.AcceptVisitor(this);
DebugEndPoint(inst);
}
protected internal override void VisitLockInstruction(LockInstruction inst)
{
DebugStartPoint(inst);
inst.OnExpression.AcceptVisitor(this);
inst.Body.AcceptVisitor(this);
DebugEndPoint(inst);
}
protected internal override void VisitILFunction(ILFunction function)
{
throw new NotImplementedException();

55
ICSharpCode.Decompiler/FlowAnalysis/DefiniteAssignmentVisitor.cs

@ -20,6 +20,9 @@ using System.Diagnostics; @@ -20,6 +20,9 @@ using System.Diagnostics;
using ICSharpCode.Decompiler.IL;
using ICSharpCode.Decompiler.Util;
using System.Threading;
using System;
using System.Collections.Generic;
using ICSharpCode.Decompiler.TypeSystem;
namespace ICSharpCode.Decompiler.FlowAnalysis
{
@ -117,6 +120,8 @@ namespace ICSharpCode.Decompiler.FlowAnalysis @@ -117,6 +120,8 @@ namespace ICSharpCode.Decompiler.FlowAnalysis
readonly CancellationToken cancellationToken;
readonly ILFunction scope;
readonly BitSet variablesWithUninitializedUsage;
readonly Dictionary<IMethod, State> stateOfLocalFunctionUse = new Dictionary<IMethod, State>();
readonly HashSet<IMethod> localFunctionsNeedingAnalysis = new HashSet<IMethod>();
public DefiniteAssignmentVisitor(ILFunction scope, CancellationToken cancellationToken)
{
@ -203,8 +208,34 @@ namespace ICSharpCode.Decompiler.FlowAnalysis @@ -203,8 +208,34 @@ namespace ICSharpCode.Decompiler.FlowAnalysis
HandleCall(inst);
}
protected internal override void VisitILFunction(ILFunction inst)
{
DebugStartPoint(inst);
State stateBeforeFunction = state.Clone();
State stateOnExceptionBeforeFunction = currentStateOnException.Clone();
inst.Body.AcceptVisitor(this);
bool changed;
do {
changed = false;
foreach (var nestedFunction in inst.LocalFunctions) {
if (!localFunctionsNeedingAnalysis.Contains(nestedFunction.ReducedMethod))
continue;
localFunctionsNeedingAnalysis.Remove(nestedFunction.ReducedMethod);
State stateOnEntry = stateOfLocalFunctionUse[nestedFunction.ReducedMethod];
this.state.ReplaceWith(stateOnEntry);
this.currentStateOnException.ReplaceWithBottom();
nestedFunction.Body.AcceptVisitor(this);
changed = true;
}
} while (changed);
currentStateOnException = stateOnExceptionBeforeFunction;
state = stateBeforeFunction;
DebugEndPoint(inst);
}
void HandleCall(CallInstruction call)
{
DebugStartPoint(call);
bool hasOutArgs = false;
foreach (var arg in call.Arguments) {
if (arg.MatchLdLoca(out var v) && call.GetParameter(arg.ChildIndex)?.IsOut == true) {
@ -223,6 +254,30 @@ namespace ICSharpCode.Decompiler.FlowAnalysis @@ -223,6 +254,30 @@ namespace ICSharpCode.Decompiler.FlowAnalysis
}
}
}
HandleLocalFunctionUse(call.Method);
DebugEndPoint(call);
}
void HandleLocalFunctionUse(IMethod method)
{
if (method.IsLocalFunction) {
if (stateOfLocalFunctionUse.TryGetValue(method, out var stateOnEntry)) {
if (!state.LessThanOrEqual(stateOnEntry)) {
stateOnEntry.JoinWith(state);
localFunctionsNeedingAnalysis.Add(method);
}
} else {
stateOfLocalFunctionUse.Add(method, state.Clone());
localFunctionsNeedingAnalysis.Add(method);
}
}
}
protected internal override void VisitLdFtn(LdFtn inst)
{
DebugStartPoint(inst);
HandleLocalFunctionUse(inst.Method);
DebugEndPoint(inst);
}
}
}

19
ICSharpCode.Decompiler/IL/Transforms/RemoveDeadVariableInit.cs

@ -35,13 +35,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -35,13 +35,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
{
public void Run(ILFunction function, ILTransformContext context)
{
var visitor = new DefiniteAssignmentVisitor(function, context.CancellationToken);
function.Body.AcceptVisitor(visitor);
foreach (var v in function.Variables) {
if (v.Kind != VariableKind.Parameter && !visitor.IsPotentiallyUsedUninitialized(v)) {
v.HasInitialValue = false;
}
}
ResetHasInitialValueFlag(function, context);
// Remove dead stores to variables that are never read from.
// If the stored value has some side-effect, the value is unwrapped.
// This is necessary to remove useless stores generated by some compilers, e.g., the F# compiler.
@ -94,5 +88,16 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -94,5 +88,16 @@ namespace ICSharpCode.Decompiler.IL.Transforms
}
}
}
internal static void ResetHasInitialValueFlag(ILFunction function, ILTransformContext context)
{
var visitor = new DefiniteAssignmentVisitor(function, context.CancellationToken);
function.AcceptVisitor(visitor);
foreach (var v in function.Variables) {
if (v.Kind != VariableKind.Parameter && !visitor.IsPotentiallyUsedUninitialized(v)) {
v.HasInitialValue = false;
}
}
}
}
}

1
ICSharpCode.Decompiler/IL/Transforms/TransformDisplayClassUsage.cs

@ -86,6 +86,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -86,6 +86,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
containingBlock.Instructions.Remove(store);
}
}
RemoveDeadVariableInit.ResetHasInitialValueFlag(function, context);
} finally {
instructionsToRemove.Clear();
displayClasses.Clear();

Loading…
Cancel
Save