Browse Source

Fix variable splitting for ldloca opcodes

pull/205/head
Pent Ploompuu 14 years ago
parent
commit
41e71ead8c
  1. 21
      ICSharpCode.Decompiler/ILAst/ILAstBuilder.cs

21
ICSharpCode.Decompiler/ILAst/ILAstBuilder.cs

@ -525,7 +525,11 @@ namespace ICSharpCode.Decompiler.ILAst
for(int variableIndex = 0; variableIndex < varCount; variableIndex++) { for(int variableIndex = 0; variableIndex < varCount; variableIndex++) {
// Find all stores and loads for this variable // Find all stores and loads for this variable
var stores = body.Where(b => (b.Code == ILCode.Stloc || b.Code == ILCode.Ldloca) && b.Operand is VariableDefinition && b.OperandAsVariable.Index == variableIndex).ToList(); var stores = body.Where(b => (b.Code == ILCode.Stloc || b.Code == ILCode.Ldloca) && b.Operand is VariableDefinition && b.OperandAsVariable.Index == variableIndex).ToList();
var loads = body.Where(b => (b.Code == ILCode.Ldloc || (b.Code == ILCode.Ldloca && b.Next.Code != ILCode.Initobj)) && b.Operand is VariableDefinition && b.OperandAsVariable.Index == variableIndex).ToList(); // ldloca on an uninitialized variable or followed by initobj isn't considered a load
var loads = body.Where(b =>
(b.Code == ILCode.Ldloc || (b.Code == ILCode.Ldloca && b.Next.Code != ILCode.Initobj &&
(b.VariablesBefore[variableIndex].StoredBy.Length != 0 || b.VariablesBefore[variableIndex].StoredByAll)))
&& b.Operand is VariableDefinition && b.OperandAsVariable.Index == variableIndex).ToList();
TypeReference varType = methodDef.Body.Variables[variableIndex].VariableType; TypeReference varType = methodDef.Body.Variables[variableIndex].VariableType;
List<VariableInfo> newVars; List<VariableInfo> newVars;
@ -545,9 +549,14 @@ namespace ICSharpCode.Decompiler.ILAst
}}; }};
} else { } else {
// Create a new variable for each store // Create a new variable for each store
newVars = stores.Where(st => st.Code == ILCode.Stloc || st.Next.Code == ILCode.Initobj).Select(st => new VariableInfo() { newVars = stores.Where(st =>
{
if (st.Code == ILCode.Stloc || st.Next.Code == ILCode.Initobj) return true;
var storedBy = st.VariablesBefore[variableIndex].StoredBy;
return storedBy.Length == 0 || storedBy[0] == st;
}).Select(st => new VariableInfo() {
Variable = new ILVariable() { Variable = new ILVariable() {
Name = "var_" + variableIndex + "_" + st.Offset.ToString("X2") + (st.Code == ILCode.Stloc ? null : "_default"), Name = "var_" + variableIndex + "_" + st.Offset.ToString("X2"),
Type = varType, Type = varType,
OriginalVariable = methodDef.Body.Variables[variableIndex] OriginalVariable = methodDef.Body.Variables[variableIndex]
}, },
@ -567,16 +576,16 @@ namespace ICSharpCode.Decompiler.ILAst
// Add loads to the data structure; merge variables if necessary // Add loads to the data structure; merge variables if necessary
foreach(ByteCode load in loads) { foreach(ByteCode load in loads) {
ByteCode[] storedBy = load.VariablesBefore[variableIndex].StoredBy; ByteCode[] storedBy = load.VariablesBefore[variableIndex].StoredBy;
if (storedBy.Length == 0 || storedBy[0] == load) { if (storedBy.Length == 0) {
// Load which always loads the default ('uninitialized') value // Load which always loads the default ('uninitialized') value
// Create a dummy variable just for this load // Create a dummy variable just for this load
newVars.Add(new VariableInfo() { newVars.Add(new VariableInfo() {
Variable = new ILVariable() { Variable = new ILVariable() {
Name = "var_" + variableIndex + "_" + load.Offset.ToString("X2") + (storedBy.Length == 0 ? "_default" : null), Name = "var_" + variableIndex + "_" + load.Offset.ToString("X2") + "_default",
Type = varType, Type = varType,
OriginalVariable = methodDef.Body.Variables[variableIndex] OriginalVariable = methodDef.Body.Variables[variableIndex]
}, },
Stores = load.Code == ILCode.Ldloc ? new List<ByteCode>() : new List<ByteCode>() { load }, Stores = new List<ByteCode>(),
Loads = new List<ByteCode>() { load } Loads = new List<ByteCode>() { load }
}); });
} else if (storedBy.Length == 1) { } else if (storedBy.Length == 1) {

Loading…
Cancel
Save