Browse Source

Merge branch 'master' of https://github.com/icsharpcode/ILSpy into copy-propagation

pull/1612/head
Siegfried Pammer 6 years ago
parent
commit
78ff7d4fdc
  1. 4
      ICSharpCode.Decompiler/FlowAnalysis/DataFlowVisitor.cs
  2. 21
      ICSharpCode.Decompiler/FlowAnalysis/DefiniteAssignmentVisitor.cs
  3. 9
      ICSharpCode.Decompiler/TypeSystem/Implementation/NullabilityAnnotatedType.cs
  4. 14
      ICSharpCode.Decompiler/TypeSystem/ParameterizedType.cs

4
ICSharpCode.Decompiler/FlowAnalysis/DataFlowVisitor.cs

@ -645,8 +645,11 @@ namespace ICSharpCode.Decompiler.FlowAnalysis
DebugStartPoint(inst); DebugStartPoint(inst);
var oldState = stateOnNullableRewrap.Clone(); var oldState = stateOnNullableRewrap.Clone();
stateOnNullableRewrap.ReplaceWithBottom(); stateOnNullableRewrap.ReplaceWithBottom();
inst.Argument.AcceptVisitor(this); inst.Argument.AcceptVisitor(this);
// Join incoming control flow from the NullableUnwraps.
state.JoinWith(stateOnNullableRewrap); state.JoinWith(stateOnNullableRewrap);
stateOnNullableRewrap = oldState; stateOnNullableRewrap = oldState;
DebugEndPoint(inst); DebugEndPoint(inst);
} }
@ -655,6 +658,7 @@ namespace ICSharpCode.Decompiler.FlowAnalysis
{ {
DebugStartPoint(inst); DebugStartPoint(inst);
inst.Argument.AcceptVisitor(this); inst.Argument.AcceptVisitor(this);
// Conditional control flow edge to the surrounding NullableRewrap.
stateOnNullableRewrap.JoinWith(state); stateOnNullableRewrap.JoinWith(state);
DebugEndPoint(inst); DebugEndPoint(inst);
} }

21
ICSharpCode.Decompiler/FlowAnalysis/DefiniteAssignmentVisitor.cs

@ -120,6 +120,7 @@ namespace ICSharpCode.Decompiler.FlowAnalysis
readonly CancellationToken cancellationToken; readonly CancellationToken cancellationToken;
readonly ILFunction scope; readonly ILFunction scope;
readonly BitSet variablesWithUninitializedUsage; readonly BitSet variablesWithUninitializedUsage;
readonly Dictionary<IMethod, State> stateOfLocalFunctionUse = new Dictionary<IMethod, State>(); readonly Dictionary<IMethod, State> stateOfLocalFunctionUse = new Dictionary<IMethod, State>();
readonly HashSet<IMethod> localFunctionsNeedingAnalysis = new HashSet<IMethod>(); readonly HashSet<IMethod> localFunctionsNeedingAnalysis = new HashSet<IMethod>();
@ -213,7 +214,19 @@ namespace ICSharpCode.Decompiler.FlowAnalysis
DebugStartPoint(inst); DebugStartPoint(inst);
State stateBeforeFunction = state.Clone(); State stateBeforeFunction = state.Clone();
State stateOnExceptionBeforeFunction = currentStateOnException.Clone(); State stateOnExceptionBeforeFunction = currentStateOnException.Clone();
// Note: lambdas are handled at their point of declaration.
// We immediately visit their body, because captured variables need to be definitely initialized at this point.
// We ignore the state after the lambda body (by resetting to the state before), because we don't know
// when the lambda will be invoked.
// This also makes this logic unsuitable for reaching definitions, as we wouldn't see the effect of stores in lambdas.
// Only the simpler case of definite assignment can support lambdas.
inst.Body.AcceptVisitor(this); inst.Body.AcceptVisitor(this);
// For local functions, the situation is similar to lambdas.
// However, we don't use the state of the declaration site when visiting local functions,
// but instead the state(s) of their point of use.
// Because we might discover additional points of use within the local functions,
// we use a fixed-point iteration.
bool changed; bool changed;
do { do {
changed = false; changed = false;
@ -223,8 +236,8 @@ namespace ICSharpCode.Decompiler.FlowAnalysis
localFunctionsNeedingAnalysis.Remove(nestedFunction.ReducedMethod); localFunctionsNeedingAnalysis.Remove(nestedFunction.ReducedMethod);
State stateOnEntry = stateOfLocalFunctionUse[nestedFunction.ReducedMethod]; State stateOnEntry = stateOfLocalFunctionUse[nestedFunction.ReducedMethod];
this.state.ReplaceWith(stateOnEntry); this.state.ReplaceWith(stateOnEntry);
this.currentStateOnException.ReplaceWithBottom(); this.currentStateOnException.ReplaceWith(stateOnEntry);
nestedFunction.Body.AcceptVisitor(this); nestedFunction.AcceptVisitor(this);
changed = true; changed = true;
} }
} while (changed); } while (changed);
@ -258,6 +271,10 @@ namespace ICSharpCode.Decompiler.FlowAnalysis
DebugEndPoint(call); DebugEndPoint(call);
} }
/// <summary>
/// For a use of a local function, remember the current state to use as stateOnEntry when
/// later processing the local function body.
/// </summary>
void HandleLocalFunctionUse(IMethod method) void HandleLocalFunctionUse(IMethod method)
{ {
if (method.IsLocalFunction) { if (method.IsLocalFunction) {

9
ICSharpCode.Decompiler/TypeSystem/Implementation/NullabilityAnnotatedType.cs

@ -53,11 +53,16 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
IType newBase = baseType.AcceptVisitor(visitor); IType newBase = baseType.AcceptVisitor(visitor);
if (newBase != baseType) { if (newBase != baseType) {
if (newBase.Nullability == Nullability.Nullable) { if (newBase.Nullability == Nullability.Nullable) {
// T?! -> T? // `T!` with substitution T=`U?` becomes `U?`
// This happens during type substitution for generic methods. // This happens during type substitution for generic methods.
return newBase; return newBase;
} }
return newBase.ChangeNullability(nullability); if (newBase.Kind == TypeKind.TypeParameter || newBase.IsReferenceType == true) {
return newBase.ChangeNullability(nullability);
} else {
// `T!` with substitution T=`int` becomes `int`, not `int!`
return newBase;
}
} else { } else {
return this; return this;
} }

14
ICSharpCode.Decompiler/TypeSystem/ParameterizedType.cs

@ -140,10 +140,20 @@ namespace ICSharpCode.Decompiler.TypeSystem
return b.ToString(); return b.ToString();
} }
} }
public override string ToString() public override string ToString()
{ {
return ReflectionName; StringBuilder b = new StringBuilder(genericType.ToString());
b.Append('[');
for (int i = 0; i < typeArguments.Length; i++) {
if (i > 0)
b.Append(',');
b.Append('[');
b.Append(typeArguments[i].ToString());
b.Append(']');
}
b.Append(']');
return b.ToString();
} }
public IReadOnlyList<IType> TypeArguments => typeArguments; public IReadOnlyList<IType> TypeArguments => typeArguments;

Loading…
Cancel
Save