コード例 #1
0
        public override void PostConditionalVisit(IfStat ifStat)
        {
            string elseIdentifier = $"else_{ifStat.Location.line}_{ifStat.Location.column}";

            this.Load(ifStat.Condition, "r1");
            InstructionStream.Add($"bz r1, {elseIdentifier}", $"If {ifStat.Condition}.");
        }
コード例 #2
0
        public override void PostForLoopConditionalVisit(ForStat forStat)
        {
            string endForIdentifier = $"endfor_{forStat.Location.line}_{forStat.Location.column}";

            this.Load(forStat.Condition, "r1");
            InstructionStream.Add($"bz r1, {endForIdentifier}");
        }
コード例 #3
0
        public void SubVisit(FCall fCall)
        {
            int stackFrameSize = this.FunctionScope.GetStackFrameSize();
            var scope          = this.GlobalScope.Get(fCall.Id, Classification.Function)?.Link;

            if (scope == null)
            {
                string inheritedClass = fCall.Id.Split(':')[0];
                string functionName   = fCall.Id.Split(':').Last();

                scope = this.GlobalScope.Get(inheritedClass, Classification.Class)?.Link;
                var functionEntry = scope.Get(functionName, Classification.Function);

                string newLink = $"{functionEntry.OriginalFunctionOwner}::{functionName}";
                scope    = this.GlobalScope.Get(newLink, Classification.Function).Link;
                fCall.Id = newLink;
            }

            int paramOffset = stackFrameSize + 4 + scope.Get("retval", Classification.SubCalculationStackSpace).EntryMemorySize;

            foreach (var expression in fCall.Parameters.Expressions)
            {
                this.LoadAndStore(expression, paramOffset, expression.NodeMemorySize, $"Passing parameter {expression}");
                paramOffset += expression.NodeMemorySize;
            }

            InstructionStream.Add($"addi r14, r14, {stackFrameSize}");
            InstructionStream.Add($"jl r15, function_{fCall.Id.Replace(':', '_')}", $"Call the function {fCall.Id}");
            InstructionStream.Add($"subi r14, r14, {stackFrameSize}");


            this.LoadAndStore(stackFrameSize + 4, fCall, fCall.NodeMemorySize, "Retrieve the returnvalue");
        }
コード例 #4
0
 public override void Visit(FuncDef funcDef)
 {
     InstructionStream.Add(new string[] {
         "lw r15, 0(r14)",
         "jr r15"
     }, "Load the return address, and return.");
 }
コード例 #5
0
        public override void PreVisit(MainStatBlock mainStatBlock)
        {
            this.FunctionScope      = GlobalScope.Get("main", Classification.Function).Link;
            this.ClassInstanceScope = new SymbolTable();

            InstructionStream.Add("entry");
        }
コード例 #6
0
        public override void PreElseBlockVisit(IfStat ifStat)
        {
            string elseIdentifier  = $"else_{ifStat.Location.line}_{ifStat.Location.column}";
            string endifIdentifier = $"endif_{ifStat.Location.line}_{ifStat.Location.column}";

            InstructionStream.Add($"j {endifIdentifier}", "Go to the end of the else block.");
            InstructionStream.Add($"{elseIdentifier}    nop", "Start the else block");
        }
コード例 #7
0
        public MoonVisitor(SymbolTable globalScope)
        {
            this.GlobalScope = globalScope;

            // Reset the instructions.
            InstructionStream.Instructions.Clear();
            InstructionStream.Add(File.ReadAllLines("puts.m").Where(line => line.Trim().Length != 0).ToArray(), "Link the puts library");
        }
コード例 #8
0
 public override void Visit(Not not)
 {
     this.Load(not.Factor, "r1");
     InstructionStream.Add(new string[] {
         "not r1, r1",
         $"sw {not.stackOffset}(r14), r1"
     }, $"Invert the sign");
 }
コード例 #9
0
        public override void Visit(ReturnStat returnStat)
        {
            this.LoadAndStore(returnStat.ReturnValueExpression, 4, returnStat.ReturnValueExpression.NodeMemorySize, $"Returning {returnStat.ReturnValueExpression}");

            InstructionStream.Add(new string[] {
                "lw r15, 0(r14)",
                "jr r15"
            }, "Load the return address, and return.");
        }
コード例 #10
0
        public override void Visit(MainStatBlock mainStatBlock)
        {
            InstructionStream.Add("hlt");

            int programSize   = InstructionStream.Instructions.Count * 4;
            int indexToInsert = InstructionStream.Instructions.IndexOf("entry") + 1;

            InstructionStream.Instructions.Insert(indexToInsert, $"addi r14, r0, {programSize}  % Set the stack pointer");
        }
コード例 #11
0
        public override void PostInitializationVisit(ForStat forStat)
        {
            string startForIdentifier  = $"for_{forStat.Location.line}_{forStat.Location.column}";
            string conditionIdentifier = $"forcond_{forStat.Location.line}_{forStat.Location.column}";

            this.LoadAndStore(forStat.Initialization, forStat.stackOffset, forStat.NodeMemorySize, $"{forStat.Type} {forStat.Id} = {forStat.Initialization}");

            InstructionStream.Add($"j {conditionIdentifier}");
            InstructionStream.Add($"{startForIdentifier}    nop", "Start the for loop");
        }
コード例 #12
0
        public override void Visit(ForStat forStat)
        {
            string startForIdentifier = $"for_{forStat.Location.line}_{forStat.Location.column}";
            string endForIdentifier   = $"endfor_{forStat.Location.line}_{forStat.Location.column}";

            InstructionStream.Add(new string[] {
                $"j {startForIdentifier}",
                $"{endForIdentifier}    nop"
            });
        }
コード例 #13
0
 void OnExplorerClauseChanged(Clause clause)
 {
     InstructionStream.Clear();
     if (clause == null)
     {
         return;
     }
     foreach (var item in clause.PrologInstructionStream)
     {
         InstructionStream.Add(item);
     }
 }
コード例 #14
0
        public override void PreVisit(FuncDef funcDef)
        {
            this.FunctionScope = this.GlobalScope.Get(funcDef.Entry.ID, Classification.Function).Link;

            this.ClassInstanceScope = new SymbolTable();
            if (funcDef.ScopeResolution != null)
            {
                this.ClassInstanceScope = this.GlobalScope.Get(funcDef.ScopeResolution.ID.Replace(':', '_'), Classification.Class).Link;
            }

            InstructionStream.Add($"function_{funcDef.Entry.ID.Replace(':', '_')} sw 0(r14), r15", $"Store the return address.");
        }
コード例 #15
0
        private void Load(Node node, params string[] registers)
        {
            for (int i = 0; i < registers.Length; i++)
            {
                string register = registers[i];
                InstructionStream.Add($"lw {register}, {node.stackOffset + i * 4}(r14)", $"Loading the value of {node}");

                if (!node.IsLiteral)
                {
                    InstructionStream.Add($"lw {register}, 0({register})", $"Pointer detected. Dereferencing {node}");
                }
            }
        }
コード例 #16
0
        public override void Visit(GetStat getStat)
        {
            InstructionStream.Add(new string[] {
                $"addi r5, r14, {getStat.Variable.stackOffset}",
                $"lw r5, 0(r5)",
                $"jl r15, geti_func"
            });

            if (getStat.Variable.SemanticalType == "float")
            {
                InstructionStream.Add(new string[] {
                    $"addi r5, r14, {getStat.Variable.stackOffset + 4}",
                    $"lw r5, 0(r5)",
                    $"jl r15, geti_func"
                });
            }
        }
コード例 #17
0
        public void PostVisit(Var var)
        {
            InstructionStream.Add($"addi r1, r14, 0", $"Calculating the REAL offset for {var}");

            foreach (var entry in var.Elements)
            {
                if (entry is DataMember member)
                {
                    InstructionStream.Add(new string[] {
                        $"lw r2, {member.stackOffset}(r14)",
                        $"add r1, r1, r2"
                    });
                }

                if (entry is FCall call)
                {
                    InstructionStream.Add(new string[] {
                        $"addi r1, r14, {call.stackOffset}"
                    }, "Get the function call's pointer");
                }
            }

            if (var.Elements.Last() as DataMember != null)
            {
                for (int i = 0; i < var.NodeMemorySize; i += 4)
                {
                    if (i != 0)
                    {
                        InstructionStream.Add($"addi r1, r1, 4");
                    }
                    InstructionStream.Add($"sw {var.stackOffset + i}(r14), r1");
                }
                var.IsLiteral = false;
            }
            else
            {
                for (int i = 0; i < var.NodeMemorySize; i += 4)
                {
                    InstructionStream.Add(new string[] {
                        $"lw r2, {var.Elements.Last().stackOffset + i}(r14)",
                        $"sw {var.stackOffset + i}(r14), r2"
                    });
                }
                var.IsLiteral = true;
            }
        }
コード例 #18
0
        public override void Visit(PutStat putStat)
        {
            int thisFrameSize = this.FunctionScope.GetStackFrameSize();

            char putFunctionChar = 'i';

            if (putStat.Expression.SemanticalType == "float")
            {
                putFunctionChar = 'f';
            }

            string putFunction = $"put{putFunctionChar}_func";

            this.LoadAndStore(putStat.Expression, thisFrameSize + 4, putStat.Expression.NodeMemorySize, $"Store the put value of {putStat.Expression}");
            InstructionStream.Add($"addi r14, r14, {thisFrameSize}");
            InstructionStream.Add($"jl r15, {putFunction}");
            InstructionStream.Add($"subi r14, r14, {thisFrameSize}");
        }
コード例 #19
0
        public override void Visit(Integer integer)
        {
            int result;

            if (!int.TryParse(integer.Value, out result))
            {
                result = 0;
            }

            var bytes = BitConverter.GetBytes(result);

            for (int i = 0; i < bytes.Length; i++)
            {
                InstructionStream.Add(new string[] {
                    $"addi r1, r0, {bytes[i]}",
                    $"sb {integer.stackOffset + i}(r14), r1"
                }, $"Storing {bytes[i]}");
            }
        }
コード例 #20
0
        public override void Visit(Sign sign)
        {
            // This works for floats and ints.
            int factor = sign.SignSymbol == "-" ? -1 : 1;

            InstructionStream.Add(new string[] {
                $"lw r2, {sign.Factor.stackOffset}(r14)",
                $"muli r2, r2, {factor}",
                $"sw {sign.stackOffset}(r14), r2"
            }, $"Calculating {sign}");

            if (sign.SemanticalType == "float")
            {
                InstructionStream.Add(new string[] {
                    $"lw r2, {sign.Factor.stackOffset + 4}(r14)",
                    $"sw {sign.stackOffset + 4}(r14), r2"
                }, $"Calculating {sign}");
            }
        }
コード例 #21
0
 private void LoadAndStore(int sourceAddresss, int destinationAddress, int copySizeInBytes, bool derefSource = false, bool derefDest = false, string comment = "")
 {
     for (int i = 0; i < copySizeInBytes; i += 4)
     {
         InstructionStream.Add($"lw r1, {sourceAddresss + (i)}(r14)", $"{comment} - loading {i} of {copySizeInBytes}");
         if (derefSource)
         {
             InstructionStream.Add("lw r1, 0(r1)", "Pointer detected. Dereferencing.");
         }
         if (derefDest)
         {
             InstructionStream.Add($"lw r2, {destinationAddress}(r14)");
             InstructionStream.Add($"sw {i}(r2), r1", "Pointer detected. Storing the value in the dereferenced location.");
         }
         else
         {
             InstructionStream.Add($"sw {destinationAddress + (i)}(r14), r1", $"{comment} - storing {i} of {copySizeInBytes}");
         }
     }
 }
コード例 #22
0
        public void SubVisit(DataMember dataMember)
        {
            InstructionStream.Add($"addi r1, r0, {dataMember.baseOffset}", $"Start to calculate the offset for {dataMember}");

            if (dataMember?.Indexes?.Expressions != null)
            {
                var maxIndexes = dataMember.MaxSizeDimensions;

                for (int i = 0; i < dataMember.Indexes.Expressions.Count; i++)
                {
                    var exp = dataMember.Indexes.Expressions[i];

                    InstructionStream.Add($"lw r2, {exp.stackOffset}(r14)", $"Getting the index [{exp}]");

                    if (!exp.IsLiteral)
                    {
                        InstructionStream.Add($"lw r2, 0(r2)", "Pointer deteced - dereferencing");
                    }

                    InstructionStream.Add($"muli r2, r2, {dataMember.NodeMemorySize}", $"Multiply by the size.");

                    for (int sizeIndex = i + 1; sizeIndex < dataMember.Indexes.Expressions.Count; sizeIndex++)
                    {
                        InstructionStream.Add($"muli r2, r2, {maxIndexes[sizeIndex]}", $"Multiply by the chunk size {maxIndexes[sizeIndex]}");
                    }

                    InstructionStream.Add($"add r1, r1, r2", $"Add the index {dataMember.Indexes.Expressions[i]}");
                }
            }

            for (int i = 0; i < dataMember.NodeMemorySize; i += 4)
            {
                if (i != 0)
                {
                    InstructionStream.Add($"addi r1, r1, 4");
                }
                InstructionStream.Add($"sw {dataMember.stackOffset + i}(r14), r1");
            }
        }
コード例 #23
0
        /// <summary>
        /// Constructs the list of ILInstructions according to the IL byte code for only 'call' type operands.
        /// </summary>
        /// <param name="module"></param>
        private void BuildInstructions()
        {
            int index = 0;

            while (index < IL.Length)
            {
                int    pos    = index; //for Instruction.Position
                byte   ilByte = IL[index++];
                OpCode code;
                if (ilByte != 0xFE)
                {
                    code = ilByte.ConvToSingleOpCode();
                }
                else
                {
                    ilByte = IL[index++];
                    code   = ilByte.ConvToMultiOpCode();
                }

                string operand = GetOperand(code.OperandType, ref index); // advance index into next instruction
                InstructionStream.Add(new Instruction(code, operand, pos));
            }
        }
コード例 #24
0
        public override void Visit(Float @float)
        {
            string floatVal = @float.Value;
            float  realValue;
            int    powerValue;

            // Get the parts.
            if (floatVal.Contains("e"))
            {
                var floatParts = floatVal.Split('e');

                if (!float.TryParse(floatParts[0], out realValue))
                {
                    realValue = 0;
                }
                if (!int.TryParse(floatParts[1], out powerValue))
                {
                    powerValue = 0;
                }
            }
            else
            {
                if (!float.TryParse(floatVal, out realValue))
                {
                    realValue = 0;
                }
                powerValue = 0;
            }

            if (realValue != 0)
            {
                // Convert into the proper format. If we keep things under 1 billion, we can retain 9 digit floats.
                while (realValue < 100000000 || realValue < -100000000)   // 100,000,000
                {
                    realValue  *= 10;
                    powerValue -= 1;
                }
                while (realValue >= 1000000000 || realValue < -1000000000)   // 1,000,000,000
                {
                    realValue  /= 10;
                    powerValue += 1;
                }
            }

            int firstWord  = (int)realValue;
            int secondWord = powerValue;


            // Store the first word.
            var bytes = BitConverter.GetBytes(firstWord);

            for (int i = 0; i < bytes.Length; i++)
            {
                InstructionStream.Add(new string[] {
                    $"addi r1, r0, {bytes[i]}",
                    $"sb {@float.stackOffset + i}(r14), r1"
                }, $"Storing {bytes[i]}");
            }

            // Store the second word.
            bytes = BitConverter.GetBytes(secondWord);

            for (int i = 0; i < bytes.Length; i++)
            {
                InstructionStream.Add(new string[] {
                    $"addi r1, r0, {bytes[i]}",
                    $"sb {@float.stackOffset + i + 4}(r14), r1"
                }, $"Storing {bytes[i]}");
            }
        }
コード例 #25
0
        public override void Visit(MultOp multOp)
        {
            string instruction = string.Empty;

            switch (multOp.Operator)
            {
            case "*":
                instruction = "mul";
                break;

            case "/":
                instruction = "div";
                break;

            case "and":
                instruction = "and";
                break;
            }

            string floatPowerInstruction = instruction == "mul" ? "add" : "sub";

            if (multOp.SemanticalType == "int" || instruction == "and")
            {
                this.Load(multOp.LHS, "r2");
                this.Load(multOp.RHS, "r3");

                InstructionStream.Add(new string[] {
                    $"{instruction} r1, r2, r3",
                    $"sw {multOp.stackOffset}(r14), r1"
                }, $"Calculating {multOp.ToString()}");
                return;
            }

            this.Load(multOp.LHS, "r2", "r3");
            this.Load(multOp.RHS, "r4", "r5");

            InstructionStream.Add(new string[] {
                $"pas1{GetTag(multOp)}    cgt r1, r3, r5     % While r3 > r5, shift it until they're equal",
                $"bz r1, pas2{GetTag(multOp)}    % Otherwise, continue.",
                "addi r5, r5, 1",
                "divi r4, r4, 10",
                $"j pas1{GetTag(multOp)}",


                $"pas2{GetTag(multOp)}   cgt r1, r5, r3      % While r5 > r3, shift it until they're equal",
                $"bz r1, pas3{GetTag(multOp)}    % Otherwise, continue.",
                "addi r3, r3, 1",
                "divi r2, r2, 10",
                $"j pas2{GetTag(multOp)}",


                $"pas3{GetTag(multOp)}   divi r2, r2, 10000      % Make sure it's in the right for for performing multiplication",
                $"addi r3, r3, 4",
                $"divi r4, r4, 10000",
                $"addi r5, r5, 4",
                $"{floatPowerInstruction} r3, r3, r5",



                $"{instruction} r2, r2, r4     % Perform {multOp}",

                "addi r6, r0, 10000     % Make 100,000,000",
                "muli r6, r6, 10000",

                "cgei r7, r2, 0         % If we're dealing with a positive number, store the sign.",
                $"bnz r7, pas4{GetTag(multOp)}",
                $"addi r7, r0, -1       % Otherwise, it's negative. Store the sign.",
                $"muli r2, r2, -1       % Also make r2 positive for now.",

                $"pas4{GetTag(multOp)} clt r1, r2, r6        % While realval < 100,000",
                $"bz r1, pas5{GetTag(multOp)}",
                "ceqi r1, r2, 0     % And also not 0",
                $"bnz r1, pas5{GetTag(multOp)}",
                "subi r3, r3, 1     % Shift it.",
                "muli r2, r2, 10",
                $"j pas4{GetTag(multOp)}",


                $"pas5{GetTag(multOp)}    muli r6, r6, 10    % Make 1,000,000,000",


                $"pas6{GetTag(multOp)}    cge r1, r2, r6     % While realval >= 1,000,000,000",
                $"bz r1, pas7{GetTag(multOp)}",
                "ceqi r1, r2, 0     % And also not 0",
                $"bnz r1, pas7{GetTag(multOp)}",
                "addi r3, r3, 1     % Shift it.",
                "divi r2, r2, 10",
                $"j pas6{GetTag(multOp)}",

                $"pas7{GetTag(multOp)}   mul r2, r2, r7     % Apply the sign.",


                $"sw {multOp.stackOffset}(r14), r2     % Store the new float val",
                $"sw {multOp.stackOffset + 4}(r14), r3"
            }, $"Calculating {multOp}");
        }
コード例 #26
0
        public override void PostUpdateVisit(ForStat forStat)
        {
            string conditionIdentifier = $"forcond_{forStat.Location.line}_{forStat.Location.column}";

            InstructionStream.Add($"{conditionIdentifier}   nop");
        }
コード例 #27
0
        public override void Visit(IfStat ifStat)
        {
            string endifIdentifier = $"endif_{ifStat.Location.line}_{ifStat.Location.column}";

            InstructionStream.Add($"{endifIdentifier}    nop", "End the else block");
        }
コード例 #28
0
        public override void Visit(Var var)
        {
            string lastDatatype = string.Empty;

            for (int i = 0; i < var.Elements.Count; i++)
            {
                var element = var.Elements[i];
                if (element is DataMember member)
                {
                    lastDatatype = member.SemanticalType;

                    this.SubVisit(member);
                }

                if (element is FCall call)
                {
                    if (lastDatatype.Length != 0)
                    {
                        call.Id = lastDatatype + "::" + call.Id;
                    }

                    lastDatatype = call.SemanticalType;


                    if (lastDatatype.Length != 0)
                    {
                        InstructionStream.Add($"addi r7, r14, 0", "This is to calculate the data offset for any potential member functions.");

                        for (int x = 0; x < i; x++)
                        {
                            if (var.Elements[x] is DataMember calcMem)
                            {
                                InstructionStream.Add($"lw r8, {calcMem.stackOffset}(r14)", "This is to calculate the next data offset AFTER a data member");
                                InstructionStream.Add($"add r7, r7, r8");
                            }
                            if (var.Elements[x] is FCall calcFunc)
                            {
                                InstructionStream.Add($"addi r7, r14, {calcFunc.stackOffset}", "This is to calculate the next data offset AFTER a function call.");
                            }
                        }

                        for (int x = 0; x < call.MemberMemorySize; x += 4)
                        {
                            InstructionStream.Add(new string[] {
                                $"lw r1, {x}(r7)",
                                $"sw {this.FunctionScope.GetStackFrameSize() + 4 + call.NodeMemorySize + x}(r14), r1"
                            });
                        }
                    }


                    this.SubVisit(call);

                    // Check if we need to retrieve the member
                    if (lastDatatype.Length != 0)
                    {
                        InstructionStream.Add($"addi r7, r14, 0", "This is to calculate the data offset for any potential member functions.");

                        for (int x = 0; x < i; x++)
                        {
                            if (var.Elements[x] is DataMember calcMem)
                            {
                                InstructionStream.Add($"lw r8, {calcMem.stackOffset}(r14)", "This is to calculate the next data offset AFTER a data member");
                                InstructionStream.Add($"add r7, r7, r8");
                            }
                            if (var.Elements[x] is FCall calcFunc)
                            {
                                InstructionStream.Add($"addi r7, r14, {calcFunc.stackOffset}", "This is to calculate the next data offset AFTER a function call.");
                            }
                        }

                        for (int y = 0; y < call.MemberMemorySize; y += 4)
                        {
                            InstructionStream.Add(new string[] {
                                $"lw r1, {this.FunctionScope.GetStackFrameSize() + 4 + call.NodeMemorySize + y}(r14)",
                                $"sw {y}(r7), r1"
                            });
                        }
                    }
                }
            }

            this.PostVisit(var);
        }
コード例 #29
0
        public override void Visit(RelExpr relExpr)
        {
            string instruction = relExpr.RelationOperator;

            switch (relExpr.RelationOperator)
            {
            case "==":
                instruction = "ceq";
                break;

            case "<>":
                instruction = "cne";
                break;

            case "<":
                instruction = "clt";
                break;

            case ">":
                instruction = "cgt";
                break;

            case "<=":
                instruction = "cle";
                break;

            case ">=":
                instruction = "cge";
                break;
            }

            if (relExpr.LHS.SemanticalType == "float")
            {
                this.Load(relExpr.LHS, "r2", "r3");
                this.Load(relExpr.RHS, "r4", "r5");

                InstructionStream.Add(new string[] {
                    $"pas1{GetTag(relExpr)}    cgt r1, r3, r5     % While r3 > r5, shift it until they're equal",
                    $"bz r1, pas2{GetTag(relExpr)}    % Otherwise, continue.",
                    "addi r5, r5, 1",
                    "divi r4, r4, 10",
                    $"j pas1{GetTag(relExpr)}",


                    $"pas2{GetTag(relExpr)}   cgt r1, r5, r3      % While r5 > r3, shift it until they're equal",
                    $"bz r1, pas3{GetTag(relExpr)}    % Otherwise, continue.",
                    "addi r3, r3, 1",
                    "divi r2, r2, 10",
                    $"j pas2{GetTag(relExpr)}",
                    $"pas3{GetTag(relExpr)}     add r3, r0, r4    % Put everything into r2 and r3 registers"
                });
            }


            this.Load(relExpr.LHS, "r2");
            this.Load(relExpr.RHS, "r3");
            InstructionStream.Add(new string[] {
                $"{instruction} r1, r2, r3",
                $"sw {relExpr.stackOffset}(r14), r1"
            }, $"Evaluate {relExpr}");
        }