Commit 01e6cfff authored by Tom Zhao's avatar Tom Zhao
Browse files

Merge branch 'develop' of https://gitlab.doc.ic.ac.uk/lab2021_spring/wacc_46 into develop

parents ddafa6ad f68b39d5
...@@ -77,7 +77,7 @@ assign_rhs : expr #Expr ...@@ -77,7 +77,7 @@ assign_rhs : expr #Expr
arg_list : expr (COMMA expr)*; arg_list : expr (COMMA expr)*;
struct_elem : IDENT (DOT IDENT)+; struct_elem : IDENT (DOT IDENT)+;
new_struct : NEW IDENT OPEN_CURLY_BRACKET arg_list? CLOSE_CURLY_BRACKET ; new_struct : NEW IDENT OPEN_PARENTHESES arg_list? CLOSE_PARENTHESES ;
pair_elem : FST expr #FstExpr pair_elem : FST expr #FstExpr
| SND expr #SndExpr | SND expr #SndExpr
......
...@@ -25,11 +25,9 @@ for folder in ${VALID_EXAMPLES[@]}; do ...@@ -25,11 +25,9 @@ for folder in ${VALID_EXAMPLES[@]}; do
echo $file echo $file
./compile -t -o1 $file > "${EXECUTABLE_FILE_NAME}.log.txt" ./compile -t -o1 $file > "${EXECUTABLE_FILE_NAME}.log.txt"
mv "${EXECUTABLE_FILE_NAME}.log.txt" "${VALID_EXAMPLES_SRC_DIR}${folder}/${FILE_NAME}.log" if diff "${EXECUTABLE_FILE_NAME}.log.txt" "${VALID_EXAMPLES_SRC_DIR}${folder}/${FILE_NAME}.log" -I scope; then
(( COUNTER += 1 ))
# if diff "${EXECUTABLE_FILE_NAME}.log.txt" "${VALID_EXAMPLES_SRC_DIR}${folder}/${FILE_NAME}.log" -I scope; then fi
# (( COUNTER += 1 ))
# fi
echo "$COUNTER / $(($TOTAL_COUNT)) files have been executed" echo "$COUNTER / $(($TOTAL_COUNT)) files have been executed"
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
VALID_EXAMPLES=( VALID_EXAMPLES=(
"/binOctHex" "/binOctHex"
"/bitwiseOperation" "/bitwise"
"/do-while" "/do-while"
"/for" "/for"
"/import" "/import"
......
...@@ -2,13 +2,13 @@ ...@@ -2,13 +2,13 @@
VALID_EXAMPLES=( VALID_EXAMPLES=(
#"/advanced" #"/advanced"
#"/array" "/array"
"/basic" "/basic"
"/expressions" "/expressions"
#"/function" "/function"
"/if" "/if"
"/IO" "/IO"
#"/pairs" "/pairs"
#"/runtimeErr" #"/runtimeErr"
"/scope" "/scope"
"/sequence" "/sequence"
...@@ -44,7 +44,7 @@ for folder in ${VALID_EXAMPLES[@]}; do ...@@ -44,7 +44,7 @@ for folder in ${VALID_EXAMPLES[@]}; do
./compile -i $file 2> "${EXECUTABLE_FILE_NAME}.log.txt" ./compile -i $file 2> "${EXECUTABLE_FILE_NAME}.log.txt"
mv "${FILE_NAME}.s" "${EXECUTABLE_FILE_NAME}.s" mv "${FILE_NAME}.s" "${EXECUTABLE_FILE_NAME}.s"
gcc "${EXECUTABLE_FILE_NAME}.s" -o "${EXECUTABLE_FILE_NAME}" gcc "${EXECUTABLE_FILE_NAME}.s" -o "${EXECUTABLE_FILE_NAME}"
./"${EXECUTABLE_FILE_NAME}" > "${EXECUTABLE_OUTPUT_FILE}" timeout 3 ./"${EXECUTABLE_FILE_NAME}" > "${EXECUTABLE_OUTPUT_FILE}"
# Generate the result from reference compiler # Generate the result from reference compiler
cat <(echo "N" | $REF_COMPILE $file -x) | awk '/===========================================================/ {x=!x; if(x) next} x==1 {print}' > temp cat <(echo "N" | $REF_COMPILE $file -x) | awk '/===========================================================/ {x=!x; if(x) next} x==1 {print}' > temp
# Use the result generated by our compiler # Use the result generated by our compiler
......
...@@ -52,7 +52,6 @@ public class Compiler { ...@@ -52,7 +52,6 @@ public class Compiler {
File sourceFile = new File(args[0]); File sourceFile = new File(args[0]);
File file = new PreCompiler(sourceFile).preCompile(); File file = new PreCompiler(sourceFile).preCompile();
// System.out.println(file.getName());
// try-with-resources so that fis can be closed properly even when error occurs // try-with-resources so that fis can be closed properly even when error occurs
try (FileInputStream fis = new FileInputStream(file)) { try (FileInputStream fis = new FileInputStream(file)) {
// Input stream of the file // Input stream of the file
......
...@@ -73,8 +73,8 @@ public class PreCompiler { ...@@ -73,8 +73,8 @@ public class PreCompiler {
str = str.split(commentMark, 2)[0]; str = str.split(commentMark, 2)[0];
if (str.contains(defineRuleContext)) { if (str.contains(defineRuleContext)) {
/* process and store the macros info */ /* process and store the macros info */
String[] macro = str.split(" ", 3); String[] macro = str.trim().split(" ", 3);
if (macro.length != 3 || macro[0].length() != defineRuleContext.length() - 1) { if (macro.length != 3 || !macro[0].equals(defineRuleContext.trim())) {
mediateFile.delete(); mediateFile.delete();
System.out.println("Invalid macro at line " + lineCounter); System.out.println("Invalid macro at line " + lineCounter);
System.exit(SYNTAX_ERROR_CODE); System.exit(SYNTAX_ERROR_CODE);
...@@ -82,12 +82,12 @@ public class PreCompiler { ...@@ -82,12 +82,12 @@ public class PreCompiler {
macros.add(new MacroInfo(macro[1], macro[2])); macros.add(new MacroInfo(macro[1], macro[2]));
} else if (str.contains(includeRuleContext)) { } else if (str.contains(includeRuleContext)) {
/* process and store the stdlib including info */ /* process and store the stdlib including info */
String[] tokens = str.split("<", 2); String[] tokens = str.trim().split("<", 2);
/* e.g. include lib<a, b, c>, tokens[0] = include lib, tokens[1] = a, b, c> */ /* e.g. include lib<a, b, c>, tokens[0] = include lib, tokens[1] = a, b, c> */
String[] prefix = tokens[0].split(" ", 2); String[] prefix = tokens[0].split(" ", 2);
String libName = prefix[1]; String libName = prefix[1].trim();
List<String> typeParams = (tokens.length == 1) ? new ArrayList<>() : getTypeParam(tokens[1], List<String> typeParams = (tokens.length == 1) ? new ArrayList<>() : getTypeParam(tokens[1],
lineCounter, prefix[0].length() == includeRuleContext.length() - 1, mediateFile); lineCounter, prefix[0].equals(includeRuleContext.trim()), mediateFile);
imports.add(new IncludeInfo(libName, typeParams, lineCounter)); imports.add(new IncludeInfo(libName, typeParams, lineCounter));
} else if (str.contains(programBodyMark)) { } else if (str.contains(programBodyMark)) {
bw.write(str + "\n"); bw.write(str + "\n");
...@@ -158,7 +158,7 @@ public class PreCompiler { ...@@ -158,7 +158,7 @@ public class PreCompiler {
if (str.contains(defineRuleContext)) { if (str.contains(defineRuleContext)) {
/* get the lib's macro info, assume macros in stdlib are all valid */ /* get the lib's macro info, assume macros in stdlib are all valid */
String[] macro = str.split(" ", 3); String[] macro = str.trim().split(" ", 3);
macros.add(new MacroInfo(macro[1], macro[2])); macros.add(new MacroInfo(macro[1], macro[2]));
} else { } else {
bw.write(" " + str + "\n"); /* copy the content */ bw.write(" " + str + "\n"); /* copy the content */
...@@ -204,7 +204,11 @@ public class PreCompiler { ...@@ -204,7 +204,11 @@ public class PreCompiler {
if (c == '<') depth++; if (c == '<') depth++;
if (c == '>') depth--; if (c == '>') depth--;
if (depth == 0) { if (c == '[' || c == '(') {
mediateFile.delete();
System.out.println("Array or pair type are not supported: line " + lineNum);
System.exit(SYNTAX_ERROR_CODE);
} else if (depth == 0) {
typeParams.add(token.toString()); typeParams.add(token.toString());
break; break;
} else if (depth == 1 && c == ',') { } else if (depth == 1 && c == ',') {
...@@ -215,15 +219,7 @@ public class PreCompiler { ...@@ -215,15 +219,7 @@ public class PreCompiler {
} }
} }
boolean hasJunkAtEnd = false; if (i != str.length() - 1 || !matchInclude || depth != 0) {
for (i = i + 1; i < str.length(); i++) {
if (str.charAt(i) != ' ') {
hasJunkAtEnd = true;
break;
}
}
if (hasJunkAtEnd || !matchInclude || depth != 0) {
mediateFile.delete(); mediateFile.delete();
System.out.println("Invalid include statement at line " + lineNum); System.out.println("Invalid include statement at line " + lineNum);
System.exit(SYNTAX_ERROR_CODE); System.exit(SYNTAX_ERROR_CODE);
......
package backend; package backend;
import backend.arm.ARMInstructionGenerator;
import backend.arm.instructions.ARMInstruction;
import backend.common.LabelInstruction; import backend.common.LabelInstruction;
import backend.intel.IntelInstructionGenerator;
import backend.intel.instructions.IntelInstruction;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import utils.NodeVisitor; import utils.NodeVisitor;
import utils.frontend.symbolTable.SymbolTable; import utils.frontend.symbolTable.SymbolTable;
public abstract class InstructionGenerator<T extends Instruction> implements NodeVisitor<Void> { public abstract class InstructionGenerator<T extends Instruction> implements NodeVisitor<Void> {
/* the code section of the assembly code */ /* the code section of the assembly code */
protected final List<T> instructions; protected final List<T> instructions;
/* record the current symbolTable used during instruction generation */ /* record the current symbolTable used during instruction generation */
...@@ -32,6 +28,10 @@ public abstract class InstructionGenerator<T extends Instruction> implements Nod ...@@ -32,6 +28,10 @@ public abstract class InstructionGenerator<T extends Instruction> implements Nod
protected LabelInstruction currBreakJumpToLabel; protected LabelInstruction currBreakJumpToLabel;
protected LabelInstruction currContinueJumpToLabel; protected LabelInstruction currContinueJumpToLabel;
/* used when a break/jump occure in a loop statment, accumulated on entering scope */
protected int breakSectionStackSize;
protected int continueSectionStackSize;
public InstructionGenerator() { public InstructionGenerator() {
instructions = new ArrayList<>(); instructions = new ArrayList<>();
currSymbolTable = null; currSymbolTable = null;
...@@ -40,5 +40,7 @@ public abstract class InstructionGenerator<T extends Instruction> implements Nod ...@@ -40,5 +40,7 @@ public abstract class InstructionGenerator<T extends Instruction> implements Nod
currBreakJumpToLabel = null; currBreakJumpToLabel = null;
currContinueJumpToLabel = null; currContinueJumpToLabel = null;
currForLoopSymbolTable = null; currForLoopSymbolTable = null;
breakSectionStackSize = 0;
continueSectionStackSize = 0;
} }
} }
package backend; package backend;
public abstract class InstructionPrinter { public abstract class InstructionPrinter {
public abstract String translate();
public abstract String translate();
} }
package backend.arm; package backend.arm;
import static backend.arm.instructions.LDR.LdrMode.*; import static backend.arm.instructions.ARMInstructionRoutines.routineFunctionMap;
import static backend.arm.instructions.STR.StrMode.*; import static backend.arm.instructions.LDR.LdrMode.LDR;
import static backend.arm.instructions.addressing.AddressingMode2.AddrMode2.*; import static backend.arm.instructions.LDR.LdrMode.LDRSB;
import static backend.arm.instructions.arithmeticLogic.ARMArithmeticLogic.armUnopAsm; import static backend.arm.instructions.STR.StrMode.STR;
import static backend.arm.instructions.STR.StrMode.STRB;
import static backend.arm.instructions.addressing.ARMImmediate.BitNum.CONST8; import static backend.arm.instructions.addressing.ARMImmediate.BitNum.CONST8;
import static backend.arm.instructions.addressing.Operand2.Operand2Operator.*; import static backend.arm.instructions.addressing.AddressingMode2.AddrMode2.OFFSET;
import static backend.arm.instructions.addressing.AddressingMode2.AddrMode2.PREINDEX;
import static backend.arm.instructions.addressing.Operand2.Operand2Operator.ASR;
import static backend.arm.instructions.addressing.Operand2.Operand2Operator.LSL;
import static backend.arm.instructions.arithmeticLogic.ARMArithmeticLogic.armUnopAsm;
import static frontend.node.expr.UnopNode.Unop.MINUS; import static frontend.node.expr.UnopNode.Unop.MINUS;
import static utils.Utils.ARM_POINTER_SIZE;
import static utils.Utils.BOOL_BASIC_TYPE;
import static utils.Utils.BRANCH_HEADER;
import static utils.Utils.CHAR_ARRAY_TYPE;
import static utils.Utils.CHAR_BASIC_TYPE;
import static utils.Utils.FALSE;
import static utils.Utils.FUNC_HEADER;
import static utils.Utils.INT_BASIC_TYPE;
import static utils.Utils.MAIN_BODY_NAME;
import static utils.Utils.MSG_HEADER;
import static utils.Utils.PAIR_TYPE;
import static utils.Utils.RoutineInstruction; import static utils.Utils.RoutineInstruction;
import static utils.Utils.RoutineInstruction.*; import static utils.Utils.RoutineInstruction.CHECK_ARRAY_BOUND;
import static utils.Utils.SystemCallInstruction.*; import static utils.Utils.RoutineInstruction.CHECK_DIVIDE_BY_ZERO;
import static utils.Utils.*; import static utils.Utils.RoutineInstruction.CHECK_NULL_POINTER;
import static backend.arm.instructions.ARMInstructionRoutines.routineFunctionMap; import static utils.Utils.RoutineInstruction.FREE_ARRAY;
import static utils.backend.Cond.*; import static utils.Utils.RoutineInstruction.FREE_PAIR;
import static utils.backend.register.arm.ARMConcreteRegister.*; import static utils.Utils.RoutineInstruction.PRINT_BOOL;
import static utils.Utils.RoutineInstruction.PRINT_CHAR;
import static utils.Utils.RoutineInstruction.PRINT_INT;
import static utils.Utils.RoutineInstruction.PRINT_LN;
import static utils.Utils.RoutineInstruction.PRINT_REFERENCE;
import static utils.Utils.RoutineInstruction.PRINT_STRING;
import static utils.Utils.RoutineInstruction.READ_CHAR;
import static utils.Utils.RoutineInstruction.READ_INT;
import static utils.Utils.RoutineInstruction.THROW_OVERFLOW_ERROR;
import static utils.Utils.RoutineInstruction.THROW_RUNTIME_ERROR;
import static utils.Utils.STRING_BASIC_TYPE;
import static utils.Utils.SystemCallInstruction.EXIT;
import static utils.Utils.SystemCallInstruction.MALLOC;
import static utils.Utils.TRUE;
import static utils.Utils.WORD_SIZE;
import static utils.backend.Cond.EQ;
import static utils.backend.Cond.NE;
import static utils.backend.Cond.NULL;
import static utils.backend.Cond.VS;
import static utils.backend.register.arm.ARMConcreteRegister.LR;
import static utils.backend.register.arm.ARMConcreteRegister.PC;
import static utils.backend.register.arm.ARMConcreteRegister.SP;
import static utils.backend.register.arm.ARMConcreteRegister.r0;
import static utils.backend.register.arm.ARMConcreteRegister.r1;
import static utils.backend.register.arm.ARMConcreteRegister.r4;
import backend.Instruction; import backend.Instruction;
import backend.InstructionGenerator; import backend.InstructionGenerator;
import backend.arm.instructions.*; import backend.arm.instructions.ARMInstruction;
import backend.arm.instructions.B;
import backend.arm.instructions.BL;
import backend.arm.instructions.Cmp;
import backend.arm.instructions.LDR;
import backend.arm.instructions.LDR.LdrMode; import backend.arm.instructions.LDR.LdrMode;
import backend.arm.instructions.STR.StrMode; import backend.arm.instructions.LTORG;
import backend.arm.instructions.addressing.*; import backend.arm.instructions.Label;
import backend.arm.instructions.arithmeticLogic.*; import backend.arm.instructions.Mov;
import backend.arm.instructions.Pop; import backend.arm.instructions.Pop;
import backend.arm.instructions.Push; import backend.arm.instructions.Push;
import backend.arm.instructions.STR;
import backend.arm.instructions.STR.StrMode;
import backend.arm.instructions.addressing.ARMImmediate;
import backend.arm.instructions.addressing.AddressingMode2;
import backend.arm.instructions.addressing.ImmedAddress;
import backend.arm.instructions.addressing.Operand2;
import backend.arm.instructions.arithmeticLogic.ARMArithmeticLogic;
import backend.arm.instructions.arithmeticLogic.Add;
import backend.arm.instructions.arithmeticLogic.Sub;
import backend.common.address.Address; import backend.common.address.Address;
import frontend.node.*; import frontend.node.FuncNode;
import frontend.node.expr.*; import frontend.node.ProgramNode;
import frontend.node.StructDeclareNode;
import frontend.node.expr.ArrayElemNode;
import frontend.node.expr.ArrayNode;
import frontend.node.expr.BinopNode;
import frontend.node.expr.BinopNode.Binop; import frontend.node.expr.BinopNode.Binop;
import frontend.node.expr.BoolNode;
import frontend.node.expr.CharNode;
import frontend.node.expr.ExprNode;
import frontend.node.expr.FunctionCallNode;
import frontend.node.expr.IdentNode;
import frontend.node.expr.IntegerNode;
import frontend.node.expr.PairElemNode;
import frontend.node.expr.PairNode;
import frontend.node.expr.StringNode;
import frontend.node.expr.StructElemNode;
import frontend.node.expr.StructNode;
import frontend.node.expr.UnopNode;
import frontend.node.expr.UnopNode.Unop; import frontend.node.expr.UnopNode.Unop;
import frontend.node.stat.*; import frontend.node.stat.AssignNode;
import frontend.node.stat.JumpNode.JumpContext; import frontend.node.stat.DeclareNode;
import frontend.node.stat.ExitNode;
import frontend.node.stat.ForNode;
import frontend.node.stat.FreeNode;
import frontend.node.stat.IfNode;
import frontend.node.stat.JumpNode;
import frontend.node.stat.JumpNode.JumpType; import frontend.node.stat.JumpNode.JumpType;
import frontend.node.stat.PrintNode;
import frontend.node.stat.PrintlnNode;
import frontend.node.stat.ReadNode;
import frontend.node.stat.ReturnNode;
import frontend.node.stat.ScopeNode;
import frontend.node.stat.SkipNode;
import frontend.node.stat.StatNode;
import frontend.node.stat.SwitchNode;
import frontend.node.stat.SwitchNode.CaseStat; import frontend.node.stat.SwitchNode.CaseStat;
import frontend.node.stat.WhileNode;
import frontend.type.Type; import frontend.type.Type;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
...@@ -42,12 +125,10 @@ import java.util.List; ...@@ -42,12 +125,10 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import utils.NodeVisitor;
import utils.backend.LabelGenerator; import utils.backend.LabelGenerator;
import utils.backend.register.Register;
import utils.backend.register.arm.ARMConcreteRegister; import utils.backend.register.arm.ARMConcreteRegister;
import utils.backend.register.arm.ARMConcreteRegisterAllocator; import utils.backend.register.arm.ARMConcreteRegisterAllocator;
import utils.backend.register.Register;
import utils.frontend.symbolTable.SymbolTable;
public class ARMInstructionGenerator extends InstructionGenerator<ARMInstruction> { public class ARMInstructionGenerator extends InstructionGenerator<ARMInstruction> {
...@@ -55,36 +136,27 @@ public class ARMInstructionGenerator extends InstructionGenerator<ARMInstruction ...@@ -55,36 +136,27 @@ public class ARMInstructionGenerator extends InstructionGenerator<ARMInstruction
public static int MAX_STACK_STEP = (1 << 10); public static int MAX_STACK_STEP = (1 << 10);
/* const used in visitBinop, for checking multiply overflow */ /* const used in visitBinop, for checking multiply overflow */
public static int ASR_SHIFT_CONST = 31; public static int ASR_SHIFT_CONST = 31;
/* the ARM concrete register allocator */
private final ARMConcreteRegisterAllocator armRegAllocator;
/* the .data section of the assembly code */ /* the .data section of the assembly code */
protected final Map<Label, String> dataSegmentMessages; protected final Map<Label, String> dataSegmentMessages;
/* call getLabel() on branchLabelGenerator to get label in the format of "L0, L1, L2, ..." */
protected final LabelGenerator<Label> branchLabelGenerator;
/* call getLabel() on msgLabelGenerator to get label in the format of "msg_0, msg_1, msg_2, ..."*/
protected final LabelGenerator<Label> msgLabelGenerator;
/* the ARM concrete register allocator */
private final ARMConcreteRegisterAllocator armRegAllocator;
/* a list of instructions for storing different helper functions /* a list of instructions for storing different helper functions
* would be appended to the end of instructions list while printing */ * would be appended to the end of instructions list while printing */
private final List<ARMInstruction> ARMRoutines; private final List<ARMInstruction> ARMRoutines;
/* record which helpers already exist, we don't want repeated helper functions */ /* record which helpers already exist, we don't want repeated helper functions */
private final Set<RoutineInstruction> alreadyExist; private final Set<RoutineInstruction> alreadyExist;
/* call getLabel() on branchLabelGenerator to get label in the format of "L0, L1, L2, ..." */
protected final LabelGenerator<Label> branchLabelGenerator;
/* call getLabel() on msgLabelGenerator to get label in the format of "msg_0, msg_1, msg_2, ..."*/
protected final LabelGenerator<Label> msgLabelGenerator;
/* used when a break/jump occure in a loop statment, accumulated on entering scope */
private int loopStackSize;
/* used for mapping type with its print routine function */ /* used for mapping type with its print routine function */
private final Map<Type, RoutineInstruction> typeRoutineMap = Map.of( private final Map<Type, RoutineInstruction> typeRoutineMap = Map.of(
INT_BASIC_TYPE, PRINT_INT, INT_BASIC_TYPE, PRINT_INT,
CHAR_BASIC_TYPE, PRINT_CHAR, CHAR_BASIC_TYPE, PRINT_CHAR,
BOOL_BASIC_TYPE, PRINT_BOOL, BOOL_BASIC_TYPE, PRINT_BOOL,
STRING_BASIC_TYPE, PRINT_STRING, STRING_BASIC_TYPE, PRINT_STRING,
CHAR_ARRAY_TYPE, PRINT_STRING CHAR_ARRAY_TYPE, PRINT_STRING
); );
/* recording the jump-to label for branching statement, i.e. break, continue */
private Label currBreakJumpToLabel;
private Label currContinueJumpToLabel;
public ARMInstructionGenerator() { public ARMInstructionGenerator() {
super(); super();
...@@ -143,7 +215,8 @@ public class ARMInstructionGenerator extends InstructionGenerator<ARMInstruction ...@@ -143,7 +215,8 @@ public class ARMInstructionGenerator extends InstructionGenerator<ARMInstruction
/* visit the content */ /* visit the content */
for (int i = 0; i < node.getElemCount(); i++) { for (int i = 0; i < node.getElemCount(); i++) {
visit(node.getElem(i)); visit(node.getElem(i));
instructions.add(new STR(armRegAllocator.curr(), new AddressingMode2(OFFSET, addrReg, node.getElemOffset(i)), STR)); instructions.add(new STR(armRegAllocator.curr(),
new AddressingMode2(OFFSET, addrReg, node.getElemOffset(i)), STR));
armRegAllocator.free(); armRegAllocator.free();
} }
...@@ -268,7 +341,7 @@ public class ARMInstructionGenerator extends InstructionGenerator<ARMInstruction ...@@ -268,7 +341,7 @@ public class ARMInstructionGenerator extends InstructionGenerator<ARMInstruction
List<Instruction> insList = ARMArithmeticLogic.binopInstruction List<Instruction> insList = ARMArithmeticLogic.binopInstruction
.get(operator) .get(operator)
.binopAssemble(e1reg, e1reg, op2, operator); .binopAssemble(e1reg, e2reg, op2, operator);
instructions.addAll(insList.stream().map(i -> (ARMInstruction) i).collect(Collectors.toList())); instructions.addAll(insList.stream().map(i -> (ARMInstruction) i).collect(Collectors.toList()));
if (operator == Binop.DIV || operator == Binop.MOD) { if (operator == Binop.DIV || operator == Binop.MOD) {
checkAndAddRoutine(CHECK_DIVIDE_BY_ZERO, msgLabelGenerator, dataSegmentMessages); checkAndAddRoutine(CHECK_DIVIDE_BY_ZERO, msgLabelGenerator, dataSegmentMessages);
...@@ -344,7 +417,8 @@ public class ARMInstructionGenerator extends InstructionGenerator<ARMInstruction ...@@ -344,7 +417,8 @@ public class ARMInstructionGenerator extends InstructionGenerator<ARMInstruction
/* 2 call function with B instruction */ /* 2 call function with B instruction */
String overloadName = node.getFunction().getOverloadName(); String overloadName = node.getFunction().getOverloadName();
String actualFuncName = (overloadName != null) ? overloadName : node.getFunction().getFunctionName(); String actualFuncName =
(overloadName != null) ? overloadName : node.getFunction().getFunctionName();
instructions.add(new BL(FUNC_HEADER + actualFuncName)); instructions.add(new BL(FUNC_HEADER + actualFuncName));
/* 3 add back stack pointer */ /* 3 add back stack pointer */
...@@ -677,7 +751,8 @@ public class ARMInstructionGenerator extends InstructionGenerator<ARMInstruction ...@@ -677,7 +751,8 @@ public class ARMInstructionGenerator extends InstructionGenerator<ARMInstruction
/* accumulate function stack size, in case this scope is a function scope and contain return */ /* accumulate function stack size, in case this scope is a function scope and contain return */
funcStackSize += stackSize; funcStackSize += stackSize;
loopStackSize += stackSize; breakSectionStackSize += stackSize;
continueSectionStackSize += stackSize;
/* 2 visit statements /* 2 visit statements
* set currentSymbolTable here, eliminate all other set symbol table in other statNode */ * set currentSymbolTable here, eliminate all other set symbol table in other statNode */
...@@ -689,7 +764,8 @@ public class ARMInstructionGenerator extends InstructionGenerator<ARMInstruction ...@@ -689,7 +764,8 @@ public class ARMInstructionGenerator extends InstructionGenerator<ARMInstruction
/* decrease function stack size, as from this point stack is freed by the scope, not by return */ /* decrease function stack size, as from this point stack is freed by the scope, not by return */
funcStackSize -= stackSize; funcStackSize -= stackSize;
loopStackSize -= stackSize; breakSectionStackSize -= stackSize;
continueSectionStackSize -= stackSize;
/* 3 restore stack */ /* 3 restore stack */
incStack(stackSize); incStack(stackSize);
...@@ -716,22 +792,27 @@ public class ARMInstructionGenerator extends InstructionGenerator<ARMInstruction ...@@ -716,22 +792,27 @@ public class ARMInstructionGenerator extends InstructionGenerator<ARMInstruction
Label nextLabel = branchLabelGenerator.getLabel().asArmLabel(); Label nextLabel = branchLabelGenerator.getLabel().asArmLabel();
/* restore the last jump-to label after visiting the while-loop body */ /* restore the last jump-to label after visiting the while-loop body */
Label lastBreakJumpToLabel = currBreakJumpToLabel; Label lastBreakJumpToLabel =
Label lastContinueJumpToLabel = currContinueJumpToLabel; currBreakJumpToLabel == null ? null : currBreakJumpToLabel.asArmLabel();
Label lastContinueJumpToLabel =
currContinueJumpToLabel == null ? null : currContinueJumpToLabel.asArmLabel();
currBreakJumpToLabel = nextLabel; currBreakJumpToLabel = nextLabel;
currContinueJumpToLabel = testLabel; currContinueJumpToLabel = testLabel;
instructions.add(startLabel); instructions.add(startLabel);
/* record how much stack parent loop used */ /* record how much stack parent loop used */
int prevLoopSize = loopStackSize; int prevBreakLoopSize = breakSectionStackSize;
loopStackSize = 0; int prevContinueLoopSize = continueSectionStackSize;
breakSectionStackSize = 0;
continueSectionStackSize = 0;
/* 3 loop body */