FDU 2021 autumn semester Compiler course serial lab. The goal is to complete a LLVM based compiler that can compile C-like simple program.
Environment configuration please refer to /document/lab3.pdf.
To compile and run:
clang++ -g -O3 lab.cpp `llvm-config --cxxflags --ldflags --system-libs --libs all` -std=c++17 -o lab
./lab input_example.data # Generate file "output.o" (Our goal)
clang++ main.cpp output.o -o main # Link
./main # Run
Our goal is to complete these rules:
<program> ::= <gdecl>*<opdef>*<sdef>*<function>*
<gdecl> ::= extern <prototype>;
<opdef> ::= unary <any><intconst><type>(<type><ident>)<body>
|binary <any><intconst><type>(<type><ident>,<type><ident>)<body>
<sdef> ::= struct <ident>{[<type><ident>;]*}
<function> ::= <prototype><body>
<prototype> ::= <type><ident>(<paramlist>)
<paramlist> ::= ε|<type><ident>[,<type><ident>]*
<body> ::= {<stmt>*}
<stmt> ::= <decl>;|<simp>;|<control>|<return>;
<decl> ::= <type><ident>[=<exp>][,<ident>[=<exp>]]*
<simp> ::= <val>=<exp>
<control> ::= if(<exp>)<block>[else<block>]
|while(<exp>)<block>
|for([<decl>];<exp>;[<simp>])<block>
<block> ::= <stmt>|{<stmt>*}
<return> ::= return <exp>
<exp> ::= (<exp>)|<const>|<var>
|<exp><binop><exp>|<unop><exp>
|<callee>
<callee> ::= <ident>(ε|<exp>[,<exp>]*)
<const> ::= <intconst>|<doubleconst>|<charconst>
<var> ::= <ident>[.<ident>]*
<type> ::= int|double|char|struct <ident>
<ident> ::= [A-Z_a-z][0-9A-Z_a-z]*
<unop> ::= <any>
<binop> ::= +|-|*|<|==|!=|<=|<any>
<intconst> ::= [0-9][0-9]*
<doubleconst> ::= <intconst>.<intconst>
<charconst> ::= '<any>'
<any> ::= [^\n]
Compared to the baseline of Lab5, we add these features:
- Support type "char", e.g., char a; a = 'a';.
- Support control flow "for".
- Support a block instead of a single statement in control flow.
- Support the scope of a variable.
- Support assignment in declaration statement, e.g., char a = 'a', b = 'b';.
- Support binary operation "==", "!=" & "<=".
- Support comment start with "#".
- Support user-defined unary & binary operators. (<opdef> above).
- Support struct, but with some limitations. (<sdef> above).
-
We will do type casting between primary data types automatically in binary operations, function arguments, function return type and so on. So feel relaxing to use primary data types.
-
We treat a
char
type as aint
type. It works well. -
We don't support a
boolean
type. We use double type as comparation result. -
A variable in a block will hide the variable with the same name outside the block. For example:
int a = 1; if (...) { double a = 2.2; return a; // 2.2 } return a; // 1
-
We support variable overlap, that is to say, you can define a variable with the same name in a block twice or more. We only use the latest variable definition. For example:
int a = 1; if (...) return a; // 1 double a = 2.2; if (...) return a; // 2.2 char a = 'c'; return c; // 'c'
You may be puzzled why we can return three different primary data types in a function. Don't forget that we will do type casting automatically. See Notes 1.
-
At present, the precedence of a user-defined unary operation is useless, because it always has the lowest precedence. But I'm too lazy to solve the problem.
-
We don't support pointer data type, so we cannot use struct type as argument to call a function in our program, nor can we use struct type as function return type. But we treat struct data type in the function argument list as pointer type, so the driver program (e.g., main.cpp) can use struct data type pointer to invoke our function.
input_example.data
is the C-like program for our compiler to compile.
output_example.data
is the execution output of main.cpp.
output.o
is the binary file generated by our compiler.
main.cpp
contains the main function to run the functions in output.o.
lab
is the executable file compiled from lab.cpp.
lab.cpp
is the source file of our compiler.
test_*/
contains more test cases.
testdriver.cpp
contains the main function to run the test without .cpp file.
test.sh
is the shell script to run the test driver.
document/
contains the lab documents from lab1 to lab5.
README.md
is this file.
- Lab documents (/document/*.pdf)
- LLVM Tutorial