Merged PR 2785: make sure rewriting passes run in sequence

Related work items: #4890
This commit is contained in:
Pantazis Deligiannis 2020-07-23 20:07:08 +00:00
Родитель 890a1fea5e
Коммит 1fe995a56d
3 изменённых файлов: 52 добавлений и 70 удалений

Просмотреть файл

@ -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;
}