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()); }
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]); } }