Skip to content
C90 to MIPS I Compiler done as a coursework for EE2-15
C++ Assembly Yacc C Lex CMake Other
Branch: master
Clone or download
Latest commit 498cee1 Jul 29, 2019
Type Name Latest commit message Commit time
Failed to load latest commit information.
.vagrant/machines/default/virtualbox Clean Jun 20, 2017
bin Create placeholder Jul 23, 2017
doc Clean Jun 20, 2017
src Clean Jun 20, 2017
test Clean Jun 20, 2017
LICENSE Initial commit Mar 28, 2017 Update Jul 29, 2019
Vagrantfile Clean Jun 20, 2017
makefile Clean Jun 20, 2017 Clean Jun 20, 2017 Clean Jun 20, 2017
ubuntu-xenial-16.04-cloudimg-console.log Clean Jun 20, 2017

C90 to MIPS I Compiler

This is a C90 (ANSI C) to MIPS I compiler. The compiler uses Flex for the lexer, Bison for the parser and virtual functions for the assembly code generation.

The repository also contains parser and lexer in separate directories under the /src directory. It also contains a plenty of tests for all three programs.

More information on the design of the compiler can be seen in the docs.


This piece of work was done in partial fulfilment of a language processors module (EE2-15). The specification for the coursework can be found here.

Currently implemented features

1 - [x] Local variables

2 - [x] Integer arithmetic

3 - [x] While

4 - [x] IfElse, SwitchCase

5 - [x] For

6 - [x] Function calls

7 - [x] Arrays

8 - [x] Pointers

9 - [ ] Strings

10 - [ ] Structures

11 - [ ] Floating-point

Building and Running

It must be run on an environment with Flex and Bison installed, a vagrant file configured to the correct target environment has been included. To deploy the environment you can run vagrant up, vagrant ssh, cd /vagrant/ and finish with exit.

The compiler can built by doing:

make bin/c_compiler

The compiler accepts valid C code through stdin and it will return MIPS 1 code through stdout, for example, if we create a file test.c and we store it under /test/c_compiler/test:

int main(){
  int j = 10;
  int i = 2;
  return i + j;

and then run it via the testing shell script:

./ 1

the file output.s will contain:

	.section .mdebug.abi32
	.nan	legacy
	.module	fp=xx
	.module	nooddspreg

	.align	2
	.globl	main
	.set	nomips16
	.set	nomicromips
	.ent	main
	.type	main, @function
	addiu $sp,$sp,-80
	sw $31,76($sp)	# Storing return address
	sw $fp,72($sp)	# Storing current frame pointer
	move $fp,$sp
	move $t9,$0
	move $2,$0
	move $t0,$0	 #Making Binding j
	sw $t0,0($fp)	 #Saving variable: j
	lw $t0,0($fp)	 #Loading variable: j
	li $t1,10	 #Value to register 10
	move $t0,$t1	 #Assigning value 
	sw $t0,0($fp)	 #Saving variable: j
	move $t1,$0	 #Making Binding i
	sw $t1,4($fp)	 #Saving variable: i
	lw $t1,4($fp)	 #Loading variable: i
	li $t2,2	 #Value to register 2
	move $t1,$t2	 #Assigning value 
	sw $t1,4($fp)	 #Saving variable: i
	move $2,$0
	lw $t1,4($fp)	 #Loading variable: i
	lw $t0,0($fp)	 #Loading variable: j
	add $2,$t1,$t0	 #Adding values 
	 #Releasing binding: i
	 #Releasing binding: j
	 #==Clearing scope context==
	 #==Loading used variables 16-23==
	move $sp,$fp
	lw $fp,72($sp)	# Loading current frame pointer
	lw $31,76($sp)	# Loading return address
	addiu $sp,$sp,80
	j $31

	.set	macro
	.set	reorder
	.end	main
	.size	main, .-main
	.ident	"GCC: (Ubuntu 5.4.0-6ubuntu1~16.04.1) 5.4.0 20160609"

and it will also produce a pretty-print XML structure of the AST:

    <Function id="main" type="int">
                    <Variable id="j" type="int"/>
                <Operator op="="/>
                    <NumberInt value="10"/>
                    <Variable id="i" type="int"/>
                <Operator op="="/>
                    <NumberInt value="2"/>
                        <Variable id="i" type=""/>
                    <Operator op="+"/>
                        <Variable id="j" type=""/>


  • All code was written by Martin Ferianc in 2017.
You can’t perform that action at this time.