/LLVM_based_compiler

FDU 2021 autumn compiler course lab.

Primary LanguageC++

LLVM Based Simple Compiler

Description

FDU 2021 autumn semester Compiler course serial lab. The goal is to complete a LLVM based compiler that can compile C-like simple program.

Usage

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

Goal

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:

  1. Support type "char", e.g., char a; a = 'a';.
  2. Support control flow "for".
  3. Support a block instead of a single statement in control flow.
  4. Support the scope of a variable.
  5. Support assignment in declaration statement, e.g., char a = 'a', b = 'b';.
  6. Support binary operation "==", "!=" & "<=".
  7. Support comment start with "#".
  8. Support user-defined unary & binary operators. (<opdef> above).
  9. Support struct, but with some limitations. (<sdef> above).

Notes

  1. 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.

  2. We treat a char type as a int type. It works well.

  3. We don't support a boolean type. We use double type as comparation result.

  4. 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
    
  5. 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.

  6. 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.

  7. 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.

Files

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.

Reference

  1. Lab documents (/document/*.pdf)
  2. LLVM Tutorial