├── .gitignore ├── CMakeLists.txt ├── README.md ├── include ├── cminusfc │ └── cminusf_builder.hpp ├── codegen │ ├── ASMInstruction.hpp │ ├── CodeGen.hpp │ ├── CodeGenUtil.hpp │ └── Register.hpp ├── common │ ├── ast.hpp │ ├── logging.hpp │ └── syntax_tree.h ├── lightir │ ├── BasicBlock.hpp │ ├── Constant.hpp │ ├── Function.hpp │ ├── GlobalVariable.hpp │ ├── IRBuilder.hpp │ ├── IRprinter.hpp │ ├── Instruction.hpp │ ├── Module.hpp │ ├── Type.hpp │ ├── User.hpp │ └── Value.hpp └── passes │ ├── DeadCode.hpp │ ├── Dominators.hpp │ ├── FuncInfo.hpp │ ├── Mem2Reg.hpp │ └── PassManager.hpp ├── src ├── CMakeLists.txt ├── cminusfc │ ├── CMakeLists.txt │ ├── Readme.md │ ├── cminusf_builder.cpp │ └── cminusfc.cpp ├── codegen │ ├── CMakeLists.txt │ ├── CodeGen.cpp │ └── Register.cpp ├── common │ ├── CMakeLists.txt │ ├── ast.cpp │ ├── logging.cpp │ └── syntax_tree.c ├── io │ ├── CMakeLists.txt │ ├── io.c │ └── io.h ├── lightir │ ├── BasicBlock.cpp │ ├── CMakeLists.txt │ ├── Constant.cpp │ ├── Function.cpp │ ├── GlobalVariable.cpp │ ├── IRprinter.cpp │ ├── Instruction.cpp │ ├── Module.cpp │ ├── Type.cpp │ ├── User.cpp │ └── Value.cpp ├── logging │ ├── CMakeLists.txt │ ├── test_ast.cpp │ └── test_logging.cpp ├── parser │ ├── CMakeLists.txt │ ├── lexer.c │ ├── lexical_analyzer.l │ ├── parser.c │ └── syntax_analyzer.y └── passes │ ├── CMakeLists.txt │ ├── DeadCode.cpp │ ├── Dominators.cpp │ ├── FuncInfo.cpp │ └── Mem2Reg.cpp └── tests ├── 1-parser ├── cleanup.sh ├── eval_lab1.sh ├── input │ ├── easy │ │ ├── FAIL_comment.cminus │ │ ├── FAIL_comment2.cminus │ │ ├── FAIL_function.cminus │ │ ├── FAIL_id.cminus │ │ ├── expr.cminus │ │ └── id.cminus │ ├── hard │ │ ├── You_Should_Pass.cminus │ │ ├── assoc.cminus │ │ ├── gcd.cminus │ │ ├── hanoi.cminus │ │ ├── if.cminus │ │ └── selectionsort.cminus │ └── normal │ │ ├── FAIL_assign.cminus │ │ ├── FAIL_local-decl.cminus │ │ ├── array.cminus │ │ ├── func.cminus │ │ ├── if.cminus │ │ ├── local-decl.cminus │ │ └── skip_spaces.cminus ├── output_standard │ ├── easy │ │ ├── FAIL_comment.syntax_tree │ │ ├── FAIL_comment2.syntax_tree │ │ ├── FAIL_function.syntax_tree │ │ ├── FAIL_id.syntax_tree │ │ ├── expr.syntax_tree │ │ └── id.syntax_tree │ ├── hard │ │ ├── You_Should_Pass.syntax_tree │ │ ├── assoc.syntax_tree │ │ ├── gcd.syntax_tree │ │ ├── hanoi.syntax_tree │ │ ├── if.syntax_tree │ │ └── selectionsort.syntax_tree │ ├── normal │ │ ├── FAIL_assign.syntax_tree │ │ ├── FAIL_local-decl.syntax_tree │ │ ├── array.syntax_tree │ │ ├── func.syntax_tree │ │ ├── if.syntax_tree │ │ ├── local-decl.syntax_tree │ │ └── skip_spaces.syntax_tree │ └── testcases_general │ │ ├── 1-return.syntax_tree │ │ ├── 10-funcall.syntax_tree │ │ ├── 11-funcall_chain.syntax_tree │ │ ├── 12-funcall_recursion.syntax_tree │ │ ├── 13-if_stmt.syntax_tree │ │ ├── 14-while_stmt.syntax_tree │ │ ├── 15-if_while.syntax_tree │ │ ├── 16-if_chain.syntax_tree │ │ ├── 17-while_chain.syntax_tree │ │ ├── 18-global_var.syntax_tree │ │ ├── 19-global_local_var.syntax_tree │ │ ├── 2-decl_int.syntax_tree │ │ ├── 20-gcd_array.syntax_tree │ │ ├── 21-comment.syntax_tree │ │ ├── 3-decl_float.syntax_tree │ │ ├── 4-decl_int_array.syntax_tree │ │ ├── 5-decl_float_array.syntax_tree │ │ ├── 6-num_add_int.syntax_tree │ │ ├── 7-assign_int_var_local.syntax_tree │ │ ├── 8-assign_int_array_local.syntax_tree │ │ └── 9-assign_cast.syntax_tree └── output_student │ └── .gitignore ├── 2-ir-gen ├── autogen │ ├── .gitignore │ ├── answers │ │ ├── lv0_1 │ │ │ ├── decl_float.out │ │ │ ├── decl_float_array.out │ │ │ ├── decl_int.out │ │ │ ├── decl_int_array.out │ │ │ ├── input.in │ │ │ ├── input.out │ │ │ ├── output_float.out │ │ │ ├── output_int.out │ │ │ └── return.out │ │ ├── lv0_2 │ │ │ ├── num_add_float.out │ │ │ ├── num_add_int.out │ │ │ ├── num_add_mixed.out │ │ │ ├── num_comp1.out │ │ │ ├── num_comp2.out │ │ │ ├── num_div_float.out │ │ │ ├── num_div_int.out │ │ │ ├── num_div_mixed.out │ │ │ ├── num_eq_float.out │ │ │ ├── num_eq_int.out │ │ │ ├── num_eq_mixed.out │ │ │ ├── num_ge_float.out │ │ │ ├── num_ge_int.out │ │ │ ├── num_ge_mixed.out │ │ │ ├── num_gt_float.out │ │ │ ├── num_gt_int.out │ │ │ ├── num_gt_mixed.out │ │ │ ├── num_le_float.out │ │ │ ├── num_le_int.out │ │ │ ├── num_le_mixed.out │ │ │ ├── num_lt_float.out │ │ │ ├── num_lt_int.out │ │ │ ├── num_lt_mixed.out │ │ │ ├── num_mul_float.out │ │ │ ├── num_mul_int.out │ │ │ ├── num_mul_mixed.out │ │ │ ├── num_neq_float.out │ │ │ ├── num_neq_int.out │ │ │ ├── num_neq_mixed.out │ │ │ ├── num_sub_float.out │ │ │ ├── num_sub_int.out │ │ │ └── num_sub_mixed.out │ │ ├── lv1 │ │ │ ├── assign_cmp.out │ │ │ ├── assign_float_array_global.out │ │ │ ├── assign_float_array_local.out │ │ │ ├── assign_float_var_global.out │ │ │ ├── assign_float_var_local.out │ │ │ ├── assign_int_array_global.out │ │ │ ├── assign_int_array_local.out │ │ │ ├── assign_int_var_global.out │ │ │ ├── assign_int_var_local.out │ │ │ ├── idx_float.out │ │ │ ├── innout.in │ │ │ ├── innout.out │ │ │ ├── iteration1.out │ │ │ ├── iteration2.out │ │ │ ├── negidx_float.out │ │ │ ├── negidx_floatfuncall.out │ │ │ ├── negidx_int.out │ │ │ ├── negidx_intfuncall.out │ │ │ ├── negidx_voidfuncall.out │ │ │ ├── scope.out │ │ │ ├── selection1.out │ │ │ ├── selection2.out │ │ │ ├── selection3.out │ │ │ ├── transfer_float_to_int.out │ │ │ └── transfer_int_to_float.out │ │ ├── lv2 │ │ │ ├── assign_chain.out │ │ │ ├── funcall_array.out │ │ │ ├── funcall_array_array.out │ │ │ ├── funcall_chain.out │ │ │ ├── funcall_float_array.out │ │ │ ├── funcall_int_array.out │ │ │ ├── funcall_type_mismatch1.out │ │ │ ├── funcall_type_mismatch2.out │ │ │ ├── funcall_var.out │ │ │ ├── return_in_middle1.out │ │ │ ├── return_in_middle2.out │ │ │ ├── return_type_mismatch1.out │ │ │ └── return_type_mismatch2.out │ │ └── lv3 │ │ │ ├── complex1.out │ │ │ ├── complex2.in │ │ │ ├── complex2.out │ │ │ ├── complex3.in │ │ │ ├── complex3.out │ │ │ └── complex4.out │ ├── eval_lab2.py │ └── testcases │ │ ├── lv0_1 │ │ ├── decl_float.cminus │ │ ├── decl_float_array.cminus │ │ ├── decl_int.cminus │ │ ├── decl_int_array.cminus │ │ ├── input.cminus │ │ ├── output_float.cminus │ │ ├── output_int.cminus │ │ └── return.cminus │ │ ├── lv0_2 │ │ ├── num_add_float.cminus │ │ ├── num_add_int.cminus │ │ ├── num_add_mixed.cminus │ │ ├── num_comp1.cminus │ │ ├── num_comp2.cminus │ │ ├── num_div_float.cminus │ │ ├── num_div_int.cminus │ │ ├── num_div_mixed.cminus │ │ ├── num_eq_float.cminus │ │ ├── num_eq_int.cminus │ │ ├── num_eq_mixed.cminus │ │ ├── num_ge_float.cminus │ │ ├── num_ge_int.cminus │ │ ├── num_ge_mixed.cminus │ │ ├── num_gt_float.cminus │ │ ├── num_gt_int.cminus │ │ ├── num_gt_mixed.cminus │ │ ├── num_le_float.cminus │ │ ├── num_le_int.cminus │ │ ├── num_le_mixed.cminus │ │ ├── num_lt_float.cminus │ │ ├── num_lt_int.cminus │ │ ├── num_lt_mixed.cminus │ │ ├── num_mul_float.cminus │ │ ├── num_mul_int.cminus │ │ ├── num_mul_mixed.cminus │ │ ├── num_neq_float.cminus │ │ ├── num_neq_int.cminus │ │ ├── num_neq_mixed.cminus │ │ ├── num_sub_float.cminus │ │ ├── num_sub_int.cminus │ │ └── num_sub_mixed.cminus │ │ ├── lv1 │ │ ├── assign_cmp.cminus │ │ ├── assign_float_array_global.cminus │ │ ├── assign_float_array_local.cminus │ │ ├── assign_float_var_global.cminus │ │ ├── assign_float_var_local.cminus │ │ ├── assign_int_array_global.cminus │ │ ├── assign_int_array_local.cminus │ │ ├── assign_int_var_global.cminus │ │ ├── assign_int_var_local.cminus │ │ ├── idx_float.cminus │ │ ├── innout.cminus │ │ ├── iteration1.cminus │ │ ├── iteration2.cminus │ │ ├── negidx_float.cminus │ │ ├── negidx_floatfuncall.cminus │ │ ├── negidx_int.cminus │ │ ├── negidx_intfuncall.cminus │ │ ├── negidx_voidfuncall.cminus │ │ ├── scope.cminus │ │ ├── selection1.cminus │ │ ├── selection2.cminus │ │ ├── selection3.cminus │ │ ├── transfer_float_to_int.cminus │ │ └── transfer_int_to_float.cminus │ │ ├── lv2 │ │ ├── assign_chain.cminus │ │ ├── funcall_array_array.cminus │ │ ├── funcall_chain.cminus │ │ ├── funcall_float_array.cminus │ │ ├── funcall_int_array.cminus │ │ ├── funcall_type_mismatch1.cminus │ │ ├── funcall_type_mismatch2.cminus │ │ ├── funcall_var.cminus │ │ ├── return_in_middle1.cminus │ │ ├── return_in_middle2.cminus │ │ ├── return_type_mismatch1.cminus │ │ └── return_type_mismatch2.cminus │ │ └── lv3 │ │ ├── complex1.cminus │ │ ├── complex2.cminus │ │ ├── complex3.cminus │ │ └── complex4.cminus └── warmup │ ├── CMakeLists.txt │ ├── c_cases │ ├── assign.c │ ├── fun.c │ ├── if.c │ ├── while.c │ └── while.ll │ ├── calculator │ ├── CMakeLists.txt │ ├── calc.cpp │ ├── calc_ast.cpp │ ├── calc_ast.hpp │ ├── calc_builder.cpp │ ├── calc_builder.hpp │ ├── calculator.l │ └── calculator.y │ ├── stu_cpp │ ├── assign_generator.cpp │ ├── fun_generator.cpp │ ├── if_generator.cpp │ └── while_generator.cpp │ ├── stu_ll │ ├── assign_hand.ll │ ├── fun_hand.ll │ ├── if_hand.ll │ └── while_hand.ll │ └── ta_gcd │ ├── gcd_array.c │ └── gcd_array_generator.cpp ├── 3-codegen ├── autogen │ ├── cleanup.sh │ ├── eval_lab3.sh │ └── testcases │ │ ├── 0-io.cminus │ │ ├── 0-io.in │ │ ├── 0-io.out │ │ ├── 1-return.cminus │ │ ├── 1-return.out │ │ ├── 10-float.cminus │ │ ├── 10-float.out │ │ ├── 11-floatcall.cminus │ │ ├── 11-floatcall.out │ │ ├── 12-global.cminus │ │ ├── 12-global.out │ │ ├── 13-complex.cminus │ │ ├── 13-complex.out │ │ ├── 2-calculate.cminus │ │ ├── 2-calculate.out │ │ ├── 3-output.cminus │ │ ├── 3-output.out │ │ ├── 4-if.cminus │ │ ├── 4-if.out │ │ ├── 5-while.cminus │ │ ├── 5-while.out │ │ ├── 6-array.cminus │ │ ├── 6-array.out │ │ ├── 7-function.cminus │ │ ├── 7-function.out │ │ ├── 8-store.cminus │ │ ├── 8-store.out │ │ ├── 9-fibonacci.cminus │ │ └── 9-fibonacci.out └── warmup │ ├── CMakeLists.txt │ ├── ll_cases │ ├── assign.ll │ ├── fcmp.ll │ ├── float.ll │ ├── function.ll │ ├── global.ll │ └── icmp.ll │ └── stu_cpp │ ├── assign_codegen.cpp │ ├── fcmp_codegen.cpp │ ├── float_codegen.cpp │ ├── function_codegen.cpp │ ├── global_codegen.cpp │ └── icmp_codegen.cpp ├── 4-mem2reg ├── cleanup.sh ├── eval_lab4.sh ├── functional-cases │ ├── 0-io.cminus │ ├── 0-io.in │ ├── 0-io.out │ ├── 1-return.cminus │ ├── 1-return.out │ ├── 10-float.cminus │ ├── 10-float.out │ ├── 11-floatcall.cminus │ ├── 11-floatcall.out │ ├── 12-global.cminus │ ├── 12-global.out │ ├── 13-complex.cminus │ ├── 13-complex.out │ ├── 2-calculate.cminus │ ├── 2-calculate.out │ ├── 3-output.cminus │ ├── 3-output.out │ ├── 4-if.cminus │ ├── 4-if.out │ ├── 5-while.cminus │ ├── 5-while.out │ ├── 6-array.cminus │ ├── 6-array.out │ ├── 7-function.cminus │ ├── 7-function.out │ ├── 8-store.cminus │ ├── 8-store.out │ ├── 9-fibonacci.cminus │ └── 9-fibonacci.out ├── performance-cases │ ├── const-prop.cminus │ ├── const-prop.in │ ├── const-prop.out │ ├── loop.cminus │ ├── loop.out │ ├── transpose.cminus │ ├── transpose.in │ └── transpose.out └── test_perf.sh ├── CMakeLists.txt └── testcases_general ├── 1-return.cminus ├── 1-return.out ├── 10-funcall.cminus ├── 10-funcall.out ├── 11-funcall_chain.cminus ├── 11-funcall_chain.out ├── 12-funcall_recursion.cminus ├── 12-funcall_recursion.out ├── 13-if_stmt.cminus ├── 13-if_stmt.out ├── 14-while_stmt.cminus ├── 14-while_stmt.out ├── 15-if_while.cminus ├── 15-if_while.out ├── 16-if_chain.cminus ├── 16-if_chain.out ├── 17-while_chain.cminus ├── 17-while_chain.out ├── 18-global_var.cminus ├── 18-global_var.out ├── 19-global_local_var.cminus ├── 19-global_local_var.out ├── 2-decl_int.cminus ├── 2-decl_int.out ├── 20-gcd_array.cminus ├── 20-gcd_array.out ├── 21-comment.cminus ├── 21-comment.out ├── 3-decl_float.cminus ├── 3-decl_float.out ├── 4-decl_int_array.cminus ├── 4-decl_int_array.out ├── 5-decl_float_array.cminus ├── 5-decl_float_array.out ├── 6-num_add_int.cminus ├── 6-num_add_int.out ├── 7-assign_int_var_local.cminus ├── 7-assign_int_var_local.out ├── 8-assign_int_array_local.cminus ├── 8-assign_int_array_local.out ├── 9-assign_cast.cminus ├── 9-assign_cast.out └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | .vscode -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | project(CMINUSF) 2 | cmake_minimum_required( VERSION 3.4 ) 3 | 4 | set(CMAKE_C_FLAGS "${CMAKE_CXX_FLAGS} -std=c99") 5 | 6 | SET(CMAKE_CXX_FLAGS_DEBUG "$ENV{CXXFLAGS} -O0 -Wall -g2 -ggdb") 7 | SET(CMAKE_CXX_FLAGS_RELEASE "$ENV{CXXFLAGS} -O3 -Wall") 8 | SET(CMAKE_CXX_FLAGS_ASAN "${CMAKE_CXX_FLAGS_DEBUG} -fsanitize=undefined -fsanitize=address") 9 | 10 | set(default_build_type "Debug") 11 | 12 | if(NOT(CMAKE_BUILD_TYPE_SHADOW STREQUAL CMAKE_BUILD_TYPE)) 13 | if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) 14 | message(STATUS "Setting build type to '${default_build_type}'") 15 | set(CMAKE_BUILD_TYPE "${default_build_type}" CACHE STRING "Choose the type of build." FORCE) 16 | else() 17 | message(STATUS "Building in ${CMAKE_BUILD_TYPE} mode") 18 | endif() 19 | 20 | set(CMAKE_BUILD_TYPE_SHADOW ${CMAKE_BUILD_TYPE} CACHE STRING "used to detect changes in build type" FORCE) 21 | endif() 22 | 23 | set(CMAKE_CXX_STANDARD 17) 24 | set(CMAKE_EXPORT_COMPILE_COMMANDS ON) 25 | 26 | find_package(FLEX REQUIRED) 27 | find_package(BISON REQUIRED) 28 | find_package(LLVM REQUIRED CONFIG) 29 | message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}") 30 | message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}") 31 | llvm_map_components_to_libnames( 32 | llvm_libs 33 | support 34 | core 35 | ) 36 | 37 | INCLUDE_DIRECTORIES( 38 | include 39 | include/cminusfc 40 | include/common 41 | include/lightir 42 | include/codegen 43 | include/passes/ 44 | ${LLVM_INCLUDE_DIRS} 45 | ) 46 | 47 | add_definitions(${LLVM_DEFINITIONS}) 48 | 49 | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}) 50 | set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}) 51 | set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}) 52 | 53 | include_directories(${PROJECT_SOURCE_DIR}) 54 | include_directories(${PROJECT_BINARY_DIR}) 55 | add_subdirectory(src) 56 | add_subdirectory(tests) 57 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 简介 2 | 3 | 本仓库为 USTC 编译原理和技术 2023 的课程实验仓库。在本学期的编译实验中,你们将构建一个从词法分析器开始到后端代码生成的JIANMU编译器。 4 | 5 | **编译课程的四个实验均已完成** 6 | -------------------------------------------------------------------------------- /include/codegen/ASMInstruction.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | struct ASMInstruction { 7 | enum InstType { Instruction, Atrribute, Label, Comment } type; 8 | std::string content; 9 | 10 | explicit ASMInstruction(std::string s, InstType ty = Instruction) 11 | : type(ty), content(s) {} 12 | 13 | std::string format() const { 14 | switch (type) { 15 | case ASMInstruction::Instruction: 16 | case ASMInstruction::Atrribute: 17 | return "\t" + content + "\n"; 18 | case ASMInstruction::Label: 19 | return content + ":\n"; 20 | case ASMInstruction::Comment: 21 | return "# " + content + "\n"; 22 | } 23 | assert(false && "unreachable"); 24 | } 25 | }; 26 | -------------------------------------------------------------------------------- /include/codegen/CodeGen.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ASMInstruction.hpp" 4 | #include "Module.hpp" 5 | #include "Register.hpp" 6 | 7 | class CodeGen { 8 | public: 9 | explicit CodeGen(Module *module) : m(module) {} 10 | 11 | std::string print() const; 12 | 13 | void run(); 14 | 15 | template void append_inst(Args... arg) { 16 | output.emplace_back(arg...); 17 | } 18 | 19 | void 20 | append_inst(const char *inst, std::initializer_list args, 21 | ASMInstruction::InstType ty = ASMInstruction::Instruction) { 22 | auto content = std::string(inst) + " "; 23 | for (const auto &arg : args) { 24 | content += arg + ", "; 25 | } 26 | content.pop_back(); 27 | content.pop_back(); 28 | output.emplace_back(content, ty); 29 | } 30 | 31 | private: 32 | void allocate(); 33 | 34 | // 向寄存器中装载数据 35 | void load_to_greg(Value *, const Reg &); 36 | void load_to_freg(Value *, const FReg &); 37 | void load_from_stack_to_greg(Value *, const Reg &); 38 | 39 | // 向寄存器中加载立即数 40 | void load_large_int32(int32_t, const Reg &); 41 | void load_large_int64(int64_t, const Reg &); 42 | void load_float_imm(float, const FReg &); 43 | 44 | // 将寄存器中的数据保存回栈上 45 | void store_from_greg(Value *, const Reg &); 46 | void store_from_freg(Value *, const FReg &); 47 | 48 | void gen_prologue(); 49 | void gen_ret(); 50 | void gen_br(); 51 | void gen_binary(); 52 | void gen_float_binary(); 53 | void gen_alloca(); 54 | void gen_load(); 55 | void gen_store(); 56 | void gen_icmp(); 57 | void gen_fcmp(); 58 | void gen_zext(); 59 | void gen_call(); 60 | void gen_gep(); 61 | void gen_sitofp(); 62 | void gen_fptosi(); 63 | void gen_epilogue(); 64 | 65 | static std::string label_name(BasicBlock *bb) { 66 | return "." + bb->get_parent()->get_name() + "_" + bb->get_name(); 67 | } 68 | 69 | struct { 70 | /* 随着ir遍历设置 */ 71 | Function *func{nullptr}; // 当前函数 72 | Instruction *inst{nullptr}; // 当前指令 73 | /* 在allocate()中设置 */ 74 | unsigned frame_size{0}; // 当前函数的栈帧大小 75 | std::unordered_map offset_map{}; // 指针相对 fp 的偏移 76 | 77 | void clear() { 78 | func = nullptr; 79 | inst = nullptr; 80 | frame_size = 0; 81 | offset_map.clear(); 82 | } 83 | 84 | } context; 85 | 86 | Module *m; 87 | std::list output; 88 | }; 89 | -------------------------------------------------------------------------------- /include/codegen/CodeGenUtil.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | /* 关于位宽 */ 6 | #define IMM_12_MAX 0x7FF 7 | #define IMM_12_MIN -0x800 8 | 9 | #define LOW_12_MASK 0x00000FFF 10 | #define LOW_20_MASK 0x000FFFFF 11 | #define LOW_32_MASK 0xFFFFFFFF 12 | 13 | inline unsigned ALIGN(unsigned x, unsigned alignment) { 14 | return ((x + (alignment - 1)) & ~(alignment - 1)); 15 | } 16 | 17 | inline bool IS_IMM_12(int x) { return x <= IMM_12_MAX and x >= IMM_12_MIN; } 18 | 19 | /* 栈帧相关 */ 20 | #define PROLOGUE_OFFSET_BASE 16 // $ra $fp 21 | #define PROLOGUE_ALIGN 16 22 | 23 | /* 龙芯指令 */ 24 | // Arithmetic 25 | #define ADD "add" 26 | #define SUB "sub" 27 | #define MUL "mul" 28 | #define DIV "div" 29 | 30 | #define ADDI "addi" 31 | 32 | #define FADD "fadd" 33 | #define FSUB "fsub" 34 | #define FMUL "fmul" 35 | #define FDIV "fdiv" 36 | 37 | #define ORI "ori" 38 | 39 | #define LU12I_W "lu12i.w" 40 | #define LU32I_D "lu32i.d" 41 | #define LU52I_D "lu52i.d" 42 | 43 | // Data transfer (greg <-> freg) 44 | #define GR2FR "movgr2fr" 45 | #define FR2GR "movfr2gr" 46 | 47 | // Memory access 48 | #define LOAD "ld" 49 | #define STORE "st" 50 | #define FLOAD "fld" 51 | #define FSTORE "fst" 52 | 53 | #define BYTE ".b" 54 | #define HALF_WORD ".h" 55 | #define WORD ".w" 56 | #define DOUBLE ".d" 57 | 58 | #define SINGLE ".s" // float 59 | #define LONG ".l" 60 | 61 | // ASM syntax sugar 62 | #define LOAD_ADDR "la.local" 63 | 64 | // errors 65 | class not_implemented_error : public std::logic_error { 66 | public: 67 | explicit not_implemented_error(std::string &&err_msg = "") 68 | : std::logic_error(err_msg){}; 69 | }; 70 | 71 | class unreachable_error : public std::logic_error { 72 | public: 73 | explicit unreachable_error(std::string &&err_msg = "") 74 | : std::logic_error(err_msg){}; 75 | }; 76 | -------------------------------------------------------------------------------- /include/codegen/Register.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | /* General-purpose Register Convention: 7 | * Name Alias Meaning 8 | * $r0 $zero constant 0 9 | * $r1 $ra return address 10 | * $r2 $tp thread pointer 11 | * $r3 $sp stack pointer 12 | * $r4 - $r5 $a0 - $a1 argument, return value 13 | * $r6 - $r11 $a2 - $a7 argument 14 | * $r12 - $r20 $t0 - $t8 temporary 15 | * $r21 saved 16 | * $r22 $fp / $s9 frame pointer 17 | * $r23 - $r31 $s0 - $s8 static 18 | * 19 | * Floating-point Register Convention 20 | * Name Alias Meaning 21 | * $f0-$f1 $fa0-$fa1 argument/return value 22 | * $f2-$f7 $fa2-$fa7 argument 23 | * $f8-$f23 $ft0-$ft15 temporary 24 | * $f24-$f31 $fs0-$fs7 static 25 | */ 26 | 27 | struct Reg { 28 | unsigned id; 29 | 30 | explicit Reg(unsigned i) : id(i) { assert(i <= 31); } 31 | bool operator==(const Reg &other) { return id == other.id; } 32 | 33 | std::string print() const; 34 | 35 | static Reg zero() { return Reg(0); } 36 | static Reg ra() { return Reg(1); } 37 | static Reg sp() { return Reg(3); } 38 | static Reg fp() { return Reg(22); } 39 | static Reg a(unsigned i) { 40 | assert(0 <= i and i <= 7); 41 | return Reg(i + 4); 42 | } 43 | static Reg t(unsigned i) { 44 | assert(0 <= i and i <= 8); 45 | return Reg(i + 12); 46 | } 47 | static Reg s(unsigned i) { 48 | assert(0 <= i and i <= 9); 49 | if (i == 9) 50 | return Reg(22); 51 | else 52 | return Reg(i + 23); 53 | } 54 | }; 55 | 56 | struct FReg { 57 | unsigned id; 58 | 59 | explicit FReg(unsigned i) : id(i) { assert(i <= 31); } 60 | bool operator==(const FReg &other) { return id == other.id; } 61 | 62 | std::string print() const; 63 | 64 | static FReg fa(unsigned i) { 65 | assert(0 <= i and i <= 7); 66 | return FReg(i); 67 | } 68 | static FReg ft(unsigned i) { 69 | assert(0 <= i and i <= 15); 70 | return FReg(i + 8); 71 | } 72 | static FReg fs(unsigned i) { 73 | assert(0 <= i and i <= 7); 74 | return FReg(i + 24); 75 | } 76 | }; 77 | 78 | struct CFReg { 79 | unsigned id; 80 | 81 | explicit CFReg(unsigned i) : id(i) { assert(i <= 7); } 82 | bool operator==(const CFReg &other) { return id == other.id; } 83 | 84 | std::string print() const { return "$fcc" + std::to_string(id); } 85 | }; 86 | -------------------------------------------------------------------------------- /include/common/logging.hpp: -------------------------------------------------------------------------------- 1 | #ifndef LOGGING_HPP 2 | #define LOGGING_HPP 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | enum LogLevel 9 | { 10 | DEBUG = 0, 11 | INFO, 12 | WARNING, 13 | ERROR 14 | }; 15 | struct LocationInfo 16 | { 17 | LocationInfo(std::string file, int line, const char *func) : file_(file), line_(line), func_(func) {} 18 | ~LocationInfo() = default; 19 | 20 | std::string file_; 21 | int line_; 22 | const char *func_; 23 | }; 24 | class LogStream; 25 | class LogWriter; 26 | 27 | class LogWriter 28 | { 29 | public: 30 | LogWriter(LocationInfo location, LogLevel loglevel) 31 | : location_(location), log_level_(loglevel) 32 | { 33 | char *logv = std::getenv("LOGV"); 34 | if (logv) 35 | { 36 | std::string string_logv = logv; 37 | env_log_level = std::stoi(logv); 38 | } 39 | else 40 | { 41 | env_log_level = 4; 42 | } 43 | }; 44 | 45 | void operator<(const LogStream &stream); 46 | 47 | private: 48 | void output_log(const std::ostringstream &g); 49 | LocationInfo location_; 50 | LogLevel log_level_; 51 | int env_log_level; 52 | }; 53 | 54 | class LogStream 55 | { 56 | public: 57 | LogStream() { sstream_ = new std::stringstream(); } 58 | ~LogStream() = default; 59 | 60 | template 61 | LogStream &operator<<(const T &val) noexcept 62 | { 63 | (*sstream_) << val; 64 | return *this; 65 | } 66 | 67 | friend class LogWriter; 68 | 69 | private: 70 | std::stringstream *sstream_; 71 | }; 72 | 73 | std::string level2string(LogLevel level); 74 | std::string get_short_name(const char *file_path); 75 | 76 | #define __FILESHORTNAME__ get_short_name(__FILE__) 77 | #define LOG_IF(level) \ 78 | LogWriter(LocationInfo(__FILESHORTNAME__, __LINE__, __FUNCTION__), level) < LogStream() 79 | #define LOG(level) LOG_##level 80 | #define LOG_DEBUG LOG_IF(DEBUG) 81 | #define LOG_INFO LOG_IF(INFO) 82 | #define LOG_WARNING LOG_IF(WARNING) 83 | #define LOG_ERROR LOG_IF(ERROR) 84 | 85 | #endif 86 | -------------------------------------------------------------------------------- /include/common/syntax_tree.h: -------------------------------------------------------------------------------- 1 | #ifndef __SYNTAXTREE_H__ 2 | #define __SYNTAXTREE_H__ 3 | 4 | #include 5 | 6 | #define SYNTAX_TREE_NODE_NAME_MAX 30 7 | 8 | struct _syntax_tree_node { 9 | struct _syntax_tree_node * parent; 10 | struct _syntax_tree_node * children[10]; 11 | int children_num; 12 | 13 | char name[SYNTAX_TREE_NODE_NAME_MAX]; 14 | }; 15 | typedef struct _syntax_tree_node syntax_tree_node; 16 | 17 | syntax_tree_node * new_anon_syntax_tree_node(); 18 | syntax_tree_node * new_syntax_tree_node(const char * name); 19 | int syntax_tree_add_child(syntax_tree_node * parent, syntax_tree_node * child); 20 | void del_syntax_tree_node(syntax_tree_node * node, int recursive); 21 | 22 | struct _syntax_tree { 23 | syntax_tree_node * root; 24 | }; 25 | typedef struct _syntax_tree syntax_tree; 26 | 27 | syntax_tree* new_syntax_tree(); 28 | void del_syntax_tree(syntax_tree * tree); 29 | void print_syntax_tree(FILE * fout, syntax_tree * tree); 30 | 31 | #endif /* SyntaxTree.h */ 32 | -------------------------------------------------------------------------------- /include/lightir/BasicBlock.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Instruction.hpp" 4 | #include "Value.hpp" 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | class Function; 13 | class Instruction; 14 | class Module; 15 | 16 | class BasicBlock : public Value, public llvm::ilist_node { 17 | public: 18 | ~BasicBlock() = default; 19 | static BasicBlock *create(Module *m, const std::string &name, 20 | Function *parent) { 21 | auto prefix = name.empty() ? "" : "label_"; 22 | return new BasicBlock(m, prefix + name, parent); 23 | } 24 | 25 | /****************api about cfg****************/ 26 | std::list &get_pre_basic_blocks() { return pre_bbs_; } 27 | std::list &get_succ_basic_blocks() { return succ_bbs_; } 28 | 29 | void add_pre_basic_block(BasicBlock *bb) { pre_bbs_.push_back(bb); } 30 | void add_succ_basic_block(BasicBlock *bb) { succ_bbs_.push_back(bb); } 31 | void remove_pre_basic_block(BasicBlock *bb) { pre_bbs_.remove(bb); } 32 | void remove_succ_basic_block(BasicBlock *bb) { succ_bbs_.remove(bb); } 33 | 34 | // If the Block is terminated by ret/br 35 | bool is_terminated() const; 36 | // Get terminator, only accept valid case use 37 | Instruction *get_terminator(); 38 | 39 | /****************api about Instruction****************/ 40 | void add_instruction(Instruction *instr); 41 | void add_instr_begin(Instruction *instr) { instr_list_.push_front(instr); } 42 | void erase_instr(Instruction *instr) { instr_list_.erase(instr); } 43 | 44 | llvm::ilist &get_instructions() { return instr_list_; } 45 | bool empty() const { return instr_list_.empty(); } 46 | int get_num_of_instr() const { return instr_list_.size(); } 47 | 48 | /****************api about accessing parent****************/ 49 | Function *get_parent() { return parent_; } 50 | Module *get_module(); 51 | void erase_from_parent(); 52 | 53 | virtual std::string print() override; 54 | 55 | private: 56 | BasicBlock(const BasicBlock &) = delete; 57 | explicit BasicBlock(Module *m, const std::string &name, Function *parent); 58 | 59 | std::list pre_bbs_; 60 | std::list succ_bbs_; 61 | llvm::ilist instr_list_; 62 | Function *parent_; 63 | }; 64 | -------------------------------------------------------------------------------- /include/lightir/Constant.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Type.hpp" 4 | #include "User.hpp" 5 | #include "Value.hpp" 6 | 7 | class Constant : public User { 8 | private: 9 | // int value; 10 | public: 11 | Constant(Type *ty, const std::string &name = "") : User(ty, name) {} 12 | ~Constant() = default; 13 | }; 14 | 15 | class ConstantInt : public Constant { 16 | private: 17 | int value_; 18 | ConstantInt(Type *ty, int val) : Constant(ty, ""), value_(val) {} 19 | 20 | public: 21 | int get_value() { return value_; } 22 | static ConstantInt *get(int val, Module *m); 23 | static ConstantInt *get(bool val, Module *m); 24 | virtual std::string print() override; 25 | }; 26 | 27 | class ConstantArray : public Constant { 28 | private: 29 | std::vector const_array; 30 | 31 | ConstantArray(ArrayType *ty, const std::vector &val); 32 | 33 | public: 34 | ~ConstantArray() = default; 35 | 36 | Constant *get_element_value(int index); 37 | 38 | unsigned get_size_of_array() { return const_array.size(); } 39 | 40 | static ConstantArray *get(ArrayType *ty, 41 | const std::vector &val); 42 | 43 | virtual std::string print() override; 44 | }; 45 | 46 | class ConstantZero : public Constant { 47 | private: 48 | ConstantZero(Type *ty) : Constant(ty, "") {} 49 | 50 | public: 51 | static ConstantZero *get(Type *ty, Module *m); 52 | virtual std::string print() override; 53 | }; 54 | 55 | class ConstantFP : public Constant { 56 | private: 57 | float val_; 58 | ConstantFP(Type *ty, float val) : Constant(ty, ""), val_(val) {} 59 | 60 | public: 61 | static ConstantFP *get(float val, Module *m); 62 | float get_value() { return val_; } 63 | virtual std::string print() override; 64 | }; 65 | -------------------------------------------------------------------------------- /include/lightir/Function.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "BasicBlock.hpp" 4 | #include "Type.hpp" 5 | #include "User.hpp" 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | class Module; 17 | class Argument; 18 | class Type; 19 | class FunctionType; 20 | 21 | class Function : public Value, public llvm::ilist_node { 22 | public: 23 | Function(const Function &) = delete; 24 | Function(FunctionType *ty, const std::string &name, Module *parent); 25 | ~Function() = default; 26 | static Function *create(FunctionType *ty, const std::string &name, 27 | Module *parent); 28 | 29 | FunctionType *get_function_type() const; 30 | Type *get_return_type() const; 31 | 32 | void add_basic_block(BasicBlock *bb); 33 | 34 | unsigned get_num_of_args() const; 35 | unsigned get_num_basic_blocks() const; 36 | 37 | Module *get_parent() const; 38 | 39 | void remove(BasicBlock *bb); 40 | BasicBlock *get_entry_block() { return &*basic_blocks_.begin(); } 41 | 42 | llvm::ilist &get_basic_blocks() { return basic_blocks_; } 43 | std::list &get_args() { return arguments_; } 44 | 45 | bool is_declaration() { return basic_blocks_.empty(); } 46 | 47 | void set_instr_name(); 48 | std::string print(); 49 | 50 | private: 51 | llvm::ilist basic_blocks_; 52 | std::list arguments_; 53 | Module *parent_; 54 | unsigned seq_cnt_; // print use 55 | }; 56 | 57 | // Argument of Function, does not contain actual value 58 | class Argument : public Value { 59 | public: 60 | Argument(const Argument &) = delete; 61 | explicit Argument(Type *ty, const std::string &name = "", 62 | Function *f = nullptr, unsigned arg_no = 0) 63 | : Value(ty, name), parent_(f), arg_no_(arg_no) {} 64 | virtual ~Argument() {} 65 | 66 | inline const Function *get_parent() const { return parent_; } 67 | inline Function *get_parent() { return parent_; } 68 | 69 | /// For example in "void foo(int a, float b)" a is 0 and b is 1. 70 | unsigned get_arg_no() const { 71 | assert(parent_ && "can't get number of unparented arg"); 72 | return arg_no_; 73 | } 74 | 75 | virtual std::string print() override; 76 | 77 | private: 78 | Function *parent_; 79 | unsigned arg_no_; // argument No. 80 | }; 81 | -------------------------------------------------------------------------------- /include/lightir/GlobalVariable.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Constant.hpp" 4 | #include "User.hpp" 5 | 6 | #include 7 | class Module; 8 | class GlobalVariable : public User, public llvm::ilist_node { 9 | private: 10 | bool is_const_; 11 | Constant *init_val_; 12 | GlobalVariable(std::string name, Module *m, Type *ty, bool is_const, 13 | Constant *init = nullptr); 14 | 15 | public: 16 | GlobalVariable(const GlobalVariable &) = delete; 17 | static GlobalVariable *create(std::string name, Module *m, Type *ty, 18 | bool is_const, Constant *init); 19 | virtual ~GlobalVariable() = default; 20 | Constant *get_init() { return init_val_; } 21 | bool is_const() { return is_const_; } 22 | std::string print(); 23 | }; 24 | -------------------------------------------------------------------------------- /include/lightir/IRprinter.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "BasicBlock.hpp" 4 | #include "Constant.hpp" 5 | #include "Function.hpp" 6 | #include "GlobalVariable.hpp" 7 | #include "Instruction.hpp" 8 | #include "Module.hpp" 9 | #include "Type.hpp" 10 | #include "User.hpp" 11 | #include "Value.hpp" 12 | 13 | std::string print_as_op(Value *v, bool print_ty); 14 | std::string print_instr_op_name(Instruction::OpID); 15 | -------------------------------------------------------------------------------- /include/lightir/Module.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Function.hpp" 4 | #include "GlobalVariable.hpp" 5 | #include "Instruction.hpp" 6 | #include "Type.hpp" 7 | #include "Value.hpp" 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | class GlobalVariable; 18 | class Function; 19 | class Module { 20 | public: 21 | Module(); 22 | ~Module() = default; 23 | 24 | Type *get_void_type(); 25 | Type *get_label_type(); 26 | IntegerType *get_int1_type(); 27 | IntegerType *get_int32_type(); 28 | PointerType *get_int32_ptr_type(); 29 | FloatType *get_float_type(); 30 | PointerType *get_float_ptr_type(); 31 | 32 | PointerType *get_pointer_type(Type *contained); 33 | ArrayType *get_array_type(Type *contained, unsigned num_elements); 34 | FunctionType *get_function_type(Type *retty, std::vector &args); 35 | 36 | void add_function(Function *f); 37 | llvm::ilist &get_functions(); 38 | void add_global_variable(GlobalVariable *g); 39 | llvm::ilist &get_global_variable(); 40 | 41 | void set_print_name(); 42 | std::string print(); 43 | 44 | private: 45 | // The global variables in the module 46 | llvm::ilist global_list_; 47 | // The functions in the module 48 | llvm::ilist function_list_; 49 | 50 | std::unique_ptr int1_ty_; 51 | std::unique_ptr int32_ty_; 52 | std::unique_ptr label_ty_; 53 | std::unique_ptr void_ty_; 54 | std::unique_ptr float32_ty_; 55 | std::map> pointer_map_; 56 | std::map, std::unique_ptr> array_map_; 57 | std::map>, 58 | std::unique_ptr> 59 | function_map_; 60 | }; 61 | -------------------------------------------------------------------------------- /include/lightir/User.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Value.hpp" 4 | 5 | #include 6 | 7 | class User : public Value { 8 | public: 9 | User(Type *ty, const std::string &name = "") : Value(ty, name){}; 10 | virtual ~User() { remove_all_operands(); } 11 | 12 | const std::vector &get_operands() const { return operands_; } 13 | unsigned get_num_operand() const { return operands_.size(); } 14 | 15 | // start from 0 16 | Value *get_operand(unsigned i) const { return operands_.at(i); }; 17 | // start from 0 18 | void set_operand(unsigned i, Value *v); 19 | void add_operand(Value *v); 20 | 21 | void remove_all_operands(); 22 | void remove_operand(unsigned i); 23 | 24 | private: 25 | std::vector operands_; // operands of this value 26 | }; 27 | 28 | /* For example: op = func(a, b) 29 | * for a: Use(op, 0) 30 | * for b: Use(op, 1) 31 | */ 32 | struct Use { 33 | User *val_; // used by whom 34 | unsigned arg_no_; // the no. of operand 35 | 36 | Use(User *val, unsigned no) : val_(val), arg_no_(no) {} 37 | 38 | bool operator==(const Use &other) const { 39 | return val_ == other.val_ and arg_no_ == other.arg_no_; 40 | } 41 | }; 42 | -------------------------------------------------------------------------------- /include/lightir/Value.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | class Type; 9 | class Value; 10 | class User; 11 | struct Use; 12 | 13 | class Value { 14 | public: 15 | explicit Value(Type *ty, const std::string &name = "") 16 | : type_(ty), name_(name){}; 17 | virtual ~Value() { replace_all_use_with(nullptr); } 18 | 19 | std::string get_name() const { return name_; }; 20 | Type *get_type() const { return type_; } 21 | const std::list &get_use_list() const { return use_list_; } 22 | 23 | bool set_name(std::string name); 24 | 25 | void add_use(User *user, unsigned arg_no); 26 | void remove_use(User *user, unsigned arg_no); 27 | 28 | void replace_all_use_with(Value *new_val); 29 | void replace_use_with_if(Value *new_val, std::function pred); 30 | 31 | virtual std::string print() = 0; 32 | 33 | private: 34 | Type *type_; 35 | std::list use_list_; // who use this value 36 | std::string name_; // should we put name field here ? 37 | }; 38 | -------------------------------------------------------------------------------- /include/passes/DeadCode.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "FuncInfo.hpp" 4 | #include "PassManager.hpp" 5 | 6 | #include 7 | 8 | /** 9 | * 死代码消除:参见 10 | *https://www.clear.rice.edu/comp512/Lectures/10Dead-Clean-SCCP.pdf 11 | **/ 12 | class DeadCode : public Pass { 13 | public: 14 | DeadCode(Module *m) : Pass(m), func_info(std::make_shared(m)) {} 15 | 16 | void run(); 17 | 18 | private: 19 | std::shared_ptr func_info; 20 | int ins_count{0}; // 用以衡量死代码消除的性能 21 | std::deque work_list{}; 22 | std::unordered_map marked{}; 23 | 24 | void mark(Function *func); 25 | void mark(Instruction *ins); 26 | bool sweep(Function *func); 27 | bool is_critical(Instruction *ins); 28 | }; 29 | -------------------------------------------------------------------------------- /include/passes/Dominators.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "BasicBlock.hpp" 4 | #include "PassManager.hpp" 5 | 6 | #include 7 | #include 8 | 9 | class Dominators : public Pass { 10 | public: 11 | using BBSet = std::set; 12 | 13 | explicit Dominators(Module *m) : Pass(m) {} 14 | ~Dominators() = default; 15 | void run() override; 16 | 17 | BasicBlock *get_idom(BasicBlock *bb) { return idom_.at(bb); } 18 | const BBSet &get_dominance_frontier(BasicBlock *bb) { 19 | return dom_frontier_.at(bb); 20 | } 21 | const BBSet &get_dom_tree_succ_blocks(BasicBlock *bb) { 22 | return dom_tree_succ_blocks_.at(bb); 23 | } 24 | 25 | private: 26 | void create_idom(Function *f); 27 | void create_dominance_frontier(Function *f); 28 | void create_dom_tree_succ(Function *f); 29 | 30 | BasicBlock* intersect(BasicBlock*b1,BasicBlock*b2); 31 | bool cmp_bb_slt(BasicBlock* b1,BasicBlock* b2); 32 | bool cmp_bb_eq(BasicBlock*b1,BasicBlock*b2); 33 | BasicBlock* first_processed_pred(BasicBlock* bb,BBSet& processed); 34 | // TODO 补充需要的函数 35 | 36 | std::map idom_{}; // 直接支配 37 | std::map dom_frontier_{}; // 支配边界集合 38 | std::map dom_tree_succ_blocks_{}; // 支配树中的后继节点 39 | }; 40 | -------------------------------------------------------------------------------- /include/passes/FuncInfo.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "PassManager.hpp" 4 | #include "logging.hpp" 5 | 6 | #include 7 | #include 8 | 9 | /** 10 | * 计算哪些函数是纯函数 11 | * WARN: 12 | * 假定所有函数都是纯函数,除非他写入了全局变量、修改了传入的数组、或者直接间接调用了非纯函数 13 | */ 14 | class FuncInfo : public Pass { 15 | public: 16 | FuncInfo(Module *m) : Pass(m) {} 17 | 18 | void run(); 19 | 20 | bool is_pure_function(Function *func) const { return is_pure.at(func); } 21 | 22 | private: 23 | std::deque worklist; 24 | std::unordered_map is_pure; 25 | 26 | void trivial_mark(Function *func); 27 | void process(Function *func); 28 | Value *get_first_addr(Value *val); 29 | 30 | bool is_side_effect_inst(Instruction *inst); 31 | bool is_local_load(LoadInst *inst); 32 | bool is_local_store(StoreInst *inst); 33 | 34 | void log(); 35 | }; 36 | -------------------------------------------------------------------------------- /include/passes/Mem2Reg.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Dominators.hpp" 4 | #include "Instruction.hpp" 5 | #include "Value.hpp" 6 | 7 | #include 8 | #include 9 | 10 | class Mem2Reg : public Pass { 11 | private: 12 | Function *func_; 13 | std::unique_ptr dominators_; 14 | std::unordered_map> crossBB_variable; 15 | std::unordered_map>variable_stacks; 16 | std::unordered_map phi_to_variable; 17 | std::unordered_map> variables_count; 18 | // TODO 添加需要的变量 19 | 20 | public: 21 | Mem2Reg(Module *m) : Pass(m) {} 22 | ~Mem2Reg() = default; 23 | 24 | void run() override; 25 | 26 | void generate_phi(); 27 | void rename(BasicBlock *bb); 28 | 29 | static inline bool is_global_variable(Value *l_val) { 30 | return dynamic_cast(l_val) != nullptr; 31 | } 32 | static inline bool is_gep_instr(Value *l_val) { 33 | return dynamic_cast(l_val) != nullptr; 34 | } 35 | 36 | static inline bool is_valid_ptr(Value *l_val) { 37 | return not is_global_variable(l_val) and not is_gep_instr(l_val); 38 | } 39 | }; 40 | -------------------------------------------------------------------------------- /include/passes/PassManager.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Module.hpp" 4 | 5 | #include 6 | #include 7 | 8 | class Pass { 9 | public: 10 | Pass(Module *m) : m_(m) {} 11 | virtual ~Pass() = default; 12 | virtual void run() = 0; 13 | 14 | protected: 15 | Module *m_; 16 | }; 17 | 18 | class PassManager { 19 | public: 20 | PassManager(Module *m) : m_(m) {} 21 | 22 | template 23 | void add_pass(Args &&...args) { 24 | passes_.emplace_back(new PassType(m_, std::forward(args)...)); 25 | } 26 | 27 | void run() { 28 | for (auto &pass : passes_) { 29 | pass->run(); 30 | } 31 | } 32 | 33 | private: 34 | std::vector> passes_; 35 | Module *m_; 36 | }; 37 | -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(parser) 2 | add_subdirectory(common) 3 | add_subdirectory(logging) 4 | add_subdirectory(io) 5 | add_subdirectory(lightir) 6 | add_subdirectory(cminusfc) 7 | add_subdirectory(codegen) 8 | add_subdirectory(passes) 9 | -------------------------------------------------------------------------------- /src/cminusfc/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable( 2 | cminusfc 3 | cminusfc.cpp 4 | cminusf_builder.cpp 5 | ) 6 | 7 | target_link_libraries( 8 | cminusfc 9 | IR_lib 10 | common 11 | syntax 12 | codegen 13 | stdc++fs 14 | opt_lib 15 | ) 16 | 17 | install( 18 | TARGETS cminusfc 19 | RUNTIME DESTINATION bin 20 | ) 21 | -------------------------------------------------------------------------------- /src/cminusfc/Readme.md: -------------------------------------------------------------------------------- 1 | # Note 2 | 1. 框架之中已经将基类的`accept`声明为虚函数,并且子类中都存在各自的具体实现,只需要简单的调用`accept()`函数即可,程序会根据父类指针所指向的子类调用对应的`accept()`实现; 3 | 2. 编写数组访问的时候注意考虑参数类型不匹配,或者参数为负的情况; -------------------------------------------------------------------------------- /src/codegen/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_library( 2 | codegen STATIC 3 | CodeGen.cpp 4 | Register.cpp 5 | ) 6 | 7 | target_link_libraries(codegen common IR_lib) 8 | -------------------------------------------------------------------------------- /src/codegen/Register.cpp: -------------------------------------------------------------------------------- 1 | #include "Register.hpp" 2 | #include 3 | 4 | std::string Reg::print() const { 5 | if (id == 0) { 6 | return "$zero"; 7 | } 8 | if (id == 1) { 9 | return "$ra"; 10 | } 11 | if (id == 2) { 12 | return "$tp"; 13 | } 14 | if (id == 3) { 15 | return "$sp"; 16 | } 17 | if (4 <= id and id <= 11) { 18 | return "$a" + std::to_string(id - 4); 19 | } 20 | if (12 <= id and id <= 20) { 21 | return "$t" + std::to_string(id - 12); 22 | } 23 | if (id == 22) { 24 | return "$fp"; 25 | } 26 | assert(false); 27 | } 28 | 29 | std::string FReg::print() const { 30 | 31 | if (0 <= id and id <= 7) { 32 | return "$fa" + std::to_string(id); 33 | } 34 | if (8 <= id and id <= 23) { 35 | return "$ft" + std::to_string(id - 8); 36 | } 37 | if (24 <= id and id <= 31) { 38 | return "$fs" + std::to_string(id - 24); 39 | } 40 | assert(false); 41 | } 42 | -------------------------------------------------------------------------------- /src/common/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_library(common STATIC 2 | syntax_tree.c 3 | ast.cpp 4 | logging.cpp 5 | ) 6 | 7 | target_link_libraries(common) 8 | 9 | -------------------------------------------------------------------------------- /src/common/logging.cpp: -------------------------------------------------------------------------------- 1 | #include "logging.hpp" 2 | 3 | void LogWriter::operator<(const LogStream &stream) { 4 | std::ostringstream msg; 5 | msg << stream.sstream_->rdbuf(); 6 | output_log(msg); 7 | } 8 | 9 | void LogWriter::output_log(const std::ostringstream &msg) { 10 | if (log_level_ >= env_log_level) 11 | std::cout << "[" << level2string(log_level_) << "] " 12 | << "(" << location_.file_ 13 | << ":" << location_.line_ 14 | << "L "<< location_.func_<<")" 15 | << msg.str() << std::endl; 16 | 17 | } 18 | std::string level2string(LogLevel level) { 19 | switch (level) 20 | { 21 | case DEBUG: 22 | return "DEBUG"; 23 | 24 | case INFO: 25 | return "INFO"; 26 | 27 | case WARNING: 28 | return "WARNING"; 29 | 30 | case ERROR: 31 | return "ERROR"; 32 | 33 | default: 34 | return ""; 35 | } 36 | } 37 | std::string get_short_name(const char * file_path) { 38 | std::string short_file_path = file_path; 39 | int index = short_file_path.find_last_of('/'); 40 | 41 | return short_file_path.substr(index+1); 42 | } 43 | -------------------------------------------------------------------------------- /src/common/syntax_tree.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "syntax_tree.h" 5 | 6 | syntax_tree_node * new_syntax_tree_node(const char * name) 7 | { 8 | syntax_tree_node * new_node = (syntax_tree_node *)malloc(sizeof(syntax_tree_node)); 9 | if (name) 10 | strncpy(new_node->name, name, SYNTAX_TREE_NODE_NAME_MAX); 11 | else 12 | new_node->name[0] = '\0'; 13 | new_node->children_num = 0; 14 | return new_node; 15 | } 16 | 17 | int syntax_tree_add_child(syntax_tree_node * parent, syntax_tree_node * child) 18 | { 19 | if (!parent || !child) return -1; 20 | parent->children[parent->children_num++] = child; 21 | return parent->children_num; 22 | } 23 | 24 | void del_syntax_tree_node(syntax_tree_node * node, int recursive) 25 | { 26 | if (!node) return; 27 | 28 | int i; 29 | if (recursive) { 30 | for (i = 0; i < node->children_num; i++) { 31 | del_syntax_tree_node(node->children[i], 1); 32 | } 33 | } 34 | free(node); 35 | } 36 | 37 | syntax_tree * new_syntax_tree() 38 | { 39 | return (syntax_tree *)malloc(sizeof(syntax_tree)); 40 | } 41 | 42 | void del_syntax_tree(syntax_tree * tree) 43 | { 44 | if (!tree) return; 45 | 46 | if (tree->root) { 47 | del_syntax_tree_node(tree->root, 1); 48 | } 49 | free(tree); 50 | } 51 | 52 | void print_syntax_tree_node(FILE * fout, syntax_tree_node * node, int level) 53 | { 54 | // assume fout valid now 55 | 56 | // check if "node" empty pointer 57 | if (!node) return; 58 | 59 | // print myself 60 | int i; 61 | for (i = 0; i < level; i++) { 62 | fprintf(fout, "| "); 63 | } 64 | fprintf(fout, ">--%s %s\n", (node->children_num ? "+" : "*"), node->name); 65 | 66 | for (i = 0; i < node->children_num; i++) { 67 | print_syntax_tree_node(fout, node->children[i], level + 1); 68 | } 69 | } 70 | 71 | void print_syntax_tree(FILE * fout, syntax_tree * tree) 72 | { 73 | if (!fout) return; 74 | 75 | print_syntax_tree_node(fout, tree->root, 0); 76 | } 77 | 78 | -------------------------------------------------------------------------------- /src/io/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_library(cminus_io io.c) 2 | 3 | install( 4 | TARGETS cminus_io 5 | ARCHIVE DESTINATION lib 6 | ) 7 | -------------------------------------------------------------------------------- /src/io/io.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | int input() { 4 | int a; 5 | scanf("%d", &a); 6 | return a; 7 | } 8 | 9 | void output(int a) { printf("%d\n", a); } 10 | 11 | void outputFloat(float a) { printf("%f\n", a); } 12 | 13 | void neg_idx_except() { 14 | printf("negative index exception\n"); 15 | exit(0); 16 | } 17 | -------------------------------------------------------------------------------- /src/io/io.h: -------------------------------------------------------------------------------- 1 | int input(); 2 | 3 | void output(int a); 4 | 5 | void outputFloat(float a); 6 | 7 | void neg_idx_except(); 8 | -------------------------------------------------------------------------------- /src/lightir/BasicBlock.cpp: -------------------------------------------------------------------------------- 1 | #include "BasicBlock.hpp" 2 | #include "Function.hpp" 3 | #include "IRprinter.hpp" 4 | #include "Module.hpp" 5 | 6 | #include 7 | 8 | BasicBlock::BasicBlock(Module *m, const std::string &name = "", 9 | Function *parent = nullptr) 10 | : Value(m->get_label_type(), name), parent_(parent) { 11 | assert(parent && "currently parent should not be nullptr"); 12 | parent_->add_basic_block(this); 13 | } 14 | 15 | Module *BasicBlock::get_module() { return get_parent()->get_parent(); } 16 | void BasicBlock::erase_from_parent() { this->get_parent()->remove(this); } 17 | 18 | bool BasicBlock::is_terminated() const { 19 | if (instr_list_.empty()) 20 | return false; 21 | switch (instr_list_.back().get_instr_type()) { 22 | case Instruction::ret: 23 | case Instruction::br: 24 | return true; 25 | default: 26 | return false; 27 | } 28 | } 29 | 30 | Instruction *BasicBlock::get_terminator() { 31 | assert(is_terminated() && 32 | "Trying to get terminator from an bb which is not terminated"); 33 | return &instr_list_.back(); 34 | } 35 | 36 | void BasicBlock::add_instruction(Instruction *instr) { 37 | assert(not is_terminated() && "Inserting instruction to terminated bb"); 38 | instr_list_.push_back(instr); 39 | } 40 | 41 | std::string BasicBlock::print() { 42 | std::string bb_ir; 43 | bb_ir += this->get_name(); 44 | bb_ir += ":"; 45 | // print prebb 46 | if (!this->get_pre_basic_blocks().empty()) { 47 | bb_ir += " ; preds = "; 48 | } 49 | for (auto bb : this->get_pre_basic_blocks()) { 50 | if (bb != *this->get_pre_basic_blocks().begin()) 51 | bb_ir += ", "; 52 | bb_ir += print_as_op(bb, false); 53 | } 54 | 55 | // print prebb 56 | if (!this->get_parent()) { 57 | bb_ir += "\n"; 58 | bb_ir += "; Error: Block without parent!"; 59 | } 60 | bb_ir += "\n"; 61 | for (auto &instr : this->get_instructions()) { 62 | bb_ir += " "; 63 | bb_ir += instr.print(); 64 | bb_ir += "\n"; 65 | } 66 | 67 | return bb_ir; 68 | } 69 | -------------------------------------------------------------------------------- /src/lightir/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_library( 2 | IR_lib STATIC 3 | Type.cpp 4 | User.cpp 5 | Value.cpp 6 | BasicBlock.cpp 7 | Constant.cpp 8 | Function.cpp 9 | GlobalVariable.cpp 10 | Instruction.cpp 11 | Module.cpp 12 | IRprinter.cpp 13 | ) 14 | 15 | target_link_libraries( 16 | IR_lib 17 | LLVMSupport 18 | ) 19 | -------------------------------------------------------------------------------- /src/lightir/GlobalVariable.cpp: -------------------------------------------------------------------------------- 1 | #include "GlobalVariable.hpp" 2 | #include "IRprinter.hpp" 3 | 4 | GlobalVariable::GlobalVariable(std::string name, Module *m, Type *ty, 5 | bool is_const, Constant *init) 6 | : User(ty, name), is_const_(is_const), init_val_(init) { 7 | m->add_global_variable(this); 8 | if (init) { 9 | this->add_operand(init); 10 | } 11 | } // global操作数为initval 12 | 13 | GlobalVariable *GlobalVariable::create(std::string name, Module *m, Type *ty, 14 | bool is_const, 15 | Constant *init = nullptr) { 16 | return new GlobalVariable(name, m, PointerType::get(ty), is_const, init); 17 | } 18 | 19 | std::string GlobalVariable::print() { 20 | std::string global_val_ir; 21 | global_val_ir += print_as_op(this, false); 22 | global_val_ir += " = "; 23 | global_val_ir += (this->is_const() ? "constant " : "global "); 24 | global_val_ir += this->get_type()->get_pointer_element_type()->print(); 25 | global_val_ir += " "; 26 | global_val_ir += this->get_init()->print(); 27 | return global_val_ir; 28 | } 29 | -------------------------------------------------------------------------------- /src/lightir/Module.cpp: -------------------------------------------------------------------------------- 1 | #include "Module.hpp" 2 | #include "Function.hpp" 3 | #include "GlobalVariable.hpp" 4 | 5 | #include 6 | #include 7 | 8 | Module::Module() { 9 | void_ty_ = std::make_unique(Type::VoidTyID, this); 10 | label_ty_ = std::make_unique(Type::LabelTyID, this); 11 | int1_ty_ = std::make_unique(1, this); 12 | int32_ty_ = std::make_unique(32, this); 13 | float32_ty_ = std::make_unique(this); 14 | } 15 | 16 | Type *Module::get_void_type() { return void_ty_.get(); } 17 | Type *Module::get_label_type() { return label_ty_.get(); } 18 | IntegerType *Module::get_int1_type() { return int1_ty_.get(); } 19 | IntegerType *Module::get_int32_type() { return int32_ty_.get(); } 20 | FloatType *Module::get_float_type() { return float32_ty_.get(); } 21 | PointerType *Module::get_int32_ptr_type() { 22 | return get_pointer_type(int32_ty_.get()); 23 | } 24 | PointerType *Module::get_float_ptr_type() { 25 | return get_pointer_type(float32_ty_.get()); 26 | } 27 | 28 | PointerType *Module::get_pointer_type(Type *contained) { 29 | if (pointer_map_.find(contained) == pointer_map_.end()) { 30 | pointer_map_[contained] = std::make_unique(contained); 31 | } 32 | return pointer_map_[contained].get(); 33 | } 34 | 35 | ArrayType *Module::get_array_type(Type *contained, unsigned num_elements) { 36 | if (array_map_.find({contained, num_elements}) == array_map_.end()) { 37 | array_map_[{contained, num_elements}] = 38 | std::make_unique(contained, num_elements); 39 | } 40 | return array_map_[{contained, num_elements}].get(); 41 | } 42 | 43 | FunctionType *Module::get_function_type(Type *retty, 44 | std::vector &args) { 45 | if (not function_map_.count({retty, args})) { 46 | function_map_[{retty, args}] = 47 | std::make_unique(retty, args); 48 | } 49 | return function_map_[{retty, args}].get(); 50 | } 51 | 52 | void Module::add_function(Function *f) { function_list_.push_back(f); } 53 | llvm::ilist &Module::get_functions() { return function_list_; } 54 | void Module::add_global_variable(GlobalVariable *g) { 55 | global_list_.push_back(g); 56 | } 57 | llvm::ilist &Module::get_global_variable() { 58 | return global_list_; 59 | } 60 | 61 | void Module::set_print_name() { 62 | for (auto &func : this->get_functions()) { 63 | func.set_instr_name(); 64 | } 65 | return; 66 | } 67 | 68 | std::string Module::print() { 69 | set_print_name(); 70 | std::string module_ir; 71 | for (auto &global_val : this->global_list_) { 72 | module_ir += global_val.print(); 73 | module_ir += "\n"; 74 | } 75 | for (auto &func : this->function_list_) { 76 | module_ir += func.print(); 77 | module_ir += "\n"; 78 | } 79 | return module_ir; 80 | } 81 | -------------------------------------------------------------------------------- /src/lightir/User.cpp: -------------------------------------------------------------------------------- 1 | #include "User.hpp" 2 | 3 | #include 4 | 5 | void User::set_operand(unsigned i, Value *v) { 6 | assert(i < operands_.size() && "set_operand out of index"); 7 | if (operands_[i]) { // old operand 8 | operands_[i]->remove_use(this, i); 9 | } 10 | if (v) { // new operand 11 | v->add_use(this, i); 12 | } 13 | operands_[i] = v; 14 | } 15 | 16 | void User::add_operand(Value *v) { 17 | assert(v != nullptr && "bad use: add_operand(nullptr)"); 18 | v->add_use(this, operands_.size()); 19 | operands_.push_back(v); 20 | } 21 | 22 | void User::remove_all_operands() { 23 | for (unsigned i = 0; i != operands_.size(); ++i) { 24 | if (operands_[i]) 25 | operands_[i]->remove_use(this, i); 26 | } 27 | operands_.clear(); 28 | } 29 | 30 | void User::remove_operand(unsigned idx) { 31 | assert(idx < operands_.size() && "remove_operand out of index"); 32 | // influence on other operands 33 | for (unsigned i = idx + 1; i < operands_.size(); ++i) { 34 | operands_[i]->remove_use(this, i); 35 | operands_[i]->add_use(this, i - 1); 36 | } 37 | // remove the designated operand 38 | operands_[idx]->remove_use(this, idx); 39 | operands_.erase(operands_.begin() + idx); 40 | } 41 | -------------------------------------------------------------------------------- /src/lightir/Value.cpp: -------------------------------------------------------------------------------- 1 | #include "Value.hpp" 2 | #include "Type.hpp" 3 | #include "User.hpp" 4 | 5 | #include 6 | 7 | bool Value::set_name(std::string name) { 8 | if (name_ == "") { 9 | name_ = name; 10 | return true; 11 | } 12 | return false; 13 | } 14 | 15 | void Value::add_use(User *user, unsigned arg_no) { 16 | use_list_.emplace_back(user, arg_no); 17 | }; 18 | 19 | void Value::remove_use(User *user, unsigned arg_no) { 20 | auto target_use = Use(user, arg_no); 21 | use_list_.remove_if([&](const Use &use) { return use == target_use; }); 22 | } 23 | 24 | void Value::replace_all_use_with(Value *new_val) { 25 | if (this == new_val) 26 | return; 27 | while (use_list_.size()) { 28 | auto use = use_list_.begin(); 29 | use->val_->set_operand(use->arg_no_, new_val); 30 | } 31 | } 32 | 33 | void Value::replace_use_with_if(Value *new_val, 34 | std::function should_replace) { 35 | if (this == new_val) 36 | return; 37 | for (auto iter = use_list_.begin(); iter != use_list_.end();) { 38 | auto use = *iter++; 39 | if (not should_replace(use)) 40 | continue; 41 | use.val_->set_operand(use.arg_no_, new_val); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/logging/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(test_ast test_ast.cpp) 2 | add_executable(test_logging test_logging.cpp) 3 | target_link_libraries(test_ast syntax common) 4 | target_link_libraries(test_logging common) 5 | 6 | install( 7 | TARGETS test_logging 8 | RUNTIME DESTINATION bin 9 | ) 10 | 11 | install( 12 | TARGETS test_ast 13 | RUNTIME DESTINATION bin 14 | ) 15 | -------------------------------------------------------------------------------- /src/logging/test_ast.cpp: -------------------------------------------------------------------------------- 1 | #include "ast.hpp" 2 | 3 | #include 4 | 5 | int main(int argc, char **argv) { 6 | if (argc != 2) { 7 | std::cout << "usage: " << argv[0] << " " << std::endl; 8 | } else { 9 | auto s = parse(argv[1]); 10 | auto a = AST(s); 11 | auto printer = ASTPrinter(); 12 | a.run_visitor(printer); 13 | } 14 | return 0; 15 | } 16 | -------------------------------------------------------------------------------- /src/logging/test_logging.cpp: -------------------------------------------------------------------------------- 1 | #include "logging.hpp" 2 | // 引入头文件 3 | int main() { 4 | LOG(DEBUG) << "This is DEBUG log item."; 5 | // 使用关键字LOG,括号中填入要输出的日志等级 6 | // 紧接着就是<<以及日志的具体信息,这一步就跟使用std::cout一样 7 | LOG(INFO) << "This is INFO log item"; 8 | LOG(WARNING) << "This is WARNING log item"; 9 | LOG(ERROR) << "This is ERROR log item"; 10 | 11 | return 0; 12 | } -------------------------------------------------------------------------------- /src/parser/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | flex_target(lex lexical_analyzer.l ${CMAKE_CURRENT_BINARY_DIR}/lexical_analyzer.c) 2 | bison_target(syntax syntax_analyzer.y 3 | ${CMAKE_CURRENT_BINARY_DIR}/syntax_analyzer.c 4 | DEFINES_FILE ${PROJECT_BINARY_DIR}/syntax_analyzer.h) 5 | 6 | add_flex_bison_dependency(lex syntax) 7 | add_library(syntax STATIC 8 | ${BISON_syntax_OUTPUTS} 9 | ${FLEX_lex_OUTPUTS} 10 | ) 11 | 12 | include_directories(${PROJECT_BINARY_DIR}) 13 | add_executable(parser parser.c) 14 | target_link_libraries(parser syntax common) 15 | add_executable(lexer lexer.c) 16 | target_link_libraries(lexer syntax common) 17 | 18 | install( 19 | TARGETS parser 20 | RUNTIME DESTINATION bin 21 | ) 22 | 23 | install( 24 | TARGETS lexer 25 | RUNTIME DESTINATION bin 26 | ) 27 | -------------------------------------------------------------------------------- /src/parser/lexer.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | /// 7 | extern int lines; 8 | extern int pos_start; 9 | extern int pos_end; 10 | 11 | /// 12 | extern FILE *yyin; 13 | extern char *yytext; 14 | extern int yylex(); 15 | 16 | // Mac-only hack. 17 | YYSTYPE yylval; 18 | 19 | /// 20 | int main(int argc, const char **argv) { 21 | if (argc != 2) { 22 | printf("usage: lexer input_file\n"); 23 | return 0; 24 | } 25 | 26 | const char *input_file = argv[1]; 27 | yyin = fopen(input_file, "r"); 28 | if (!yyin) { 29 | fprintf(stderr, "cannot open file: %s\n", input_file); 30 | return 1; 31 | } 32 | 33 | int token; 34 | printf("%5s\t%10s\t%s\t%s\n", "Token", "Text", "Line", "Column (Start,End)"); 35 | while ((token = yylex())) { 36 | printf("%-5d\t%10s\t%d\t(%d,%d)\n", 37 | token, yytext, 38 | lines, pos_start, pos_end); 39 | } 40 | return 0; 41 | } 42 | -------------------------------------------------------------------------------- /src/parser/lexical_analyzer.l: -------------------------------------------------------------------------------- 1 | %option noyywrap 2 | %{ 3 | /*****************声明和选项设置 begin*****************/ 4 | #include 5 | #include 6 | 7 | #include "syntax_tree.h" 8 | #include "syntax_analyzer.h" 9 | 10 | int lines=1; 11 | int pos_start=1; 12 | int pos_end=1; 13 | 14 | void pass_node(char *text){ 15 | yylval.node = new_syntax_tree_node(text); 16 | } 17 | 18 | /*****************声明和选项设置 end*****************/ 19 | 20 | %} 21 | 22 | digit [0-9] 23 | ID [a-zA-Z]+ 24 | INTEGER {digit}+ 25 | 26 | %% 27 | /* to do for students */ 28 | /* two cases for you, pass_node will send flex's token to bison */ 29 | \n {lines++;pos_start=1; pos_end = 1;} 30 | [ \t\r]+ {pos_end++;} 31 | \/\*\/*([^\/]*[^\/\*]\/[\/]*)*[^\/]*\*\/ {} 32 | \+ {pos_start = pos_end; pos_end += 1;pass_node(yytext); return ADD;} 33 | \- {pos_start = pos_end; pos_end += 1;pass_node(yytext); return SUB;} 34 | \* {pos_start = pos_end; pos_end += 1;pass_node(yytext); return MUL;} 35 | \/ {pos_start = pos_end; pos_end += 1;pass_node(yytext); return FAC;} 36 | \< {pos_start = pos_end; pos_end += 1;pass_node(yytext); return LT;} 37 | \<= {pos_start = pos_end; pos_end += 2;pass_node(yytext); return LE;} 38 | \> {pos_start = pos_end; pos_end += 1;pass_node(yytext); return GT;} 39 | \>= {pos_start = pos_end; pos_end += 2;pass_node(yytext); return GE;} 40 | \== {pos_start = pos_end; pos_end += 2;pass_node(yytext); return EQ;} 41 | \!= {pos_start = pos_end; pos_end += 2;pass_node(yytext); return NE;} 42 | \= {pos_start = pos_end; pos_end += 1;pass_node(yytext); return EQ1;} 43 | \; {pos_start = pos_end; pos_end += 1;pass_node(yytext); return FH;} 44 | \, {pos_start = pos_end; pos_end += 1;pass_node(yytext); return DH;} 45 | \( {pos_start = pos_end; pos_end += 1;pass_node(yytext); return LSK;} 46 | \) {pos_start = pos_end; pos_end += 1;pass_node(yytext); return RSK;} 47 | \[ {pos_start = pos_end; pos_end += 1;pass_node(yytext); return LMK;} 48 | \] {pos_start = pos_end; pos_end += 1;pass_node(yytext); return RMK;} 49 | \{ {pos_start = pos_end; pos_end += 1;pass_node(yytext); return LBK;} 50 | \} {pos_start = pos_end; pos_end += 1;pass_node(yytext); return RBK;} 51 | if {pos_start = pos_end;pos_end += 2;pass_node(yytext); return IF;} 52 | else {pos_start = pos_end;pos_end += 4;pass_node(yytext); return ELSE;} 53 | int {pos_start = pos_end;pos_end +=3;pass_node(yytext); return INT;} 54 | return {pos_start = pos_end; pos_end += 6;pass_node(yytext); return RETURN;} 55 | void {pos_start = pos_end; pos_end += 4; pass_node(yytext); return VOID;} 56 | while {pos_start = pos_end; pos_end += 5; pass_node(yytext); return WHILE;} 57 | float {pos_start = pos_end; pos_end += 5; pass_node(yytext); return FLOAT_TYPE;} 58 | {ID} {pos_start = pos_end; pos_end += yyleng; pass_node(yytext); return id;} 59 | {INTEGER} {pos_start = pos_end; pos_end += yyleng; pass_node(yytext); return int_num;} 60 | [0-9]*\.[0-9]+ {pos_start = pos_end; pos_end += yyleng;pass_node(yytext); return float_num;} 61 | [0-9]+\. {pos_start = pos_end; pos_end += yyleng;pass_node(yytext); return float_num;} 62 | . { pos_start = pos_end; pos_end++; return ERROR; } 63 | /****请在此补全所有flex的模式与动作 end******/ 64 | %% 65 | -------------------------------------------------------------------------------- /src/parser/parser.c: -------------------------------------------------------------------------------- 1 | #include "syntax_tree.h" 2 | extern syntax_tree *parse(const char*); 3 | 4 | int main(int argc, char *argv[]) 5 | { 6 | syntax_tree *tree = NULL; 7 | const char *input = NULL; 8 | 9 | if (argc == 2) { 10 | input = argv[1]; 11 | } else if(argc >= 3) { 12 | printf("usage: %s \n", argv[0]); 13 | return 1; 14 | } 15 | 16 | // Call the syntax analyzer. 17 | tree = parse(input); 18 | print_syntax_tree(stdout, tree); 19 | del_syntax_tree(tree); 20 | return 0; 21 | } 22 | -------------------------------------------------------------------------------- /src/passes/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_library( 2 | opt_lib STATIC 3 | Dominators.cpp 4 | Mem2Reg.cpp 5 | FuncInfo.cpp 6 | DeadCode.cpp 7 | ) 8 | -------------------------------------------------------------------------------- /src/passes/DeadCode.cpp: -------------------------------------------------------------------------------- 1 | #include "DeadCode.hpp" 2 | #include "logging.hpp" 3 | 4 | // 处理流程:两趟处理,mark 标记有用变量,sweep 删除无用指令 5 | void DeadCode::run() { 6 | bool changed{}; 7 | func_info->run(); 8 | do { 9 | changed = false; 10 | for (auto &F : m_->get_functions()) { 11 | auto func = &F; 12 | mark(func); 13 | changed |= sweep(func); 14 | } 15 | } while (changed); 16 | LOG_INFO << "dead code pass erased " << ins_count << " instructions"; 17 | } 18 | 19 | void DeadCode::mark(Function *func) { 20 | work_list.clear(); 21 | marked.clear(); 22 | 23 | for (auto &bb : func->get_basic_blocks()) { 24 | for (auto &ins : bb.get_instructions()) { 25 | if (is_critical(&ins)) { 26 | marked[&ins] = true; 27 | work_list.push_back(&ins); 28 | } 29 | } 30 | } 31 | 32 | while (work_list.empty() == false) { 33 | auto now = work_list.front(); 34 | work_list.pop_front(); 35 | 36 | mark(now); 37 | } 38 | } 39 | 40 | void DeadCode::mark(Instruction *ins) { 41 | for (auto op : ins->get_operands()) { 42 | auto def = dynamic_cast(op); 43 | if (def == nullptr) 44 | continue; 45 | if (marked[def]) 46 | continue; 47 | if (def->get_function() != ins->get_function()) 48 | continue; 49 | marked[def] = true; 50 | work_list.push_back(def); 51 | } 52 | } 53 | 54 | bool DeadCode::sweep(Function *func) { 55 | std::unordered_set wait_del{}; 56 | for (auto &bb : func->get_basic_blocks()) { 57 | for (auto it = bb.get_instructions().begin(); 58 | it != bb.get_instructions().end();) { 59 | if (marked[&*it]) { 60 | ++it; 61 | continue; 62 | } else { 63 | auto tmp = &*it; 64 | wait_del.insert(tmp); 65 | it++; 66 | } 67 | } 68 | } 69 | for (auto inst : wait_del) 70 | inst->remove_all_operands(); 71 | for (auto inst : wait_del) 72 | inst->get_parent()->get_instructions().erase(inst); 73 | ins_count += wait_del.size(); 74 | return not wait_del.empty(); // changed 75 | } 76 | 77 | bool DeadCode::is_critical(Instruction *ins) { 78 | // 对纯函数的无用调用也可以在删除之列 79 | if (ins->is_call()) { 80 | auto call_inst = dynamic_cast(ins); 81 | auto callee = dynamic_cast(call_inst->get_operand(0)); 82 | if (func_info->is_pure_function(callee)) 83 | return false; 84 | return true; 85 | } 86 | if (ins->is_br() || ins->is_ret()) 87 | return true; 88 | if (ins->is_store()) 89 | return true; 90 | return false; 91 | } 92 | -------------------------------------------------------------------------------- /tests/1-parser/cleanup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | rm -rf output_student/* 3 | -------------------------------------------------------------------------------- /tests/1-parser/eval_lab1.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # DO NOT MODIFY! 4 | # If you need customized behavior, please create your own script. 5 | 6 | if [[ $# -lt 1 ]]; then 7 | echo "usage: ./eval_lab1.sh []" 8 | echo " can be one of 'easy', 'normal', 'hard', and 'testcases_general'." 9 | echo " can be one of 'no', 'yes', and 'verbose'. the default value is 'no'" 10 | exit 1 11 | fi 12 | CUR_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" 13 | TESTCASE="${1:-testcase}" 14 | if [[ $TESTCASE == 'easy' || $TESTCASE == 'normal' || $TESTCASE == 'hard' ]]; then 15 | TESTCASE_DIR="$CUR_DIR/input/$TESTCASE" 16 | elif [[ $TESTCASE == 'testcases_general' ]]; then 17 | TESTCASE_DIR="$CUR_DIR/../$TESTCASE" 18 | fi 19 | OUTPUT_DIR="$CUR_DIR/output_student/$TESTCASE" 20 | OUTPUT_STD_DIR="$CUR_DIR/output_standard/$TESTCASE" 21 | BUILD_DIR="$CUR_DIR/../../build" 22 | 23 | # Make sure $OUTPUT_DIR exists. 24 | mkdir -p "$OUTPUT_DIR" 25 | 26 | # Generate a .syntax_tree file for all .cminus files in the testcase dir. 27 | SAVEIFS=$IFS 28 | IFS=$(echo -en "\n\b") 29 | for testcase in "$TESTCASE_DIR"/*.cminus 30 | do 31 | filename="$(basename $testcase)" 32 | echo "[info] Analyzing $filename" 33 | "$BUILD_DIR"/parser "$testcase" > "$OUTPUT_DIR/${filename%.cminus}.syntax_tree" 34 | done 35 | 36 | # Output a summary when requested. 37 | if [[ ${2:-no} != "no" ]]; then 38 | echo "[info] Comparing..." 39 | if [[ ${2:-no} == "verbose" ]]; then 40 | diff "$OUTPUT_DIR" "$OUTPUT_STD_DIR" 41 | else 42 | diff -qr "$OUTPUT_DIR" "$OUTPUT_STD_DIR" 43 | fi 44 | if [ $? -eq 0 ]; then 45 | echo "[info] No difference! Congratulations!" 46 | fi 47 | fi 48 | 49 | IFS=$SAVEIFS 50 | -------------------------------------------------------------------------------- /tests/1-parser/input/easy/FAIL_comment.cminus: -------------------------------------------------------------------------------- 1 | /* unclosed comment -------------------------------------------------------------------------------- /tests/1-parser/input/easy/FAIL_comment2.cminus: -------------------------------------------------------------------------------- 1 | // cminus dont support comment like that 2 | 3 | int main(void){ 4 | return 0; 5 | } -------------------------------------------------------------------------------- /tests/1-parser/input/easy/FAIL_function.cminus: -------------------------------------------------------------------------------- 1 | /* unclosed function */ 2 | int main(void) 3 | { -------------------------------------------------------------------------------- /tests/1-parser/input/easy/FAIL_id.cminus: -------------------------------------------------------------------------------- 1 | int a1; 2 | int f1(void) {} 3 | int f2(void) {} 4 | -------------------------------------------------------------------------------- /tests/1-parser/input/easy/expr.cminus: -------------------------------------------------------------------------------- 1 | /*Basic num part*/ 2 | int main(void){ 3 | a = 0; 4 | 5 | x = 0.0; 6 | x = 1.; 7 | x = .1; 8 | 9 | a = 1+1; 10 | a = a-1; 11 | 12 | x = x*1; 13 | x = a/x; 14 | 15 | return 0; 16 | } -------------------------------------------------------------------------------- /tests/1-parser/input/easy/id.cminus: -------------------------------------------------------------------------------- 1 | int a; 2 | int f(void) {} 3 | int g(void) {} 4 | -------------------------------------------------------------------------------- /tests/1-parser/input/hard/You_Should_Pass.cminus: -------------------------------------------------------------------------------- 1 | /* 2 | I konw it's weird, even stupid, to code C like this. w(゚Д゚)w 3 | HOWEVER, we have to use some tricky cases to test your answer. 4 | */ 5 | 6 | float GVAR; 7 | void NeverEverDeclareLikeThis; 8 | int GARRAY[2333]; 9 | 10 | void MyFuncA(int floatNum, float intNum, void voidNums[]){ 11 | int IKnowYouAreVoid; 12 | return MyFuncB(IKnowYouAreVoid); 13 | } 14 | 15 | float MyFuncB(void){ 16 | int IAmVoid[0]; 17 | return MyFuncA(.0, 0, IAmVoid); 18 | } 19 | 20 | int main(void){ 21 | 22 | int a; int b; int c; 23 | 24 | a = b = c = (85 == 84 + 0.4); 25 | 26 | if(a = b){ 27 | GARRAY[ ( MyFuncB() ) ] = GARRAY[c = 1.*.1 == 1.1]; 28 | }else if (MyFuncC(NotDeclared)){ 29 | 30 | }else; 31 | 32 | return 0.; 33 | } -------------------------------------------------------------------------------- /tests/1-parser/input/hard/assoc.cminus: -------------------------------------------------------------------------------- 1 | /* associativity and precedence */ 2 | int main(void) 3 | { 4 | a = b = c = 1 + 1 / 2 * 1 * (1 + 1 + 1 - 1 / 1) + 3 + 4 * 3; 5 | } 6 | -------------------------------------------------------------------------------- /tests/1-parser/input/hard/gcd.cminus: -------------------------------------------------------------------------------- 1 | int gcd (int u, int v) { /* calculate the gcd of u and v */ 2 | if (v == 0) return u; 3 | else return gcd(v, u - u / v * v); /* v,u-u/v*v is equals to u mod v*/ 4 | } 5 | int main(void) { 6 | int x; int y; int temp; 7 | x = 72; 8 | y = 18; 9 | if (x 0) { 22 | hanoi(getint(), 1, 2, 3); 23 | putch(10); 24 | n = n - 1; 25 | } 26 | return 0; 27 | } 28 | -------------------------------------------------------------------------------- /tests/1-parser/input/hard/if.cminus: -------------------------------------------------------------------------------- 1 | /* else should be bound to the closest if */ 2 | int main(void) 3 | { 4 | if (1) {} else if (2) {} else {} 5 | return 0; 6 | } 7 | -------------------------------------------------------------------------------- /tests/1-parser/input/hard/selectionsort.cminus: -------------------------------------------------------------------------------- 1 | /* this is the sample program in C- in the book "Compiler Construction" */ 2 | /* A program to perform selection sort on a 10 element array. */ 3 | int x[10]; 4 | int minloc ( int a[], int low, int high ) 5 | { int i; int x; int k; 6 | k = low; 7 | x = a[low]; 8 | i = low + 1; 9 | while (i < high) 10 | { if (a[i] < x) 11 | { x = a[i]; 12 | k = i; } 13 | i = i + 1; 14 | } 15 | return k; 16 | } 17 | 18 | void sort( int a[], int low, int high) 19 | { int i; int k; 20 | i = low; 21 | while ( i < high-1) 22 | { int t; 23 | k = minloc(a, i, high); 24 | t = a[k]; 25 | a[k] = a[i]; 26 | a[i] = t; 27 | i = i + 1; 28 | } 29 | } 30 | 31 | void main(void) 32 | { int i; 33 | i = 0; 34 | while ( i < 10) 35 | { x[i] = input(); 36 | i = i + 1; } 37 | sort(x, 0, 10); 38 | i = 0; 39 | while (i < 10) 40 | { output(x[i]); 41 | i = i + 1; } 42 | } 43 | -------------------------------------------------------------------------------- /tests/1-parser/input/normal/FAIL_assign.cminus: -------------------------------------------------------------------------------- 1 | int main(void) 2 | { 3 | a=1; 4 | 1=a; 5 | } 6 | -------------------------------------------------------------------------------- /tests/1-parser/input/normal/FAIL_local-decl.cminus: -------------------------------------------------------------------------------- 1 | int main(void){ 2 | int a; 3 | a = 1; 4 | int b; 5 | return 0; 6 | } -------------------------------------------------------------------------------- /tests/1-parser/input/normal/array.cminus: -------------------------------------------------------------------------------- 1 | int main(void) { 2 | int array[1]; 3 | array[1] = 0; 4 | return 0; 5 | } 6 | -------------------------------------------------------------------------------- /tests/1-parser/input/normal/func.cminus: -------------------------------------------------------------------------------- 1 | float foo(float a, float b[]) { 2 | return 1; 3 | } 4 | 5 | int main(void) { 6 | return 0; 7 | } 8 | -------------------------------------------------------------------------------- /tests/1-parser/input/normal/if.cminus: -------------------------------------------------------------------------------- 1 | /*Basic selection part*/ 2 | 3 | int main(void){ 4 | int a; int b; 5 | 6 | a = 1; 7 | b = 1; 8 | 9 | if(a != b){ 10 | if(a == b); 11 | else{ 12 | a = b; 13 | } 14 | } 15 | 16 | return 0; 17 | } -------------------------------------------------------------------------------- /tests/1-parser/input/normal/local-decl.cminus: -------------------------------------------------------------------------------- 1 | int main(void) { 2 | int i; float j; 3 | void v; 4 | return 0; 5 | } 6 | -------------------------------------------------------------------------------- /tests/1-parser/input/normal/skip_spaces.cminus: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | int main() { 4 | int arr[100]; 5 | int i; 6 | int sum; 7 | i = 0; 8 | sum = 0; 9 | while (getint()) { 10 | arr[i] = getint(); 11 | i = i + 1; 12 | }*/ 13 | int main(void) { 14 | int arr[100]; 15 | int i; 16 | int sum; 17 | i = 0; 18 | sum = 0; 19 | while (getint()) { 20 | arr[i] = getint(); 21 | i = i + 1; 22 | } 23 | while (i) { 24 | i = i - 1; 25 | sum = sum + arr[i]; 26 | } 27 | return sum - 79; 28 | } 29 | -------------------------------------------------------------------------------- /tests/1-parser/output_standard/easy/FAIL_comment.syntax_tree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WeithWu/USTC-2023-compilers-lab/fe8679e378701951a8a688acba125b1c6ae5ab3e/tests/1-parser/output_standard/easy/FAIL_comment.syntax_tree -------------------------------------------------------------------------------- /tests/1-parser/output_standard/easy/FAIL_comment2.syntax_tree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WeithWu/USTC-2023-compilers-lab/fe8679e378701951a8a688acba125b1c6ae5ab3e/tests/1-parser/output_standard/easy/FAIL_comment2.syntax_tree -------------------------------------------------------------------------------- /tests/1-parser/output_standard/easy/FAIL_function.syntax_tree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WeithWu/USTC-2023-compilers-lab/fe8679e378701951a8a688acba125b1c6ae5ab3e/tests/1-parser/output_standard/easy/FAIL_function.syntax_tree -------------------------------------------------------------------------------- /tests/1-parser/output_standard/easy/FAIL_id.syntax_tree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WeithWu/USTC-2023-compilers-lab/fe8679e378701951a8a688acba125b1c6ae5ab3e/tests/1-parser/output_standard/easy/FAIL_id.syntax_tree -------------------------------------------------------------------------------- /tests/1-parser/output_standard/easy/id.syntax_tree: -------------------------------------------------------------------------------- 1 | >--+ program 2 | | >--+ declaration-list 3 | | | >--+ declaration-list 4 | | | | >--+ declaration-list 5 | | | | | >--+ declaration 6 | | | | | | >--+ var-declaration 7 | | | | | | | >--+ type-specifier 8 | | | | | | | | >--* int 9 | | | | | | | >--* a 10 | | | | | | | >--* ; 11 | | | | >--+ declaration 12 | | | | | >--+ fun-declaration 13 | | | | | | >--+ type-specifier 14 | | | | | | | >--* int 15 | | | | | | >--* f 16 | | | | | | >--* ( 17 | | | | | | >--+ params 18 | | | | | | | >--* void 19 | | | | | | >--* ) 20 | | | | | | >--+ compound-stmt 21 | | | | | | | >--* { 22 | | | | | | | >--+ local-declarations 23 | | | | | | | | >--* epsilon 24 | | | | | | | >--+ statement-list 25 | | | | | | | | >--* epsilon 26 | | | | | | | >--* } 27 | | | >--+ declaration 28 | | | | >--+ fun-declaration 29 | | | | | >--+ type-specifier 30 | | | | | | >--* int 31 | | | | | >--* g 32 | | | | | >--* ( 33 | | | | | >--+ params 34 | | | | | | >--* void 35 | | | | | >--* ) 36 | | | | | >--+ compound-stmt 37 | | | | | | >--* { 38 | | | | | | >--+ local-declarations 39 | | | | | | | >--* epsilon 40 | | | | | | >--+ statement-list 41 | | | | | | | >--* epsilon 42 | | | | | | >--* } 43 | -------------------------------------------------------------------------------- /tests/1-parser/output_standard/normal/FAIL_assign.syntax_tree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WeithWu/USTC-2023-compilers-lab/fe8679e378701951a8a688acba125b1c6ae5ab3e/tests/1-parser/output_standard/normal/FAIL_assign.syntax_tree -------------------------------------------------------------------------------- /tests/1-parser/output_standard/normal/FAIL_local-decl.syntax_tree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WeithWu/USTC-2023-compilers-lab/fe8679e378701951a8a688acba125b1c6ae5ab3e/tests/1-parser/output_standard/normal/FAIL_local-decl.syntax_tree -------------------------------------------------------------------------------- /tests/1-parser/output_standard/normal/array.syntax_tree: -------------------------------------------------------------------------------- 1 | >--+ program 2 | | >--+ declaration-list 3 | | | >--+ declaration 4 | | | | >--+ fun-declaration 5 | | | | | >--+ type-specifier 6 | | | | | | >--* int 7 | | | | | >--* main 8 | | | | | >--* ( 9 | | | | | >--+ params 10 | | | | | | >--* void 11 | | | | | >--* ) 12 | | | | | >--+ compound-stmt 13 | | | | | | >--* { 14 | | | | | | >--+ local-declarations 15 | | | | | | | >--+ local-declarations 16 | | | | | | | | >--* epsilon 17 | | | | | | | >--+ var-declaration 18 | | | | | | | | >--+ type-specifier 19 | | | | | | | | | >--* int 20 | | | | | | | | >--* array 21 | | | | | | | | >--* [ 22 | | | | | | | | >--* 1 23 | | | | | | | | >--* ] 24 | | | | | | | | >--* ; 25 | | | | | | >--+ statement-list 26 | | | | | | | >--+ statement-list 27 | | | | | | | | >--+ statement-list 28 | | | | | | | | | >--* epsilon 29 | | | | | | | | >--+ statement 30 | | | | | | | | | >--+ expression-stmt 31 | | | | | | | | | | >--+ expression 32 | | | | | | | | | | | >--+ var 33 | | | | | | | | | | | | >--* array 34 | | | | | | | | | | | | >--* [ 35 | | | | | | | | | | | | >--+ expression 36 | | | | | | | | | | | | | >--+ simple-expression 37 | | | | | | | | | | | | | | >--+ additive-expression 38 | | | | | | | | | | | | | | | >--+ term 39 | | | | | | | | | | | | | | | | >--+ factor 40 | | | | | | | | | | | | | | | | | >--+ integer 41 | | | | | | | | | | | | | | | | | | >--* 1 42 | | | | | | | | | | | | >--* ] 43 | | | | | | | | | | | >--* = 44 | | | | | | | | | | | >--+ expression 45 | | | | | | | | | | | | >--+ simple-expression 46 | | | | | | | | | | | | | >--+ additive-expression 47 | | | | | | | | | | | | | | >--+ term 48 | | | | | | | | | | | | | | | >--+ factor 49 | | | | | | | | | | | | | | | | >--+ integer 50 | | | | | | | | | | | | | | | | | >--* 0 51 | | | | | | | | | | >--* ; 52 | | | | | | | >--+ statement 53 | | | | | | | | >--+ return-stmt 54 | | | | | | | | | >--* return 55 | | | | | | | | | >--+ expression 56 | | | | | | | | | | >--+ simple-expression 57 | | | | | | | | | | | >--+ additive-expression 58 | | | | | | | | | | | | >--+ term 59 | | | | | | | | | | | | | >--+ factor 60 | | | | | | | | | | | | | | >--+ integer 61 | | | | | | | | | | | | | | | >--* 0 62 | | | | | | | | | >--* ; 63 | | | | | | >--* } 64 | -------------------------------------------------------------------------------- /tests/1-parser/output_standard/normal/func.syntax_tree: -------------------------------------------------------------------------------- 1 | >--+ program 2 | | >--+ declaration-list 3 | | | >--+ declaration-list 4 | | | | >--+ declaration 5 | | | | | >--+ fun-declaration 6 | | | | | | >--+ type-specifier 7 | | | | | | | >--* float 8 | | | | | | >--* foo 9 | | | | | | >--* ( 10 | | | | | | >--+ params 11 | | | | | | | >--+ param-list 12 | | | | | | | | >--+ param-list 13 | | | | | | | | | >--+ param 14 | | | | | | | | | | >--+ type-specifier 15 | | | | | | | | | | | >--* float 16 | | | | | | | | | | >--* a 17 | | | | | | | | >--* , 18 | | | | | | | | >--+ param 19 | | | | | | | | | >--+ type-specifier 20 | | | | | | | | | | >--* float 21 | | | | | | | | | >--* b 22 | | | | | | | | | >--* [ 23 | | | | | | | | | >--* ] 24 | | | | | | >--* ) 25 | | | | | | >--+ compound-stmt 26 | | | | | | | >--* { 27 | | | | | | | >--+ local-declarations 28 | | | | | | | | >--* epsilon 29 | | | | | | | >--+ statement-list 30 | | | | | | | | >--+ statement-list 31 | | | | | | | | | >--* epsilon 32 | | | | | | | | >--+ statement 33 | | | | | | | | | >--+ return-stmt 34 | | | | | | | | | | >--* return 35 | | | | | | | | | | >--+ expression 36 | | | | | | | | | | | >--+ simple-expression 37 | | | | | | | | | | | | >--+ additive-expression 38 | | | | | | | | | | | | | >--+ term 39 | | | | | | | | | | | | | | >--+ factor 40 | | | | | | | | | | | | | | | >--+ integer 41 | | | | | | | | | | | | | | | | >--* 1 42 | | | | | | | | | | >--* ; 43 | | | | | | | >--* } 44 | | | >--+ declaration 45 | | | | >--+ fun-declaration 46 | | | | | >--+ type-specifier 47 | | | | | | >--* int 48 | | | | | >--* main 49 | | | | | >--* ( 50 | | | | | >--+ params 51 | | | | | | >--* void 52 | | | | | >--* ) 53 | | | | | >--+ compound-stmt 54 | | | | | | >--* { 55 | | | | | | >--+ local-declarations 56 | | | | | | | >--* epsilon 57 | | | | | | >--+ statement-list 58 | | | | | | | >--+ statement-list 59 | | | | | | | | >--* epsilon 60 | | | | | | | >--+ statement 61 | | | | | | | | >--+ return-stmt 62 | | | | | | | | | >--* return 63 | | | | | | | | | >--+ expression 64 | | | | | | | | | | >--+ simple-expression 65 | | | | | | | | | | | >--+ additive-expression 66 | | | | | | | | | | | | >--+ term 67 | | | | | | | | | | | | | >--+ factor 68 | | | | | | | | | | | | | | >--+ integer 69 | | | | | | | | | | | | | | | >--* 0 70 | | | | | | | | | >--* ; 71 | | | | | | >--* } 72 | -------------------------------------------------------------------------------- /tests/1-parser/output_standard/normal/local-decl.syntax_tree: -------------------------------------------------------------------------------- 1 | >--+ program 2 | | >--+ declaration-list 3 | | | >--+ declaration 4 | | | | >--+ fun-declaration 5 | | | | | >--+ type-specifier 6 | | | | | | >--* int 7 | | | | | >--* main 8 | | | | | >--* ( 9 | | | | | >--+ params 10 | | | | | | >--* void 11 | | | | | >--* ) 12 | | | | | >--+ compound-stmt 13 | | | | | | >--* { 14 | | | | | | >--+ local-declarations 15 | | | | | | | >--+ local-declarations 16 | | | | | | | | >--+ local-declarations 17 | | | | | | | | | >--+ local-declarations 18 | | | | | | | | | | >--* epsilon 19 | | | | | | | | | >--+ var-declaration 20 | | | | | | | | | | >--+ type-specifier 21 | | | | | | | | | | | >--* int 22 | | | | | | | | | | >--* i 23 | | | | | | | | | | >--* ; 24 | | | | | | | | >--+ var-declaration 25 | | | | | | | | | >--+ type-specifier 26 | | | | | | | | | | >--* float 27 | | | | | | | | | >--* j 28 | | | | | | | | | >--* ; 29 | | | | | | | >--+ var-declaration 30 | | | | | | | | >--+ type-specifier 31 | | | | | | | | | >--* void 32 | | | | | | | | >--* v 33 | | | | | | | | >--* ; 34 | | | | | | >--+ statement-list 35 | | | | | | | >--+ statement-list 36 | | | | | | | | >--* epsilon 37 | | | | | | | >--+ statement 38 | | | | | | | | >--+ return-stmt 39 | | | | | | | | | >--* return 40 | | | | | | | | | >--+ expression 41 | | | | | | | | | | >--+ simple-expression 42 | | | | | | | | | | | >--+ additive-expression 43 | | | | | | | | | | | | >--+ term 44 | | | | | | | | | | | | | >--+ factor 45 | | | | | | | | | | | | | | >--+ integer 46 | | | | | | | | | | | | | | | >--* 0 47 | | | | | | | | | >--* ; 48 | | | | | | >--* } 49 | 50 | -------------------------------------------------------------------------------- /tests/1-parser/output_standard/testcases_general/1-return.syntax_tree: -------------------------------------------------------------------------------- 1 | >--+ program 2 | | >--+ declaration-list 3 | | | >--+ declaration 4 | | | | >--+ fun-declaration 5 | | | | | >--+ type-specifier 6 | | | | | | >--* void 7 | | | | | >--* main 8 | | | | | >--* ( 9 | | | | | >--+ params 10 | | | | | | >--* void 11 | | | | | >--* ) 12 | | | | | >--+ compound-stmt 13 | | | | | | >--* { 14 | | | | | | >--+ local-declarations 15 | | | | | | | >--* epsilon 16 | | | | | | >--+ statement-list 17 | | | | | | | >--+ statement-list 18 | | | | | | | | >--* epsilon 19 | | | | | | | >--+ statement 20 | | | | | | | | >--+ return-stmt 21 | | | | | | | | | >--* return 22 | | | | | | | | | >--* ; 23 | | | | | | >--* } 24 | -------------------------------------------------------------------------------- /tests/1-parser/output_standard/testcases_general/18-global_var.syntax_tree: -------------------------------------------------------------------------------- 1 | >--+ program 2 | | >--+ declaration-list 3 | | | >--+ declaration-list 4 | | | | >--+ declaration 5 | | | | | >--+ var-declaration 6 | | | | | | >--+ type-specifier 7 | | | | | | | >--* int 8 | | | | | | >--* a 9 | | | | | | >--* ; 10 | | | >--+ declaration 11 | | | | >--+ fun-declaration 12 | | | | | >--+ type-specifier 13 | | | | | | >--* int 14 | | | | | >--* main 15 | | | | | >--* ( 16 | | | | | >--+ params 17 | | | | | | >--* void 18 | | | | | >--* ) 19 | | | | | >--+ compound-stmt 20 | | | | | | >--* { 21 | | | | | | >--+ local-declarations 22 | | | | | | | >--* epsilon 23 | | | | | | >--+ statement-list 24 | | | | | | | >--+ statement-list 25 | | | | | | | | >--+ statement-list 26 | | | | | | | | | >--* epsilon 27 | | | | | | | | >--+ statement 28 | | | | | | | | | >--+ expression-stmt 29 | | | | | | | | | | >--+ expression 30 | | | | | | | | | | | >--+ var 31 | | | | | | | | | | | | >--* a 32 | | | | | | | | | | | >--* = 33 | | | | | | | | | | | >--+ expression 34 | | | | | | | | | | | | >--+ simple-expression 35 | | | | | | | | | | | | | >--+ additive-expression 36 | | | | | | | | | | | | | | >--+ term 37 | | | | | | | | | | | | | | | >--+ factor 38 | | | | | | | | | | | | | | | | >--+ integer 39 | | | | | | | | | | | | | | | | | >--* 10 40 | | | | | | | | | | >--* ; 41 | | | | | | | >--+ statement 42 | | | | | | | | >--+ return-stmt 43 | | | | | | | | | >--* return 44 | | | | | | | | | >--+ expression 45 | | | | | | | | | | >--+ simple-expression 46 | | | | | | | | | | | >--+ additive-expression 47 | | | | | | | | | | | | >--+ term 48 | | | | | | | | | | | | | >--+ factor 49 | | | | | | | | | | | | | | >--+ var 50 | | | | | | | | | | | | | | | >--* a 51 | | | | | | | | | >--* ; 52 | | | | | | >--* } 53 | -------------------------------------------------------------------------------- /tests/1-parser/output_standard/testcases_general/2-decl_int.syntax_tree: -------------------------------------------------------------------------------- 1 | >--+ program 2 | | >--+ declaration-list 3 | | | >--+ declaration 4 | | | | >--+ fun-declaration 5 | | | | | >--+ type-specifier 6 | | | | | | >--* void 7 | | | | | >--* main 8 | | | | | >--* ( 9 | | | | | >--+ params 10 | | | | | | >--* void 11 | | | | | >--* ) 12 | | | | | >--+ compound-stmt 13 | | | | | | >--* { 14 | | | | | | >--+ local-declarations 15 | | | | | | | >--+ local-declarations 16 | | | | | | | | >--* epsilon 17 | | | | | | | >--+ var-declaration 18 | | | | | | | | >--+ type-specifier 19 | | | | | | | | | >--* int 20 | | | | | | | | >--* a 21 | | | | | | | | >--* ; 22 | | | | | | >--+ statement-list 23 | | | | | | | >--+ statement-list 24 | | | | | | | | >--* epsilon 25 | | | | | | | >--+ statement 26 | | | | | | | | >--+ return-stmt 27 | | | | | | | | | >--* return 28 | | | | | | | | | >--* ; 29 | | | | | | >--* } 30 | -------------------------------------------------------------------------------- /tests/1-parser/output_standard/testcases_general/21-comment.syntax_tree: -------------------------------------------------------------------------------- 1 | >--+ program 2 | | >--+ declaration-list 3 | | | >--+ declaration 4 | | | | >--+ fun-declaration 5 | | | | | >--+ type-specifier 6 | | | | | | >--* void 7 | | | | | >--* main 8 | | | | | >--* ( 9 | | | | | >--+ params 10 | | | | | | >--* void 11 | | | | | >--* ) 12 | | | | | >--+ compound-stmt 13 | | | | | | >--* { 14 | | | | | | >--+ local-declarations 15 | | | | | | | >--* epsilon 16 | | | | | | >--+ statement-list 17 | | | | | | | >--+ statement-list 18 | | | | | | | | >--* epsilon 19 | | | | | | | >--+ statement 20 | | | | | | | | >--+ return-stmt 21 | | | | | | | | | >--* return 22 | | | | | | | | | >--* ; 23 | | | | | | >--* } 24 | -------------------------------------------------------------------------------- /tests/1-parser/output_standard/testcases_general/3-decl_float.syntax_tree: -------------------------------------------------------------------------------- 1 | >--+ program 2 | | >--+ declaration-list 3 | | | >--+ declaration 4 | | | | >--+ fun-declaration 5 | | | | | >--+ type-specifier 6 | | | | | | >--* void 7 | | | | | >--* main 8 | | | | | >--* ( 9 | | | | | >--+ params 10 | | | | | | >--* void 11 | | | | | >--* ) 12 | | | | | >--+ compound-stmt 13 | | | | | | >--* { 14 | | | | | | >--+ local-declarations 15 | | | | | | | >--+ local-declarations 16 | | | | | | | | >--* epsilon 17 | | | | | | | >--+ var-declaration 18 | | | | | | | | >--+ type-specifier 19 | | | | | | | | | >--* float 20 | | | | | | | | >--* a 21 | | | | | | | | >--* ; 22 | | | | | | >--+ statement-list 23 | | | | | | | >--+ statement-list 24 | | | | | | | | >--* epsilon 25 | | | | | | | >--+ statement 26 | | | | | | | | >--+ return-stmt 27 | | | | | | | | | >--* return 28 | | | | | | | | | >--* ; 29 | | | | | | >--* } 30 | -------------------------------------------------------------------------------- /tests/1-parser/output_standard/testcases_general/4-decl_int_array.syntax_tree: -------------------------------------------------------------------------------- 1 | >--+ program 2 | | >--+ declaration-list 3 | | | >--+ declaration 4 | | | | >--+ fun-declaration 5 | | | | | >--+ type-specifier 6 | | | | | | >--* void 7 | | | | | >--* main 8 | | | | | >--* ( 9 | | | | | >--+ params 10 | | | | | | >--* void 11 | | | | | >--* ) 12 | | | | | >--+ compound-stmt 13 | | | | | | >--* { 14 | | | | | | >--+ local-declarations 15 | | | | | | | >--+ local-declarations 16 | | | | | | | | >--* epsilon 17 | | | | | | | >--+ var-declaration 18 | | | | | | | | >--+ type-specifier 19 | | | | | | | | | >--* int 20 | | | | | | | | >--* a 21 | | | | | | | | >--* [ 22 | | | | | | | | >--* 10 23 | | | | | | | | >--* ] 24 | | | | | | | | >--* ; 25 | | | | | | >--+ statement-list 26 | | | | | | | >--+ statement-list 27 | | | | | | | | >--* epsilon 28 | | | | | | | >--+ statement 29 | | | | | | | | >--+ return-stmt 30 | | | | | | | | | >--* return 31 | | | | | | | | | >--* ; 32 | | | | | | >--* } 33 | -------------------------------------------------------------------------------- /tests/1-parser/output_standard/testcases_general/5-decl_float_array.syntax_tree: -------------------------------------------------------------------------------- 1 | >--+ program 2 | | >--+ declaration-list 3 | | | >--+ declaration 4 | | | | >--+ fun-declaration 5 | | | | | >--+ type-specifier 6 | | | | | | >--* void 7 | | | | | >--* main 8 | | | | | >--* ( 9 | | | | | >--+ params 10 | | | | | | >--* void 11 | | | | | >--* ) 12 | | | | | >--+ compound-stmt 13 | | | | | | >--* { 14 | | | | | | >--+ local-declarations 15 | | | | | | | >--+ local-declarations 16 | | | | | | | | >--* epsilon 17 | | | | | | | >--+ var-declaration 18 | | | | | | | | >--+ type-specifier 19 | | | | | | | | | >--* float 20 | | | | | | | | >--* a 21 | | | | | | | | >--* [ 22 | | | | | | | | >--* 10 23 | | | | | | | | >--* ] 24 | | | | | | | | >--* ; 25 | | | | | | >--+ statement-list 26 | | | | | | | >--+ statement-list 27 | | | | | | | | >--* epsilon 28 | | | | | | | >--+ statement 29 | | | | | | | | >--+ return-stmt 30 | | | | | | | | | >--* return 31 | | | | | | | | | >--* ; 32 | | | | | | >--* } 33 | -------------------------------------------------------------------------------- /tests/1-parser/output_standard/testcases_general/6-num_add_int.syntax_tree: -------------------------------------------------------------------------------- 1 | >--+ program 2 | | >--+ declaration-list 3 | | | >--+ declaration 4 | | | | >--+ fun-declaration 5 | | | | | >--+ type-specifier 6 | | | | | | >--* int 7 | | | | | >--* main 8 | | | | | >--* ( 9 | | | | | >--+ params 10 | | | | | | >--* void 11 | | | | | >--* ) 12 | | | | | >--+ compound-stmt 13 | | | | | | >--* { 14 | | | | | | >--+ local-declarations 15 | | | | | | | >--+ local-declarations 16 | | | | | | | | >--* epsilon 17 | | | | | | | >--+ var-declaration 18 | | | | | | | | >--+ type-specifier 19 | | | | | | | | | >--* int 20 | | | | | | | | >--* a 21 | | | | | | | | >--* ; 22 | | | | | | >--+ statement-list 23 | | | | | | | >--+ statement-list 24 | | | | | | | | >--+ statement-list 25 | | | | | | | | | >--* epsilon 26 | | | | | | | | >--+ statement 27 | | | | | | | | | >--+ expression-stmt 28 | | | | | | | | | | >--+ expression 29 | | | | | | | | | | | >--+ var 30 | | | | | | | | | | | | >--* a 31 | | | | | | | | | | | >--* = 32 | | | | | | | | | | | >--+ expression 33 | | | | | | | | | | | | >--+ simple-expression 34 | | | | | | | | | | | | | >--+ additive-expression 35 | | | | | | | | | | | | | | >--+ additive-expression 36 | | | | | | | | | | | | | | | >--+ term 37 | | | | | | | | | | | | | | | | >--+ factor 38 | | | | | | | | | | | | | | | | | >--+ integer 39 | | | | | | | | | | | | | | | | | | >--* 1000 40 | | | | | | | | | | | | | | >--+ addop 41 | | | | | | | | | | | | | | | >--* + 42 | | | | | | | | | | | | | | >--+ term 43 | | | | | | | | | | | | | | | >--+ factor 44 | | | | | | | | | | | | | | | | >--+ integer 45 | | | | | | | | | | | | | | | | | >--* 234 46 | | | | | | | | | | >--* ; 47 | | | | | | | >--+ statement 48 | | | | | | | | >--+ return-stmt 49 | | | | | | | | | >--* return 50 | | | | | | | | | >--+ expression 51 | | | | | | | | | | >--+ simple-expression 52 | | | | | | | | | | | >--+ additive-expression 53 | | | | | | | | | | | | >--+ term 54 | | | | | | | | | | | | | >--+ factor 55 | | | | | | | | | | | | | | >--+ var 56 | | | | | | | | | | | | | | | >--* a 57 | | | | | | | | | >--* ; 58 | | | | | | >--* } 59 | -------------------------------------------------------------------------------- /tests/1-parser/output_standard/testcases_general/7-assign_int_var_local.syntax_tree: -------------------------------------------------------------------------------- 1 | >--+ program 2 | | >--+ declaration-list 3 | | | >--+ declaration 4 | | | | >--+ fun-declaration 5 | | | | | >--+ type-specifier 6 | | | | | | >--* int 7 | | | | | >--* main 8 | | | | | >--* ( 9 | | | | | >--+ params 10 | | | | | | >--* void 11 | | | | | >--* ) 12 | | | | | >--+ compound-stmt 13 | | | | | | >--* { 14 | | | | | | >--+ local-declarations 15 | | | | | | | >--+ local-declarations 16 | | | | | | | | >--* epsilon 17 | | | | | | | >--+ var-declaration 18 | | | | | | | | >--+ type-specifier 19 | | | | | | | | | >--* int 20 | | | | | | | | >--* a 21 | | | | | | | | >--* ; 22 | | | | | | >--+ statement-list 23 | | | | | | | >--+ statement-list 24 | | | | | | | | >--+ statement-list 25 | | | | | | | | | >--* epsilon 26 | | | | | | | | >--+ statement 27 | | | | | | | | | >--+ expression-stmt 28 | | | | | | | | | | >--+ expression 29 | | | | | | | | | | | >--+ var 30 | | | | | | | | | | | | >--* a 31 | | | | | | | | | | | >--* = 32 | | | | | | | | | | | >--+ expression 33 | | | | | | | | | | | | >--+ simple-expression 34 | | | | | | | | | | | | | >--+ additive-expression 35 | | | | | | | | | | | | | | >--+ term 36 | | | | | | | | | | | | | | | >--+ factor 37 | | | | | | | | | | | | | | | | >--+ integer 38 | | | | | | | | | | | | | | | | | >--* 1234 39 | | | | | | | | | | >--* ; 40 | | | | | | | >--+ statement 41 | | | | | | | | >--+ return-stmt 42 | | | | | | | | | >--* return 43 | | | | | | | | | >--+ expression 44 | | | | | | | | | | >--+ simple-expression 45 | | | | | | | | | | | >--+ additive-expression 46 | | | | | | | | | | | | >--+ term 47 | | | | | | | | | | | | | >--+ factor 48 | | | | | | | | | | | | | | >--+ var 49 | | | | | | | | | | | | | | | >--* a 50 | | | | | | | | | >--* ; 51 | | | | | | >--* } 52 | -------------------------------------------------------------------------------- /tests/1-parser/output_student/.gitignore: -------------------------------------------------------------------------------- 1 | easy 2 | normal 3 | hard 4 | testcases_general -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/.gitignore: -------------------------------------------------------------------------------- 1 | eval_result 2 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/answers/lv0_1/decl_float.out: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WeithWu/USTC-2023-compilers-lab/fe8679e378701951a8a688acba125b1c6ae5ab3e/tests/2-ir-gen/autogen/answers/lv0_1/decl_float.out -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/answers/lv0_1/decl_float_array.out: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WeithWu/USTC-2023-compilers-lab/fe8679e378701951a8a688acba125b1c6ae5ab3e/tests/2-ir-gen/autogen/answers/lv0_1/decl_float_array.out -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/answers/lv0_1/decl_int.out: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WeithWu/USTC-2023-compilers-lab/fe8679e378701951a8a688acba125b1c6ae5ab3e/tests/2-ir-gen/autogen/answers/lv0_1/decl_int.out -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/answers/lv0_1/decl_int_array.out: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WeithWu/USTC-2023-compilers-lab/fe8679e378701951a8a688acba125b1c6ae5ab3e/tests/2-ir-gen/autogen/answers/lv0_1/decl_int_array.out -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/answers/lv0_1/input.in: -------------------------------------------------------------------------------- 1 | 4 2 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/answers/lv0_1/input.out: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WeithWu/USTC-2023-compilers-lab/fe8679e378701951a8a688acba125b1c6ae5ab3e/tests/2-ir-gen/autogen/answers/lv0_1/input.out -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/answers/lv0_1/output_float.out: -------------------------------------------------------------------------------- 1 | 123.400002 2 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/answers/lv0_1/output_int.out: -------------------------------------------------------------------------------- 1 | 1234 2 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/answers/lv0_1/return.out: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WeithWu/USTC-2023-compilers-lab/fe8679e378701951a8a688acba125b1c6ae5ab3e/tests/2-ir-gen/autogen/answers/lv0_1/return.out -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/answers/lv0_2/num_add_float.out: -------------------------------------------------------------------------------- 1 | 123 2 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/answers/lv0_2/num_add_int.out: -------------------------------------------------------------------------------- 1 | 1234 2 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/answers/lv0_2/num_add_mixed.out: -------------------------------------------------------------------------------- 1 | 1023 2 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/answers/lv0_2/num_comp1.out: -------------------------------------------------------------------------------- 1 | -44.720001 2 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/answers/lv0_2/num_comp2.out: -------------------------------------------------------------------------------- 1 | 1 2 | 1 3 | 0 4 | 0 5 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/answers/lv0_2/num_div_float.out: -------------------------------------------------------------------------------- 1 | 12 2 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/answers/lv0_2/num_div_int.out: -------------------------------------------------------------------------------- 1 | 1234 2 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/answers/lv0_2/num_div_mixed.out: -------------------------------------------------------------------------------- 1 | 12 2 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/answers/lv0_2/num_eq_float.out: -------------------------------------------------------------------------------- 1 | 0 2 | 1 3 | 0 4 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/answers/lv0_2/num_eq_int.out: -------------------------------------------------------------------------------- 1 | 0 2 | 1 3 | 0 4 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/answers/lv0_2/num_eq_mixed.out: -------------------------------------------------------------------------------- 1 | 0 2 | 1 3 | 0 4 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/answers/lv0_2/num_ge_float.out: -------------------------------------------------------------------------------- 1 | 0 2 | 1 3 | 1 4 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/answers/lv0_2/num_ge_int.out: -------------------------------------------------------------------------------- 1 | 0 2 | 1 3 | 1 4 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/answers/lv0_2/num_ge_mixed.out: -------------------------------------------------------------------------------- 1 | 0 2 | 1 3 | 1 4 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/answers/lv0_2/num_gt_float.out: -------------------------------------------------------------------------------- 1 | 0 2 | 0 3 | 1 4 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/answers/lv0_2/num_gt_int.out: -------------------------------------------------------------------------------- 1 | 0 2 | 0 3 | 1 4 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/answers/lv0_2/num_gt_mixed.out: -------------------------------------------------------------------------------- 1 | 0 2 | 0 3 | 1 4 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/answers/lv0_2/num_le_float.out: -------------------------------------------------------------------------------- 1 | 1 2 | 1 3 | 0 4 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/answers/lv0_2/num_le_int.out: -------------------------------------------------------------------------------- 1 | 1 2 | 1 3 | 0 4 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/answers/lv0_2/num_le_mixed.out: -------------------------------------------------------------------------------- 1 | 1 2 | 1 3 | 0 4 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/answers/lv0_2/num_lt_float.out: -------------------------------------------------------------------------------- 1 | 1 2 | 0 3 | 0 4 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/answers/lv0_2/num_lt_int.out: -------------------------------------------------------------------------------- 1 | 1 2 | 0 3 | 0 4 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/answers/lv0_2/num_lt_mixed.out: -------------------------------------------------------------------------------- 1 | 1 2 | 0 3 | 0 4 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/answers/lv0_2/num_mul_float.out: -------------------------------------------------------------------------------- 1 | 123 2 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/answers/lv0_2/num_mul_int.out: -------------------------------------------------------------------------------- 1 | 1234 2 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/answers/lv0_2/num_mul_mixed.out: -------------------------------------------------------------------------------- 1 | 123 2 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/answers/lv0_2/num_neq_float.out: -------------------------------------------------------------------------------- 1 | 1 2 | 0 3 | 1 4 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/answers/lv0_2/num_neq_int.out: -------------------------------------------------------------------------------- 1 | 1 2 | 0 3 | 1 4 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/answers/lv0_2/num_neq_mixed.out: -------------------------------------------------------------------------------- 1 | 1 2 | 0 3 | 1 4 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/answers/lv0_2/num_sub_float.out: -------------------------------------------------------------------------------- 1 | 192 2 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/answers/lv0_2/num_sub_int.out: -------------------------------------------------------------------------------- 1 | 1234 2 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/answers/lv0_2/num_sub_mixed.out: -------------------------------------------------------------------------------- 1 | 1923 2 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/answers/lv1/assign_cmp.out: -------------------------------------------------------------------------------- 1 | 1 2 | 0 3 | 0 4 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/answers/lv1/assign_float_array_global.out: -------------------------------------------------------------------------------- 1 | 1234.000000 2 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/answers/lv1/assign_float_array_local.out: -------------------------------------------------------------------------------- 1 | 1234.000000 2 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/answers/lv1/assign_float_var_global.out: -------------------------------------------------------------------------------- 1 | 1234.000000 2 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/answers/lv1/assign_float_var_local.out: -------------------------------------------------------------------------------- 1 | 1234.000000 2 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/answers/lv1/assign_int_array_global.out: -------------------------------------------------------------------------------- 1 | 1234 2 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/answers/lv1/assign_int_array_local.out: -------------------------------------------------------------------------------- 1 | 1234 2 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/answers/lv1/assign_int_var_global.out: -------------------------------------------------------------------------------- 1 | 1234 2 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/answers/lv1/assign_int_var_local.out: -------------------------------------------------------------------------------- 1 | 1234 2 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/answers/lv1/idx_float.out: -------------------------------------------------------------------------------- 1 | 1024 2 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/answers/lv1/innout.in: -------------------------------------------------------------------------------- 1 | 9 2 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/answers/lv1/innout.out: -------------------------------------------------------------------------------- 1 | 9 2 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/answers/lv1/iteration1.out: -------------------------------------------------------------------------------- 1 | 10 2 | 9 3 | 8 4 | 7 5 | 6 6 | 5 7 | 4 8 | 3 9 | 2 10 | 1 11 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/answers/lv1/iteration2.out: -------------------------------------------------------------------------------- 1 | 10 2 | 9 3 | 8 4 | 7 5 | 6 6 | 5 7 | 4 8 | 3 9 | 2 10 | 1 11 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/answers/lv1/negidx_float.out: -------------------------------------------------------------------------------- 1 | negative index exception 2 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/answers/lv1/negidx_floatfuncall.out: -------------------------------------------------------------------------------- 1 | negative index exception 2 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/answers/lv1/negidx_int.out: -------------------------------------------------------------------------------- 1 | negative index exception 2 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/answers/lv1/negidx_intfuncall.out: -------------------------------------------------------------------------------- 1 | negative index exception 2 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/answers/lv1/negidx_voidfuncall.out: -------------------------------------------------------------------------------- 1 | negative index exception 2 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/answers/lv1/scope.out: -------------------------------------------------------------------------------- 1 | 3 2 | 11 3 | 3 4 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/answers/lv1/selection1.out: -------------------------------------------------------------------------------- 1 | 42 2 | 24 3 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/answers/lv1/selection2.out: -------------------------------------------------------------------------------- 1 | 42 2 | 24 3 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/answers/lv1/selection3.out: -------------------------------------------------------------------------------- 1 | 42 2 | 24 3 | 1234 4 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/answers/lv1/transfer_float_to_int.out: -------------------------------------------------------------------------------- 1 | 1 2 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/answers/lv1/transfer_int_to_float.out: -------------------------------------------------------------------------------- 1 | 1.000000 2 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/answers/lv2/assign_chain.out: -------------------------------------------------------------------------------- 1 | 3 2 | 3 3 | 3 4 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/answers/lv2/funcall_array.out: -------------------------------------------------------------------------------- 1 | 10 2 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/answers/lv2/funcall_array_array.out: -------------------------------------------------------------------------------- 1 | 1024 2 | 1024 3 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/answers/lv2/funcall_chain.out: -------------------------------------------------------------------------------- 1 | 1234 2 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/answers/lv2/funcall_float_array.out: -------------------------------------------------------------------------------- 1 | 3 2 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/answers/lv2/funcall_int_array.out: -------------------------------------------------------------------------------- 1 | 10 2 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/answers/lv2/funcall_type_mismatch1.out: -------------------------------------------------------------------------------- 1 | 10 2 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/answers/lv2/funcall_type_mismatch2.out: -------------------------------------------------------------------------------- 1 | 4.000000 2 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/answers/lv2/funcall_var.out: -------------------------------------------------------------------------------- 1 | 10 2 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/answers/lv2/return_in_middle1.out: -------------------------------------------------------------------------------- 1 | 0 2 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/answers/lv2/return_in_middle2.out: -------------------------------------------------------------------------------- 1 | 0 2 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/answers/lv2/return_type_mismatch1.out: -------------------------------------------------------------------------------- 1 | 233 2 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/answers/lv2/return_type_mismatch2.out: -------------------------------------------------------------------------------- 1 | 7.000000 2 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/answers/lv3/complex2.in: -------------------------------------------------------------------------------- 1 | 9 2 | 8 3 | 7 4 | 6 5 | 5 6 | 4 7 | 3 8 | 2 9 | 1 10 | 0 11 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/answers/lv3/complex2.out: -------------------------------------------------------------------------------- 1 | 0 2 | 1 3 | 2 4 | 3 5 | 4 6 | 5 7 | 6 8 | 7 9 | 8 10 | 9 11 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/answers/lv3/complex3.in: -------------------------------------------------------------------------------- 1 | 78 2 | 117 3 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/answers/lv3/complex3.out: -------------------------------------------------------------------------------- 1 | 39 2 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/answers/lv3/complex4.out: -------------------------------------------------------------------------------- 1 | 1.000000 2 | -0.200000 3 | 0.400000 4 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/testcases/lv0_1/decl_float.cminus: -------------------------------------------------------------------------------- 1 | void main(void) { 2 | float a; 3 | return; 4 | } 5 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/testcases/lv0_1/decl_float_array.cminus: -------------------------------------------------------------------------------- 1 | void main(void) { 2 | float a[10]; 3 | return; 4 | } 5 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/testcases/lv0_1/decl_int.cminus: -------------------------------------------------------------------------------- 1 | void main(void) { 2 | int a; 3 | return; 4 | } 5 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/testcases/lv0_1/decl_int_array.cminus: -------------------------------------------------------------------------------- 1 | void main(void) { 2 | int a[10]; 3 | return; 4 | } 5 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/testcases/lv0_1/input.cminus: -------------------------------------------------------------------------------- 1 | void main(void) { 2 | input(); 3 | return; 4 | } 5 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/testcases/lv0_1/output_float.cminus: -------------------------------------------------------------------------------- 1 | void main(void) { 2 | outputFloat(123.4); 3 | return; 4 | } 5 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/testcases/lv0_1/output_int.cminus: -------------------------------------------------------------------------------- 1 | void main(void) { 2 | output(1234); 3 | return; 4 | } 5 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/testcases/lv0_1/return.cminus: -------------------------------------------------------------------------------- 1 | void main(void) { return; } 2 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/testcases/lv0_2/num_add_float.cminus: -------------------------------------------------------------------------------- 1 | void main(void) { 2 | output(100.0 + 23.4); 3 | return; 4 | } 5 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/testcases/lv0_2/num_add_int.cminus: -------------------------------------------------------------------------------- 1 | void main(void) { 2 | output(1000 + 234); 3 | return; 4 | } 5 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/testcases/lv0_2/num_add_mixed.cminus: -------------------------------------------------------------------------------- 1 | void main(void) { 2 | output(1000 + 23.4); 3 | return; 4 | } 5 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/testcases/lv0_2/num_comp1.cminus: -------------------------------------------------------------------------------- 1 | void main(void) { 2 | outputFloat(9 + 1.2 / (2 * 2 + 5 - 6) * 3.2 - 55); 3 | return; 4 | } 5 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/testcases/lv0_2/num_comp2.cminus: -------------------------------------------------------------------------------- 1 | void main(void) { 2 | output((1 > 2.) < 3); 3 | output((1 > 2) < ((3 == 4) >= 0)); 4 | output(((3 == 4.) >= 0) <= (4 != 4)); 5 | output(((1 > 2) < ((3 == 4) >= 0)) <= (4. != 4)); 6 | return; 7 | } 8 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/testcases/lv0_2/num_div_float.cminus: -------------------------------------------------------------------------------- 1 | void main(void) { 2 | output(24.68 / 2.); 3 | return; 4 | } 5 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/testcases/lv0_2/num_div_int.cminus: -------------------------------------------------------------------------------- 1 | void main(void) { 2 | output(2468 / 2); 3 | return; 4 | } 5 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/testcases/lv0_2/num_div_mixed.cminus: -------------------------------------------------------------------------------- 1 | void main(void) { 2 | output(24.68 / 2); 3 | return; 4 | } 5 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/testcases/lv0_2/num_eq_float.cminus: -------------------------------------------------------------------------------- 1 | void main(void) { 2 | output(1. == 2.); 3 | output(2. == 2.); 4 | output(3. == 2.); 5 | return; 6 | } 7 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/testcases/lv0_2/num_eq_int.cminus: -------------------------------------------------------------------------------- 1 | void main(void) { 2 | output(1 == 2); 3 | output(2 == 2); 4 | output(3 == 2); 5 | return; 6 | } 7 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/testcases/lv0_2/num_eq_mixed.cminus: -------------------------------------------------------------------------------- 1 | void main(void) { 2 | output(1. == 2); 3 | output(2. == 2); 4 | output(3 == 2.); 5 | return; 6 | } 7 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/testcases/lv0_2/num_ge_float.cminus: -------------------------------------------------------------------------------- 1 | void main(void) { 2 | output(1. >= 2.); 3 | output(2. >= 2.); 4 | output(3. >= 2.); 5 | return; 6 | } 7 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/testcases/lv0_2/num_ge_int.cminus: -------------------------------------------------------------------------------- 1 | void main(void) { 2 | output(1 >= 2); 3 | output(2 >= 2); 4 | output(3 >= 2); 5 | return; 6 | } 7 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/testcases/lv0_2/num_ge_mixed.cminus: -------------------------------------------------------------------------------- 1 | void main(void) { 2 | output(1. >= 2); 3 | output(2. >= 2); 4 | output(3 >= 2.); 5 | return; 6 | } 7 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/testcases/lv0_2/num_gt_float.cminus: -------------------------------------------------------------------------------- 1 | void main(void) { 2 | output(1. > 2.); 3 | output(2. > 2.); 4 | output(3. > 2.); 5 | return; 6 | } 7 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/testcases/lv0_2/num_gt_int.cminus: -------------------------------------------------------------------------------- 1 | void main(void) { 2 | output(1 > 2); 3 | output(2 > 2); 4 | output(3 > 2); 5 | return; 6 | } 7 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/testcases/lv0_2/num_gt_mixed.cminus: -------------------------------------------------------------------------------- 1 | void main(void) { 2 | output(1. > 2); 3 | output(2. > 2); 4 | output(3 > 2.); 5 | return; 6 | } 7 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/testcases/lv0_2/num_le_float.cminus: -------------------------------------------------------------------------------- 1 | void main(void) { 2 | output(1. <= 2.); 3 | output(2. <= 2.); 4 | output(3. <= 2.); 5 | return; 6 | } 7 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/testcases/lv0_2/num_le_int.cminus: -------------------------------------------------------------------------------- 1 | void main(void) { 2 | output(1 <= 2); 3 | output(2 <= 2); 4 | output(3 <= 2); 5 | return; 6 | } 7 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/testcases/lv0_2/num_le_mixed.cminus: -------------------------------------------------------------------------------- 1 | void main(void) { 2 | output(1. <= 2); 3 | output(2. <= 2); 4 | output(3 <= 2.); 5 | return; 6 | } 7 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/testcases/lv0_2/num_lt_float.cminus: -------------------------------------------------------------------------------- 1 | void main(void) { 2 | output(1. < 2.); 3 | output(2. < 2.); 4 | output(3. < 2.); 5 | return; 6 | } 7 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/testcases/lv0_2/num_lt_int.cminus: -------------------------------------------------------------------------------- 1 | void main(void) { 2 | output(1 < 2); 3 | output(2 < 2); 4 | output(3 < 2); 5 | return; 6 | } 7 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/testcases/lv0_2/num_lt_mixed.cminus: -------------------------------------------------------------------------------- 1 | void main(void) { 2 | output(1. < 2); 3 | output(2 < 2.); 4 | output(3. < 2); 5 | return; 6 | } 7 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/testcases/lv0_2/num_mul_float.cminus: -------------------------------------------------------------------------------- 1 | void main(void) { 2 | output(2. * 61.7); 3 | return; 4 | } 5 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/testcases/lv0_2/num_mul_int.cminus: -------------------------------------------------------------------------------- 1 | void main(void) { 2 | output(2 * 617); 3 | return; 4 | } 5 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/testcases/lv0_2/num_mul_mixed.cminus: -------------------------------------------------------------------------------- 1 | void main(void) { 2 | output(2 * 61.7); 3 | return; 4 | } 5 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/testcases/lv0_2/num_neq_float.cminus: -------------------------------------------------------------------------------- 1 | void main(void) { 2 | output(1. != 2.); 3 | output(2. != 2.); 4 | output(3. != 2.); 5 | return; 6 | } 7 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/testcases/lv0_2/num_neq_int.cminus: -------------------------------------------------------------------------------- 1 | void main(void) { 2 | output(1 != 2); 3 | output(2 != 2); 4 | output(3 != 2); 5 | return; 6 | } 7 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/testcases/lv0_2/num_neq_mixed.cminus: -------------------------------------------------------------------------------- 1 | void main(void) { 2 | output(1. != 2); 3 | output(2 != 2.); 4 | output(3 != 2.); 5 | return; 6 | } 7 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/testcases/lv0_2/num_sub_float.cminus: -------------------------------------------------------------------------------- 1 | void main(void) { 2 | output(200.0 - 7.66); 3 | return; 4 | } 5 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/testcases/lv0_2/num_sub_int.cminus: -------------------------------------------------------------------------------- 1 | void main(void) { 2 | output(2000 - 766); 3 | return; 4 | } 5 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/testcases/lv0_2/num_sub_mixed.cminus: -------------------------------------------------------------------------------- 1 | void main(void) { 2 | output(2000 - 76.6); 3 | return; 4 | } 5 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/testcases/lv1/assign_cmp.cminus: -------------------------------------------------------------------------------- 1 | void main(void) { 2 | int a; 3 | int b; 4 | int c; 5 | a = 1 < 3; 6 | b = 2 == 4; 7 | c = 3 > 5; 8 | output(a); 9 | output(b); 10 | output(c); 11 | return; 12 | } 13 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/testcases/lv1/assign_float_array_global.cminus: -------------------------------------------------------------------------------- 1 | float b[10]; 2 | void main(void) { 3 | b[3] = 1234.0; 4 | outputFloat(b[3]); 5 | return; 6 | } 7 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/testcases/lv1/assign_float_array_local.cminus: -------------------------------------------------------------------------------- 1 | void main(void) { 2 | float b[10]; 3 | b[3] = 1234.0; 4 | outputFloat(b[3]); 5 | return; 6 | } 7 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/testcases/lv1/assign_float_var_global.cminus: -------------------------------------------------------------------------------- 1 | float b; 2 | void main(void) { 3 | b = 1234.0; 4 | outputFloat(b); 5 | return; 6 | } 7 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/testcases/lv1/assign_float_var_local.cminus: -------------------------------------------------------------------------------- 1 | void main(void) { 2 | float b; 3 | b = 1234.0; 4 | outputFloat(b); 5 | return; 6 | } 7 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/testcases/lv1/assign_int_array_global.cminus: -------------------------------------------------------------------------------- 1 | int a[10]; 2 | void main(void) { 3 | a[3] = 1234; 4 | output(a[3]); 5 | return; 6 | } 7 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/testcases/lv1/assign_int_array_local.cminus: -------------------------------------------------------------------------------- 1 | void main(void) { 2 | int a[10]; 3 | a[3] = 1234; 4 | output(a[3]); 5 | return; 6 | } 7 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/testcases/lv1/assign_int_var_global.cminus: -------------------------------------------------------------------------------- 1 | int a; 2 | void main(void) { 3 | a = 1234; 4 | output(a); 5 | return; 6 | } 7 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/testcases/lv1/assign_int_var_local.cminus: -------------------------------------------------------------------------------- 1 | void main(void) { 2 | int a; 3 | a = 1234; 4 | output(a); 5 | return; 6 | } 7 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/testcases/lv1/idx_float.cminus: -------------------------------------------------------------------------------- 1 | void main(void) { 2 | int a[10]; 3 | a[0] = 1024; 4 | output(a[0.1]); 5 | return; 6 | } 7 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/testcases/lv1/innout.cminus: -------------------------------------------------------------------------------- 1 | void main(void) { 2 | int a; 3 | a = input(); 4 | output(a); 5 | return; 6 | } 7 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/testcases/lv1/iteration1.cminus: -------------------------------------------------------------------------------- 1 | void main(void) { 2 | int i; 3 | i = 10; 4 | while (i) { 5 | output(i); 6 | i = i - 1; 7 | } 8 | return; 9 | } 10 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/testcases/lv1/iteration2.cminus: -------------------------------------------------------------------------------- 1 | void main(void) { 2 | int i; 3 | i = 10; 4 | while (i > 0) { 5 | output(i); 6 | i = i - 1; 7 | } 8 | return; 9 | } 10 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/testcases/lv1/negidx_float.cminus: -------------------------------------------------------------------------------- 1 | void main(void) { 2 | int a[10]; 3 | a[2. - 3]; 4 | return; 5 | } 6 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/testcases/lv1/negidx_floatfuncall.cminus: -------------------------------------------------------------------------------- 1 | float test(void) { 2 | int a[10]; 3 | a[2 - 3]; 4 | return 2.; 5 | } 6 | void main(void) { 7 | test(); 8 | return; 9 | } 10 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/testcases/lv1/negidx_int.cminus: -------------------------------------------------------------------------------- 1 | void main(void) { 2 | int a[10]; 3 | a[2 - 3]; 4 | return; 5 | } 6 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/testcases/lv1/negidx_intfuncall.cminus: -------------------------------------------------------------------------------- 1 | int test(void) { 2 | int a[10]; 3 | a[2 - 3]; 4 | return 2; 5 | } 6 | void main(void) { 7 | test(); 8 | return; 9 | } 10 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/testcases/lv1/negidx_voidfuncall.cminus: -------------------------------------------------------------------------------- 1 | void test(void) { 2 | int a[10]; 3 | a[2 - 3]; 4 | return; 5 | } 6 | void main(void) { 7 | test(); 8 | return; 9 | } 10 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/testcases/lv1/scope.cminus: -------------------------------------------------------------------------------- 1 | void main(void) { 2 | int a; 3 | a = 3; 4 | output(a); 5 | { 6 | int a; 7 | a = 11; 8 | output(a); 9 | } 10 | output(a); 11 | return; 12 | } 13 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/testcases/lv1/selection1.cminus: -------------------------------------------------------------------------------- 1 | void main(void) { 2 | int a; 3 | a = 2; 4 | if (a) 5 | output(42); 6 | output(24); 7 | return; 8 | } 9 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/testcases/lv1/selection2.cminus: -------------------------------------------------------------------------------- 1 | void main(void) { 2 | if (2 > 1) 3 | output(42); 4 | output(24); 5 | if (1 > 2) { 6 | output(1234); 7 | } 8 | return; 9 | } 10 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/testcases/lv1/selection3.cminus: -------------------------------------------------------------------------------- 1 | void main(void) { 2 | if (2 > 1) { 3 | output(42); 4 | } else 5 | output(1234); 6 | 7 | output(24); 8 | 9 | if (2 < 1) 10 | output(42); 11 | else { 12 | output(1234); 13 | } 14 | return; 15 | } 16 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/testcases/lv1/transfer_float_to_int.cminus: -------------------------------------------------------------------------------- 1 | void main(void) { 2 | int a; 3 | a = 1.0; 4 | output(a); 5 | return; 6 | } 7 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/testcases/lv1/transfer_int_to_float.cminus: -------------------------------------------------------------------------------- 1 | void main(void) { 2 | float a; 3 | a = 1; 4 | outputFloat(a); 5 | return; 6 | } 7 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/testcases/lv2/assign_chain.cminus: -------------------------------------------------------------------------------- 1 | void main(void) { 2 | int a; 3 | int b; 4 | int c; 5 | a = b = c = 3; 6 | output(a); 7 | output(b); 8 | output(c); 9 | return; 10 | } 11 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/testcases/lv2/funcall_array_array.cminus: -------------------------------------------------------------------------------- 1 | void g(int b[]) { 2 | output(b[3]); 3 | return; 4 | } 5 | 6 | void f(int c[]) { 7 | output(c[3]); 8 | g(c); 9 | return; 10 | } 11 | 12 | void main(void) { 13 | int a[10]; 14 | a[3] = 1024; 15 | f(a); 16 | return; 17 | } 18 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/testcases/lv2/funcall_chain.cminus: -------------------------------------------------------------------------------- 1 | int addone(int a) { return a + 1; } 2 | void main(void) { 3 | int result; 4 | result = addone(addone(addone(addone(1230)))); 5 | output(result); 6 | return; 7 | } 8 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/testcases/lv2/funcall_float_array.cminus: -------------------------------------------------------------------------------- 1 | void test(float a[]) { 2 | output(a[3]); 3 | return; 4 | } 5 | 6 | void main(void) { 7 | float a[10]; 8 | a[3] = 3.14; 9 | test(a); 10 | return; 11 | } 12 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/testcases/lv2/funcall_int_array.cminus: -------------------------------------------------------------------------------- 1 | void test(int a[]) { 2 | output(a[3]); 3 | return; 4 | } 5 | 6 | void main(void) { 7 | int a[10]; 8 | a[3] = 10; 9 | test(a); 10 | return; 11 | } 12 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/testcases/lv2/funcall_type_mismatch1.cminus: -------------------------------------------------------------------------------- 1 | void f(int a) { 2 | output(a); 3 | return; 4 | } 5 | 6 | void main(void) { 7 | float a; 8 | a = 10; 9 | f(a); 10 | return; 11 | } 12 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/testcases/lv2/funcall_type_mismatch2.cminus: -------------------------------------------------------------------------------- 1 | void f(float a) { 2 | outputFloat(a); 3 | return; 4 | } 5 | 6 | void main(void) { 7 | int a; 8 | a = 4.5; 9 | f(a); 10 | return; 11 | } 12 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/testcases/lv2/funcall_var.cminus: -------------------------------------------------------------------------------- 1 | void test(int a) { 2 | output(a); 3 | return; 4 | } 5 | 6 | void main(void) { 7 | int a; 8 | a = 10; 9 | test(a); 10 | return; 11 | } 12 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/testcases/lv2/return_in_middle1.cminus: -------------------------------------------------------------------------------- 1 | int result(void) { 2 | int i; 3 | if (1) { 4 | i = 1; 5 | return 0; 6 | } else { 7 | i = 2; 8 | } 9 | output(3); 10 | return 3; 11 | } 12 | 13 | void main(void) { 14 | output(result()); 15 | return; 16 | } 17 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/testcases/lv2/return_in_middle2.cminus: -------------------------------------------------------------------------------- 1 | int result(void) { 2 | int i; 3 | i = 10; 4 | while (i > 0) { 5 | return 0; 6 | } 7 | output(4); 8 | return 1; 9 | } 10 | 11 | void main(void) { 12 | output(result()); 13 | return; 14 | } 15 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/testcases/lv2/return_type_mismatch1.cminus: -------------------------------------------------------------------------------- 1 | int f(void) { return 233.3; } 2 | 3 | void main(void) { 4 | output(f()); 5 | return; 6 | } 7 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/testcases/lv2/return_type_mismatch2.cminus: -------------------------------------------------------------------------------- 1 | float f(void) { return 7; } 2 | 3 | void main(void) { 4 | outputFloat(f()); 5 | return; 6 | } 7 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/testcases/lv3/complex1.cminus: -------------------------------------------------------------------------------- 1 | /* 2 | This code is adapted from Dik T. Winter at CWI 3 | It computes pi to 800 decimal digits 4 | */ 5 | 6 | int mod(int a, int b) { return a - a / b * b; } 7 | 8 | void printfour(int input) { 9 | int a; 10 | int b; 11 | int c; 12 | int d; 13 | input = mod(input, 10000); 14 | d = mod(input, 10); 15 | input = input / 10; 16 | c = mod(input, 10); 17 | input = input / 10; 18 | b = mod(input, 10); 19 | input = input / 10; 20 | a = input; 21 | output(a); 22 | output(b); 23 | output(c); 24 | output(d); 25 | return; 26 | } 27 | 28 | void main(void) { 29 | int r[2801]; 30 | int i; 31 | int k; 32 | int b; 33 | int d; 34 | int c; 35 | c = 0; 36 | d = 1234; 37 | 38 | { 39 | int mod; 40 | mod = 0; 41 | while (mod < 2800) { 42 | r[mod] = 2000; 43 | mod = mod + 1; 44 | } 45 | } 46 | 47 | k = 2800; 48 | while (k) { 49 | int d; 50 | d = 0; 51 | i = k; 52 | 53 | while (i != 0) { 54 | d = d + r[i] * 10000; 55 | b = 2 * i - 1; 56 | r[i] = mod(d, b); 57 | d = d / b; 58 | i = i - 1; 59 | if (i != 0) { 60 | d = d * i; 61 | } 62 | } 63 | 64 | printfour(c + d / 10000); 65 | c = mod(d, 10000); 66 | 67 | k = k - 14; 68 | } 69 | 70 | return; 71 | } 72 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/testcases/lv3/complex2.cminus: -------------------------------------------------------------------------------- 1 | /* this is the sample program in C- in the book "Compiler Construction" */ 2 | /* A program to perform selection sort on a 10 element array. */ 3 | float x[10]; 4 | int minloc(float a[], float low, int high) { 5 | int i; 6 | int x; 7 | int k; 8 | k = low; 9 | x = a[low]; 10 | i = low + 1; 11 | while (i < high) { 12 | if (a[i] < x) { 13 | x = a[i]; 14 | k = i; 15 | } 16 | i = i + 1; 17 | } 18 | return k; 19 | } 20 | 21 | void sort(float a[], int low, float high) { 22 | int i; 23 | int k; 24 | i = low; 25 | while (i < high - 1) { 26 | int t; 27 | k = minloc(a, i, high); 28 | t = a[k]; 29 | a[k] = a[i]; 30 | a[i] = t; 31 | i = i + 1; 32 | } 33 | return; 34 | } 35 | 36 | void main(void) { 37 | int i; 38 | i = 0; 39 | while (i < 10) { 40 | x[i] = input(); 41 | i = i + 1; 42 | } 43 | sort(x, 0, 10); 44 | i = 0; 45 | while (i < 10) { 46 | output(x[i]); 47 | i = i + 1; 48 | } 49 | return; 50 | } 51 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/testcases/lv3/complex3.cminus: -------------------------------------------------------------------------------- 1 | int gcd(int u, int v) { 2 | if (v == 0) 3 | return u; 4 | else 5 | return gcd(v, u - u / v * v); 6 | } 7 | 8 | void main(void) { 9 | int x; 10 | int y; 11 | int temp; 12 | x = input(); 13 | y = input(); 14 | if (x < y) { 15 | temp = x; 16 | x = y; 17 | y = temp; 18 | } 19 | temp = gcd(x, y); 20 | output(temp); 21 | return; 22 | } 23 | -------------------------------------------------------------------------------- /tests/2-ir-gen/autogen/testcases/lv3/complex4.cminus: -------------------------------------------------------------------------------- 1 | float get(float a[], int x, int y, int row) { return a[x * row + y]; } 2 | 3 | float abs(float x) { 4 | if (x > 0) 5 | return x; 6 | else 7 | return 0 - x; 8 | } 9 | 10 | float isZero(float t) { return abs(t) < 0.000001; } 11 | 12 | int gauss(float vars[], float equ[], int var) { 13 | int i; 14 | int j; 15 | int k; 16 | int varone; 17 | int maxr; 18 | int col; 19 | float temp; 20 | varone = var + 1; 21 | 22 | i = 0; 23 | while (i < var) { 24 | vars[i] = 0; 25 | i = i + 1; 26 | } 27 | 28 | col = 0; 29 | k = 0; 30 | while (k < var) { 31 | maxr = k; 32 | i = k + 1; 33 | while (i < var) { 34 | if (abs(get(equ, i, col, varone)) > abs(get(equ, maxr, col, varone))) 35 | maxr = i; 36 | i = i + 1; 37 | } 38 | if (maxr != k) { 39 | j = k; 40 | 41 | while (j < varone) { 42 | temp = get(equ, k, j, varone); 43 | equ[k * varone + j] = get(equ, maxr, j, varone); 44 | equ[maxr * varone + j] = temp; 45 | j = j + 1; 46 | } 47 | } 48 | if (isZero(get(equ, k, col, varone))) { 49 | k = k - 1; 50 | } else { 51 | i = k + 1; 52 | while (i < var) { 53 | if (1 - isZero(get(equ, i, col, varone))) { 54 | temp = get(equ, i, col, varone) / get(equ, k, col, varone); 55 | j = col; 56 | while (j < varone) { 57 | equ[i * varone + j] = equ[i * varone + j] - get(equ, k, j, varone) * temp; 58 | j = j + 1; 59 | } 60 | } 61 | i = i + 1; 62 | } 63 | } 64 | k = k + 1; 65 | col = col + 1; 66 | } 67 | 68 | i = var - 1; 69 | while (i >= 0) { 70 | temp = get(equ, i, var, varone); 71 | j = i + 1; 72 | while (j < var) { 73 | if (1 - isZero(get(equ, i, j, varone))) 74 | temp = temp - get(equ, i, j, varone) * vars[j]; 75 | j = j + 1; 76 | } 77 | vars[i] = temp / get(equ, i, i, varone); 78 | i = i - 1; 79 | } 80 | return 0; 81 | } 82 | 83 | void main(void) { 84 | int num; 85 | float vars[3]; 86 | float equ[12]; 87 | equ[0] = 1; 88 | equ[1] = 2; 89 | equ[2] = 1; 90 | equ[3] = 1; 91 | equ[1 * 4 + 0] = 2; 92 | equ[1 * 4 + 1] = 3; 93 | equ[1 * 4 + 2] = 4; 94 | equ[1 * 4 + 3] = 3; 95 | equ[2 * 4 + 0] = 1; 96 | equ[2 * 4 + 1] = 1; 97 | equ[2 * 4 + 2] = 0 - 2; 98 | equ[2 * 4 + 3] = 0; 99 | gauss(vars, equ, 3); 100 | num = 0; 101 | while (num < 3) { 102 | outputFloat(vars[num]); 103 | num = num + 1; 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /tests/2-ir-gen/warmup/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(calculator) 2 | add_executable( 3 | gcd_array_generator 4 | ta_gcd/gcd_array_generator.cpp 5 | ) 6 | target_link_libraries( 7 | gcd_array_generator 8 | IR_lib 9 | ) 10 | 11 | add_executable( 12 | stu_assign_generator 13 | stu_cpp/assign_generator.cpp 14 | ) 15 | target_link_libraries( 16 | stu_assign_generator 17 | IR_lib 18 | ) 19 | 20 | add_executable( 21 | stu_fun_generator 22 | stu_cpp/fun_generator.cpp 23 | ) 24 | target_link_libraries( 25 | stu_fun_generator 26 | IR_lib 27 | ) 28 | 29 | add_executable( 30 | stu_if_generator 31 | stu_cpp/if_generator.cpp 32 | ) 33 | target_link_libraries( 34 | stu_if_generator 35 | IR_lib 36 | ) 37 | 38 | add_executable( 39 | stu_while_generator 40 | stu_cpp/while_generator.cpp 41 | ) 42 | target_link_libraries( 43 | stu_while_generator 44 | IR_lib 45 | ) 46 | -------------------------------------------------------------------------------- /tests/2-ir-gen/warmup/c_cases/assign.c: -------------------------------------------------------------------------------- 1 | int main() { 2 | int a[10]; 3 | a[0] = 10; 4 | a[1] = a[0] * 2; 5 | return a[1]; 6 | } 7 | -------------------------------------------------------------------------------- /tests/2-ir-gen/warmup/c_cases/fun.c: -------------------------------------------------------------------------------- 1 | int callee(int a) { return 2 * a; } 2 | int main() { return callee(110); } 3 | -------------------------------------------------------------------------------- /tests/2-ir-gen/warmup/c_cases/if.c: -------------------------------------------------------------------------------- 1 | int main() { 2 | float a = 5.555; 3 | if (a > 1) 4 | return 233; 5 | return 0; 6 | } 7 | -------------------------------------------------------------------------------- /tests/2-ir-gen/warmup/c_cases/while.c: -------------------------------------------------------------------------------- 1 | int main() { 2 | int a; 3 | int i; 4 | a = 10; 5 | i = 0; 6 | while (i < 10) { 7 | i = i + 1; 8 | a = a + i; 9 | } 10 | return a; 11 | } 12 | -------------------------------------------------------------------------------- /tests/2-ir-gen/warmup/c_cases/while.ll: -------------------------------------------------------------------------------- 1 | ; ModuleID = 'while.c' 2 | source_filename = "while.c" 3 | target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" 4 | target triple = "x86_64-pc-linux-gnu" 5 | 6 | ; Function Attrs: noinline nounwind optnone uwtable 7 | define dso_local i32 @main() #0 { 8 | %1 = alloca i32, align 4 9 | %2 = alloca i32, align 4 10 | %3 = alloca i32, align 4 11 | store i32 0, i32* %1, align 4 12 | store i32 10, i32* %2, align 4 13 | store i32 0, i32* %3, align 4 14 | br label %4 15 | 16 | 4: ; preds = %7, %0 17 | %5 = load i32, i32* %3, align 4 18 | %6 = icmp slt i32 %5, 10 19 | br i1 %6, label %7, label %13 20 | 21 | 7: ; preds = %4 22 | %8 = load i32, i32* %3, align 4 23 | %9 = add nsw i32 %8, 1 24 | store i32 %9, i32* %3, align 4 25 | %10 = load i32, i32* %2, align 4 26 | %11 = load i32, i32* %3, align 4 27 | %12 = add nsw i32 %10, %11 28 | store i32 %12, i32* %2, align 4 29 | br label %4, !llvm.loop !6 30 | 31 | 13: ; preds = %4 32 | %14 = load i32, i32* %2, align 4 33 | ret i32 %14 34 | } 35 | 36 | attributes #0 = { noinline nounwind optnone uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } 37 | 38 | !llvm.module.flags = !{!0, !1, !2, !3, !4} 39 | !llvm.ident = !{!5} 40 | 41 | !0 = !{i32 1, !"wchar_size", i32 4} 42 | !1 = !{i32 7, !"PIC Level", i32 2} 43 | !2 = !{i32 7, !"PIE Level", i32 2} 44 | !3 = !{i32 7, !"uwtable", i32 1} 45 | !4 = !{i32 7, !"frame-pointer", i32 2} 46 | !5 = !{!"Ubuntu clang version 14.0.0-1ubuntu1.1"} 47 | !6 = distinct !{!6, !7} 48 | !7 = !{!"llvm.loop.mustprogress"} 49 | -------------------------------------------------------------------------------- /tests/2-ir-gen/warmup/calculator/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | flex_target(calc_lex calculator.l ${CMAKE_CURRENT_BINARY_DIR}/calc_lex.c) 2 | bison_target(calc_syntax calculator.y 3 | ${CMAKE_CURRENT_BINARY_DIR}/calc_syntax.c 4 | DEFINES_FILE ${PROJECT_BINARY_DIR}/calculator.h) 5 | add_flex_bison_dependency(calc_lex calc_syntax) 6 | add_library(calc_syntax STATIC 7 | ${BISON_calc_syntax_OUTPUTS} 8 | ${FLEX_calc_lex_OUTPUTS} 9 | ) 10 | 11 | add_executable( 12 | calc 13 | calc.cpp 14 | calc_ast.cpp 15 | calc_builder.cpp 16 | ) 17 | target_link_libraries( 18 | calc 19 | IR_lib 20 | calc_syntax 21 | common 22 | ) 23 | 24 | install( 25 | TARGETS calc 26 | RUNTIME DESTINATION bin 27 | ) -------------------------------------------------------------------------------- /tests/2-ir-gen/warmup/calculator/calc.cpp: -------------------------------------------------------------------------------- 1 | extern "C" { 2 | #include "syntax_tree.h" 3 | extern syntax_tree *parse(const char *); 4 | } 5 | #include "calc_ast.hpp" 6 | #include "calc_builder.hpp" 7 | 8 | #include 9 | #include 10 | using namespace std::literals::string_literals; 11 | 12 | int main(int argc, char *argv[]) { 13 | syntax_tree *tree = NULL; 14 | const char *input = NULL; 15 | 16 | if (argc >= 3) { 17 | printf("usage: %s\n", argv[0]); 18 | printf("usage: %s \n", argv[0]); 19 | return 1; 20 | } 21 | 22 | if (argc == 2) { 23 | input = argv[1]; 24 | } else { 25 | printf("Input an arithmatic expression (press Ctrl+D in a new line after you finish the expression):\n"); 26 | } 27 | 28 | tree = parse(input); 29 | CalcAST ast(tree); 30 | CalcBuilder builder; 31 | auto module = builder.build(ast); 32 | auto IR = module->print(); 33 | 34 | std::ofstream output_stream; 35 | auto output_file = "result.ll"; 36 | output_stream.open(output_file, std::ios::out); 37 | output_stream << "; ModuleID = 'calculator'\n"; 38 | output_stream << IR; 39 | output_stream.close(); 40 | auto command_string = "clang -O0 -w "s + "result.ll -o result -L. -lcminus_io"; 41 | auto ret = std::system(command_string.c_str()); 42 | if (ret) { 43 | printf("something went wrong!\n"); 44 | } else { 45 | printf("result and result.ll have been generated.\n"); 46 | } 47 | return ret; 48 | } 49 | -------------------------------------------------------------------------------- /tests/2-ir-gen/warmup/calculator/calc_ast.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | extern "C" { 4 | #include "syntax_tree.h" 5 | extern syntax_tree *parse(const char *input); 6 | } 7 | #include 8 | #include 9 | 10 | enum AddOp { 11 | // + 12 | OP_PLUS, 13 | // - 14 | OP_MINUS 15 | }; 16 | 17 | enum MulOp { 18 | // * 19 | OP_MUL, 20 | // / 21 | OP_DIV 22 | }; 23 | 24 | class CalcAST; 25 | 26 | struct CalcASTNode; 27 | struct CalcASTInput; 28 | struct CalcASTExpression; 29 | struct CalcASTNum; 30 | struct CalcASTTerm; 31 | struct CalcASTFactor; 32 | 33 | class CalcASTVisitor; 34 | 35 | class CalcAST { 36 | public: 37 | CalcAST() = delete; 38 | CalcAST(syntax_tree *); 39 | CalcAST(CalcAST &&tree) { 40 | root = tree.root; 41 | tree.root = nullptr; 42 | } 43 | CalcASTInput *get_root() { return root.get(); } 44 | void run_visitor(CalcASTVisitor &visitor); 45 | 46 | private: 47 | CalcASTNode *transform_node_iter(syntax_tree_node *); 48 | std::shared_ptr root = nullptr; 49 | }; 50 | 51 | struct CalcASTNode { 52 | virtual void accept(CalcASTVisitor &) = 0; 53 | virtual ~CalcASTNode() = default; 54 | }; 55 | 56 | struct CalcASTInput : CalcASTNode { 57 | virtual void accept(CalcASTVisitor &) override final; 58 | std::shared_ptr expression; 59 | }; 60 | 61 | struct CalcASTFactor : CalcASTNode { 62 | virtual void accept(CalcASTVisitor &) override; 63 | }; 64 | 65 | struct CalcASTNum : CalcASTFactor { 66 | virtual void accept(CalcASTVisitor &) override final; 67 | int val; 68 | }; 69 | 70 | struct CalcASTExpression : CalcASTFactor { 71 | virtual void accept(CalcASTVisitor &) override final; 72 | std::shared_ptr expression; 73 | AddOp op; 74 | std::shared_ptr term; 75 | }; 76 | 77 | struct CalcASTTerm : CalcASTNode { 78 | virtual void accept(CalcASTVisitor &) override final; 79 | std::shared_ptr term; 80 | MulOp op; 81 | std::shared_ptr factor; 82 | }; 83 | 84 | class CalcASTVisitor { 85 | public: 86 | virtual void visit(CalcASTInput &) = 0; 87 | virtual void visit(CalcASTNum &) = 0; 88 | virtual void visit(CalcASTExpression &) = 0; 89 | virtual void visit(CalcASTTerm &) = 0; 90 | }; 91 | -------------------------------------------------------------------------------- /tests/2-ir-gen/warmup/calculator/calc_builder.cpp: -------------------------------------------------------------------------------- 1 | #include "calc_builder.hpp" 2 | #include 3 | std::unique_ptr CalcBuilder::build(CalcAST &ast) { 4 | module = std::unique_ptr(new Module()); 5 | builder = std::make_unique(nullptr, module.get()); 6 | auto TyVoid = module->get_void_type(); 7 | TyInt32 = module->get_int32_type(); 8 | 9 | std::vector output_params; 10 | output_params.push_back(TyInt32); 11 | auto output_type = FunctionType::get(TyVoid, output_params); 12 | auto output_fun = Function::create(output_type, "output", module.get()); 13 | auto main = 14 | Function::create(FunctionType::get(TyInt32, {}), "main", module.get()); 15 | auto bb = BasicBlock::create(module.get(), "entry", main); 16 | builder->set_insert_point(bb); 17 | ast.run_visitor(*this); 18 | builder->create_call(output_fun, {val}); 19 | builder->create_ret(ConstantInt::get(0, module.get())); 20 | return std::move(module); 21 | } 22 | void CalcBuilder::visit(CalcASTInput &node) { node.expression->accept(*this); } 23 | void CalcBuilder::visit(CalcASTExpression &node) { 24 | if (node.expression == nullptr) { 25 | node.term->accept(*this); 26 | } else { 27 | node.expression->accept(*this); 28 | auto l_val = val; 29 | node.term->accept(*this); 30 | auto r_val = val; 31 | switch (node.op) { 32 | case OP_PLUS: 33 | val = builder->create_iadd(l_val, r_val); 34 | break; 35 | case OP_MINUS: 36 | val = builder->create_isub(l_val, r_val); 37 | break; 38 | } 39 | } 40 | } 41 | 42 | void CalcBuilder::visit(CalcASTTerm &node) { 43 | if (node.term == nullptr) { 44 | node.factor->accept(*this); 45 | } else { 46 | node.term->accept(*this); 47 | auto l_val = val; 48 | node.factor->accept(*this); 49 | auto r_val = val; 50 | switch (node.op) { 51 | case OP_MUL: 52 | val = builder->create_imul(l_val, r_val); 53 | break; 54 | case OP_DIV: 55 | val = builder->create_isdiv(l_val, r_val); 56 | break; 57 | } 58 | } 59 | } 60 | 61 | void CalcBuilder::visit(CalcASTNum &node) { 62 | val = ConstantInt::get(node.val, module.get()); 63 | } 64 | -------------------------------------------------------------------------------- /tests/2-ir-gen/warmup/calculator/calc_builder.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "BasicBlock.hpp" 4 | #include "Constant.hpp" 5 | #include "Function.hpp" 6 | #include "IRBuilder.hpp" 7 | #include "Module.hpp" 8 | #include "Type.hpp" 9 | #include "calc_ast.hpp" 10 | #include 11 | 12 | class CalcBuilder : public CalcASTVisitor { 13 | public: 14 | std::unique_ptr build(CalcAST &ast); 15 | 16 | private: 17 | virtual void visit(CalcASTInput &) override final; 18 | virtual void visit(CalcASTNum &) override final; 19 | virtual void visit(CalcASTExpression &) override final; 20 | virtual void visit(CalcASTTerm &) override final; 21 | 22 | std::unique_ptr builder; 23 | Value *val; 24 | Type *TyInt32; 25 | std::unique_ptr module; 26 | }; 27 | -------------------------------------------------------------------------------- /tests/2-ir-gen/warmup/calculator/calculator.l: -------------------------------------------------------------------------------- 1 | %option noyywrap 2 | %{ 3 | /*****************声明和选项设置 begin*****************/ 4 | #include 5 | #include 6 | 7 | #include "syntax_tree.h" 8 | #include "calculator.h" 9 | 10 | int lines; 11 | int pos_start; 12 | int pos_end; 13 | 14 | void pass_node(char *text){ 15 | yylval.node = new_syntax_tree_node(text); 16 | } 17 | 18 | /*****************声明和选项设置 end*****************/ 19 | 20 | %} 21 | 22 | %x COMMENT 23 | 24 | %% 25 | 26 | \+ {pos_start = pos_end; pos_end += 1; pass_node(yytext); return ADD;} 27 | \- {pos_start = pos_end; pos_end += 1; pass_node(yytext); return SUB;} 28 | \* {pos_start = pos_end; pos_end += 1; pass_node(yytext); return MUL;} 29 | \/ {pos_start = pos_end; pos_end += 1; pass_node(yytext); return DIV;} 30 | \( {pos_start = pos_end; pos_end += 1; pass_node(yytext); return LPARENTHESE;} 31 | \) {pos_start = pos_end; pos_end += 1; pass_node(yytext); return RPARENTHESE;} 32 | [0-9]+ { pos_start = pos_end; pos_end += strlen(yytext); pass_node(yytext); return NUM;} 33 | 34 | \n {lines++; pos_start = 1; pos_end = 1;} 35 | [ \t] {pos_start = pos_end; pos_end += 1;} 36 | %% 37 | -------------------------------------------------------------------------------- /tests/2-ir-gen/warmup/calculator/calculator.y: -------------------------------------------------------------------------------- 1 | %{ 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "syntax_tree.h" 8 | 9 | // external functions from lex 10 | extern int yylex(); 11 | extern int yyparse(); 12 | extern int yyrestart(); 13 | extern FILE * yyin; 14 | 15 | // external variables from lexical_analyzer module 16 | extern int lines; 17 | extern char * yytext; 18 | extern int pos_end; 19 | extern int pos_start; 20 | 21 | // Global syntax tree 22 | syntax_tree *gt; 23 | 24 | // Error reporting 25 | void yyerror(const char *s); 26 | syntax_tree_node *node(const char *node_name, int children_num, ...); 27 | %} 28 | 29 | %union { 30 | struct _syntax_tree_node * node; 31 | char * name; 32 | } 33 | 34 | %token ADD 35 | %token SUB 36 | %token MUL 37 | %token DIV 38 | %token NUM 39 | %token LPARENTHESE 40 | %token RPARENTHESE 41 | %type input expression addop term mulop factor num 42 | 43 | %start input 44 | 45 | %% 46 | input : expression {$$ = node( "input", 1, $1); gt->root = $$;} 47 | ; 48 | expression : expression addop term {$$ = node( "expression", 3, $1, $2, $3);} 49 | | term {$$ = node( "expression", 1, $1);} 50 | ; 51 | 52 | addop : ADD {$$ = node( "addop", 1, $1);} 53 | | SUB {$$ = node( "addop", 1, $1);} 54 | ; 55 | 56 | term : term mulop factor {$$ = node( "term", 3, $1, $2, $3);} 57 | | factor {$$ = node( "term", 1, $1);} 58 | ; 59 | 60 | mulop : MUL {$$ = node( "mulop", 1, $1);} 61 | | DIV {$$ = node( "mulop", 1, $1);} 62 | ; 63 | 64 | factor : LPARENTHESE expression RPARENTHESE {$$ = node( "factor", 3, $1, $2, $3);} 65 | | num {$$ = node( "factor", 1, $1);} 66 | ; 67 | 68 | num : NUM {$$ = node( "num", 1, $1);} 69 | %% 70 | 71 | void yyerror(const char * s) { 72 | fprintf(stderr, "error at line %d column %d: %s\n", lines, pos_start, s); 73 | } 74 | 75 | syntax_tree *parse(const char *input_path) { 76 | if (input_path != NULL) { 77 | if (!(yyin = fopen(input_path, "r"))) { 78 | fprintf(stderr, "[ERR] Open input file %s failed.\n", input_path); 79 | exit(1); 80 | } 81 | } else { 82 | yyin = stdin; 83 | } 84 | 85 | lines = pos_start = pos_end = 1; 86 | gt = new_syntax_tree(); 87 | yyrestart(yyin); 88 | yyparse(); 89 | return gt; 90 | } 91 | 92 | syntax_tree_node *node(const char *name, int children_num, ...) { 93 | syntax_tree_node *p = new_syntax_tree_node(name); 94 | syntax_tree_node *child; 95 | if (children_num == 0) { 96 | child = new_syntax_tree_node("epsilon"); 97 | syntax_tree_add_child(p, child); 98 | } else { 99 | va_list ap; 100 | va_start(ap, children_num); 101 | for (int i = 0; i < children_num; ++i) { 102 | child = va_arg(ap, syntax_tree_node *); 103 | syntax_tree_add_child(p, child); 104 | } 105 | va_end(ap); 106 | } 107 | return p; 108 | } 109 | -------------------------------------------------------------------------------- /tests/2-ir-gen/warmup/stu_cpp/assign_generator.cpp: -------------------------------------------------------------------------------- 1 | #include "BasicBlock.hpp" 2 | #include "Constant.hpp" 3 | #include "Function.hpp" 4 | #include "IRBuilder.hpp" 5 | #include "Module.hpp" 6 | #include "Type.hpp" 7 | 8 | #include 9 | #include 10 | 11 | #define CONST_INT(num) ConstantInt::get(num,module) 12 | #define CONST_FP(num) ConstantFP::get(num,module) 13 | 14 | int main() { 15 | auto module = new Module(); 16 | auto builder = new IRBuilder(nullptr,module); 17 | Type *Int32Type = module->get_int32_type(); 18 | //auto *Int32PtrType = module->get_int32_ptr_type(); 19 | auto *arryType = ArrayType::get(Int32Type,10); 20 | auto mainFun = Function::create(FunctionType::get(Int32Type,{}),"main",module); 21 | auto bb = BasicBlock::create(module,"entry",mainFun); 22 | builder->set_insert_point(bb); 23 | auto retAlloca = builder->create_alloca(Int32Type); 24 | auto arryAlloca = builder->create_alloca(arryType); 25 | auto arr0_gep = builder->create_gep(arryAlloca,{CONST_INT(0),CONST_INT(0)}); 26 | builder->create_store(CONST_INT(10),arr0_gep); 27 | arr0_gep = builder->create_gep(arryAlloca,{CONST_INT(0),CONST_INT(0)}); 28 | auto arr0 = builder->create_load(arr0_gep); 29 | auto mul = builder->create_imul(CONST_INT(2),arr0); 30 | auto arr1_gep = builder->create_gep(arryAlloca,{CONST_INT(0),CONST_INT(1)}); 31 | builder->create_store(mul,arr1_gep); 32 | auto arr1 = builder->create_load(arr1_gep); 33 | builder->create_store(arr1,retAlloca); 34 | 35 | auto retLoad = builder->create_load(retAlloca); 36 | builder->create_ret(retLoad); 37 | std::cout << module->print(); 38 | delete module; 39 | return 0; 40 | } -------------------------------------------------------------------------------- /tests/2-ir-gen/warmup/stu_cpp/fun_generator.cpp: -------------------------------------------------------------------------------- 1 | #include "BasicBlock.hpp" 2 | #include "Constant.hpp" 3 | #include "Function.hpp" 4 | #include "IRBuilder.hpp" 5 | #include "Module.hpp" 6 | #include "Type.hpp" 7 | 8 | #include 9 | #include 10 | 11 | #define CONST_INT(num) ConstantInt::get(num,module) 12 | #define CONST_FP(num) ConstantFP::get(num,module) 13 | 14 | int main() { 15 | auto module = new Module(); 16 | auto builder = new IRBuilder(nullptr,module); 17 | Type * Int32Type = module->get_int32_type(); 18 | std::vector IntPtrs(1,Int32Type); 19 | auto calleeFuncType = FunctionType::get(Int32Type,IntPtrs); 20 | auto calleeFunc = Function::create(calleeFuncType,"callee",module); 21 | auto bb = BasicBlock::create(module,"entry",calleeFunc); 22 | builder->set_insert_point(bb); 23 | auto aAlloca = builder->create_alloca(Int32Type); 24 | auto retAlloca = builder->create_alloca(Int32Type); 25 | std::vector args1; 26 | for (auto &arg: calleeFunc->get_args()) { 27 | args1.push_back(&arg); 28 | } 29 | builder->create_store(args1[0],aAlloca); 30 | auto aLoad = builder->create_load(aAlloca); 31 | auto mul = builder->create_imul(CONST_INT(2),aLoad); 32 | builder->create_store(mul,retAlloca); 33 | auto retLoad = builder->create_load(retAlloca); 34 | builder->create_ret(retLoad); 35 | auto mainFun = Function::create(FunctionType::get(Int32Type, {}), "main", module); 36 | bb = BasicBlock::create(module,"entry",mainFun); 37 | builder->set_insert_point(bb); 38 | auto call = builder->create_call(calleeFunc,{CONST_INT(110)}); 39 | builder->create_ret(call); 40 | std::cout << module->print(); 41 | delete module; 42 | return 0; 43 | } -------------------------------------------------------------------------------- /tests/2-ir-gen/warmup/stu_cpp/if_generator.cpp: -------------------------------------------------------------------------------- 1 | #include "BasicBlock.hpp" 2 | #include "Constant.hpp" 3 | #include "Function.hpp" 4 | #include "IRBuilder.hpp" 5 | #include "Module.hpp" 6 | #include "Type.hpp" 7 | 8 | #include 9 | #include 10 | 11 | #define CONST_INT(num) ConstantInt::get(num,module) 12 | #define CONST_FP(num) ConstantFP::get(num,module) 13 | 14 | int main() { 15 | auto module = new Module(); 16 | auto builder = new IRBuilder(nullptr,module); 17 | Type * Int32Type = module->get_int32_type(); 18 | auto *FPType = module->get_float_type(); 19 | auto mainFun = Function::create(FunctionType::get(Int32Type, {}), "main", module); 20 | auto bb = BasicBlock::create(module,"entry",mainFun); 21 | builder->set_insert_point(bb); 22 | auto aAlloca = builder->create_alloca(FPType); 23 | builder->create_store(CONST_FP(5.555),aAlloca); 24 | auto aLoad = builder->create_load(aAlloca); 25 | auto fcmp = builder->create_fcmp_gt(aLoad,CONST_FP(1)); 26 | auto trueBB = BasicBlock::create(module,"trueBB",mainFun); 27 | auto retBB = BasicBlock::create(module,"retBB",mainFun); 28 | builder->create_cond_br(fcmp,trueBB,retBB); 29 | builder->set_insert_point(trueBB); 30 | auto retAlloca = builder->create_alloca(Int32Type); 31 | builder->create_store(CONST_INT(233),retAlloca); 32 | auto retLoad = builder->create_load(retAlloca); 33 | builder->create_ret(retLoad); 34 | builder->set_insert_point(retBB); 35 | retAlloca = builder->create_alloca(Int32Type); 36 | builder->create_store(CONST_INT(0),retAlloca); 37 | retLoad = builder->create_load(retAlloca); 38 | builder->create_ret(retLoad); 39 | std::cout << module->print(); 40 | delete module; 41 | return 0; 42 | } -------------------------------------------------------------------------------- /tests/2-ir-gen/warmup/stu_cpp/while_generator.cpp: -------------------------------------------------------------------------------- 1 | #include "BasicBlock.hpp" 2 | #include "Constant.hpp" 3 | #include "Function.hpp" 4 | #include "IRBuilder.hpp" 5 | #include "Module.hpp" 6 | #include "Type.hpp" 7 | 8 | #include 9 | #include 10 | 11 | #define CONST_INT(num) ConstantInt::get(num,module) 12 | #define CONST_FP(num) ConstantFP::get(num,module) 13 | 14 | int main() { 15 | auto module = new Module(); 16 | auto builder = new IRBuilder(nullptr,module); 17 | auto Int32Type = module->get_int32_type(); 18 | auto mainFun = Function::create(FunctionType::get(Int32Type, {}), "main", module); 19 | auto bb = BasicBlock::create(module,"entry",mainFun); 20 | builder->set_insert_point(bb); 21 | auto aAlloca = builder->create_alloca(Int32Type); 22 | auto iAlloca = builder->create_alloca(Int32Type); 23 | builder->create_store(CONST_INT(10),aAlloca); 24 | builder->create_store(CONST_INT(0),iAlloca); 25 | bb = BasicBlock::create(module,"whilBB",mainFun); 26 | auto retBB = BasicBlock::create(module,"retBB",mainFun); 27 | auto cmpBB = BasicBlock::create(module,"cmpBB",mainFun); 28 | builder->create_br(cmpBB); 29 | builder->set_insert_point(cmpBB); 30 | auto iLoad = builder->create_load(iAlloca); 31 | auto icmp = builder->create_icmp_lt(iLoad,CONST_INT(10)); 32 | builder->create_cond_br(icmp,bb,retBB); 33 | builder->set_insert_point(bb); 34 | iLoad = builder->create_load(iAlloca); 35 | auto aLoad = builder->create_load(aAlloca); 36 | auto addi = builder->create_iadd(CONST_INT(1),iLoad); 37 | builder->create_store(addi,iAlloca); 38 | iLoad = builder->create_load(iAlloca); 39 | auto adda = builder->create_iadd(iLoad,aLoad); 40 | builder->create_store(adda,aAlloca); 41 | builder->create_br(cmpBB); 42 | builder->set_insert_point(retBB); 43 | aLoad = builder->create_load(aAlloca); 44 | builder->create_ret(aLoad); 45 | std::cout << module->print(); 46 | delete module; 47 | return 0; 48 | } -------------------------------------------------------------------------------- /tests/2-ir-gen/warmup/stu_ll/assign_hand.ll: -------------------------------------------------------------------------------- 1 | define i32 @main(){ 2 | %1 = alloca [10 x i32] 3 | %2 = getelementptr [10 x i32], [10 x i32]* %1, i32 0, i32 0 4 | store i32 10, i32* %2 5 | %3 = getelementptr [10 x i32], [10 x i32]* %1, i32 0, i32 0 6 | %4 = load i32, i32* %3 7 | %5 = mul i32 2, %4 8 | %6 = getelementptr [10 x i32], [10 x i32]* %1, i32 0, i32 1 9 | store i32 %5, i32* %6 10 | %7 = load i32, i32* %6 11 | %8 = alloca i32 12 | store i32 %7, i32* %8 13 | %9 = load i32, i32* %8 14 | ret i32 %9 15 | 16 | } -------------------------------------------------------------------------------- /tests/2-ir-gen/warmup/stu_ll/fun_hand.ll: -------------------------------------------------------------------------------- 1 | define i32 @callee(i32 %arg0) { 2 | %1 = alloca i32 3 | %2 = alloca i32 4 | store i32 %arg0, i32* %1 5 | %3 = load i32, i32* %1 6 | %4 = mul i32 2, %3 7 | store i32 %4, i32* %2 8 | %5 = load i32, i32* %2 9 | ret i32 %5 10 | } 11 | define i32 @main() { 12 | %1 = call i32 @callee(i32 110) 13 | ret i32 %1 14 | } 15 | -------------------------------------------------------------------------------- /tests/2-ir-gen/warmup/stu_ll/if_hand.ll: -------------------------------------------------------------------------------- 1 | define i32 @main() { 2 | label_entry: 3 | %0 = alloca float 4 | store float 0x40163851e0000000, float* %0 5 | %1 = load float, float* %0 6 | %2 = fcmp ugt float %1, 0x3ff0000000000000 7 | br i1 %2, label %label_trueBB, label %label_retBB 8 | label_trueBB: 9 | %3 = alloca i32 10 | store i32 233, i32* %3 11 | %4 = load i32, i32* %3 12 | ret i32 %4 13 | label_retBB: 14 | %5 = alloca i32 15 | store i32 0, i32* %5 16 | %6 = load i32, i32* %5 17 | ret i32 %6 18 | } -------------------------------------------------------------------------------- /tests/2-ir-gen/warmup/stu_ll/while_hand.ll: -------------------------------------------------------------------------------- 1 | define i32 @main() { 2 | label_entry: 3 | %0 = alloca i32 4 | %1 = alloca i32 5 | store i32 10, i32* %0 6 | store i32 0, i32* %1 7 | br label %label_cmpBB 8 | label_whilBB: 9 | %2 = load i32, i32* %1 10 | %3 = load i32, i32* %0 11 | %4 = add i32 1, %2 12 | store i32 %4, i32* %1 13 | %5 = load i32, i32* %1 14 | %6 = add i32 %5, %3 15 | store i32 %6, i32* %0 16 | br label %label_cmpBB 17 | label_retBB: 18 | %7 = load i32, i32* %0 19 | ret i32 %7 20 | label_cmpBB: 21 | %8 = load i32, i32* %1 22 | %9 = icmp slt i32 %8, 10 23 | br i1 %9, label %label_whilBB, label %label_retBB 24 | } -------------------------------------------------------------------------------- /tests/2-ir-gen/warmup/ta_gcd/gcd_array.c: -------------------------------------------------------------------------------- 1 | int x[1]; 2 | int y[1]; 3 | 4 | int gcd(int u, int v) { 5 | if (v == 0) 6 | return u; 7 | else 8 | return gcd(v, u - u / v * v); 9 | } 10 | 11 | int funArray(int u[], int v[]) { 12 | int a; 13 | int b; 14 | int temp; 15 | a = u[0]; 16 | b = v[0]; 17 | if (a < b) { 18 | temp = a; 19 | a = b; 20 | b = temp; 21 | } 22 | return gcd(a, b); 23 | } 24 | 25 | int main(void) { 26 | x[0] = 90; 27 | y[0] = 18; 28 | return funArray(x, y); 29 | } -------------------------------------------------------------------------------- /tests/3-codegen/autogen/cleanup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | rm -rf output log.txt 3 | -------------------------------------------------------------------------------- /tests/3-codegen/autogen/eval_lab3.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | project_dir=$(realpath ../../../) 4 | io_dir=$(realpath "$project_dir"/src/io) 5 | output_dir=output 6 | suffix=cminus 7 | 8 | LOG=log.txt 9 | 10 | usage() { 11 | cat </dev/null 48 | 49 | mkdir -p $output_dir 50 | 51 | truncate -s 0 $LOG 52 | 53 | if [ $debug_mode = false ]; then 54 | exec 3>/dev/null 4>&1 5>&2 1>&3 2>&3 55 | else 56 | exec 3>&1 57 | fi 58 | 59 | if [ $debug_mode = false ]; then 60 | exec 1>&4 2>&5 61 | fi 62 | 63 | echo "[info] Start testing, using testcase dir: $test_dir" 64 | # asm 65 | for case in $testcases; do 66 | echo "==========$case==========" >>$LOG 67 | case_base_name=$(basename -s .$suffix "$case") 68 | std_out_file=$test_dir/$case_base_name.out 69 | in_file=$test_dir/$case_base_name.in 70 | asm_file=$output_dir/$case_base_name.s 71 | exe_file=$output_dir/$case_base_name 72 | out_file=$output_dir/$case_base_name.out 73 | ll_file=$output_dir/$case_base_name.ll 74 | 75 | echo -n "$case_base_name..." 76 | # if debug mode on, generate .ll also 77 | if [ $debug_mode = true ]; then 78 | bash -c "cminusfc -emit-llvm $case -o $ll_file" >>$LOG 2>&1 79 | fi 80 | # cminusfc compile to .s 81 | bash -c "cminusfc -S $case -o $asm_file" >>$LOG 2>&1 82 | check_return_value $? 0 "CE" "cminusfc compiler error" || continue 83 | 84 | # gcc compile asm to executable 85 | loongarch64-unknown-linux-gnu-gcc -static \ 86 | "$asm_file" "$io_dir"/io.c -o "$exe_file" \ 87 | >>$LOG 88 | check_return_value $? 0 "CE" "gcc compiler error" || continue 89 | 90 | # qemu run 91 | if [ -e "$in_file" ]; then 92 | exec_cmd="qemu-loongarch64 $exe_file >$out_file <$in_file" 93 | else 94 | exec_cmd="qemu-loongarch64 $exe_file >$out_file" 95 | fi 96 | bash -c "$exec_cmd" 97 | ret=$? 98 | # remove trailing null byte in the end line 99 | sed -i "\$s/\x00*$//" "$out_file" 100 | # append return value 101 | echo $ret >>"$out_file" 102 | 103 | # compare output 104 | diff --strip-trailing-cr "$std_out_file" "$out_file" -y >>$LOG 105 | check_return_value $? 0 "WA" "output differ, check $std_out_file and $out_file" || continue 106 | 107 | # ok 108 | printf "\033[1;32mOK\033[0m\n" 109 | done 110 | -------------------------------------------------------------------------------- /tests/3-codegen/autogen/testcases/0-io.cminus: -------------------------------------------------------------------------------- 1 | int main(void) { 2 | output(input()); 3 | return 0; 4 | } 5 | -------------------------------------------------------------------------------- /tests/3-codegen/autogen/testcases/0-io.in: -------------------------------------------------------------------------------- 1 | 1234 2 | -------------------------------------------------------------------------------- /tests/3-codegen/autogen/testcases/0-io.out: -------------------------------------------------------------------------------- 1 | 1234 2 | 0 3 | -------------------------------------------------------------------------------- /tests/3-codegen/autogen/testcases/1-return.cminus: -------------------------------------------------------------------------------- 1 | int main(void) { 2 | output(111); 3 | return 111; 4 | } 5 | -------------------------------------------------------------------------------- /tests/3-codegen/autogen/testcases/1-return.out: -------------------------------------------------------------------------------- 1 | 111 2 | 111 3 | -------------------------------------------------------------------------------- /tests/3-codegen/autogen/testcases/10-float.cminus: -------------------------------------------------------------------------------- 1 | int main(void) { 2 | float a; 3 | float b; 4 | float c; 5 | 6 | a = 1.1; 7 | b = 1.5; 8 | c = 1.2; 9 | 10 | outputFloat(a * b + c); 11 | return 0; 12 | } 13 | 14 | /* 15 | 用 gcc 编译此文件生成汇编代码时,命令为 gcc -include io.h -S 10-float.c 16 | 其中 io.h 位于 src/io/io.h, 17 | 18 | 也可以在本文件开头加上 void outputFloat(float x); 19 | */ 20 | -------------------------------------------------------------------------------- /tests/3-codegen/autogen/testcases/10-float.out: -------------------------------------------------------------------------------- 1 | 2.850000 2 | 0 3 | -------------------------------------------------------------------------------- /tests/3-codegen/autogen/testcases/11-floatcall.cminus: -------------------------------------------------------------------------------- 1 | /* float function call */ 2 | 3 | float mod(float x, float y) { 4 | int div; 5 | div = x / y; 6 | return x - div * y; 7 | } 8 | 9 | int main(void) { 10 | float a; 11 | float b; 12 | 13 | a = 11.2; 14 | b = 2.2; 15 | 16 | outputFloat(mod(a, b)); 17 | return 0; 18 | } 19 | -------------------------------------------------------------------------------- /tests/3-codegen/autogen/testcases/11-floatcall.out: -------------------------------------------------------------------------------- 1 | 0.200000 2 | 0 3 | -------------------------------------------------------------------------------- /tests/3-codegen/autogen/testcases/12-global.cminus: -------------------------------------------------------------------------------- 1 | int seed; 2 | 3 | int randomLCG(void) { 4 | seed = seed * 1103515245 + 12345; 5 | return seed; 6 | } 7 | 8 | int randBin(void) { 9 | if (randomLCG() > 0) 10 | return 1; 11 | else 12 | return 0; 13 | } 14 | 15 | /* random walk */ 16 | int returnToZeroSteps(void) { 17 | int x; 18 | int steps; 19 | 20 | x = 0; 21 | steps = 0; 22 | 23 | while (steps < 20) { 24 | if (randBin()) 25 | x = x + 1; 26 | else 27 | x = x - 1; 28 | 29 | steps = steps + 1; 30 | if (x == 0) 31 | return steps; 32 | } 33 | return 20; 34 | } 35 | 36 | int main(void) { 37 | int i; 38 | i = 0; 39 | 40 | seed = 3407; 41 | 42 | while (i < 20) { 43 | output(returnToZeroSteps()); 44 | i = i + 1; 45 | } 46 | return 0; 47 | } 48 | -------------------------------------------------------------------------------- /tests/3-codegen/autogen/testcases/12-global.out: -------------------------------------------------------------------------------- 1 | 4 2 | 2 3 | 2 4 | 4 5 | 8 6 | 2 7 | 2 8 | 2 9 | 2 10 | 2 11 | 6 12 | 2 13 | 10 14 | 8 15 | 4 16 | 2 17 | 20 18 | 2 19 | 2 20 | 8 21 | 0 22 | -------------------------------------------------------------------------------- /tests/3-codegen/autogen/testcases/13-complex.cminus: -------------------------------------------------------------------------------- 1 | /* 01 背包问题 */ 2 | 3 | int n; 4 | int m; 5 | 6 | int w[5]; 7 | int v[5]; 8 | 9 | int dp[66]; /* dp[n * 11 + size] 表示前 n 个物品放入容量为 size 的背包中的最大价值,初始化为 -1 */ 10 | 11 | int max(int a, int b) { 12 | if (a > b) 13 | return a; 14 | else 15 | return b; 16 | } 17 | 18 | /* 状态转移方程: 19 | dp[n][size] = max(dp[n - 1][size], dp[n - 1][size - w[n]] + v[n]) 20 | 边界条件: 21 | dp[n][size <= 0] = 0 22 | dp[0][size] = 0 */ 23 | 24 | int knapsack(int n, int size) { 25 | int result; 26 | if (size <= 0) 27 | return 0; 28 | if (n == 0) 29 | return 0; 30 | if (dp[n * 11 + size] >= 0) 31 | return dp[n * 11 + size]; 32 | 33 | if (size < w[n - 1]) 34 | result = knapsack(n - 1, size); 35 | else 36 | result = max(knapsack(n - 1, size), knapsack(n - 1, size - w[n - 1]) + v[n - 1]); 37 | 38 | dp[n * 11 + size] = result; 39 | return result; 40 | } 41 | 42 | int main(void) { 43 | int i; 44 | i = 0; 45 | 46 | n = 5; 47 | m = 10; 48 | w[0] = 2; 49 | w[1] = 2; 50 | w[2] = 6; 51 | w[3] = 5; 52 | w[4] = 4; 53 | 54 | v[0] = 6; 55 | v[1] = 3; 56 | v[2] = 5; 57 | v[3] = 4; 58 | v[4] = 6; 59 | 60 | while (i < 66) { 61 | dp[i] = 0 - 1; 62 | i = i + 1; 63 | } 64 | 65 | output(knapsack(n, m)); 66 | return 0; 67 | } 68 | -------------------------------------------------------------------------------- /tests/3-codegen/autogen/testcases/13-complex.out: -------------------------------------------------------------------------------- 1 | 15 2 | 0 3 | -------------------------------------------------------------------------------- /tests/3-codegen/autogen/testcases/2-calculate.cminus: -------------------------------------------------------------------------------- 1 | int main(void) { 2 | int a; 3 | int b; 4 | int c; 5 | 6 | a = 23; 7 | b = 25; 8 | c = 4; 9 | 10 | return a + b * c; 11 | } 12 | -------------------------------------------------------------------------------- /tests/3-codegen/autogen/testcases/2-calculate.out: -------------------------------------------------------------------------------- 1 | 123 2 | -------------------------------------------------------------------------------- /tests/3-codegen/autogen/testcases/3-output.cminus: -------------------------------------------------------------------------------- 1 | int main(void) { 2 | output(11); 3 | output(22222); 4 | return 0; 5 | } 6 | -------------------------------------------------------------------------------- /tests/3-codegen/autogen/testcases/3-output.out: -------------------------------------------------------------------------------- 1 | 11 2 | 22222 3 | 0 4 | -------------------------------------------------------------------------------- /tests/3-codegen/autogen/testcases/4-if.cminus: -------------------------------------------------------------------------------- 1 | int main(void) { 2 | int a; 3 | int b; 4 | int c; 5 | 6 | a = 11; 7 | b = 22; 8 | c = 33; 9 | 10 | /* max value */ 11 | if (a > b) { 12 | if (a > c) 13 | output(a); 14 | else 15 | output(c); 16 | } else { 17 | if (c < b) 18 | output(b); 19 | else 20 | output(c); 21 | } 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /tests/3-codegen/autogen/testcases/4-if.out: -------------------------------------------------------------------------------- 1 | 33 2 | 0 3 | -------------------------------------------------------------------------------- /tests/3-codegen/autogen/testcases/5-while.cminus: -------------------------------------------------------------------------------- 1 | int main(void) { 2 | int n; 3 | int i; 4 | 5 | n = 10; 6 | i = 0; 7 | 8 | while (i < n) { 9 | output(i); 10 | i = i + 1; 11 | } 12 | 13 | return 0; 14 | } 15 | -------------------------------------------------------------------------------- /tests/3-codegen/autogen/testcases/5-while.out: -------------------------------------------------------------------------------- 1 | 0 2 | 1 3 | 2 4 | 3 5 | 4 6 | 5 7 | 6 8 | 7 9 | 8 10 | 9 11 | 0 12 | -------------------------------------------------------------------------------- /tests/3-codegen/autogen/testcases/6-array.cminus: -------------------------------------------------------------------------------- 1 | int main(void) { 2 | int a[10]; 3 | int i; 4 | 5 | i = 0; 6 | a[0] = 11; 7 | a[4] = 22; 8 | a[9] = 33; 9 | 10 | output(a[0]); 11 | output(a[4]); 12 | output(a[9]); 13 | 14 | return 0; 15 | } 16 | -------------------------------------------------------------------------------- /tests/3-codegen/autogen/testcases/6-array.out: -------------------------------------------------------------------------------- 1 | 11 2 | 22 3 | 33 4 | 0 5 | -------------------------------------------------------------------------------- /tests/3-codegen/autogen/testcases/7-function.cminus: -------------------------------------------------------------------------------- 1 | int min(int a, int b) { 2 | if (a <= b) 3 | return a; 4 | else 5 | return b; 6 | } 7 | 8 | int main(void) { 9 | int a; 10 | int b; 11 | int c; 12 | 13 | a = 11; 14 | b = 22; 15 | c = 33; 16 | 17 | output(min(a, b)); 18 | output(min(b, c)); 19 | output(min(c, a)); 20 | return 0; 21 | } 22 | -------------------------------------------------------------------------------- /tests/3-codegen/autogen/testcases/7-function.out: -------------------------------------------------------------------------------- 1 | 11 2 | 22 3 | 11 4 | 0 5 | -------------------------------------------------------------------------------- /tests/3-codegen/autogen/testcases/8-store.cminus: -------------------------------------------------------------------------------- 1 | int store(int arr[], int index, int value) { 2 | arr[index] = value; 3 | return value; 4 | } 5 | 6 | int main(void) { 7 | int a[10]; 8 | int i; 9 | int sum; 10 | 11 | i = 0; 12 | while (i < 10) { 13 | store(a, i, i * 2); 14 | i = i + 1; 15 | } 16 | 17 | sum = 0; 18 | i = 0; 19 | while (i < 10) { 20 | sum = sum + a[i]; 21 | i = i + 1; 22 | } 23 | 24 | output(sum); 25 | return 0; 26 | } 27 | -------------------------------------------------------------------------------- /tests/3-codegen/autogen/testcases/8-store.out: -------------------------------------------------------------------------------- 1 | 90 2 | 0 3 | -------------------------------------------------------------------------------- /tests/3-codegen/autogen/testcases/9-fibonacci.cminus: -------------------------------------------------------------------------------- 1 | int fibonacci(int n) { 2 | if (n == 0) 3 | return 0; 4 | else if (n == 1) 5 | return 1; 6 | else 7 | return fibonacci(n - 1) + fibonacci(n - 2); 8 | } 9 | 10 | int main(void) { 11 | int n; 12 | int i; 13 | 14 | n = 10; 15 | i = 0; 16 | 17 | while (i < n) { 18 | output(fibonacci(i)); 19 | i = i + 1; 20 | } 21 | 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /tests/3-codegen/autogen/testcases/9-fibonacci.out: -------------------------------------------------------------------------------- 1 | 0 2 | 1 3 | 1 4 | 2 5 | 3 6 | 5 7 | 8 8 | 13 9 | 21 10 | 34 11 | 0 12 | -------------------------------------------------------------------------------- /tests/3-codegen/warmup/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable( 2 | stu_assign_codegen 3 | stu_cpp/assign_codegen.cpp 4 | ) 5 | target_link_libraries( 6 | stu_assign_codegen 7 | IR_lib 8 | codegen 9 | ) 10 | 11 | add_executable( 12 | stu_function_codegen 13 | stu_cpp/function_codegen.cpp 14 | ) 15 | target_link_libraries( 16 | stu_function_codegen 17 | IR_lib 18 | codegen 19 | ) 20 | 21 | add_executable( 22 | stu_icmp_codegen 23 | stu_cpp/icmp_codegen.cpp 24 | ) 25 | target_link_libraries( 26 | stu_icmp_codegen 27 | IR_lib 28 | codegen 29 | ) 30 | 31 | add_executable( 32 | stu_fcmp_codegen 33 | stu_cpp/fcmp_codegen.cpp 34 | ) 35 | target_link_libraries( 36 | stu_fcmp_codegen 37 | IR_lib 38 | codegen 39 | ) 40 | 41 | add_executable( 42 | stu_float_codegen 43 | stu_cpp/float_codegen.cpp 44 | ) 45 | target_link_libraries( 46 | stu_float_codegen 47 | IR_lib 48 | codegen 49 | ) 50 | 51 | add_executable( 52 | stu_global_codegen 53 | stu_cpp/global_codegen.cpp 54 | ) 55 | target_link_libraries( 56 | stu_global_codegen 57 | IR_lib 58 | codegen 59 | ) 60 | -------------------------------------------------------------------------------- /tests/3-codegen/warmup/ll_cases/assign.ll: -------------------------------------------------------------------------------- 1 | define i32 @main() { 2 | label_entry: 3 | %op0 = alloca [10 x i32] 4 | %op1 = getelementptr [10 x i32], [10 x i32]* %op0, i32 0, i32 0 5 | store i32 10, i32* %op1 6 | %op2 = getelementptr [10 x i32], [10 x i32]* %op0, i32 0, i32 1 7 | %op3 = load i32, i32* %op1 8 | %op4 = mul i32 %op3, 3 9 | store i32 %op4, i32* %op2 10 | %op5 = load i32, i32* %op2 11 | ret i32 %op5 12 | } 13 | -------------------------------------------------------------------------------- /tests/3-codegen/warmup/ll_cases/fcmp.ll: -------------------------------------------------------------------------------- 1 | define i32 @main() { 2 | label_entry: 3 | ; 5.5 (0x40b00000) > 1.0 (0x3f800000) 4 | %op0 = fcmp ugt float 0x4016000000000000, 0x3ff0000000000000 5 | %op1 = zext i1 %op0 to i32 6 | %op2 = icmp ne i32 %op1, 0 7 | br i1 %op2, label %label3, label %label4 8 | label3: ; preds = %label_entry 9 | ret i32 233 10 | label4: ; preds = %label_entry 11 | ret i32 0 12 | } 13 | -------------------------------------------------------------------------------- /tests/3-codegen/warmup/ll_cases/float.ll: -------------------------------------------------------------------------------- 1 | define i32 @main() { 2 | label_entry: 3 | %op0 = alloca float 4 | store float 0x40091eb860000000, float* %op0 ; 3.14, FP32 0x4048f5c3 5 | %op1 = load float, float* %op0 6 | %op2 = fptosi float %op1 to i32 7 | ret i32 %op2 8 | } 9 | -------------------------------------------------------------------------------- /tests/3-codegen/warmup/ll_cases/function.ll: -------------------------------------------------------------------------------- 1 | define i32 @callee(i32 %arg0) { 2 | label_entry: 3 | %op1 = alloca i32 4 | store i32 %arg0, i32* %op1 5 | %op2 = load i32, i32* %op1 6 | %op3 = mul i32 3, %op2 7 | ret i32 %op3 8 | } 9 | 10 | define i32 @main() { 11 | label_entry: 12 | %op0 = call i32 @callee(i32 110) 13 | ret i32 %op0 14 | } 15 | -------------------------------------------------------------------------------- /tests/3-codegen/warmup/ll_cases/global.ll: -------------------------------------------------------------------------------- 1 | @a = global i32 zeroinitializer 2 | 3 | define i32 @main() { 4 | label_entry: 5 | store i32 10, i32* @a 6 | %op0 = load i32, i32* @a 7 | ret i32 %op0 8 | } 9 | -------------------------------------------------------------------------------- /tests/3-codegen/warmup/ll_cases/icmp.ll: -------------------------------------------------------------------------------- 1 | define i32 @main() { 2 | label_entry: 3 | %op0 = icmp sgt i32 5, 1 4 | %op1 = zext i1 %op0 to i32 5 | %op2 = icmp ne i32 %op1, 0 6 | br i1 %op2, label %label3, label %label4 7 | label3: ; preds = %label_entry 8 | ret i32 233 9 | label4: ; preds = %label_entry 10 | ret i32 0 11 | } 12 | -------------------------------------------------------------------------------- /tests/4-mem2reg/cleanup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | rm -rf output log.txt 3 | -------------------------------------------------------------------------------- /tests/4-mem2reg/eval_lab4.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | project_dir=$(realpath ../../) 4 | io_dir=$(realpath "$project_dir"/src/io) 5 | output_dir=output 6 | suffix=cminus 7 | 8 | LOG=log.txt 9 | 10 | usage() { 11 | cat </dev/null 48 | 49 | mkdir -p $output_dir 50 | 51 | truncate -s 0 $LOG 52 | 53 | if [ $debug_mode = false ]; then 54 | exec 3>/dev/null 4>&1 5>&2 1>&3 2>&3 55 | else 56 | exec 3>&1 57 | fi 58 | 59 | if [ $debug_mode = false ]; then 60 | exec 1>&4 2>&5 61 | fi 62 | 63 | echo "[info] Start testing, using testcase dir: $test_dir" 64 | # asm 65 | for case in $testcases; do 66 | echo "==========$case==========" >>$LOG 67 | case_base_name=$(basename -s .$suffix "$case") 68 | std_out_file=$test_dir/$case_base_name.out 69 | in_file=$test_dir/$case_base_name.in 70 | asm_file=$output_dir/$case_base_name.s 71 | exe_file=$output_dir/$case_base_name 72 | out_file=$output_dir/$case_base_name.out 73 | ll_file=$output_dir/$case_base_name.ll 74 | 75 | echo -n "$case_base_name..." 76 | # if debug mode on, generate .ll also 77 | if [ $debug_mode = true ]; then 78 | bash -c "cminusfc -mem2reg -emit-llvm $case -o $ll_file" >>$LOG 2>&1 79 | fi 80 | # cminusfc compile to .s 81 | bash -c "cminusfc -S -mem2reg $case -o $asm_file" >>$LOG 2>&1 82 | check_return_value $? 0 "CE" "cminusfc compiler error" || continue 83 | 84 | # gcc compile asm to executable 85 | loongarch64-unknown-linux-gnu-gcc -static \ 86 | "$asm_file" "$io_dir"/io.c -o "$exe_file" \ 87 | >>$LOG 88 | check_return_value $? 0 "CE" "gcc compiler error" || continue 89 | 90 | # qemu run 91 | if [ -e "$in_file" ]; then 92 | exec_cmd="qemu-loongarch64 $exe_file >$out_file <$in_file" 93 | else 94 | exec_cmd="qemu-loongarch64 $exe_file >$out_file" 95 | fi 96 | bash -c "$exec_cmd" 97 | ret=$? 98 | # remove trailing null byte in the end line 99 | sed -i "\$s/\x00*$//" "$out_file" 100 | # append return value 101 | echo $ret >>"$out_file" 102 | 103 | # compare output 104 | diff --strip-trailing-cr "$std_out_file" "$out_file" -y >>$LOG 105 | check_return_value $? 0 "WA" "output differ, check $std_out_file and $out_file" || continue 106 | 107 | # ok 108 | printf "\033[1;32mOK\033[0m\n" 109 | done 110 | -------------------------------------------------------------------------------- /tests/4-mem2reg/functional-cases/0-io.cminus: -------------------------------------------------------------------------------- 1 | int main(void) { 2 | output(input()); 3 | return 0; 4 | } 5 | -------------------------------------------------------------------------------- /tests/4-mem2reg/functional-cases/0-io.in: -------------------------------------------------------------------------------- 1 | 1234 2 | -------------------------------------------------------------------------------- /tests/4-mem2reg/functional-cases/0-io.out: -------------------------------------------------------------------------------- 1 | 1234 2 | 0 3 | -------------------------------------------------------------------------------- /tests/4-mem2reg/functional-cases/1-return.cminus: -------------------------------------------------------------------------------- 1 | int main(void) { 2 | output(111); 3 | return 111; 4 | } 5 | -------------------------------------------------------------------------------- /tests/4-mem2reg/functional-cases/1-return.out: -------------------------------------------------------------------------------- 1 | 111 2 | 111 3 | -------------------------------------------------------------------------------- /tests/4-mem2reg/functional-cases/10-float.cminus: -------------------------------------------------------------------------------- 1 | int main(void) { 2 | float a; 3 | float b; 4 | float c; 5 | 6 | a = 1.1; 7 | b = 1.5; 8 | c = 1.2; 9 | 10 | outputFloat(a * b + c); 11 | return 0; 12 | } 13 | 14 | /* 15 | 用 gcc 编译此文件生成汇编代码时,命令为 gcc -include io.h -S 10-float.c 16 | 其中 io.h 位于 src/io/io.h, 17 | 18 | 也可以在本文件开头加上 void outputFloat(float x); 19 | */ 20 | -------------------------------------------------------------------------------- /tests/4-mem2reg/functional-cases/10-float.out: -------------------------------------------------------------------------------- 1 | 2.850000 2 | 0 3 | -------------------------------------------------------------------------------- /tests/4-mem2reg/functional-cases/11-floatcall.cminus: -------------------------------------------------------------------------------- 1 | /* float function call */ 2 | 3 | float mod(float x, float y) { 4 | int div; 5 | div = x / y; 6 | return x - div * y; 7 | } 8 | 9 | int main(void) { 10 | float a; 11 | float b; 12 | 13 | a = 11.2; 14 | b = 2.2; 15 | 16 | outputFloat(mod(a, b)); 17 | return 0; 18 | } 19 | -------------------------------------------------------------------------------- /tests/4-mem2reg/functional-cases/11-floatcall.out: -------------------------------------------------------------------------------- 1 | 0.200000 2 | 0 3 | -------------------------------------------------------------------------------- /tests/4-mem2reg/functional-cases/12-global.cminus: -------------------------------------------------------------------------------- 1 | int seed; 2 | 3 | int randomLCG(void) { 4 | seed = seed * 1103515245 + 12345; 5 | return seed; 6 | } 7 | 8 | int randBin(void) { 9 | if (randomLCG() > 0) 10 | return 1; 11 | else 12 | return 0; 13 | } 14 | 15 | /* random walk */ 16 | int returnToZeroSteps(void) { 17 | int x; 18 | int steps; 19 | 20 | x = 0; 21 | steps = 0; 22 | 23 | while (steps < 20) { 24 | if (randBin()) 25 | x = x + 1; 26 | else 27 | x = x - 1; 28 | 29 | steps = steps + 1; 30 | if (x == 0) 31 | return steps; 32 | } 33 | return 20; 34 | } 35 | 36 | int main(void) { 37 | int i; 38 | i = 0; 39 | 40 | seed = 3407; 41 | 42 | while (i < 20) { 43 | output(returnToZeroSteps()); 44 | i = i + 1; 45 | } 46 | return 0; 47 | } 48 | -------------------------------------------------------------------------------- /tests/4-mem2reg/functional-cases/12-global.out: -------------------------------------------------------------------------------- 1 | 4 2 | 2 3 | 2 4 | 4 5 | 8 6 | 2 7 | 2 8 | 2 9 | 2 10 | 2 11 | 6 12 | 2 13 | 10 14 | 8 15 | 4 16 | 2 17 | 20 18 | 2 19 | 2 20 | 8 21 | 0 22 | -------------------------------------------------------------------------------- /tests/4-mem2reg/functional-cases/13-complex.cminus: -------------------------------------------------------------------------------- 1 | /* 01 背包问题 */ 2 | 3 | int n; 4 | int m; 5 | 6 | int w[5]; 7 | int v[5]; 8 | 9 | int dp[66]; /* dp[n * 11 + size] 表示前 n 个物品放入容量为 size 的背包中的最大价值,初始化为 -1 */ 10 | 11 | int max(int a, int b) { 12 | if (a > b) 13 | return a; 14 | else 15 | return b; 16 | } 17 | 18 | /* 状态转移方程: 19 | dp[n][size] = max(dp[n - 1][size], dp[n - 1][size - w[n]] + v[n]) 20 | 边界条件: 21 | dp[n][size <= 0] = 0 22 | dp[0][size] = 0 */ 23 | 24 | int knapsack(int n, int size) { 25 | int result; 26 | if (size <= 0) 27 | return 0; 28 | if (n == 0) 29 | return 0; 30 | if (dp[n * 11 + size] >= 0) 31 | return dp[n * 11 + size]; 32 | 33 | if (size < w[n - 1]) 34 | result = knapsack(n - 1, size); 35 | else 36 | result = max(knapsack(n - 1, size), knapsack(n - 1, size - w[n - 1]) + v[n - 1]); 37 | 38 | dp[n * 11 + size] = result; 39 | return result; 40 | } 41 | 42 | int main(void) { 43 | int i; 44 | i = 0; 45 | 46 | n = 5; 47 | m = 10; 48 | w[0] = 2; 49 | w[1] = 2; 50 | w[2] = 6; 51 | w[3] = 5; 52 | w[4] = 4; 53 | 54 | v[0] = 6; 55 | v[1] = 3; 56 | v[2] = 5; 57 | v[3] = 4; 58 | v[4] = 6; 59 | 60 | while (i < 66) { 61 | dp[i] = 0 - 1; 62 | i = i + 1; 63 | } 64 | 65 | output(knapsack(n, m)); 66 | return 0; 67 | } 68 | -------------------------------------------------------------------------------- /tests/4-mem2reg/functional-cases/13-complex.out: -------------------------------------------------------------------------------- 1 | 15 2 | 0 3 | -------------------------------------------------------------------------------- /tests/4-mem2reg/functional-cases/2-calculate.cminus: -------------------------------------------------------------------------------- 1 | int main(void) { 2 | int a; 3 | int b; 4 | int c; 5 | 6 | a = 23; 7 | b = 25; 8 | c = 4; 9 | 10 | return a + b * c; 11 | } 12 | -------------------------------------------------------------------------------- /tests/4-mem2reg/functional-cases/2-calculate.out: -------------------------------------------------------------------------------- 1 | 123 2 | -------------------------------------------------------------------------------- /tests/4-mem2reg/functional-cases/3-output.cminus: -------------------------------------------------------------------------------- 1 | int main(void) { 2 | output(11); 3 | output(22222); 4 | return 0; 5 | } 6 | -------------------------------------------------------------------------------- /tests/4-mem2reg/functional-cases/3-output.out: -------------------------------------------------------------------------------- 1 | 11 2 | 22222 3 | 0 4 | -------------------------------------------------------------------------------- /tests/4-mem2reg/functional-cases/4-if.cminus: -------------------------------------------------------------------------------- 1 | int main(void) { 2 | int a; 3 | int b; 4 | int c; 5 | 6 | a = 11; 7 | b = 22; 8 | c = 33; 9 | 10 | /* max value */ 11 | if (a > b) { 12 | if (a > c) 13 | output(a); 14 | else 15 | output(c); 16 | } else { 17 | if (c < b) 18 | output(b); 19 | else 20 | output(c); 21 | } 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /tests/4-mem2reg/functional-cases/4-if.out: -------------------------------------------------------------------------------- 1 | 33 2 | 0 3 | -------------------------------------------------------------------------------- /tests/4-mem2reg/functional-cases/5-while.cminus: -------------------------------------------------------------------------------- 1 | int main(void) { 2 | int n; 3 | int i; 4 | 5 | n = 10; 6 | i = 0; 7 | 8 | while (i < n) { 9 | output(i); 10 | i = i + 1; 11 | } 12 | 13 | return 0; 14 | } 15 | -------------------------------------------------------------------------------- /tests/4-mem2reg/functional-cases/5-while.out: -------------------------------------------------------------------------------- 1 | 0 2 | 1 3 | 2 4 | 3 5 | 4 6 | 5 7 | 6 8 | 7 9 | 8 10 | 9 11 | 0 12 | -------------------------------------------------------------------------------- /tests/4-mem2reg/functional-cases/6-array.cminus: -------------------------------------------------------------------------------- 1 | int main(void) { 2 | int a[10]; 3 | int i; 4 | 5 | i = 0; 6 | a[0] = 11; 7 | a[4] = 22; 8 | a[9] = 33; 9 | 10 | output(a[0]); 11 | output(a[4]); 12 | output(a[9]); 13 | 14 | return 0; 15 | } 16 | -------------------------------------------------------------------------------- /tests/4-mem2reg/functional-cases/6-array.out: -------------------------------------------------------------------------------- 1 | 11 2 | 22 3 | 33 4 | 0 5 | -------------------------------------------------------------------------------- /tests/4-mem2reg/functional-cases/7-function.cminus: -------------------------------------------------------------------------------- 1 | int min(int a, int b) { 2 | if (a <= b) 3 | return a; 4 | else 5 | return b; 6 | } 7 | 8 | int main(void) { 9 | int a; 10 | int b; 11 | int c; 12 | 13 | a = 11; 14 | b = 22; 15 | c = 33; 16 | 17 | output(min(a, b)); 18 | output(min(b, c)); 19 | output(min(c, a)); 20 | return 0; 21 | } 22 | -------------------------------------------------------------------------------- /tests/4-mem2reg/functional-cases/7-function.out: -------------------------------------------------------------------------------- 1 | 11 2 | 22 3 | 11 4 | 0 5 | -------------------------------------------------------------------------------- /tests/4-mem2reg/functional-cases/8-store.cminus: -------------------------------------------------------------------------------- 1 | int store(int arr[], int index, int value) { 2 | arr[index] = value; 3 | return value; 4 | } 5 | 6 | int main(void) { 7 | int a[10]; 8 | int i; 9 | int sum; 10 | 11 | i = 0; 12 | while (i < 10) { 13 | store(a, i, i * 2); 14 | i = i + 1; 15 | } 16 | 17 | sum = 0; 18 | i = 0; 19 | while (i < 10) { 20 | sum = sum + a[i]; 21 | i = i + 1; 22 | } 23 | 24 | output(sum); 25 | return 0; 26 | } 27 | -------------------------------------------------------------------------------- /tests/4-mem2reg/functional-cases/8-store.out: -------------------------------------------------------------------------------- 1 | 90 2 | 0 3 | -------------------------------------------------------------------------------- /tests/4-mem2reg/functional-cases/9-fibonacci.cminus: -------------------------------------------------------------------------------- 1 | int fibonacci(int n) { 2 | if (n == 0) 3 | return 0; 4 | else if (n == 1) 5 | return 1; 6 | else 7 | return fibonacci(n - 1) + fibonacci(n - 2); 8 | } 9 | 10 | int main(void) { 11 | int n; 12 | int i; 13 | 14 | n = 10; 15 | i = 0; 16 | 17 | while (i < n) { 18 | output(fibonacci(i)); 19 | i = i + 1; 20 | } 21 | 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /tests/4-mem2reg/functional-cases/9-fibonacci.out: -------------------------------------------------------------------------------- 1 | 0 2 | 1 3 | 1 4 | 2 5 | 3 6 | 5 7 | 8 8 | 13 9 | 21 10 | 34 11 | 0 12 | -------------------------------------------------------------------------------- /tests/4-mem2reg/performance-cases/const-prop.cminus: -------------------------------------------------------------------------------- 1 | void main(void) { 2 | int c; 3 | int a; 4 | int b; 5 | int d; 6 | int f; 7 | int g; 8 | int loopCnt; 9 | loopCnt = input(); 10 | c = 0; 11 | a = 0; 12 | g = 0; 13 | while (c < loopCnt) { 14 | a = 1.23456 * 5.73478 * 2.3333 * 4.3673 * 6.34636; 15 | b = a * a * a * a * a * a; 16 | d = b * b * b * b * b * b; 17 | f = d * d * d * d * d * d; 18 | g = f * f * f * f * f * f; 19 | c = c + 1; 20 | } 21 | output(g); 22 | return; 23 | } -------------------------------------------------------------------------------- /tests/4-mem2reg/performance-cases/const-prop.in: -------------------------------------------------------------------------------- 1 | 100000000 2 | -------------------------------------------------------------------------------- /tests/4-mem2reg/performance-cases/const-prop.out: -------------------------------------------------------------------------------- 1 | 711082625 2 | 0 3 | -------------------------------------------------------------------------------- /tests/4-mem2reg/performance-cases/loop.cminus: -------------------------------------------------------------------------------- 1 | int main(void) { 2 | int a; 3 | a = 1; 4 | 5 | while (a < 999999999) { 6 | a = a + 1; 7 | } 8 | return a; 9 | } 10 | -------------------------------------------------------------------------------- /tests/4-mem2reg/performance-cases/loop.out: -------------------------------------------------------------------------------- 1 | 255 2 | -------------------------------------------------------------------------------- /tests/4-mem2reg/performance-cases/transpose.cminus: -------------------------------------------------------------------------------- 1 | int matrix[20000000]; 2 | int ad[100000]; 3 | 4 | int len; 5 | 6 | void readarray(void) { 7 | int cnt; 8 | cnt = 0; 9 | while (cnt < len) { 10 | ad[cnt] = input(); 11 | cnt = cnt + 1; 12 | } 13 | } 14 | 15 | int transpose(int n, int matrix[], int rowsize) { 16 | int colsize; 17 | int i; 18 | int j; 19 | int curr; 20 | colsize = n / rowsize; 21 | i = 0; 22 | j = 0; 23 | while (i < colsize) { 24 | j = 0; 25 | while (j < rowsize) { 26 | if (i < j) { 27 | j = j + 1; 28 | } else { 29 | curr = matrix[i * rowsize + j]; 30 | matrix[j * colsize + i] = matrix[i * rowsize + j]; 31 | matrix[i * rowsize + j] = curr; 32 | j = j + 1; 33 | } 34 | } 35 | i = i + 1; 36 | } 37 | return 0 - 1; 38 | } 39 | 40 | int main(void) { 41 | int n; 42 | int i; 43 | int ans; 44 | n = input(); 45 | len = input(); 46 | readarray(); 47 | i = 0; 48 | 49 | while (i < n) { 50 | matrix[i] = i; 51 | i = i + 1; 52 | } 53 | i = 0; 54 | while (i < len) { 55 | transpose(n, matrix, ad[i]); 56 | i = i + 1; 57 | } 58 | 59 | ans = 0; 60 | i = 0; 61 | while (i < len) { 62 | ans = ans + i * i * matrix[i]; 63 | i = i + 1; 64 | } 65 | if (ans < 0) { 66 | ans = 0 - ans; 67 | } 68 | output(ans); 69 | return 0; 70 | } 71 | -------------------------------------------------------------------------------- /tests/4-mem2reg/performance-cases/transpose.in: -------------------------------------------------------------------------------- 1 | 10000000 2 | 30 3 | 2 4 | 5 5 | 4 6 | 25 7 | 8 8 | 125 9 | 16 10 | 625 11 | 32 12 | 3125 13 | 2 14 | 5 15 | 4 16 | 25 17 | 8 18 | 125 19 | 16 20 | 625 21 | 32 22 | 3125 23 | 2 24 | 5 25 | 4 26 | 25 27 | 8 28 | 125 29 | 16 30 | 625 31 | 32 32 | 3125 33 | -------------------------------------------------------------------------------- /tests/4-mem2reg/performance-cases/transpose.out: -------------------------------------------------------------------------------- 1 | 1042523985 2 | 0 3 | -------------------------------------------------------------------------------- /tests/4-mem2reg/test_perf.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | project_dir=$(realpath ../../) 4 | io_dir=$(realpath "$project_dir"/src/io) 5 | output_dir=output 6 | suffix=cminus 7 | 8 | LOG=log.txt 9 | 10 | check_return_value() { 11 | rv=$1 12 | expected_rv=$2 13 | fail_msg=$3 14 | detail=$4 15 | if [ "$rv" -eq "$expected_rv" ]; then 16 | return 0 17 | else 18 | printf "\033[1;31m%s: \033[0m%s\n" "$fail_msg" "$detail" 19 | return 1 20 | fi 21 | } 22 | 23 | test_dir=./performance-cases 24 | testcases=$(ls "$test_dir"/*."$suffix" | sort -V) 25 | check_return_value $? 0 "PATH" "unable to access to '$test_dir'" || exit 1 26 | 27 | # hide stderr in the script 28 | # exec 2>/dev/null 29 | 30 | mkdir -p $output_dir 31 | 32 | truncate -s 0 $LOG 33 | 34 | echo "[info] Start testing, using testcase dir: $test_dir" 35 | # asm 36 | for case in $testcases; do 37 | echo "==========$case==========" >>$LOG 38 | case_base_name=$(basename -s .$suffix "$case") 39 | in_file=$test_dir/$case_base_name.in 40 | asm_mem2reg_on=$output_dir/${case_base_name}-mem2reg-on.s 41 | asm_mem2reg_off=$output_dir/${case_base_name}-mem2reg-off.s 42 | exe_mem2reg_on=$output_dir/${case_base_name}-mem2reg-on 43 | exe_mem2reg_off=$output_dir/${case_base_name}-mem2reg-off 44 | 45 | echo "==========$case==========" 46 | #### mem2reg off 47 | # cminusfc compile to .s 48 | bash -c "cminusfc -S $case -o $asm_mem2reg_off" >>$LOG 2>&1 49 | check_return_value $? 0 "CE" "cminusfc compiler error" || continue 50 | # gcc compile asm to executable 51 | loongarch64-unknown-linux-gnu-gcc -static \ 52 | "$asm_mem2reg_off" "$io_dir"/io.c -o "$exe_mem2reg_off" \ 53 | >>$LOG 54 | check_return_value $? 0 "CE" "gcc compiler error" || continue 55 | 56 | #### mem2reg on 57 | # cminusfc compile to .s 58 | bash -c "cminusfc -S -mem2reg $case -o $asm_mem2reg_on" >>$LOG 2>&1 59 | check_return_value $? 0 "CE" "cminusfc compiler error" || continue 60 | # gcc compile asm to executable 61 | loongarch64-unknown-linux-gnu-gcc -static \ 62 | "$asm_mem2reg_on" "$io_dir"/io.c -o "$exe_mem2reg_on" \ 63 | >>$LOG 64 | check_return_value $? 0 "CE" "gcc compiler error" || continue 65 | 66 | echo "==========mem2reg off" 67 | if [ -e "$in_file" ]; then 68 | exec_cmd="qemu-loongarch64 $exe_mem2reg_off >/dev/null <$in_file" 69 | else 70 | exec_cmd="qemu-loongarch64 $exe_mem2reg_off >/dev/null" 71 | fi 72 | time bash -c "$exec_cmd" 73 | echo "==========mem2reg on" 74 | if [ -e "$in_file" ]; then 75 | exec_cmd="qemu-loongarch64 $exe_mem2reg_on >/dev/null <$in_file" 76 | else 77 | exec_cmd="qemu-loongarch64 $exe_mem2reg_on >/dev/null" 78 | fi 79 | time bash -c "$exec_cmd" 80 | 81 | done 82 | -------------------------------------------------------------------------------- /tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory("2-ir-gen/warmup") 2 | add_subdirectory("3-codegen/warmup") 3 | -------------------------------------------------------------------------------- /tests/testcases_general/1-return.cminus: -------------------------------------------------------------------------------- 1 | void main(void) { return; } 2 | -------------------------------------------------------------------------------- /tests/testcases_general/1-return.out: -------------------------------------------------------------------------------- 1 | 0 2 | -------------------------------------------------------------------------------- /tests/testcases_general/10-funcall.cminus: -------------------------------------------------------------------------------- 1 | void test(int a) { 2 | return; 3 | } 4 | 5 | void main(void) { 6 | int a; 7 | a = 10; 8 | test(a); 9 | return; 10 | } 11 | -------------------------------------------------------------------------------- /tests/testcases_general/10-funcall.out: -------------------------------------------------------------------------------- 1 | 0 2 | -------------------------------------------------------------------------------- /tests/testcases_general/11-funcall_chain.cminus: -------------------------------------------------------------------------------- 1 | int addone(int a) { return a + 1; } 2 | int main(void) { 3 | int result; 4 | result = addone(addone(addone(addone(1230)))); 5 | return result; 6 | } 7 | -------------------------------------------------------------------------------- /tests/testcases_general/11-funcall_chain.out: -------------------------------------------------------------------------------- 1 | 210 2 | -------------------------------------------------------------------------------- /tests/testcases_general/12-funcall_recursion.cminus: -------------------------------------------------------------------------------- 1 | int factorial(int a) { 2 | if(a==0) 3 | return 1; 4 | else 5 | return a*factorial(a-1); 6 | } 7 | int main(void) { 8 | int result; 9 | result = factorial(10); 10 | return result; 11 | } 12 | -------------------------------------------------------------------------------- /tests/testcases_general/12-funcall_recursion.out: -------------------------------------------------------------------------------- 1 | 0 2 | -------------------------------------------------------------------------------- /tests/testcases_general/13-if_stmt.cminus: -------------------------------------------------------------------------------- 1 | void main(void) { 2 | int a; 3 | a = 2; 4 | if (a) 5 | a = 3; 6 | a = 4; 7 | return; 8 | } 9 | -------------------------------------------------------------------------------- /tests/testcases_general/13-if_stmt.out: -------------------------------------------------------------------------------- 1 | 0 2 | -------------------------------------------------------------------------------- /tests/testcases_general/14-while_stmt.cminus: -------------------------------------------------------------------------------- 1 | void main(void) { 2 | int i; 3 | i = 10; 4 | while (i) { 5 | i = i - 1; 6 | } 7 | return; 8 | } 9 | -------------------------------------------------------------------------------- /tests/testcases_general/14-while_stmt.out: -------------------------------------------------------------------------------- 1 | 0 2 | -------------------------------------------------------------------------------- /tests/testcases_general/15-if_while.cminus: -------------------------------------------------------------------------------- 1 | int main(void) { 2 | int i; 3 | int a; 4 | int b; 5 | a = 0; 6 | b = 0; 7 | i = 10; 8 | while (i) { 9 | i = i - 1; 10 | if (i < 5) 11 | a = a + i; 12 | else { 13 | b = b + i; 14 | } 15 | } 16 | return a + b; 17 | } 18 | -------------------------------------------------------------------------------- /tests/testcases_general/15-if_while.out: -------------------------------------------------------------------------------- 1 | 45 2 | -------------------------------------------------------------------------------- /tests/testcases_general/16-if_chain.cminus: -------------------------------------------------------------------------------- 1 | int main(void) { 2 | int a; 3 | int b; 4 | int c; 5 | c = 0; 6 | a = 2; 7 | b = 1; 8 | if (b) 9 | if (c) 10 | a = 4; 11 | else 12 | a = 3; 13 | return a; 14 | } 15 | -------------------------------------------------------------------------------- /tests/testcases_general/16-if_chain.out: -------------------------------------------------------------------------------- 1 | 3 2 | -------------------------------------------------------------------------------- /tests/testcases_general/17-while_chain.cminus: -------------------------------------------------------------------------------- 1 | int main(void) { 2 | int i; 3 | int j; 4 | i = 10; 5 | while (i) { 6 | i = i - 1; 7 | j = i; 8 | while(j) { 9 | j = j - 1; 10 | } 11 | } 12 | return i + j; 13 | } -------------------------------------------------------------------------------- /tests/testcases_general/17-while_chain.out: -------------------------------------------------------------------------------- 1 | 0 2 | -------------------------------------------------------------------------------- /tests/testcases_general/18-global_var.cminus: -------------------------------------------------------------------------------- 1 | int a; 2 | int main(void) { 3 | a = 10; 4 | return a; 5 | } -------------------------------------------------------------------------------- /tests/testcases_general/18-global_var.out: -------------------------------------------------------------------------------- 1 | 10 2 | -------------------------------------------------------------------------------- /tests/testcases_general/19-global_local_var.cminus: -------------------------------------------------------------------------------- 1 | int a; 2 | void GlobalAssign(void) { 3 | a = 10; 4 | return; 5 | } 6 | int main(void) { 7 | int a; 8 | GlobalAssign(); 9 | a = 20; 10 | return a; 11 | } 12 | -------------------------------------------------------------------------------- /tests/testcases_general/19-global_local_var.out: -------------------------------------------------------------------------------- 1 | 20 2 | -------------------------------------------------------------------------------- /tests/testcases_general/2-decl_int.cminus: -------------------------------------------------------------------------------- 1 | void main(void) { 2 | int a; 3 | return; 4 | } 5 | -------------------------------------------------------------------------------- /tests/testcases_general/2-decl_int.out: -------------------------------------------------------------------------------- 1 | 0 2 | -------------------------------------------------------------------------------- /tests/testcases_general/20-gcd_array.cminus: -------------------------------------------------------------------------------- 1 | int x[1]; 2 | int y[1]; 3 | 4 | int gcd(int u, int v) { 5 | if (v == 0) 6 | return u; 7 | else 8 | return gcd(v, u - u / v * v); 9 | } 10 | 11 | int funArray(int u[], int v[]) { 12 | int a; 13 | int b; 14 | int temp; 15 | a = u[0]; 16 | b = v[0]; 17 | if (a < b) { 18 | temp = a; 19 | a = b; 20 | b = temp; 21 | } 22 | return gcd(a, b); 23 | } 24 | 25 | int main(void) { 26 | x[0] = 90; 27 | y[0] = 18; 28 | return funArray(x, y); 29 | } -------------------------------------------------------------------------------- /tests/testcases_general/20-gcd_array.out: -------------------------------------------------------------------------------- 1 | 18 2 | -------------------------------------------------------------------------------- /tests/testcases_general/21-comment.cminus: -------------------------------------------------------------------------------- 1 | /*this is comment*/ 2 | void main(void) { return; } -------------------------------------------------------------------------------- /tests/testcases_general/21-comment.out: -------------------------------------------------------------------------------- 1 | 0 2 | -------------------------------------------------------------------------------- /tests/testcases_general/3-decl_float.cminus: -------------------------------------------------------------------------------- 1 | void main(void) { 2 | float a; 3 | return; 4 | } 5 | -------------------------------------------------------------------------------- /tests/testcases_general/3-decl_float.out: -------------------------------------------------------------------------------- 1 | 0 2 | -------------------------------------------------------------------------------- /tests/testcases_general/4-decl_int_array.cminus: -------------------------------------------------------------------------------- 1 | void main(void) { 2 | int a[10]; 3 | return; 4 | } 5 | -------------------------------------------------------------------------------- /tests/testcases_general/4-decl_int_array.out: -------------------------------------------------------------------------------- 1 | 0 2 | -------------------------------------------------------------------------------- /tests/testcases_general/5-decl_float_array.cminus: -------------------------------------------------------------------------------- 1 | void main(void) { 2 | float a[10]; 3 | return; 4 | } 5 | -------------------------------------------------------------------------------- /tests/testcases_general/5-decl_float_array.out: -------------------------------------------------------------------------------- 1 | 0 2 | -------------------------------------------------------------------------------- /tests/testcases_general/6-num_add_int.cminus: -------------------------------------------------------------------------------- 1 | int main(void) { 2 | int a; 3 | a = 1000 + 234; 4 | return a; 5 | } 6 | -------------------------------------------------------------------------------- /tests/testcases_general/6-num_add_int.out: -------------------------------------------------------------------------------- 1 | 210 2 | -------------------------------------------------------------------------------- /tests/testcases_general/7-assign_int_var_local.cminus: -------------------------------------------------------------------------------- 1 | int main(void) { 2 | int a; 3 | a = 1234; 4 | return a; 5 | } 6 | -------------------------------------------------------------------------------- /tests/testcases_general/7-assign_int_var_local.out: -------------------------------------------------------------------------------- 1 | 210 2 | -------------------------------------------------------------------------------- /tests/testcases_general/8-assign_int_array_local.cminus: -------------------------------------------------------------------------------- 1 | int main(void) { 2 | int a[10]; 3 | a[3] = 1234; 4 | return a[3]; 5 | } 6 | -------------------------------------------------------------------------------- /tests/testcases_general/8-assign_int_array_local.out: -------------------------------------------------------------------------------- 1 | 210 2 | -------------------------------------------------------------------------------- /tests/testcases_general/9-assign_cast.cminus: -------------------------------------------------------------------------------- 1 | int main(void) { 2 | int a; 3 | int b; 4 | a = 1 < 3; 5 | b = 2 + 2.4; 6 | return a + b; 7 | } 8 | -------------------------------------------------------------------------------- /tests/testcases_general/9-assign_cast.out: -------------------------------------------------------------------------------- 1 | 5 2 | -------------------------------------------------------------------------------- /tests/testcases_general/README.md: -------------------------------------------------------------------------------- 1 | | case name | 语法特性 | 2 | | ---- | ---- | 3 | | 1-return.cminus | base case | 4 | | 2-decl_int.cminus | int变量声明 | 5 | | 3-decl_float.cminus | float变量声明 | 6 | | 4-decl_int_array.cminus | int数组变量声明 | 7 | | 5-decl_float_array.cminus | float数组变量声明 | 8 | | 6-num_add_int.cminus | 加法运算 | 9 | | 7-assign_int_var_local.cminus | 赋值语句 | 10 | | 8-assign_int_array_local.cminus | 数组赋值语句 | 11 | | 9-assign_cast.cminus | 类型转换情况 | 12 | | 10-funcall.cminus | 函数调用 | 13 | | 11-funcall_chain.cminus | 函数嵌套调用 | 14 | | 12-funcall_recursion.cminus | 函数递归 | 15 | | 13-if_stmt.cminus | if选择语句 | 16 | | 14-while_stmt.cminus | while循环语句 | 17 | | 15-if_while.cminus | if与while语句嵌套 | 18 | | 16-if_recursion.cminus | if嵌套 | 19 | | 17-while_recursion.cminus | while嵌套 | 20 | | 18-global_var.cminus | 全局变量 | 21 | | 19-global_local_var.cminus | 全局变量与局部变量重名 | 22 | | 20-gcd_array.cminus | 稍微复杂一些的case | --------------------------------------------------------------------------------