예제 #1
0
        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()));
        }
예제 #2
0
        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());
        }
예제 #3
0
        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));
        }
예제 #4
0
 public CompiledAssembly(IEnumerable <CompiledType> types, CompiledSubroutine entryPoint)
 {
     Types      = types;
     EntryPoint = entryPoint;
 }