├── .gitignore ├── Makefile ├── Vagrantfile ├── admin ├── c_compiler.md ├── log.md ├── logo.png ├── management.md └── notes.md ├── compiler_tests ├── Extra │ ├── arrayinit.c │ ├── arrayinit_driver.c │ ├── break_for.c │ ├── break_for_driver.c │ ├── break_while.c │ ├── break_while_driver.c │ ├── continue_for.c │ ├── continue_for_driver.c │ ├── continue_while.c │ ├── continue_while_driver.c │ ├── enum_inst.c │ ├── enum_inst_driver.c │ ├── float_array.c │ ├── float_array_driver.c │ ├── global_array.c │ ├── global_array_driver.c │ ├── global_array_sw.c │ ├── global_array_sw_driver.c │ ├── global_double.c │ ├── global_double_driver.c │ ├── global_float.c │ ├── global_float_driver.c │ ├── global_int.c │ ├── global_int_driver.c │ ├── global_int_sw.c │ ├── global_int_sw_driver.c │ ├── init_double.c │ ├── init_double_driver.c │ ├── init_float.c │ ├── init_float_driver.c │ ├── mod.c │ ├── mod_driver.c │ ├── ptrdbladdr.c │ ├── ptrdbladdr_driver.c │ ├── ptrsubptr.c │ ├── ptrsubptr_driver.c │ ├── return_const_double.c │ ├── return_const_double_driver.c │ ├── return_const_float.c │ ├── return_const_float_driver.c │ ├── six_args_khayle.c │ ├── six_args_khayle_driver.c │ ├── void.c │ └── void_driver.c ├── array │ ├── declare_global.c │ ├── declare_global_driver.c │ ├── declare_local.c │ ├── declare_local_driver.c │ ├── index_constant.c │ ├── index_constant_driver.c │ ├── index_expression.c │ ├── index_expression_driver.c │ ├── index_variable.c │ └── index_variable_driver.c ├── control_flow │ ├── for_empty_inc.c │ ├── for_empty_inc_driver.c │ ├── for_multiple.c │ ├── for_multiple_driver.c │ ├── for_one.c │ ├── for_one_driver.c │ ├── for_zero_v1.c │ ├── for_zero_v1_driver.c │ ├── for_zero_v2.c │ ├── for_zero_v2_driver.c │ ├── if_else_false.c │ ├── if_else_false_driver.c │ ├── if_else_true.c │ ├── if_else_true_driver.c │ ├── if_false.c │ ├── if_false_driver.c │ ├── if_true.c │ ├── if_true_driver.c │ ├── sequence.c │ ├── sequence_driver.c │ ├── while_multiple.c │ ├── while_multiple_driver.c │ ├── while_once.c │ ├── while_once_driver.c │ ├── while_zero.c │ └── while_zero_driver.c ├── default │ ├── test_ADD0.c │ ├── test_ADD0_driver.c │ ├── test_ADD1.c │ ├── test_ADD1_driver.c │ ├── test_CALL.c │ ├── test_CALL_driver.c │ ├── test_LOCAL.c │ ├── test_LOCAL_driver.c │ ├── test_RETURN.c │ └── test_RETURN_driver.c ├── float │ ├── float_add.c │ ├── float_add_double.c │ ├── float_add_double_driver.c │ ├── float_add_driver.c │ ├── float_add_mul.c │ ├── float_add_mul_driver.c │ ├── float_mul.c │ ├── float_mul_add.c │ ├── float_mul_add_driver.c │ ├── float_mul_double.c │ ├── float_mul_double_driver.c │ ├── float_mul_driver.c │ ├── float_pow.c │ └── float_pow_driver.c ├── functions │ ├── call_constant_external.c │ ├── call_constant_external_driver.c │ ├── call_constant_internal.c │ ├── call_constant_internal_driver.c │ ├── call_five_args_external.c │ ├── call_five_args_external_driver.c │ ├── call_five_args_internal.c │ ├── call_five_args_internal_driver.c │ ├── call_identity_external.c │ ├── call_identity_external_driver.c │ ├── call_identity_internal.c │ ├── call_identity_internal_driver.c │ ├── call_mutual_recursive.c │ ├── call_mutual_recursive_driver.c │ ├── call_recursive_internal.c │ ├── call_recursive_internal_driver.c │ ├── call_two_args_external.c │ ├── call_two_args_external_driver.c │ ├── call_two_args_internal.c │ └── call_two_args_internal_driver.c ├── integer │ ├── add.c │ ├── add_driver.c │ ├── bitwise_and.c │ ├── bitwise_and_driver.c │ ├── bitwise_or.c │ ├── bitwise_or_driver.c │ ├── bitwise_xor.c │ ├── bitwise_xor_driver.c │ ├── div.c │ ├── div_driver.c │ ├── equal.c │ ├── equal_driver.c │ ├── less_than.c │ ├── less_than_driver.c │ ├── less_than_equal.c │ ├── less_than_equal_driver.c │ ├── logical_and.c │ ├── logical_and_driver.c │ ├── logical_or.c │ ├── logical_or_driver.c │ ├── mul.c │ ├── mul_driver.c │ ├── sub.c │ └── sub_driver.c ├── local_var │ ├── constant_initialiser.c │ ├── constant_initialiser_driver.c │ ├── dual_var.c │ ├── dual_var_driver.c │ ├── expression_initialiser.c │ ├── expression_initialiser_driver.c │ ├── identity.c │ ├── identity_driver.c │ ├── return_constant.c │ ├── return_constant_driver.c │ ├── scoped_var.c │ ├── scoped_var_driver.c │ ├── single_var.c │ └── single_var_driver.c ├── misc │ ├── enum1.c │ ├── enum1_driver.c │ ├── enum2.c │ ├── enum2_driver.c │ ├── switch1.c │ ├── switch1_driver.c │ ├── switch2.c │ ├── switch2_driver.c │ ├── typedef1.c │ ├── typedef1_driver.c │ ├── typedef2.c │ └── typedef2_driver.c ├── pointer │ ├── addressof.c │ ├── addressof_driver.c │ ├── arithmetic.c │ ├── arithmetic_driver.c │ ├── assign.c │ ├── assign_driver.c │ ├── dereference.c │ ├── dereference_driver.c │ ├── index.c │ └── index_driver.c ├── programs │ ├── fibonacci.c │ ├── fibonacci_driver.c │ ├── multiply.c │ ├── multiply_driver.c │ ├── sqrt.c │ └── sqrt_driver.c ├── strings │ ├── chliteral.c │ ├── chliteral_driver.c │ ├── escaped.c │ ├── escaped_driver.c │ ├── literal.c │ ├── literal_driver.c │ ├── puts.c │ ├── puts_driver.c │ ├── search.c │ └── search_driver.c ├── struct │ ├── sizeof.c │ ├── sizeof_driver.c │ ├── struct_inst.c │ ├── struct_inst_driver.c │ ├── struct_member_get.c │ ├── struct_member_get_driver.c │ ├── struct_member_set.c │ ├── struct_member_set_driver.c │ ├── struct_two_members.c │ └── struct_two_members_driver.c └── types │ ├── sizeof_char_inst.c │ ├── sizeof_char_inst_driver.c │ ├── sizeof_char_type.c │ ├── sizeof_char_type_driver.c │ ├── sizeof_int_inst.c │ ├── sizeof_int_inst_driver.c │ ├── sizeof_int_type.c │ ├── sizeof_int_type_driver.c │ ├── unsigned.c │ └── unsigned_driver.c ├── include ├── ast.hpp ├── ast │ ├── arrays │ │ ├── ast_arrayDeclarator.hpp │ │ ├── ast_arrayIndex.hpp │ │ └── ast_arrayInit.hpp │ ├── ast_declaration.hpp │ ├── ast_declarator.hpp │ ├── ast_empty.hpp │ ├── ast_identifier.hpp │ ├── ast_initDeclarator.hpp │ ├── ast_node.hpp │ ├── ast_nodeList.hpp │ ├── ast_pointerDeclarator.hpp │ ├── ast_root.hpp │ ├── blocks │ │ ├── ast_for.hpp │ │ ├── ast_ifElse.hpp │ │ ├── ast_scope.hpp │ │ ├── ast_scopeGlobal.hpp │ │ ├── ast_sequence.hpp │ │ ├── ast_while.hpp │ │ └── switch │ │ │ ├── ast_case.hpp │ │ │ ├── ast_default.hpp │ │ │ └── ast_switch.hpp │ ├── context.hpp │ ├── functions │ │ ├── ast_functionCall.hpp │ │ ├── ast_functionDeclarator.hpp │ │ └── ast_functionDefinition.hpp │ ├── keywords │ │ ├── ast_break.hpp │ │ ├── ast_continue.hpp │ │ └── ast_return.hpp │ ├── literals │ │ ├── ast_char.hpp │ │ ├── ast_float.hpp │ │ └── ast_integer.hpp │ ├── operators │ │ ├── ast_binaryOperation.hpp │ │ ├── ast_sizeof.hpp │ │ ├── ast_unaryOperation.hpp │ │ ├── binaryOps │ │ │ ├── ast_binaryAND.hpp │ │ │ ├── ast_binaryAdd.hpp │ │ │ ├── ast_binaryAssign.hpp │ │ │ ├── ast_binaryDiv.hpp │ │ │ ├── ast_binaryEQ.hpp │ │ │ ├── ast_binaryGT.hpp │ │ │ ├── ast_binaryGTEQ.hpp │ │ │ ├── ast_binaryLShift.hpp │ │ │ ├── ast_binaryLT.hpp │ │ │ ├── ast_binaryLTEQ.hpp │ │ │ ├── ast_binaryLogAND.hpp │ │ │ ├── ast_binaryLogOR.hpp │ │ │ ├── ast_binaryMod.hpp │ │ │ ├── ast_binaryMul.hpp │ │ │ ├── ast_binaryNEQ.hpp │ │ │ ├── ast_binaryOR.hpp │ │ │ ├── ast_binaryRShift.hpp │ │ │ ├── ast_binarySub.hpp │ │ │ └── ast_binaryXOR.hpp │ │ └── unaryOps │ │ │ ├── ast_unaryAdr.hpp │ │ │ ├── ast_unaryBWNOT.hpp │ │ │ ├── ast_unaryDec.hpp │ │ │ ├── ast_unaryInc.hpp │ │ │ ├── ast_unaryNOT.hpp │ │ │ ├── ast_unaryPostDec.hpp │ │ │ ├── ast_unaryPostInc.hpp │ │ │ ├── ast_unaryPtr.hpp │ │ │ └── ast_unarySub.hpp │ └── types │ │ ├── ast_enumSpecifier.hpp │ │ ├── ast_enumerator.hpp │ │ ├── ast_primitive.hpp │ │ └── ast_typedef.hpp └── parser_list.hpp ├── readme.md ├── src ├── compiler.cpp ├── include_impl │ └── ast │ │ ├── arrays │ │ ├── ast_arrayDeclarator.cpp │ │ ├── ast_arrayIndex.cpp │ │ └── ast_arrayInit.cpp │ │ ├── ast_declaration.cpp │ │ ├── ast_declarator.cpp │ │ ├── ast_empty.cpp │ │ ├── ast_identifier.cpp │ │ ├── ast_initDeclarator.cpp │ │ ├── ast_node.cpp │ │ ├── ast_nodeList.cpp │ │ ├── ast_pointerDeclarator.cpp │ │ ├── ast_root.cpp │ │ ├── blocks │ │ ├── ast_for.cpp │ │ ├── ast_ifElse.cpp │ │ ├── ast_scope.cpp │ │ ├── ast_scopeGlobal.cpp │ │ ├── ast_sequence.cpp │ │ ├── ast_while.cpp │ │ └── switch │ │ │ ├── ast_case.cpp │ │ │ ├── ast_default.cpp │ │ │ └── ast_switch.cpp │ │ ├── context.cpp │ │ ├── functions │ │ ├── ast_functionCall.cpp │ │ ├── ast_functionDeclarator.cpp │ │ └── ast_functionDefinition.cpp │ │ ├── keywords │ │ ├── ast_break.cpp │ │ ├── ast_continue.cpp │ │ └── ast_return.cpp │ │ ├── literals │ │ ├── ast_char.cpp │ │ ├── ast_float.cpp │ │ └── ast_integer.cpp │ │ ├── operators │ │ ├── ast_binaryOperation.cpp │ │ ├── ast_sizeof.cpp │ │ ├── ast_unaryOperation.cpp │ │ ├── binaryOps │ │ │ ├── ast_binaryAND.cpp │ │ │ ├── ast_binaryAdd.cpp │ │ │ ├── ast_binaryAssign.cpp │ │ │ ├── ast_binaryDiv.cpp │ │ │ ├── ast_binaryEQ.cpp │ │ │ ├── ast_binaryGT.cpp │ │ │ ├── ast_binaryGTEQ.cpp │ │ │ ├── ast_binaryLShift.cpp │ │ │ ├── ast_binaryLT.cpp │ │ │ ├── ast_binaryLTEQ.cpp │ │ │ ├── ast_binaryLogAND.cpp │ │ │ ├── ast_binaryLogOR.cpp │ │ │ ├── ast_binaryMod.cpp │ │ │ ├── ast_binaryMul.cpp │ │ │ ├── ast_binaryNEQ.cpp │ │ │ ├── ast_binaryOR.cpp │ │ │ ├── ast_binaryRShift.cpp │ │ │ ├── ast_binarySub.cpp │ │ │ └── ast_binaryXOR.cpp │ │ └── unaryOps │ │ │ ├── ast_unaryAdr.cpp │ │ │ ├── ast_unaryBWNOT.cpp │ │ │ ├── ast_unaryDec.cpp │ │ │ ├── ast_unaryInc.cpp │ │ │ ├── ast_unaryNOT.cpp │ │ │ ├── ast_unaryPostDec.cpp │ │ │ ├── ast_unaryPostInc.cpp │ │ │ ├── ast_unaryPtr.cpp │ │ │ └── ast_unarySub.cpp │ │ └── types │ │ ├── ast_enumSpecifier.cpp │ │ ├── ast_enumerator.cpp │ │ ├── ast_primitive.cpp │ │ └── ast_typedef.cpp ├── lexer.flex ├── parser.y └── wrapper.sh └── utility ├── add_ast.sh ├── add_test.sh ├── old ├── add_and_make_file_ast.sh ├── insert_genMIPS.sh ├── readme.md ├── refactor.sh └── rename_tests.sh ├── run_test.sh ├── test_dir.sh ├── test_single.sh └── test_test.sh /.gitignore: -------------------------------------------------------------------------------- 1 | bin 2 | src/*.tab.cpp 3 | src/*.tab.hpp 4 | src/*.yy.cpp 5 | Vagrantfile 6 | src/**/*.o 7 | src/*.output 8 | .vagrant 9 | *.log 10 | out 11 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | LINK_TARGET = bin/c_compiler 2 | CC = g++ 3 | 4 | CPPFLAGS += -std=c++17 -W -Wall -g -Wno-unused-parameter -Wno-unused-variable -Wno-unused-function 5 | CPPFLAGS += -I include -I src 6 | 7 | HPPFILES := $(shell find include/ -type f -name "*.hpp") 8 | CPPFILES := $(shell find src/ -type f -name "*.cpp") 9 | OBJS = $(patsubst %.cpp,%.o,$(CPPFILES)) 10 | 11 | all : $(LINK_TARGET) 12 | 13 | $(LINK_TARGET) : src/lexer.yy.o src/parser.tab.o $(OBJS) 14 | $(CC) $(CPPFLAGS) $^ -o $@ 15 | 16 | src/%.o: src/%.cpp $(HPPFILES) 17 | $(CC) $(CPPFLAGS) -c -o $@ $< 18 | 19 | src/parser.tab.cpp src/parser.tab.hpp: src/parser.y 20 | yacc -v -d src/parser.y -o src/parser.tab.cpp 21 | mkdir -p bin; 22 | 23 | src/lexer.yy.cpp : src/lexer.flex src/parser.tab.hpp 24 | flex -o src/lexer.yy.cpp src/lexer.flex 25 | 26 | makeobj: 27 | $(CC) $(CPPFLAGS) src/$(CPPALLTEST) -o bin/testout 28 | 29 | lexer: src/lexer.yy.cpp 30 | 31 | parser: src/parser.tab.cpp src/parser.tab.hpp 32 | 33 | bin/compiler: src/c_compiler.output 34 | 35 | 36 | .PHONY: clean 37 | clean : 38 | rm -rf bin/* 39 | rm -rf out/* 40 | rm -f src/*.tab.hpp 41 | rm -f src/*.tab.cpp 42 | rm -f src/*.yy.cpp 43 | rm -f src/*.output 44 | find src/ -type f -name '*.o' -delete 45 | -------------------------------------------------------------------------------- /Vagrantfile: -------------------------------------------------------------------------------- 1 | # -*- mode: ruby -*- 2 | # vi: set ft=ruby : 3 | 4 | # All Vagrant configuration is done below. The "2" in Vagrant.configure 5 | # configures the configuration version (we support older styles for 6 | # backwards compatibility). Please don't change it unless you know what 7 | # you're doing. 8 | Vagrant.configure(2) do |config| 9 | # The most common configuration options are documented and commented below. 10 | # For a complete reference, please see the online documentation at 11 | # https://docs.vagrantup.com. 12 | 13 | # Every Vagrant development environment requires a box. You can search for 14 | # boxes at https://atlas.hashicorp.com/search. 15 | config.vm.box = "ubuntu/xenial64" 16 | 17 | 18 | # Share an additional folder to the guest VM. The first argument is 19 | # the path on the host to the actual folder. The second argument is 20 | # the path on the guest to mount the folder. And the optional third 21 | # argument is a set of non-required options. 22 | # config.vm.synced_folder "../data", "/vagrant_data" 23 | 24 | # Provider-specific configuration so you can fine-tune various 25 | # backing providers for Vagrant. These expose provider-specific options. 26 | # Example for VirtualBox: 27 | # 28 | # config.vm.provider "virtualbox" do |vb| 29 | # # Display the VirtualBox GUI when booting the machine 30 | # vb.gui = true 31 | # 32 | # # Customize the amount of memory on the VM: 33 | # vb.memory = "1024" 34 | # end 35 | 36 | 37 | # Enable provisioning with a shell script. Additional provisioners such as 38 | # Puppet, Chef, Ansible, Salt, and Docker are also available. Please see the 39 | # documentation for more information about their specific syntax and use. 40 | config.vm.provision "shell", inline: <<-SHELL 41 | sudo apt-get update 42 | 43 | # Standard build tools 44 | sudo apt-get -y install g++ gdb make dos2unix git 45 | 46 | # Compiler build tools 47 | sudo apt-get -y install bison flex 48 | 49 | # MIPS cross-compiler stuff 50 | sudo apt-get -y install g++-mips-linux-gnu gdb-multiarch 51 | 52 | # QEMU run-time emulator 53 | sudo apt-get -y install qemu 54 | 55 | SHELL 56 | end 57 | -------------------------------------------------------------------------------- /admin/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simon-staal/Odyssey_C_Compiler/02908f4eb4ae910d9018cb5d299d199cef369535/admin/logo.png -------------------------------------------------------------------------------- /admin/management.md: -------------------------------------------------------------------------------- 1 | Time/Project management 2 | ======================= 3 | 4 | This deliverable is designed to encourage groups to practise good time and project management practices. 5 | 6 | You should write (and keep up-to-date as the project progresses): 7 | 8 | - a list of defined milestones, including the dependencies that each milestone has, which team member is responsible for leading it, and the completion status of each, 9 | 10 | - a week-by-week view of planned effort (hours to be spent) going into the project (taking into account other deadlines that you expect to have from other courses), and 11 | 12 | - a log of actual effort spent on each milestone (including an assessment of whether the estimates were optimistic or pessimistic, and whether you need to reduce the scope of certain deliverables). 13 | 14 | This tracking system is very ad-hoc and simple. However, it contains the key data and models the main activities of many commercial tools used in software development such as JIRA, Asana, Fogbugz, Trello, and so on. If you have already used such a system, and your team would prefer to use it, then that's fine. 15 | 16 | You may also find it helpful to use GitHub issues as part of your project management flow. 17 | 18 | The expectation is that you will update the project plan on at least a weekly basis. You do not need to update the information at a very fine granularity -- updating the information should take only a minute, and does not need to be done for every commit. 19 | 20 | 21 | Assessment 22 | ---------- 23 | 24 | The main goal of this component is to get you to do some time and project management, so you need to build up evidence that you did it. You don't need to do the project management particularly *well* -- the main thing is that you *do* it! The assessment will be in a 20 minute oral session per team in Summer term, where the team spends 10 minutes explaining the milestones, and how things were managed. The only thing needed for the oral will be the submitted repository (no presentation or other preparation is needed). The remaining 10 minutes will be feedback on the submitted compiler deliverable. 25 | 26 | Levels of achievement are: 27 | 28 | - A: demonstrated good understanding of how to plan and track progress, and showed good practices in terms of managing milestones and time. Outcomes from effort spent are clear. 29 | 30 | - B: updated progress each week, with acceptable granularity in terms of time spent and milestone planning. Most effort has a clear outcome. 31 | 32 | - C: progress not updated regularly, and weak link between effort spent and achieved outcomes. 33 | 34 | - D: sporadic time management, with files updated well after effort was expended. 35 | -------------------------------------------------------------------------------- /compiler_tests/Extra/arrayinit.c: -------------------------------------------------------------------------------- 1 | 2 | int f(){ 3 | 4 | int x[5] = {1, 3, 5, 22, 69}; 5 | 6 | return x[3]; 7 | 8 | } 9 | -------------------------------------------------------------------------------- /compiler_tests/Extra/arrayinit_driver.c: -------------------------------------------------------------------------------- 1 | int f(); 2 | 3 | int main() 4 | { 5 | return !(f()==22); 6 | } 7 | -------------------------------------------------------------------------------- /compiler_tests/Extra/break_for.c: -------------------------------------------------------------------------------- 1 | int f() 2 | { 3 | int i; 4 | int x = 20; 5 | for(i = 0; i < 10; i++){ 6 | if(i == 6){ 7 | break; 8 | } 9 | x += i; 10 | } 11 | return x; 12 | } 13 | -------------------------------------------------------------------------------- /compiler_tests/Extra/break_for_driver.c: -------------------------------------------------------------------------------- 1 | 2 | int f(); 3 | 4 | int main() 5 | { 6 | return !(f()==35); 7 | } 8 | -------------------------------------------------------------------------------- /compiler_tests/Extra/break_while.c: -------------------------------------------------------------------------------- 1 | int f() 2 | { 3 | int i = 5; 4 | int x = 4; 5 | while(i != 2){ 6 | if(i == 3){ 7 | break; 8 | return 2; 9 | } 10 | x *= i; 11 | --i; 12 | } 13 | return x; 14 | } 15 | -------------------------------------------------------------------------------- /compiler_tests/Extra/break_while_driver.c: -------------------------------------------------------------------------------- 1 | 2 | int f(); 3 | 4 | int main() 5 | { 6 | return !(f()==80); 7 | } 8 | -------------------------------------------------------------------------------- /compiler_tests/Extra/continue_for.c: -------------------------------------------------------------------------------- 1 | int f(int x) 2 | { 3 | int i; 4 | for(i = 32; i > 0; i /= 2){ 5 | x--; 6 | if(i == 8 || i == 16){ 7 | continue; 8 | return 2; 9 | } 10 | x += i+1; 11 | } 12 | return x; 13 | } 14 | -------------------------------------------------------------------------------- /compiler_tests/Extra/continue_for_driver.c: -------------------------------------------------------------------------------- 1 | 2 | int f(int x); 3 | 4 | int main() 5 | { 6 | return !(f(8)==45); 7 | } 8 | -------------------------------------------------------------------------------- /compiler_tests/Extra/continue_while.c: -------------------------------------------------------------------------------- 1 | int f(int x, int y) 2 | { 3 | while(y < x){ 4 | ++y; 5 | if(y+5 < x){ 6 | continue; 7 | return 4; 8 | } 9 | --x; 10 | } 11 | return x; 12 | } 13 | -------------------------------------------------------------------------------- /compiler_tests/Extra/continue_while_driver.c: -------------------------------------------------------------------------------- 1 | 2 | int f(int x, int y); 3 | 4 | int main() 5 | { 6 | return !(f(8,0)==5); 7 | } 8 | -------------------------------------------------------------------------------- /compiler_tests/Extra/enum_inst.c: -------------------------------------------------------------------------------- 1 | enum week { monday = 1, tuesday, wednesday, thursday, friday, saturday, sunday}; 2 | 3 | int f() 4 | { 5 | enum week day; 6 | day = friday; 7 | return day; 8 | } 9 | -------------------------------------------------------------------------------- /compiler_tests/Extra/enum_inst_driver.c: -------------------------------------------------------------------------------- 1 | 2 | int f(); 3 | 4 | int main() 5 | { 6 | return !(f()==5); 7 | } 8 | -------------------------------------------------------------------------------- /compiler_tests/Extra/float_array.c: -------------------------------------------------------------------------------- 1 | double f() 2 | { 3 | double arr[5] = {1.0, 2.0, 3.0, 4.0, 5.0}; 4 | arr[4] = 9.0; 5 | return arr[4]; 6 | } 7 | -------------------------------------------------------------------------------- /compiler_tests/Extra/float_array_driver.c: -------------------------------------------------------------------------------- 1 | 2 | double f(); 3 | 4 | int main() 5 | { 6 | return !(f()==9.0); 7 | } 8 | -------------------------------------------------------------------------------- /compiler_tests/Extra/global_array.c: -------------------------------------------------------------------------------- 1 | int arr[3] = {69, 420, 21}; 2 | 3 | int f() 4 | { 5 | return arr[1]; 6 | } 7 | -------------------------------------------------------------------------------- /compiler_tests/Extra/global_array_driver.c: -------------------------------------------------------------------------------- 1 | int f(); 2 | 3 | int main() 4 | { 5 | return !(f()==420); 6 | } 7 | -------------------------------------------------------------------------------- /compiler_tests/Extra/global_array_sw.c: -------------------------------------------------------------------------------- 1 | int global[5]; 2 | 3 | int f(int x) 4 | { 5 | global[3] = x+1; 6 | return global[3]; 7 | } 8 | -------------------------------------------------------------------------------- /compiler_tests/Extra/global_array_sw_driver.c: -------------------------------------------------------------------------------- 1 | 2 | int f(int x); 3 | 4 | int main() 5 | { 6 | return !(f(112)==113); 7 | } 8 | -------------------------------------------------------------------------------- /compiler_tests/Extra/global_double.c: -------------------------------------------------------------------------------- 1 | double x = 99.0; 2 | 3 | double f(double y) 4 | { 5 | return x+y; 6 | } 7 | -------------------------------------------------------------------------------- /compiler_tests/Extra/global_double_driver.c: -------------------------------------------------------------------------------- 1 | double f(double y); 2 | 3 | int main() 4 | { 5 | return !(f(1.0)==100.0d); 6 | } 7 | -------------------------------------------------------------------------------- /compiler_tests/Extra/global_float.c: -------------------------------------------------------------------------------- 1 | float y = 3.0; 2 | 3 | float f(float x) 4 | { 5 | return y+x; 6 | } 7 | -------------------------------------------------------------------------------- /compiler_tests/Extra/global_float_driver.c: -------------------------------------------------------------------------------- 1 | 2 | float f(float x); 3 | 4 | int main() 5 | { 6 | return !(f(4.0)==7.0); 7 | } 8 | -------------------------------------------------------------------------------- /compiler_tests/Extra/global_int.c: -------------------------------------------------------------------------------- 1 | int x = 69; 2 | 3 | int f() 4 | { 5 | return x; 6 | } 7 | -------------------------------------------------------------------------------- /compiler_tests/Extra/global_int_driver.c: -------------------------------------------------------------------------------- 1 | 2 | int f(); 3 | 4 | int main() 5 | { 6 | return !(f()==69); 7 | } 8 | -------------------------------------------------------------------------------- /compiler_tests/Extra/global_int_sw.c: -------------------------------------------------------------------------------- 1 | int x = 42; 2 | 3 | int f(int a) 4 | { 5 | x = a; 6 | return x; 7 | } 8 | -------------------------------------------------------------------------------- /compiler_tests/Extra/global_int_sw_driver.c: -------------------------------------------------------------------------------- 1 | 2 | int f(int a); 3 | 4 | int main() 5 | { 6 | return !(f(112)==112); 7 | } 8 | -------------------------------------------------------------------------------- /compiler_tests/Extra/init_double.c: -------------------------------------------------------------------------------- 1 | double f() 2 | { 3 | double x = 45.0; 4 | return x; 5 | } 6 | -------------------------------------------------------------------------------- /compiler_tests/Extra/init_double_driver.c: -------------------------------------------------------------------------------- 1 | 2 | double f(); 3 | 4 | int main() 5 | { 6 | return !(f()==45.0); 7 | } 8 | -------------------------------------------------------------------------------- /compiler_tests/Extra/init_float.c: -------------------------------------------------------------------------------- 1 | float f() 2 | { 3 | float x = 3.0; 4 | return x; 5 | } 6 | -------------------------------------------------------------------------------- /compiler_tests/Extra/init_float_driver.c: -------------------------------------------------------------------------------- 1 | 2 | float f(); 3 | 4 | int main() 5 | { 6 | return !(f()==3.0); 7 | } 8 | -------------------------------------------------------------------------------- /compiler_tests/Extra/mod.c: -------------------------------------------------------------------------------- 1 | 2 | 3 | int f(){ 4 | 5 | int x = 100%66; 6 | 7 | return x; 8 | } -------------------------------------------------------------------------------- /compiler_tests/Extra/mod_driver.c: -------------------------------------------------------------------------------- 1 | 2 | int f(); 3 | 4 | int main() 5 | { 6 | return !(f()==34); 7 | } 8 | -------------------------------------------------------------------------------- /compiler_tests/Extra/ptrdbladdr.c: -------------------------------------------------------------------------------- 1 | 2 | float f(){ 3 | 4 | float x[5] = {1.0, 2.0, 3.0, 4.0, 5.0}; 5 | float *p = &x[0]; 6 | p=p+1; 7 | 8 | return *p; 9 | } -------------------------------------------------------------------------------- /compiler_tests/Extra/ptrdbladdr_driver.c: -------------------------------------------------------------------------------- 1 | float f(); 2 | 3 | int main() 4 | { 5 | return !(f()==2.0); 6 | } 7 | -------------------------------------------------------------------------------- /compiler_tests/Extra/ptrsubptr.c: -------------------------------------------------------------------------------- 1 | 2 | 3 | int g() 4 | { 5 | 6 | int x[5]; 7 | int *p = &x[1]; 8 | int *q = &x[2]; 9 | return q-p; 10 | 11 | } 12 | -------------------------------------------------------------------------------- /compiler_tests/Extra/ptrsubptr_driver.c: -------------------------------------------------------------------------------- 1 | int g(); 2 | 3 | 4 | int main() { 5 | 6 | return !(g()==1); 7 | } 8 | -------------------------------------------------------------------------------- /compiler_tests/Extra/return_const_double.c: -------------------------------------------------------------------------------- 1 | 2 | double f() 3 | { 4 | return 69.0; 5 | } 6 | -------------------------------------------------------------------------------- /compiler_tests/Extra/return_const_double_driver.c: -------------------------------------------------------------------------------- 1 | 2 | double f(); 3 | 4 | int main() 5 | { 6 | return !(f()==69.0); 7 | } 8 | -------------------------------------------------------------------------------- /compiler_tests/Extra/return_const_float.c: -------------------------------------------------------------------------------- 1 | 2 | float f() 3 | { 4 | return 6.0; 5 | } 6 | -------------------------------------------------------------------------------- /compiler_tests/Extra/return_const_float_driver.c: -------------------------------------------------------------------------------- 1 | 2 | float f(); 3 | 4 | int main() 5 | { 6 | return !(f()==6.0); 7 | } 8 | -------------------------------------------------------------------------------- /compiler_tests/Extra/six_args_khayle.c: -------------------------------------------------------------------------------- 1 | int g(int x, int y, int z, int a, int b, int c) 2 | { 3 | return x + y + z + a + b + c; 4 | } 5 | 6 | int f() { 7 | return g(1,2,3,4,5,6); 8 | } 9 | -------------------------------------------------------------------------------- /compiler_tests/Extra/six_args_khayle_driver.c: -------------------------------------------------------------------------------- 1 | int g(int a, int b, int c, int d, int e, int f); 2 | int f(); 3 | 4 | int main() 5 | { 6 | return !(f()==21); 7 | } 8 | -------------------------------------------------------------------------------- /compiler_tests/Extra/void.c: -------------------------------------------------------------------------------- 1 | int x = 9; 2 | 3 | void f(int y) 4 | { 5 | x+=y; 6 | return; 7 | } 8 | -------------------------------------------------------------------------------- /compiler_tests/Extra/void_driver.c: -------------------------------------------------------------------------------- 1 | int x; 2 | void f(int y); 3 | 4 | int main() 5 | { 6 | f(10); 7 | return !(x==19); 8 | } 9 | -------------------------------------------------------------------------------- /compiler_tests/array/declare_global.c: -------------------------------------------------------------------------------- 1 | int x[8]; 2 | 3 | int f() 4 | { 5 | return 11; 6 | } 7 | -------------------------------------------------------------------------------- /compiler_tests/array/declare_global_driver.c: -------------------------------------------------------------------------------- 1 | 2 | int f(); 3 | 4 | int main() 5 | { 6 | return !(f()==11); 7 | } 8 | -------------------------------------------------------------------------------- /compiler_tests/array/declare_local.c: -------------------------------------------------------------------------------- 1 | int f() 2 | { 3 | int y; 4 | int x[8]; 5 | y=13; 6 | return y; 7 | } 8 | -------------------------------------------------------------------------------- /compiler_tests/array/declare_local_driver.c: -------------------------------------------------------------------------------- 1 | 2 | int f(); 3 | 4 | int main() 5 | { 6 | return !(f()==13); 7 | } 8 | -------------------------------------------------------------------------------- /compiler_tests/array/index_constant.c: -------------------------------------------------------------------------------- 1 | int f() 2 | { 3 | int x[8]; 4 | x[0]=23; 5 | return x[0]; 6 | } 7 | -------------------------------------------------------------------------------- /compiler_tests/array/index_constant_driver.c: -------------------------------------------------------------------------------- 1 | 2 | int f(); 3 | 4 | int main() 5 | { 6 | return !(f()==23); 7 | } 8 | -------------------------------------------------------------------------------- /compiler_tests/array/index_expression.c: -------------------------------------------------------------------------------- 1 | int f() 2 | { 3 | int i; 4 | int x[8]; 5 | int acc; 6 | for(i=8; i<16; i++){ 7 | x[i-8]=i; 8 | } 9 | acc=0; 10 | for(i=0; i<8; i++){ 11 | acc=acc+x[i+0]; 12 | } 13 | return acc; 14 | } 15 | -------------------------------------------------------------------------------- /compiler_tests/array/index_expression_driver.c: -------------------------------------------------------------------------------- 1 | 2 | int f(); 3 | 4 | int main() 5 | { 6 | return !(f()==92); 7 | } 8 | -------------------------------------------------------------------------------- /compiler_tests/array/index_variable.c: -------------------------------------------------------------------------------- 1 | int f() 2 | { 3 | int i; 4 | int x[8]; 5 | for(i=0; i<8; i++){ 6 | x[i]=i; 7 | } 8 | return x[4]; 9 | } 10 | -------------------------------------------------------------------------------- /compiler_tests/array/index_variable_driver.c: -------------------------------------------------------------------------------- 1 | 2 | int f(); 3 | 4 | int main() 5 | { 6 | return !(f()==4); 7 | } 8 | -------------------------------------------------------------------------------- /compiler_tests/control_flow/for_empty_inc.c: -------------------------------------------------------------------------------- 1 | int f(int x) 2 | { 3 | int i = -10; 4 | for(i=0; i>-10; ){ 5 | x = x + i; 6 | i = i - 1; 7 | } 8 | return x; 9 | } 10 | -------------------------------------------------------------------------------- /compiler_tests/control_flow/for_empty_inc_driver.c: -------------------------------------------------------------------------------- 1 | 2 | int f(int x); 3 | 4 | int main() 5 | { 6 | return !(f(500)==455); 7 | } 8 | -------------------------------------------------------------------------------- /compiler_tests/control_flow/for_multiple.c: -------------------------------------------------------------------------------- 1 | int f() 2 | { 3 | int x; 4 | int y; 5 | y=0; 6 | for(x=0; x<10; x=x+1){ 7 | y=y-1; 8 | } 9 | return y; 10 | } 11 | -------------------------------------------------------------------------------- /compiler_tests/control_flow/for_multiple_driver.c: -------------------------------------------------------------------------------- 1 | 2 | int f(); 3 | 4 | int main() 5 | { 6 | return !(f()==-10); 7 | } 8 | -------------------------------------------------------------------------------- /compiler_tests/control_flow/for_one.c: -------------------------------------------------------------------------------- 1 | int f() 2 | { 3 | int x; 4 | for(x=0; x<1; x=x+1){ 5 | 6 | } 7 | return x+19937; 8 | } 9 | -------------------------------------------------------------------------------- /compiler_tests/control_flow/for_one_driver.c: -------------------------------------------------------------------------------- 1 | 2 | int f(); 3 | 4 | int main() 5 | { 6 | return !(f()==19938); 7 | } 8 | -------------------------------------------------------------------------------- /compiler_tests/control_flow/for_zero_v1.c: -------------------------------------------------------------------------------- 1 | int f() 2 | { 3 | int x; 4 | for(x=0; x<0; x=x+1){ 5 | return 1; 6 | } 7 | return 19937; 8 | } 9 | -------------------------------------------------------------------------------- /compiler_tests/control_flow/for_zero_v1_driver.c: -------------------------------------------------------------------------------- 1 | 2 | int f(); 3 | 4 | int main() 5 | { 6 | return !(f()==19937); 7 | } 8 | -------------------------------------------------------------------------------- /compiler_tests/control_flow/for_zero_v2.c: -------------------------------------------------------------------------------- 1 | int f() 2 | { 3 | int x; 4 | for(x=0; x<0; x++){ 5 | return 1; 6 | } 7 | return 19937; 8 | } 9 | -------------------------------------------------------------------------------- /compiler_tests/control_flow/for_zero_v2_driver.c: -------------------------------------------------------------------------------- 1 | 2 | int f(); 3 | 4 | int main() 5 | { 6 | return !(f()==19937); 7 | } 8 | -------------------------------------------------------------------------------- /compiler_tests/control_flow/if_else_false.c: -------------------------------------------------------------------------------- 1 | int f() 2 | { 3 | if(0){ 4 | return 11; 5 | }else{ 6 | return 10; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /compiler_tests/control_flow/if_else_false_driver.c: -------------------------------------------------------------------------------- 1 | 2 | int f(); 3 | 4 | int main() 5 | { 6 | return !(f()==10); 7 | } 8 | -------------------------------------------------------------------------------- /compiler_tests/control_flow/if_else_true.c: -------------------------------------------------------------------------------- 1 | int f() 2 | { 3 | if(1){ 4 | return 11; 5 | }else{ 6 | return 10; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /compiler_tests/control_flow/if_else_true_driver.c: -------------------------------------------------------------------------------- 1 | 2 | int f(); 3 | 4 | int main() 5 | { 6 | return !(f()==11); 7 | } 8 | -------------------------------------------------------------------------------- /compiler_tests/control_flow/if_false.c: -------------------------------------------------------------------------------- 1 | int f() 2 | { 3 | if(0){ 4 | return 11; 5 | } 6 | return 10; 7 | } 8 | -------------------------------------------------------------------------------- /compiler_tests/control_flow/if_false_driver.c: -------------------------------------------------------------------------------- 1 | 2 | int f(); 3 | 4 | int main() 5 | { 6 | return !(f()==10); 7 | } 8 | -------------------------------------------------------------------------------- /compiler_tests/control_flow/if_true.c: -------------------------------------------------------------------------------- 1 | int f() 2 | { 3 | if(1){ 4 | return 11; 5 | } 6 | return 10; 7 | } 8 | -------------------------------------------------------------------------------- /compiler_tests/control_flow/if_true_driver.c: -------------------------------------------------------------------------------- 1 | 2 | int f(); 3 | 4 | int main() 5 | { 6 | return !(f()==11); 7 | } 8 | -------------------------------------------------------------------------------- /compiler_tests/control_flow/sequence.c: -------------------------------------------------------------------------------- 1 | int f() 2 | { 3 | int x; 4 | x=1; 5 | x=x+x; 6 | return x; 7 | } 8 | -------------------------------------------------------------------------------- /compiler_tests/control_flow/sequence_driver.c: -------------------------------------------------------------------------------- 1 | 2 | int f(int x, int y); 3 | 4 | int main() 5 | { 6 | return !(f(10,20)==2); 7 | } 8 | -------------------------------------------------------------------------------- /compiler_tests/control_flow/while_multiple.c: -------------------------------------------------------------------------------- 1 | int f() 2 | { 3 | int x; 4 | x=20; 5 | while(x > 10){ 6 | x=x-1; 7 | } 8 | return x; 9 | } 10 | -------------------------------------------------------------------------------- /compiler_tests/control_flow/while_multiple_driver.c: -------------------------------------------------------------------------------- 1 | 2 | int f(); 3 | 4 | int main() 5 | { 6 | return !(f(10,20)==10); 7 | } 8 | -------------------------------------------------------------------------------- /compiler_tests/control_flow/while_once.c: -------------------------------------------------------------------------------- 1 | int f() 2 | { 3 | int x; 4 | x=1; 5 | while(x){ 6 | x=0; 7 | } 8 | return 19937; 9 | } 10 | -------------------------------------------------------------------------------- /compiler_tests/control_flow/while_once_driver.c: -------------------------------------------------------------------------------- 1 | 2 | int f(int x, int y); 3 | 4 | int main() 5 | { 6 | return !(f(10,20)==19937); 7 | } 8 | -------------------------------------------------------------------------------- /compiler_tests/control_flow/while_zero.c: -------------------------------------------------------------------------------- 1 | int f() 2 | { 3 | while(0){ 4 | return 69420; 5 | } 6 | return 19937; 7 | } 8 | -------------------------------------------------------------------------------- /compiler_tests/control_flow/while_zero_driver.c: -------------------------------------------------------------------------------- 1 | 2 | int f(); 3 | 4 | int main() 5 | { 6 | return !(f()==19937); 7 | } 8 | -------------------------------------------------------------------------------- /compiler_tests/default/test_ADD0.c: -------------------------------------------------------------------------------- 1 | int f(int a, int b) 2 | { 3 | return a+b; 4 | } 5 | -------------------------------------------------------------------------------- /compiler_tests/default/test_ADD0_driver.c: -------------------------------------------------------------------------------- 1 | 2 | int f(int x, int y); 3 | 4 | int main() 5 | { 6 | return !( 40 == f(30,10) ); 7 | } 8 | -------------------------------------------------------------------------------- /compiler_tests/default/test_ADD1.c: -------------------------------------------------------------------------------- 1 | int f(int a) 2 | { 3 | return a+10; 4 | } 5 | -------------------------------------------------------------------------------- /compiler_tests/default/test_ADD1_driver.c: -------------------------------------------------------------------------------- 1 | 2 | int f(int x); 3 | 4 | int main() 5 | { 6 | return !( 40 == f(30) ); 7 | } 8 | -------------------------------------------------------------------------------- /compiler_tests/default/test_CALL.c: -------------------------------------------------------------------------------- 1 | int g(); 2 | 3 | int f() 4 | { 5 | return g(); 6 | } 7 | -------------------------------------------------------------------------------- /compiler_tests/default/test_CALL_driver.c: -------------------------------------------------------------------------------- 1 | 2 | int f(); 3 | 4 | int g() 5 | { 6 | return 10; 7 | } 8 | 9 | int main() 10 | { 11 | return !( 10==f() ); 12 | } 13 | -------------------------------------------------------------------------------- /compiler_tests/default/test_LOCAL.c: -------------------------------------------------------------------------------- 1 | int ffff() 2 | { 3 | int x; 4 | x=10; 5 | return x; 6 | } 7 | -------------------------------------------------------------------------------- /compiler_tests/default/test_LOCAL_driver.c: -------------------------------------------------------------------------------- 1 | int ffff(); 2 | 3 | int main() 4 | { 5 | return !( ffff()==10 ); 6 | } 7 | -------------------------------------------------------------------------------- /compiler_tests/default/test_RETURN.c: -------------------------------------------------------------------------------- 1 | int f() 2 | { 3 | return 10; 4 | } 5 | -------------------------------------------------------------------------------- /compiler_tests/default/test_RETURN_driver.c: -------------------------------------------------------------------------------- 1 | 2 | int f(); 3 | 4 | int main() 5 | { 6 | return !( 10==f() ); 7 | } 8 | -------------------------------------------------------------------------------- /compiler_tests/float/float_add.c: -------------------------------------------------------------------------------- 1 | float f(float x, float y) 2 | { 3 | return x+y; 4 | } 5 | -------------------------------------------------------------------------------- /compiler_tests/float/float_add_double.c: -------------------------------------------------------------------------------- 1 | double f(double x, double y) 2 | { 3 | return x+y; 4 | } 5 | -------------------------------------------------------------------------------- /compiler_tests/float/float_add_double_driver.c: -------------------------------------------------------------------------------- 1 | 2 | double f(double x, double y); 3 | 4 | int main() 5 | { 6 | return !(f(11.0,1.0)==12.0); 7 | } 8 | -------------------------------------------------------------------------------- /compiler_tests/float/float_add_driver.c: -------------------------------------------------------------------------------- 1 | 2 | float f(float x, float y); 3 | 4 | int main() 5 | { 6 | return !(f(11.0f,1.0f)==12.0f); 7 | } 8 | -------------------------------------------------------------------------------- /compiler_tests/float/float_add_mul.c: -------------------------------------------------------------------------------- 1 | float f(float x, float y, float z) 2 | { 3 | return x+y*z; 4 | } 5 | -------------------------------------------------------------------------------- /compiler_tests/float/float_add_mul_driver.c: -------------------------------------------------------------------------------- 1 | 2 | float f(float x, float y, float z); 3 | 4 | int main() 5 | { 6 | return !(f(2.0f,3.0f,4.0f)==14.0f); 7 | } 8 | -------------------------------------------------------------------------------- /compiler_tests/float/float_mul.c: -------------------------------------------------------------------------------- 1 | float f(float x, float y) 2 | { 3 | return x*y; 4 | } 5 | -------------------------------------------------------------------------------- /compiler_tests/float/float_mul_add.c: -------------------------------------------------------------------------------- 1 | float f(float x, float y, float z) 2 | { 3 | return x*y+z; 4 | } 5 | -------------------------------------------------------------------------------- /compiler_tests/float/float_mul_add_driver.c: -------------------------------------------------------------------------------- 1 | 2 | float f(float x, float y, float z); 3 | 4 | int main() 5 | { 6 | return !(f(2.0f,3.0f,4.0f)==10.0f); 7 | } 8 | -------------------------------------------------------------------------------- /compiler_tests/float/float_mul_double.c: -------------------------------------------------------------------------------- 1 | double f(double x, double y) 2 | { 3 | return x*y; 4 | } 5 | -------------------------------------------------------------------------------- /compiler_tests/float/float_mul_double_driver.c: -------------------------------------------------------------------------------- 1 | 2 | double f(double x, double y); 3 | 4 | int main() 5 | { 6 | return !(f(11.0,2.0)==22.0); 7 | } 8 | -------------------------------------------------------------------------------- /compiler_tests/float/float_mul_driver.c: -------------------------------------------------------------------------------- 1 | 2 | float f(float x, float y); 3 | 4 | int main() 5 | { 6 | return !(f(11.0f,2.0f)==22.0f); 7 | } 8 | -------------------------------------------------------------------------------- /compiler_tests/float/float_pow.c: -------------------------------------------------------------------------------- 1 | float f(float x, int n) 2 | { 3 | float acc=1.0f; 4 | int i=0; 5 | while(i 2 | int g(int x); 3 | 4 | int main() 5 | { 6 | int x; 7 | for(int i=0; i<4; i++){ 8 | fprintf(stderr, "g(%d)==%d\n", i, g(i)); 9 | } 10 | return !( (g(0)+g(1)+g(2)+g(3))==9); 11 | } 12 | -------------------------------------------------------------------------------- /compiler_tests/misc/typedef1.c: -------------------------------------------------------------------------------- 1 | typedef int int_t; 2 | 3 | int g() 4 | { 5 | int_t x; 6 | x=13; 7 | return 13; 8 | } 9 | -------------------------------------------------------------------------------- /compiler_tests/misc/typedef1_driver.c: -------------------------------------------------------------------------------- 1 | 2 | int g(); 3 | 4 | int main() 5 | { 6 | int x; 7 | return !(g()==13); 8 | } 9 | -------------------------------------------------------------------------------- /compiler_tests/misc/typedef2.c: -------------------------------------------------------------------------------- 1 | typedef int int_t; 2 | 3 | typedef int_t *pint_t; 4 | 5 | int_t g(int_t y) 6 | { 7 | pint_t p; 8 | int_t x; 9 | x=y; 10 | p=&x; 11 | return 1+*p; 12 | } 13 | -------------------------------------------------------------------------------- /compiler_tests/misc/typedef2_driver.c: -------------------------------------------------------------------------------- 1 | 2 | int g(int ); 3 | 4 | int main() 5 | { 6 | int x; 7 | return !(g(16)==17); 8 | } 9 | -------------------------------------------------------------------------------- /compiler_tests/pointer/addressof.c: -------------------------------------------------------------------------------- 1 | int f() 2 | { 3 | int x; 4 | int *y=&x; 5 | return 13; 6 | } 7 | -------------------------------------------------------------------------------- /compiler_tests/pointer/addressof_driver.c: -------------------------------------------------------------------------------- 1 | 2 | int f(); 3 | 4 | int main() 5 | { 6 | int x; 7 | return !(f()==13); 8 | } 9 | -------------------------------------------------------------------------------- /compiler_tests/pointer/arithmetic.c: -------------------------------------------------------------------------------- 1 | int f(int *p) 2 | { 3 | p=p+1; 4 | return *p; 5 | } 6 | -------------------------------------------------------------------------------- /compiler_tests/pointer/arithmetic_driver.c: -------------------------------------------------------------------------------- 1 | 2 | int f(); 3 | 4 | int main() 5 | { 6 | int x[2]; 7 | x[1]=13; 8 | return !(f(x)==13); 9 | } 10 | -------------------------------------------------------------------------------- /compiler_tests/pointer/assign.c: -------------------------------------------------------------------------------- 1 | int f() 2 | { 3 | int x; 4 | int *y=&x; 5 | *y=64; 6 | return x; 7 | } 8 | -------------------------------------------------------------------------------- /compiler_tests/pointer/assign_driver.c: -------------------------------------------------------------------------------- 1 | 2 | int f(); 3 | 4 | int main() 5 | { 6 | return !(f()==64); 7 | } 8 | -------------------------------------------------------------------------------- /compiler_tests/pointer/dereference.c: -------------------------------------------------------------------------------- 1 | int f() 2 | { 3 | int x; 4 | int *y=&x; 5 | x=13; 6 | return *y; 7 | } 8 | -------------------------------------------------------------------------------- /compiler_tests/pointer/dereference_driver.c: -------------------------------------------------------------------------------- 1 | 2 | int f(); 3 | 4 | int main() 5 | { 6 | int x; 7 | return !(f()==13); 8 | } 9 | -------------------------------------------------------------------------------- /compiler_tests/pointer/index.c: -------------------------------------------------------------------------------- 1 | int f(int *p) 2 | { 3 | return p[1]; 4 | } 5 | -------------------------------------------------------------------------------- /compiler_tests/pointer/index_driver.c: -------------------------------------------------------------------------------- 1 | 2 | int f(); 3 | 4 | int main() 5 | { 6 | int x[2]; 7 | x[1]=13; 8 | return !(f(x)==13); 9 | } 10 | -------------------------------------------------------------------------------- /compiler_tests/programs/fibonacci.c: -------------------------------------------------------------------------------- 1 | int fib(int x) 2 | { 3 | if(x <= 0){ 4 | return 0; 5 | } 6 | if(x == 1){ 7 | return 1; 8 | } 9 | return fib(x-1)+fib(x-2); 10 | } 11 | -------------------------------------------------------------------------------- /compiler_tests/programs/fibonacci_driver.c: -------------------------------------------------------------------------------- 1 | 2 | int fib(int x); 3 | 4 | int main() 5 | { 6 | int x; 7 | return !(fib(6)==8); 8 | } 9 | -------------------------------------------------------------------------------- /compiler_tests/programs/multiply.c: -------------------------------------------------------------------------------- 1 | int multiply(int x, int y) 2 | { 3 | int acc=0; 4 | if(x < 0){ 5 | return -multiply(-x, y); 6 | } 7 | 8 | while(x > 0){ 9 | acc += y; 10 | x--; 11 | } 12 | return acc; 13 | } 14 | -------------------------------------------------------------------------------- /compiler_tests/programs/multiply_driver.c: -------------------------------------------------------------------------------- 1 | 2 | int multiply(int x, int y); 3 | 4 | int main() 5 | { 6 | return !(multiply(-20,30)==-600); 7 | } 8 | -------------------------------------------------------------------------------- /compiler_tests/programs/sqrt.c: -------------------------------------------------------------------------------- 1 | int bsqrt(int lo, int hi, int val) 2 | { 3 | while(lo+1 < hi){ 4 | int mid=(lo+hi)>>1; 5 | int sqr=mid*mid; 6 | if(sqr <= val){ 7 | lo=mid; 8 | }else{ 9 | hi=mid; 10 | } 11 | } 12 | if( lo*lo < val ) { 13 | return hi; 14 | }else{ 15 | return lo; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /compiler_tests/programs/sqrt_driver.c: -------------------------------------------------------------------------------- 1 | 2 | int bsqrt(int lo, int hi, int v); 3 | 4 | int main() 5 | { 6 | int x; 7 | return !(bsqrt(1,1000,64)==8); 8 | } 9 | -------------------------------------------------------------------------------- /compiler_tests/strings/chliteral.c: -------------------------------------------------------------------------------- 1 | int g() 2 | { 3 | return 'h'; 4 | } 5 | -------------------------------------------------------------------------------- /compiler_tests/strings/chliteral_driver.c: -------------------------------------------------------------------------------- 1 | 2 | int g(); 3 | 4 | int main() 5 | { 6 | int x; 7 | return !(g()=='h'); 8 | } 9 | -------------------------------------------------------------------------------- /compiler_tests/strings/escaped.c: -------------------------------------------------------------------------------- 1 | int g() 2 | { 3 | char *x="\\"; 4 | return x[0]; 5 | } 6 | -------------------------------------------------------------------------------- /compiler_tests/strings/escaped_driver.c: -------------------------------------------------------------------------------- 1 | 2 | int g(); 3 | 4 | int main() 5 | { 6 | int x; 7 | return !(g()=='\\'); 8 | } 9 | -------------------------------------------------------------------------------- /compiler_tests/strings/literal.c: -------------------------------------------------------------------------------- 1 | int g() 2 | { 3 | char *x="hello"; 4 | return x[0]; 5 | } 6 | -------------------------------------------------------------------------------- /compiler_tests/strings/literal_driver.c: -------------------------------------------------------------------------------- 1 | 2 | int g(); 3 | 4 | int main() 5 | { 6 | int x; 7 | return !(g()=='h'); 8 | } 9 | -------------------------------------------------------------------------------- /compiler_tests/strings/puts.c: -------------------------------------------------------------------------------- 1 | void fakeputs(char *x); 2 | 3 | void g() 4 | { 5 | fakeputs("wibble"); 6 | } 7 | -------------------------------------------------------------------------------- /compiler_tests/strings/puts_driver.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int ok; 4 | 5 | void fakeputs(char *x) 6 | { 7 | ok=!strcmp(x,"wibble"); 8 | } 9 | 10 | int g(); 11 | 12 | int main() 13 | { 14 | ok=0; 15 | g(); 16 | return !(ok==1); 17 | } 18 | -------------------------------------------------------------------------------- /compiler_tests/strings/search.c: -------------------------------------------------------------------------------- 1 | char *search(char *x, char c) 2 | { 3 | while(*x){ 4 | if(*x==c){ 5 | return x; 6 | } 7 | x=x+1; 8 | } 9 | return 0; 10 | } 11 | -------------------------------------------------------------------------------- /compiler_tests/strings/search_driver.c: -------------------------------------------------------------------------------- 1 | char *search(char *x, char c); 2 | 3 | int main() 4 | { 5 | char *s="abcdef"; 6 | 7 | char *p=search((char*)s,'c'); 8 | return !(p==s+2); 9 | } 10 | -------------------------------------------------------------------------------- /compiler_tests/struct/sizeof.c: -------------------------------------------------------------------------------- 1 | struct x{ 2 | int y; 3 | }; 4 | 5 | int f() 6 | { 7 | struct x y; 8 | return sizeof(y); 9 | } -------------------------------------------------------------------------------- /compiler_tests/struct/sizeof_driver.c: -------------------------------------------------------------------------------- 1 | int f(); 2 | 3 | int main() 4 | { 5 | return !(f()==4); 6 | } 7 | -------------------------------------------------------------------------------- /compiler_tests/struct/struct_inst.c: -------------------------------------------------------------------------------- 1 | struct x{ 2 | int y; 3 | }; 4 | 5 | int f() 6 | { 7 | struct x y; 8 | return 13; 9 | } -------------------------------------------------------------------------------- /compiler_tests/struct/struct_inst_driver.c: -------------------------------------------------------------------------------- 1 | int f(); 2 | 3 | int main() 4 | { 5 | return !(f()==13); 6 | } 7 | -------------------------------------------------------------------------------- /compiler_tests/struct/struct_member_get.c: -------------------------------------------------------------------------------- 1 | struct x{ 2 | int y; 3 | }; 4 | 5 | int f() 6 | { 7 | struct x z; 8 | z.y=13; 9 | return z.y; 10 | } -------------------------------------------------------------------------------- /compiler_tests/struct/struct_member_get_driver.c: -------------------------------------------------------------------------------- 1 | int f(); 2 | 3 | int main() 4 | { 5 | return !(f()==13); 6 | } 7 | -------------------------------------------------------------------------------- /compiler_tests/struct/struct_member_set.c: -------------------------------------------------------------------------------- 1 | struct x{ 2 | int y; 3 | }; 4 | 5 | int f() 6 | { 7 | struct x z; 8 | z.y=17; 9 | return 13; 10 | } -------------------------------------------------------------------------------- /compiler_tests/struct/struct_member_set_driver.c: -------------------------------------------------------------------------------- 1 | int f(); 2 | 3 | int main() 4 | { 5 | return !(f()==13); 6 | } 7 | -------------------------------------------------------------------------------- /compiler_tests/struct/struct_two_members.c: -------------------------------------------------------------------------------- 1 | struct x{ 2 | int y; 3 | int z; 4 | }; 5 | 6 | int f() 7 | { 8 | struct x g; 9 | g.y=17; 10 | g.z=13; 11 | return g.y+g.z; 12 | } -------------------------------------------------------------------------------- /compiler_tests/struct/struct_two_members_driver.c: -------------------------------------------------------------------------------- 1 | int f(); 2 | 3 | int main() 4 | { 5 | return !(f()==30); 6 | } 7 | -------------------------------------------------------------------------------- /compiler_tests/types/sizeof_char_inst.c: -------------------------------------------------------------------------------- 1 | int f() 2 | { 3 | char x; 4 | return sizeof(x); 5 | } 6 | -------------------------------------------------------------------------------- /compiler_tests/types/sizeof_char_inst_driver.c: -------------------------------------------------------------------------------- 1 | int f(); 2 | 3 | int main() 4 | { 5 | return !(f()==1); 6 | } 7 | -------------------------------------------------------------------------------- /compiler_tests/types/sizeof_char_type.c: -------------------------------------------------------------------------------- 1 | int f() 2 | { 3 | return sizeof(char); 4 | } 5 | -------------------------------------------------------------------------------- /compiler_tests/types/sizeof_char_type_driver.c: -------------------------------------------------------------------------------- 1 | int f(); 2 | 3 | int main() 4 | { 5 | return !(f()==1); 6 | } 7 | -------------------------------------------------------------------------------- /compiler_tests/types/sizeof_int_inst.c: -------------------------------------------------------------------------------- 1 | int f() 2 | { 3 | int x; 4 | return sizeof(x); 5 | } 6 | -------------------------------------------------------------------------------- /compiler_tests/types/sizeof_int_inst_driver.c: -------------------------------------------------------------------------------- 1 | int f(); 2 | 3 | int main() 4 | { 5 | return !(f()==4); 6 | } 7 | -------------------------------------------------------------------------------- /compiler_tests/types/sizeof_int_type.c: -------------------------------------------------------------------------------- 1 | int f() 2 | { 3 | return sizeof(int); 4 | } 5 | -------------------------------------------------------------------------------- /compiler_tests/types/sizeof_int_type_driver.c: -------------------------------------------------------------------------------- 1 | int f(); 2 | 3 | int main() 4 | { 5 | return !(f()==4); 6 | } 7 | -------------------------------------------------------------------------------- /compiler_tests/types/unsigned.c: -------------------------------------------------------------------------------- 1 | unsigned f() 2 | { 3 | return 11; 4 | } 5 | -------------------------------------------------------------------------------- /compiler_tests/types/unsigned_driver.c: -------------------------------------------------------------------------------- 1 | unsigned f(); 2 | 3 | int main() 4 | { 5 | return !(f()==11); 6 | } 7 | -------------------------------------------------------------------------------- /include/ast.hpp: -------------------------------------------------------------------------------- 1 | #ifndef generic_ast_hpp 2 | #define generic_ast_hpp 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "ast/ast_node.hpp" 12 | #include "ast/ast_nodeList.hpp" 13 | #include "ast/ast_root.hpp" 14 | #include "ast/ast_empty.hpp" 15 | #include "ast/ast_declarator.hpp" 16 | #include "ast/ast_initDeclarator.hpp" 17 | #include "ast/ast_declaration.hpp" 18 | #include "ast/ast_identifier.hpp" 19 | 20 | #include "ast/keywords/ast_return.hpp" 21 | #include "ast/keywords/ast_break.hpp" 22 | #include "ast/keywords/ast_continue.hpp" 23 | 24 | #include "ast/blocks/ast_sequence.hpp" 25 | #include "ast/blocks/ast_scope.hpp" 26 | #include "ast/blocks/ast_scopeGlobal.hpp" 27 | #include "ast/blocks/ast_ifElse.hpp" 28 | #include "ast/blocks/ast_while.hpp" 29 | #include "ast/blocks/ast_for.hpp" 30 | 31 | #include "ast/blocks/switch/ast_switch.hpp" 32 | #include "ast/blocks/switch/ast_case.hpp" 33 | #include "ast/blocks/switch/ast_default.hpp" 34 | 35 | #include "ast/literals/ast_integer.hpp" 36 | #include "ast/literals/ast_float.hpp" 37 | #include "ast/literals/ast_char.hpp" 38 | 39 | #include "ast/types/ast_primitive.hpp" 40 | #include "ast/types/ast_typedef.hpp" 41 | #include "ast/types/ast_enumerator.hpp" 42 | #include "ast/types/ast_enumSpecifier.hpp" 43 | 44 | #include "ast/functions/ast_functionDeclarator.hpp" 45 | #include "ast/functions/ast_functionDefinition.hpp" 46 | #include "ast/functions/ast_functionCall.hpp" 47 | 48 | #include "ast/operators/ast_sizeof.hpp" 49 | 50 | #include "ast/operators/ast_binaryOperation.hpp" 51 | #include "ast/operators/binaryOps/ast_binaryAdd.hpp" 52 | #include "ast/operators/binaryOps/ast_binarySub.hpp" 53 | #include "ast/operators/binaryOps/ast_binaryMul.hpp" 54 | #include "ast/operators/binaryOps/ast_binaryDiv.hpp" 55 | #include "ast/operators/binaryOps/ast_binaryMod.hpp" 56 | #include "ast/operators/binaryOps/ast_binaryGT.hpp" 57 | #include "ast/operators/binaryOps/ast_binaryLT.hpp" 58 | #include "ast/operators/binaryOps/ast_binaryGTEQ.hpp" 59 | #include "ast/operators/binaryOps/ast_binaryLTEQ.hpp" 60 | #include "ast/operators/binaryOps/ast_binaryNEQ.hpp" 61 | #include "ast/operators/binaryOps/ast_binaryEQ.hpp" 62 | #include "ast/operators/binaryOps/ast_binaryAND.hpp" 63 | #include "ast/operators/binaryOps/ast_binaryLogAND.hpp" 64 | #include "ast/operators/binaryOps/ast_binaryLogOR.hpp" 65 | #include "ast/operators/binaryOps/ast_binaryOR.hpp" 66 | #include "ast/operators/binaryOps/ast_binaryXOR.hpp" 67 | #include "ast/operators/binaryOps/ast_binaryRShift.hpp" 68 | #include "ast/operators/binaryOps/ast_binaryLShift.hpp" 69 | #include "ast/operators/binaryOps/ast_binaryAssign.hpp" 70 | 71 | #include "ast/operators/unaryOps/ast_unaryNOT.hpp" 72 | #include "ast/operators/unaryOps/ast_unaryBWNOT.hpp" 73 | #include "ast/operators/unaryOps/ast_unaryPtr.hpp" 74 | #include "ast/operators/unaryOps/ast_unaryAdr.hpp" 75 | #include "ast/operators/unaryOps/ast_unarySub.hpp" 76 | #include "ast/operators/unaryOps/ast_unaryInc.hpp" 77 | #include "ast/operators/unaryOps/ast_unaryDec.hpp" 78 | #include "ast/operators/unaryOps/ast_unaryPostInc.hpp" 79 | #include "ast/operators/unaryOps/ast_unaryPostDec.hpp" 80 | 81 | #include "ast/arrays/ast_arrayDeclarator.hpp" 82 | #include "ast/arrays/ast_arrayIndex.hpp" 83 | #include "ast/arrays/ast_arrayInit.hpp" 84 | 85 | #include "ast/ast_pointerDeclarator.hpp" 86 | 87 | #include "ast/context.hpp" 88 | 89 | extern Node *parseAST(std::string filename); 90 | 91 | #endif 92 | -------------------------------------------------------------------------------- /include/ast/arrays/ast_arrayDeclarator.hpp: -------------------------------------------------------------------------------- 1 | #ifndef ast_arrayDeclarator_hpp 2 | #define ast_arrayDeclarator_hpp 3 | 4 | #include "ast/ast_node.hpp" 5 | #include "ast/literals/ast_integer.hpp" // For empty size constructor 6 | 7 | class ArrayDeclarator 8 | : public Node 9 | { 10 | public: 11 | // Constructors 12 | ArrayDeclarator(NodePtr id, NodePtr size); 13 | ArrayDeclarator(NodePtr id); 14 | 15 | // Destructor 16 | virtual ~ArrayDeclarator(); 17 | 18 | // Visualising 19 | void PrettyPrint(std::ostream &dst, std::string indent) const override; 20 | 21 | // Codegen helpers 22 | std::string getId() const override; 23 | bool isFunction() const override; 24 | bool isInit() const override; 25 | int getArraySize() const override; 26 | }; 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /include/ast/arrays/ast_arrayIndex.hpp: -------------------------------------------------------------------------------- 1 | #ifndef ast_arrayIndex_hpp 2 | #define ast_arrayIndex_hpp 3 | 4 | #include "ast/ast_node.hpp" 5 | #include "ast/ast_nodeList.hpp" 6 | 7 | 8 | class ArrayIndex 9 | : public Node 10 | { 11 | public: 12 | // Constructors 13 | ArrayIndex(NodePtr id, NodePtr index); 14 | 15 | // Destructor 16 | virtual ~ArrayIndex(); 17 | 18 | // Visualising 19 | void PrettyPrint(std::ostream &dst, std::string indent) const override; 20 | 21 | // Codegen + helpers 22 | void generateMIPS(std::ostream &dst, Context &context, int destReg) const; 23 | void generateTypeMIPS(std::ostream &dst, Context &context, int destReg, enum Specifier type) const override; 24 | 25 | std::string getId() const override; 26 | bool isFunction() const override; 27 | }; 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /include/ast/arrays/ast_arrayInit.hpp: -------------------------------------------------------------------------------- 1 | #ifndef ast_arrayInit_hpp 2 | #define ast_arrayInit_hpp 3 | 4 | #include "ast/ast_node.hpp" 5 | 6 | class ArrayInit 7 | : public Node 8 | { 9 | public: 10 | // Constructors 11 | ArrayInit(std::vector elements); 12 | 13 | // Destructor 14 | ~ArrayInit(); 15 | 16 | // Visualising 17 | void PrettyPrint(std::ostream &dst, std::string indent) const override; 18 | 19 | // Codegen + helpers 20 | void generateMIPS(std::ostream &dst, Context &context, int destReg) const override; 21 | int getValue(int i) const override; 22 | double getFloat(int i) const override; 23 | void generateTypeMIPS(std::ostream &dst, Context &context, int destReg, enum Specifier type) const override; 24 | 25 | }; 26 | 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /include/ast/ast_declaration.hpp: -------------------------------------------------------------------------------- 1 | #ifndef ast_declaration_hpp 2 | #define ast_declaration_hpp 3 | 4 | #include "ast_node.hpp" 5 | #include "ast_identifier.hpp" 6 | 7 | // Represents declarations as type (i.e. int) + what the declaration actually is, which could be a bunch of stuff 8 | 9 | class Declaration 10 | : public Node 11 | { 12 | public: 13 | // Constructors 14 | Declaration(NodePtr type, NodePtr id); 15 | Declaration(NodePtr type); 16 | 17 | // Destructor 18 | virtual ~Declaration(); 19 | 20 | // Visualising 21 | void PrettyPrint(std::ostream &dst, std::string indent) const override; 22 | 23 | // Codegen + helpers 24 | void generateMIPS(std::ostream &dst, Context &context, int destReg) const override; 25 | NodePtr getNode(unsigned index) const override; 26 | int getSize() const override; 27 | std::string getId() const override; 28 | bool isFunction() const override; 29 | bool isInit() const override; 30 | int getArraySize() const override; 31 | int getValue() const override; 32 | int getValue(int i) const override; 33 | double getFloat() const override; 34 | double getFloat(int i) const override; 35 | enum Specifier getType() const override; 36 | }; 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /include/ast/ast_declarator.hpp: -------------------------------------------------------------------------------- 1 | #ifndef ast_declarator_hpp 2 | #define ast_declarator_hpp 3 | 4 | #include "ast_node.hpp" 5 | #include "ast_identifier.hpp" 6 | 7 | // Used for base declarators from parser, functionDeclarator uses this as its id 8 | 9 | class Declarator 10 | : public Node 11 | { 12 | public: 13 | // Constructors 14 | Declarator(NodePtr id); 15 | Declarator(std::string id); 16 | 17 | // Destructor 18 | virtual ~Declarator(); 19 | 20 | // Visualising 21 | void PrettyPrint(std::ostream &dst, std::string indent) const override; 22 | 23 | // Codegen helpers 24 | std::string getId() const override; 25 | bool isFunction() const override; 26 | bool isInit() const override; 27 | 28 | }; 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /include/ast/ast_empty.hpp: -------------------------------------------------------------------------------- 1 | #ifndef ast_empty_hpp 2 | #define ast_empty_hpp 3 | 4 | #include "ast_node.hpp" 5 | 6 | // Symbolises empty node, used in parser for For loops 7 | 8 | class EmptyNode 9 | : public Node 10 | { 11 | public: 12 | // Should inherit contructor from Node 13 | 14 | // Visualising 15 | void PrettyPrint(std::ostream &dst, std::string indent) const override; 16 | 17 | // Codegen 18 | void generateMIPS(std::ostream &dst, Context &context, int destReg) const override {} // Does nothing (duh) 19 | }; 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /include/ast/ast_identifier.hpp: -------------------------------------------------------------------------------- 1 | #ifndef ast_identifier_hpp 2 | #define ast_identifier_hpp 3 | 4 | #include "ast_node.hpp" 5 | 6 | class Identifier 7 | : public Node 8 | { 9 | protected: 10 | std::string id; 11 | public: 12 | // Constructor 13 | Identifier(std::string _id); 14 | 15 | // Visualising 16 | void PrettyPrint(std::ostream &dst, std::string indent) const override; 17 | 18 | // Codegen + helpers 19 | void generateMIPS(std::ostream &dst, Context &context, int destReg) const override; 20 | void generateTypeMIPS(std::ostream &dst, Context &context, int destReg, enum Specifier type) const override; 21 | std::string getId() const override; // Getting identifier 22 | int getSize(Context &context) const override; // Size of variable 23 | }; 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /include/ast/ast_initDeclarator.hpp: -------------------------------------------------------------------------------- 1 | #ifndef ast_initDeclarator_hpp 2 | #define ast_initDeclarator_hpp 3 | 4 | #include "ast_declarator.hpp" 5 | 6 | // This is used for declarations which are initialised (int x = 3;) 7 | // Basically a combination of declarator and binaryNormalAssign, but i'm too lazy to think 8 | // of an elegant way to combine them so I'm just making a new class 9 | 10 | class InitDeclarator 11 | : public Node 12 | { 13 | public: 14 | // Consturctor 15 | InitDeclarator(NodePtr declarator, NodePtr initializer); 16 | 17 | // Destructor 18 | virtual ~InitDeclarator(); 19 | 20 | // Visualising 21 | void PrettyPrint(std::ostream &dst, std::string indent) const override; 22 | 23 | // Codegen + helpers 24 | void generateMIPS(std::ostream &dst, Context &context, int destReg) const override; 25 | void generateTypeMIPS(std::ostream &dst, Context &context, int destReg, enum Specifier type) const override; 26 | std::string getId() const override; 27 | bool isFunction() const override; 28 | bool isInit() const override; 29 | int getValue() const override; 30 | int getValue(int i) const override; 31 | double getFloat() const override; 32 | double getFloat(int i) const override; 33 | int getArraySize() const override; 34 | }; 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /include/ast/ast_node.hpp: -------------------------------------------------------------------------------- 1 | #ifndef ast_node_hpp 2 | #define ast_node_hpp 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "context.hpp" 11 | 12 | // Base building block for everything, the Argos 13 | 14 | class Node; 15 | typedef Node *NodePtr; 16 | 17 | class Node 18 | { 19 | protected: 20 | std::vector branches; 21 | 22 | public: 23 | // Constructors 24 | // Used in derived classes 25 | Node(std::vector _branches); 26 | Node(); 27 | Node(std::vector branches1, std::vector branches2); // Specifically used for sequence 28 | 29 | // Destructor 30 | virtual ~Node(); 31 | 32 | // Visualising 33 | virtual void PrettyPrint(std::ostream &dst, std::string indent) const = 0; 34 | // We friends with ostream now :D 35 | friend std::ostream& operator<<(std::ostream &dst, const Node &Node); 36 | friend std::ostream& operator<<(std::ostream &dst, const NodePtr Node); 37 | 38 | // Codegen + helpers 39 | virtual void generateMIPS(std::ostream &dst, Context &context, int destReg) const; 40 | virtual void generateTypeMIPS(std::ostream &dst, Context &context, int destReg, enum Specifier type) const; 41 | 42 | // Used in codegen for more complex, context-dependant constructs (i.e. to process declarator's in a higher node) 43 | virtual NodePtr getNode(unsigned index) const; 44 | // Used for codegen in returning the size of a variable 45 | virtual int getSize() const; 46 | virtual int getSize(Context &context) const; 47 | // Used in codegen in returning the identifier of a variable / function 48 | virtual std::string getId() const; 49 | // Used in codegen to check if a declaration is for a function 50 | virtual bool isFunction() const; 51 | // Used in codegen to check if enumeration 52 | virtual bool isEnum() const; 53 | // Used in codegen to check if declarator is initialised 54 | virtual bool isInit() const; 55 | // Used to get ArraySize 56 | virtual int getArraySize() const; 57 | // used to get literal values before codegen 58 | virtual int getValue() const; 59 | virtual int getValue(int i) const; // For arrays 60 | virtual double getFloat() const; // getValue but for floating point stuff 61 | virtual double getFloat(int i) const; 62 | virtual bool isPtr() const; 63 | virtual NodePtr getOp() const; // for unaryops 64 | virtual enum Specifier getType() const; // Used for different typed instructions 65 | }; 66 | 67 | 68 | 69 | #endif 70 | -------------------------------------------------------------------------------- /include/ast/ast_nodeList.hpp: -------------------------------------------------------------------------------- 1 | #ifndef ast_nodeList_hpp 2 | #define ast_nodeList_hpp 3 | 4 | #include "ast_node.hpp" 5 | 6 | class NodeList; 7 | typedef NodeList *NodeListPtr; 8 | 9 | class NodeList 10 | : public Node 11 | { 12 | public: 13 | // Constructors 14 | NodeList(std::vector nodes); 15 | NodeList(); 16 | 17 | // Destructor 18 | virtual ~NodeList(); 19 | 20 | // Visualising 21 | virtual void PrettyPrint(std::ostream &dst, std::string indent) const override; 22 | 23 | // Get stuff in list (codegen) 24 | virtual NodePtr getNode(unsigned index) const override; 25 | }; 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /include/ast/ast_pointerDeclarator.hpp: -------------------------------------------------------------------------------- 1 | #ifndef ast_pointerDeclarator_hpp 2 | #define ast_pointerDeclarator_hpp 3 | 4 | #include "ast_node.hpp" 5 | 6 | 7 | class PointerDeclarator 8 | : public Node 9 | { 10 | public: 11 | 12 | PointerDeclarator(NodePtr id); 13 | 14 | // Destructor 15 | virtual ~PointerDeclarator(); 16 | 17 | // Visualising 18 | void PrettyPrint(std::ostream &dst, std::string indent) const override; 19 | 20 | // Get stuff in list (codegen) 21 | bool isInit() const override; 22 | bool isFunction() const override; 23 | std::string getId() const override; 24 | bool isPtr() const override; 25 | 26 | }; 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /include/ast/ast_root.hpp: -------------------------------------------------------------------------------- 1 | #ifndef ast_root_hpp 2 | #define ast_root_hpp 3 | 4 | #include "ast_node.hpp" 5 | 6 | // Top-level entity in our AST, holds the global scope 7 | 8 | class Root 9 | : public Node 10 | { 11 | public: 12 | // Constructor 13 | Root(NodePtr globalScope); 14 | 15 | // Destructor 16 | virtual ~Root(); 17 | 18 | // Visualising 19 | void PrettyPrint(std::ostream &dst, std::string indent) const override; 20 | 21 | // Codegen 22 | void generateMIPS(std::ostream &dst, Context &context, int destReg) const override; 23 | }; 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /include/ast/blocks/ast_for.hpp: -------------------------------------------------------------------------------- 1 | #ifndef ast_for_hpp 2 | #define ast_for_hpp 3 | 4 | #include "ast/ast_node.hpp" 5 | 6 | class For 7 | : public Node 8 | { 9 | public: 10 | // Constructor 11 | For(NodePtr initializer, NodePtr condition, NodePtr increment, NodePtr scope); 12 | 13 | // Destructor 14 | virtual ~For(); 15 | 16 | // Visualising 17 | void PrettyPrint(std::ostream &dst, std::string indent) const override; 18 | 19 | // Codegen 20 | void generateMIPS(std::ostream &dst, Context &context, int destReg) const override; 21 | }; 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /include/ast/blocks/ast_ifElse.hpp: -------------------------------------------------------------------------------- 1 | #ifndef ast_ifElse_hpp 2 | #define ast_ifElse_hpp 3 | 4 | #include "ast/ast_node.hpp" 5 | #include "ast/blocks/ast_scope.hpp" // Required for exclusive if constructor 6 | 7 | class IfElse 8 | : public Node 9 | { 10 | public: 11 | // Constructors 12 | IfElse(NodePtr condition, NodePtr ifScope, NodePtr elseScope); 13 | IfElse(NodePtr condition, NodePtr ifScope); 14 | 15 | // Destructor 16 | virtual ~IfElse(); 17 | 18 | // Visualising 19 | void PrettyPrint(std::ostream &dst, std::string indent) const override; 20 | 21 | // Codegen 22 | void generateMIPS(std::ostream &dst, Context &context, int destReg) const override; 23 | }; 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /include/ast/blocks/ast_scope.hpp: -------------------------------------------------------------------------------- 1 | #ifndef ast_scope_hpp 2 | #define ast_scope_hpp 3 | 4 | #include "ast/blocks/ast_sequence.hpp" 5 | 6 | // The meat and potatoes of a function, basically a sequence 7 | 8 | class Scope 9 | : public Sequence 10 | { 11 | public: 12 | // Does everything like Sequence (constructor/destructor wise) 13 | using Sequence::Sequence; 14 | 15 | // Visualising 16 | void PrettyPrint(std::ostream &dst, std::string indent) const override; 17 | 18 | // Codegen 19 | void generateMIPS(std::ostream &dst, Context &context, int destReg) const override; 20 | }; 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /include/ast/blocks/ast_scopeGlobal.hpp: -------------------------------------------------------------------------------- 1 | #ifndef ast_scopeGlobal_hpp 2 | #define ast_scopeGlobal_hpp 3 | 4 | #include "ast/blocks/ast_sequence.hpp" 5 | 6 | // Holds everything declared in global scope 7 | 8 | class GlobalScope 9 | : public Sequence 10 | { 11 | public: 12 | using Sequence::Sequence; 13 | 14 | // Visualising 15 | void PrettyPrint(std::ostream &dst, std::string indent) const override; 16 | 17 | // Codegen 18 | void generateMIPS(std::ostream &dst, Context &context, int destReg) const override; 19 | }; 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /include/ast/blocks/ast_sequence.hpp: -------------------------------------------------------------------------------- 1 | #ifndef ast_sequence_hpp 2 | #define ast_sequence_hpp 3 | 4 | #include "ast/ast_node.hpp" 5 | 6 | // Represents a generic sequence of c++ code, basically going to be used for scope, keeping sequence generic 7 | // cause it might be reusable for other shit later (globals?) 8 | 9 | class Sequence; 10 | typedef Sequence *SeqPtr; 11 | 12 | class Sequence 13 | : public Node 14 | { 15 | public: 16 | // Constructors 17 | Sequence(); 18 | Sequence(NodePtr in); 19 | Sequence(std::vector _branches); 20 | Sequence(std::vector decList, std::vector statList); 21 | 22 | // Destructor 23 | ~Sequence(); 24 | 25 | // Visualising 26 | virtual void PrettyPrint(std::ostream &dst, std::string indent) const override; 27 | 28 | // Codegen helper 29 | virtual NodePtr getNode(unsigned index) const; 30 | }; 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /include/ast/blocks/ast_while.hpp: -------------------------------------------------------------------------------- 1 | #ifndef ast_while_hpp 2 | #define ast_while_hpp 3 | 4 | #include "ast/ast_node.hpp" 5 | 6 | class While 7 | : public Node 8 | { 9 | public: 10 | // Constructor 11 | While(NodePtr condition, NodePtr scope); 12 | 13 | // Destructor 14 | virtual ~While(); 15 | 16 | // Visualising 17 | void PrettyPrint(std::ostream &dst, std::string indent) const override; 18 | 19 | // Codegen 20 | void generateMIPS(std::ostream &dst, Context &context, int destReg) const override; 21 | }; 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /include/ast/blocks/switch/ast_case.hpp: -------------------------------------------------------------------------------- 1 | #ifndef ast_case_hpp 2 | #define ast_case_hpp 3 | 4 | #include "ast/ast_node.hpp" 5 | 6 | class Case 7 | : public Node 8 | { 9 | public: 10 | // Constructor 11 | Case(NodePtr condition, NodePtr execute); 12 | 13 | // Destructor 14 | virtual ~Case(); 15 | 16 | // Visualising 17 | void PrettyPrint(std::ostream &dst, std::string indent) const override; 18 | 19 | // Codegen 20 | void generateMIPS(std::ostream &dst, Context &context, int destReg) const override; 21 | }; 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /include/ast/blocks/switch/ast_default.hpp: -------------------------------------------------------------------------------- 1 | #ifndef ast_default_hpp 2 | #define ast_default_hpp 3 | 4 | #include "ast/ast_node.hpp" 5 | 6 | class Default 7 | : public Node 8 | { 9 | public: 10 | // Constructor 11 | Default(NodePtr execute); 12 | 13 | // Destructor 14 | virtual ~Default(); 15 | 16 | // Visualising 17 | void PrettyPrint(std::ostream &dst, std::string indent) const override; 18 | 19 | // Codegen 20 | void generateMIPS(std::ostream &dst, Context &context, int destReg) const override; 21 | }; 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /include/ast/blocks/switch/ast_switch.hpp: -------------------------------------------------------------------------------- 1 | #ifndef ast_switch_hpp 2 | #define ast_switch_hpp 3 | 4 | #include "ast/ast_node.hpp" 5 | 6 | class Switch 7 | : public Node 8 | { 9 | public: 10 | // Constructor 11 | Switch(NodePtr expression, NodePtr scope); 12 | 13 | // Destructor 14 | virtual ~Switch(); 15 | 16 | // Visualising 17 | void PrettyPrint(std::ostream &dst, std::string indent) const override; 18 | 19 | // Codegen 20 | void generateMIPS(std::ostream &dst, Context &context, int destReg) const override; 21 | }; 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /include/ast/functions/ast_functionCall.hpp: -------------------------------------------------------------------------------- 1 | #ifndef ast_functionCall_hpp 2 | #define ast_functionCall_hpp 3 | 4 | #include "ast/ast_node.hpp" 5 | #include "ast/ast_nodeList.hpp" 6 | 7 | // Represents a function call as an identifier + parameters 8 | 9 | class FunctionCall 10 | : public Node 11 | { 12 | public: 13 | // Constructors 14 | FunctionCall(NodePtr id, NodeListPtr params); 15 | FunctionCall(NodePtr id, std::vector params); 16 | FunctionCall(NodePtr id); // No params 17 | 18 | // Destructor 19 | virtual ~FunctionCall(); 20 | 21 | // Visualising 22 | void PrettyPrint(std::ostream &dst, std::string indent) const override; 23 | 24 | // Codegen + helpers 25 | void generateMIPS(std::ostream &dst, Context &context, int destReg) const override; 26 | std::string getId() const override; 27 | bool isFunction() const override; 28 | }; 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /include/ast/functions/ast_functionDeclarator.hpp: -------------------------------------------------------------------------------- 1 | #ifndef ast_functionDeclarator_hpp 2 | #define ast_functionDeclarator_hpp 3 | 4 | #include "ast/ast_node.hpp" 5 | #include "ast/ast_nodeList.hpp" 6 | 7 | class FunctionDeclarator 8 | : public Node 9 | { 10 | public: 11 | // Constructors 12 | FunctionDeclarator(NodePtr id, NodeListPtr params); 13 | FunctionDeclarator(NodePtr id, std::vector params); 14 | FunctionDeclarator(NodePtr id); 15 | 16 | // Destructor 17 | virtual ~FunctionDeclarator(); 18 | 19 | // Visualising 20 | void PrettyPrint(std::ostream &dst, std::string indent) const override; 21 | 22 | // Codegen + helpers 23 | void generateMIPS(std::ostream &dst, Context &context, int destReg) const override; 24 | NodePtr getNode(unsigned index) const override; 25 | std::string getId() const override; 26 | bool isFunction() const override; 27 | }; 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /include/ast/functions/ast_functionDefinition.hpp: -------------------------------------------------------------------------------- 1 | #ifndef ast_functionDefinition_hpp 2 | #define ast_functionDefinition_hpp 3 | 4 | #include "ast/ast_node.hpp" 5 | 6 | // Represents a function as a declaration + {shit in here}, where the scope node contains the shit 7 | 8 | class FunctionDefinition 9 | : public Node 10 | { 11 | public: 12 | // Constructors 13 | FunctionDefinition(NodePtr declaration, NodePtr scope); 14 | 15 | // Destructor 16 | virtual ~FunctionDefinition(); 17 | 18 | // Visualising 19 | void PrettyPrint(std::ostream &dst, std::string indent) const override; 20 | 21 | // Codegen + helpers 22 | void generateMIPS(std::ostream &dst, Context &context, int destReg) const override; 23 | bool isFunction() const override; 24 | }; 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /include/ast/keywords/ast_break.hpp: -------------------------------------------------------------------------------- 1 | #ifndef ast_break_hpp 2 | #define ast_break_hpp 3 | 4 | #include "ast/ast_node.hpp" 5 | 6 | class Break 7 | : public Node 8 | { 9 | public: 10 | // Should inherit constructor from Node() 11 | 12 | // Visualising 13 | void PrettyPrint(std::ostream &dst, std::string indent) const override; 14 | 15 | // Codegen 16 | void generateMIPS(std::ostream &dst, Context &context, int destReg) const override; 17 | }; 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /include/ast/keywords/ast_continue.hpp: -------------------------------------------------------------------------------- 1 | #ifndef ast_continue_hpp 2 | #define ast_continue_hpp 3 | 4 | #include "ast/ast_node.hpp" 5 | 6 | class Continue 7 | : public Node 8 | { 9 | public: 10 | // Should inherit constructor from Node() 11 | 12 | // Visualising 13 | void PrettyPrint(std::ostream &dst, std::string indent) const override; 14 | 15 | // Codegen 16 | void generateMIPS(std::ostream &dst, Context &context, int destReg) const override; 17 | }; 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /include/ast/keywords/ast_return.hpp: -------------------------------------------------------------------------------- 1 | #ifndef ast_return_hpp 2 | #define ast_return_hpp 3 | 4 | #include "ast/ast_node.hpp" 5 | 6 | class Return 7 | : public Node 8 | { 9 | public: 10 | // Constructors 11 | Return(NodePtr val); 12 | //Return(); // For void funcitons returns 0 (i.e. success) REFACTORED 13 | 14 | // Destructor 15 | ~Return(); 16 | 17 | // Visualising 18 | void PrettyPrint(std::ostream &dst, std::string indent) const override; 19 | 20 | // Codegen 21 | void generateMIPS(std::ostream &dst, Context &context, int destReg) const override; 22 | 23 | }; 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /include/ast/literals/ast_char.hpp: -------------------------------------------------------------------------------- 1 | #ifndef ast_char_hpp 2 | #define ast_char_hpp 3 | 4 | #include "ast/ast_node.hpp" 5 | 6 | class Char 7 | : public Node 8 | { 9 | private: 10 | int value; // Using int so we can reuse all the getValue methods (and just use lsb) 11 | 12 | public: 13 | // Constructor 14 | Char(int _value); 15 | 16 | // Visualising 17 | void PrettyPrint(std::ostream &dst, std::string indent) const override; 18 | 19 | // Codegen + helpers 20 | void generateTypeMIPS(std::ostream &dst, Context &context, int destReg, enum Specifier type) const override; 21 | int getValue() const override; //needed for arrays 22 | int getSize() const override; // getsize stuff 23 | }; 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /include/ast/literals/ast_float.hpp: -------------------------------------------------------------------------------- 1 | #ifndef ast_float_hpp 2 | #define ast_float_hpp 3 | 4 | #include "ast/ast_node.hpp" 5 | 6 | class Float 7 | : public Node 8 | { 9 | private: 10 | double value; // Using doubles by default, will convert to single precision if type is float when generating MIPS 11 | 12 | public: 13 | // Constructors 14 | Float(double _value); 15 | 16 | // Visualising 17 | void PrettyPrint(std::ostream &dst, std::string indent) const override; 18 | 19 | // Codegen + helpers 20 | void generateTypeMIPS(std::ostream &dst, Context &context, int destReg, enum Specifier type) const; 21 | double getFloat() const override; //needed for arrays 22 | int getSize() const override; // getsize stuff 23 | }; 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /include/ast/literals/ast_integer.hpp: -------------------------------------------------------------------------------- 1 | #ifndef ast_integer_hpp 2 | #define ast_integer_hpp 3 | 4 | #include "ast/ast_node.hpp" 5 | 6 | class Integer 7 | : public Node 8 | { 9 | private: 10 | int value; 11 | 12 | public: 13 | // Constructors 14 | Integer(int _value); 15 | Integer(); // Default initializer 16 | 17 | // Visualising 18 | void PrettyPrint(std::ostream &dst, std::string indent) const override; 19 | 20 | // Codegen + helpers 21 | void generateMIPS(std::ostream &dst, Context &context, int destReg) const override; 22 | int getValue() const override; //needed for arrays 23 | int getSize() const override; // getsize stuff 24 | 25 | }; 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /include/ast/operators/ast_binaryOperation.hpp: -------------------------------------------------------------------------------- 1 | #ifndef ast_binaryOperation_hpp 2 | #define ast_binaryOperation_hpp 3 | 4 | #include "ast/ast_node.hpp" 5 | 6 | class BinaryOperation 7 | : public Node 8 | 9 | { 10 | protected: 11 | 12 | NodePtr LeftOp() const; 13 | NodePtr RightOp() const; 14 | 15 | public: 16 | 17 | BinaryOperation(NodePtr left, NodePtr right); 18 | 19 | virtual ~BinaryOperation(); 20 | 21 | //implement in its derived functions 22 | virtual void PrettyPrint(std::ostream &dst, std::string indent) const = 0; 23 | 24 | virtual void generateMIPS(std::ostream &dst, Context &context, int destReg) const; 25 | 26 | virtual void EZPrint(std::ostream &dst, std::string instr, int destReg, int regLeft, int regRight) const; 27 | 28 | virtual int DoLeft(std::ostream &dst, Context &context, int destReg) const; 29 | 30 | virtual int DoRight(std::ostream &dst, Context &context, int destReg, int regLeft) const; 31 | 32 | virtual variable LeftVar(Context &context) const; 33 | 34 | void ifFunction(std::ostream &dst, Context &context, int destReg) const; 35 | 36 | virtual void generateTypeMIPS(std::ostream &dst, Context &context, int destReg, enum Specifier type) const; 37 | 38 | bool isPtrVar(Context &context, NodePtr op) const; 39 | 40 | int DoTypeLeft(std::ostream &dst, Context &context, int destReg, enum Specifier type) const; 41 | 42 | int DoTypeRight(std::ostream &dst, Context &context, int destReg, int regLeft, enum Specifier type) const; 43 | 44 | }; 45 | 46 | 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /include/ast/operators/ast_sizeof.hpp: -------------------------------------------------------------------------------- 1 | #ifndef ast_sizeof_hpp 2 | #define ast_sizeof_hpp 3 | 4 | #include "ast/ast_node.hpp" 5 | 6 | class SizeOf 7 | : public Node 8 | { 9 | public: 10 | // Constructor 11 | SizeOf(NodePtr type); 12 | 13 | // Destructor 14 | ~SizeOf(); 15 | 16 | // Visualising 17 | void PrettyPrint(std::ostream &dst, std::string indent) const override; 18 | 19 | // Codegen + helpers 20 | void generateMIPS(std::ostream &dst, Context &context, int destReg) const override; 21 | }; 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /include/ast/operators/ast_unaryOperation.hpp: -------------------------------------------------------------------------------- 1 | #ifndef ast_unaryOperation_hpp 2 | #define ast_unaryOperation_hpp 3 | 4 | #include "ast/ast_node.hpp" 5 | 6 | class UnaryOperation 7 | : public Node 8 | 9 | { 10 | protected: 11 | 12 | NodePtr getOp() const; 13 | 14 | public: 15 | 16 | UnaryOperation(NodePtr op); 17 | 18 | virtual ~UnaryOperation(); 19 | 20 | //implement in its derived functions 21 | virtual void PrettyPrint(std::ostream &dst, std::string indent) const = 0; 22 | 23 | virtual void generateMIPS(std::ostream &dst, Context &context, int destReg) const; 24 | 25 | void ifFunction(std::ostream &dst, Context &context, int destReg) const; 26 | 27 | bool isPtr() const override; 28 | 29 | std::string getId() const; 30 | int getSize(Context &context) const override; // For sizeof stuff 31 | 32 | 33 | }; 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /include/ast/operators/binaryOps/ast_binaryAND.hpp: -------------------------------------------------------------------------------- 1 | #ifndef ast_binaryAND_hpp 2 | #define ast_binaryAND_hpp 3 | 4 | #include "ast/operators/ast_binaryOperation.hpp" 5 | 6 | class BinaryAND 7 | : public BinaryOperation 8 | { 9 | public: 10 | 11 | using BinaryOperation::BinaryOperation; 12 | 13 | virtual void PrettyPrint(std::ostream &dst, std::string indent) const override; 14 | virtual void generateMIPS(std::ostream &dst, Context &context, int destReg) const override; 15 | 16 | 17 | }; 18 | 19 | #endif -------------------------------------------------------------------------------- /include/ast/operators/binaryOps/ast_binaryAdd.hpp: -------------------------------------------------------------------------------- 1 | #ifndef ast_binaryAdd_hpp 2 | #define ast_binaryAdd_hpp 3 | 4 | #include "ast/operators/ast_binaryOperation.hpp" 5 | 6 | class BinaryAdd 7 | : public BinaryOperation 8 | { 9 | public: 10 | 11 | using BinaryOperation::BinaryOperation; 12 | 13 | virtual void PrettyPrint(std::ostream &dst, std::string indent) const override; 14 | virtual void generateMIPS(std::ostream &dst, Context &context, int destReg) const override; 15 | virtual void generateTypeMIPS(std::ostream &dst, Context &context, int destReg, enum Specifier type) const override; 16 | 17 | }; 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /include/ast/operators/binaryOps/ast_binaryAssign.hpp: -------------------------------------------------------------------------------- 1 | #ifndef ast_binaryAssign_hpp 2 | #define ast_binaryAssign_hpp 3 | 4 | #include "ast/operators/ast_binaryOperation.hpp" 5 | 6 | class BinaryAssign 7 | : public BinaryOperation 8 | { 9 | public: 10 | 11 | using BinaryOperation::BinaryOperation; 12 | 13 | virtual void PrettyPrint(std::ostream &dst, std::string indent) const override; 14 | virtual void generateMIPS(std::ostream &dst, Context &context, int destReg) const override; 15 | virtual void generateTypeMIPS(std::ostream &dst, Context &context, int destReg, enum Specifier type) const override; 16 | 17 | }; 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /include/ast/operators/binaryOps/ast_binaryDiv.hpp: -------------------------------------------------------------------------------- 1 | #ifndef ast_binaryDiv_hpp 2 | #define ast_binaryDiv_hpp 3 | 4 | #include "ast/operators/ast_binaryOperation.hpp" 5 | 6 | class BinaryDiv 7 | : public BinaryOperation 8 | { 9 | public: 10 | 11 | using BinaryOperation::BinaryOperation; 12 | 13 | virtual void PrettyPrint(std::ostream &dst, std::string indent) const override; 14 | virtual void generateMIPS(std::ostream &dst, Context &context, int destReg) const override; 15 | virtual void generateTypeMIPS(std::ostream &dst, Context &context, int destReg, enum Specifier type) const override; 16 | 17 | 18 | }; 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /include/ast/operators/binaryOps/ast_binaryEQ.hpp: -------------------------------------------------------------------------------- 1 | #ifndef ast_binaryEQ_hpp 2 | #define ast_binaryEQ_hpp 3 | 4 | #include "ast/operators/ast_binaryOperation.hpp" 5 | 6 | class BinaryEQ 7 | : public BinaryOperation 8 | { 9 | public: 10 | 11 | using BinaryOperation::BinaryOperation; 12 | 13 | virtual void PrettyPrint(std::ostream &dst, std::string indent) const override; 14 | virtual void generateMIPS(std::ostream &dst, Context &context, int destReg) const override; 15 | void generateTypeMIPS(std::ostream &dst, Context &context, int destReg, enum Specifier type) const override; 16 | 17 | 18 | }; 19 | 20 | #endif -------------------------------------------------------------------------------- /include/ast/operators/binaryOps/ast_binaryGT.hpp: -------------------------------------------------------------------------------- 1 | #ifndef ast_binaryGT_hpp 2 | #define ast_binaryGT_hpp 3 | 4 | #include "ast/operators/ast_binaryOperation.hpp" 5 | 6 | class BinaryGT 7 | : public BinaryOperation 8 | { 9 | public: 10 | 11 | using BinaryOperation::BinaryOperation; 12 | 13 | virtual void PrettyPrint(std::ostream &dst, std::string indent) const override; 14 | virtual void generateMIPS(std::ostream &dst, Context &context, int destReg) const override; 15 | 16 | 17 | }; 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /include/ast/operators/binaryOps/ast_binaryGTEQ.hpp: -------------------------------------------------------------------------------- 1 | #ifndef ast_binaryGTEQ_hpp 2 | #define ast_binaryGTEQ_hpp 3 | 4 | #include "ast/operators/ast_binaryOperation.hpp" 5 | 6 | class BinaryGTEQ 7 | : public BinaryOperation 8 | { 9 | public: 10 | 11 | using BinaryOperation::BinaryOperation; 12 | 13 | virtual void PrettyPrint(std::ostream &dst, std::string indent) const override; 14 | virtual void generateMIPS(std::ostream &dst, Context &context, int destReg) const override; 15 | 16 | 17 | }; 18 | 19 | #endif -------------------------------------------------------------------------------- /include/ast/operators/binaryOps/ast_binaryLShift.hpp: -------------------------------------------------------------------------------- 1 | #ifndef ast_binaryLShift_hpp 2 | #define ast_binaryLShift_hpp 3 | 4 | #include "ast/operators/ast_binaryOperation.hpp" 5 | 6 | class BinaryLShift 7 | : public BinaryOperation 8 | { 9 | public: 10 | 11 | using BinaryOperation::BinaryOperation; 12 | 13 | virtual void PrettyPrint(std::ostream &dst, std::string indent) const override; 14 | virtual void generateMIPS(std::ostream &dst, Context &context, int destReg) const override; 15 | 16 | 17 | }; 18 | 19 | #endif -------------------------------------------------------------------------------- /include/ast/operators/binaryOps/ast_binaryLT.hpp: -------------------------------------------------------------------------------- 1 | #ifndef ast_binaryLT_hpp 2 | #define ast_binaryLT_hpp 3 | 4 | #include "ast/operators/ast_binaryOperation.hpp" 5 | 6 | class BinaryLT 7 | : public BinaryOperation 8 | { 9 | public: 10 | 11 | using BinaryOperation::BinaryOperation; 12 | 13 | virtual void PrettyPrint(std::ostream &dst, std::string indent) const override; 14 | virtual void generateMIPS(std::ostream &dst, Context &context, int destReg) const override; 15 | 16 | 17 | }; 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /include/ast/operators/binaryOps/ast_binaryLTEQ.hpp: -------------------------------------------------------------------------------- 1 | #ifndef ast_binaryLTEQ_hpp 2 | #define ast_binaryLTEQ_hpp 3 | 4 | #include "ast/operators/ast_binaryOperation.hpp" 5 | 6 | class BinaryLTEQ 7 | : public BinaryOperation 8 | { 9 | public: 10 | 11 | using BinaryOperation::BinaryOperation; 12 | 13 | virtual void PrettyPrint(std::ostream &dst, std::string indent) const override; 14 | virtual void generateMIPS(std::ostream &dst, Context &context, int destReg) const override; 15 | 16 | 17 | }; 18 | 19 | #endif -------------------------------------------------------------------------------- /include/ast/operators/binaryOps/ast_binaryLogAND.hpp: -------------------------------------------------------------------------------- 1 | #ifndef ast_binaryLogAND_hpp 2 | #define ast_binaryLogAND_hpp 3 | 4 | #include "ast/operators/ast_binaryOperation.hpp" 5 | 6 | class BinaryLogAND 7 | : public BinaryOperation 8 | { 9 | public: 10 | 11 | using BinaryOperation::BinaryOperation; 12 | 13 | virtual void PrettyPrint(std::ostream &dst, std::string indent) const override; 14 | virtual void generateMIPS(std::ostream &dst, Context &context, int destReg) const override; 15 | 16 | 17 | }; 18 | 19 | #endif -------------------------------------------------------------------------------- /include/ast/operators/binaryOps/ast_binaryLogOR.hpp: -------------------------------------------------------------------------------- 1 | #ifndef ast_binaryLogOR_hpp 2 | #define ast_binaryLogOR_hpp 3 | 4 | #include "ast/operators/ast_binaryOperation.hpp" 5 | 6 | class BinaryLogOR 7 | : public BinaryOperation 8 | { 9 | public: 10 | 11 | using BinaryOperation::BinaryOperation; 12 | 13 | virtual void PrettyPrint(std::ostream &dst, std::string indent) const override; 14 | virtual void generateMIPS(std::ostream &dst, Context &context, int destReg) const override; 15 | 16 | 17 | }; 18 | 19 | #endif -------------------------------------------------------------------------------- /include/ast/operators/binaryOps/ast_binaryMod.hpp: -------------------------------------------------------------------------------- 1 | #ifndef ast_binaryMod_hpp 2 | #define ast_binaryMod_hpp 3 | 4 | #include "ast/operators/ast_binaryOperation.hpp" 5 | 6 | class BinaryMod 7 | : public BinaryOperation 8 | { 9 | public: 10 | 11 | using BinaryOperation::BinaryOperation; 12 | 13 | virtual void PrettyPrint(std::ostream &dst, std::string indent) const override; 14 | virtual void generateMIPS(std::ostream &dst, Context &context, int destReg) const override; 15 | 16 | 17 | }; 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /include/ast/operators/binaryOps/ast_binaryMul.hpp: -------------------------------------------------------------------------------- 1 | #ifndef ast_binaryMul_hpp 2 | #define ast_binaryMul_hpp 3 | 4 | #include "ast/operators/ast_binaryOperation.hpp" 5 | 6 | class BinaryMul 7 | : public BinaryOperation 8 | { 9 | public: 10 | 11 | using BinaryOperation::BinaryOperation; 12 | 13 | virtual void PrettyPrint(std::ostream &dst, std::string indent) const override; 14 | virtual void generateMIPS(std::ostream &dst, Context &context, int destReg) const override; 15 | void generateTypeMIPS(std::ostream &dst, Context &context, int destReg, enum Specifier type) const override; 16 | 17 | 18 | }; 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /include/ast/operators/binaryOps/ast_binaryNEQ.hpp: -------------------------------------------------------------------------------- 1 | #ifndef ast_binaryNEQ_hpp 2 | #define ast_binaryNEQ_hpp 3 | 4 | #include "ast/operators/ast_binaryOperation.hpp" 5 | 6 | class BinaryNEQ 7 | : public BinaryOperation 8 | { 9 | public: 10 | 11 | using BinaryOperation::BinaryOperation; 12 | 13 | virtual void PrettyPrint(std::ostream &dst, std::string indent) const override; 14 | virtual void generateMIPS(std::ostream &dst, Context &context, int destReg) const override; 15 | 16 | 17 | }; 18 | 19 | #endif -------------------------------------------------------------------------------- /include/ast/operators/binaryOps/ast_binaryOR.hpp: -------------------------------------------------------------------------------- 1 | #ifndef ast_binaryOR_hpp 2 | #define ast_binaryOR_hpp 3 | 4 | #include "ast/operators/ast_binaryOperation.hpp" 5 | 6 | class BinaryOR 7 | : public BinaryOperation 8 | { 9 | public: 10 | 11 | using BinaryOperation::BinaryOperation; 12 | 13 | virtual void PrettyPrint(std::ostream &dst, std::string indent) const override; 14 | virtual void generateMIPS(std::ostream &dst, Context &context, int destReg) const override; 15 | 16 | 17 | }; 18 | 19 | #endif -------------------------------------------------------------------------------- /include/ast/operators/binaryOps/ast_binaryRShift.hpp: -------------------------------------------------------------------------------- 1 | #ifndef ast_binaryRShift_hpp 2 | #define ast_binaryRShift_hpp 3 | 4 | #include "ast/operators/ast_binaryOperation.hpp" 5 | 6 | class BinaryRShift 7 | : public BinaryOperation 8 | { 9 | public: 10 | 11 | using BinaryOperation::BinaryOperation; 12 | 13 | virtual void PrettyPrint(std::ostream &dst, std::string indent) const override; 14 | virtual void generateMIPS(std::ostream &dst, Context &context, int destReg) const override; 15 | 16 | 17 | }; 18 | 19 | #endif -------------------------------------------------------------------------------- /include/ast/operators/binaryOps/ast_binarySub.hpp: -------------------------------------------------------------------------------- 1 | #ifndef ast_binarySub_hpp 2 | #define ast_binarySub_hpp 3 | 4 | #include "ast/operators/ast_binaryOperation.hpp" 5 | 6 | class BinarySub 7 | : public BinaryOperation 8 | { 9 | public: 10 | 11 | using BinaryOperation::BinaryOperation; 12 | 13 | virtual void PrettyPrint(std::ostream &dst, std::string indent) const override; 14 | virtual void generateMIPS(std::ostream &dst, Context &context, int destReg) const override; 15 | void generateTypeMIPS(std::ostream &dst, Context &context, int destReg, enum Specifier type) const override; 16 | 17 | 18 | 19 | }; 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /include/ast/operators/binaryOps/ast_binaryXOR.hpp: -------------------------------------------------------------------------------- 1 | #ifndef ast_binaryXOR_hpp 2 | #define ast_binaryXOR_hpp 3 | 4 | #include "ast/operators/ast_binaryOperation.hpp" 5 | 6 | class BinaryXOR 7 | : public BinaryOperation 8 | { 9 | public: 10 | 11 | using BinaryOperation::BinaryOperation; 12 | 13 | virtual void PrettyPrint(std::ostream &dst, std::string indent) const override; 14 | virtual void generateMIPS(std::ostream &dst, Context &context, int destReg) const override; 15 | 16 | 17 | }; 18 | 19 | #endif -------------------------------------------------------------------------------- /include/ast/operators/unaryOps/ast_unaryAdr.hpp: -------------------------------------------------------------------------------- 1 | #ifndef ast_unaryAdr_hpp 2 | #define ast_unaryAdr_hpp 3 | 4 | #include "ast/operators/ast_unaryOperation.hpp" 5 | 6 | class UnaryAdr 7 | : public UnaryOperation 8 | { 9 | public: 10 | 11 | using UnaryOperation::UnaryOperation; 12 | 13 | virtual void PrettyPrint(std::ostream &dst, std::string indent) const override; 14 | virtual void generateMIPS(std::ostream &dst, Context &context, int destReg) const override; 15 | 16 | 17 | }; 18 | 19 | #endif 20 | 21 | 22 | -------------------------------------------------------------------------------- /include/ast/operators/unaryOps/ast_unaryBWNOT.hpp: -------------------------------------------------------------------------------- 1 | #ifndef ast_unaryBWNOT_hpp 2 | #define ast_unaryBWNOT_hpp 3 | 4 | #include "ast/operators/ast_unaryOperation.hpp" 5 | 6 | class UnaryBWNOT 7 | : public UnaryOperation 8 | { 9 | public: 10 | 11 | using UnaryOperation::UnaryOperation; 12 | 13 | virtual void PrettyPrint(std::ostream &dst, std::string indent) const override; 14 | virtual void generateMIPS(std::ostream &dst, Context &context, int destReg) const override; 15 | 16 | 17 | }; 18 | 19 | #endif 20 | 21 | 22 | -------------------------------------------------------------------------------- /include/ast/operators/unaryOps/ast_unaryDec.hpp: -------------------------------------------------------------------------------- 1 | #ifndef ast_unaryDec_hpp 2 | #define ast_unaryDec_hpp 3 | 4 | #include "ast/operators/ast_unaryOperation.hpp" 5 | 6 | class UnaryDec 7 | : public UnaryOperation 8 | { 9 | public: 10 | 11 | using UnaryOperation::UnaryOperation; 12 | 13 | virtual void PrettyPrint(std::ostream &dst, std::string indent) const override; 14 | virtual void generateMIPS(std::ostream &dst, Context &context, int destReg) const override; 15 | 16 | 17 | }; 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /include/ast/operators/unaryOps/ast_unaryInc.hpp: -------------------------------------------------------------------------------- 1 | #ifndef ast_unaryInc_hpp 2 | #define ast_unaryInc_hpp 3 | 4 | #include "ast/operators/ast_unaryOperation.hpp" 5 | 6 | class UnaryInc 7 | : public UnaryOperation 8 | { 9 | public: 10 | 11 | using UnaryOperation::UnaryOperation; 12 | 13 | virtual void PrettyPrint(std::ostream &dst, std::string indent) const override; 14 | virtual void generateMIPS(std::ostream &dst, Context &context, int destReg) const override; 15 | 16 | 17 | }; 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /include/ast/operators/unaryOps/ast_unaryNOT.hpp: -------------------------------------------------------------------------------- 1 | #ifndef ast_unaryNOT_hpp 2 | #define ast_unaryNOT_hpp 3 | 4 | #include "ast/operators/ast_unaryOperation.hpp" 5 | 6 | class UnaryNOT 7 | : public UnaryOperation 8 | { 9 | public: 10 | 11 | using UnaryOperation::UnaryOperation; 12 | 13 | virtual void PrettyPrint(std::ostream &dst, std::string indent) const override; 14 | virtual void generateMIPS(std::ostream &dst, Context &context, int destReg) const override; 15 | 16 | 17 | }; 18 | 19 | #endif 20 | 21 | 22 | -------------------------------------------------------------------------------- /include/ast/operators/unaryOps/ast_unaryPostDec.hpp: -------------------------------------------------------------------------------- 1 | #ifndef ast_unaryPostDec_hpp 2 | #define ast_unaryPostDec_hpp 3 | 4 | #include "ast/operators/ast_unaryOperation.hpp" 5 | 6 | class UnaryPostDec 7 | : public UnaryOperation 8 | { 9 | public: 10 | 11 | using UnaryOperation::UnaryOperation; 12 | 13 | virtual void PrettyPrint(std::ostream &dst, std::string indent) const override; 14 | virtual void generateMIPS(std::ostream &dst, Context &context, int destReg) const override; 15 | 16 | 17 | }; 18 | 19 | #endif -------------------------------------------------------------------------------- /include/ast/operators/unaryOps/ast_unaryPostInc.hpp: -------------------------------------------------------------------------------- 1 | #ifndef ast_unaryPostInc_hpp 2 | #define ast_unaryPostInc_hpp 3 | 4 | #include "ast/operators/ast_unaryOperation.hpp" 5 | 6 | class UnaryPostInc 7 | : public UnaryOperation 8 | { 9 | public: 10 | 11 | using UnaryOperation::UnaryOperation; 12 | 13 | virtual void PrettyPrint(std::ostream &dst, std::string indent) const override; 14 | virtual void generateMIPS(std::ostream &dst, Context &context, int destReg) const override; 15 | 16 | 17 | }; 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /include/ast/operators/unaryOps/ast_unaryPtr.hpp: -------------------------------------------------------------------------------- 1 | #ifndef ast_unaryPtr_hpp 2 | #define ast_unaryPtr_hpp 3 | 4 | #include "ast/operators/ast_unaryOperation.hpp" 5 | 6 | class UnaryPtr 7 | : public UnaryOperation 8 | { 9 | public: 10 | 11 | using UnaryOperation::UnaryOperation; 12 | 13 | virtual void PrettyPrint(std::ostream &dst, std::string indent) const override; 14 | virtual void generateMIPS(std::ostream &dst, Context &context, int destReg) const override; 15 | virtual void generateTypeMIPS(std::ostream &dst, Context &context, int destReg, enum Specifier type) const override; 16 | 17 | virtual bool isPtr() const override; 18 | 19 | }; 20 | 21 | #endif 22 | 23 | 24 | -------------------------------------------------------------------------------- /include/ast/operators/unaryOps/ast_unarySub.hpp: -------------------------------------------------------------------------------- 1 | #ifndef ast_unarySub_hpp 2 | #define ast_unarySub_hpp 3 | 4 | #include "ast/operators/ast_unaryOperation.hpp" 5 | 6 | class UnarySub 7 | : public UnaryOperation 8 | { 9 | public: 10 | 11 | using UnaryOperation::UnaryOperation; 12 | 13 | virtual void PrettyPrint(std::ostream &dst, std::string indent) const override; 14 | virtual void generateMIPS(std::ostream &dst, Context &context, int destReg) const override; 15 | void generateTypeMIPS(std::ostream &dst, Context &context, int destReg, enum Specifier type) const override; 16 | 17 | 18 | }; 19 | 20 | #endif 21 | 22 | 23 | -------------------------------------------------------------------------------- /include/ast/types/ast_enumSpecifier.hpp: -------------------------------------------------------------------------------- 1 | #ifndef ast_enumSpecifier_hpp 2 | #define ast_enumSpecifier_hpp 3 | 4 | #include "ast/ast_node.hpp" 5 | 6 | class EnumSpecifier 7 | : public Node 8 | { 9 | public: 10 | // Constructor 11 | EnumSpecifier(std::string _id, std::vector enums); 12 | EnumSpecifier(std::string _id); // Not sure what this actually does functionally 13 | 14 | // Destructor 15 | ~EnumSpecifier(); 16 | 17 | // Visualising 18 | void PrettyPrint(std::ostream &dst, std::string indent) const override; 19 | 20 | // Codegen 21 | void generateMIPS(std::ostream &dst, Context &context, int destReg) const override; 22 | std::string getId() const override; 23 | int getSize() const override; 24 | bool isEnum() const override; 25 | enum Specifier getType() const override; 26 | 27 | protected: 28 | std::string id; 29 | }; 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /include/ast/types/ast_enumerator.hpp: -------------------------------------------------------------------------------- 1 | #ifndef ast_enumerator_hpp 2 | #define ast_enumerator_hpp 3 | 4 | #include "ast/ast_node.hpp" 5 | 6 | class Enumerator 7 | : public Node 8 | { 9 | public: 10 | // Constructor 11 | Enumerator(std::string _id, NodePtr expression); 12 | 13 | // Destructor 14 | ~Enumerator(); 15 | 16 | // Visualising 17 | void PrettyPrint(std::ostream &dst, std::string indent) const override; 18 | 19 | // Codegen 20 | //void generateMIPS(std::ostream &dst, Context &context, int destReg) const override; // idk if we need this rn 21 | NodePtr getNode(unsigned index) const override; 22 | bool isEnum() const override; 23 | std::string getId() const override; 24 | int getValue() const override; 25 | 26 | protected: 27 | std::string id; 28 | }; 29 | 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /include/ast/types/ast_primitive.hpp: -------------------------------------------------------------------------------- 1 | #ifndef ast_primitive_hpp 2 | #define ast_primitive_hpp 3 | 4 | #include "ast/ast_node.hpp" 5 | 6 | class PrimitiveType 7 | : public Node 8 | { 9 | public: 10 | // Constructor 11 | PrimitiveType(enum Specifier _type); 12 | 13 | // Destructor 14 | ~PrimitiveType(); 15 | 16 | // Visualising 17 | void PrettyPrint(std::ostream &dst, std::string indent) const override; 18 | 19 | // Helper for codegen 20 | int getSize() const override; 21 | enum Specifier getType() const override; 22 | protected: 23 | enum Specifier type; 24 | }; 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /include/ast/types/ast_typedef.hpp: -------------------------------------------------------------------------------- 1 | #ifndef ast_typedef_hpp 2 | #define ast_typedef_hpp 3 | 4 | #include "ast/ast_node.hpp" 5 | 6 | class TypeDef 7 | : public Node 8 | { 9 | public: 10 | // Constructor 11 | TypeDef(NodePtr type); 12 | 13 | // Destructor 14 | ~TypeDef(); 15 | 16 | // Visualising 17 | void PrettyPrint(std::ostream &dst, std::string indent) const override; 18 | }; 19 | 20 | 21 | 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /include/parser_list.hpp: -------------------------------------------------------------------------------- 1 | #ifndef parser_list_hpp 2 | #define parser_list_hpp 3 | 4 | #include "ast/ast_node.hpp" 5 | 6 | #include 7 | 8 | // Functions to be used in parser for instantiation / concatenation 9 | typedef std::vector List; 10 | typedef List *ListPtr; 11 | 12 | // Functions to be used in parser for instantiation / concatenation 13 | inline ListPtr initList(NodePtr expr) 14 | { 15 | ListPtr exprList = new List(); // Potentially replace with Nodelist(NodePtr) constructor 16 | exprList->push_back(expr); 17 | return exprList; 18 | } 19 | 20 | inline ListPtr concatList(ListPtr exprList, NodePtr expr) 21 | { 22 | exprList->push_back(expr); 23 | return exprList; 24 | } 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /src/compiler.cpp: -------------------------------------------------------------------------------- 1 | #include "ast.hpp" 2 | 3 | #include // Headers for formatting 4 | #include 5 | void printHeader(std::string title); // Nice pretty output format 6 | 7 | int main(int argc, char *argv[]) 8 | { 9 | if(argc < 5){ 10 | std::cerr<<"Usage: bin/c_compiler -S [source-file.c] -o [dest-file.s] -V (optional)"<generateMIPS(std::cout, context_vis, 2); 31 | } 32 | 33 | // Actual compilation 34 | Context context; 35 | // Directives 36 | std::vector macros = { 37 | ".section .mdebug.abi32", 38 | ".previous", 39 | ".nan legacy", 40 | ".module fp=32", 41 | ".module nooddspreg" 42 | }; 43 | std::ofstream ofs(argv[4], std::ofstream::out); 44 | if(ofs.is_open()){ 45 | for(unsigned i = 0; i < macros.size(); i++){ 46 | ofs << macros[i] << std::endl; 47 | } 48 | program->generateMIPS(ofs, context, 2); 49 | ofs.close(); 50 | } 51 | else{ 52 | std::cerr << "Couldn't open output file: " << argv[4] << std::endl; 53 | exit(1); 54 | } 55 | 56 | // delete program; <- Get this working one day :) 57 | } 58 | 59 | void printHeader(std::string title){ 60 | struct winsize size; 61 | ioctl(STDOUT_FILENO, TIOCGWINSZ, &size); 62 | int width = size.ws_col; 63 | int lead = (width-title.length())/2; 64 | int extra = (width-title.length())%2; 65 | std::string buffer (lead, '='); 66 | std::string pad = (extra) ? "=" : ""; 67 | std::cout << buffer << title << buffer << pad << std::endl; 68 | } 69 | -------------------------------------------------------------------------------- /src/include_impl/ast/arrays/ast_arrayDeclarator.cpp: -------------------------------------------------------------------------------- 1 | #include "ast/arrays/ast_arrayDeclarator.hpp" 2 | 3 | // Constructors 4 | ArrayDeclarator::ArrayDeclarator(NodePtr id, NodePtr size) 5 | { 6 | branches.push_back(id); 7 | branches.push_back(size); 8 | } 9 | 10 | 11 | ArrayDeclarator::ArrayDeclarator(NodePtr id) 12 | : ArrayDeclarator(id, new Integer(-1)) 13 | { 14 | 15 | } 16 | 17 | // Destructor 18 | ArrayDeclarator::~ArrayDeclarator() 19 | { 20 | delete branches[0]; 21 | delete branches[1]; 22 | } 23 | 24 | // Visualising 25 | void ArrayDeclarator::PrettyPrint(std::ostream &dst, std::string indent) const 26 | { 27 | dst << indent << "Array Declarator [" << std::endl; 28 | dst << indent << "Identifier: " << std::endl; 29 | branches[0]->PrettyPrint(dst, indent+" "); 30 | dst << indent << "Size: " << std::endl; 31 | branches[1]->PrettyPrint(dst, indent+" "); 32 | dst << indent << "]" << std::endl; 33 | } 34 | 35 | // Codegen helpers 36 | std::string ArrayDeclarator::getId() const 37 | { 38 | return branches[0]->getId(); 39 | } 40 | 41 | bool ArrayDeclarator::isInit() const 42 | { 43 | return false; 44 | } 45 | 46 | bool ArrayDeclarator::isFunction() const 47 | { 48 | return false; 49 | } 50 | 51 | int ArrayDeclarator::getArraySize() const // gets size of array when its being declared 52 | { 53 | return branches[1]->getValue(); 54 | } 55 | -------------------------------------------------------------------------------- /src/include_impl/ast/arrays/ast_arrayInit.cpp: -------------------------------------------------------------------------------- 1 | #include "ast/arrays/ast_arrayInit.hpp" 2 | 3 | ArrayInit::ArrayInit(std::vector elements) 4 | : Node(elements) 5 | {} 6 | 7 | ArrayInit::~ArrayInit() 8 | { 9 | for(unsigned i = 0; i < branches.size(); i++){ 10 | delete branches[i]; 11 | } 12 | } 13 | 14 | void ArrayInit::PrettyPrint(std::ostream &dst, std::string indent) const 15 | { 16 | dst << indent << "Array Initializer [" << std::endl; 17 | for(unsigned i = 0; i < branches.size(); i++){ 18 | dst << indent << i << ": " << std::endl; 19 | branches[i]->PrettyPrint(dst, indent+" "); 20 | } 21 | dst << indent << "] endInitializer" << std::endl; 22 | } 23 | 24 | void ArrayInit::generateMIPS(std::ostream &dst, Context &context, int destReg) const 25 | { 26 | for(unsigned i = 0; i < branches.size(); i++){ 27 | branches[i]->generateMIPS(dst, context, destReg); 28 | dst << "sw $" << destReg << ", " << i*4 << "($29)" << std::endl; 29 | } 30 | } 31 | 32 | int ArrayInit::getValue(int i) const 33 | { 34 | if(i < branches.size()){ 35 | return branches[i]->getValue(); 36 | } 37 | std::cerr << "WARNING: Trying to getValue outside initializer range" << std::endl; 38 | return 0; // Default initialisation = 0 39 | } 40 | 41 | double ArrayInit::getFloat(int i) const 42 | { 43 | if(i < branches.size()){ 44 | return branches[i]->getFloat(); 45 | } 46 | std::cerr << "WARNING: Trying to getFloat outside intializer range" << std::endl; 47 | } 48 | 49 | void ArrayInit::generateTypeMIPS(std::ostream &dst, Context &context, int destReg, enum Specifier type) const 50 | { 51 | 52 | switch(type) 53 | { 54 | case _float: 55 | { 56 | for( unsigned i = 0; i < branches.size(); i++ ){ 57 | branches[i]->generateTypeMIPS(dst, context, destReg, type); 58 | dst << "swc1 $f" << destReg << ", " << i*4 << "($29)" << std::endl; 59 | } 60 | break; 61 | } 62 | 63 | case _double: 64 | { 65 | for( unsigned i = 0; i < branches.size(); i++ ){ 66 | branches[i]->generateTypeMIPS(dst, context, destReg, type); 67 | dst << "sdc1 $f" << destReg << ", " << i*8 << "($29)" << std::endl; 68 | } 69 | break; 70 | } 71 | 72 | } 73 | 74 | } 75 | 76 | -------------------------------------------------------------------------------- /src/include_impl/ast/ast_declarator.cpp: -------------------------------------------------------------------------------- 1 | #include "ast/ast_declarator.hpp" 2 | 3 | // Constructors 4 | Declarator::Declarator(NodePtr id) 5 | { 6 | branches.push_back(id); 7 | } 8 | 9 | Declarator::Declarator(std::string id) 10 | : Declarator(new Identifier(id)) 11 | {} 12 | 13 | // Destructor 14 | Declarator::~Declarator() 15 | { 16 | delete branches[0]; 17 | } 18 | 19 | // Visualising 20 | void Declarator::PrettyPrint(std::ostream &dst, std::string indent) const 21 | { 22 | dst << indent << "Declarator: [" << std::endl; 23 | branches[0]->PrettyPrint(dst, indent+" "); 24 | dst << indent << "]" << std::endl; 25 | } 26 | 27 | // Helpers for codegen 28 | std::string Declarator::getId() const 29 | { 30 | return branches[0]->getId(); 31 | } 32 | 33 | bool Declarator::isFunction() const 34 | { 35 | return false; 36 | } 37 | 38 | bool Declarator::isInit() const 39 | { 40 | return false; 41 | } 42 | -------------------------------------------------------------------------------- /src/include_impl/ast/ast_empty.cpp: -------------------------------------------------------------------------------- 1 | #include "ast/ast_empty.hpp" 2 | 3 | void EmptyNode::PrettyPrint(std::ostream &dst, std::string indent) const 4 | { 5 | dst << indent << "EmptyNode" << std::endl; 6 | } 7 | -------------------------------------------------------------------------------- /src/include_impl/ast/ast_initDeclarator.cpp: -------------------------------------------------------------------------------- 1 | #include "ast/ast_initDeclarator.hpp" 2 | 3 | // Constructor 4 | InitDeclarator::InitDeclarator(NodePtr declarator, NodePtr initializer) 5 | { 6 | branches.push_back(declarator); 7 | branches.push_back(initializer); 8 | } 9 | 10 | // Destructor 11 | InitDeclarator::~InitDeclarator() 12 | { 13 | delete branches[0]; 14 | delete branches[1]; 15 | } 16 | 17 | // Visualising 18 | void InitDeclarator::PrettyPrint(std::ostream &dst, std::string indent) const 19 | { 20 | branches[0]->PrettyPrint(dst, indent); 21 | dst << indent << "Initializer : [" << std::endl; 22 | branches[1]->PrettyPrint(dst, indent+" "); 23 | dst << indent << "]" << std::endl; 24 | } 25 | 26 | // Codegen (could probably refactor into here if necessary -- will do later) 27 | void InitDeclarator::generateMIPS(std::ostream &dst, Context &context, int destReg) const 28 | { 29 | branches[1]->generateMIPS(dst, context, destReg); 30 | } 31 | 32 | void InitDeclarator::generateTypeMIPS(std::ostream &dst, Context &context, int destReg, enum Specifier type) const 33 | { 34 | branches[1]->generateTypeMIPS(dst, context, destReg, type); 35 | } 36 | 37 | // Helpers 38 | std::string InitDeclarator::getId() const 39 | { 40 | return branches[0]->getId(); 41 | } 42 | 43 | bool InitDeclarator::isFunction() const 44 | { 45 | return branches[0]->isFunction(); 46 | } 47 | 48 | bool InitDeclarator::isInit() const 49 | { 50 | return true; 51 | } 52 | 53 | int InitDeclarator::getValue() const 54 | { 55 | return branches[1]->getValue(); 56 | } 57 | 58 | int InitDeclarator::getValue(int i) const 59 | { 60 | return branches[1]->getValue(i); 61 | } 62 | 63 | double InitDeclarator::getFloat() const 64 | { 65 | return branches[1]->getFloat(); 66 | } 67 | 68 | double InitDeclarator::getFloat(int i) const 69 | { 70 | return branches[1]->getFloat(i); 71 | } 72 | 73 | int InitDeclarator::getArraySize() const 74 | { 75 | return branches[0]->getArraySize(); 76 | } 77 | -------------------------------------------------------------------------------- /src/include_impl/ast/ast_nodeList.cpp: -------------------------------------------------------------------------------- 1 | #include "ast/ast_nodeList.hpp" 2 | 3 | // Constructors 4 | NodeList::NodeList(std::vector nodes) 5 | { 6 | branches = nodes; 7 | } 8 | 9 | NodeList::NodeList() 10 | : NodeList(std::vector{}) 11 | {} 12 | 13 | // Destructor 14 | NodeList::~NodeList() 15 | { 16 | for(unsigned i = 0; i < branches.size(); i++){ 17 | delete branches[i]; 18 | } 19 | } 20 | 21 | // Visualising 22 | void NodeList::PrettyPrint(std::ostream &dst, std::string indent) const 23 | { 24 | dst << indent << "NodeList [" << std::endl; 25 | for(unsigned i = 0; i < branches.size(); i++){ 26 | branches[i]->PrettyPrint(dst, indent+" "); 27 | } 28 | dst << indent << "]" << std::endl; 29 | } 30 | 31 | // Get stuff in list - codegen helper 32 | NodePtr NodeList::getNode(unsigned index) const 33 | { 34 | if(index < branches.size()){ 35 | return branches[index]; 36 | } 37 | else{ 38 | return NULL; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/include_impl/ast/ast_pointerDeclarator.cpp: -------------------------------------------------------------------------------- 1 | #include "ast/ast_pointerDeclarator.hpp" 2 | 3 | // Constructors 4 | PointerDeclarator::PointerDeclarator(NodePtr id) 5 | { 6 | branches.push_back(id); 7 | } 8 | 9 | // Destructor 10 | PointerDeclarator::~PointerDeclarator() 11 | { 12 | delete branches[0]; 13 | } 14 | 15 | // Visualising 16 | void PointerDeclarator::PrettyPrint(std::ostream &dst, std::string indent) const 17 | { 18 | dst << indent << "Pointer Declarator [" << std::endl; 19 | dst << indent << "Identifier: " << std::endl; 20 | branches[0]->PrettyPrint(dst, indent+" "); 21 | dst << indent << "]" << std::endl; 22 | } 23 | 24 | // Codegen helpers 25 | std::string PointerDeclarator::getId() const 26 | { 27 | return branches[0]->getId(); 28 | } 29 | 30 | bool PointerDeclarator::isInit() const 31 | { 32 | return false; 33 | } 34 | 35 | bool PointerDeclarator::isFunction() const 36 | { 37 | return false; 38 | } 39 | 40 | bool PointerDeclarator::isPtr() const 41 | { 42 | return true; 43 | } 44 | -------------------------------------------------------------------------------- /src/include_impl/ast/ast_root.cpp: -------------------------------------------------------------------------------- 1 | #include "ast/ast_root.hpp" 2 | 3 | // Constructor 4 | Root::Root(NodePtr globalScope) 5 | { 6 | branches.push_back(globalScope); 7 | } 8 | 9 | // Destructor 10 | Root::~Root() 11 | { 12 | delete branches[0]; 13 | } 14 | 15 | // Visualising 16 | void Root::PrettyPrint(std::ostream &dst, std::string indent) const 17 | { 18 | branches[0]->PrettyPrint(dst, indent); 19 | } 20 | 21 | // Codegen 22 | void Root::generateMIPS(std::ostream &dst, Context &context, int destReg) const 23 | { 24 | branches[0]->generateMIPS(dst, context, destReg); 25 | } 26 | -------------------------------------------------------------------------------- /src/include_impl/ast/blocks/ast_for.cpp: -------------------------------------------------------------------------------- 1 | #include "ast/blocks/ast_for.hpp" 2 | 3 | // Constructor 4 | For::For(NodePtr initializer, NodePtr condition, NodePtr increment, NodePtr scope) 5 | { 6 | branches.push_back(initializer); 7 | branches.push_back(condition); 8 | branches.push_back(increment); 9 | branches.push_back(scope); 10 | } 11 | 12 | // Destructor 13 | For::~For() 14 | { 15 | for(unsigned i = 0; i < 4; i++){ // I used the for loop to destroy the for loop 16 | delete branches[i]; 17 | } 18 | } 19 | 20 | // Visualising 21 | void For::PrettyPrint(std::ostream &dst, std::string indent) const 22 | { 23 | dst << indent << "For initilisation [" << std::endl; 24 | branches[0]->PrettyPrint(dst, indent+" "); 25 | dst << indent+" " << "Condition: " << std::endl; 26 | branches[1]->PrettyPrint(dst, indent+" "); 27 | dst << indent+" " << "Increment: " << std::endl; 28 | branches[2]->PrettyPrint(dst, indent+" "); 29 | dst << indent << "] endInitialisation" << std::endl; 30 | dst << indent << "Do scope [" << std::endl; 31 | branches[3]->PrettyPrint(dst, indent+" "); 32 | dst << indent << "]endDoScope" << std::endl; 33 | } 34 | 35 | // Codegen 36 | void For::generateMIPS(std::ostream &dst, Context &context, int destReg) const 37 | { 38 | // Required for initializer 39 | context.enterScope(); 40 | 41 | // Initialise iterator 42 | int itReg = context.allocate(); 43 | branches[0]->generateMIPS(dst, context, itReg); 44 | 45 | // Start of loop 46 | std::string startLabel = context.makeLabel("START"); 47 | dst << startLabel << ":" << std::endl; 48 | // To handle continue statements 49 | std::string incLabel = context.makeLabel("INC"); 50 | context.stack.back().startLabel = incLabel; 51 | // Evaluate condition 52 | branches[1]->generateMIPS(dst, context, itReg); 53 | 54 | // Loopy bit 55 | std::string endLabel = context.makeLabel("END"); 56 | context.stack.back().endLabel = endLabel; 57 | dst << "beq $" << itReg << ",$0," << endLabel << std::endl; 58 | dst << "nop" << std::endl; 59 | unsigned i = 0; 60 | NodePtr node = branches[3]->getNode(i); 61 | while(node != NULL){ 62 | node->generateMIPS(dst, context, destReg); // Scope 63 | i++; 64 | node = branches[3]->getNode(i); 65 | } 66 | dst << incLabel << ":" << std::endl; 67 | branches[2]->generateMIPS(dst, context, itReg); // Increment 68 | dst << "b " << startLabel << std::endl; 69 | dst << "nop" << std::endl; 70 | 71 | // End of loop 72 | dst << endLabel << ":" << std::endl; 73 | context.regFile.freeReg(itReg); 74 | context.exitScope(dst); 75 | } 76 | -------------------------------------------------------------------------------- /src/include_impl/ast/blocks/ast_ifElse.cpp: -------------------------------------------------------------------------------- 1 | #include "ast/blocks/ast_ifElse.hpp" 2 | 3 | // Constructors 4 | IfElse::IfElse(NodePtr condition, NodePtr ifScope, NodePtr elseScope) 5 | { 6 | branches.push_back(condition); 7 | branches.push_back(ifScope); 8 | branches.push_back(elseScope); 9 | } 10 | 11 | IfElse::IfElse(NodePtr condition, NodePtr ifScope) 12 | : IfElse(condition, ifScope, new Scope()) 13 | {} 14 | 15 | // Destructor 16 | IfElse::~IfElse() 17 | { 18 | delete branches[0]; 19 | delete branches[1]; 20 | delete branches[2]; 21 | } 22 | 23 | // Visualising 24 | void IfElse::PrettyPrint(std::ostream &dst, std::string indent) const 25 | { 26 | dst << indent << "Condition [" << std::endl; 27 | branches[0]->PrettyPrint(dst, indent+" "); 28 | dst << indent << "] endCondition" << std::endl; 29 | dst << indent << "If Scope [" << std::endl; 30 | branches[1]->PrettyPrint(dst, indent+" "); 31 | dst << indent << "] endIfScope" << std::endl; 32 | dst << indent << "Else Scope [" << std::endl; 33 | branches[2]->PrettyPrint(dst, indent+" "); 34 | dst << indent << "] endElseScope" << std::endl; 35 | } 36 | 37 | // Codegen 38 | void IfElse::generateMIPS(std::ostream &dst, Context &context, int destReg) const 39 | { 40 | // If scope (needed for condition) 41 | context.enterScope(); 42 | 43 | // Evaluate condition 44 | int conReg = context.allocate(); 45 | branches[0]->generateMIPS(dst, context, conReg); 46 | 47 | // If branch 48 | std::string elseLabel = context.makeLabel("ELSE"); 49 | std::string endLabel = context.makeLabel("ENDIF"); 50 | dst << "beq $" << conReg << ",$0," << elseLabel << std::endl; 51 | dst << "nop" << std::endl; 52 | context.regFile.freeReg(conReg); // Condition no longer needed 53 | // Generate mips for contents of scope 54 | unsigned i = 0; 55 | NodePtr node = branches[1]->getNode(i); 56 | while(node != NULL){ 57 | node->generateMIPS(dst, context, destReg); 58 | i++; 59 | node = branches[1]->getNode(i); 60 | } 61 | context.exitScope(dst); // Exit ifscope 62 | dst << "b " << endLabel << std::endl; // Go to end of ifElse 63 | dst << "nop" << std::endl; 64 | 65 | // Else branch 66 | dst << elseLabel << ":" << std::endl; 67 | branches[2]->generateMIPS(dst, context, destReg); 68 | 69 | // End of ifElse 70 | dst << endLabel << ":" << std::endl; 71 | } 72 | -------------------------------------------------------------------------------- /src/include_impl/ast/blocks/ast_scope.cpp: -------------------------------------------------------------------------------- 1 | #include "ast/blocks/ast_scope.hpp" 2 | 3 | // Visualising 4 | void Scope::PrettyPrint(std::ostream &dst, std::string indent) const 5 | { 6 | dst << indent << "Scope [" << std::endl; 7 | for(unsigned i = 0; i < branches.size(); i++){ 8 | branches[i]->PrettyPrint(dst, indent+" "); 9 | } 10 | dst << indent << "]" << std::endl; 11 | } 12 | 13 | // Codegen 14 | void Scope::generateMIPS(std::ostream &dst, Context &context, int destReg) const 15 | { 16 | context.enterScope(); 17 | for(unsigned i = 0; i < branches.size(); i++){ 18 | branches[i]->generateMIPS(dst, context, destReg); 19 | } 20 | context.exitScope(dst); 21 | } 22 | -------------------------------------------------------------------------------- /src/include_impl/ast/blocks/ast_scopeGlobal.cpp: -------------------------------------------------------------------------------- 1 | #include "ast/blocks/ast_scopeGlobal.hpp" 2 | 3 | // Visualising 4 | void GlobalScope::PrettyPrint(std::ostream &dst, std::string indent) const 5 | { 6 | dst << indent << "Global Scope [" << std::endl; 7 | for(unsigned i = 0; i < branches.size(); i++){ 8 | branches[i]->PrettyPrint(dst, indent+" "); 9 | } 10 | dst << indent << "]" << std::endl; 11 | } 12 | 13 | // Codegen 14 | void GlobalScope::generateMIPS(std::ostream &dst, Context &context, int destReg) const 15 | { 16 | for(unsigned i = 0; i < branches.size(); i++){ 17 | if(branches[i]->isFunction()){ 18 | branches[i]->generateMIPS(dst, context, destReg); 19 | } 20 | else if(branches[i]->isEnum()){ 21 | branches[i]->generateMIPS(dst, context, destReg); 22 | } 23 | else{ 24 | // Global variables 25 | std::string id = branches[i]->getId(); 26 | enum Specifier type = branches[i]->getType(); 27 | context.globals.insert(std::pair(id, type)); // Add to global set 28 | dst << ".globl " << id << std::endl; 29 | dst << ".data" << std::endl; 30 | dst << ".align 2" << std::endl; 31 | int array = branches[i]->getArraySize(); 32 | if(array == 0){ // Not an array 33 | int size = branches[i]->getSize(); 34 | dst << ".size " << id << ", " << size << std::endl; 35 | dst << id << ":" << std::endl; 36 | if(branches[i]->isInit()){ 37 | switch(type) 38 | { 39 | case _float: 40 | dst << ".float " << (float)branches[i]->getFloat() << std::endl; // Hopefully these work 41 | break; 42 | case _double: 43 | dst << ".double " << branches[i]->getFloat() << std::endl; 44 | break; 45 | default: 46 | dst << ".word " << branches[i]->getValue() << std::endl; 47 | } 48 | 49 | } 50 | else{ 51 | dst << ".space " << size << std::endl; 52 | } 53 | } 54 | else{ 55 | int size = array*branches[i]->getSize(); 56 | dst << ".size " << id << ", " << size << std::endl; 57 | dst << id << ":" << std::endl; 58 | if(branches[i]->isInit()){ 59 | switch(type) 60 | { 61 | case _float: 62 | for(unsigned index = 0; index < array; index++){ 63 | dst << ".float " << (float)branches[i]->getFloat(index) << std::endl; 64 | } 65 | break; 66 | case _double: 67 | for(unsigned index = 0; index < array; index++){ 68 | dst << ".double " << branches[i]->getFloat(index) << std::endl; 69 | } 70 | break; 71 | default: 72 | // Initializes every index in order 73 | for(unsigned index = 0; index < array; index++){ 74 | dst << ".word " << branches[i]->getValue(index) << std::endl; 75 | } 76 | } 77 | } 78 | else{ 79 | dst << ".space " << size << std::endl; 80 | } 81 | } 82 | 83 | 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/include_impl/ast/blocks/ast_sequence.cpp: -------------------------------------------------------------------------------- 1 | #include "ast/blocks/ast_sequence.hpp" 2 | 3 | // Constructors 4 | Sequence::Sequence() 5 | { 6 | // Empty, do nothing 7 | } 8 | 9 | Sequence::Sequence(NodePtr in) 10 | { 11 | branches.push_back(in); 12 | } 13 | 14 | Sequence::Sequence(std::vector _branches) 15 | : Node(_branches) 16 | {} 17 | 18 | Sequence::Sequence(std::vector decList, std::vector statList) 19 | : Node(decList, statList) 20 | {} 21 | 22 | // Destructor 23 | Sequence::~Sequence() 24 | { 25 | for(unsigned i = 0; i < branches.size(); i++){ 26 | delete branches[i]; 27 | } 28 | } 29 | 30 | // Visualising 31 | void Sequence::PrettyPrint(std::ostream &dst, std::string indent) const 32 | { 33 | dst << indent << "Sequence [" << std::endl; 34 | for(unsigned i = 0; i < branches.size(); i++){ 35 | branches[i]->PrettyPrint(dst, indent+" "); 36 | } 37 | dst << indent << "]" << std::endl; 38 | } 39 | 40 | NodePtr Sequence::getNode(unsigned index) const 41 | { 42 | if(index < branches.size()){ 43 | return branches[index]; 44 | } 45 | return NULL; 46 | } 47 | -------------------------------------------------------------------------------- /src/include_impl/ast/blocks/ast_while.cpp: -------------------------------------------------------------------------------- 1 | #include "ast/blocks/ast_while.hpp" 2 | 3 | // Constructor 4 | While::While(NodePtr condition, NodePtr scope) 5 | { 6 | branches.push_back(condition); 7 | branches.push_back(scope); 8 | } 9 | 10 | // Destructor 11 | While::~While() 12 | { 13 | delete branches[0]; 14 | delete branches[1]; 15 | } 16 | 17 | // Visualising 18 | void While::PrettyPrint(std::ostream &dst, std::string indent) const 19 | { 20 | dst << indent << "While condition [" << std::endl; 21 | branches[0]->PrettyPrint(dst, indent+" "); 22 | dst << indent << "] endCondition" << std::endl; 23 | dst << indent << "Do scope [" << std::endl; 24 | branches[1]->PrettyPrint(dst, indent+" "); 25 | dst << indent << "] endDoScope" << std::endl; 26 | } 27 | 28 | // Codegen 29 | void While::generateMIPS(std::ostream &dst, Context &context, int destReg) const 30 | { 31 | context.enterScope(); 32 | 33 | std::string startLabel = context.makeLabel("START"); 34 | context.stack.back().startLabel = startLabel; 35 | dst << startLabel << ":" << std::endl; 36 | 37 | //Evaluate condition 38 | int conReg = context.allocate(); 39 | branches[0]->generateMIPS(dst, context, conReg); 40 | 41 | // Scope of while loop 42 | std::string endLabel = context.makeLabel("END"); 43 | context.stack.back().endLabel = endLabel; 44 | dst << "beq $" << conReg << ",$0," << endLabel << std::endl; 45 | dst << "nop" << std::endl; 46 | unsigned i = 0; 47 | NodePtr node = branches[1]->getNode(i); 48 | while(node != NULL){ 49 | node->generateMIPS(dst, context, destReg); // Scope 50 | i++; 51 | node = branches[1]->getNode(i); 52 | } 53 | dst << "b " << startLabel << std::endl; 54 | dst << "nop" << std::endl; 55 | 56 | // End of while 57 | dst << endLabel << ":" << std::endl; 58 | context.regFile.freeReg(conReg); 59 | context.exitScope(dst); // Closing scope opened for condition 60 | } 61 | -------------------------------------------------------------------------------- /src/include_impl/ast/blocks/switch/ast_case.cpp: -------------------------------------------------------------------------------- 1 | #include "ast/blocks/switch/ast_case.hpp" 2 | 3 | // Constructor 4 | Case::Case(NodePtr condition, NodePtr execute) 5 | { 6 | branches.push_back(condition); 7 | branches.push_back(execute); 8 | } 9 | 10 | // Destructor 11 | Case::~Case() 12 | { 13 | delete branches[0]; 14 | delete branches[1]; 15 | } 16 | 17 | void Case::PrettyPrint(std::ostream &dst, std::string indent) const 18 | { 19 | dst << indent << "Case [" << std::endl; 20 | dst << indent << "MatchExpression:" << std::endl; 21 | branches[0]->PrettyPrint(dst, indent+" "); 22 | dst << indent << "Execute:" << std::endl; 23 | branches[1]->PrettyPrint(dst, indent+" "); 24 | dst << indent << "] endCase" << std::endl; 25 | } 26 | 27 | void Case::generateMIPS(std::ostream &dst, Context &context, int destReg) const 28 | { 29 | // Start of case 30 | dst << context.stack.back().startLabel << ":" << std::endl; 31 | 32 | // Evaluate condition 33 | int conReg = context.allocate(); 34 | branches[0]->generateMIPS(dst, context, conReg); 35 | std::string nextCase = context.makeLabel("CASE"); 36 | context.stack.back().startLabel = nextCase; // Updates next case 37 | dst << "bne $" << conReg << ",$17," << nextCase << std::endl; // Skips to next case if condition doesn't match 38 | dst << "nop" << std::endl; 39 | context.regFile.freeReg(conReg); 40 | 41 | // Execute case 42 | branches[1]->generateMIPS(dst, context, destReg); 43 | } 44 | -------------------------------------------------------------------------------- /src/include_impl/ast/blocks/switch/ast_default.cpp: -------------------------------------------------------------------------------- 1 | #include "ast/blocks/switch/ast_default.hpp" 2 | 3 | // Constructor 4 | Default::Default(NodePtr execute) 5 | { 6 | branches.push_back(execute); 7 | } 8 | 9 | // Destructor 10 | Default::~Default() 11 | { 12 | delete branches[0]; 13 | } 14 | 15 | // Visualising 16 | void Default::PrettyPrint(std::ostream &dst, std::string indent) const 17 | { 18 | dst << indent << "Default case [" << std::endl; 19 | dst << indent << "Execute:" << std::endl; 20 | branches[0]->PrettyPrint(dst, indent+" "); 21 | dst << indent << "] endCase" << std::endl; 22 | } 23 | 24 | void Default::generateMIPS(std::ostream &dst, Context &context, int destReg) const 25 | { 26 | // Last case 27 | dst << context.stack.back().startLabel << ":" << std::endl; 28 | context.stack.back().startLabel = "DONE"; // In case no default 29 | branches[0]->generateMIPS(dst, context, destReg); 30 | } 31 | -------------------------------------------------------------------------------- /src/include_impl/ast/blocks/switch/ast_switch.cpp: -------------------------------------------------------------------------------- 1 | #include "ast/blocks/switch/ast_switch.hpp" 2 | 3 | // Constructor 4 | Switch::Switch(NodePtr expression, NodePtr scope) 5 | { 6 | branches.push_back(expression); 7 | branches.push_back(scope); 8 | } 9 | 10 | // Destructor 11 | Switch::~Switch() 12 | { 13 | delete branches[0]; 14 | delete branches[1]; 15 | } 16 | 17 | // Visualising 18 | void Switch::PrettyPrint(std::ostream &dst, std::string indent) const 19 | { 20 | dst << indent << "Switch [" << std::endl; 21 | dst << indent << "Expression: " << std::endl; 22 | branches[0]->PrettyPrint(dst, indent+" "); 23 | dst << indent << "SwitchScope:" << std::endl; 24 | branches[1]->PrettyPrint(dst, indent+" "); 25 | dst << indent << "] endSwitch" << std::endl; 26 | } 27 | 28 | // Codegen 29 | void Switch::generateMIPS(std::ostream &dst, Context &context, int destReg) const 30 | { 31 | //Basically evaluate condition, compare with condition of each case subnode 32 | // Potential workaround is to evaluate expression into special reg, and pass that along to the cases so they can do everything 33 | context.enterScope(); 34 | // Use $s1 to store evaluated expression for case comparison 35 | dst << "addiu $29,$29,-4" << std::endl; 36 | context.stack.back().offset += 4; 37 | context.stack.back().varBindings["$s1"] = {4, -context.stack.back().offset, -1}; 38 | dst << "sw $17,0($29)" << std::endl; 39 | branches[0]->generateMIPS(dst, context, 17); 40 | 41 | // Label for next case 42 | std::string nextCase = context.makeLabel("CASE"); 43 | context.stack.back().startLabel = nextCase; 44 | dst << "b " << nextCase << std::endl; 45 | dst << "nop" << std::endl; 46 | 47 | // Break stuff 48 | std::string endLabel = context.makeLabel("END"); 49 | context.stack.back().endLabel = endLabel; 50 | 51 | // Contents of switch scope 52 | unsigned i = 0; 53 | NodePtr node = branches[1]->getNode(i); 54 | while(node != NULL){ 55 | node->generateMIPS(dst, context, destReg); 56 | i++; 57 | node = branches[1]->getNode(i); 58 | } 59 | if(context.stack.back().startLabel != "DONE"){ 60 | dst << context.stack.back().startLabel << ":" << std::endl; 61 | } 62 | dst << endLabel << ":" << std::endl; 63 | 64 | // Restore $s1 65 | dst << "lw $17," << context.stack.back().varBindings["$s1"].offset << "($30)" << std::endl; 66 | context.exitScope(dst); 67 | } 68 | -------------------------------------------------------------------------------- /src/include_impl/ast/functions/ast_functionCall.cpp: -------------------------------------------------------------------------------- 1 | #include "ast/functions/ast_functionCall.hpp" 2 | #include 3 | 4 | // Constructors 5 | FunctionCall::FunctionCall(NodePtr id, NodeListPtr params) 6 | { 7 | branches.push_back(id); 8 | branches.push_back(params); 9 | } 10 | 11 | FunctionCall::FunctionCall(NodePtr id, std::vector params) 12 | : FunctionCall(id, new NodeList(params)) 13 | {} 14 | 15 | FunctionCall::FunctionCall(NodePtr id) 16 | : FunctionCall(id, new NodeList()) 17 | {} 18 | 19 | // Destructor 20 | FunctionCall::~FunctionCall() 21 | { 22 | delete branches[0]; 23 | delete branches[1]; 24 | } 25 | 26 | // Visualising 27 | void FunctionCall::PrettyPrint(std::ostream &dst, std::string indent) const 28 | { 29 | dst << indent << "Function Call [" << std::endl; 30 | dst << indent << "Identifier: " << std::endl; 31 | branches[0]->PrettyPrint(dst, indent+" "); 32 | dst << indent << "Parameters: " << std::endl; 33 | branches[1]->PrettyPrint(dst, indent+" "); 34 | dst << indent << "]" << std::endl; 35 | } 36 | 37 | // Codegen + helpers 38 | void FunctionCall::generateMIPS(std::ostream &dst, Context &context, int destReg) const 39 | { 40 | std::string id = getId(); 41 | int argSize = context.functions[id].size; 42 | //dst << "DEBUGGING: argSize of " << id << " = " << argSize << std::endl; 43 | 44 | // Staging arguments 45 | if(argSize > 0){ 46 | dst << "addiu $29,$29," << -argSize << std::endl; // Decrement stack pointer by appropriate amount 47 | NodePtr param = branches[1]->getNode(0); 48 | int i = 0; 49 | int offset = 0; 50 | while(param != NULL && i < 4){ // First 4 arguments stored in registers $4-$7 51 | param->generateMIPS(dst, context, i+4); 52 | offset += context.functions[id].argSize[i]; 53 | i++; 54 | param = branches[1]->getNode(i); 55 | } 56 | if(argSize > 16){ // Rest stored in memory 57 | int paramReg = context.allocate(); 58 | while(param != NULL){ 59 | param->generateMIPS(dst, context, paramReg); 60 | dst << "sw $" << paramReg << "," << offset << "($29)" << std::endl; 61 | offset += context.functions[id].argSize[i]; 62 | i++; 63 | param = branches[1]->getNode(i); 64 | } 65 | } 66 | } 67 | 68 | // Indicate variable stored in reg no longer available 69 | for(auto it = context.stack.back().varBindings.begin(); it != context.stack.back().varBindings.end(); it++){ 70 | std::unordered_set regs = {2, 3, 4, 5, 6, 7, 8 ,9, 10, 11, 12, 13, 14, 15, 24, 25}; // Regs changed by function calls (that we use) 71 | if(regs.find(it->second.reg) != regs.end()){ 72 | it->second.reg = -1; 73 | } 74 | } 75 | 76 | // Going to function 77 | dst << "jal " << id << std::endl; 78 | dst << "nop" << std::endl; 79 | 80 | // Returning from function 81 | dst << "addiu $29, $29," << argSize << std::endl; // Deallocate memory allocated for function call vars 82 | } 83 | 84 | std::string FunctionCall::getId() const 85 | { 86 | return branches[0]->getId(); 87 | } 88 | 89 | bool FunctionCall::isFunction() const 90 | { 91 | return true; 92 | } 93 | -------------------------------------------------------------------------------- /src/include_impl/ast/functions/ast_functionDefinition.cpp: -------------------------------------------------------------------------------- 1 | #include "ast/functions/ast_functionDefinition.hpp" 2 | 3 | // Constructors 4 | FunctionDefinition::FunctionDefinition(NodePtr declaration, NodePtr scope) 5 | { 6 | branches.push_back(declaration); 7 | branches.push_back(scope); 8 | } 9 | 10 | // Destructor 11 | FunctionDefinition::~FunctionDefinition() 12 | { 13 | delete branches[0]; 14 | delete branches[1]; 15 | } 16 | 17 | // Visualising 18 | void FunctionDefinition::PrettyPrint(std::ostream &dst, std::string indent) const 19 | { 20 | dst << indent << "Function Definition [" << std::endl; 21 | branches[0]->PrettyPrint(dst, indent+" "); 22 | branches[1]->PrettyPrint(dst, indent+" "); 23 | dst << indent << "]" << std::endl; 24 | } 25 | 26 | // Codegen 27 | void FunctionDefinition::generateMIPS(std::ostream &dst, Context &context, int destReg) const 28 | { 29 | NodePtr funcDec = branches[0]->getNode(1); 30 | funcDec->generateMIPS(dst, context, destReg); 31 | // Stores return type in stack frame created by function declaration 32 | enum Specifier returnType = branches[0]->getType(); 33 | context.stack.back().returnType = returnType; 34 | // At this point, $sp and $fp should be pointing at the right place 35 | // All params are assigned in current.varBindings, and will copied by the function call 36 | branches[1]->generateMIPS(dst, context, destReg); 37 | } 38 | 39 | bool FunctionDefinition::isFunction() const 40 | { 41 | return true; 42 | } 43 | -------------------------------------------------------------------------------- /src/include_impl/ast/keywords/ast_break.cpp: -------------------------------------------------------------------------------- 1 | #include "ast/keywords/ast_break.hpp" 2 | 3 | void Break::PrettyPrint(std::ostream &dst, std::string indent) const 4 | { 5 | dst << indent << "BREAK" << std::endl; 6 | } 7 | 8 | void Break::generateMIPS(std::ostream &dst, Context &context, int destReg) const 9 | { 10 | dst << "b " << context.stack.back().endLabel << std::endl; 11 | dst << "nop" << std::endl; 12 | } 13 | -------------------------------------------------------------------------------- /src/include_impl/ast/keywords/ast_continue.cpp: -------------------------------------------------------------------------------- 1 | #include "ast/keywords/ast_continue.hpp" 2 | 3 | void Continue::PrettyPrint(std::ostream &dst, std::string indent) const 4 | { 5 | dst << indent << "CONTINUE" << std::endl; 6 | } 7 | 8 | void Continue::generateMIPS(std::ostream &dst, Context &context, int destReg) const 9 | { 10 | dst << "b " << context.stack.back().startLabel << std::endl; 11 | dst << "nop" << std::endl; 12 | } 13 | -------------------------------------------------------------------------------- /src/include_impl/ast/keywords/ast_return.cpp: -------------------------------------------------------------------------------- 1 | #include "ast/keywords/ast_return.hpp" 2 | 3 | // Constructors 4 | Return::Return(NodePtr val) 5 | { 6 | branches.push_back(val); 7 | } 8 | 9 | /* REFACTORED INTO PARSER 10 | Return::Return() // For void funcitons (hopefully this works), returns 0 (i.e. success) 11 | : Return(new Integer()) 12 | {} 13 | */ 14 | 15 | // Destructor 16 | Return::~Return() 17 | { 18 | delete branches[0]; 19 | } 20 | 21 | // Visualising 22 | void Return::PrettyPrint(std::ostream &dst, std::string indent) const 23 | { 24 | dst << indent << "Return: [" << std::endl; 25 | branches[0]->PrettyPrint(dst, indent+" "); 26 | dst << indent << "]" << std::endl; 27 | } 28 | 29 | // Codegen 30 | void Return::generateMIPS(std::ostream &dst, Context &context, int destReg) const 31 | { 32 | switch(context.stack.back().returnType) 33 | { 34 | case _float: 35 | branches[0]->generateTypeMIPS(dst, context, 0, Specifier::_float); // Evaluates expression into $f0 (return register for floats) 36 | break; 37 | case _double: 38 | branches[0]->generateTypeMIPS(dst, context, 0, Specifier::_double); 39 | break; 40 | default: // Evaluates expression into $2 41 | branches[0]->generateMIPS(dst, context, 2); 42 | } 43 | 44 | 45 | // Exiting function 46 | dst << "move $29,$30" << std::endl; 47 | dst << "lw $30,0($29)" << std::endl; 48 | dst << "lw $31,4($29)" << std::endl; 49 | dst << "addiu $29,$29,8" << std::endl; 50 | dst << "jr $31" << std::endl; 51 | dst << "nop" << std::endl; // <- Not using delay slot (gross) 52 | } 53 | -------------------------------------------------------------------------------- /src/include_impl/ast/literals/ast_char.cpp: -------------------------------------------------------------------------------- 1 | #include "ast/literals/ast_char.hpp" 2 | 3 | // Constructor 4 | Char::Char(int _value) 5 | : value(_value) 6 | {} 7 | 8 | // Visualising 9 | void Char::PrettyPrint(std::ostream &dst, std::string indent) const 10 | { 11 | dst << indent << "Char = '" << (char)value << "'" << std::endl; 12 | } 13 | 14 | // Codegen 15 | void Char::generateTypeMIPS(std::ostream &dst, Context &context, int destReg, enum Specifier type) const 16 | { 17 | dst << "li $" << destReg << "," << value << std::endl; 18 | } 19 | 20 | int Char::getValue() const 21 | { 22 | return value; 23 | } 24 | 25 | int Char::getSize() const 26 | { 27 | return 1; 28 | } 29 | -------------------------------------------------------------------------------- /src/include_impl/ast/literals/ast_float.cpp: -------------------------------------------------------------------------------- 1 | #include "ast/literals/ast_float.hpp" 2 | 3 | // Constructors 4 | Float::Float(double _value) 5 | : value(_value) 6 | {} 7 | 8 | // Visualising 9 | void Float::PrettyPrint(std::ostream &dst, std::string indent) const 10 | { 11 | dst << indent << "Float = " << value << std::endl; 12 | } 13 | 14 | // Codegen + helpers 15 | void Float::generateTypeMIPS(std::ostream &dst, Context &context, int destReg, enum Specifier type) const 16 | { 17 | switch(type){ 18 | case _float: 19 | dst << "li.s $f" << destReg << ", " << value << std::endl; 20 | break; 21 | case _double: 22 | dst << "li.s $f" << destReg << ", " << value << std::endl; 23 | dst << "cvt.d.s $f" << destReg << ", $f" << destReg << std::endl; // Converts to double 24 | break; 25 | default: 26 | std::cerr << "Generating float but type isn't float or double" << std::endl; 27 | exit(1); 28 | } 29 | } 30 | 31 | double Float::getFloat() const 32 | { 33 | return value; 34 | } 35 | 36 | int Float::getSize() const 37 | { 38 | std::cerr << "WARNING: CALLING GETSIZE ON FLOAT LITERAL" << std::endl; 39 | return 4; 40 | } 41 | -------------------------------------------------------------------------------- /src/include_impl/ast/literals/ast_integer.cpp: -------------------------------------------------------------------------------- 1 | #include "ast/literals/ast_integer.hpp" 2 | 3 | // Constructor 4 | Integer::Integer(int _value) 5 | : value(_value) 6 | {} 7 | 8 | Integer::Integer() // Default initializer 9 | : Integer(0) 10 | {} 11 | 12 | // Visualising 13 | void Integer::PrettyPrint(std::ostream &dst, std::string indent) const 14 | { 15 | dst << indent << "Integer = " << value << std::endl; 16 | } 17 | 18 | // Codegen 19 | void Integer::generateMIPS(std::ostream &dst, Context &context, int destReg) const 20 | { 21 | dst << "li $" << destReg << "," << value << std::endl; 22 | } 23 | 24 | int Integer::getValue() const // returns value 25 | { 26 | return value; 27 | } 28 | 29 | int Integer::getSize() const 30 | { 31 | return 4; // Int size is 4 32 | } 33 | -------------------------------------------------------------------------------- /src/include_impl/ast/operators/ast_sizeof.cpp: -------------------------------------------------------------------------------- 1 | #include "ast/operators/ast_sizeof.hpp" 2 | 3 | // Constructor 4 | SizeOf::SizeOf(NodePtr type) 5 | { 6 | branches.push_back(type); 7 | } 8 | 9 | SizeOf::~SizeOf() 10 | { 11 | branches[0]; 12 | } 13 | 14 | void SizeOf::PrettyPrint(std::ostream &dst, std::string indent) const 15 | { 16 | dst << indent << "sizeof [" << std::endl; 17 | branches[0]->PrettyPrint(dst, indent+" "); 18 | dst << indent << "]" << std::endl; 19 | } 20 | 21 | void SizeOf::generateMIPS(std::ostream &dst, Context &context, int destReg) const 22 | { 23 | int size = branches[0]->getSize(); 24 | if(size != 0){ 25 | dst << "li $" << destReg << "," << size << std::endl; 26 | } 27 | else{ 28 | dst << "li $" << destReg << "," << branches[0]->getSize(context) << std::endl; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/include_impl/ast/operators/ast_unaryOperation.cpp: -------------------------------------------------------------------------------- 1 | #include "ast/operators/ast_unaryOperation.hpp" 2 | 3 | UnaryOperation::UnaryOperation(NodePtr op) 4 | { 5 | branches.push_back(op); 6 | } 7 | 8 | UnaryOperation::~UnaryOperation() 9 | { 10 | delete branches[0]; 11 | } 12 | 13 | NodePtr UnaryOperation::getOp() const 14 | { 15 | return branches[0]; 16 | } 17 | 18 | void UnaryOperation::generateMIPS(std::ostream &dst, Context &context, int destReg) const 19 | { 20 | 21 | } 22 | 23 | void UnaryOperation::ifFunction(std::ostream &dst, Context &context, int destReg) const 24 | { 25 | if(getOp()->isFunction()){ 26 | dst << "move $" << destReg << ", $2" << std::endl; 27 | 28 | } 29 | } 30 | 31 | std::string UnaryOperation::getId() const 32 | { 33 | return branches[0]->getId(); 34 | } 35 | 36 | bool UnaryOperation::isPtr() const 37 | { 38 | return branches[0]->isPtr(); 39 | } 40 | int UnaryOperation::getSize(Context &context) const 41 | { 42 | return branches[0]->getSize(context); 43 | } 44 | -------------------------------------------------------------------------------- /src/include_impl/ast/operators/binaryOps/ast_binaryAND.cpp: -------------------------------------------------------------------------------- 1 | #include "ast/operators/binaryOps/ast_binaryAND.hpp" 2 | 3 | void BinaryAND::PrettyPrint(std::ostream &dst, std::string indent) const 4 | { 5 | dst << indent << "Binary AND [ " << std::endl; 6 | dst << indent << "Left Op:" << std::endl; 7 | LeftOp()->PrettyPrint(dst, indent+" "); 8 | std::cout << indent << "Right Op: " << std::endl; 9 | RightOp()->PrettyPrint(dst, indent+" "); 10 | std::cout << indent << "]" <PrettyPrint(dst, indent+" "); 8 | std::cout << indent << "Right Op: " << std::endl; 9 | RightOp()->PrettyPrint(dst, indent+" "); 10 | std::cout << indent << "]" <generateMIPS(dst, context, destReg); 33 | }else{ 34 | LeftOp()->generateMIPS(dst, context, destReg); 35 | dst << "sll $" << destReg << ", $" << destReg << ", 2" << std::endl; 36 | } 37 | 38 | int temp = context.allocate(); 39 | if( isPtrVar(context, RightOp()) ){ 40 | RightOp()->generateMIPS(dst, context, temp); 41 | }else{ 42 | RightOp()->generateMIPS(dst, context, temp); 43 | dst << "sll $" << temp << ", $" << temp << ", 2" << std::endl; 44 | } 45 | EZPrint(dst, "add", destReg, destReg, temp); 46 | context.regFile.freeReg(temp); 47 | break; 48 | } 49 | case _float: 50 | { 51 | int regLeft = DoTypeLeft(dst, context, destReg, type); 52 | int regRight = DoTypeRight(dst, context, destReg, regLeft, type); 53 | 54 | dst << "add.s $f" << destReg << ", $f" << regLeft << ", $f" << regRight << std::endl; 55 | 56 | context.floatRegs.freeReg(regLeft); 57 | context.floatRegs.freeReg(regRight); 58 | 59 | break; 60 | } 61 | 62 | case _double: 63 | { 64 | int regLeft = DoTypeLeft(dst, context, destReg, type); 65 | int regRight = DoTypeRight(dst, context, destReg, regLeft, type); 66 | 67 | dst << "add.d $f" << destReg << ", $f" << regLeft << ", $f" << regRight << std::endl; 68 | 69 | context.floatRegs.freeReg(regLeft); 70 | context.floatRegs.freeReg(regRight); 71 | 72 | break; 73 | } 74 | 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/include_impl/ast/operators/binaryOps/ast_binaryDiv.cpp: -------------------------------------------------------------------------------- 1 | #include "ast/operators/binaryOps/ast_binaryDiv.hpp" 2 | 3 | void BinaryDiv::PrettyPrint(std::ostream &dst, std::string indent) const 4 | { 5 | dst << indent << "Binary Division [ " << std::endl; 6 | dst << indent << "Left Op:" << std::endl; 7 | LeftOp()->PrettyPrint(dst, indent+" "); 8 | std::cout << indent << "Right Op: " << std::endl; 9 | RightOp()->PrettyPrint(dst, indent+" "); 10 | std::cout << indent << "]" < pointers are we?" << std::endl; 33 | } 34 | case _float: 35 | { 36 | int regLeft = DoTypeLeft(dst, context, destReg, type); 37 | int regRight = DoTypeRight(dst, context, destReg, regLeft, type); 38 | 39 | dst << "div.s $f" << destReg << ", $f" << regLeft << ", $f" << regRight << std::endl; 40 | 41 | context.floatRegs.freeReg(regLeft); 42 | context.floatRegs.freeReg(regRight); 43 | 44 | break; 45 | } 46 | 47 | case _double: 48 | { 49 | int regLeft = DoTypeLeft(dst, context, destReg, type); 50 | int regRight = DoTypeRight(dst, context, destReg, regLeft, type); 51 | 52 | dst << "div.d $f" << destReg << ", $f" << regLeft << ", $f" << regRight << std::endl; 53 | 54 | context.floatRegs.freeReg(regLeft); 55 | context.floatRegs.freeReg(regRight); 56 | 57 | break; 58 | 59 | } 60 | 61 | } 62 | } 63 | 64 | 65 | -------------------------------------------------------------------------------- /src/include_impl/ast/operators/binaryOps/ast_binaryEQ.cpp: -------------------------------------------------------------------------------- 1 | #include "ast/operators/binaryOps/ast_binaryEQ.hpp" 2 | 3 | void BinaryEQ::PrettyPrint(std::ostream &dst, std::string indent) const 4 | { 5 | dst << indent << "Binary Equal? [ " << std::endl; 6 | dst << indent << "Left Op:" << std::endl; 7 | LeftOp()->PrettyPrint(dst, indent+" "); 8 | std::cout << indent << "Right Op: " << std::endl; 9 | RightOp()->PrettyPrint(dst, indent+" "); 10 | std::cout << indent << "]" <PrettyPrint(dst, indent+" "); 8 | std::cout << indent << "Right Op: " << std::endl; 9 | RightOp()->PrettyPrint(dst, indent+" "); 10 | std::cout << indent << "]" <PrettyPrint(dst, indent+" "); 8 | std::cout << indent << "Right Op: " << std::endl; 9 | RightOp()->PrettyPrint(dst, indent+" "); 10 | std::cout << indent << "]" <PrettyPrint(dst, indent+" "); 8 | std::cout << indent << "Right Op: " << std::endl; 9 | RightOp()->PrettyPrint(dst, indent+" "); 10 | std::cout << indent << "]" <PrettyPrint(dst, indent+" "); 8 | std::cout << indent << "Right Op: " << std::endl; 9 | RightOp()->PrettyPrint(dst, indent+" "); 10 | std::cout << indent << "]" <PrettyPrint(dst, indent+" "); 8 | std::cout << indent << "Right Op: " << std::endl; 9 | RightOp()->PrettyPrint(dst, indent+" "); 10 | std::cout << indent << "]" <PrettyPrint(dst, indent+" "); 8 | std::cout << indent << "Right Op: " << std::endl; 9 | RightOp()->PrettyPrint(dst, indent+" "); 10 | std::cout << indent << "]" <PrettyPrint(dst, indent+" "); 8 | std::cout << indent << "Right Op: " << std::endl; 9 | RightOp()->PrettyPrint(dst, indent+" "); 10 | std::cout << indent << "]" <PrettyPrint(dst, indent+" "); 8 | std::cout << indent << "Right Op: " << std::endl; 9 | RightOp()->PrettyPrint(dst, indent+" "); 10 | std::cout << indent << "]" <PrettyPrint(dst, indent+" "); 8 | std::cout << indent << "Right Op: " << std::endl; 9 | RightOp()->PrettyPrint(dst, indent+" "); 10 | std::cout << indent << "]" <PrettyPrint(dst, indent+" "); 8 | std::cout << indent << "Right Op: " << std::endl; 9 | RightOp()->PrettyPrint(dst, indent+" "); 10 | std::cout << indent << "]" <PrettyPrint(dst, indent+" "); 8 | std::cout << indent << "Right Op: " << std::endl; 9 | RightOp()->PrettyPrint(dst, indent+" "); 10 | std::cout << indent << "]" <PrettyPrint(dst, indent+" "); 8 | std::cout << indent << "Right Op: " << std::endl; 9 | RightOp()->PrettyPrint(dst, indent+" "); 10 | std::cout << indent << "]" <PrettyPrint(dst, indent+" "); 8 | std::cout << indent << "Right Op: " << std::endl; 9 | RightOp()->PrettyPrint(dst, indent+" "); 10 | std::cout << indent << "]" <generateMIPS(dst, context, destReg); 40 | }else{ 41 | LeftOp()->generateMIPS(dst, context, destReg); 42 | dst << "sll $" << destReg << ", $" << destReg << ", 2" << std::endl; 43 | } 44 | 45 | int temp = context.allocate(); 46 | if( isPtrVar(context, RightOp()) ){ 47 | ptrcount++; 48 | RightOp()->generateMIPS(dst, context, temp); 49 | }else{ 50 | RightOp()->generateMIPS(dst, context, temp); 51 | dst << "sll $" << temp << ", $" << temp << ", 2" << std::endl; 52 | } 53 | 54 | EZPrint(dst, "sub", destReg, destReg, temp); 55 | if( ptrcount > 1 ){ 56 | dst << "sra $" << destReg << ", $" << destReg << ", 2" << std::endl; 57 | } 58 | context.regFile.freeReg(temp); 59 | } 60 | 61 | case _float: 62 | { 63 | 64 | int regLeft = DoTypeLeft(dst, context, destReg, type); 65 | int regRight = DoTypeRight(dst, context, destReg, regLeft, type); 66 | 67 | dst << "sub.s $f" << destReg << ", $f" << regLeft << ", $f" << regRight << std::endl; 68 | 69 | context.floatRegs.freeReg(regLeft); 70 | context.floatRegs.freeReg(regRight); 71 | 72 | break; 73 | 74 | } 75 | 76 | case _double: 77 | { 78 | 79 | int regLeft = DoTypeLeft(dst, context, destReg, type); 80 | int regRight = DoTypeRight(dst, context, destReg, regLeft, type); 81 | 82 | dst << "sub.d $f" << destReg << ", $f" << regLeft << ", $f" << regRight << std::endl; 83 | 84 | context.floatRegs.freeReg(regLeft); 85 | context.floatRegs.freeReg(regRight); 86 | 87 | break; 88 | 89 | } 90 | } 91 | } 92 | 93 | -------------------------------------------------------------------------------- /src/include_impl/ast/operators/binaryOps/ast_binaryXOR.cpp: -------------------------------------------------------------------------------- 1 | #include "ast/operators/binaryOps/ast_binaryXOR.hpp" 2 | 3 | void BinaryXOR::PrettyPrint(std::ostream &dst, std::string indent) const 4 | { 5 | dst << indent << "Binary XOR [ " << std::endl; 6 | dst << indent << "Left Op:" << std::endl; 7 | LeftOp()->PrettyPrint(dst, indent+" "); 8 | std::cout << indent << "Right Op: " << std::endl; 9 | RightOp()->PrettyPrint(dst, indent+" "); 10 | std::cout << indent << "]" < 3 | 4 | void UnaryAdr::PrettyPrint(std::ostream &dst, std::string indent) const 5 | { 6 | dst << indent << "Unary Adr [ " << std::endl; 7 | dst << indent << "Op:" << std::endl; 8 | getOp()->PrettyPrint(dst, indent+" "); 9 | std::cout << indent << "]" <getId(); 17 | variable var; 18 | 19 | auto it = context.stack.back().varBindings.find(id); 20 | if( it == context.stack.back().varBindings.end() ){ 21 | std::cerr << "Uninitialised Variable?" << std::endl; 22 | }else{ 23 | var = it->second; 24 | } 25 | 26 | if(getOp()->getNode(1) != NULL){ // array 27 | getOp()->getNode(1)->generateMIPS(dst, context, destReg); 28 | dst << "sll $" << destReg << ", $" << destReg << ", " << (int)log2(var.size) << std::endl; 29 | dst << "addi $" << destReg << ", $" << destReg << ", " << var.offset << std::endl; 30 | dst << "add $" << destReg << ", $" << destReg << ", $30" << std::endl; 31 | }else{ 32 | 33 | //put its address in destReg 34 | dst << "addi $" << destReg << ", $30, " << var.offset << std::endl; 35 | } 36 | 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/include_impl/ast/operators/unaryOps/ast_unaryBWNOT.cpp: -------------------------------------------------------------------------------- 1 | #include "ast/operators/unaryOps/ast_unaryBWNOT.hpp" 2 | 3 | void UnaryBWNOT::PrettyPrint(std::ostream &dst, std::string indent) const 4 | { 5 | dst << indent << "Unary BWNOT [ " << std::endl; 6 | dst << indent << "Op:" << std::endl; 7 | getOp()->PrettyPrint(dst, indent+" "); 8 | std::cout << indent << "]" <generateMIPS(dst, context, destReg); 16 | 17 | ifFunction(dst, context, destReg); 18 | 19 | int reg = context.allocate(); 20 | dst << "li $" << reg << ", -1" << std::endl; 21 | 22 | dst << "xor $" << destReg << ", $" << destReg << ", $" << reg << std::endl; 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/include_impl/ast/operators/unaryOps/ast_unaryDec.cpp: -------------------------------------------------------------------------------- 1 | #include "ast/operators/unaryOps/ast_unaryDec.hpp" 2 | 3 | void UnaryDec::PrettyPrint(std::ostream &dst, std::string indent) const 4 | { 5 | dst << indent << "Unary Dec [ " << std::endl; 6 | dst << indent << "Op:" << std::endl; 7 | getOp()->PrettyPrint(dst, indent+" "); 8 | std::cout << indent << "]" <getId(); 15 | variable op; 16 | 17 | auto it = context.stack.back().varBindings.find(id); 18 | if( it == context.stack.back().varBindings.end() ){ 19 | std::cerr << "Dec a non var?" << std::endl; 20 | }else{ 21 | op = it->second; 22 | } 23 | 24 | if(op.reg == -1){ 25 | 26 | dst << "lw $" << destReg << ", " << op.offset << "($30)" << std::endl; 27 | dst << "addiu $" << destReg << ", $" << destReg << ", -1" << std::endl; 28 | dst << "sw $" << destReg << ", " << op.offset << "($30)" << std::endl; 29 | 30 | 31 | }else{ 32 | 33 | dst << "addiu $" << op.reg << ", $" << op.reg << ", -1" << std::endl; 34 | dst << "sw $" << op.reg << ", " << op.offset << "($30)" << std::endl; 35 | dst << "move $" << destReg << ", $" << op.reg << std::endl; 36 | 37 | 38 | } 39 | 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/include_impl/ast/operators/unaryOps/ast_unaryInc.cpp: -------------------------------------------------------------------------------- 1 | #include "ast/operators/unaryOps/ast_unaryInc.hpp" 2 | 3 | void UnaryInc::PrettyPrint(std::ostream &dst, std::string indent) const 4 | { 5 | dst << indent << "Unary Inc [ " << std::endl; 6 | dst << indent << "Op:" << std::endl; 7 | getOp()->PrettyPrint(dst, indent+" "); 8 | std::cout << indent << "]" <getId(); 14 | variable op; 15 | 16 | auto it = context.stack.back().varBindings.find(id); 17 | if( it == context.stack.back().varBindings.end() ){ 18 | std::cerr << "Inc a non var?" << std::endl; 19 | }else{ 20 | op = it->second; 21 | } 22 | 23 | if(op.reg == -1){ 24 | 25 | dst << "lw $" << destReg << ", " << op.offset << "($30)" << std::endl; 26 | dst << "addiu $" << destReg << ", $" << destReg << ", 1" << std::endl; 27 | dst << "sw $" << destReg << ", " << op.offset << "($30)" << std::endl; 28 | 29 | 30 | }else{ 31 | 32 | dst << "addiu $" << op.reg << ", $" << op.reg << ", +1" << std::endl; 33 | dst << "sw $" << op.reg << ", " << op.offset << "($30)" << std::endl; 34 | dst << "move $" << destReg << ", $" << op.reg << std::endl; 35 | 36 | 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/include_impl/ast/operators/unaryOps/ast_unaryNOT.cpp: -------------------------------------------------------------------------------- 1 | #include "ast/operators/unaryOps/ast_unaryNOT.hpp" 2 | 3 | void UnaryNOT::PrettyPrint(std::ostream &dst, std::string indent) const 4 | { 5 | dst << indent << "Unary NOT [ " << std::endl; 6 | dst << indent << "Op:" << std::endl; 7 | getOp()->PrettyPrint(dst, indent+" "); 8 | std::cout << indent << "]" <generateMIPS(dst, context, destReg); 16 | 17 | ifFunction(dst, context, destReg); 18 | 19 | dst << "slti $" << destReg << ", $" << destReg << ", 1" << std::endl; 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/include_impl/ast/operators/unaryOps/ast_unaryPostDec.cpp: -------------------------------------------------------------------------------- 1 | #include "ast/operators/unaryOps/ast_unaryPostDec.hpp" 2 | 3 | void UnaryPostDec::PrettyPrint(std::ostream &dst, std::string indent) const 4 | { 5 | dst << indent << "Unary Post Dec [ " << std::endl; 6 | dst << indent << "Op:" << std::endl; 7 | getOp()->PrettyPrint(dst, indent+" "); 8 | std::cout << indent << "]" <getId(); 14 | variable op; 15 | 16 | auto it = context.stack.back().varBindings.find(id); 17 | if( it == context.stack.back().varBindings.end() ){ 18 | std::cerr << "Dec a non var?" << std::endl; 19 | }else{ 20 | op = it->second; 21 | } 22 | 23 | if( op.type == _ptr ){ 24 | 25 | if(op.reg == -1){ 26 | 27 | dst << "lw $" << destReg << ", " << op.offset << "($30)" << std::endl; 28 | dst << "addiu $" << destReg << ", $" << destReg << ", -4" << std::endl; 29 | dst << "sw $" << destReg << ", " << op.offset << "($30)" << std::endl; 30 | dst << "addiu $" << destReg << ", $" << destReg << ", 4" << std::endl; 31 | 32 | }else{ 33 | 34 | dst << "addiu $" << op.reg << ", $" << op.reg << ", -4" << std::endl; 35 | dst << "sw $" << op.reg << ", " << op.offset << "($30)" << std::endl; 36 | dst << "addiu $" << destReg << ", $" << op.reg << ", 4" << std::endl; 37 | } 38 | 39 | }else{ 40 | 41 | if(op.reg == -1){ 42 | 43 | dst << "lw $" << destReg << ", " << op.offset << "($30)" << std::endl; 44 | dst << "addiu $" << destReg << ", $" << destReg << ", -1" << std::endl; 45 | dst << "sw $" << destReg << ", " << op.offset << "($30)" << std::endl; 46 | dst << "addiu $" << destReg << ", $" << destReg << ", 1" << std::endl; 47 | 48 | }else{ 49 | 50 | dst << "addiu $" << op.reg << ", $" << op.reg << ", -1" << std::endl; 51 | dst << "sw $" << op.reg << ", " << op.offset << "($30)" << std::endl; 52 | dst << "addiu $" << destReg << ", $" << op.reg << ", 1" << std::endl; 53 | 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/include_impl/ast/operators/unaryOps/ast_unaryPostInc.cpp: -------------------------------------------------------------------------------- 1 | #include "ast/operators/unaryOps/ast_unaryPostInc.hpp" 2 | 3 | void UnaryPostInc::PrettyPrint(std::ostream &dst, std::string indent) const 4 | { 5 | dst << indent << "Unary Post Inc [ " << std::endl; 6 | dst << indent << "Op:" << std::endl; 7 | getOp()->PrettyPrint(dst, indent+" "); 8 | std::cout << indent << "]" <getId(); 14 | variable op; 15 | 16 | auto it = context.stack.back().varBindings.find(id); 17 | if( it == context.stack.back().varBindings.end() ){ 18 | std::cerr << "Inc a non var?" << std::endl; 19 | }else{ 20 | op = it->second; 21 | } 22 | 23 | if( op.type == _ptr ){ 24 | 25 | if(op.reg == -1){ 26 | 27 | dst << "lw $" << destReg << ", " << op.offset << "($30)" << std::endl; 28 | dst << "addiu $" << destReg << ", $" << destReg << ", 4" << std::endl; 29 | dst << "sw $" << destReg << ", " << op.offset << "($30)" << std::endl; 30 | dst << "addiu $" << destReg << ", $" << destReg << ", -4" << std::endl; 31 | 32 | }else{ 33 | 34 | dst << "addiu $" << op.reg << ", $" << op.reg << ", 4" << std::endl; 35 | dst << "sw $" << op.reg << ", " << op.offset << "($30)" << std::endl; 36 | dst << "addiu $" << destReg << ", $" << op.reg << ", -4" << std::endl; 37 | } 38 | 39 | }else{ 40 | 41 | if(op.reg == -1){ 42 | 43 | dst << "lw $" << destReg << ", " << op.offset << "($30)" << std::endl; 44 | dst << "addiu $" << destReg << ", $" << destReg << ", 1" << std::endl; 45 | dst << "sw $" << destReg << ", " << op.offset << "($30)" << std::endl; 46 | dst << "addiu $" << destReg << ", $" << destReg << ", -1" << std::endl; 47 | 48 | }else{ 49 | 50 | dst << "addiu $" << op.reg << ", $" << op.reg << ", 1" << std::endl; 51 | dst << "sw $" << op.reg << ", " << op.offset << "($30)" << std::endl; 52 | dst << "addiu $" << destReg << ", $" << op.reg << ", -1" << std::endl; 53 | 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/include_impl/ast/operators/unaryOps/ast_unaryPtr.cpp: -------------------------------------------------------------------------------- 1 | #include "ast/operators/unaryOps/ast_unaryPtr.hpp" 2 | 3 | void UnaryPtr::PrettyPrint(std::ostream &dst, std::string indent) const 4 | { 5 | dst << indent << "Unary Ptr [ " << std::endl; 6 | dst << indent << "Op:" << std::endl; 7 | getOp()->PrettyPrint(dst, indent+" "); 8 | std::cout << indent << "]" <getId(); 15 | variable var; 16 | 17 | auto it = context.stack.back().varBindings.find(id); 18 | if( it == context.stack.back().varBindings.end() ){ 19 | std::cerr << "Uninitialised Variable?" << std::endl; 20 | }else{ 21 | var = it->second; 22 | } 23 | 24 | getOp()->generateMIPS(dst, context, destReg); // puts ptr value (its pointed address) into destReg like any other variable 25 | dst << "lw $" << destReg << ", 0($" << destReg << ")" << std::endl; // loads whatever its pointing at. 26 | 27 | } 28 | 29 | bool UnaryPtr::isPtr() const 30 | { 31 | return true; 32 | } 33 | 34 | 35 | void UnaryPtr::generateTypeMIPS(std::ostream &dst, Context &context, int destReg, enum Specifier type) const // only for dereferencing. 36 | { 37 | 38 | switch(type) 39 | { 40 | 41 | case _float: 42 | { 43 | //find variable you are *ing 44 | std::string id = getOp()->getId(); 45 | variable var; 46 | 47 | auto it = context.stack.back().varBindings.find(id); 48 | if( it == context.stack.back().varBindings.end() ){ 49 | std::cerr << "Uninitialised Variable?" << std::endl; 50 | }else{ 51 | var = it->second; 52 | } 53 | 54 | int reg = context.allocate(); 55 | getOp()->generateMIPS(dst, context, reg); // puts ptr value (its pointed address) into destReg like any other variable 56 | dst << "lwc1 $f" << destReg << ", 0($" << reg << ")" << std::endl; // loads whatever its pointing at. 57 | context.regFile.freeReg(reg); 58 | 59 | break; 60 | } 61 | 62 | case _double: 63 | { 64 | //find variable you are *ing 65 | std::string id = getOp()->getId(); 66 | variable var; 67 | 68 | auto it = context.stack.back().varBindings.find(id); 69 | if( it == context.stack.back().varBindings.end() ){ 70 | std::cerr << "Uninitialised Variable?" << std::endl; 71 | }else{ 72 | var = it->second; 73 | } 74 | 75 | int reg = context.allocate(); 76 | getOp()->generateMIPS(dst, context, reg); // puts ptr value (its pointed address) into destReg like any other variable 77 | dst << "ldc1 $f" << destReg << ", 0($" << reg << ")" << std::endl; // loads whatever its pointing at. 78 | context.regFile.freeReg(reg); 79 | 80 | break; 81 | } 82 | 83 | 84 | } 85 | 86 | } -------------------------------------------------------------------------------- /src/include_impl/ast/operators/unaryOps/ast_unarySub.cpp: -------------------------------------------------------------------------------- 1 | #include "ast/operators/unaryOps/ast_unarySub.hpp" 2 | 3 | void UnarySub::PrettyPrint(std::ostream &dst, std::string indent) const 4 | { 5 | dst << indent << "Unary Sub [ " << std::endl; 6 | dst << indent << "Op:" << std::endl; 7 | getOp()->PrettyPrint(dst, indent+" "); 8 | std::cout << indent << "]" <generateMIPS(dst, context, destReg); 15 | 16 | ifFunction(dst, context, destReg); 17 | 18 | dst << "sub $" << destReg << ", $0, $" << destReg << std::endl; 19 | 20 | } 21 | 22 | void UnarySub::generateTypeMIPS(std::ostream &dst, Context &context, int destReg, enum Specifier type) const 23 | { 24 | switch(type) 25 | { 26 | case _ptr: 27 | { 28 | std::cerr << "multiplying pointers are we?" << std::endl; 29 | } 30 | case _float: 31 | { 32 | 33 | getOp()->generateTypeMIPS(dst, context, destReg, type); 34 | if( getOp()-isFunction() ){ 35 | dst << "mov.s $f" << destReg << ", $f0" << std::endl; 36 | } 37 | 38 | dst << "neg.s $f" << destReg << ", $f" << destReg << std::endl; 39 | 40 | break; 41 | } 42 | 43 | case _double: 44 | { 45 | 46 | getOp()->generateTypeMIPS(dst, context, destReg, type); 47 | if( getOp()-isFunction() ){ 48 | dst << "mov.d $f" << destReg << ", $f0" << std::endl; 49 | } 50 | 51 | dst << "neg.d $f" << destReg << ", $f" << destReg << std::endl; 52 | 53 | 54 | break; 55 | 56 | } 57 | 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/include_impl/ast/types/ast_enumSpecifier.cpp: -------------------------------------------------------------------------------- 1 | #include "ast/types/ast_enumSpecifier.hpp" 2 | 3 | // Constructor 4 | EnumSpecifier::EnumSpecifier(std::string _id, std::vector enums) 5 | { 6 | id = _id; 7 | branches = enums; 8 | } 9 | 10 | EnumSpecifier::EnumSpecifier(std::string _id) 11 | : EnumSpecifier(_id, std::vector{}) 12 | {} 13 | 14 | EnumSpecifier::~EnumSpecifier() 15 | { 16 | for(unsigned i = 0; i < branches.size(); i++){ 17 | delete branches[i]; 18 | } 19 | } 20 | 21 | // Visualising 22 | void EnumSpecifier::PrettyPrint(std::ostream &dst, std::string indent) const 23 | { 24 | dst << indent << "EnumerationSpecifier [" << std::endl; 25 | dst << indent << "id: " << id << std::endl; 26 | for(unsigned i = 0; i < branches.size(); i++){ 27 | branches[i]->PrettyPrint(dst, indent+" "); 28 | } 29 | dst << indent << "] endEnumeration" << std::endl; 30 | } 31 | 32 | void EnumSpecifier::generateMIPS(std::ostream &dst, Context &context, int destReg) const 33 | { 34 | std::string enumId = getId(); 35 | int val = -1; 36 | for(unsigned i = 0; i < branches.size(); i++){ 37 | std::string id = branches[i]->getId(); 38 | if(branches[i]->getNode(0) != NULL){ 39 | val = branches[i]->getValue(); 40 | } 41 | else{ 42 | val++; 43 | } 44 | context.enums[id] = {enumId, val}; 45 | } 46 | } 47 | 48 | std::string EnumSpecifier::getId() const 49 | { 50 | return id; 51 | } 52 | 53 | int EnumSpecifier::getSize() const 54 | { 55 | return 4; 56 | } 57 | 58 | bool EnumSpecifier::isEnum() const 59 | { 60 | return true; 61 | } 62 | 63 | enum Specifier EnumSpecifier::getType() const 64 | { 65 | return Specifier::_int; // Enums are int type 66 | } 67 | -------------------------------------------------------------------------------- /src/include_impl/ast/types/ast_enumerator.cpp: -------------------------------------------------------------------------------- 1 | #include "ast/types/ast_enumerator.hpp" 2 | 3 | Enumerator::Enumerator(std::string _id, NodePtr expression) 4 | { 5 | id = _id; 6 | branches.push_back(expression); 7 | } 8 | 9 | Enumerator::~Enumerator() 10 | { 11 | if(branches[0] != NULL){ 12 | delete branches[0]; 13 | } 14 | } 15 | 16 | void Enumerator::PrettyPrint(std::ostream &dst, std::string indent) const 17 | { 18 | dst << indent << id << ": " << std::endl; 19 | if(branches[0] != NULL){ 20 | branches[0]->PrettyPrint(dst, indent+" "); 21 | } 22 | else{ 23 | dst << indent+" "+"Default" << std::endl; 24 | } 25 | } 26 | 27 | NodePtr Enumerator::getNode(unsigned index) const 28 | { 29 | if(index == 0){ 30 | return branches[0]; 31 | } 32 | std::cerr << "Tried to getNode out of enum range" << std::endl; 33 | return NULL; 34 | } 35 | 36 | std::string Enumerator::getId() const 37 | { 38 | return id; 39 | } 40 | 41 | bool Enumerator::isEnum() const 42 | { 43 | return true; 44 | } 45 | 46 | int Enumerator::getValue() const 47 | { 48 | if(branches[0] == NULL){ 49 | std::cerr << "Tried to getValue of uninit enum" << std::endl; 50 | exit(1); 51 | } 52 | return branches[0]->getValue(); 53 | } 54 | -------------------------------------------------------------------------------- /src/include_impl/ast/types/ast_primitive.cpp: -------------------------------------------------------------------------------- 1 | #include "ast/types/ast_primitive.hpp" 2 | 3 | // Constructor 4 | PrimitiveType::PrimitiveType(Specifier _type) 5 | : type(_type) 6 | {} 7 | 8 | // Destructor 9 | PrimitiveType::~PrimitiveType() 10 | {}; 11 | 12 | // Visualising 13 | void PrimitiveType::PrettyPrint(std::ostream &dst, std::string indent) const 14 | { 15 | switch(type){ 16 | case _int: 17 | dst << "int"; 18 | break; 19 | case _void: 20 | dst << "void"; 21 | break; 22 | case _unsigned: 23 | dst << "unsigned"; 24 | break; 25 | case _char: 26 | dst << "char"; 27 | break; 28 | case _float: 29 | dst << "float"; 30 | break; 31 | case _double: 32 | dst << "double"; 33 | break; 34 | default: 35 | dst << "unknown type "; 36 | } 37 | dst << std::endl; 38 | } 39 | 40 | // Codegen helper 41 | int PrimitiveType::getSize() const 42 | { 43 | switch(type){ 44 | case _int: 45 | return 4; 46 | case _void: 47 | return 4; // You should never really try to getSize of void, just loads integer 0 48 | case _unsigned: 49 | return 4; 50 | case _char: 51 | return 1; 52 | case _float: 53 | return 4; 54 | case _double: 55 | return 8; 56 | default: 57 | std::cerr << "Tried to getsize of something with no primitive type" << std::endl; 58 | return 0; 59 | } 60 | } 61 | 62 | enum Specifier PrimitiveType::getType() const 63 | { 64 | switch(type){ 65 | case _int: 66 | return type; 67 | case _void: 68 | return type; 69 | case _unsigned: 70 | return type; 71 | case _char: 72 | return type; 73 | case _float: 74 | return type; 75 | case _double: 76 | return type; 77 | default: 78 | std::cerr << "Tried to getType of something with no primitve type" << std::endl; 79 | exit(1); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/include_impl/ast/types/ast_typedef.cpp: -------------------------------------------------------------------------------- 1 | #include "ast/types/ast_typedef.hpp" 2 | 3 | // This was never really implemented properly, we'd need to add an extern mapping in the lexer / parser to update types as we go 4 | 5 | // Constructor 6 | TypeDef::TypeDef(NodePtr type) 7 | { 8 | branches.push_back(type); 9 | } 10 | 11 | // Destructor 12 | TypeDef::~TypeDef() 13 | { 14 | delete branches[0]; 15 | } 16 | 17 | // Visualising 18 | void TypeDef::PrettyPrint(std::ostream &dst, std::string indent) const 19 | { 20 | dst << "Typedef: "; 21 | branches[0]->PrettyPrint(dst, indent); 22 | } 23 | -------------------------------------------------------------------------------- /src/wrapper.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | echo "Compiling to MIPS..." 3 | cat $2 | ./bin/compiler 2> /dev/null 1> $4 4 | -------------------------------------------------------------------------------- /utility/add_ast.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Creates the .hpp and .cpp files for AST construct following naming conventions and adds them to git 4 | # NOTE: Run this in base directory 5 | 6 | set -euo pipefail 7 | 8 | INCLUDE_DIR="include/ast/" 9 | SRC_DIR="src/include_impl/ast/" 10 | 11 | if [[ $# -eq 0 ]] ; then 12 | >&2 echo "Usage: utility/add_ast.sh " 13 | >&2 echo " is the name of the new class to be added to the AST (without prefix), i.e. ifThenElse for ast_ifThenElse" 14 | >&2 echo " (optional) is any extra filepath from the ast directory (i.e. \"operators/\" would create file in .../ast/operators/ )" 15 | exit 1 16 | fi 17 | 18 | NAME="$1" 19 | DIR="${2:-null}" 20 | NAMESHORT="3" 21 | 22 | if [[ "${DIR}" = "null" ]] ; then 23 | touch "${INCLUDE_DIR}ast_${NAME}.hpp" 24 | touch "${SRC_DIR}ast_${NAME}.cpp" 25 | git add "${INCLUDE_DIR}ast_${NAME}.hpp" "${SRC_DIR}ast_${NAME}.cpp" 26 | else 27 | touch "${INCLUDE_DIR}${DIR}ast_${NAME}.hpp" 28 | touch "${SRC_DIR}${DIR}ast_${NAME}.cpp" 29 | git add "${INCLUDE_DIR}${DIR}ast_${NAME}.hpp" "${SRC_DIR}${DIR}ast_${NAME}.cpp" 30 | fi 31 | 32 | >&2 echo "Created files" 33 | -------------------------------------------------------------------------------- /utility/add_test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -euo pipefail 4 | 5 | TEST_DIR="compiler_tests/" 6 | 7 | if [[ $# -eq 0 ]] ; then 8 | >&2 echo "Usage: utlility/add_test.sh " 9 | >&2 echo " is the filepath from ${TEST_DIR} to the new test name, i.e. control_flow/for_empty_it" 10 | exit 1 11 | fi 12 | 13 | NAME="$1" 14 | 15 | touch "${TEST_DIR}${NAME}.c" 16 | touch "${TEST_DIR}${NAME}_driver.c" 17 | 18 | git add "${TEST_DIR}${NAME}.c" "${TEST_DIR}${NAME}_driver.c" 19 | 20 | >&2 echo "Created files" 21 | -------------------------------------------------------------------------------- /utility/old/add_and_make_file_ast.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Creates the .hpp and .cpp files for AST construct following naming conventions and adds them to git 4 | # NOTE: Run this in base directory 5 | 6 | set -euo pipefail 7 | 8 | INCLUDE_DIR="include/ast/" 9 | SRC_DIR="src/include_impl/ast/" 10 | 11 | if [[ $# -eq 0 ]] ; then 12 | >&2 echo "Usage: ./add_ast.sh " 13 | >&2 echo " is the name of the new class to be added to the AST (without prefix), i.e. ifThenElse for ast_ifThenElse" 14 | >&2 echo " (optional) is any extra filepath from the ast directory (i.e. \"operators/\" would create file in .../ast/operators/ )" 15 | exit 1 16 | fi 17 | 18 | NAME="$1" 19 | DIR="${2:-null}" 20 | SHORTNAME="$3" 21 | 22 | if [[ "${DIR}" = "null" ]] ; then 23 | touch "${INCLUDE_DIR}ast_${NAME}.hpp" 24 | touch "${SRC_DIR}ast_${NAME}.cpp" 25 | git add "${INCLUDE_DIR}ast_${NAME}.hpp" "${SRC_DIR}ast_${NAME}.cpp" 26 | else 27 | touch "${INCLUDE_DIR}${DIR}ast_${NAME}.hpp" 28 | touch "${SRC_DIR}${DIR}ast_${NAME}.cpp" 29 | git add "${INCLUDE_DIR}${DIR}ast_${NAME}.hpp" "${SRC_DIR}${DIR}ast_${NAME}.cpp" 30 | fi 31 | 32 | echo "#include \"ast/operators/binaryOps/ast_binary${SHORTNAME}.hpp\" 33 | 34 | void Binary$SHORTNAME::PrettyPrint(std::ostream &dst, std::string indent) const 35 | { 36 | dst << indent << \"Binary ${SHORTNAME} [ \" << std::endl; 37 | dst << indent << \"Left Op:\" << std::endl; 38 | LeftOp()->PrettyPrint(dst, indent+ \" \"); 39 | std::cout << indent << \"Right Op: \" << std::endl; 40 | RightOp()->PrettyPrint(dst, indent+\" \"); 41 | std::cout << indent << \"]\" < ${SRC_DIR}${DIR}ast_${NAME}.cpp 44 | 45 | echo "#ifndef ast_binary${SHORTNAME}_hpp 46 | #define ast_binary${SHORTNAME}_hpp 47 | 48 | #include \"ast/operators/ast_binaryOperation.hpp\" 49 | 50 | class Binary${SHORTNAME} 51 | : public BinaryOperation 52 | { 53 | public: 54 | 55 | using BinaryOperation::BinaryOperation; 56 | 57 | virtual void PrettyPrint(std::ostream &dst, std::string indent) const override; 58 | 59 | 60 | }; 61 | 62 | #endif 63 | " > ${INCLUDE_DIR}${DIR}ast_${NAME}.hpp 64 | 65 | echo "#include \"ast/operators/binaryOps/ast_binary${SHORTNAME}.hpp\"" >> include/ast.hpp 66 | 67 | 68 | >&2 echo "Created files" 69 | -------------------------------------------------------------------------------- /utility/old/insert_genMIPS.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Creates the .hpp and .cpp files for AST construct following naming conventions and adds them to git 4 | # NOTE: Run this in base directory 5 | 6 | set -euo pipefail 7 | 8 | INCLUDE_DIR="include/ast/" 9 | SRC_DIR="src/include_impl/ast/" 10 | 11 | 12 | for i in src/include_impl/ast/operators/binaryOps/*.cpp; do 13 | echo "void BinaryAdd::generateMIPS(std::ostream &dst, Context context, int destReg) const 14 | { 15 | int regLeft, regRight; 16 | if( ((regLeft = context.regFile.allocate()) == -1) | (regRight = context.regFile.allocate();) == -1 ){ 17 | std::cerr << \"OOPSIES NO REGS ARE FREE. OVERWRITING\" << std::endl; 18 | } 19 | 20 | getLeft->generateMIPS(&dst, context, regLeft); 21 | getRight->generateMIPS(&dst, context, regRight); 22 | 23 | EZPrint(&dst, \"add\", destReg, regLeft, regRight); 24 | 25 | context.regFile.freeReg(regLeft); 26 | context.regFile.freeReg(regRight); 27 | }" >> ${i} 28 | done 29 | 30 | 31 | 32 | >&2 echo "Inserted it" 33 | -------------------------------------------------------------------------------- /utility/old/readme.md: -------------------------------------------------------------------------------- 1 | README 2 | ------ 3 | This sub-directory just contains old scripts that were typically used for refactoring / automation are no longer needed, but are kept for the sake of reference. 4 | -------------------------------------------------------------------------------- /utility/old/refactor.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -euo pipefail 4 | 5 | #cp -r include/ src/include_impl/ 6 | 7 | find src/include_impl/ -type d | while read d ; do 8 | echo "${d}" 9 | for file in ${d}/*.hpp ; do 10 | mv "$file" "${file%.hpp}.cpp" 11 | done 12 | done 13 | -------------------------------------------------------------------------------- /utility/old/rename_tests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -euo pipefail 4 | 5 | for FILE in $(find compiler_tests/float -type f -name "*.c") ; do 6 | F_NAME=$(basename "${FILE}") 7 | F_PATH=$(dirname "${FILE}") 8 | echo "${F_PATH}/float_${F_NAME}" 9 | # mv "${FILE}" "${F_PATH}/float_${F_NAME}" 10 | done 11 | -------------------------------------------------------------------------------- /utility/run_test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -euo pipefail 4 | 5 | # Staging output directory 6 | if [[ ! -d "out" ]] ; then 7 | mkdir out 8 | fi 9 | 10 | if [[ $# -eq 0 ]] ; then 11 | >&2 echo "Usage: utility/run_test.sh -V (optional)" 12 | >&2 echo " is the full path to a test" 13 | >&2 echo "-V enables visualalisation" 14 | exit 1 15 | fi 16 | 17 | TEST=${1} 18 | TEST_NAME=${TEST%.c} 19 | TEST_NAME=${TEST_NAME##*/} 20 | TEST_DRIVER=$(echo "${TEST}" | cut -f 1 -d '.') 21 | TEST_DRIVER="${TEST_DRIVER}_driver.c" 22 | OUT=$(echo "out/${TEST_NAME}" | cut -f 1 -d '.') 23 | 24 | # Formatting 25 | TERMINAL_WIDTH=$(tput cols) 26 | TITLE="Running test for ${TEST_NAME}" 27 | LEN=`expr length "$TITLE"` 28 | DIFF=$(($TERMINAL_WIDTH - $LEN)) 29 | BUFFER=$(($DIFF / 2)) 30 | UNEVEN=$(($DIFF % 2)) 31 | if [[ $UNEVEN -eq 1 ]] ; then 32 | EXTRA="=" 33 | else 34 | EXTRA="" 35 | fi 36 | SEP=$(echo $(printf '=%.0s' $(eval "echo {1.."$(($BUFFER))"}"))) 37 | 38 | echo "${SEP}${TITLE}${SEP}${EXTRA}" 39 | echo "Compiling ${TEST_NAME}" 40 | if [[ $# -eq 2 ]] ; then 41 | bin/c_compiler -S "${TEST}" -o "${OUT}.s" -V 42 | else 43 | bin/c_compiler -S "${TEST}" -o "${OUT}.s" 44 | fi 45 | 46 | echo $(printf '=%.0s' $(eval "echo {1.."$(($TERMINAL_WIDTH))"}")) 47 | echo "Assembling output" 48 | mips-linux-gnu-gcc -mfp32 -static -o "${OUT}.o" -c "${OUT}.s" 49 | 50 | echo "Linking with driver program" 51 | mips-linux-gnu-gcc -mfp32 -static -o "${OUT}" "${OUT}.o" "${TEST_DRIVER}" 52 | 53 | echo "Simulating" 54 | set +e 55 | qemu-mips "${OUT}" 56 | RESULT=${?} 57 | set -e 58 | 59 | if [[ ${RESULT} -eq 0 ]] ; then 60 | >&2 echo "Testcase ${1} passed successfully" 61 | else 62 | >&2 echo "Testcase ${1} failed" 63 | exit 1 64 | fi 65 | -------------------------------------------------------------------------------- /utility/test_dir.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -euo pipefail 4 | 5 | # Usage: utility/test_dir.sh (optional) 6 | # is the name of a directory in the compiler_tests directory(i.e. local_var) 7 | # if unspecified will test all files in compiler_tests 8 | 9 | if [[ $# -eq 0 ]] ; then 10 | TESTS=$(find compiler_tests -type f -not -name "*_driver.c") 11 | else 12 | TESTS=$(find compiler_tests/${1} -type f -not -name "*_driver.c") 13 | fi 14 | 15 | # Formatting 16 | TERMINAL_WIDTH=$(tput cols) 17 | BUFFER=$(($TERMINAL_WIDTH / 2 - 9)) 18 | UNEVEN=$(($TERMINAL_WIDTH % 2)) 19 | if [[ $UNEVEN -eq 1 ]] ; then 20 | EXTRA="=" 21 | else 22 | EXTRA="" 23 | fi 24 | 25 | SEP=$(echo $(printf '=%.0s' $(eval "echo {1.."$(($BUFFER))"}"))) 26 | 27 | echo "${SEP}Compiling compiler${SEP}${EXTRA}" 28 | make 29 | 30 | PASSED=0 31 | TOTAL=0 32 | TEST_FAIL="" 33 | 34 | for TEST in ${TESTS}; do 35 | set +e 36 | utility/run_test.sh ${TEST} 37 | RESULT=${?} 38 | set -e 39 | if [[ ${RESULT} -eq 0 ]] ; then 40 | PASSED=$((${PASSED}+1)) 41 | else 42 | TEST_FAIL="${TEST_FAIL} ${TEST}" 43 | fi 44 | TOTAL=$((${TOTAL}+1)) 45 | done 46 | 47 | echo $(printf '=%.0s' $(eval "echo {1.."$(($TERMINAL_WIDTH))"}")) 48 | echo "Passed ${PASSED} out of ${TOTAL} tests" 49 | echo "Failed: ${TEST_FAIL}" 50 | -------------------------------------------------------------------------------- /utility/test_single.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -euo pipefail 4 | 5 | if [[ $# -eq 0 ]] ; then 6 | >&2 echo "Usage: utility/single_test.sh " 7 | >&2 echo " is the name of a test in the compiler_tests directory without filepath (i.e. return_constant.c)" 8 | exit 1 9 | fi 10 | 11 | # Recursively finds test file 12 | shopt -s globstar 13 | TEST=$(echo compiler_tests/**/"${1}") 14 | 15 | # Formatting 16 | TERMINAL_WIDTH=$(tput cols) 17 | BUFFER=$(($TERMINAL_WIDTH / 2 - 9)) 18 | UNEVEN=$(($TERMINAL_WIDTH % 2)) 19 | if [[ $UNEVEN -eq 1 ]] ; then 20 | EXTRA="=" 21 | else 22 | EXTRA="" 23 | fi 24 | 25 | SEP=$(echo $(printf '=%.0s' $(eval "echo {1.."$(($BUFFER))"}"))) 26 | 27 | echo "${SEP}Compiling compiler${SEP}${EXTRA}" 28 | make 29 | 30 | # Run single test 31 | utility/run_test.sh ${TEST} -V 32 | -------------------------------------------------------------------------------- /utility/test_test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -euo pipefail 4 | 5 | # Staging output directory 6 | if [[ ! -d "out" ]] ; then 7 | mkdir out 8 | fi 9 | 10 | if [[ $# -eq 0 ]] ; then 11 | >&2 echo "Usage: utility/test_test.sh " 12 | >&2 echo " is the full path to a test" 13 | exit 1 14 | fi 15 | 16 | TEST=${1} 17 | TEST_NAME=${TEST%.c} 18 | TEST_NAME=${TEST_NAME##*/} 19 | TEST_DRIVER=$(echo "${TEST}" | cut -f 1 -d '.') 20 | TEST_DRIVER="${TEST_DRIVER}_driver.c" 21 | OUT=$(echo "out/${TEST_NAME}" | cut -f 1 -d '.') 22 | 23 | echo "==========Running test for ${TEST_NAME}==========" 24 | echo "Compiling ${TEST_NAME}" 25 | mips-linux-gnu-gcc -mfp32 -static -o "${OUT}.s" -S "${TEST}" 26 | 27 | echo "===============================================" 28 | echo "Assembling output" 29 | mips-linux-gnu-gcc -mfp32 -static -o "${OUT}.o" -c "${OUT}.s" 30 | 31 | echo "Linking with driver program" 32 | mips-linux-gnu-gcc -mfp32 -static -o "${OUT}" "${OUT}.o" "${TEST_DRIVER}" 33 | 34 | echo "Simulating" 35 | set +e 36 | qemu-mips "${OUT}" 37 | RESULT=${?} 38 | set -e 39 | 40 | if [[ ${RESULT} -eq 0 ]] ; then 41 | >&2 echo "Testcase ${1} is correct" 42 | else 43 | >&2 echo "Testcase ${1} is incorrect" 44 | exit 1 45 | fi 46 | --------------------------------------------------------------------------------