Browse Source

Variable splitting for variables of type Nullable<T>.

pull/832/head
Daniel Grunwald 8 years ago
parent
commit
5c4a87eb32
  1. 1
      ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
  2. 40
      ICSharpCode.Decompiler/IL/Transforms/SplitVariables.cs

1
ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs

@ -79,6 +79,7 @@ namespace ICSharpCode.Decompiler.CSharp
// RemoveDeadVariableInit must run after ExpressionTransforms so that stobj(ldloca V, ...) // RemoveDeadVariableInit must run after ExpressionTransforms so that stobj(ldloca V, ...)
// is already collapsed into stloc(V, ...). // is already collapsed into stloc(V, ...).
new RemoveDeadVariableInit(), new RemoveDeadVariableInit(),
new SplitVariables(), // split variables once again, because the stobj(ldloca V, ...) may open up new replacements
new SwitchDetection(), new SwitchDetection(),
new BlockILTransform { // per-block transforms new BlockILTransform { // per-block transforms
PostOrderTransforms = { PostOrderTransforms = {

40
ICSharpCode.Decompiler/IL/Transforms/SplitVariables.cs

@ -48,7 +48,12 @@ namespace ICSharpCode.Decompiler.IL.Transforms
switch (v.Kind) { switch (v.Kind) {
case VariableKind.Local: case VariableKind.Local:
case VariableKind.Exception: case VariableKind.Exception:
return v.AddressCount == 0; foreach (var ldloca in v.AddressInstructions) {
if (!AddressUsedOnlyForReading(ldloca)) {
return false;
}
}
return true;
default: default:
// parameters: avoid splitting parameters // parameters: avoid splitting parameters
// stack slots: are already split by construction // stack slots: are already split by construction
@ -57,6 +62,28 @@ namespace ICSharpCode.Decompiler.IL.Transforms
} }
} }
static bool AddressUsedOnlyForReading(ILInstruction addressLoadingInstruction)
{
switch (addressLoadingInstruction.Parent) {
case LdObj ldobj:
return true;
case LdFlda ldflda:
return AddressUsedOnlyForReading(ldflda);
case Call call:
if (call.Method.DeclaringTypeDefinition.KnownTypeCode == TypeSystem.KnownTypeCode.NullableOfT) {
switch (call.Method.Name) {
case "get_HasValue":
case "get_Value":
case "GetValueOrDefault":
return true;
}
}
return false;
default:
return false;
}
}
/// <summary> /// <summary>
/// Use the union-find structure to merge /// Use the union-find structure to merge
/// </summary> /// </summary>
@ -75,6 +102,17 @@ namespace ICSharpCode.Decompiler.IL.Transforms
protected internal override void VisitLdLoc(LdLoc inst) protected internal override void VisitLdLoc(LdLoc inst)
{ {
base.VisitLdLoc(inst); base.VisitLdLoc(inst);
HandleLoad(inst);
}
protected internal override void VisitLdLoca(LdLoca inst)
{
base.VisitLdLoca(inst);
HandleLoad(inst);
}
void HandleLoad(IInstructionWithVariableOperand inst)
{
if (IsAnalyzedVariable(inst.Variable)) { if (IsAnalyzedVariable(inst.Variable)) {
if (IsPotentiallyUninitialized(state, inst.Variable)) { if (IsPotentiallyUninitialized(state, inst.Variable)) {
uninitVariableUsage.Add(inst); uninitVariableUsage.Add(inst);

Loading…
Cancel
Save