Example #1
0
        public static RomInfo CreateRom(CompiledProgram program, string assemblerPath)
        {
            var memoryManager = new MemoryManager(program);
            var lines         = new List <AssemblyLine>();

            lines.AddRange(CreateHeader());
            lines.AddRange(CreateStaticVariables(program.Types, memoryManager));
            lines.AddRange(CreateEntryPoint(program.EntryPoint));
            lines.AddRange(CreateMethods(program));
            lines.AddRange(CreateInterruptVectors());

            File.WriteAllLines(AssemblyFileName, lines.Select(l => l.ToString()));
            var assembled = AssembleOutput(assemblerPath);

            return(new RomInfo(assembled,
                               Path.GetFullPath(BinaryFileName),
                               Path.GetFullPath(AssemblyFileName),
                               Path.GetFullPath(SymbolsFileName),
                               Path.GetFullPath(ListFileName)));
        }
Example #2
0
        private static IEnumerable <AssemblyLine> CreateMethods(CompiledProgram program)
        {
            var nodes   = program.CallGraph.AllNodes;
            var methods = program.Types.SelectMany(t => t.Subroutines)
                          .Where(s => s != program.EntryPoint)
                          .Where(s => s.Body.Any())                                   // Don't emit empty methods.
                          .Where(s => nodes.Any(n => n.Value == s.MethodDefinition)); // Don't emit methods that are never called.

            yield return(Comment("Begin subroutine emit.", 0));

            yield return(BlankLine());

            foreach (var method in methods)
            {
                // Do not emit subroutines that will never be JSR'd.
                if (method.TryGetFrameworkAttribute <AlwaysInlineAttribute>(out _))
                {
                    continue;
                }
                foreach (var line in CreateMethod(method))
                {
                    yield return(line);
                }
            }
            yield return(Comment("End subroutine emit.", 0));

            yield return(BlankLine());

            IEnumerable <AssemblyLine> CreateMethod(CompiledSubroutine subroutine)
            {
                yield return(Comment(subroutine.MethodDefinition.ToString(), 0));

                yield return(Label(LabelGenerator.GetFromMethod(subroutine.MethodDefinition)));

                foreach (var line in subroutine.Body)
                {
                    yield return(line);
                }
                yield return(BlankLine());
            }
        }
Example #3
0
        public static Task <RomInfo> CompileFromFiles(IEnumerable <string> filePaths, string frameworkPath, string dasmPath)
        {
            if (filePaths == null)
            {
                throw new ArgumentNullException(nameof(filePaths));
            }
            else if (!filePaths.Any())
            {
                throw new ArgumentException("No source files specified.", nameof(filePaths));
            }

            if (frameworkPath == null)
            {
                throw new ArgumentNullException(nameof(frameworkPath));
            }
            else if (string.IsNullOrWhiteSpace(frameworkPath))
            {
                throw new ArgumentException("VCS framework DLL path must be specified.", nameof(frameworkPath));
            }

            // TODO - No DASM path should mean the caller just wants the assembly output, not a compiled binary.

            var compilation         = CompilationCreator.CreateFromFilePaths(filePaths);
            var assemblyDefinition  = GetAssemblyDefinition(compilation, out var assemblyStream);
            var frameworkAssembly   = System.Reflection.Assembly.Load(new AssemblyName(Path.GetFileNameWithoutExtension(frameworkPath)));
            var frameworkAttributes = frameworkAssembly.ExportedTypes.Where(t => t.GetTypeInfo().BaseType == typeof(Attribute));
            var compiler            = new Compiler(frameworkAssembly, assemblyDefinition, frameworkAttributes.ToArray());

            compiler.AddPredefinedTypes();
            var frameworkCompiledAssembly = CompileAssembly(compiler, AssemblyDefinition.ReadAssembly(frameworkPath, new ReaderParameters {
                ReadSymbols = true
            }));
            var userCompiledAssembly = CompileAssembly(compiler, assemblyDefinition);
            var callGraph            = CallGraph.CreateFromEntryMethod(userCompiledAssembly.EntryPoint);
            var program = new CompiledProgram(new[] { frameworkCompiledAssembly, userCompiledAssembly }, callGraph);
            var romInfo = RomCreator.CreateRom(program, dasmPath);

            return(Task.FromResult(romInfo));
        }
Example #4
0
 public MemoryManager(CompiledProgram program)
 {
     Program    = program;
     AllSymbols = AddPredefinedGlobals().Concat(LayoutGlobals()).Concat(AllocateLocalAddresses(program.CallGraph));
 }