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}."); }
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}"); }
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"); }
public override void Visit(FuncDef funcDef) { InstructionStream.Add(new string[] { "lw r15, 0(r14)", "jr r15" }, "Load the return address, and return."); }
public override void PreVisit(MainStatBlock mainStatBlock) { this.FunctionScope = GlobalScope.Get("main", Classification.Function).Link; this.ClassInstanceScope = new SymbolTable(); InstructionStream.Add("entry"); }
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"); }
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"); }
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"); }
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."); }
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"); }
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"); }
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" }); }
void OnExplorerClauseChanged(Clause clause) { InstructionStream.Clear(); if (clause == null) { return; } foreach (var item in clause.PrologInstructionStream) { InstructionStream.Add(item); } }
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."); }
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}"); } } }
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" }); } }
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; } }
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}"); }
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]}"); } }
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}"); } }
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}"); } } }
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"); } }
/// <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)); } }
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]}"); } }
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}"); }
public override void PostUpdateVisit(ForStat forStat) { string conditionIdentifier = $"forcond_{forStat.Location.line}_{forStat.Location.column}"; InstructionStream.Add($"{conditionIdentifier} nop"); }
public override void Visit(IfStat ifStat) { string endifIdentifier = $"endif_{ifStat.Location.line}_{ifStat.Location.column}"; InstructionStream.Add($"{endifIdentifier} nop", "End the else block"); }
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); }
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}"); }