aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Thomas <m8pple@github.com>2017-03-09 10:01:27 +0000
committerDavid Thomas <m8pple@github.com>2017-03-09 10:01:27 +0000
commit7922bd0454bc19cc974de7e2f5cf5ef614569782 (patch)
tree9eb38fa047a57a9c545e40ded9c51f4dae901367
parent6baea6b1eeb184ca49f3d2e1961ffd2e43ba8ef4 (diff)
downloadCompiler-7922bd0454bc19cc974de7e2f5cf5ef614569782.tar.gz
Compiler-7922bd0454bc19cc974de7e2f5cf5ef614569782.zip
Transfer in test and documentation parts.
-rw-r--r--3-compiler-documentation.md187
-rw-r--r--3-compiler-test_deliverable.md94
-rw-r--r--3-compiler.md9
-rw-r--r--run_test_deliverable.sh45
-rw-r--r--test_deliverable/c_compiler_ref.sh4
-rw-r--r--test_deliverable/testcases/test_ADD0.c4
-rw-r--r--test_deliverable/testcases/test_ADD0_driver.c7
-rw-r--r--test_deliverable/testcases/test_ADD1.c4
-rw-r--r--test_deliverable/testcases/test_ADD1_driver.c7
-rw-r--r--test_deliverable/testcases/test_CALL.c6
-rw-r--r--test_deliverable/testcases/test_CALL_driver.c12
-rw-r--r--test_deliverable/testcases/test_LOCAL.c6
-rw-r--r--test_deliverable/testcases/test_LOCAL_driver.c6
-rw-r--r--test_deliverable/testcases/test_RETURN.c4
-rw-r--r--test_deliverable/testcases/test_RETURN_driver.c7
-rw-r--r--testing/ref_compiler.sh3
-rw-r--r--testing/testcases/test_ADD.c4
-rw-r--r--testing/testcases/test_ADD_driver.c8
18 files changed, 411 insertions, 6 deletions
diff --git a/3-compiler-documentation.md b/3-compiler-documentation.md
new file mode 100644
index 0000000..9fa5bf3
--- /dev/null
+++ b/3-compiler-documentation.md
@@ -0,0 +1,187 @@
+Documentation
+=============
+
+In total the documentation burden is (at most) 1000 words
+plus one diagram. Assesment of the documentation is not relative
+to compiler functionality, it just requires a description
+of the compiler as-is, and a realistic assessment of the
+compiler's strengths and weaknesses.
+
+
+AST
+===
+
+Overview Diagram
+----------------
+
+_Add a diagram of your AST, which is designed to *usefully* communicate
+the *important* properties of the AST._
+
+- _Use whatever level of detail you feel is appropriate_.
+
+- _You do not need to include every part of the AST, and you
+ don't need to include every class_.
+
+- _Zooming should not be necessary to understand it_.
+
+The file should be called `my-ast.png`. The software used
+to generate the png is up to you, or you can draw it by hand
+and scan it if you wish (though beware the eventual file-size).
+
+![my-ast.png](my-ast.png)
+
+Description
+-----------
+
+_Describe the structure and organisation of your AST in 200 words
+or fewer_.
+
+- _Feel free to refer to your diagram_.
+
+- _Try to capture the most important properties_.
+
+- _You can use code, but it is included in your budget_.
+
+Strengths
+---------
+
+_Give two strengths or capabilites of your AST, using 50 words or less for each one_.
+
+### Strength 1
+
+_50 words or less_
+
+### Strength 2
+
+_50 words or less_
+
+Limitations
+-----------
+
+_Give two limitations of your AST, using 50 words or less for each one_.
+
+### Limitation 1
+
+_50 words or less_
+
+### Limitation 2
+
+_50 words or less_
+
+
+Variable binding
+================
+
+General approach
+----------------
+
+_Describe your overall approach to mapping variable, parameters, etc.
+into registers or memory locations at exection time, using 200 words
+or less_.
+
+- _how did you manage registers?_
+- _did you use the stack?_
+- _is there a function or API for managing and looking up bindings?_
+
+_200 words or less_
+
+Strengths
+---------
+
+_Give two strengths or capabilites of your binding approach, using 50 words or less for each one_.
+
+### Strength 1
+
+_50 words or less_
+
+### Strength 2
+
+_50 words or less_
+
+Limitations
+-----------
+
+_Give two limitations of your binding approach, using 50 words or less for each one_.
+
+### Limitation 1
+
+_50 words or less_
+
+### Limitation 2
+
+_50 words or less_
+
+
+Reflection
+==========
+
+Strengths
+---------
+
+_What two aspects of your compiler do you think work well (beyond
+those identified in the AST and binding parts)?_
+
+### Strength 1
+
+_50 words or fewer_
+
+### Strength 2
+
+_50 words or fewer_
+
+Scope for Improvment
+---------------------
+
+_What parts of your compiler do you think could be improved?_
+
+- _This is not looking for things like "It should support more C constructs". What
+ would you need to do or change in order to support those things?_
+
+### Improvement 1
+
+_50 words or fewer_
+
+### Improvement 2
+
+_50 words or fewer_
+
+
+Functionality (not assessed)
+============================
+
+Which of these features does your compiler support (insert
+an `x` to check a box):
+
+1 - [ ] Local variables
+2 - [ ] Integer arithmetic
+3 - [ ] While
+4 - [ ] IfElse
+5 - [ ] For
+6 - [ ] Function calls
+7 - [ ] Arrays
+8 - [ ] Pointers
+9 - [ ] Strings
+10 - [ ] Structures
+11 - [ ] Floating-point
+
+Note that all features will be tested, regardless of what
+appears here. This is documentation of what you expect to work,
+versus what doesn't work.
+
+
+Feedback (not assessed)
+=======================
+
+_What aspects of your compiler would you like feedback on.
+Be specific, as "what could I have done differently" is
+too general to answer._
+
+### Feedback 1
+
+_20 words or fewer_
+
+### Feedback 2
+
+_20 words or fewer_
+
+
diff --git a/3-compiler-test_deliverable.md b/3-compiler-test_deliverable.md
new file mode 100644
index 0000000..71ce1b2
--- /dev/null
+++ b/3-compiler-test_deliverable.md
@@ -0,0 +1,94 @@
+Test Deliverable
+================
+
+You need test programs in order to check whether your compiler
+emits code that actually works. Writing test-cases is quite
+a skill, and it is very difficult to get good test coverage.
+As much as possible you should develop independent test-cases
+which look at individual features you are working on. Also, once
+a test-case is successfully passed, no future features should
+stop that test-case passing. The situation where the addition
+of something new stops something old working is generally
+called a _regression_, and _regression testing _is used to
+make sure that functionality doesn't go backwards.
+
+In order to do regression testing, you need two things:
+
+1 - A set of test-cases.
+
+2 - An automated system for running the test-cases.
+
+A simple version of the latter will be developed in the
+lecture, then committed here. Your job is to develop five
+test cases for five language features. There is no requirement
+that your compiler implements these features, only that
+your test-cases try to test them.
+
+Test case format
+----------------
+
+Each test case has a name ${NAME}, and consists of two files:
+
+- `${NAME}.c` : The source file to be compiled by the compiler under test.
+ This should be very minimal, and use the smallest amount of code needed
+ to perform the test.
+
+- `${NAME}_driver.c` : A driver file to be compiled by GCC, which knows how
+ to invoke the functionality in the tested file. This can contain any
+ C code at all, as it will be compiled by GCC.
+
+The testing process for a test-case is then:
+
+1 - Compile `${NAME}.c` using the compiler under test into assembly.
+
+2 - Compile `${NAME}_driver.c` using MIPS GCC.
+
+3 - Link the generated assembly and the driver object into a MIPS executable.
+
+4 - Run the executable under QEMU
+
+5 - If the executable returns 1 (via `$?` in the shell), then the test-case has passed.
+
+If any of these steps fail, then either the test-case is malformed,
+or the compiler under test is not generating correct code.
+
+Required tests
+--------------
+
+The requirements for the deliverable are to create ten tests:
+
+1 - IFT : Can the compiled code correctly execute a branch of an if.
+
+2 - IFF : Can the compiled code correctly not execute a branch of an if.
+
+3 - IFELSET : Test that an if else condition correctly executes the true branch.
+
+4 - IFELSEF : Test that an if else condition correctly executes the false branch.
+
+5 - WHILE0 : Check that a while loop can execute zero times.
+
+6 - WHILEN : Check that a while loop can execute more than once.
+
+7 - RECURSION : A minimal test that recursive function calls work.
+
+8 - GLOBAL : Check that global variables can be shared between object files.
+
+9 - MAIN : Check that the compiler under test can emit a valid `main` entry point.
+
+10 - ATOI : Check that the generated code can call the C function `atoi` (note
+ that `atoi` is just a function, so all you need is the declaration for
+ `atoi` - you don't need to be able to handle all of the C standard library
+ header).
+
+Note that these tests do not reflect either a required level
+of achievement for your compiler, nor should they mean that
+you can't add other tests.
+
+Submitted files
+---------------
+
+Your tests cases should be included in a folder called
+
+ test_deliverable/test_cases
+
+and follow the name convention in the example files.
diff --git a/3-compiler.md b/3-compiler.md
index 7ac2fe7..b05d373 100644
--- a/3-compiler.md
+++ b/3-compiler.md
@@ -16,7 +16,7 @@ The output format should be MIPS1 assembly code.
It should be possible to assemble and link this code
against a C run-time, and have it execute correctly
-on a MIPS processor.
+on a MIPS processor as emulated by `qemu-mips`.
Compilation
-----------
@@ -36,10 +36,7 @@ There are actually three deliverables here:
1 - The compiler itself
-2 - A test framework
+2 - A [test framework](3-compiler-test_deliverable.md)
-3 - Documentation
+3 - [Documentation](3-compiler-documentation.md)
-There are certain requirements on test and a format for the
-documentation, but we'll elaborate on those when they are
-encountered in the course.
diff --git a/run_test_deliverable.sh b/run_test_deliverable.sh
new file mode 100644
index 0000000..f77e8b7
--- /dev/null
+++ b/run_test_deliverable.sh
@@ -0,0 +1,45 @@
+#!/bin/bash
+
+if [[ -z "$1" ]]; then
+ COMPILER=bin/c_compiler
+else
+ COMPILER=$1
+fi
+
+mkdir -p working
+
+for DRIVER in test_deliverable/testcases/*_driver.c ; do
+ NAME=$(basename $DRIVER _driver.c)
+ TESTCODE=test_deliverable/testcases/$NAME.c
+
+ >&2 echo "Test case $NAME"
+
+ # Compile driver with normal GCC
+ mips-linux-gnu-gcc -c $DRIVER -o working/${NAME}_driver.o 2> working/${NAME}_driver.compile.stderr
+ if [[ $? -ne 0 ]]; then
+ >&2 echo "ERROR : Couldn't compile driver program using GCC."
+ continue
+ fi
+
+ # Compile test function with compiler under test to assembly
+ cat $TESTCODE | $COMPILER > working/$NAME.s 2> working/${NAME}.compile.stderr
+ if [[ $? -ne 0 ]]; then
+ >&2 echo "ERROR : Compiler returned error message."
+ continue
+ fi
+
+ # Link driver object and assembly into executable
+ mips-linux-gnu-gcc -static working/${NAME}.s working/${NAME}_driver.o -o working/${NAME}.elf 2> working/${NAME}.link.stderr
+ if [[ $? -ne 0 ]]; then
+ >&2 echo "ERROR : Linker returned error message."
+ continue
+ fi
+
+ # Run the actual executable
+ qemu-mips working/${NAME}.elf
+ if [[ $? -ne 1 ]]; then
+ >&2 echo "ERROR : Testcase returned $?, but expected 0."
+ fi
+
+
+done
diff --git a/test_deliverable/c_compiler_ref.sh b/test_deliverable/c_compiler_ref.sh
new file mode 100644
index 0000000..a55b56d
--- /dev/null
+++ b/test_deliverable/c_compiler_ref.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+
+mips-linux-gnu-gcc -c -S -x c - -o -
+exit $?
diff --git a/test_deliverable/testcases/test_ADD0.c b/test_deliverable/testcases/test_ADD0.c
new file mode 100644
index 0000000..62bb292
--- /dev/null
+++ b/test_deliverable/testcases/test_ADD0.c
@@ -0,0 +1,4 @@
+int f(int a, int b)
+{
+ return a+b;
+}
diff --git a/test_deliverable/testcases/test_ADD0_driver.c b/test_deliverable/testcases/test_ADD0_driver.c
new file mode 100644
index 0000000..383949c
--- /dev/null
+++ b/test_deliverable/testcases/test_ADD0_driver.c
@@ -0,0 +1,7 @@
+
+int f(int x, int y);
+
+int main()
+{
+ return 40 == f(30,10);
+}
diff --git a/test_deliverable/testcases/test_ADD1.c b/test_deliverable/testcases/test_ADD1.c
new file mode 100644
index 0000000..88f1864
--- /dev/null
+++ b/test_deliverable/testcases/test_ADD1.c
@@ -0,0 +1,4 @@
+int f(int a)
+{
+ return a+10;
+}
diff --git a/test_deliverable/testcases/test_ADD1_driver.c b/test_deliverable/testcases/test_ADD1_driver.c
new file mode 100644
index 0000000..c0e447b
--- /dev/null
+++ b/test_deliverable/testcases/test_ADD1_driver.c
@@ -0,0 +1,7 @@
+
+int f(int x);
+
+int main()
+{
+ return 40 == f(30);
+}
diff --git a/test_deliverable/testcases/test_CALL.c b/test_deliverable/testcases/test_CALL.c
new file mode 100644
index 0000000..2aef1c7
--- /dev/null
+++ b/test_deliverable/testcases/test_CALL.c
@@ -0,0 +1,6 @@
+int g();
+
+int f()
+{
+ return g();
+}
diff --git a/test_deliverable/testcases/test_CALL_driver.c b/test_deliverable/testcases/test_CALL_driver.c
new file mode 100644
index 0000000..8bbc3a8
--- /dev/null
+++ b/test_deliverable/testcases/test_CALL_driver.c
@@ -0,0 +1,12 @@
+
+int f();
+
+int g()
+{
+ return 10;
+}
+
+int main()
+{
+ return 10==f();
+}
diff --git a/test_deliverable/testcases/test_LOCAL.c b/test_deliverable/testcases/test_LOCAL.c
new file mode 100644
index 0000000..f8d1629
--- /dev/null
+++ b/test_deliverable/testcases/test_LOCAL.c
@@ -0,0 +1,6 @@
+int ffff()
+{
+ int x;
+ x=10;
+ return x;
+}
diff --git a/test_deliverable/testcases/test_LOCAL_driver.c b/test_deliverable/testcases/test_LOCAL_driver.c
new file mode 100644
index 0000000..277543b
--- /dev/null
+++ b/test_deliverable/testcases/test_LOCAL_driver.c
@@ -0,0 +1,6 @@
+int ffff();
+
+int main()
+{
+ return ffff()==10;
+}
diff --git a/test_deliverable/testcases/test_RETURN.c b/test_deliverable/testcases/test_RETURN.c
new file mode 100644
index 0000000..f48f9b5
--- /dev/null
+++ b/test_deliverable/testcases/test_RETURN.c
@@ -0,0 +1,4 @@
+int f()
+{
+ return 10;
+}
diff --git a/test_deliverable/testcases/test_RETURN_driver.c b/test_deliverable/testcases/test_RETURN_driver.c
new file mode 100644
index 0000000..dfc0e19
--- /dev/null
+++ b/test_deliverable/testcases/test_RETURN_driver.c
@@ -0,0 +1,7 @@
+
+int f();
+
+int main()
+{
+ return 10==f();
+}
diff --git a/testing/ref_compiler.sh b/testing/ref_compiler.sh
new file mode 100644
index 0000000..b5425b0
--- /dev/null
+++ b/testing/ref_compiler.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+mips-linux-gnu-gcc -c -S -x c - -o -
diff --git a/testing/testcases/test_ADD.c b/testing/testcases/test_ADD.c
new file mode 100644
index 0000000..327dc85
--- /dev/null
+++ b/testing/testcases/test_ADD.c
@@ -0,0 +1,4 @@
+int f(int a, int b)
+{
+ return 1;
+}
diff --git a/testing/testcases/test_ADD_driver.c b/testing/testcases/test_ADD_driver.c
new file mode 100644
index 0000000..9e74f32
--- /dev/null
+++ b/testing/testcases/test_ADD_driver.c
@@ -0,0 +1,8 @@
+int f(int a, int b);
+
+int main()
+{
+ int r=f(10,11);
+
+ return r == 21;
+}