Commit b42a3f3f authored by 徐世桐's avatar 徐世桐
Browse files

Merge branch 'master' into develop

parents b798cdd8 ca5ed482
...@@ -10,6 +10,7 @@ stages: ...@@ -10,6 +10,7 @@ stages:
- build - build
- frontend-test - frontend-test
- backend-test - backend-test
- optimise-test
build-job: build-job:
stage: build stage: build
...@@ -57,6 +58,17 @@ test-execute-valid: ...@@ -57,6 +58,17 @@ test-execute-valid:
- echo "Making arm executable for each assembly file and trying to execute them..." - echo "Making arm executable for each assembly file and trying to execute them..."
- ./scripts/assembleExecuteTest - ./scripts/assembleExecuteTest
- ./scripts/executeOutputTest - ./scripts/executeOutputTest
artifacts:
paths:
- log/assembly
- log/output
test-optimise:
stage: optimise-test
script:
- echo "compile oprimise sample tests and conpair with given .log result file"
- ./scripts/constantPropagationTest.sh
- ./scripts/extensionValidTest.sh
artifacts: artifacts:
paths: paths:
- log/assembly - log/assembly
......
...@@ -131,8 +131,7 @@ expr : INT_LITER #IntExpr ...@@ -131,8 +131,7 @@ expr : INT_LITER #IntExpr
| expr bop=( '+' | '-' ) expr #ArithmeticExpr | expr bop=( '+' | '-' ) expr #ArithmeticExpr
| expr bop=( '>' | '>=' | '<' | '<=' ) expr #CmpExpr | expr bop=( '>' | '>=' | '<' | '<=' ) expr #CmpExpr
| expr bop=( '==' | '!=' ) expr #EqExpr | expr bop=( '==' | '!=' ) expr #EqExpr
| expr '&' expr #BitwiseAndExpr | expr bitop=( '&' | '|' ) expr #BitwiseExpr
| expr '|' expr #BitwiseOrExpr
| expr '&&' expr #AndExpr | expr '&&' expr #AndExpr
| expr '||' expr #OrExpr | expr '||' expr #OrExpr
| OPEN_PARENTHESES expr CLOSE_PARENTHESES #ParenExpr | OPEN_PARENTHESES expr CLOSE_PARENTHESES #ParenExpr
......
...@@ -39,4 +39,5 @@ then ...@@ -39,4 +39,5 @@ then
fi fi
# compile the given wacc file here # compile the given wacc file here
java -cp ./bin:./lib/antlr-4.9.1-complete.jar Compiler $1 $PARSE_ONLY $PRINT_AST $OPTIMISE "--assembly" $EXECUTE # default as using -o1 optimise and generate assembly
\ No newline at end of file java -cp ./bin:./lib/antlr-4.9.1-complete.jar Compiler $1 $PARSE_ONLY $PRINT_AST $OPTIMISE "--optimise" "1" "--assembly" $EXECUTE
\ No newline at end of file
...@@ -7,4 +7,6 @@ ...@@ -7,4 +7,6 @@
./scripts/semanticCheckerValid ./scripts/semanticCheckerValid
./scripts/semanticCheckerSemanticErr ./scripts/semanticCheckerSemanticErr
./scripts/assembleTest.sh ./scripts/assembleTest.sh
./scripts/executeTest.sh ./scripts/executeTest.sh
\ No newline at end of file ./scripts/constantPropagation.sh
./scripts/extensionValidTest.sh
\ No newline at end of file
#!/bin/bash #!/bin/bash
VALID_EXAMPLE_DIR="./src/test/examples/valid/"
VALID_EXAMPLES=( VALID_EXAMPLES=(
"/constantPropagation/evaluation/" "/propagation"
# "/evaluation"
) )
VALID_EXAMPLE_LOG="./log/const_eval.log" VALID_EXAMPLES_SRC_DIR="./src/test/custom/valid/constantPropagation"
> $VALID_EXAMPLE_LOG ASSEMBLY_OUTPUT_DIR="./log/assembly/constantPropagation"
mkdir log
mkdir $ASSEMBLY_OUTPUT_DIR
TEST_DIR="$VALID_EXAMPLE_DIR$VALID_EXAMPLES"
# counters to represent the total number of test files to be processed # counters to represent the total number of test files to be processed
TOTAL_COUNT=$(find "$VALID_EXAMPLE_DIR${VALID_EXAMPLES[@]}" -name "*.wacc" | wc -l) TOTAL_COUNT=$(find "${VALID_EXAMPLES[@]/#/${VALID_EXAMPLES_SRC_DIR}}" -name "*.wacc" | wc -l)
COUNTER=0 COUNTER=0
for folder in "$VALID_EXAMPLE_DIR${VALID_EXAMPLES[@]}"; do for folder in ${VALID_EXAMPLES[@]}; do
for file in $(find "$folder" -name "*.wacc"); do ASSEMBLY_OUTPUT_VALID_FOLDER="${ASSEMBLY_OUTPUT_DIR}${folder}"
mkdir $ASSEMBLY_OUTPUT_VALID_FOLDER
for file in $(find "${VALID_EXAMPLES_SRC_DIR}${folder}" -name "*.wacc")
do
FILE_NAME=$(basename "${file%.*}") FILE_NAME=$(basename "${file%.*}")
./compile -o1 -t $file 2> $VALID_EXAMPLE_LOG EXECUTABLE_FILE_NAME="${ASSEMBLY_OUTPUT_VALID_FOLDER}/${FILE_NAME}"
ret=$? echo $file
echo "exit status: " $ret ./compile -t -o1 $file > "${EXECUTABLE_FILE_NAME}.log.txt"
if [ $ret -ne 0 ]; then
echo $file if diff "${EXECUTABLE_FILE_NAME}.log.txt" "${VALID_EXAMPLES_SRC_DIR}${folder}/${FILE_NAME}.log" -I scope; then
echo "status code incorrect: " $ret (( COUNTER += 1 ))
exit 1
fi
if diff "$TEST_DIR${FILE_NAME}.log" $VALID_EXAMPLE_LOG > temp; then
echo $FILE_NAME
echo "optimise differ from expected result: "
exit 1
fi fi
(( COUNTER += 1 ))
echo "$COUNTER / $(($TOTAL_COUNT)) finished"
echo "" echo "$COUNTER / $(($TOTAL_COUNT)) files have been executed"
done done
echo "========================================================================================" echo "========================================================================================"
......
...@@ -5,8 +5,8 @@ VALID_EXAMPLES=( ...@@ -5,8 +5,8 @@ VALID_EXAMPLES=(
"/bitwiseOperation" "/bitwiseOperation"
"/do-while" "/do-while"
"/for" "/for"
"/import" # OK "/import"
"/jump" # OK "/jump"
"/struct" "/struct"
"/switch" "/switch"
) )
...@@ -35,6 +35,8 @@ for folder in ${VALID_EXAMPLES[@]}; do ...@@ -35,6 +35,8 @@ for folder in ${VALID_EXAMPLES[@]}; do
EXECUTABLE_OUTPUT_FILE="${EXECUTE_OUTPUT_VALID_FOLDER}/${FILE_NAME}" EXECUTABLE_OUTPUT_FILE="${EXECUTE_OUTPUT_VALID_FOLDER}/${FILE_NAME}"
echo $file echo $file
./compile $file 2> "${EXECUTABLE_FILE_NAME}.log.txt" ./compile $file 2> "${EXECUTABLE_FILE_NAME}.log.txt"
echo "${EXECUTABLE_FILE_NAME}.s"
echo "${FILE_NAME}.s"
mv "${FILE_NAME}.s" "${EXECUTABLE_FILE_NAME}.s" mv "${FILE_NAME}.s" "${EXECUTABLE_FILE_NAME}.s"
arm-linux-gnueabi-gcc -o $EXECUTABLE_OUTPUT_FILE -mcpu=arm1176jzf-s -mtune=arm1176jzf-s "${EXECUTABLE_FILE_NAME}.s" > "${EXECUTABLE_OUTPUT_FILE}.log.txt" arm-linux-gnueabi-gcc -o $EXECUTABLE_OUTPUT_FILE -mcpu=arm1176jzf-s -mtune=arm1176jzf-s "${EXECUTABLE_FILE_NAME}.s" > "${EXECUTABLE_OUTPUT_FILE}.log.txt"
...@@ -45,11 +47,11 @@ for folder in ${VALID_EXAMPLES[@]}; do ...@@ -45,11 +47,11 @@ for folder in ${VALID_EXAMPLES[@]}; do
echo "execution exit status" $ret2 echo "execution exit status" $ret2
## altomatically generate output .log file ## altomatically generate output .log file
mv "${EXECUTABLE_OUTPUT_FILE}.output.txt" "${VALID_EXAMPLES_SRC_DIR}${folder}/${FILE_NAME}.log" # mv "${EXECUTABLE_OUTPUT_FILE}.output.txt" "${VALID_EXAMPLES_SRC_DIR}${folder}/${FILE_NAME}.log"
if [ "$ret1" -eq 0 ] && [ "$ret2" -eq 0 ]; then if [ "$ret1" -eq 0 ] && [ "$ret2" -eq 0 ]; then
## test if output is same as .log file ## test if output is same as .log file
# diff "${EXECUTABLE_OUTPUT_FILE}.output.txt" "${VALID_EXAMPLES_SRC_DIR}${folder}/${FILE_NAME}.log" diff "${EXECUTABLE_OUTPUT_FILE}.output.txt" "${VALID_EXAMPLES_SRC_DIR}${folder}/${FILE_NAME}.log"
(( COUNTER += 1 )) (( COUNTER += 1 ))
fi fi
......
...@@ -64,13 +64,13 @@ public class Compiler { ...@@ -64,13 +64,13 @@ public class Compiler {
int optimise_cmd_index = cmd_ops.indexOf("--optimise"); int optimise_cmd_index = cmd_ops.indexOf("--optimise");
/* if not found optimise flag, no optimise */ if (optimise_cmd_index != 0) {
if (optimise_cmd_index == 0) {
String optimise_level = cmd_ops.get(optimise_cmd_index + 1); String optimise_level = cmd_ops.get(optimise_cmd_index + 1);
switch (optimise_level) { switch (optimise_level) {
case "0": case "0":
break; break;
case "1": case "1":
System.out.println("optimising using const propagate");
NodeVisitor<Node> constPropOptimiser = new ConstantPropagation(); NodeVisitor<Node> constPropOptimiser = new ConstantPropagation();
program = constPropOptimiser.visit(program); program = constPropOptimiser.visit(program);
break; break;
......
...@@ -83,6 +83,9 @@ public class ARMInstructionGenerator implements NodeVisitor<Void> { ...@@ -83,6 +83,9 @@ public class ARMInstructionGenerator implements NodeVisitor<Void> {
no need to distinguish function and non function scope, as non function scope does not call return */ no need to distinguish function and non function scope, as non function scope does not call return */
private int funcStackSize; private int funcStackSize;
/* 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,
...@@ -683,16 +686,11 @@ public class ARMInstructionGenerator implements NodeVisitor<Void> { ...@@ -683,16 +686,11 @@ public class ARMInstructionGenerator implements NodeVisitor<Void> {
/* 1 leave space for variables in stack */ /* 1 leave space for variables in stack */
int stackSize = node.getStackSize(); int stackSize = node.getStackSize();
int temp = stackSize; decStack(stackSize);
while (temp > 0) {
int realStackSize = temp / MAX_STACK_STEP >= 1 ? MAX_STACK_STEP : temp;
instructions.add(new Sub(SP, SP,
new Operand2(realStackSize)));
temp = temp - realStackSize;
}
/* 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;
/* 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 */
...@@ -704,15 +702,10 @@ public class ARMInstructionGenerator implements NodeVisitor<Void> { ...@@ -704,15 +702,10 @@ public class ARMInstructionGenerator implements NodeVisitor<Void> {
/* 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;
/* 3 restore stack */ /* 3 restore stack */
temp = stackSize; incStack(stackSize);
while (temp > 0) {
int realStackSize = temp / MAX_STACK_STEP >= 1 ? MAX_STACK_STEP : temp;
instructions.add(new Add(SP, SP,
new Operand2(realStackSize)));
temp = temp - realStackSize;
}
return null; return null;
} }
...@@ -743,8 +736,15 @@ public class ARMInstructionGenerator implements NodeVisitor<Void> { ...@@ -743,8 +736,15 @@ public class ARMInstructionGenerator implements NodeVisitor<Void> {
instructions.add(startLabel); instructions.add(startLabel);
/* record how much stack parent loop used */
int prevLoopSize = loopStackSize;
loopStackSize = 0;
/* 3 loop body */ /* 3 loop body */
visit(node.getBody()); visit(node.getBody());
/* restore parent loop stack size */
loopStackSize = prevLoopSize;
currBreakJumpToLabel = lastBreakJumpToLabel; currBreakJumpToLabel = lastBreakJumpToLabel;
currContinueJumpToLabel = lastContinueJumpToLabel; currContinueJumpToLabel = lastContinueJumpToLabel;
...@@ -863,86 +863,78 @@ public class ARMInstructionGenerator implements NodeVisitor<Void> { ...@@ -863,86 +863,78 @@ public class ARMInstructionGenerator implements NodeVisitor<Void> {
@Override @Override
public Void visitForNode(ForNode node) { public Void visitForNode(ForNode node) {
/* 1 translate the initiator of the for-loop */ /* 1 translate the initiator of the for-loop */
currSymbolTable = node.getIncrement().getScope();
int stackSize = currSymbolTable.getSize();
decStack(stackSize);
visit(node.getInit()); visit(node.getInit());
/* 2 create labels and translate for for-loop body */ /* 2 create labels and translate for for-loop body */
Label bodyLabel = branchLabelGenerator.getLabel(); Label bodyLabel = branchLabelGenerator.getLabel();
Label condLabel = branchLabelGenerator.getLabel(); Label condLabel = branchLabelGenerator.getLabel();
Label nextLabel = branchLabelGenerator.getLabel(); Label nextLabel = branchLabelGenerator.getLabel();
Label incrementLabel = branchLabelGenerator.getLabel();
/* restore the last jump-to label after visiting the for-loop body */ /* restore the last jump-to label after visiting the for-loop body */
Label lastBreakJumpToLabel = currBreakJumpToLabel; Label lastBreakJumpToLabel = currBreakJumpToLabel;
Label lastContinueJumpToLabel = currContinueJumpToLabel; Label lastContinueJumpToLabel = currContinueJumpToLabel;
currBreakJumpToLabel = nextLabel; currBreakJumpToLabel = nextLabel;
currContinueJumpToLabel = condLabel; currContinueJumpToLabel = incrementLabel;
instructions.add(new B(NULL, condLabel.getName())); instructions.add(new B(NULL, condLabel.getName()));
instructions.add(bodyLabel); instructions.add(bodyLabel);
currForLoopSymbolTable = node.getBody().getScope(); currForLoopSymbolTable = node.getBody().getScope();
/* record now much stack loop body have occupied */
int prevLoopSize = loopStackSize;
loopStackSize = 0;
visit(node.getBody()); visit(node.getBody());
/* restore parent loop stack size */
loopStackSize = prevLoopSize;
/* here we also need to append the for-loop increment at the end */
instructions.add(incrementLabel);
visit(node.getIncrement());
currBreakJumpToLabel = lastBreakJumpToLabel; currBreakJumpToLabel = lastBreakJumpToLabel;
currContinueJumpToLabel = lastContinueJumpToLabel; currContinueJumpToLabel = lastContinueJumpToLabel;
/* here we also need to append the for-loop in crement at the end */
visit(node.getIncrement());
/* 3 add label for condition checking */ /* 3 add label for condition checking */
instructions.add(condLabel); instructions.add(condLabel);
currSymbolTable = node.getBody().getScope();
/* TODO: better code quality here */ currSymbolTable = node.getIncrement().getScope();
int stackSize = currSymbolTable.getSize();
int temp = stackSize;
while (temp > 0) {
int realStackSize = temp / MAX_STACK_STEP >= 1 ? MAX_STACK_STEP : temp;
instructions.add(new Sub(SP, SP,
new Operand2(realStackSize)));
temp = temp - realStackSize;
}
visit(node.getCond()); visit(node.getCond());
temp = stackSize;
while (temp > 0) {
int realStackSize = temp / MAX_STACK_STEP >= 1 ? MAX_STACK_STEP : temp;
instructions.add(new Add(SP, SP,
new Operand2(realStackSize)));
temp = temp - realStackSize;
}
currSymbolTable = currSymbolTable.getParentSymbolTable(); currSymbolTable = currSymbolTable.getParentSymbolTable();
instructions.add(new Cmp(armRegAllocator.curr(), new Operand2(TRUE))); instructions.add(new Cmp(armRegAllocator.curr(), new Operand2(TRUE)));
armRegAllocator.free(); armRegAllocator.free();
/* 4 conditional branch jump to the start of loop */ /* 4 conditional branch jump to the start of loop */
instructions.add(new B(EQ, bodyLabel.getName())); instructions.add(new B(EQ, bodyLabel.getName()));
/* 5 add the label for the following instructions after for-loop */ /* 5 add the label for the following instructions after for-loop */
instructions.add(nextLabel); instructions.add(nextLabel);
/* loop varient's stack clearing should be after next label,
so that BREAK can add back stack used by varients */
incStack(stackSize);
return null; return null;
} }
@Override @Override
public Void visitJumpNode(JumpNode node) { public Void visitJumpNode(JumpNode node) {
Instruction addStack = null; List<Instruction> addStack = new ArrayList<>();
/* this snippet is to deal with for-loop stack difference */ /* this snippet is to deal with for-loop stack difference */
if (currForLoopSymbolTable != null && !node.getJumpContext().equals(JumpContext.SWITCH)) { if (!node.getJumpType().equals(JumpType.BREAK) || !node.getJumpContext().equals(JumpContext.SWITCH)) {
int stackSize = currForLoopSymbolTable.getSize(); incStack(loopStackSize);
int temp = stackSize;
while (temp > 0) {
int realStackSize = temp / MAX_STACK_STEP >= 1 ? MAX_STACK_STEP : temp;
addStack = new Add(SP, SP,
new Operand2(realStackSize));
temp = temp - realStackSize;
}
} }
if (node.getJumpType().equals(JumpType.BREAK)) { if (node.getJumpType().equals(JumpType.BREAK)) {
if (addStack != null) instructions.add(addStack);
instructions.add(new B(NULL, currBreakJumpToLabel.getName())); instructions.add(new B(NULL, currBreakJumpToLabel.getName()));
} else if (node.getJumpType().equals(JumpType.CONTINUE)) { } else if (node.getJumpType().equals(JumpType.CONTINUE)) {
/* this snippet is to deal with the for-loop increment */
StatNode increment = node.getForIncrement();
if (increment != null) visit(increment);
if (addStack != null) instructions.add(addStack);
instructions.add(new B(NULL, currContinueJumpToLabel.getName())); instructions.add(new B(NULL, currContinueJumpToLabel.getName()));
} }
...@@ -988,4 +980,22 @@ public class ARMInstructionGenerator implements NodeVisitor<Void> { ...@@ -988,4 +980,22 @@ public class ARMInstructionGenerator implements NodeVisitor<Void> {
return null; return null;
} }
private void incStack(int stackSize) {
while (stackSize > 0) {
int realStackSize = stackSize / MAX_STACK_STEP >= 1 ? MAX_STACK_STEP : stackSize;
instructions.add(new Add(SP, SP,
new Operand2(realStackSize)));
stackSize = stackSize - realStackSize;
}
}
private void decStack(int stackSize) {
while (stackSize > 0) {
int realStackSize = stackSize / MAX_STACK_STEP >= 1 ? MAX_STACK_STEP : stackSize;
instructions.add(new Sub(SP, SP,
new Operand2(realStackSize)));
stackSize = stackSize - realStackSize;
}
}
} }
...@@ -328,12 +328,13 @@ public class ASTPrinter implements NodeVisitor<Void> { ...@@ -328,12 +328,13 @@ public class ASTPrinter implements NodeVisitor<Void> {
/* body */ /* body */
leadingSpace += INDENT_SIZE; leadingSpace += INDENT_SIZE;
visit(node.getBody()); visit(node.getBody());
leadingSpace -= INDENT_SIZE;
appendLeadingSpace();
System.out.print("while "); System.out.print("while ");
visit(node.getCond()); visit(node.getCond());
System.out.println(" :"); System.out.println(" :");
leadingSpace -= INDENT_SIZE;
} else { } else {
System.out.print("while "); System.out.print("while ");
visit(node.getCond()); visit(node.getCond());
...@@ -384,10 +385,16 @@ public class ASTPrinter implements NodeVisitor<Void> { ...@@ -384,10 +385,16 @@ public class ASTPrinter implements NodeVisitor<Void> {
/* for 3 expressions : */ /* for 3 expressions : */
appendLeadingSpace(); appendLeadingSpace();
System.out.print("for "); System.out.print("for ");
leadingSpace += INDENT_SIZE;
visit(node.getInit()); visit(node.getInit());
appendLeadingSpace();
visit(node.getCond()); visit(node.getCond());
visit(node.getIncrement()); visit(node.getIncrement());
System.out.println(" :"); leadingSpace -= INDENT_SIZE;
appendLeadingSpace();
System.out.println(":");
/* body */ /* body */
leadingSpace += INDENT_SIZE; leadingSpace += INDENT_SIZE;
...@@ -406,15 +413,18 @@ public class ASTPrinter implements NodeVisitor<Void> { ...@@ -406,15 +413,18 @@ public class ASTPrinter implements NodeVisitor<Void> {
public Void visitSwitchNode(SwitchNode node) { public Void visitSwitchNode(SwitchNode node) {
/* switch statement */ /* switch statement */
appendLeadingSpace(); appendLeadingSpace();
System.out.println("switch "); System.out.print("switch ");
System.out.println(node.getExpr()); visit(node.getExpr());
System.out.println();
/* switch body */ /* switch body */
leadingSpace += INDENT_SIZE; leadingSpace += INDENT_SIZE;
for (CaseStat c : node.getCases()) { for (CaseStat c : node.getCases()) {
System.out.println("case "); appendLeadingSpace();
System.out.print("case ");
visit(c.getExpr()); visit(c.getExpr());
System.out.println();
/* case body */ /* case body */
leadingSpace += INDENT_SIZE; leadingSpace += INDENT_SIZE;
...@@ -422,9 +432,12 @@ public class ASTPrinter implements NodeVisitor<Void> { ...@@ -422,9 +432,12 @@ public class ASTPrinter implements NodeVisitor<Void> {
leadingSpace -= INDENT_SIZE; leadingSpace -= INDENT_SIZE;
} }
appendLeadingSpace();
System.out.println("default");
leadingSpace += INDENT_SIZE;
visit(node.getDefault()); visit(node.getDefault());
leadingSpace -= INDENT_SIZE; leadingSpace -= 2 * INDENT_SIZE;
return null; return null;
} }
......
...@@ -11,11 +11,7 @@ import java.io.File; ...@@ -11,11 +11,7 @@ import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.*;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import frontend.node.FuncNode; import frontend.node.FuncNode;
import frontend.node.Node; import frontend.node.Node;
...@@ -30,7 +26,6 @@ import frontend.node.expr.BinopNode.Binop; ...@@ -30,7 +26,6 @@ import frontend.node.expr.BinopNode.Binop;
import frontend.node.expr.UnopNode.Unop; import frontend.node.expr.UnopNode.Unop;
import frontend.type.*; import frontend.type.*;
import java.util.Set;