Merged PR 2785: make sure rewriting passes run in sequence
Related work items: #4890
This commit is contained in:
Родитель
890a1fea5e
Коммит
1fe995a56d
|
@ -58,8 +58,8 @@ namespace Microsoft.Coyote.Rewriting
|
|||
|
||||
this.Transforms = new List<AssemblyTransform>()
|
||||
{
|
||||
new TaskTransform(),
|
||||
new MonitorTransform()
|
||||
new TaskTransform(),
|
||||
new MonitorTransform()
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -111,10 +111,14 @@ namespace Microsoft.Coyote.Rewriting
|
|||
}
|
||||
|
||||
Console.WriteLine($"... Rewriting the '{assemblyName}' assembly ({assembly.FullName})");
|
||||
foreach (var module in assembly.Modules)
|
||||
foreach (var transform in this.Transforms)
|
||||
{
|
||||
Debug.WriteLine($"..... Rewriting the '{module.Name}' module ({module.FileName})");
|
||||
this.RewriteModule(module);
|
||||
// Traverse the assembly to apply each transformation pass.
|
||||
Debug.WriteLine($"..... Applying the '{transform.GetType().Name}' transform");
|
||||
foreach (var module in assembly.Modules)
|
||||
{
|
||||
RewriteModule(module, transform);
|
||||
}
|
||||
}
|
||||
|
||||
// Write the binary in the output path with portable symbols enabled.
|
||||
|
@ -138,68 +142,51 @@ namespace Microsoft.Coyote.Rewriting
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Rewrites the specified module definition.
|
||||
/// Rewrites the specified module definition using the specified transform.
|
||||
/// </summary>
|
||||
private void RewriteModule(ModuleDefinition module)
|
||||
private static void RewriteModule(ModuleDefinition module, AssemblyTransform transform)
|
||||
{
|
||||
foreach (var t in this.Transforms)
|
||||
{
|
||||
t.VisitModule(module);
|
||||
}
|
||||
|
||||
Debug.WriteLine($"....... Module: {module.Name} ({module.FileName})");
|
||||
transform.VisitModule(module);
|
||||
foreach (var type in module.GetTypes())
|
||||
{
|
||||
this.RewriteType(type);
|
||||
RewriteType(type, transform);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Rewrites the specified type definition.
|
||||
/// Rewrites the specified type definition using the specified transform.
|
||||
/// </summary>
|
||||
private void RewriteType(TypeDefinition type)
|
||||
private static void RewriteType(TypeDefinition type, AssemblyTransform transform)
|
||||
{
|
||||
Debug.WriteLine($"..... Rewriting type '{type.FullName}'");
|
||||
|
||||
foreach (var t in this.Transforms)
|
||||
{
|
||||
t.VisitType(type);
|
||||
}
|
||||
|
||||
Debug.WriteLine($"......... Type: {type.FullName}");
|
||||
transform.VisitType(type);
|
||||
foreach (var field in type.Fields)
|
||||
{
|
||||
foreach (var t in this.Transforms)
|
||||
{
|
||||
t.VisitField(field);
|
||||
}
|
||||
Debug.WriteLine($"........... Field: {field.FullName}");
|
||||
transform.VisitField(field);
|
||||
}
|
||||
|
||||
foreach (var method in type.Methods)
|
||||
{
|
||||
this.RewriteMethod(method);
|
||||
RewriteMethod(method, transform);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Rewrites the specified method definition.
|
||||
/// Rewrites the specified method definition using the specified transform.
|
||||
/// </summary>
|
||||
private void RewriteMethod(MethodDefinition method)
|
||||
private static void RewriteMethod(MethodDefinition method, AssemblyTransform transform)
|
||||
{
|
||||
Debug.WriteLine($"....... Rewriting method '{method.FullName}'");
|
||||
|
||||
foreach (var t in this.Transforms)
|
||||
{
|
||||
t.VisitMethod(method);
|
||||
}
|
||||
Debug.WriteLine($"........... Method {method.FullName}");
|
||||
transform.VisitMethod(method);
|
||||
|
||||
// Only non-abstract method bodies can be rewritten.
|
||||
if (!method.IsAbstract)
|
||||
{
|
||||
foreach (var variable in method.Body.Variables)
|
||||
{
|
||||
foreach (var t in this.Transforms)
|
||||
{
|
||||
t.VisitVariable(variable);
|
||||
}
|
||||
transform.VisitVariable(variable);
|
||||
}
|
||||
|
||||
// Do exception handlers before the method instructions because they are a
|
||||
|
@ -207,25 +194,18 @@ namespace Microsoft.Coyote.Rewriting
|
|||
// raw instructions.
|
||||
if (method.Body.HasExceptionHandlers)
|
||||
{
|
||||
foreach (var t in this.Transforms)
|
||||
foreach (var handler in method.Body.ExceptionHandlers)
|
||||
{
|
||||
foreach (var handler in method.Body.ExceptionHandlers)
|
||||
{
|
||||
t.VisitExceptionHandler(handler);
|
||||
}
|
||||
transform.VisitExceptionHandler(handler);
|
||||
}
|
||||
}
|
||||
|
||||
// in this case run each transform as separate passes over the method body
|
||||
// so they don't trip over each other's edits.
|
||||
foreach (var t in this.Transforms)
|
||||
// Rewrite the method body instructions.
|
||||
Instruction instruction = method.Body.Instructions.FirstOrDefault();
|
||||
while (instruction != null)
|
||||
{
|
||||
Instruction instruction = method.Body.Instructions.FirstOrDefault();
|
||||
while (instruction != null)
|
||||
{
|
||||
instruction = t.VisitInstruction(instruction);
|
||||
instruction = instruction.Next;
|
||||
}
|
||||
instruction = transform.VisitInstruction(instruction);
|
||||
instruction = instruction.Next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -74,9 +74,9 @@ namespace Microsoft.Coyote.Rewriting
|
|||
{
|
||||
// Since the method parameters match there's no need to modify the parameter setup code
|
||||
// we can simply switch out the call.
|
||||
Debug.WriteLine($"......... [-] call '{method}'");
|
||||
Debug.WriteLine($"............. [-] call '{method}'");
|
||||
var newInstruction = Instruction.Create(OpCodes.Call, newMethod);
|
||||
Debug.WriteLine($"......... [+] call '{newMethod}'");
|
||||
Debug.WriteLine($"............. [+] call '{newMethod}'");
|
||||
this.Processor.Replace(instruction, newInstruction);
|
||||
instruction = newInstruction;
|
||||
}
|
||||
|
@ -108,7 +108,7 @@ namespace Microsoft.Coyote.Rewriting
|
|||
}
|
||||
}
|
||||
|
||||
Debug.WriteLine($"......... [?] Monitor method not found '{monitorMethod}'");
|
||||
Debug.WriteLine($"............. [?] Monitor method not found '{monitorMethod}'");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -89,9 +89,9 @@ namespace Microsoft.Coyote.Rewriting
|
|||
{
|
||||
if (this.TryRewriteCompilerType(field.FieldType, out TypeReference newFieldType))
|
||||
{
|
||||
Debug.WriteLine($"....... [-] field '{field}'");
|
||||
Debug.WriteLine($"............. [-] field '{field}'");
|
||||
field.FieldType = newFieldType;
|
||||
Debug.WriteLine($"....... [+] field '{field}'");
|
||||
Debug.WriteLine($"............. [+] field '{field}'");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -114,9 +114,9 @@ namespace Microsoft.Coyote.Rewriting
|
|||
// but good to understand what that entails and give warnings/errors perhaps: work item #4678
|
||||
if (this.TryRewriteCompilerType(method.ReturnType, out TypeReference newReturnType))
|
||||
{
|
||||
Debug.WriteLine($"......... [-] return type '{method.ReturnType}'");
|
||||
Debug.WriteLine($"............. [-] return type '{method.ReturnType}'");
|
||||
method.ReturnType = newReturnType;
|
||||
Debug.WriteLine($"......... [+] return type '{method.ReturnType}'");
|
||||
Debug.WriteLine($"............. [+] return type '{method.ReturnType}'");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -130,9 +130,9 @@ namespace Microsoft.Coyote.Rewriting
|
|||
|
||||
if (this.TryRewriteCompilerType(variable.VariableType, out TypeReference newVariableType))
|
||||
{
|
||||
Debug.WriteLine($"......... [-] variable '{variable.VariableType}'");
|
||||
Debug.WriteLine($"............. [-] variable '{variable.VariableType}'");
|
||||
variable.VariableType = newVariableType;
|
||||
Debug.WriteLine($"......... [+] variable '{variable.VariableType}'");
|
||||
Debug.WriteLine($"............. [+] variable '{variable.VariableType}'");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -152,16 +152,16 @@ namespace Microsoft.Coyote.Rewriting
|
|||
if (instruction.Operand is FieldDefinition fd &&
|
||||
this.TryRewriteCompilerType(fd.FieldType, out TypeReference newFieldType))
|
||||
{
|
||||
Debug.WriteLine($"......... [-] {instruction}");
|
||||
Debug.WriteLine($"........... [-] {instruction}");
|
||||
fd.FieldType = newFieldType;
|
||||
Debug.WriteLine($"......... [+] {instruction}");
|
||||
Debug.WriteLine($"........... [+] {instruction}");
|
||||
}
|
||||
else if (instruction.Operand is FieldReference fr &&
|
||||
this.TryRewriteCompilerType(fr.FieldType, out newFieldType))
|
||||
{
|
||||
Debug.WriteLine($"......... [-] {instruction}");
|
||||
Debug.WriteLine($"........... [-] {instruction}");
|
||||
fr.FieldType = newFieldType;
|
||||
Debug.WriteLine($"......... [+] {instruction}");
|
||||
Debug.WriteLine($"........... [+] {instruction}");
|
||||
}
|
||||
}
|
||||
else if (instruction.OpCode == OpCodes.Initobj)
|
||||
|
@ -187,9 +187,11 @@ namespace Microsoft.Coyote.Rewriting
|
|||
if (this.TryRewriteCompilerType(type, out TypeReference newType))
|
||||
{
|
||||
var newInstruction = Instruction.Create(instruction.OpCode, newType);
|
||||
Debug.WriteLine($"......... [-] {instruction}");
|
||||
newInstruction.Offset = instruction.Offset;
|
||||
|
||||
Debug.WriteLine($"............. [-] {instruction}");
|
||||
this.Processor.Replace(instruction, newInstruction);
|
||||
Debug.WriteLine($"......... [+] {newInstruction}");
|
||||
Debug.WriteLine($"............. [+] {newInstruction}");
|
||||
instruction = newInstruction;
|
||||
}
|
||||
|
||||
|
@ -222,9 +224,9 @@ namespace Microsoft.Coyote.Rewriting
|
|||
Instruction newInstruction = Instruction.Create(resolvedMethod.IsVirtual ? OpCodes.Callvirt : OpCodes.Call, newMethod);
|
||||
newInstruction.Offset = instruction.Offset;
|
||||
|
||||
Debug.WriteLine($"......... [-] {instruction}");
|
||||
Debug.WriteLine($"............. [-] {instruction}");
|
||||
this.Processor.Replace(instruction, newInstruction);
|
||||
Debug.WriteLine($"......... [+] {newInstruction}");
|
||||
Debug.WriteLine($"............. [+] {newInstruction}");
|
||||
return newInstruction;
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче