Example #1
0
        public void Generate(TypeDef tDef)
        {
            EmitStaticStruct(MachineSpec.GetTypeName(tDef) + "_static", tDef.StaticSize);

            //TODO generate reference copies of objects

            for (int i = 0; i < tDef.StaticMethods.Length; i++)
            {
                GenerateMethod(tDef, tDef.StaticMethods[i]);
            }

            for (int i = 0; i < tDef.InstanceMethods.Length; i++)
            {
                GenerateMethod(tDef, tDef.InstanceMethods[i]);
            }

            Lines.AddRange(Emitter.GetLines());
        }
Example #2
0
        public void GenerateMethod(TypeDef tDef, MethodDef method)
        {
            prefix = MachineSpec.GetTypeName(tDef);
            var mthdName = MachineSpec.GetMethodName(method);

            if (mthdName == "ctor_System_Object_0System_Object_i_1System_Object_r_")
            {
                return;
            }

            for (int i = 0; i < method.Aliases.Count; i++)
            {
                Emitter.MakeGlobalFunction(method.Aliases[i]);
            }
            Emitter.MakeGlobalFunction(mthdName);

            if (method.IsConstructor && method.IsStatic)
            {
                static_ctors.Add(mthdName);
            }

            //Setup ArgumentTopOffset
            ArgumentTopOffset = MachineSpec.PointerSize * 2;

            //Setup LocalTopOffset
            ArgumentTopOffset += method.LocalsSize;
            LocalTopSize       = method.LocalsSize;
            LocalTopOffset     = 0;
            InstructionOffsets = new Queue <int>();

            Emitter.SubRegConst(AssemRegisters.Rsp, LocalTopSize);

            //Setup StackSpillOffset
            if (method.StackSize > 15)
            {
                throw new NotImplementedException();
            }

            //Convert the tokens into a more flexible form that is suited to optimization
            if (method.ByteCode == null)
            {
                return;
            }

            var tkns      = method.ByteCode.GetTokens();
            var mainGraph = new Graph <GraphNode <OptimizationToken> >();

            for (int i = 0; i < tkns.Length; i++)
            {
                InstructionOffsets.Enqueue(tkns[i].InstructionOffset);

                if (tkns[i].Operation == InstructionTypes.Nop)
                {
                    continue;
                }

                mainGraph.AddNode(new GraphNode <OptimizationToken>(tkns[i].ID, OptimizationTokenParser.Parse(tkns[i])));

                if (tkns[i].Parameters != null)
                {
                    for (int j = 0; j < tkns[i].Parameters.Length; j++)
                    {
                        mainGraph.AddDirectionalEdge(tkns[i].Parameters[j], tkns[i].ID);
                    }
                }
            }

            var subGraphs = mainGraph.FloodFill();

            //Get root nodes to propogate constant evaluations
            for (int i = 0; i < subGraphs.Length; i++)
            {
                var leaves = subGraphs[i].GetLeafNodes();

                for (int j = 0; j < leaves.Length; j++)
                {
                    SimplifyGraph(leaves[j], subGraphs[i]);
                }

                subGraphs[i].RemoveDisconnected();
            }


            //Propogate thunk registers through the graph
            var thunkSets = new Dictionary <AssemRegisters, List <int> > [subGraphs.Length];

            for (int i = 0; i < subGraphs.Length; i++)
            {
                Thunks = new Dictionary <AssemRegisters, List <int> >();
                var leaves = subGraphs[i].GetLeafNodes();

                for (int j = 0; j < leaves.Length; j++)
                {
                    ThunkRegisters(leaves[j], subGraphs[i]);
                }

                thunkSets[i] = Thunks;
            }

            //Propogate register preferences through the graph
            var registerSets      = new Dictionary <AssemRegisters, int> [subGraphs.Length];
            var registerInUseSets = new Dictionary <AssemRegisters, bool> [subGraphs.Length];

            for (int i = 0; i < subGraphs.Length; i++)
            {
                Thunks = thunkSets[i];

                RegisterAllocs = new Dictionary <AssemRegisters, int>();
                RegisterAllocs[AssemRegisters.Rax] = 0;
                RegisterAllocs[AssemRegisters.Rbx] = 0;
                RegisterAllocs[AssemRegisters.Rcx] = 0;
                RegisterAllocs[AssemRegisters.Rdx] = 0;
                RegisterAllocs[AssemRegisters.Rsi] = 0;
                RegisterAllocs[AssemRegisters.Rdi] = 0;
                RegisterAllocs[AssemRegisters.Rbp] = 0;
                RegisterAllocs[AssemRegisters.R8]  = 0;
                RegisterAllocs[AssemRegisters.R9]  = 0;
                RegisterAllocs[AssemRegisters.R10] = 0;
                RegisterAllocs[AssemRegisters.R11] = 0;
                RegisterAllocs[AssemRegisters.R12] = 0;
                RegisterAllocs[AssemRegisters.R13] = 0;
                RegisterAllocs[AssemRegisters.R14] = 0;
                RegisterAllocs[AssemRegisters.R15] = 0;

                RegisterInUse = new Dictionary <AssemRegisters, bool>();
                RegisterInUse[AssemRegisters.Rax] = false;
                RegisterInUse[AssemRegisters.Rbx] = false;
                RegisterInUse[AssemRegisters.Rcx] = false;
                RegisterInUse[AssemRegisters.Rdx] = false;
                RegisterInUse[AssemRegisters.Rsi] = false;
                RegisterInUse[AssemRegisters.Rdi] = false;
                RegisterInUse[AssemRegisters.Rbp] = false;
                RegisterInUse[AssemRegisters.R8]  = false;
                RegisterInUse[AssemRegisters.R9]  = false;
                RegisterInUse[AssemRegisters.R10] = false;
                RegisterInUse[AssemRegisters.R11] = false;
                RegisterInUse[AssemRegisters.R12] = false;
                RegisterInUse[AssemRegisters.R13] = false;
                RegisterInUse[AssemRegisters.R14] = false;
                RegisterInUse[AssemRegisters.R15] = false;

                var leaves = subGraphs[i].GetLeafNodes();

                for (int j = 0; j < leaves.Length; j++)
                {
                    PropogateRegisters(leaves[j], subGraphs[i]);
                }

                registerSets[i]      = RegisterAllocs;
                registerInUseSets[i] = RegisterInUse;
            }

            //Allocate registers, each subgraph has its own allocation set
            for (int i = 0; i < subGraphs.Length; i++)
            {
                RegisterAllocs = registerSets[i];
                RegisterInUse  = registerInUseSets[i];

                var nodes     = subGraphs[i].Nodes.Values.ToArray();
                var node_tkns = nodes.Select(a => a.Node.Token).ToArray();

                for (int j = 0; j < node_tkns.Length; j++)
                {
                    AllocateRegisters(node_tkns);
                }

                registerInUseSets[i] = RegisterInUse;
                registerSets[i]      = RegisterAllocs;
            }

#if DEBUG
            for (int i = 0; i < subGraphs.Length; i++)
            {
                Console.WriteLine($"Subgraph {i}");
                Console.WriteLine(subGraphs[i].ToString());
            }
#endif

            //Generate the assembly output
            for (int i = 0; i < subGraphs.Length; i++)
            {
                GenerateCode(subGraphs[i]);
            }
        }