Browse Source

Don't unnecessarily default-initialize variables prior to a call with out-parameter.

pull/1087/head
Daniel Grunwald 7 years ago
parent
commit
96d9e63f4c
  1. 10
      ICSharpCode.Decompiler/FlowAnalysis/DefiniteAssignmentVisitor.cs
  2. 13
      ICSharpCode.Decompiler/IL/Instructions/CallInstruction.cs
  3. 2
      ICSharpCode.Decompiler/IL/Transforms/AssignVariableNames.cs

10
ICSharpCode.Decompiler/FlowAnalysis/DefiniteAssignmentVisitor.cs

@ -183,7 +183,17 @@ namespace ICSharpCode.Decompiler.FlowAnalysis
protected internal override void VisitLdLoca(LdLoca inst) protected internal override void VisitLdLoca(LdLoca inst)
{ {
// A variable needs to be initialized before we can take it by reference.
// The exception is if the variable is passed to an out parameter.
if (!IsOutArgument(inst)) {
EnsureInitialized(inst.Variable); EnsureInitialized(inst.Variable);
} }
} }
static bool IsOutArgument(ILInstruction inst)
{
return inst.Parent is CallInstruction call
&& call.GetParameter(inst.ChildIndex)?.IsOut == true;
}
}
} }

13
ICSharpCode.Decompiler/IL/Instructions/CallInstruction.cs

@ -65,6 +65,19 @@ namespace ICSharpCode.Decompiler.IL
this.Arguments = new InstructionCollection<ILInstruction>(this, 0); this.Arguments = new InstructionCollection<ILInstruction>(this, 0);
} }
/// <summary>
/// Gets the parameter for the argument with the specified index.
/// Returns null for the <c>this</c> parameter.
/// </summary>
public IParameter GetParameter(int argumentIndex)
{
int firstParamIndex = (Method.IsStatic || OpCode == OpCode.NewObj) ? 0 : 1;
if (argumentIndex < firstParamIndex) {
return null; // asking for 'this' parameter
}
return Method.Parameters[argumentIndex - firstParamIndex];
}
public override StackType ResultType { public override StackType ResultType {
get { get {
if (OpCode == OpCode.NewObj) if (OpCode == OpCode.NewObj)

2
ICSharpCode.Decompiler/IL/Transforms/AssignVariableNames.cs

@ -338,7 +338,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return CleanUpVariableName(m.Name.Substring(3)); return CleanUpVariableName(m.Name.Substring(3));
} }
} }
var p = m.Parameters.ElementAtOrDefault((!(call is NewObj) && !m.IsStatic) ? i - 1 : i); var p = call.GetParameter(i);
if (p != null && !string.IsNullOrEmpty(p.Name)) if (p != null && !string.IsNullOrEmpty(p.Name))
return CleanUpVariableName(p.Name); return CleanUpVariableName(p.Name);
break; break;

Loading…
Cancel
Save