diff options
author | David Thomas <m8pple@github.com> | 2017-03-09 10:01:27 +0000 |
---|---|---|
committer | David Thomas <m8pple@github.com> | 2017-03-09 10:01:27 +0000 |
commit | 7922bd0454bc19cc974de7e2f5cf5ef614569782 (patch) | |
tree | 9eb38fa047a57a9c545e40ded9c51f4dae901367 | |
parent | 6baea6b1eeb184ca49f3d2e1961ffd2e43ba8ef4 (diff) | |
download | Compiler-7922bd0454bc19cc974de7e2f5cf5ef614569782.tar.gz Compiler-7922bd0454bc19cc974de7e2f5cf5ef614569782.zip |
Transfer in test and documentation parts.
-rw-r--r-- | 3-compiler-documentation.md | 187 | ||||
-rw-r--r-- | 3-compiler-test_deliverable.md | 94 | ||||
-rw-r--r-- | 3-compiler.md | 9 | ||||
-rw-r--r-- | run_test_deliverable.sh | 45 | ||||
-rw-r--r-- | test_deliverable/c_compiler_ref.sh | 4 | ||||
-rw-r--r-- | test_deliverable/testcases/test_ADD0.c | 4 | ||||
-rw-r--r-- | test_deliverable/testcases/test_ADD0_driver.c | 7 | ||||
-rw-r--r-- | test_deliverable/testcases/test_ADD1.c | 4 | ||||
-rw-r--r-- | test_deliverable/testcases/test_ADD1_driver.c | 7 | ||||
-rw-r--r-- | test_deliverable/testcases/test_CALL.c | 6 | ||||
-rw-r--r-- | test_deliverable/testcases/test_CALL_driver.c | 12 | ||||
-rw-r--r-- | test_deliverable/testcases/test_LOCAL.c | 6 | ||||
-rw-r--r-- | test_deliverable/testcases/test_LOCAL_driver.c | 6 | ||||
-rw-r--r-- | test_deliverable/testcases/test_RETURN.c | 4 | ||||
-rw-r--r-- | test_deliverable/testcases/test_RETURN_driver.c | 7 | ||||
-rw-r--r-- | testing/ref_compiler.sh | 3 | ||||
-rw-r--r-- | testing/testcases/test_ADD.c | 4 | ||||
-rw-r--r-- | testing/testcases/test_ADD_driver.c | 8 |
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;
+}
|