Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/cecil.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVitek Karas <vitek.karas@microsoft.com>2020-07-24 01:01:43 +0300
committerGitHub <noreply@github.com>2020-07-24 01:01:43 +0300
commit5e37f44535e0753ff3e4dbdef4ef148ca8bb09e0 (patch)
treef462504d65aab086df9fda33ae0f1d9b4b85819a /Mono.Cecil.Cil
parentcd450b0f09615c0e1e9c6663bbf7ae00ad96a7bc (diff)
Automatically update local variable debug info (#676)
* Automatically update local variable debug info When manipulating the local variables collection on a method body, automatically update the debug info for all affected local variables. When removing a local variable, also remove the debug info for that local variable from the scopes. When removing or inserting update the indeces of local variable debug infos which are afected by the action. Note the local variable debug info either holds just a backpointer to the local variable in which case it doesn't store the index at all (and thus nothing to do), or it stores the index explicitly in which case it needs to be updated. Added tests for both insert and remove cases. * Add internal properties on `VariableOffset` to make it easier to manipulate it. Reworked the `UpdateVariableIndeces` to only loop over variables once and also to handle removal of resolved variable debug infos. * Simplify the code a little and add comments * PR feedback
Diffstat (limited to 'Mono.Cecil.Cil')
-rw-r--r--Mono.Cecil.Cil/CodeReader.cs2
-rw-r--r--Mono.Cecil.Cil/MethodBody.cs55
-rw-r--r--Mono.Cecil.Cil/Symbols.cs4
3 files changed, 52 insertions, 9 deletions
diff --git a/Mono.Cecil.Cil/CodeReader.cs b/Mono.Cecil.Cil/CodeReader.cs
index ac5b31b..89515d6 100644
--- a/Mono.Cecil.Cil/CodeReader.cs
+++ b/Mono.Cecil.Cil/CodeReader.cs
@@ -132,7 +132,7 @@ namespace Mono.Cecil.Cil {
public VariableDefinitionCollection ReadVariables (MetadataToken local_var_token)
{
var position = reader.position;
- var variables = reader.ReadVariables (local_var_token);
+ var variables = reader.ReadVariables (local_var_token, method);
reader.position = position;
return variables;
diff --git a/Mono.Cecil.Cil/MethodBody.cs b/Mono.Cecil.Cil/MethodBody.cs
index df96849..0b5692d 100644
--- a/Mono.Cecil.Cil/MethodBody.cs
+++ b/Mono.Cecil.Cil/MethodBody.cs
@@ -81,7 +81,7 @@ namespace Mono.Cecil.Cil {
public Collection<VariableDefinition> Variables {
get {
if (variables == null)
- Interlocked.CompareExchange (ref variables, new VariableDefinitionCollection (), null);
+ Interlocked.CompareExchange (ref variables, new VariableDefinitionCollection (this.method), null);
return variables;
}
@@ -134,13 +134,17 @@ namespace Mono.Cecil.Cil {
sealed class VariableDefinitionCollection : Collection<VariableDefinition> {
- internal VariableDefinitionCollection ()
+ readonly MethodDefinition method;
+
+ internal VariableDefinitionCollection (MethodDefinition method)
{
+ this.method = method;
}
- internal VariableDefinitionCollection (int capacity)
+ internal VariableDefinitionCollection (MethodDefinition method, int capacity)
: base (capacity)
{
+ this.method = method;
}
protected override void OnAdd (VariableDefinition item, int index)
@@ -151,9 +155,7 @@ namespace Mono.Cecil.Cil {
protected override void OnInsert (VariableDefinition item, int index)
{
item.index = index;
-
- for (int i = index; i < size; i++)
- items [i].index = i + 1;
+ UpdateVariableIndices (index, 1);
}
protected override void OnSet (VariableDefinition item, int index)
@@ -163,10 +165,47 @@ namespace Mono.Cecil.Cil {
protected override void OnRemove (VariableDefinition item, int index)
{
+ UpdateVariableIndices (index + 1, -1, item);
item.index = -1;
+ }
- for (int i = index + 1; i < size; i++)
- items [i].index = i - 1;
+ void UpdateVariableIndices (int startIndex, int offset, VariableDefinition variableToRemove = null)
+ {
+ for (int i = startIndex; i < size; i++)
+ items [i].index = i + offset;
+
+ var debug_info = method == null ? null : method.debug_info;
+ if (debug_info == null || debug_info.Scope == null)
+ return;
+
+ foreach (var scope in debug_info.GetScopes ()) {
+ if (!scope.HasVariables)
+ continue;
+
+ var variables = scope.Variables;
+ int variableDebugInfoIndexToRemove = -1;
+ for (int i = 0; i < variables.Count; i++) {
+ var variable = variables [i];
+
+ // If a variable is being removed detect if it has debug info counterpart, if so remove that as well.
+ // Note that the debug info can be either resolved (has direct reference to the VariableDefinition)
+ // or unresolved (has only the number index of the variable) - this needs to handle both cases.
+ if (variableToRemove != null &&
+ ((variable.index.IsResolved && variable.index.ResolvedVariable == variableToRemove) ||
+ (!variable.index.IsResolved && variable.Index == variableToRemove.Index))) {
+ variableDebugInfoIndexToRemove = i;
+ continue;
+ }
+
+ // For unresolved debug info updates indeces to keep them pointing to the same variable.
+ if (!variable.index.IsResolved && variable.Index >= startIndex) {
+ variable.index = new VariableIndex (variable.Index + offset);
+ }
+ }
+
+ if (variableDebugInfoIndexToRemove >= 0)
+ variables.RemoveAt (variableDebugInfoIndexToRemove);
+ }
}
}
diff --git a/Mono.Cecil.Cil/Symbols.cs b/Mono.Cecil.Cil/Symbols.cs
index 59a2bec..38b47a4 100644
--- a/Mono.Cecil.Cil/Symbols.cs
+++ b/Mono.Cecil.Cil/Symbols.cs
@@ -248,6 +248,10 @@ namespace Mono.Cecil.Cil {
}
}
+ internal bool IsResolved => variable != null;
+
+ internal VariableDefinition ResolvedVariable => variable;
+
public VariableIndex (VariableDefinition variable)
{
if (variable == null)