Example #1
0
        private ImmutableGraph <ProcessedSubroutine> CreateCallGraph(ProcessedType processedType)
        {
            var graph = ImmutableGraph <ProcessedSubroutine> .Empty;

            foreach (var subroutine in processedType.Subroutines)
            {
                graph = graph.AddNode(subroutine);
            }

            foreach (var subroutine in processedType.Subroutines)
            {
                var calls = subroutine.MethodDefinition.Body.Instructions
                            .Where(i => i.OpCode == OpCodes.Call)
                            .Select(i => i.Operand)
                            .OfType <MethodDefinition>()
                            .Where(md => processedType.Subroutines.Any(s => s.MethodDefinition == md))
                            .Select(md => processedType.Subroutines.Single(s => s.MethodDefinition == md));

                foreach (var call in calls)
                {
                    graph = graph.AddEdge(subroutine, call);
                }
            }

            return(graph);
        }
Example #2
0
 public CompiledType(ProcessedType processedType, IImmutableList <CompiledSubroutine> compiledSubroutines)
     : base(processedType, compiledSubroutines)
 {
     if (compiledSubroutines.Count() != processedType.Subroutines.Count())
     {
         throw new FatalCompilationException($"Can not create CompiledType '{processedType.FullName}' with {compiledSubroutines.Count()} CompiledSubroutines because it has {processedType.Subroutines.Count()} ProcessedSubroutines!");
     }
 }
Example #3
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()));
        }
Example #4
0
 public ProcessedType(
     TypeDefinition typeDefinition,
     ProcessedType baseType,
     IEnumerable <ProcessedField> fields,
     IImmutableDictionary <ProcessedField, byte> fieldOffsets,
     IImmutableList <ProcessedSubroutine> subroutines,
     int?size             = null,
     bool allowedAsLValue = true)
 {
     BaseType        = baseType;
     TypeDefinition  = typeDefinition;
     Fields          = fields;
     FieldOffsets    = fieldOffsets;
     Subroutines     = subroutines;
     AllowedAsLValue = allowedAsLValue;
     ThisSize        = size ?? Fields.Sum(pf => pf.FieldType.TotalSize);
 }
Example #5
0
 public ProcessedSubroutine(
     MethodDefinition methodDefinition,
     ControlFlowGraph controlFlowGraph,
     bool isEntryPoint,
     ProcessedType returnType,
     IList <ProcessedType> parameters,
     IList <ProcessedType> locals,
     IEnumerable <Attribute> frameworkAttributes)
 {
     MethodDefinition    = methodDefinition;
     ControlFlowGraph    = controlFlowGraph;
     IsEntryPoint        = isEntryPoint;
     ReturnType          = returnType;
     Parameters          = parameters;
     Locals              = locals;
     FrameworkAttributes = frameworkAttributes;
 }
Example #6
0
 protected ProcessedType(ProcessedType processedType, IImmutableList <CompiledSubroutine> compiledSubroutines)
     : this(processedType.TypeDefinition, processedType.BaseType, processedType.Fields, processedType.FieldOffsets, compiledSubroutines.Cast <ProcessedSubroutine>().ToImmutableList(), processedType.ThisSize, processedType.AllowedAsLValue)
 {
 }
Example #7
0
 public ProcessedField(FieldDefinition fieldDefinition, ProcessedType fieldType)
 {
     FieldDefinition = fieldDefinition;
     FieldType       = fieldType;
 }