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;
            }
        }
Example #2
0
 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>();
 }
Example #3
0
        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))
            })
Example #4
0
        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);
        }