Browse Source

Add RemoveDeadCode option

pull/925/merge
Siegfried Pammer 8 years ago
parent
commit
d2f2a13982
  1. 90
      ICSharpCode.Decompiler/DecompilerSettings.cs
  2. 34
      ICSharpCode.Decompiler/IL/Transforms/RemoveDeadVariableInit.cs
  3. 1
      ILSpy/Options/DecompilerSettingsPanel.xaml

90
ICSharpCode.Decompiler/DecompilerSettings.cs

@ -29,7 +29,7 @@ namespace ICSharpCode.Decompiler
public class DecompilerSettings : INotifyPropertyChanged public class DecompilerSettings : INotifyPropertyChanged
{ {
bool anonymousMethods = true; bool anonymousMethods = true;
/// <summary> /// <summary>
/// Decompile anonymous methods/lambdas. /// Decompile anonymous methods/lambdas.
/// </summary> /// </summary>
@ -59,7 +59,7 @@ namespace ICSharpCode.Decompiler
} }
bool expressionTrees = true; bool expressionTrees = true;
/// <summary> /// <summary>
/// Decompile expression trees. /// Decompile expression trees.
/// </summary> /// </summary>
@ -72,9 +72,9 @@ namespace ICSharpCode.Decompiler
} }
} }
} }
bool yieldReturn = true; bool yieldReturn = true;
/// <summary> /// <summary>
/// Decompile enumerators. /// Decompile enumerators.
/// </summary> /// </summary>
@ -87,9 +87,9 @@ namespace ICSharpCode.Decompiler
} }
} }
} }
bool asyncAwait = true; bool asyncAwait = true;
/// <summary> /// <summary>
/// Decompile async methods. /// Decompile async methods.
/// </summary> /// </summary>
@ -134,7 +134,7 @@ namespace ICSharpCode.Decompiler
} }
bool automaticProperties = true; bool automaticProperties = true;
/// <summary> /// <summary>
/// Decompile automatic properties /// Decompile automatic properties
/// </summary> /// </summary>
@ -147,9 +147,9 @@ namespace ICSharpCode.Decompiler
} }
} }
} }
bool automaticEvents = true; bool automaticEvents = true;
/// <summary> /// <summary>
/// Decompile automatic events /// Decompile automatic events
/// </summary> /// </summary>
@ -162,9 +162,9 @@ namespace ICSharpCode.Decompiler
} }
} }
} }
bool usingStatement = true; bool usingStatement = true;
/// <summary> /// <summary>
/// Decompile using statements. /// Decompile using statements.
/// </summary> /// </summary>
@ -177,9 +177,9 @@ namespace ICSharpCode.Decompiler
} }
} }
} }
bool forEachStatement = true; bool forEachStatement = true;
/// <summary> /// <summary>
/// Decompile foreach statements. /// Decompile foreach statements.
/// </summary> /// </summary>
@ -192,9 +192,9 @@ namespace ICSharpCode.Decompiler
} }
} }
} }
bool lockStatement = true; bool lockStatement = true;
/// <summary> /// <summary>
/// Decompile lock statements. /// Decompile lock statements.
/// </summary> /// </summary>
@ -207,9 +207,9 @@ namespace ICSharpCode.Decompiler
} }
} }
} }
bool switchStatementOnString = true; bool switchStatementOnString = true;
public bool SwitchStatementOnString { public bool SwitchStatementOnString {
get { return switchStatementOnString; } get { return switchStatementOnString; }
set { set {
@ -219,9 +219,9 @@ namespace ICSharpCode.Decompiler
} }
} }
} }
bool usingDeclarations = true; bool usingDeclarations = true;
public bool UsingDeclarations { public bool UsingDeclarations {
get { return usingDeclarations; } get { return usingDeclarations; }
set { set {
@ -231,9 +231,9 @@ namespace ICSharpCode.Decompiler
} }
} }
} }
bool queryExpressions = true; bool queryExpressions = true;
public bool QueryExpressions { public bool QueryExpressions {
get { return queryExpressions; } get { return queryExpressions; }
set { set {
@ -262,7 +262,7 @@ namespace ICSharpCode.Decompiler
} }
bool fullyQualifyAmbiguousTypeNames = true; bool fullyQualifyAmbiguousTypeNames = true;
public bool FullyQualifyAmbiguousTypeNames { public bool FullyQualifyAmbiguousTypeNames {
get { return fullyQualifyAmbiguousTypeNames; } get { return fullyQualifyAmbiguousTypeNames; }
set { set {
@ -272,9 +272,9 @@ namespace ICSharpCode.Decompiler
} }
} }
} }
bool useDebugSymbols = true; bool useDebugSymbols = true;
/// <summary> /// <summary>
/// Gets/Sets whether to use variable names from debug symbols, if available. /// Gets/Sets whether to use variable names from debug symbols, if available.
/// </summary> /// </summary>
@ -287,9 +287,9 @@ namespace ICSharpCode.Decompiler
} }
} }
} }
bool objectCollectionInitializers = true; bool objectCollectionInitializers = true;
/// <summary> /// <summary>
/// Gets/Sets whether to use C# 3.0 object/collection initializers /// Gets/Sets whether to use C# 3.0 object/collection initializers
/// </summary> /// </summary>
@ -302,9 +302,9 @@ namespace ICSharpCode.Decompiler
} }
} }
} }
bool showXmlDocumentation = true; bool showXmlDocumentation = true;
/// <summary> /// <summary>
/// Gets/Sets whether to include XML documentation comments in the decompiled code /// Gets/Sets whether to include XML documentation comments in the decompiled code
/// </summary> /// </summary>
@ -319,7 +319,7 @@ namespace ICSharpCode.Decompiler
} }
bool foldBraces = false; bool foldBraces = false;
public bool FoldBraces { public bool FoldBraces {
get { return foldBraces; } get { return foldBraces; }
set { set {
@ -329,10 +329,10 @@ namespace ICSharpCode.Decompiler
} }
} }
} }
#region Options to aid VB decompilation #region Options to aid VB decompilation
bool introduceIncrementAndDecrement = true; bool introduceIncrementAndDecrement = true;
/// <summary> /// <summary>
/// Gets/Sets whether to use increment and decrement operators /// Gets/Sets whether to use increment and decrement operators
/// </summary> /// </summary>
@ -345,9 +345,9 @@ namespace ICSharpCode.Decompiler
} }
} }
} }
bool makeAssignmentExpressions = true; bool makeAssignmentExpressions = true;
/// <summary> /// <summary>
/// Gets/Sets whether to use assignment expressions such as in while ((count = Do()) != 0) ; /// Gets/Sets whether to use assignment expressions such as in while ((count = Do()) != 0) ;
/// </summary> /// </summary>
@ -360,9 +360,9 @@ namespace ICSharpCode.Decompiler
} }
} }
} }
bool alwaysGenerateExceptionVariableForCatchBlocks = false; bool alwaysGenerateExceptionVariableForCatchBlocks = false;
/// <summary> /// <summary>
/// Gets/Sets whether to always generate exception variables in catch blocks /// Gets/Sets whether to always generate exception variables in catch blocks
/// </summary> /// </summary>
@ -390,6 +390,20 @@ namespace ICSharpCode.Decompiler
#endregion #endregion
#region Options to aid F# decompilation
bool removeDeadCode = false;
public bool RemoveDeadCode {
get { return removeDeadCode; }
set {
if (removeDeadCode != value) {
removeDeadCode = value;
OnPropertyChanged();
}
}
}
#endregion
#region Assembly Load and Resolve options #region Assembly Load and Resolve options
bool loadInMemory = false; bool loadInMemory = false;
@ -419,7 +433,7 @@ namespace ICSharpCode.Decompiler
#endregion #endregion
CSharpFormattingOptions csharpFormattingOptions; CSharpFormattingOptions csharpFormattingOptions;
public CSharpFormattingOptions CSharpFormattingOptions { public CSharpFormattingOptions CSharpFormattingOptions {
get { get {
if (csharpFormattingOptions == null) { if (csharpFormattingOptions == null) {
@ -440,14 +454,14 @@ namespace ICSharpCode.Decompiler
} }
public event PropertyChangedEventHandler PropertyChanged; public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{ {
if (PropertyChanged != null) { if (PropertyChanged != null) {
PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
} }
} }
public DecompilerSettings Clone() public DecompilerSettings Clone()
{ {
DecompilerSettings settings = (DecompilerSettings)MemberwiseClone(); DecompilerSettings settings = (DecompilerSettings)MemberwiseClone();

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

@ -44,22 +44,24 @@ namespace ICSharpCode.Decompiler.IL.Transforms
// This is necessary to remove useless stores generated by some compilers, e.g., the F# compiler. // This is necessary to remove useless stores generated by some compilers, e.g., the F# compiler.
// In yield return + async, the C# compiler tends to store null/default(T) to variables // In yield return + async, the C# compiler tends to store null/default(T) to variables
// when the variable goes out of scope. // when the variable goes out of scope.
var variableQueue = new Queue<ILVariable>(function.Variables); if (function.IsAsync || function.IsIterator || context.Settings.RemoveDeadCode) {
while (variableQueue.Count > 0) { var variableQueue = new Queue<ILVariable>(function.Variables);
var v = variableQueue.Dequeue(); while (variableQueue.Count > 0) {
if (v.Kind != VariableKind.Local && v.Kind != VariableKind.StackSlot) var v = variableQueue.Dequeue();
continue; if (v.Kind != VariableKind.Local && v.Kind != VariableKind.StackSlot)
if (v.LoadCount != 0 || v.AddressCount != 0) continue;
continue; if (v.LoadCount != 0 || v.AddressCount != 0)
foreach (var stloc in v.StoreInstructions.OfType<StLoc>().ToArray()) { continue;
if (stloc.Parent is Block block) { foreach (var stloc in v.StoreInstructions.OfType<StLoc>().ToArray()) {
if (SemanticHelper.IsPure(stloc.Value.Flags)) { if (stloc.Parent is Block block) {
block.Instructions.Remove(stloc); if (SemanticHelper.IsPure(stloc.Value.Flags)) {
} else { block.Instructions.Remove(stloc);
stloc.ReplaceWith(stloc.Value); } else {
} stloc.ReplaceWith(stloc.Value);
if (stloc.Value is LdLoc ldloc) { }
variableQueue.Enqueue(ldloc.Variable); if (stloc.Value is LdLoc ldloc) {
variableQueue.Enqueue(ldloc.Variable);
}
} }
} }
} }

1
ILSpy/Options/DecompilerSettingsPanel.xaml

@ -14,5 +14,6 @@
<CheckBox IsChecked="{Binding ShowDebugInfo}">Show info from debug symbols, if available</CheckBox> <CheckBox IsChecked="{Binding ShowDebugInfo}">Show info from debug symbols, if available</CheckBox>
<CheckBox IsChecked="{Binding ShowXmlDocumentation}">Show XML documentation in decompiled code</CheckBox> <CheckBox IsChecked="{Binding ShowXmlDocumentation}">Show XML documentation in decompiled code</CheckBox>
<CheckBox IsChecked="{Binding FoldBraces}">Enable folding on all blocks in braces</CheckBox> <CheckBox IsChecked="{Binding FoldBraces}">Enable folding on all blocks in braces</CheckBox>
<CheckBox IsChecked="{Binding RemoveDeadCode}">Remove dead and side effect free code.</CheckBox>
</StackPanel> </StackPanel>
</UserControl> </UserControl>
Loading…
Cancel
Save