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
arg_list : expr (COMMA expr)*;
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
| SND expr #SndExpr
......
......@@ -25,11 +25,9 @@ for folder in ${VALID_EXAMPLES[@]}; do
echo $file
./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 ))
# fi
if diff "${EXECUTABLE_FILE_NAME}.log.txt" "${VALID_EXAMPLES_SRC_DIR}${folder}/${FILE_NAME}.log" -I scope; then
(( COUNTER += 1 ))
fi
echo "$COUNTER / $(($TOTAL_COUNT)) files have been executed"
......
......@@ -2,7 +2,7 @@
VALID_EXAMPLES=(
"/binOctHex"
"/bitwiseOperation"
"/bitwise"
"/do-while"
"/for"
"/import"
......
......@@ -2,13 +2,13 @@
VALID_EXAMPLES=(
#"/advanced"
#"/array"
"/array"
"/basic"
"/expressions"
#"/function"
"/function"
"/if"
"/IO"
#"/pairs"
"/pairs"
#"/runtimeErr"
"/scope"
"/sequence"
......@@ -44,7 +44,7 @@ for folder in ${VALID_EXAMPLES[@]}; do
./compile -i $file 2> "${EXECUTABLE_FILE_NAME}.log.txt"
mv "${FILE_NAME}.s" "${EXECUTABLE_FILE_NAME}.s"
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
cat <(echo "N" | $REF_COMPILE $file -x) | awk '/===========================================================/ {x=!x; if(x) next} x==1 {print}' > temp
# Use the result generated by our compiler
......
......@@ -52,7 +52,6 @@ public class Compiler {
File sourceFile = new File(args[0]);
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 (FileInputStream fis = new FileInputStream(file)) {
// Input stream of the file
......
......@@ -73,8 +73,8 @@ public class PreCompiler {
str = str.split(commentMark, 2)[0];
if (str.contains(defineRuleContext)) {
/* process and store the macros info */
String[] macro = str.split(" ", 3);
if (macro.length != 3 || macro[0].length() != defineRuleContext.length() - 1) {
String[] macro = str.trim().split(" ", 3);
if (macro.length != 3 || !macro[0].equals(defineRuleContext.trim())) {
mediateFile.delete();
System.out.println("Invalid macro at line " + lineCounter);
System.exit(SYNTAX_ERROR_CODE);
......@@ -82,12 +82,12 @@ public class PreCompiler {
macros.add(new MacroInfo(macro[1], macro[2]));
} else if (str.contains(includeRuleContext)) {
/* 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> */
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],
lineCounter, prefix[0].length() == includeRuleContext.length() - 1, mediateFile);
lineCounter, prefix[0].equals(includeRuleContext.trim()), mediateFile);
imports.add(new IncludeInfo(libName, typeParams, lineCounter));
} else if (str.contains(programBodyMark)) {
bw.write(str + "\n");
......@@ -158,7 +158,7 @@ public class PreCompiler {
if (str.contains(defineRuleContext)) {
/* 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]));
} else {
bw.write(" " + str + "\n"); /* copy the content */
......@@ -204,7 +204,11 @@ public class PreCompiler {
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());
break;
} else if (depth == 1 && c == ',') {
......@@ -215,15 +219,7 @@ public class PreCompiler {
}
}
boolean hasJunkAtEnd = false;
for (i = i + 1; i < str.length(); i++) {
if (str.charAt(i) != ' ') {
hasJunkAtEnd = true;
break;
}
}
if (hasJunkAtEnd || !matchInclude || depth != 0) {
if (i != str.length() - 1 || !matchInclude || depth != 0) {
mediateFile.delete();
System.out.println("Invalid include statement at line " + lineNum);
System.exit(SYNTAX_ERROR_CODE);
......
package backend;
import backend.arm.ARMInstructionGenerator;
import backend.arm.instructions.ARMInstruction;
import backend.common.LabelInstruction;
import backend.intel.IntelInstructionGenerator;
import backend.intel.instructions.IntelInstruction;
import java.util.ArrayList;
import java.util.List;
import utils.NodeVisitor;
import utils.frontend.symbolTable.SymbolTable;
public abstract class InstructionGenerator<T extends Instruction> implements NodeVisitor<Void> {
/* the code section of the assembly code */
protected final List<T> instructions;
/* record the current symbolTable used during instruction generation */
......@@ -32,6 +28,10 @@ public abstract class InstructionGenerator<T extends Instruction> implements Nod
protected LabelInstruction currBreakJumpToLabel;
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() {
instructions = new ArrayList<>();
currSymbolTable = null;
......@@ -40,5 +40,7 @@ public abstract class InstructionGenerator<T extends Instruction> implements Nod
currBreakJumpToLabel = null;
currContinueJumpToLabel = null;
currForLoopSymbolTable = null;
breakSectionStackSize = 0;
continueSectionStackSize = 0;
}
}
package backend;
public abstract class InstructionPrinter {
public abstract String translate();
}
package backend.arm;
import static backend.arm.instructions.LDR.LdrMode.*;
import static backend.arm.instructions.STR.StrMode.*;
import static backend.arm.instructions.addressing.AddressingMode2.AddrMode2.*;
import static backend.arm.instructions.arithmeticLogic.ARMArithmeticLogic.armUnopAsm;
import static backend.arm.instructions.ARMInstructionRoutines.routineFunctionMap;
import static backend.arm.instructions.LDR.LdrMode.LDR;
import static backend.arm.instructions.LDR.LdrMode.LDRSB;
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.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 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.SystemCallInstruction.*;
import static utils.Utils.*;
import static backend.arm.instructions.ARMInstructionRoutines.routineFunctionMap;
import static utils.backend.Cond.*;
import static utils.backend.register.arm.ARMConcreteRegister.*;
import static utils.Utils.RoutineInstruction.CHECK_ARRAY_BOUND;
import static utils.Utils.RoutineInstruction.CHECK_DIVIDE_BY_ZERO;
import static utils.Utils.RoutineInstruction.CHECK_NULL_POINTER;
import static utils.Utils.RoutineInstruction.FREE_ARRAY;
import static utils.Utils.RoutineInstruction.FREE_PAIR;
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.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.STR.StrMode;
import backend.arm.instructions.addressing.*;
import backend.arm.instructions.arithmeticLogic.*;
import backend.arm.instructions.LTORG;
import backend.arm.instructions.Label;
import backend.arm.instructions.Mov;
import backend.arm.instructions.Pop;
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 frontend.node.*;
import frontend.node.expr.*;
import frontend.node.FuncNode;
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.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.stat.*;
import frontend.node.stat.JumpNode.JumpContext;
import frontend.node.stat.AssignNode;
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.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.WhileNode;
import frontend.type.Type;
import java.util.ArrayList;
import java.util.Collections;
......@@ -42,12 +125,10 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import utils.NodeVisitor;
import utils.backend.LabelGenerator;
import utils.backend.register.Register;
import utils.backend.register.arm.ARMConcreteRegister;
import utils.backend.register.arm.ARMConcreteRegisterAllocator;
import utils.backend.register.Register;
import utils.frontend.symbolTable.SymbolTable;
public class ARMInstructionGenerator extends InstructionGenerator<ARMInstruction> {
......@@ -55,25 +136,19 @@ public class ARMInstructionGenerator extends InstructionGenerator<ARMInstruction
public static int MAX_STACK_STEP = (1 << 10);
/* const used in visitBinop, for checking multiply overflow */
public static int ASR_SHIFT_CONST = 31;
/* the ARM concrete register allocator */
private final ARMConcreteRegisterAllocator armRegAllocator;
/* the .data section of the assembly code */
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
* would be appended to the end of instructions list while printing */
private final List<ARMInstruction> ARMRoutines;
/* record which helpers already exist, we don't want repeated helper functions */
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 */
private final Map<Type, RoutineInstruction> typeRoutineMap = Map.of(
INT_BASIC_TYPE, PRINT_INT,
......@@ -82,9 +157,6 @@ public class ARMInstructionGenerator extends InstructionGenerator<ARMInstruction
STRING_BASIC_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() {
super();
......@@ -143,7 +215,8 @@ public class ARMInstructionGenerator extends InstructionGenerator<ARMInstruction
/* visit the content */
for (int i = 0; i < node.getElemCount(); 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();
}
......@@ -268,7 +341,7 @@ public class ARMInstructionGenerator extends InstructionGenerator<ARMInstruction
List<Instruction> insList = ARMArithmeticLogic.binopInstruction
.get(operator)
.binopAssemble(e1reg, e1reg, op2, operator);
.binopAssemble(e1reg, e2reg, op2, operator);
instructions.addAll(insList.stream().map(i -> (ARMInstruction) i).collect(Collectors.toList()));
if (operator == Binop.DIV || operator == Binop.MOD) {
checkAndAddRoutine(CHECK_DIVIDE_BY_ZERO, msgLabelGenerator, dataSegmentMessages);
......@@ -344,7 +417,8 @@ public class ARMInstructionGenerator extends InstructionGenerator<ARMInstruction
/* 2 call function with B instruction */
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));
/* 3 add back stack pointer */
......@@ -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 */
funcStackSize += stackSize;
loopStackSize += stackSize;
breakSectionStackSize += stackSize;
continueSectionStackSize += stackSize;
/* 2 visit statements
* set currentSymbolTable here, eliminate all other set symbol table in other statNode */
......@@ -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 */
funcStackSize -= stackSize;
loopStackSize -= stackSize;
breakSectionStackSize -= stackSize;
continueSectionStackSize -= stackSize;
/* 3 restore stack */
incStack(stackSize);
......@@ -716,22 +792,27 @@ public class ARMInstructionGenerator extends InstructionGenerator<ARMInstruction
Label nextLabel = branchLabelGenerator.getLabel().asArmLabel();
/* restore the last jump-to label after visiting the while-loop body */
Label lastBreakJumpToLabel = currBreakJumpToLabel;
Label lastContinueJumpToLabel = currContinueJumpToLabel;
Label lastBreakJumpToLabel =
currBreakJumpToLabel == null ? null : currBreakJumpToLabel.asArmLabel();
Label lastContinueJumpToLabel =
currContinueJumpToLabel == null ? null : currContinueJumpToLabel.asArmLabel();
currBreakJumpToLabel = nextLabel;
currContinueJumpToLabel = testLabel;
instructions.add(startLabel);
/* record how much stack parent loop used */
int prevLoopSize = loopStackSize;
loopStackSize = 0;
int prevBreakLoopSize = breakSectionStackSize;
int prevContinueLoopSize = continueSectionStackSize;
breakSectionStackSize = 0;
continueSectionStackSize = 0;
/* 3 loop body */
visit(node.getBody());
/* restore parent loop stack size */
loopStackSize = prevLoopSize;
breakSectionStackSize = prevBreakLoopSize;
continueSectionStackSize = prevContinueLoopSize;
currBreakJumpToLabel = lastBreakJumpToLabel;
currContinueJumpToLabel = lastContinueJumpToLabel;
......@@ -863,32 +944,35 @@ public class ARMInstructionGenerator extends InstructionGenerator<ARMInstruction
Label incrementLabel = branchLabelGenerator.getLabel().asArmLabel();
/* restore the last jump-to label after visiting the for-loop body */
Label lastBreakJumpToLabel = currBreakJumpToLabel;
Label lastContinueJumpToLabel = currContinueJumpToLabel;
Label lastBreakJumpToLabel =
currBreakJumpToLabel == null ? null : currBreakJumpToLabel.asArmLabel();
Label lastContinueJumpToLabel =
currContinueJumpToLabel == null ? null : currContinueJumpToLabel.asArmLabel();
currBreakJumpToLabel = nextLabel;
currContinueJumpToLabel = incrementLabel;
instructions.add(new B(NULL, condLabel.getName()));
instructions.add(bodyLabel);
currForLoopSymbolTable = node.getBody().getScope();
/* record now much stack loop body have occupied */
int prevLoopSize = loopStackSize;
loopStackSize = 0;
int prevBreakLoopSize = breakSectionStackSize;
int prevContinueLoopSize = continueSectionStackSize;
breakSectionStackSize = 0;
continueSectionStackSize = 0;
visit(node.getBody());
/* restore parent loop stack size */
loopStackSize = prevLoopSize;
breakSectionStackSize = prevBreakLoopSize;
continueSectionStackSize = prevContinueLoopSize;
/* here we also need to append the for-loop increment at the end */
instructions.add(incrementLabel);
visit(node.getIncrement());
currBreakJumpToLabel = lastBreakJumpToLabel;
Label afterLabel = branchLabelGenerator.getLabel();
currContinueJumpToLabel = afterLabel;
currContinueJumpToLabel = lastContinueJumpToLabel;
/* 3 add label for condition checking */
instructions.add(condLabel);
......@@ -914,15 +998,12 @@ public class ARMInstructionGenerator extends InstructionGenerator<ARMInstruction
@Override
public Void visitJumpNode(JumpNode node) {
List<Instruction> addStack = new ArrayList<>();
/* this snippet is to deal with for-loop stack difference */
if (!node.getJumpType().equals(JumpType.BREAK) || !node.getJumpContext().equals(JumpContext.SWITCH)) {
incStack(loopStackSize);
}
if (node.getJumpType().equals(JumpType.BREAK)) {
/* this snippet is to deal with for-loop stack difference */
incStack(breakSectionStackSize);
instructions.add(new B(NULL, currBreakJumpToLabel.getName()));
} else if (node.getJumpType().equals(JumpType.CONTINUE)) {
incStack(continueSectionStackSize);
instructions.add(new B(NULL, currContinueJumpToLabel.getName()));
}
......@@ -948,19 +1029,29 @@ public class ARMInstructionGenerator extends InstructionGenerator<ARMInstruction
Label afterLabel = branchLabelGenerator.getLabel().asArmLabel();
/* restore the jump-to label after visiting the switch cases and default */
Label lastBreakJumpToLabel = currBreakJumpToLabel;
Label lastBreakJumpToLabel =
currBreakJumpToLabel == null ? null : currBreakJumpToLabel.asArmLabel();
currBreakJumpToLabel = afterLabel;
instructions.add(new B(NULL, defaultLabel.getName()));
for (int i = 0; i < cLabels.size(); i++) {
instructions.add(cLabels.get(i));
/* record now much stack switch body have occupied */
int prevLoopSize = breakSectionStackSize;
breakSectionStackSize = 0;
visit(node.getCases().get(i).getBody());
/* restore parent switch stack size */
breakSectionStackSize = prevLoopSize;
}
int prevLoopSize = breakSectionStackSize;
breakSectionStackSize = 0;
instructions.add(defaultLabel);
visit(node.getDefault());
breakSectionStackSize = prevLoopSize;
currBreakJumpToLabel = lastBreakJumpToLabel;
instructions.add(afterLabel);
......
......@@ -11,32 +11,40 @@ public class Operand2 extends Address {
private final ARMImmediate immed;
private final Operand2Operator operator;
private final Register Rm;
private Operand2(Register Rm, Operand2Operator operator, ARMImmediate immed) {
private final Register Rs;
private Operand2(Register Rm, Register Rs, Operand2Operator operator, ARMImmediate immed) {
this.immed = immed;
this.operator = operator;
this.Rm = Rm;
this.Rs = Rs;
}
public Operand2(Register Rm, Operand2Operator operator, int intVal) {
this.immed = new ARMImmediate(intVal, BitNum.CONST5);
this.operator = operator;
this.Rm = Rm;
this.Rs = null;
}
public Operand2(ARMImmediate immed) {
this(null, Operand2Operator.NONE, immed);
this(null, null, Operand2Operator.NONE, immed);
}
public Operand2(int intVal) {
this(null, Operand2Operator.NONE, new ARMImmediate(intVal, BitNum.CONST8));
this(null, null, Operand2Operator.NONE, new ARMImmediate(intVal, BitNum.CONST8));
}
public Operand2(Register Rm) {
this(Rm, Operand2Operator.NONE, null);
this(Rm, null, Operand2Operator.NONE, null);
}
public Operand2(Register Rm, Operand2Operator operator) {
this(Rm, operator, null);
this(Rm, null, operator, null);
}
public Operand2(Register Rm, Register Rs, Operand2Operator operator) {
this(Rm, Rs, operator, null);
}
@Override
......@@ -46,12 +54,17 @@ public class Operand2 extends Address {
if (Rm != null) {