private CompiledType CompileType(ProcessedType processedType) { var compiledSubroutines = new List <CompiledSubroutine>(); var callGraph = CreateCallGraph(processedType); var compilationOrder = callGraph.TopologicalSort(); foreach (var subroutine in compilationOrder) { Console.WriteLine($"Compiling {subroutine.FullName}"); if (subroutine.TryGetFrameworkAttribute <UseProvidedImplementationAttribute>(out var providedImplementation)) { var implementationDefinition = processedType.TypeDefinition.Methods.Single(m => m.Name == providedImplementation.ImplementationName); var implementation = FrameworkAssembly.GetType(processedType.FullName, true).GetTypeInfo().GetMethod(implementationDefinition.Name, BindingFlags.Static | BindingFlags.NonPublic); var compiledBody = (IEnumerable <AssemblyLine>)implementation.Invoke(null, null); compiledSubroutines.Add(new CompiledSubroutine(subroutine, compiledBody)); Console.WriteLine($"Implementation provided by '{implementationDefinition.FullName}':"); foreach (var line in compiledBody) { Console.WriteLine(line); } continue; } foreach (var line in subroutine.MethodDefinition.Body.Instructions) { Console.WriteLine(line); } Console.WriteLine("v Compile v"); IEnumerable <AssemblyLine> body; if (subroutine.TryGetFrameworkAttribute <IgnoreImplementationAttribute>(out _)) { body = Enumerable.Empty <AssemblyLine>(); Console.WriteLine($"Skipping CIL compilation due to {nameof(IgnoreImplementationAttribute)}, assuming an empty subroutine body."); } else { body = CilCompiler.CompileMethod(subroutine.MethodDefinition, Types.ToImmutableDictionary(), FrameworkAssembly); } if (subroutine.IsEntryPoint) { Console.WriteLine("Injecting entry point code."); body = GetEntryPointPrependedCode().Concat(body); } var compiledSubroutine = new CompiledSubroutine(subroutine, body); compiledSubroutines.Add(compiledSubroutine); Types[processedType.FullName] = Types[processedType.FullName].ReplaceSubroutine(subroutine, compiledSubroutine); Console.WriteLine($"{subroutine.FullName}, compilation finished"); } return(new CompiledType(processedType, compiledSubroutines.ToImmutableList())); }
private static IEnumerable <AssemblyLine> CreateEntryPoint(CompiledSubroutine entryPoint) { yield return(Comment($"Entry point '{entryPoint.FullName}':", 0)); yield return(Subroutine(EntryPoint)); foreach (var line in entryPoint.Body) { yield return(line); } yield return(Comment("End entry point code.", 0)); yield return(BlankLine()); }
public ProcessedType ReplaceSubroutine(ProcessedSubroutine oldSubroutine, CompiledSubroutine newSubroutine) { var finalSubroutines = new List <ProcessedSubroutine>(Subroutines); var oldSubroutineToRemove = finalSubroutines.Single(s => s.MethodDefinition == oldSubroutine.MethodDefinition); finalSubroutines.Remove(oldSubroutineToRemove); finalSubroutines.Add(newSubroutine); return(new ProcessedType( TypeDefinition, BaseType, Fields, FieldOffsets, finalSubroutines.ToImmutableList(), ThisSize, AllowedAsLValue)); }
public CompiledAssembly(IEnumerable <CompiledType> types, CompiledSubroutine entryPoint) { Types = types; EntryPoint = entryPoint; }