private IEnumerable <ProcedureCompilation> CompileDeclaration(IDeclaration declaration) { switch (declaration) { case NamespaceDeclaration decl: foreach (var compilation in decl.Declarations.SelectMany(CompileDeclaration)) { yield return(compilation); } break; case Procedure procedure: var(transformed, parameters) = Transformer.TransformProcedureStatement(procedure.EntryPoint, procedure.Parameters); var cfg = CFGNode.ConstructCFG(transformed); LivenessAnalysis.PerformAnalysis(cfg); var allocation = RegisterAllocation.Generate(cfg, parameters .Select((x, i) => (x, i)).Where(x => x.i != 1).ToDictionary( x => x.x, x => ProcedureCompilation.ParameterLocation(x.i))); yield return(new ProcedureCompilation(procedure, parameters, transformed, ConstantTable, FalseConstant, TrueConstant, allocation)); break; case ProcedureImport import: Externs.Add(import.Name); Imports.Add(import.ImportedName); break; } }
public CodegenEmitter( Mono.Cecil.Cil.ILProcessor processor, RegisterAllocation <CilCodegenRegister> registerAllocation) { this.Processor = processor; this.RegisterAllocation = registerAllocation; this.branchTargets = new Dictionary <BasicBlockTag, CilInstruction>(); this.pendingTargets = new List <BasicBlockTag>(); this.patches = new List <CilOpInstruction>(); this.registerUseCounters = new Dictionary <Mono.Cecil.Cil.VariableDefinition, int>(); }
private IEnumerable <NasmInstruction> CompileInstruction(int i, IInstruction instruction) { yield return(NasmInstruction.Comment(instruction.ToString())); yield return(NasmInstruction.Comment("In = { " + string.Join(", ", RegisterAllocation.GetAllInAt(i)) + " }")); foreach (var inst in instruction switch { UnaryComputationAssignment inst => CompileCore(inst), BinaryComputationAssignment inst => CompileCore(inst), ConditionalJump inst => CompileCore(inst), UnconditionalJump inst => CompileCore(inst), LabelInstruction inst => CompileCore(inst), CallInstruction inst => CompileCore(i, inst), ReturnInstruction inst => CompileCore(inst), ParameterQueryAssignment inst => CompileCore(inst), _ => throw new ArgumentException(nameof(instruction)) })
public ProcedureCompilation( Procedure procedure, List <Variable> parameters, List <IInstruction> instructions, Dictionary <Constant, DataLocation> constantTable, DataLocation falseConstant, DataLocation trueConstant, RegisterAllocation registerAllocation) { Procedure = procedure; Parameters = parameters; Instructions = instructions; ConstantTable = constantTable; FalseConstant = falseConstant; TrueConstant = trueConstant; RegisterAllocation = registerAllocation; StackRegisterTemporary = Align(RegisterAllocation.StackOffset); var calls = Instructions .Select((x, i) => (x, i)) // Get all CallInstructions with their indicies .Where(x => x.x is CallInstruction) .Select(x => (Call: (CallInstruction)x.x, Index: x.i)) .ToList(); int maxCallDeposit = calls.Count > 0 ? // Check how many variables are live at the instruction and get the max calls.Max(x => RegisterAllocation.GetAllInAt(x.Index).Count()) : 0; StackHomeSpace = Align(StackRegisterTemporary + (maxCallDeposit * 8)); int maxParameters = calls.Count > 0 ? calls.Max(x => Math.Max(0, x.Call.Parameters.Count - 4)) // - 4 since the first 4 parameters are saved in registers : 0; StackEnd = StackHomeSpace + 32 + Align(maxParameters * 8); }