├── CMakeLists.txt ├── LICENSE ├── README.md ├── SysY_def.pdf ├── SysY_lib.pdf ├── frontend.zip ├── include ├── CodeGen │ ├── Analyzer.hh │ ├── CodeGen.hh │ └── InstructionsGen.hh ├── HIR │ ├── AccumulatePattern.h │ ├── BBExps.h │ └── LoopMerge.h ├── IR │ ├── BaseBlock.h │ ├── BasicBlock.h │ ├── Constant.h │ ├── Function.h │ ├── GlobalVariable.h │ ├── HighBlock.h │ ├── IRBuilder.h │ ├── Instruction.h │ ├── Module.h │ ├── Type.h │ ├── User.h │ └── Value.h ├── IRBuilder │ └── SYSYCBuilder.h ├── OptimizePass │ ├── ActiveVars.h │ ├── BBCommonSubExper.h │ ├── BBConstPropagation.h │ ├── BranchMerge.h │ ├── CondSimplify.h │ ├── ConstFlod.h │ ├── ConstLoopExpansion.h │ ├── ControlTree.h │ ├── DeadCodeEliminate.h │ ├── Dominators.h │ ├── FunctionInline.h │ ├── FunctionOptimization.h │ ├── GlobalVariableLocal.h │ ├── HIRToMIR.h │ ├── HighIRsimplyCFG.h │ ├── IRCheck.h │ ├── InstructionSchedule.h │ ├── LoopFind.h │ ├── LoopInvariant.h │ ├── LowerIR.h │ ├── MergeCond.h │ ├── Multithreading.h │ ├── PassManager.h │ ├── PowerArray.h │ ├── ReachDefinitions.h │ ├── RefactorPartIns.h │ ├── RegisterAllocation.h │ ├── ReturnVal.h │ ├── SimplifyCFG.h │ ├── SparseCondConstPropagation.h │ ├── Vectorization.h │ └── mem2reg.h ├── front │ ├── FlexLexer.h │ ├── location.hh │ ├── position.hh │ ├── stack.hh │ ├── sysyFlexLexer.hh │ ├── sysy_driver.hh │ └── sysy_parser.hh └── syntax_tree │ └── syntax_tree.hh ├── libsysy.a ├── mt.png └── src ├── CodeGen ├── Analyzer.cc ├── CMakeLists.txt ├── CodeGen.cc ├── InstructionsGen.cc └── RegAlloc.cc ├── HIR ├── AccumulatePattern.cc ├── BBExps.cc └── LoopMerge.cc ├── IR ├── BaseBlock.cc ├── BasicBlock.cc ├── CMakeLists.txt ├── Constant.cc ├── Function.cc ├── GlobalVariable.cc ├── Instruction.cc ├── Module.cc ├── Type.cc ├── User.cc └── Value.cc ├── IRBuilder ├── CMakeLists.txt ├── SYSYCBuilder.cc └── monkeyType.cc ├── OptimizePass ├── ActiveVars.cc ├── BBCommonSubExper.cc ├── BBConstPropagation.cc ├── BranchMerge.cc ├── CMakeLists.txt ├── CondSimplify.cc ├── ConstFlod.cc ├── ConstLoopExpansion.cc ├── DeadCodeEliminate.cc ├── Dominators.cc ├── FunctionInline.cc ├── FunctionOptimization.cc ├── GlobalVariableLocal.cc ├── HIRToMIR.cc ├── HighIRsimplyCFG.cc ├── IRCheck.cc ├── InstructionSchedule.cc ├── LoopFind.cc ├── LoopInvariant.cc ├── LowerIR.cc ├── MergeCond.cc ├── Multithreading.cc ├── PowerArray.cc ├── ReachDefinitions.cc ├── RefactorPartIns.cc ├── RegisterAllocation.cc ├── SimplifyCFG.cc ├── SparseCondConstPropagation.cc ├── Vectorization.cc └── mem2reg.cc ├── front ├── CMakeLists.txt ├── sysy.cc.bak ├── sysy_driver.cc ├── sysy_parser.cc └── sysy_scanner.cc ├── main.cc └── syntax_tree ├── CMakeLists.txt └── syntax_tree.cc /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.16) 2 | SET(CMAKE_CXX_COMPILER /usr/bin/clang++) 3 | project(SYSYCompiler) 4 | 5 | SET(CMAKE_BUILD_TYPE "Debug") 6 | SET(CMAKE_CXX_FLAGS "$ENV{CXXFLAGS} -O0 -Wall -g2 -ggdb") 7 | SET(CMAKE_CXX_FLAGS_RELEASE "$ENV{CXXFLAGS} -O3 -Wall") 8 | 9 | # Import LLVM 10 | find_package(LLVM REQUIRED CONFIG) 11 | message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}") 12 | message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}") 13 | llvm_map_components_to_libnames( 14 | llvm_libs 15 | all 16 | ) 17 | 18 | include_directories(${LLVM_INCLUDE_DIRS}) 19 | add_definitions(${LLVM_DEFINITIONS}) 20 | 21 | 22 | # Import LLVM 23 | 24 | INCLUDE_DIRECTORIES(include/front) 25 | 26 | include_directories(include/syntax_tree) 27 | 28 | include_directories(include) 29 | include_directories(include/IR) 30 | include_directories(include/IRBuilder) 31 | include_directories(include/CodeGen) 32 | include_directories(include/OptimizePass) 33 | #include_directories(include/llvm-builder) 34 | include_directories(include/HIR) 35 | 36 | add_subdirectory(src/front) 37 | 38 | add_subdirectory(src/syntax_tree) 39 | add_subdirectory(src/IRBuilder) 40 | add_subdirectory(src/IR) 41 | add_subdirectory(src/CodeGen) 42 | add_subdirectory(src/OptimizePass) 43 | #add_subdirectory(src/llvm-builder) 44 | 45 | set(CMAKE_CXX_STANDARD 17) 46 | 47 | add_executable( 48 | compiler 49 | src/main.cc 50 | ) 51 | 52 | target_link_libraries( 53 | compiler 54 | IRBuilder 55 | driver 56 | IR_lib 57 | Pass 58 | CodeGen 59 | # ControlTree 60 | ActiveVars 61 | RegisterAllocation 62 | ) 63 | 64 | install( 65 | TARGETS compiler 66 | RUNTIME DESTINATION bin 67 | ) 68 | 69 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CSC2020-USTC-FlammingMyCompiler 2 | 3 | 2020 年全国大学生计算机系统能力大赛编译系统设计赛项目 4 | 5 | 队伍学校:中国科学技术大学 6 | 7 | 队伍名称:燃烧我的编译器 8 | 9 | 队伍成员:陈清源、黄奕桐、曾明亮、章耀辉 10 | 11 | ## 项目简介 12 | 13 | 这是一个 SysY 语言(简化的 C 语言)的编译器,目标平台是树莓派(ARMv8)(32bit)。 14 | 15 | 这个编译器有很强的优化能力,在比赛提供的大多数性能测试用例上超过了 GCC -O3 的优化效果。 16 | 17 | 这个项目在决赛取得了最好的成绩。[链接](https://compiler.educg.net/) 18 | 19 | ## 如何构建与运行本项目 20 | 21 | ### 构建 22 | 23 | 进入项目根目录然后执行: 24 | 25 | ```bash 26 | mkdir build && cd build && cmake .. && make -j 4 27 | ``` 28 | 29 | ### 运行 30 | 31 | 使用 build 目录下的可执行文件 compiler 即可将源代码文件(test.sy)编译得到汇编文件(test.s): 32 | 33 | ```bash 34 | echo "int main() { int a = getint(); putint(a * a); }" > test.sy 35 | ``` 36 | ```bash 37 | ./compiler test.sy 38 | ``` 39 | ```bash 40 | cat test.s 41 | ``` 42 | 43 | ### 测试 44 | 45 | 用 GCC 将汇编文件(test.s)汇编并与 SysY 运行时库(libsysy.a)链接得到可执行文件然后运行即可: 46 | 47 | #### 在树莓派上测试 48 | 49 | ```bash 50 | gcc test.s libsysy.a -o test 51 | ./test 52 | ``` 53 | 54 | 输入 111 即可看到输出 12321。 55 | 56 | #### 在其它平台上交叉编译测试 57 | 58 | ```bash 59 | arm-linux-gnueabihf-gcc test.s libsysy.a -o test 60 | qemu-arm -L /usr/arm-linux-gnueabihf/ ./test 61 | ``` 62 | 63 | 输入 111 即可看到输出 12321。 64 | 65 | ### SysY 语言定义与运行时库 66 | 67 | * [SysY 语言定义](SysY_def.pdf) 68 | * [SysY 运行时库定义](SysY_lib.pdf) 69 | * [SysY 运行时库](libsysy.a?raw=true) 70 | 71 | ### SysY 语言测试用例 72 | 73 | 可以到大赛官方网站上下载:[SysY 语言测试用例](https://gitlab.eduxiji.net/windcome/sysyruntimelibrary) 74 | 75 | ## 编译器的中间代码优化部分的设计 76 | 77 | 中间代码部分包含三个层次的 IR(每个层次都列出了相关的 Pass) 78 | 79 | ### 高层 IR 80 | 81 | 设计上保留了源代码 if while 等结构的信息,方便结构级变换。 82 | 83 | * AccumulatePattern:累加变量外提 84 | * BBExps: 分析得到表达式结构 85 | * HighIRsimplyCFG: 控制流图化简 86 | * LoopMerge:while 循环合并 87 | * MergeCond:嵌套 if 条件块合并 88 | 89 | ### 中层 IR 90 | 91 | 设计上接近 LLVM IR,适合于各类通用优化。 92 | 93 | * ActiveVars: 活跃变量分析 94 | * BBCommonSubExper: 块内公共子表达式消除 95 | * BBConstPropagation: 块内常量传播 96 | * BranchMerge:分支合并 97 | * CondSimplify:条件块简化 98 | * ConstFlod:常量折叠 99 | * ConstLoopExpansion:循环展开 100 | * DeadCodeEliminate:死代码删除 101 | * Dominators:支配树分析 102 | * FunctionInline:函数智能内联 103 | * GlobalVariableLocal:全局变量局部化 104 | * HIRToMIR:将高层 IR 翻译到中层 IR 105 | * IRCheck:检测 IR 的数据结构是否有不一致 106 | * LoopFind:循环查找 107 | * LoopInvariant:循环不变量外提 108 | * Multithreading: 循环多线程化 109 | * PowerArray:将特殊形式数组的访问替换为计算 110 | * ReachDefinition:到达定值分析 111 | * RefactorParlins:交换操作数位置 112 | * SimplifyCFG:基本块合并与删除 113 | * SparseCondConstPropagation:稀疏有条件常量传播 114 | * Mem2Reg:半剪枝算法构造 SSA 形式 IR 115 | * Vectorizaiton:循环向量化 116 | 117 | ### 低层 IR 118 | 119 | 设计上贴近硬件架构,与后端相配合共同完成指令融合、调度和选择等优化。 120 | 121 | * InstructionSchedule: 指令调度软流水 122 | * LowerIR:将中层 IR 翻译到低层 IR 并在上面做一系列相关优化 123 | * SplitGEP:将 GEP 指令拆分为子指令(Mul + Add) 124 | * SplitRem:将 Rem 指令拆分成子指令(Div + Mul + Sub) 125 | * FuseCmpBr:将比较指令和分支指令融合(这样比较结果就不占用寄存器) 126 | * FuseMulAdd:将乘法和加法融合为乘加指令 127 | * ConvertMulToShift:将部分常数乘法替换成左移 128 | * ConvertRemToAnd:将部分常数取模替换成逻辑与 129 | * RemoveUnusedOp:消除不被用到的操作数 130 | * ...... (还有很多) 131 | * RegisterAllocation: 初版寄存器分配 132 | 133 | ## 编译器的后端部分的设计 134 | 135 | 后端与中间代码优化的低层 IR Pass 相配合共同完成指令融合、调度和选择等优化。后端部分包含三个层次的虚拟指令,上层指令会选择最小代价智能翻译成一系列下层指令(不一定要是相邻层)(在多线程区域会有不同的翻译行为)。智能翻译的过程会充分利用 ARM 指令的特性,例如 flexible operand 之类的(需要优化过的低层 IR 来提供某些机会)。 136 | 137 | ### 指令层次与相关约束 138 | 139 | * 高层虚拟指令:不可使用临时寄存器。 140 | * 中层虚拟指令:可用低频临时寄存器 r12 r14。 141 | * 低层虚拟指令:可用高频临时寄存器 r11。 142 | * 物理指令:直接对应到 ARM 指令 143 | 144 | ### 寄存器分配 145 | 146 | * 后端尽量节省了临时寄存器的使用(例如没有使用帧指针 fp),所以留出了 11 个通用寄存器(r0-r10),有效减少了寄存器分配时的溢出。 147 | * 新版寄存器分配器直接集成在后端(初版为 IR Pass),与创新多线程框架有一些配合(创新多线程框架共享部分栈空间所以在并行区域被赋值的虚拟变量分配溢出或者调用函数时需要特殊处理)。 148 | * 分配器使用图着色算法,会衡量各种方面的奖励与代价来优化分配。 149 | * 各种环境下溢出的代价(写入?读取?栈上数组指针?) 150 | * Phi 节点同色时的奖励 151 | * 染色与 ABI 规定一致时的奖励 152 | * ZExt 之类的指令同色时的奖励 153 | * 按照循环嵌套深度来放大奖励与代价 154 | 155 | ### 创新多线程框架 156 | 157 | 与经典框架 OpenMP 对比: 158 | 159 | * **共享栈空间**:不需要将被并行化的区域拆分出来变成函数 160 | * **框架更加易于实现**:不需要保存上下文和维护各种信息 161 | * **更便于代码变换**:前后就地插个 `tid=__mtstart()` 和 `__mtend(tid)` 就行了 162 | 163 | ```C 164 | for (int i = 0; i < n; i++) { 165 | for (int j = 0; j < n; j++) { 166 | for (int k = 0; k < n; k++) { 167 | A[i][j] = A[i][j] + B[i][k] * C[k][j]; 168 | } 169 | } 170 | } 171 | ``` 172 | 173 | 变换为: 174 | 175 | ```C 176 | int tid = __mtstart(); 177 | for (int i = starti(tid) ; i < endi(tid) ; i++) { 178 | for (int j = 0; j < n; j++) { 179 | for (int k = 0; k < n; k++) { 180 | A[i][j] = A[i][j] + B[i][k] * C[k][j]; 181 | } 182 | } 183 | } 184 | __mtend(t); 185 | ``` 186 | 187 | (注:为了方便调试和测试,编译器支持在 SysY 语言中直接调用 `__mtstart` 和 `__mtend` 函数。) 188 | 189 | (注:这里使用源代码来表述是为了便于理解,实际上的自动多线程化的变换是在中间代码层次上由 Multithreading Pass 完成的。) 190 | 191 | * **更高的运行性能**:栈上的资源仍然可以直接通过栈指针加偏移访问 192 | 193 | 函数调用相关的开销倒不是关键,提升性能的主要因素是这样在某些场景下可以减少寄存器的使用,避免寄存器分配溢出或者减轻其影响。以矩阵乘法为例,其包含三个数组 `a` `b` `c`,被函数内联与全局数组局部化优化之后就在栈上了,`a` `b` `c` 的地址都可以直接通过栈指针加上一个编译期确定的常量得到。一般的多线程框架例如 OpenMP 栈空间不共享,每个线程的栈指针是不同的,那么就至少需要用一个新寄存器保存一下以前的栈指针才能访问 `a` `b` `c` 里面的东西了(如果保存每个数组的地址代价会更大);而创新多线程框架在启动多线程后栈指针不会变化,所有线程栈指针是一样的,就不需要新的寄存器了。 194 | 195 | ![创新多线程框架](mt.png?raw=true) 196 | -------------------------------------------------------------------------------- /SysY_def.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlzeng/CSC2020-USTC-FlammingMyCompiler/ed205c0a5bc013a888a8c37c80ccffd1ae1134e0/SysY_def.pdf -------------------------------------------------------------------------------- /SysY_lib.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlzeng/CSC2020-USTC-FlammingMyCompiler/ed205c0a5bc013a888a8c37c80ccffd1ae1134e0/SysY_lib.pdf -------------------------------------------------------------------------------- /frontend.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlzeng/CSC2020-USTC-FlammingMyCompiler/ed205c0a5bc013a888a8c37c80ccffd1ae1134e0/frontend.zip -------------------------------------------------------------------------------- /include/CodeGen/Analyzer.hh: -------------------------------------------------------------------------------- 1 | #ifndef SYSYC_ANALYZER_H 2 | #define SYSYC_ANALYZER_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "CodeGen.hh" 11 | 12 | namespace Analyzer { 13 | 14 | extern std::random_device rd; 15 | 16 | enum Functionality { set, gnp, mm, mv, unknown }; 17 | 18 | const int sample_count = 16; 19 | 20 | const bool show_num_steps = false; 21 | 22 | class Var { 23 | private: 24 | int val; 25 | 26 | public: 27 | Var() { this->val = (rd() % 2) ? (rd() % 16) : (rd()); } 28 | Var(int val) { this->val = val; } 29 | Var(const Var &rhs) { this->val = rhs.val; } 30 | Var operator+(const Var &rhs) const { return this->val + rhs.val; } 31 | Var operator-(const Var &rhs) const { return this->val - rhs.val; } 32 | Var operator*(const Var &rhs) const { return this->val * rhs.val; } 33 | Var operator/(const Var &rhs) const { return this->val / rhs.val; } 34 | Var operator%(const Var &rhs) const { return this->val % rhs.val; } 35 | Var operator^(const Var &rhs) const { return this->val ^ rhs.val; } 36 | Var operator|(const Var &rhs) const { return this->val | rhs.val; } 37 | Var operator&(const Var &rhs) const { return this->val & rhs.val; } 38 | Var operator<<(const Var &rhs) const { return this->val << rhs.val; } 39 | Var operator>>(const Var &rhs) const { return this->val >> rhs.val; } 40 | Var operator<(const Var &rhs) const { return this->val < rhs.val; } 41 | Var operator>(const Var &rhs) const { return this->val > rhs.val; } 42 | Var operator<=(const Var &rhs) const { return this->val <= rhs.val; } 43 | Var operator>=(const Var &rhs) const { return this->val >= rhs.val; } 44 | Var operator==(const Var &rhs) const { return this->val == rhs.val; } 45 | Var operator!=(const Var &rhs) const { return this->val != rhs.val; } 46 | Var operator-() const { return -this->val; } 47 | Var operator!() const { return !this->val; } 48 | Var operator~() const { return ~this->val; } 49 | int getVal() const { return this->val; } 50 | }; 51 | 52 | class Analyzer { 53 | private: 54 | Function *func; 55 | std::map next_inst; 56 | Instruction *start_inst; 57 | int free_addr; 58 | std::map vmem; 59 | std::map vreg; 60 | int ret_gas; 61 | 62 | public: 63 | Analyzer(Function *func); 64 | void clear(); 65 | std::pair run(int gas); 66 | Functionality analyzeFunctionality(); 67 | bool analyzeMTsafety(); 68 | }; 69 | }; // namespace Analyzer 70 | 71 | #endif -------------------------------------------------------------------------------- /include/CodeGen/CodeGen.hh: -------------------------------------------------------------------------------- 1 | #ifndef SYSYC_CODEGEN_H 2 | #define SYSYC_CODEGEN_H 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include "BasicBlock.h" 15 | #include "Constant.h" 16 | #include "Function.h" 17 | #include "GlobalVariable.h" 18 | #include "IRBuilder.h" 19 | #include "Instruction.h" 20 | #include "InstructionsGen.hh" 21 | #include "Module.h" 22 | #include "Type.h" 23 | #include "User.h" 24 | #include "Value.h" 25 | 26 | const std::string global_vars_label = ".global_vars"; 27 | const int arch_version = 8; 28 | const bool enlarge_stack = true; 29 | const int enlarge_stack_size = 256 * (1 << 20); // 256MB 30 | 31 | const int op_reg_0 = 12; 32 | const int op_reg_1 = 14; // lr 33 | const int op_reg_2 = vinst_temp_reg.getID(); 34 | 35 | const std::set caller_save_regs = { 36 | InstGen::Reg(0), InstGen::Reg(1), InstGen::Reg(2), 37 | InstGen::Reg(3), InstGen::Reg(12), InstGen::Reg(14)}; 38 | const std::set callee_save_regs = { 39 | InstGen::Reg(4), InstGen::Reg(5), InstGen::Reg(6), InstGen::Reg(7), 40 | InstGen::Reg(8), InstGen::Reg(9), InstGen::Reg(10), InstGen::Reg(11)}; 41 | const std::set allocate_regs = { 42 | InstGen::Reg(0), InstGen::Reg(1), InstGen::Reg(2), InstGen::Reg(3), 43 | InstGen::Reg(4), InstGen::Reg(5), InstGen::Reg(6), InstGen::Reg(7), 44 | InstGen::Reg(8), InstGen::Reg(9), InstGen::Reg(10)}; 45 | const std::set temp_regs = { 46 | InstGen::Reg(op_reg_0), InstGen::Reg(op_reg_1), InstGen::Reg(op_reg_2)}; 47 | 48 | const int cache_line_bits = 7; 49 | const int cache_line_size = 1 << cache_line_bits; 50 | const int mt_num_threads = 4; 51 | 52 | const int L1_cache_size = 32 * (1 << 10); // 32KiB per core 53 | const int L2_cache_size = 1 * (1 << 20); // 1MB shared 54 | 55 | const int thread_id_reg = 10; 56 | 57 | const int clone_flag = CLONE_VM | SIGCHLD; 58 | 59 | class CodeGen { 60 | private: 61 | std::shared_ptr module; 62 | std::map register_mapping; 63 | std::map stack_mapping; 64 | std::set allocated; 65 | std::map GOT; 66 | std::map> context_active_vars; 67 | int stack_size; 68 | int thread_stack_bits; 69 | int thread_stack_size; 70 | bool debug; 71 | double spill_cost_total; 72 | double color_bonus_total; 73 | bool mt_enabled; 74 | std::map in_mt_env; 75 | Value *cur_inst_mt_env; 76 | 77 | public: 78 | CodeGen(std::shared_ptr module, bool debug = false) { 79 | this->module = module; 80 | this->debug = debug; 81 | } 82 | ~CodeGen() {} 83 | std::string generateModuleCode(std::map register_mapping); 84 | std::string generateModuleCode(bool autoAlloc) { 85 | return generateModuleCode(autoAlloc ? regAlloc() 86 | : std::map()); 87 | } 88 | std::string generateFunctionCode(Function *func); 89 | void findMTVars(Function *func); 90 | std::string generateFunctionEntryCode(Function *func); 91 | std::string generateFunctionExitCode(Function *func); 92 | std::string generateFunctionPostCode(Function *func); 93 | std::string generateBasicBlockCode(BasicBlock *bb); 94 | std::string generateInstructionCode(Instruction *inst); 95 | std::string global(std::string name); 96 | std::string getLabelName(BasicBlock *bb); 97 | std::string getLabelName(Function *func, int type); 98 | std::string generateFunctionCall(Instruction *inst, std::string func_name, 99 | std::vector ops, int return_reg = 0, 100 | int sp_ofs = 0); 101 | std::vector getAllRegisters(Function *func); 102 | std::vector getCallerSaveRegisters(Function *func); 103 | std::vector getCalleeSaveRegisters(Function *func); 104 | void allocateStackSpace(Function *func); 105 | bool isSameMapping(Value *a, Value *b); 106 | std::string virtualRegMove(std::vector target, 107 | std::vector source, int sp_ofs = 0); 108 | std::string virtualRegMove(Value *target, Value *source, int sp_ofs = 0); 109 | std::string assignToSpecificReg(Value *val, int target, int sp_ofs = 0); 110 | std::string getFromSpecificReg(Value *val, int source, int sp_ofs = 0); 111 | std::string generateGOT(); 112 | std::string generateGlobalVarsCode(); 113 | std::string generateInitializerCode(Constant *init); 114 | std::pair getConstIntVal(Value *val); 115 | int queryGOT(Value *val); 116 | std::string comment(std::string s); 117 | std::map regAlloc(); 118 | void printIR(); 119 | void printStat(); 120 | InstGen::CmpOp cmpConvert(CmpInst::CmpOp op, bool reverse = false); 121 | bool is_mt_inside(Function *func); 122 | bool is_mt_inst(Value *val); 123 | bool is_mt_start(Value *val); 124 | bool is_mt_end(Value *val); 125 | std::string mtstart(); 126 | std::string mtend(); 127 | std::string vv(const InstGen::Reg &len); 128 | }; 129 | 130 | #endif -------------------------------------------------------------------------------- /include/HIR/AccumulatePattern.h: -------------------------------------------------------------------------------- 1 | #ifndef __ACCUMULATEPATTERN_H__ 2 | #define __ACCUMULATEPATTERN_H__ 3 | 4 | #include "BBExps.h" 5 | #include "PassManager.h" 6 | #include 7 | 8 | class AccumulatePattern : public Pass { 9 | using exp_t = std::tuple; 10 | std::unique_ptr BB2exps; 11 | WhileBlock *curWhile; 12 | Value *curStartVal; 13 | Value *curEndVal; 14 | Value *curIter; 15 | Value *AccuAddr = nullptr; 16 | std::unordered_set curVar; 17 | std::vector _BasicBBs; 18 | bool nestedLoop(IfBlock *BB); 19 | bool isSimpleIterPattern(); 20 | bool hasSimpleAccuPattern(); 21 | bool isInvariant(Value *); 22 | bool isSameAddr(Value *, Value *); 23 | bool isSameOffsetPattern(Value *val, Value *val2); 24 | bool isAssignPlus(exp_t &); 25 | bool hasNot(Exp_hir &, Value *); 26 | void moveAccuOut(); 27 | BasicBlock *getNewPreBasicBlock(BaseBlock *); 28 | BasicBlock *getNewPostBasicBlock(BaseBlock *); 29 | std::vector getRelatedInsInOrder(Value *); 30 | 31 | public: 32 | AccumulatePattern(Module *m) : Pass(m) {} 33 | void run() override; 34 | }; 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /include/HIR/BBExps.h: -------------------------------------------------------------------------------- 1 | #ifndef __BBEXPS_H__ 2 | #define __BBEXPS_H__ 3 | 4 | #include "PassManager.h" 5 | 6 | enum OP_hir { 7 | nop_hir, 8 | eq_hir, // == 9 | ne_hir, // != 10 | gt_hir, // > 11 | ge_hir, // >= 12 | lt_hir, // < 13 | le_hir, // <= 14 | plus_hir, 15 | minus_hir, 16 | multiple_hir, 17 | divide_hir, 18 | call_hir, 19 | rem_hir 20 | }; 21 | 22 | enum OPlevel { 23 | Nop_level, 24 | lor_level, 25 | land_level, 26 | cmp_level, 27 | plus_level, 28 | multiple_level, 29 | call_level, 30 | }; 31 | 32 | struct Exp_hir { 33 | Value *lval; 34 | OPlevel level; 35 | std::vector> _exp; 36 | Exp_hir(Value *val, OPlevel level) : lval(val), level(level) {} 37 | }; 38 | struct BBExps_hir { 39 | std::vector> exps; 40 | }; 41 | 42 | class BBExpsAnalysis_hir : public Pass { 43 | std::unordered_map BB2exp; 44 | bool failed = false; 45 | int opMap[20][20]; 46 | void analysisExps(BaseBlock *BB); 47 | void handleLogicalExp(BasicBlock *BB, Value *val); 48 | void handleAssignment(BasicBlock *BB, Value *val); 49 | void handleCall(BasicBlock *BB, Value *val); 50 | void handleRet(BasicBlock *BB, Value *val); 51 | OP_hir cmpOp2ExpOp(CmpInst::CmpOp op) { return OP_hir(op + 1); } 52 | OP_hir instrOp2ExpOp(Instruction *instr); 53 | OP_hir determineOP(OP_hir UpperOp, OP_hir curOp, OPlevel level); 54 | bool shouldNotBeLayered(OP_hir UpperOp, OP_hir curOp, OPlevel level); 55 | Exp_hir getExp(Value *val); 56 | void _initOpMap(); 57 | std::string _printExp(const Exp_hir &exp); 58 | std::string _ins2string(const Instruction *ins); 59 | 60 | public: 61 | BBExpsAnalysis_hir(Module *m) : Pass(m) { _initOpMap(); } 62 | auto &getExps(BasicBlock *BB) { return BB2exp[BB]; } 63 | bool runFailed() { return failed; } 64 | void run() override; 65 | }; 66 | 67 | #endif -------------------------------------------------------------------------------- /include/HIR/LoopMerge.h: -------------------------------------------------------------------------------- 1 | #ifndef __LOOPMERGE_H__ 2 | #define __LOOPMERGE_H__ 3 | 4 | #include "BBExps.h" 5 | #include "PassManager.h" 6 | #include 7 | 8 | class LoopMerge : public Pass { 9 | // std::unique_ptr patternFinder; 10 | std::unique_ptr BB2exps; 11 | WhileBlock *lastWhile = nullptr; 12 | Value *lastStartVal; 13 | Value *lastEndVal; 14 | Value *lastIter; 15 | std::unordered_set lastVar; 16 | WhileBlock *curWhile; 17 | Value *curStartVal; 18 | Value *curEndVal; 19 | Value *curIter; 20 | std::unordered_set curVar; 21 | bool mergeAble(); 22 | void merge(); 23 | bool isSimpleAccuPat(); 24 | bool allAccu(BasicBlock *); 25 | bool isSameAddr(Value *, Value *); 26 | bool isInvariant(Value *val, BaseBlock *block); 27 | bool checkSetCurStart(BasicBlock *BB); 28 | bool isSameAccuPattern(); 29 | bool isSameOffsetPattern(Value *val, Value *val2); 30 | bool hasNot(Exp_hir &, Value *); 31 | void clearFormerInformation(Instruction *); 32 | void insertAsNewBefore(Instruction *, std::_List_iterator, 33 | std::list &); 34 | void resetLastPat() { lastWhile = nullptr; } 35 | void setLastPatternFromCur() { 36 | lastWhile = curWhile; 37 | lastIter = curIter; 38 | lastStartVal = curStartVal; 39 | lastEndVal = curEndVal; 40 | lastVar = std::move(curVar); 41 | } 42 | std::list &getList(BaseBlock *); 43 | std::vector getRelatedIns(Instruction *); 44 | 45 | public: 46 | LoopMerge(Module *m) : Pass(m) {} 47 | void run() override; 48 | }; 49 | 50 | #endif -------------------------------------------------------------------------------- /include/IR/BaseBlock.h: -------------------------------------------------------------------------------- 1 | #ifndef SYSYC_BASEBLOCK_H 2 | #define SYSYC_BASEBLOCK_H 3 | 4 | #include "Type.h" 5 | #include "Value.h" 6 | 7 | class Function; 8 | 9 | class BaseBlock : public Value { 10 | public: 11 | enum BlockType { 12 | Basic, 13 | If, 14 | While, 15 | }; 16 | 17 | bool isBasicBlock() const { return block_ty_ == Basic; } 18 | bool isIfBlock() const { return block_ty_ == If; } 19 | bool isWhileBlock() const { return block_ty_ == While; } 20 | 21 | void setFunction(Function *func) { func_ = func; } 22 | void setBaseFather(BaseBlock *father) { 23 | father_ = father; 24 | this->setFunction(father->getFunction()); 25 | } 26 | void clearFather() { father_ = nullptr; } 27 | 28 | BaseBlock *getBaseFather() const { return father_; } 29 | Function *getFunction() const { return func_; } 30 | 31 | void print() override {} 32 | 33 | protected: 34 | // this will auto add this to function's baseblock list 35 | // don't use this in nested structure 36 | explicit BaseBlock(BlockType ty, Module *m, const std::string &name, 37 | Function *func); 38 | 39 | explicit BaseBlock(BlockType ty, Module *m, const std::string &name) 40 | : block_ty_(ty), Value(Type::getLabelTy(m), name), father_(nullptr), 41 | func_(nullptr) {} 42 | 43 | BlockType block_ty_; 44 | BaseBlock *father_; 45 | Function *func_; 46 | }; 47 | 48 | #endif // SYSYC_BASEBLOCK_H 49 | -------------------------------------------------------------------------------- /include/IR/BasicBlock.h: -------------------------------------------------------------------------------- 1 | #ifndef SYSYC_BASICBLOCK_H 2 | #define SYSYC_BASICBLOCK_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "BaseBlock.h" 12 | #include "Value.h" 13 | 14 | class Function; 15 | class Instruction; 16 | class Module; 17 | 18 | class BasicBlock : public BaseBlock { 19 | public: 20 | static BasicBlock *create(Module *m, const std::string &name) { 21 | return new BasicBlock(m, name); 22 | } 23 | 24 | // this will auto add this to function's baseblock list 25 | // don't use this in nested structure 26 | static BasicBlock *create(Module *m, const std::string &name, 27 | Function *func) { 28 | return new BasicBlock(m, name, func); 29 | } 30 | 31 | void setParent(Function *parent) { func_ = parent; } 32 | 33 | // return parent, or null if none. 34 | Function *getParent() const { return func_; } 35 | 36 | Module *getModule() const; 37 | 38 | // TODO(zyh) 待确认 39 | auto rbegin() { return instr_list_.rbegin(); } 40 | auto rend() { return instr_list_.rend(); } 41 | std::list &getInstructions() { return instr_list_; } 42 | 43 | /// Returns the terminator instruction if the block is well formed or null 44 | /// if the block is not well formed. 45 | const Instruction *getTerminator() const; 46 | Instruction *getTerminator() { 47 | return const_cast( 48 | static_cast(this)->getTerminator()); 49 | } 50 | 51 | void addInstruction(Instruction *instr); 52 | 53 | void addInstrBegin(Instruction *instr); 54 | 55 | bool empty() { return instr_list_.empty(); } 56 | // void eraseFromParent() { parent_->Remove(this); } 57 | 58 | int getNumOfInstr() { return instr_list_.size(); } 59 | std::list &getInstrList() { return instr_list_; } 60 | 61 | void insertInstr(Instruction *pos, Instruction *insert); 62 | void deleteInstr(Instruction *instr); 63 | 64 | std::map> &getBBAssignIn() { 65 | return reach_assign_in_; 66 | } 67 | std::map> &getBBAssignOut() { 68 | return reach_assign_out_; 69 | } 70 | 71 | std::list &getPreBasicBlocks() { return pre_bbs_; } 72 | std::list &getSuccBasicBlocks() { return succ_bbs_; } 73 | 74 | void addPreBasicBlock(BasicBlock *bb) { pre_bbs_.push_back(bb); } 75 | void addSuccBasicBlock(BasicBlock *bb) { succ_bbs_.push_back(bb); } 76 | 77 | void removePreBasicBlock(BasicBlock *bb) { pre_bbs_.remove(bb); } 78 | void removeSuccBasicBlock(BasicBlock *bb) { succ_bbs_.remove(bb); } 79 | void clearSuccBasicBlock() { succ_bbs_.clear(); } 80 | 81 | void addDom(BasicBlock *bb) { doms_.insert(bb); } 82 | std::set &getDoms() { return doms_; } 83 | void setDoms(std::set &doms) { 84 | doms_.clear(); 85 | doms_.insert(doms.begin(), doms.end()); 86 | } 87 | 88 | BasicBlock *getIDom() { return idom_; } 89 | void setIDom(BasicBlock *idom) { idom_ = idom; } 90 | 91 | void addDominanceFrontier(BasicBlock *bb) { domFrontier_.insert(bb); } 92 | std::set &getDominanceFrontier() { return domFrontier_; } 93 | void setDominanceFrontier(std::set &df) { 94 | domFrontier_.clear(); 95 | domFrontier_.insert(df.begin(), df.end()); 96 | } 97 | 98 | // successor blocks of this node in dominance tree 99 | std::set getDomTreeSuccBlocks() { return domTreeSuccBlocks_; } 100 | void addDomTreeSuccBlock(BasicBlock *bb) { domTreeSuccBlocks_.insert(bb); } 101 | 102 | virtual void print() override; 103 | 104 | protected: 105 | explicit BasicBlock(Module *m, const std::string &name); 106 | explicit BasicBlock(Module *m, const std::string &name, Function *func); 107 | 108 | std::list instr_list_; 109 | 110 | private: 111 | std::map> reach_assign_in_; // data flow 112 | std::map> reach_assign_out_; 113 | 114 | std::list pre_bbs_; 115 | std::list succ_bbs_; 116 | 117 | std::set doms_; // dominance set 118 | BasicBlock *idom_ = nullptr; // immediate dominance 119 | std::set domFrontier_; // dominance frontier set 120 | std::set domTreeSuccBlocks_; 121 | 122 | // TODO(zyh) 待确认 123 | std::unordered_set activeIn, activeOut, definedVals; 124 | std::unordered_map inheritedVals; 125 | // bool hasReturn; 126 | // bool isEntry; 127 | public: 128 | bool hasRet(); 129 | bool isEntry() { return getName() == "entry"; } 130 | auto &getActiveIns() { return activeIn; } 131 | auto &getActiveOuts() { return activeOut; } 132 | auto &getDefinedVals() { return definedVals; } 133 | auto &getInheritedVals() { return inheritedVals; } 134 | void addActiveIn(Value *val) { activeIn.insert(val); } 135 | void addActiveOut(Value *val) { activeOut.insert(val); } 136 | void initAuxilliaryValsOfActiveSet( 137 | std::unordered_set *, 138 | std::unordered_map> *); 139 | void initDefinedVals(std::unordered_set *); 140 | BasicBlock *intendedBB = nullptr; 141 | }; 142 | 143 | #endif // SYSYC_BASICBLOCK_H 144 | -------------------------------------------------------------------------------- /include/IR/Constant.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by cqy on 2020/6/29. 3 | // 4 | 5 | #ifndef SYSYC_CONSTANT_H 6 | #define SYSYC_CONSTANT_H 7 | #include "Type.h" 8 | #include "User.h" 9 | #include "Value.h" 10 | 11 | // class User; 12 | class Constant : public User { 13 | private: 14 | // int value; 15 | public: 16 | Constant(Type *ty, const std::string &name = "", unsigned num_ops = 0) 17 | : User(ty, name, num_ops) {} 18 | ~Constant() = default; 19 | 20 | virtual void print() override; 21 | }; 22 | 23 | class ConstantInt : public Constant { 24 | private: 25 | int value_; 26 | ConstantInt(Type *ty, int val) : Constant(ty, "", 0), value_(val) {} 27 | 28 | public: 29 | static int getValue(ConstantInt *const_val) { return const_val->value_; } 30 | int getValue() { return value_; } 31 | void setValue(int val) { value_ = val; } 32 | static ConstantInt *get(int val, Module *m); 33 | virtual void print() override; 34 | }; 35 | 36 | class ConstantArray : public Constant { 37 | private: 38 | std::vector const_array; 39 | 40 | ConstantArray(ArrayType *ty, const std::vector &val); 41 | 42 | public: 43 | ~ConstantArray() = default; 44 | 45 | Constant *getElementValue(int index); 46 | 47 | unsigned getNumElements() const { return const_array.size(); } 48 | 49 | static ConstantArray *get(ArrayType *ty, const std::vector &val); 50 | 51 | virtual void print() override; 52 | }; 53 | 54 | #endif // SYSYC_CONSTANT_H 55 | -------------------------------------------------------------------------------- /include/IR/Function.h: -------------------------------------------------------------------------------- 1 | #ifndef SYSYC_FUNCTION_H 2 | #define SYSYC_FUNCTION_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "BasicBlock.h" 11 | #include "HighBlock.h" 12 | #include "Instruction.h" 13 | #include "ReturnVal.h" 14 | #include "User.h" 15 | #include 16 | 17 | class Module; 18 | class Argument; 19 | class BaseBlock; 20 | class BasicBlock; 21 | class Type; 22 | class FunctionType; 23 | 24 | class Function : public Value { 25 | public: 26 | Function(FunctionType *ty, const std::string &name, Module *parent); 27 | ~Function(); 28 | static Function *create(FunctionType *ty, const std::string &name, 29 | Module *parent); 30 | 31 | FunctionType *getFunctionType() const; 32 | 33 | Type *getResultType() const; 34 | 35 | void addBasicBlock(BasicBlock *bb); 36 | 37 | void addBasicBlockAfter(std::list::iterator after_pos, 38 | BasicBlock *bb); 39 | 40 | unsigned getNumArgs() const; 41 | 42 | unsigned getNumBasicBlocks() const { return basic_blocks_.size(); } 43 | 44 | Module *getParent() const; 45 | 46 | std::list &getBasicBlocks() { return basic_blocks_; } 47 | std::list &getArgs() { return arguments_; } 48 | 49 | BasicBlock *getEntryBlock() { return *basic_blocks_.begin(); } 50 | 51 | std::list::iterator arg_begin() { return arguments_.begin(); } 52 | std::list::iterator arg_end() { return arguments_.end(); } 53 | 54 | void removeBasicBlock(BasicBlock *bb); 55 | 56 | void HighIRprint(); 57 | 58 | void print() override; 59 | 60 | private: 61 | void buildArgs(); 62 | 63 | private: 64 | std::list basic_blocks_; // basic blocks 65 | std::list arguments_; // arguments 66 | Module *parent_; 67 | int print_cnt_; 68 | 69 | private: 70 | std::list base_blocks_; // base blocks 71 | 72 | bool multithreading_ = false; 73 | 74 | public: 75 | void removeBaseBlock(BaseBlock *bb) { base_blocks_.remove(bb); } 76 | void addBaseBlock(BaseBlock *basebb); 77 | void insertBaseBlock(std::list::iterator iter, 78 | BaseBlock *basebb) { 79 | base_blocks_.insert(iter, basebb); 80 | basebb->clearFather(); 81 | } 82 | std::list &getBaseBlocks() { return base_blocks_; } 83 | 84 | void setMultithreading(bool stat) { multithreading_ = stat; } 85 | bool getMultithreading() { return multithreading_; } 86 | void clearCnt() { print_cnt_ = 0; } 87 | }; 88 | 89 | // Argument of Function, does not contain actual value 90 | class Argument : public Value { 91 | public: 92 | /// Argument constructor. 93 | explicit Argument(Type *ty, const std::string &name = "", 94 | Function *f = nullptr, unsigned arg_no = 0) 95 | : Value(ty, name), parent_(f), arg_no_(arg_no) {} 96 | ~Argument() {} 97 | 98 | inline const Function *getParent() const { return parent_; } 99 | inline Function *getParent() { return parent_; } 100 | 101 | /// For example in "void foo(int a, float b)" a is 0 and b is 1. 102 | unsigned getArgNo() const { 103 | if (parent_ == nullptr) 104 | exit(_getArgNo_Argument); 105 | return arg_no_; 106 | } 107 | 108 | virtual void print() override; 109 | 110 | private: 111 | Function *parent_; 112 | unsigned arg_no_; // argument No. 113 | std::vector array_bound_; 114 | 115 | public: 116 | void setArrayBound(std::vector &array_bound) { 117 | array_bound_.assign(array_bound.begin(), array_bound.end()); 118 | } 119 | 120 | std::vector &getArrayBound() { return array_bound_; } 121 | }; 122 | 123 | #endif // SYSYC_FUNCTION_H 124 | -------------------------------------------------------------------------------- /include/IR/GlobalVariable.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by cqy on 2020/6/29. 3 | // 4 | 5 | #ifndef SYSYC_GLOBALVARIABLE_H 6 | #define SYSYC_GLOBALVARIABLE_H 7 | 8 | #include "Constant.h" 9 | #include "Module.h" 10 | #include "User.h" 11 | 12 | class GlobalVariable : public User { 13 | private: 14 | bool is_const_ : true; 15 | Constant *init_val_; 16 | GlobalVariable(std::string name, Module *m, Type *ty, bool is_const, 17 | Constant *init = nullptr); 18 | 19 | public: 20 | static GlobalVariable *create(std::string name, Module *m, Type *ty, 21 | bool is_const, Constant *init); 22 | 23 | Constant *getInit() { return init_val_; } 24 | void print(); 25 | }; 26 | #endif // SYSYC_GLOBALVARIABLE_H 27 | -------------------------------------------------------------------------------- /include/IR/HighBlock.h: -------------------------------------------------------------------------------- 1 | #ifndef SYSYC_HIGHBLOCK_H 2 | #define SYSYC_HIGHBLOCK_H 3 | 4 | #include "BaseBlock.h" 5 | #include "Value.h" 6 | 7 | class IfBlock : public BaseBlock { 8 | public: 9 | // this will auto add this to function's baseblock list 10 | // don't use this in nested structure 11 | static IfBlock *create(Module *m, const std::string &name, Function *func) { 12 | return new IfBlock(m, name, func); 13 | } 14 | static IfBlock *create(Module *m, const std::string &name) { 15 | return new IfBlock(m, name); 16 | } 17 | 18 | void addCondBB(BaseBlock *bb) { 19 | cond_.push_back(bb); 20 | bb->setBaseFather(this); 21 | } 22 | void addIfBodyBB(BaseBlock *bb) { 23 | if_body_.push_back(bb); 24 | bb->setBaseFather(this); 25 | } 26 | void addElseBodyBB(BaseBlock *bb) { 27 | else_body_.push_back(bb); 28 | bb->setBaseFather(this); 29 | } 30 | 31 | std::list &getCondBBs() { return cond_; } 32 | std::list &getIfBodyBBs() { return if_body_; } 33 | std::list &getElseBodyBBs() { return else_body_; } 34 | 35 | void removeCondBB(BaseBlock *bb) { cond_.remove(bb); } 36 | void removeIfBodyBB(BaseBlock *bb) { if_body_.remove(bb); } 37 | void removeElseBodyBB(BaseBlock *bb) { else_body_.remove(bb); } 38 | void removeBB(BaseBlock *bb) { 39 | removeCondBB(bb); 40 | removeIfBodyBB(bb); 41 | removeElseBodyBB(bb); 42 | } 43 | 44 | void insertCondBB(std::list::iterator it, BaseBlock *bb) { 45 | cond_.insert(it, bb); 46 | bb->setBaseFather(this); 47 | } 48 | void insertIfBodyBB(std::list::iterator it, BaseBlock *bb) { 49 | if_body_.insert(it, bb); 50 | bb->setBaseFather(this); 51 | } 52 | void insertElseBodyBB(std::list::iterator it, BaseBlock *bb) { 53 | else_body_.insert(it, bb); 54 | bb->setBaseFather(this); 55 | } 56 | 57 | void clearCondBBs() { cond_.clear(); } 58 | // TODO 59 | void print() override {} 60 | 61 | private: 62 | explicit IfBlock(Module *m, const std::string &name, Function *func) 63 | : BaseBlock(BaseBlock::If, m, name, func) {} 64 | explicit IfBlock(Module *m, const std::string &name) 65 | : BaseBlock(BaseBlock::If, m, name) {} 66 | 67 | std::list cond_; 68 | std::list if_body_; 69 | std::list else_body_; 70 | }; 71 | 72 | class WhileBlock : public BaseBlock { 73 | public: 74 | // this will auto add this to function's baseblock list 75 | // don't use this in nested structure 76 | static WhileBlock *create(Module *m, const std::string &name, 77 | Function *func) { 78 | return new WhileBlock(m, name, func); 79 | } 80 | static WhileBlock *create(Module *m, const std::string &name) { 81 | return new WhileBlock(m, name); 82 | } 83 | 84 | void addCondBB(BaseBlock *bb) { 85 | cond_.push_back(bb); 86 | bb->setBaseFather(this); 87 | } 88 | void addBodyBB(BaseBlock *bb) { 89 | body_.push_back(bb); 90 | bb->setBaseFather(this); 91 | } 92 | 93 | std::list &getCondBBs() { return cond_; } 94 | std::list &getBodyBBs() { return body_; } 95 | 96 | void removeCondBB(BaseBlock *bb) { cond_.remove(bb); } 97 | void removeWhileBodyBB(BaseBlock *bb) { body_.remove(bb); } 98 | void removeBB(BaseBlock *bb) { 99 | removeCondBB(bb); 100 | removeWhileBodyBB(bb); 101 | } 102 | // TODO 103 | void insertCondBB(std::list::iterator it, BaseBlock *bb) { 104 | cond_.insert(it, bb); 105 | bb->setBaseFather(this); 106 | } 107 | void insertWhileBodyBB(std::list::iterator it, BaseBlock *bb) { 108 | body_.insert(it, bb); 109 | bb->setBaseFather(this); 110 | } 111 | 112 | void print() override {} 113 | 114 | private: 115 | explicit WhileBlock(Module *m, const std::string &name, Function *func) 116 | : BaseBlock(BaseBlock::While, m, name, func) {} 117 | explicit WhileBlock(Module *m, const std::string &name) 118 | : BaseBlock(BaseBlock::While, m, name) {} 119 | 120 | std::list cond_; 121 | std::list body_; 122 | }; 123 | 124 | #endif // SYSYC_HIGHBLOCK_H 125 | -------------------------------------------------------------------------------- /include/IR/IRBuilder.h: -------------------------------------------------------------------------------- 1 | #ifndef SYSYC_IRBUILDER_H 2 | #define SYSYC_IRBUILDER_H 3 | 4 | #include "BasicBlock.h" 5 | #include "Instruction.h" 6 | #include "Value.h" 7 | 8 | class IRBuilder { 9 | private: 10 | BasicBlock *BB_; 11 | 12 | public: 13 | IRBuilder(BasicBlock *bb) { this->BB_ = bb; }; 14 | ~IRBuilder() = default; 15 | BasicBlock *GetInsertBlock() { return this->BB_; } 16 | void SetInsertPoint(BasicBlock *bb) { 17 | this->BB_ = bb; 18 | } //在某个基本块中插入指令 19 | void insertInstr(Instruction *pos, Instruction *insert) { 20 | BB_->insertInstr(pos, insert); 21 | } 22 | void deleteInstr(Instruction *instr) { BB_->deleteInstr(instr); } 23 | 24 | BinaryInst *CreateAdd(Value *v1, Value *v2) { 25 | return BinaryInst::createAdd(v1, v2, this->BB_); 26 | } //创建加法指令(以及其他算术指令) 27 | BinaryInst *CreateSub(Value *v1, Value *v2) { 28 | return BinaryInst::createSub(v1, v2, this->BB_); 29 | } 30 | BinaryInst *CreateMul(Value *v1, Value *v2) { 31 | return BinaryInst::createMul(v1, v2, this->BB_); 32 | } 33 | BinaryInst *CreateDiv(Value *v1, Value *v2) { 34 | return BinaryInst::createDiv(v1, v2, this->BB_); 35 | } 36 | BinaryInst *CreateRem(Value *v1, Value *v2) { 37 | return BinaryInst::createRem(v1, v2, this->BB_); 38 | } 39 | BinaryInst *CreateAnd(Value *v1, Value *v2) { 40 | return BinaryInst::createAnd(v1, v2, this->BB_); 41 | } 42 | BinaryInst *CreateOr(Value *v1, Value *v2) { 43 | return BinaryInst::createOr(v1, v2, this->BB_); 44 | } 45 | 46 | CmpInst *CreateCmpEQ(Value *lhs, Value *rhs, Module *m) { 47 | return CmpInst::createCmp(CmpInst::EQ, lhs, rhs, this->BB_, m); 48 | } 49 | CmpInst *CreateCmpNE(Value *lhs, Value *rhs, Module *m) { 50 | return CmpInst::createCmp(CmpInst::NE, lhs, rhs, this->BB_, m); 51 | } 52 | CmpInst *CreateCmpGT(Value *lhs, Value *rhs, Module *m) { 53 | return CmpInst::createCmp(CmpInst::GT, lhs, rhs, this->BB_, m); 54 | } 55 | CmpInst *CreateCmpGE(Value *lhs, Value *rhs, Module *m) { 56 | return CmpInst::createCmp(CmpInst::GE, lhs, rhs, this->BB_, m); 57 | } 58 | CmpInst *CreateCmpLT(Value *lhs, Value *rhs, Module *m) { 59 | return CmpInst::createCmp(CmpInst::LT, lhs, rhs, this->BB_, m); 60 | } 61 | CmpInst *CreateCmpLE(Value *lhs, Value *rhs, Module *m) { 62 | return CmpInst::createCmp(CmpInst::LE, lhs, rhs, this->BB_, m); 63 | } 64 | 65 | CallInst *CreateCall(Function *func, std::vector args) { 66 | return CallInst::create(func, args, this->BB_); 67 | } 68 | 69 | BranchInst *CreateBr(BasicBlock *if_true) { 70 | return BranchInst::createBr(if_true, this->BB_); 71 | } 72 | BranchInst *CreateCondBr(Value *cond, BasicBlock *if_true, 73 | BasicBlock *if_false) { 74 | return BranchInst::createCondBr(cond, if_true, if_false, this->BB_); 75 | } 76 | 77 | ReturnInst *CreateRet(Value *val) { 78 | return ReturnInst::createRet(val, this->BB_); 79 | } 80 | ReturnInst *CreateVoidRet() { return ReturnInst::createVoidRet(this->BB_); } 81 | 82 | GetElementPtrInst *CreateGEP(Value *ptr, std::vector idxs) { 83 | return GetElementPtrInst::createGEP(ptr, idxs, this->BB_); 84 | } 85 | 86 | StoreInst *CreateStore(Value *val, Value *ptr) { 87 | return StoreInst::createStore(val, ptr, this->BB_); 88 | } 89 | LoadInst *CreateLoad(Type *ty, Value *ptr) { 90 | return LoadInst::createLoad(ty, ptr, this->BB_); 91 | } 92 | LoadInst *CreateLoad(Value *ptr) { 93 | return LoadInst::createLoad(ptr->getType()->getPointerElementType(), ptr, 94 | this->BB_); 95 | } 96 | 97 | AllocaInst *CreateAlloca(Type *ty) { 98 | return AllocaInst::createAlloca(ty, this->BB_); 99 | } 100 | CastInst *CreateZext(Value *val, Type *ty) { 101 | return CastInst::createZExt(val, ty, this->BB_); 102 | } 103 | PhiInst *CreatePhi(Type *ty) { return PhiInst::createPhi(ty, this->BB_); } 104 | 105 | HighIR *CreateBreak(Module *m) { return HighIR::createBreak(m, this->BB_); } 106 | HighIR *CreateContinue(Module *m) { 107 | return HighIR::createContinue(m, this->BB_); 108 | } 109 | }; 110 | 111 | #endif // SYSYC_IRBUILDER_H 112 | -------------------------------------------------------------------------------- /include/IR/Module.h: -------------------------------------------------------------------------------- 1 | #ifndef SYSYC_MODULE_H 2 | #define SYSYC_MODULE_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include "Function.h" 9 | #include "GlobalVariable.h" 10 | #include "Type.h" 11 | #include "Value.h" 12 | 13 | class GlobalVariable; 14 | 15 | class Module { 16 | public: 17 | enum IRLeval { HIR, MIR_MEM, MIR_SSA, LIR }; 18 | 19 | explicit Module(std::string name); 20 | ~Module(); 21 | Type *getVoidTy(); 22 | Type *getLabelTy(); 23 | IntegerType *getInt1Ty(); 24 | IntegerType *getInt32Ty(); 25 | PointerType *getInt32PtrTy(); 26 | 27 | void addFunction(Function *f); 28 | void removeFunction(Function *f) { function_list_.remove(f); } 29 | void removeGlobalVariable(GlobalVariable *v) { global_list_.remove(v); } 30 | std::list &getFunctions() { return function_list_; } 31 | std::list &getGlobalVariables() { return global_list_; } 32 | std::map &getValueSym() { return value_sym_; } 33 | std::string getModuleName() { return module_name_; } 34 | std::string getSourceFileName() { return source_file_name_; } 35 | void addGlobalVariable(GlobalVariable *g); 36 | void HighIRprint(); 37 | virtual void print(); 38 | 39 | Function *getMainFunction() { 40 | for (auto f : function_list_) { 41 | if (f->getName() == "main") { 42 | return f; 43 | } 44 | } 45 | // assert(! "Can't find main"); 46 | } 47 | 48 | Function *getFunction(std::string name) { 49 | for (auto f : function_list_) { 50 | if (f->getName() == name) { 51 | return f; 52 | } 53 | } 54 | exit(_getFunction_Function); 55 | } 56 | 57 | void setIRLevel(IRLeval level) { ir_level_ = level; } 58 | IRLeval getIRLevel() { return ir_level_; } 59 | bool isMIRSSALevel() { return ir_level_ == MIR_SSA; } 60 | 61 | private: 62 | std::list 63 | global_list_; // The Global Variables in the module 64 | std::list function_list_; // The Functions in the module 65 | std::map value_sym_; // Symbol table for values 66 | 67 | std::string module_name_; // Human readable identifier for the module 68 | std::string source_file_name_; // Original source file name for module, for 69 | // test and debug 70 | 71 | IRLeval ir_level_ = HIR; 72 | 73 | private: 74 | IntegerType *int1_ty_; 75 | IntegerType *int32_ty_; 76 | Type *label_ty_; 77 | Type *void_ty_; 78 | PointerType *int32ptr_ty_; 79 | }; 80 | 81 | #endif // SYSYC_MODULE_H -------------------------------------------------------------------------------- /include/IR/Type.h: -------------------------------------------------------------------------------- 1 | #ifndef SYSYC_TYPE_H 2 | #define SYSYC_TYPE_H 3 | 4 | #include 5 | #include 6 | 7 | class Module; 8 | class IntegerType; 9 | class FunctionType; 10 | class ArrayType; 11 | class PointerType; 12 | 13 | class Type { 14 | public: 15 | enum TypeID { 16 | VoidTyID, // Void 17 | LabelTyID, // Labels, e.g., BasicBlock 18 | IntegerTyID, // Integers, include 32 bits and 1 bit 19 | FunctionTyID, // Functions 20 | ArrayTyID, // Arrays 21 | PointerTyID, // Pointer 22 | }; 23 | 24 | explicit Type(TypeID tid); 25 | ~Type() = default; 26 | 27 | TypeID getTypeID() const { return tid_; } 28 | 29 | bool isVoidTy() const { return getTypeID() == VoidTyID; } 30 | 31 | bool isLabelTy() const { return getTypeID() == LabelTyID; } 32 | 33 | bool isIntegerTy() const { return getTypeID() == IntegerTyID; } 34 | 35 | bool isFunctionTy() const { return getTypeID() == FunctionTyID; } 36 | 37 | bool isArrayTy() const { return getTypeID() == ArrayTyID; } 38 | 39 | bool isPointerTy() const { return getTypeID() == PointerTyID; } 40 | 41 | bool isInt1(); 42 | 43 | bool isInt32(); 44 | 45 | static Type *getVoidTy(Module *m); 46 | 47 | static Type *getLabelTy(Module *m); 48 | 49 | static IntegerType *getInt1Ty(Module *m); 50 | 51 | static IntegerType *getInt32Ty(Module *m); 52 | 53 | static PointerType *getInt32PtrTy(Module *m); 54 | 55 | Type *getPointerElementType(); 56 | 57 | void print(); 58 | std::string CommentPrint(); 59 | 60 | int getSize(bool extended = true); 61 | 62 | bool eq(Type rhs) { 63 | if (this->tid_ != rhs.tid_) { 64 | return false; 65 | } else if (this->isPointerTy()) { 66 | return this->getPointerElementType()->eq(*rhs.getPointerElementType()); 67 | } else { 68 | return true; 69 | } 70 | } 71 | 72 | private: 73 | TypeID tid_; 74 | }; 75 | 76 | class IntegerType : public Type { 77 | public: 78 | explicit IntegerType(unsigned num_bits); 79 | 80 | static IntegerType *get(unsigned num_bits); 81 | 82 | unsigned getNumBits(); 83 | 84 | private: 85 | unsigned num_bits_; 86 | }; 87 | 88 | class FunctionType : public Type { 89 | public: 90 | FunctionType(Type *result, std::vector params); 91 | 92 | static bool isValidReturnType(Type *ty); 93 | static bool isValidArgumentType(Type *ty); 94 | 95 | static FunctionType *get(Type *result, std::vector params); 96 | 97 | unsigned getNumArgs() const; 98 | 99 | Type *getArgType(unsigned i) const; 100 | Type *getResultType() const; 101 | 102 | private: 103 | Type *result_; 104 | std::vector args_; 105 | }; 106 | 107 | class ArrayType : public Type { 108 | public: 109 | ArrayType(Type *contained, unsigned num_elements); 110 | 111 | static bool isValidElementType(Type *ty); 112 | 113 | static ArrayType *get(Type *contained, unsigned num_elements); 114 | 115 | Type *getElementType() const { return contained_; } 116 | unsigned getNumOfElements() const { return num_elements_; } 117 | std::vector getDims() const; 118 | 119 | private: 120 | Type *contained_; // The element type of the array. 121 | unsigned num_elements_; // Number of elements in the array. 122 | }; 123 | 124 | class PointerType : public Type { 125 | public: 126 | PointerType(Type *contained); 127 | Type *getElementType() const { return contained_; } 128 | 129 | static PointerType *get(Type *contained); 130 | 131 | private: 132 | Type *contained_; // The element type of the ptr. 133 | }; 134 | 135 | #endif // SYSYC_TYPE_H -------------------------------------------------------------------------------- /include/IR/User.h: -------------------------------------------------------------------------------- 1 | #ifndef SYSYC_USER_H 2 | #define SYSYC_USER_H 3 | 4 | #include "Value.h" 5 | #include 6 | // #include 7 | // class Value; 8 | class User : public Value { 9 | public: 10 | User(Type *ty, const std::string &name = "", unsigned num_ops = 0); 11 | ~User() = default; 12 | 13 | std::vector &getOperandList(); 14 | 15 | // start from 0 16 | Value *getOperand(unsigned i) const; 17 | 18 | // start from 0, auto add use 19 | void setOperand(unsigned i, Value *v); 20 | 21 | void addOperand(Value *v); 22 | void removeOperand(unsigned i); 23 | void removeOperand(unsigned i, unsigned j); 24 | 25 | unsigned getNumOperand() const; 26 | 27 | // TODO(zyh) 待确认 28 | std::vector &getOperands() { return operands_; } 29 | 30 | virtual void print() override {} 31 | 32 | // remove the use of all operands 33 | void removeUseOfOps(); 34 | 35 | void setNumOps(unsigned num) { 36 | num_ops_ = num; 37 | operands_.resize(num, nullptr); 38 | } 39 | void clearOps() { 40 | num_ops_ = 0; 41 | removeUseOfOps(); 42 | operands_.clear(); 43 | } 44 | 45 | private: 46 | // std::unique_ptr< std::list > operands_; // operands of this 47 | // value 48 | std::vector operands_; // operands of this value 49 | unsigned num_ops_; 50 | }; 51 | 52 | #endif // SYSYC_USER_H -------------------------------------------------------------------------------- /include/IR/Value.h: -------------------------------------------------------------------------------- 1 | #ifndef SYSYC_VALUE_H 2 | #define SYSYC_VALUE_H 3 | 4 | #include 5 | #include 6 | #include 7 | // #include "Constant.h" 8 | 9 | class Type; 10 | class Value; 11 | 12 | struct Use { 13 | Value *val_; 14 | unsigned arg_no_; // the no. of operand, e.g., func(a, b), a is 0, b is 1 15 | Use(Value *val, unsigned no) : val_(val), arg_no_(no) {} 16 | friend bool operator==(const Use &lhs, const Use &rhs) { 17 | return lhs.val_ == rhs.val_ && lhs.arg_no_ == rhs.arg_no_; 18 | } 19 | }; 20 | 21 | class UseHash { 22 | public: 23 | size_t operator()(const Use &u) const { 24 | return (std::hash()(u.val_)) ^ (std::hash()(u.arg_no_)); 25 | } 26 | }; 27 | 28 | class Value { 29 | public: 30 | explicit Value(Type *ty, const std::string &name = ""); 31 | ~Value() = default; 32 | 33 | Type *getType() const { return type_; } 34 | 35 | std::list &getUseList() { return use_list_; } 36 | 37 | void addUse(Value *val, unsigned arg_no = 0); 38 | 39 | bool setName(std::string name) { 40 | if (name_ == "") { 41 | name_ = name; 42 | return true; 43 | } 44 | return false; 45 | } 46 | std::string getName() const; 47 | 48 | virtual void print() {} 49 | 50 | // replace all uses of this value to new_val 51 | // e.g., replace a = this_value + b to a = new_value + b 52 | void replaceAllUseWith(Value *new_val); 53 | 54 | void removeUse(Value *val, unsigned arg_no); 55 | 56 | // bool isValidVar() {(type_->isIntegerTy() && 57 | // dynamic_cast(this)) || type_->isPointerTy();} 58 | private: 59 | Type *type_; 60 | std::list use_list_; // who use this value 61 | std::string name_; // should we put name field here ? 62 | }; 63 | 64 | #endif // SYSYC_VALUE_H -------------------------------------------------------------------------------- /include/IRBuilder/SYSYCBuilder.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by cqy on 2020/6/11. 3 | // 4 | 5 | #ifndef SYSYC_SYSYBUILDER_HPP 6 | #define SYSYC_SYSYBUILDER_HPP 7 | 8 | #include "BasicBlock.h" 9 | #include "Constant.h" 10 | #include "Function.h" 11 | #include "GlobalVariable.h" 12 | #include "HighBlock.h" 13 | #include "IRBuilder.h" 14 | #include "Instruction.h" 15 | #include "Module.h" 16 | #include "Type.h" 17 | #include "User.h" 18 | #include "Value.h" 19 | 20 | // #include "Verifier.h" 21 | #include "syntax_tree.hh" 22 | #include 23 | 24 | class Scope { 25 | public: 26 | // enter a new scope 27 | void enter() { 28 | inner.push_back({}); 29 | array_param.push_back({}); 30 | } 31 | 32 | // exit a scope 33 | void exit() { 34 | inner.pop_back(); 35 | array_param.pop_back(); 36 | } 37 | 38 | bool in_global() { return inner.size() == 1; } 39 | 40 | // push a name to scope 41 | // return true if successful 42 | // return false if this name already exits 43 | bool push(std::string name, Value *val) { 44 | auto result = inner[inner.size() - 1].insert({name, val}); 45 | return result.second; 46 | } 47 | 48 | bool push_params(std::string name, Value *val, std::vector params) { 49 | auto result = array_param[array_param.size() - 1].insert({name, params}); 50 | return result.second; 51 | } 52 | 53 | Value *find(std::string name) { 54 | for (auto s = inner.rbegin(); s != inner.rend(); s++) { 55 | auto iter = s->find(name); 56 | if (iter != s->end()) { 57 | return iter->second; 58 | } 59 | } 60 | 61 | return nullptr; 62 | } 63 | 64 | Value *find_params(std::string name, std::vector ¶ms) { 65 | // std::cout<<"find_params"<find(name); 69 | if (iter != s->end()) { 70 | // std::cout<<"find_params2"<second.begin(), iter->second.end()); 72 | return iter->second[0]; 73 | } 74 | } 75 | // std::cout<<"find_params3"<> inner; 81 | std::vector>> array_param; 82 | }; 83 | 84 | class SYSYCBuilder : public syntax_tree_visitor { 85 | public: 86 | SYSYCBuilder() { 87 | module = std::shared_ptr(new Module("SysY code")); 88 | builder = std::unique_ptr(new IRBuilder(nullptr)); 89 | auto TyVoid = Type::getVoidTy(&*module); 90 | auto TyInt32 = Type::getInt32Ty(&*module); 91 | auto TyPtr = Type::getInt32PtrTy(&*module); 92 | 93 | auto getint_type = FunctionType::get(TyInt32, {}); 94 | // auto getch_type = FunctionType::get(TyInt32, false); 95 | auto getint_fun = Function::create(getint_type, "getint", module.get()); 96 | 97 | auto getch_fun = Function::create(getint_type, "getch", module.get()); 98 | 99 | std::vector putint_params; 100 | putint_params.push_back(TyInt32); 101 | auto putint_type = FunctionType::get(TyVoid, putint_params); 102 | 103 | auto putint_fun = Function::create(putint_type, "putint", module.get()); 104 | 105 | auto putch_fun = Function::create(putint_type, "putch", module.get()); 106 | 107 | std::vector getarray_params; 108 | getarray_params.push_back(TyPtr); 109 | auto getarray_type = FunctionType::get(TyInt32, getarray_params); 110 | 111 | auto getarray_fun = 112 | Function::create(getarray_type, "getarray", module.get()); 113 | 114 | std::vector putarray_params; 115 | putarray_params.push_back(TyInt32); 116 | putarray_params.push_back(TyPtr); 117 | auto putarray_type = FunctionType::get(TyInt32, putarray_params); 118 | 119 | auto putarray_fun = 120 | Function::create(putarray_type, "putarray", module.get()); 121 | 122 | std::vector starttime_params; 123 | starttime_params.push_back(TyInt32); 124 | 125 | auto starttime_type = FunctionType::get(TyVoid, starttime_params); 126 | 127 | auto starttime_fun = 128 | Function::create(starttime_type, "_sysy_starttime", module.get()); 129 | 130 | std::vector stoptime_params; 131 | stoptime_params.push_back(TyInt32); 132 | auto stoptime_type = FunctionType::get(TyVoid, stoptime_params); 133 | 134 | auto stoptime_fun = 135 | Function::create(stoptime_type, "_sysy_stoptime", module.get()); 136 | 137 | auto mtstart_type = FunctionType::get(TyInt32, {}); 138 | 139 | auto mtstart_fun = 140 | Function::create(mtstart_type, "__mtstart", module.get()); 141 | 142 | std::vector mtend_params; 143 | mtend_params.push_back(TyInt32); 144 | auto mtend_type = FunctionType::get(TyVoid, mtend_params); 145 | 146 | auto mtend_fun = Function::create(mtend_type, "__mtend", module.get()); 147 | 148 | scope.enter(); 149 | scope.push("getint", getint_fun); 150 | scope.push("getch", getch_fun); 151 | scope.push("putint", putint_fun); 152 | scope.push("putch", putch_fun); 153 | scope.push("getarray", getarray_fun); 154 | scope.push("putarray", putarray_fun); 155 | scope.push("_sysy_starttime", starttime_fun); 156 | scope.push("_sysy_stoptime", stoptime_fun); 157 | 158 | scope.push("__mtstart", mtstart_fun); 159 | scope.push("__mtend", mtend_fun); 160 | } 161 | 162 | void IRprint() { module->print(); } 163 | 164 | void HighIRprint() { module->HighIRprint(); } 165 | 166 | std::shared_ptr getModule() { return this->module; } 167 | 168 | private: 169 | virtual void visit(SyntaxCompUnit &) override final; 170 | virtual void visit(SyntaxConstDecl &) override final; 171 | virtual void visit(SyntaxConstDef &) override final; 172 | virtual void visit(SyntaxConstInitVal &) override final; 173 | virtual void visit(SyntaxVarDecl &) override final; 174 | virtual void visit(SyntaxVarDef &) override final; 175 | virtual void visit(SyntaxInitVal &) override final; 176 | virtual void visit(SyntaxFuncDef &) override final; 177 | virtual void visit(SyntaxFuncFParam &) override final; 178 | virtual void visit(SyntaxBlock &) override final; 179 | virtual void visit(SyntaxBreakStmt &) override final; 180 | virtual void visit(SyntaxContinueStmt &) override final; 181 | virtual void visit(SyntaxAssignStmt &) override final; 182 | virtual void visit(SyntaxSelectStmt &) override final; 183 | virtual void visit(SyntaxIterationStmt &) override final; 184 | virtual void visit(SyntaxReturnStmt &) override final; 185 | virtual void visit(SyntaxLVal &) override final; 186 | virtual void visit(SyntaxPrimaryExp &) override final; 187 | virtual void visit(SyntaxNumber &) override final; 188 | virtual void visit(SyntaxUnaryExp &) override final; 189 | virtual void visit(SyntaxCallee &) override final; 190 | virtual void visit(SyntaxMulExp &) override final; 191 | virtual void visit(SyntaxAddExp &) override final; 192 | virtual void visit(SyntaxRelExp &) override final; 193 | virtual void visit(SyntaxEqExp &) override final; 194 | virtual void visit(SyntaxLAndExp &) override final; 195 | virtual void visit(SyntaxLOrExp &) override final; 196 | virtual void visit(SyntaxConstExp &) override final; 197 | std::unique_ptr builder; 198 | Scope scope; 199 | std::shared_ptr module; 200 | }; 201 | #endif // SYSYC_SYSYBUILDERLLVM_HPP 202 | -------------------------------------------------------------------------------- /include/OptimizePass/ActiveVars.h: -------------------------------------------------------------------------------- 1 | #ifndef ACTIVEVARS_H 2 | #define ACTIVEVARS_H 3 | #include "Module.h" 4 | 5 | extern void ActiveVars(Module *m); 6 | 7 | #endif -------------------------------------------------------------------------------- /include/OptimizePass/BBCommonSubExper.h: -------------------------------------------------------------------------------- 1 | #include "BasicBlock.h" 2 | #include "ConstFlod.h" 3 | #include "Function.h" 4 | #include "IRBuilder.h" 5 | #include "Instruction.h" 6 | #include "Module.h" 7 | #include "PassManager.h" 8 | 9 | class Arglist { 10 | public: 11 | std::vector args_; 12 | const bool operator<(const Arglist &a) const; 13 | const bool operator>(const Arglist &a) const; 14 | const bool operator==(const Arglist &a) const; 15 | }; 16 | 17 | class BBCommonSubExper : public Transform { 18 | private: 19 | BasicBlock *bb_; 20 | std::set eliminatable_call_; 21 | 22 | public: 23 | BBCommonSubExper(Module *m) : Transform(m) {} 24 | ~BBCommonSubExper() {} 25 | void run() override; 26 | void CommonSubExperElimination(); 27 | Value *getBinaryLop(Instruction *instr); 28 | Value *getBinaryRop(Instruction *instr); 29 | Value *getLoadPtr(Instruction *instr); 30 | Value *getLoadOffset(Instruction *instr); 31 | int getLoadOffsetShl(Instruction *instr); 32 | 33 | Value *getGepPtr(Instruction *instr); 34 | Value *getGepOffset(Instruction *instr); 35 | 36 | Arglist *getCallArgs(CallInst *instr); 37 | std::string getFuncID(CallInst *instr); 38 | bool eliminatableCall(std::string func_id); 39 | void getEliminatableCall(); 40 | }; -------------------------------------------------------------------------------- /include/OptimizePass/BBConstPropagation.h: -------------------------------------------------------------------------------- 1 | #include "BasicBlock.h" 2 | #include "ConstFlod.h" 3 | #include "Function.h" 4 | #include "IRBuilder.h" 5 | #include "Instruction.h" 6 | #include "Module.h" 7 | #include "PassManager.h" 8 | 9 | class BBConstPropagation : public Transform { 10 | private: 11 | BasicBlock *bb_; 12 | IRBuilder *builder_; 13 | ConstFlod *flod_; 14 | std::map> array_const_def_; 15 | std::map global_def_; 16 | 17 | public: 18 | BBConstPropagation(Module *m) : Transform(m) { 19 | flod_ = new ConstFlod(m); 20 | builder_ = new IRBuilder(nullptr); 21 | } 22 | ~BBConstPropagation() { delete flod_; } 23 | 24 | void run() override; 25 | void ConstPropagation(); 26 | ConstantInt *getConstVal(Value *v); 27 | ConstantInt *getDefVal(Value *v); 28 | ConstantInt *setDefVal(Value *v, ConstantInt *const_val); 29 | }; -------------------------------------------------------------------------------- /include/OptimizePass/BranchMerge.h: -------------------------------------------------------------------------------- 1 | #include "BasicBlock.h" 2 | #include "ConstFlod.h" 3 | #include "Function.h" 4 | #include "IRBuilder.h" 5 | #include "Instruction.h" 6 | #include "LoopFind.h" 7 | #include "Module.h" 8 | #include "PassManager.h" 9 | #include "syntax_tree.hh" 10 | 11 | // class AriExp; 12 | 13 | class ExpVal { 14 | private: 15 | int low_limit_; 16 | int high_limit_; 17 | bool free_int_; 18 | 19 | public: 20 | ExpVal() { free_int_ = true; } 21 | ExpVal(int const_val) { 22 | low_limit_ = const_val; 23 | high_limit_ = const_val; 24 | free_int_ = false; 25 | } 26 | ExpVal(int low, int high) { 27 | low_limit_ = low; 28 | high_limit_ = high; 29 | free_int_ = false; 30 | } 31 | 32 | void setLowLimit(int val) { low_limit_ = val; } 33 | void setHighLimit(int val) { high_limit_ = val; } 34 | 35 | int getLowLimit() { return low_limit_; } 36 | int getHighLimit() { return high_limit_; } 37 | 38 | bool isConst() { return low_limit_ == high_limit_; } 39 | bool isFreeInt() { return free_int_; } 40 | bool isBool() { return low_limit_ == 0 && high_limit_ == 1; } 41 | }; 42 | 43 | class AriExp { 44 | private: 45 | AriExp *ari_exp1_; 46 | AriExp *ari_exp2_; 47 | 48 | ExpVal *val_; 49 | 50 | public: 51 | ExpVal *computeExpVal(); 52 | 53 | AriExp() { 54 | ari_exp1_ = nullptr; 55 | ari_exp2_ = nullptr; 56 | val_ = new ExpVal(); 57 | } 58 | 59 | AriExp(int const_val) { 60 | ari_exp1_ = nullptr; 61 | ari_exp2_ = nullptr; 62 | val_ = new ExpVal(const_val); 63 | } 64 | 65 | enum OpID { ADD, SUB, MUL, DIV, REM, AND, OR, EQ, NE, GT, GE, LT, LE }; 66 | 67 | AriExp(AriExp *exp1, AriExp *exp2, OpID op); 68 | 69 | void setLopExp(AriExp *exp) { ari_exp1_ = exp; } 70 | void setRopExp(AriExp *exp) { ari_exp2_ = exp; } 71 | 72 | AriExp *getLopExp() { return ari_exp1_; } 73 | AriExp *getRopExp() { return ari_exp2_; } 74 | 75 | int getLowLimit() { return val_->getLowLimit(); } 76 | int getHighLimit() { return val_->getHighLimit(); } 77 | 78 | bool isBoolOpID() { 79 | return op_ == EQ || op_ == NE || op_ == GT || op_ == GE || op_ == LE || 80 | op_ == LT; 81 | } 82 | bool isConst() { return val_->isConst(); } 83 | bool isFreeInt() { return val_->isFreeInt(); } 84 | bool isBool() { return val_->isFreeInt(); } 85 | 86 | private: 87 | OpID op_; 88 | }; 89 | 90 | class BranchMerge : public Transform { 91 | private: 92 | public: 93 | BranchMerge(Module *m, SyntaxCompUnit *root) : Transform(m) {} 94 | ~BranchMerge() {} 95 | void run() override; 96 | void MergeCond() {} 97 | void simplifyAlgebra(AriExp *exp); 98 | AriExp *getCondInst(BranchInst *br); 99 | AriExp *getAriExp(Value *op_val); 100 | }; -------------------------------------------------------------------------------- /include/OptimizePass/CondSimplify.h: -------------------------------------------------------------------------------- 1 | #include "BasicBlock.h" 2 | #include "Function.h" 3 | #include "IRBuilder.h" 4 | #include "Instruction.h" 5 | #include "Module.h" 6 | #include "PassManager.h" 7 | 8 | class Exp { 9 | private: 10 | Value *val_; 11 | Exp *lhs_; 12 | Exp *rhs_; 13 | int cost_depth_; 14 | int print_depth_ = 0; 15 | 16 | public: 17 | enum OpID { 18 | Assign, 19 | Add, 20 | Sub, 21 | Mul, 22 | Div, 23 | Rem, 24 | And, 25 | Or, 26 | GT, 27 | GE, 28 | LT, 29 | LE, 30 | EQ, 31 | NE 32 | }; 33 | OpID op_; 34 | 35 | Exp(Value *val) : val_(val), op_(Assign), cost_depth_(0) {} 36 | Exp(Exp *lhs, Exp *rhs, OpID op) : lhs_(lhs), rhs_(rhs), op_(op) { 37 | auto depth1 = lhs_->cost_depth_; 38 | auto depth2 = rhs_->cost_depth_; 39 | cost_depth_ = (depth1 > depth2) ? depth1 : depth2; 40 | } 41 | bool isAssign() { return op_ == Assign; } 42 | bool isAdd() { return op_ == Add; } 43 | bool isSub() { return op_ == Sub; } 44 | bool isMul() { return op_ == Mul; } 45 | bool isDiv() { return op_ == Div; } 46 | bool isRem() { return op_ == Rem; } 47 | bool isAnd() { return op_ == And; } 48 | bool isOr() { return op_ == Or; } 49 | bool isGT() { return op_ == GT; } 50 | bool isGE() { return op_ == GE; } 51 | bool isLT() { return op_ == LT; } 52 | bool isLE() { return op_ == LE; } 53 | bool isEQ() { return op_ == EQ; } 54 | bool isNE() { return op_ == NE; } 55 | OpID getOp() { return op_; } 56 | 57 | Exp *getLSubexp() { return lhs_; } 58 | Exp *getRSubexp() { return rhs_; } 59 | Value *getVal() { return val_; } 60 | int getCostDepth() { return cost_depth_; } 61 | static Exp *create(Value *root); 62 | void setPrintDepth(int depth) { print_depth_ = depth; } 63 | void print(); 64 | }; 65 | 66 | class CondSimplify : public Transform { 67 | private: 68 | Function *func_; 69 | // BasicBlock *bb_; 70 | 71 | public: 72 | CondSimplify(Module *m) : Transform(m) {} 73 | ~CondSimplify(){}; 74 | void run() override; 75 | // recog cond 76 | void EmliteCond(); 77 | Exp *genExp(BranchInst *br); 78 | Value *ExpSimplify(Exp *exp); 79 | std::pair item_1(Exp *exp); 80 | std::pair item_2(Exp *exp); 81 | // std::pairitem_3( Exp *exp ); 82 | // change add to assign 83 | std::pair Accumulate(StoreInst *str); 84 | bool AddrCmp(Instruction *addr1, Instruction *addr2); 85 | bool expCmp(Exp *exp1, Exp *exp2); 86 | void BranchMerge(); 87 | }; 88 | -------------------------------------------------------------------------------- /include/OptimizePass/ConstFlod.h: -------------------------------------------------------------------------------- 1 | #ifndef SYSYC_CONSTFLOD_H 2 | #define SYSYC_CONSTFLOD_H 3 | 4 | #include 5 | 6 | #include "Constant.h" 7 | #include "Instruction.h" 8 | #include "Module.h" 9 | 10 | class ConstFlod { 11 | public: 12 | ConstFlod(Module *m) : module_(m) {} 13 | 14 | ConstantInt *compute(Instruction::OpID op, ConstantInt *v1, ConstantInt *v2); 15 | ConstantInt *compute(Instruction::OpID op, ConstantInt *v1); // not neg 16 | ConstantInt *compute(CmpInst::CmpOp op, ConstantInt *v1, ConstantInt *v2); 17 | 18 | private: 19 | Module *module_; 20 | }; 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /include/OptimizePass/ConstLoopExpansion.h: -------------------------------------------------------------------------------- 1 | #ifndef __CONSTLOOPEXPANSION_H__ 2 | #define __CONSTLOOPEXPANSION_H__ 3 | 4 | #include "LoopFind.h" 5 | #include "PassManager.h" 6 | 7 | class ConstLoopExpansion : public Pass { 8 | void tryExpand(BasicBlock *, BasicBlock *); 9 | 10 | public: 11 | ConstLoopExpansion(Module *m) : Pass(m) {} 12 | void run() override; 13 | }; 14 | 15 | #endif -------------------------------------------------------------------------------- /include/OptimizePass/ControlTree.h: -------------------------------------------------------------------------------- 1 | #ifndef CONTROL_TREE__ 2 | #define CONTROL_TREE__ 3 | 4 | #include "PassManager.h" 5 | #include 6 | 7 | // class Pass; 8 | 9 | enum ControlStruct_t { 10 | _NULL, 11 | REAL, 12 | CONTINUE, 13 | BREAK, 14 | RETURN, 15 | BLOCK, 16 | IFTHEN, 17 | IFTHENELSE, 18 | WHILE, 19 | ENTRY, 20 | END 21 | }; 22 | 23 | struct CTnode { 24 | struct CTnode *p; 25 | struct CTnode *firstChild; 26 | struct CTnode *nextSibling; 27 | int nodeType; 28 | BasicBlock *BB; 29 | }; 30 | 31 | using BB2Node_t = std::unordered_map; 32 | 33 | class ControlTreeAnalysis { 34 | Module *m_; 35 | 36 | public: 37 | ControlTreeAnalysis(Module *m) : m_(m) {} 38 | void run(); 39 | }; 40 | 41 | // class ControlTree { 42 | // struct CTnode *root; 43 | // std::unordered_map m; 44 | // public: 45 | // void ControlTree(Function* func); 46 | // void ~ControlTree(); 47 | // } 48 | 49 | #endif -------------------------------------------------------------------------------- /include/OptimizePass/DeadCodeEliminate.h: -------------------------------------------------------------------------------- 1 | #ifndef SYSYC_DEADCODEELIMATE_H 2 | #define SYSYC_DEADCODEELIMATE_H 3 | 4 | #include "PassManager.h" 5 | 6 | class DeadCodeEliminate : public Transform { 7 | public: 8 | DeadCodeEliminate(Module *m) : Transform(m) {} 9 | void run() override; 10 | 11 | bool isSideEffect(Instruction *inst); 12 | bool isSideEffectAndCall(Instruction *inst); 13 | bool isLocalStore(StoreInst *store); 14 | bool isDeadInstruction(Instruction *inst); 15 | bool isEqualStoreLoadPtr(StoreInst *store, LoadInst *load); 16 | bool isStrictEqualStoreLoadPtr(StoreInst *store, LoadInst *load); 17 | bool isEqualStorePtr(StoreInst *store_a, StoreInst *store_b); 18 | bool isSideEffectFunc(Function *func) { 19 | return notSideEffectFunc.find(func) == notSideEffectFunc.end(); 20 | } 21 | Value *getFirstAddr(Value *v); 22 | 23 | void detectNotSideEffectFunc(Module *m); 24 | 25 | void deleteDeadFunc(Module *m); 26 | void deleteDeadInst(Function *func); 27 | void deleteDeadStore(Function *func); 28 | void deleteDeadRet(Function *func); 29 | 30 | void markUse(Instruction *inst, std::unordered_set &worklist); 31 | 32 | void printStats(); 33 | 34 | private: 35 | int inst_counter = 0; 36 | int store_counter = 0; 37 | int func_counter = 0; 38 | 39 | std::unordered_set notSideEffectFunc; 40 | }; 41 | 42 | #endif // SYSYC_DEADCODEELIMATE_H 43 | -------------------------------------------------------------------------------- /include/OptimizePass/Dominators.h: -------------------------------------------------------------------------------- 1 | #ifndef SYSYC_DOMINATORS_H 2 | #define SYSYC_DOMINATORS_H 3 | 4 | #include "BasicBlock.h" 5 | #include "PassManager.h" 6 | #include 7 | #include 8 | #include 9 | 10 | class Dominators : public Analysis { 11 | public: 12 | Dominators(Module *m) : Analysis(m) {} 13 | void run() override; 14 | void createDoms(Function *f); 15 | void createReversePostOrder(Function *f); 16 | void createIDom(Function *f); 17 | void createDominanceFrontier(Function *f); 18 | void createDomTreeSucc(Function *f); 19 | 20 | // for debug 21 | void printIDom(Function *f); 22 | void printDominanceFrontier(Function *f); 23 | 24 | private: 25 | void postOrderVisit(BasicBlock *bb, std::set &visited); 26 | BasicBlock *intersect(BasicBlock *b1, BasicBlock *b2); 27 | 28 | std::list reversePostOrder_; 29 | std::map postOrderID_; // the root has highest ID 30 | }; 31 | 32 | #endif // SYSYC_DOMINATORS_H 33 | -------------------------------------------------------------------------------- /include/OptimizePass/FunctionInline.h: -------------------------------------------------------------------------------- 1 | #ifndef SYSYC_FUNCTIONINLINE_H 2 | #define SYSYC_FUNCTIONINLINE_H 3 | 4 | #include "PassManager.h" 5 | #include 6 | #include 7 | 8 | class FunctionInline : public Transform { 9 | public: 10 | const bool ONLY_INLINE_SMALL_FUNC = false; 11 | const bool INLINE_BB_NUM_MAX = 4; 12 | const bool NOT_INLINE_MULTILEVEL_LOOP_FUNC = true; 13 | const int INLINE_LOOP_LEVEL_MAX = 1; 14 | const bool INLINE_RECURSIVE = false; 15 | 16 | public: 17 | FunctionInline(Module *m) : Transform(m) {} 18 | void run() override; 19 | void inlining(Function *entry_func); 20 | void inliningRecursive(Function *entry_func); 21 | void init(); 22 | bool isIgnored(Function *f) { return ignored_.find(f) != ignored_.end(); } 23 | bool isInlined(Function *f) { return inlined_.find(f) != inlined_.end(); } 24 | 25 | bool canBeInlined(Instruction *instr); 26 | bool canBeInlinedRecursive(Instruction *instr); 27 | void removeInlineFunc(); 28 | 29 | bool isRecursive(Function *f) { 30 | return recursive_func_.find(f) != recursive_func_.end(); 31 | } 32 | 33 | private: 34 | void createFuncSucc(); 35 | void detectRecursive(); 36 | void visitFunc(Function *entry, std::set &visited); 37 | 38 | std::list copyBasicBlocks(Function *old_func); 39 | std::list copyBasicBlocks(CallInst *call_inst, 40 | Function *old_func); 41 | std::list copyBasicBlocks(CallInst *call_inst, 42 | std::list copy_bbs, 43 | Function *old_func); 44 | BasicBlock *splitBasicBlock(std::list::iterator call_pos, 45 | std::list &instrs); 46 | void handleReturns(BasicBlock *return_bb, AllocaInst *ret_val, 47 | std::list &func_bbs); 48 | void handleVoidReturn(BasicBlock *return_bb, 49 | std::list &func_bbs); 50 | void handlePHIReturns(BasicBlock *return_bb, PhiInst *ret_val, 51 | std::list &func_bbs); 52 | 53 | private: 54 | std::set ignored_; // ignored functions 55 | std::set inlined_; // inlined functions 56 | std::set has_inline_; // func that has inlined functions 57 | std::map> func_succ_; 58 | std::set recursive_func_; 59 | }; 60 | 61 | #endif // SYSYC_FUNCTIONINLINE_H 62 | -------------------------------------------------------------------------------- /include/OptimizePass/FunctionOptimization.h: -------------------------------------------------------------------------------- 1 | #include "Analyzer.hh" 2 | #include "BasicBlock.h" 3 | #include "Function.h" 4 | #include "IRBuilder.h" 5 | #include "PassManager.h" 6 | 7 | class FunctionOptimization : public Transform { 8 | private: 9 | Function *func_; 10 | IRBuilder *builder; 11 | 12 | public: 13 | FunctionOptimization(Module *m) : Transform(m) { 14 | builder = new IRBuilder(nullptr); 15 | } 16 | ~FunctionOptimization() {} 17 | void run() override; 18 | void Set(); 19 | void Gnp(); 20 | void Mv(); 21 | void MM(); 22 | void createArgs(); 23 | }; -------------------------------------------------------------------------------- /include/OptimizePass/GlobalVariableLocal.h: -------------------------------------------------------------------------------- 1 | #ifndef SYSYC_GLOBALVARIABLELOCAL_H 2 | #define SYSYC_GLOBALVARIABLELOCAL_H 3 | 4 | #include "PassManager.h" 5 | #include 6 | #include 7 | 8 | class GlobalVariableLocal : public Transform { 9 | public: 10 | GlobalVariableLocal(Module *m) : Transform(m) {} 11 | void run() override; 12 | void localGlobalVariable(GlobalVariable *global_var, Function *func); 13 | bool genArrayInitStores(Instruction *ptr, Constant *init_var); 14 | void genGEPLocal(GlobalVariable *global_var, Function *func); 15 | void createFuncSucc(); 16 | void detectRecursive(); 17 | void visitFunc(Function *entry, std::set &visited); 18 | 19 | private: 20 | std::list init_instr_; 21 | BasicBlock *insert_bb_; 22 | std::map> func_succ_; 23 | std::set recursive_func_; 24 | }; 25 | 26 | #endif // SYSYC_GLOBALVARIABLELOCAL_H -------------------------------------------------------------------------------- /include/OptimizePass/HIRToMIR.h: -------------------------------------------------------------------------------- 1 | #ifndef SYSY_HIRTOMIR_H 2 | #define SYSY_HIRTOMIR_H 3 | 4 | #include "PassManager.h" 5 | 6 | class HIRToMIR : public Transform { 7 | public: 8 | HIRToMIR(Module *m) : Transform(m) {} 9 | void run() override; 10 | BasicBlock *genBaseBlock(BaseBlock *basebb, BasicBlock *next_bb, 11 | BasicBlock *while_entry, BasicBlock *while_exit, 12 | Function *func); 13 | }; 14 | 15 | #endif // SYSY_HIRTOMIR_H 16 | -------------------------------------------------------------------------------- /include/OptimizePass/HighIRsimplyCFG.h: -------------------------------------------------------------------------------- 1 | #include "BasicBlock.h" 2 | #include "Function.h" 3 | #include "HighBlock.h" 4 | #include "IRBuilder.h" 5 | #include "Instruction.h" 6 | #include "Module.h" 7 | #include "PassManager.h" 8 | 9 | class HighIRsimplyCFG : public Transform { 10 | private: 11 | Function *func_; 12 | std::vector wait_delete_; 13 | 14 | public: 15 | HighIRsimplyCFG(Module *m) : Transform(m) {} 16 | ~HighIRsimplyCFG() {} 17 | 18 | void run() override; 19 | void MergeSinglePredecessorBB(); 20 | bool MergeBasicBlock(BasicBlock *bb, BaseBlock *pre_bb); 21 | void MergeWhileBB(WhileBlock *whilebb); 22 | void MergeIfBB(IfBlock *ifbb); 23 | // void removeAllBB(); 24 | }; 25 | -------------------------------------------------------------------------------- /include/OptimizePass/IRCheck.h: -------------------------------------------------------------------------------- 1 | #include "BasicBlock.h" 2 | #include "Function.h" 3 | #include "IRBuilder.h" 4 | #include "Instruction.h" 5 | #include "Module.h" 6 | #include "PassManager.h" 7 | 8 | class IRCheck : public Analysis { 9 | public: 10 | IRCheck(Module *m) : Analysis(m) {} 11 | ~IRCheck(){}; 12 | void run() override; 13 | 14 | private: 15 | void CheckPraent(); 16 | void CheckPhiPostion(); 17 | void CheckRetBrPostion(); 18 | void CheckTerminate(); 19 | void CheckPredSucc(); 20 | void CheckEntry(); 21 | }; -------------------------------------------------------------------------------- /include/OptimizePass/InstructionSchedule.h: -------------------------------------------------------------------------------- 1 | #ifndef SYSYC_INSTRUCTIONSCHEDULE_H 2 | #define SYSYC_INSTRUCTIONSCHEDULE_H 3 | 4 | #include "Instruction.h" 5 | #include "PassManager.h" 6 | #include 7 | #include 8 | 9 | class InstructionSchedule : public Transform { 10 | public: 11 | const bool DEBUG = false; 12 | 13 | public: 14 | InstructionSchedule(Module *m) : Transform(m) {} 15 | void run() override; 16 | void createDAG(std::list &insts); 17 | void genPrePriority(); 18 | std::list schedule(std::list &insts); 19 | bool notScheduleInst(Instruction *inst); 20 | void assertEqual(std::list &a, std::list &b); 21 | 22 | public: 23 | using OpID = Instruction::OpID; 24 | enum Unit { 25 | B, // Branch μops 26 | I, // Integer ALU μops 27 | M, // Integer shift-ALU, multiply, divide, CRC and 28 | // sum-of-absolute-differences μops 29 | L, // Load and register transfer μops 30 | S, // Store and special memory μops 31 | N, // op which are not considered during scheduling, e.g., alloca, phi 32 | }; 33 | const std::map AVAILABLE_UNIT = { 34 | {B, 1}, {I, 2}, {M, 1}, {L, 1}, {S, 1}}; 35 | struct Node { 36 | Instruction *inst; 37 | int delay; 38 | int cycle; 39 | int delay_prio; 40 | Unit unit; 41 | OpID id; 42 | std::list succ; 43 | Node(); 44 | Node(Instruction *i); 45 | }; 46 | using NodePtr = std::shared_ptr; 47 | struct NodePtrCmp { 48 | bool operator()(NodePtr a, NodePtr b) { 49 | return a->delay_prio < b->delay_prio; 50 | } 51 | }; 52 | using NodePtrQueue = 53 | std::priority_queue, NodePtrCmp>; 54 | 55 | private: 56 | bool isDefinedInBB(Instruction *inst) { 57 | return inst2node_.find(inst) != inst2node_.end(); 58 | } 59 | void initNode(NodePtr node); 60 | void assignPrePriority(NodePtr node); 61 | 62 | private: 63 | std::map> 64 | succs_; // 后继,使用者集合,使用key的节点 65 | std::map> pres_; // 前驱,操作数集合,key依赖的节点 66 | std::map inst2node_; 67 | }; 68 | 69 | #endif // SYSYC_INSTRUCTIONSCHEDULE_H 70 | -------------------------------------------------------------------------------- /include/OptimizePass/LoopFind.h: -------------------------------------------------------------------------------- 1 | #ifndef __LOOOFIND_H__ 2 | #define __LOOOFIND_H__ 3 | 4 | #include "BasicBlock.h" 5 | #include "PassManager.h" 6 | #include 7 | #include 8 | #include 9 | 10 | struct CFGnode { 11 | std::unordered_set succs; 12 | std::unordered_set preds; 13 | BasicBlock *BB; 14 | int index; 15 | int lowlink; 16 | int onStack; 17 | }; 18 | 19 | using BBset_t = std::unordered_set; 20 | 21 | class LoopFind : public Pass { 22 | std::unordered_set loops; 23 | std::unordered_map base2Loop; 24 | std::unordered_map loop2Base; 25 | std::unordered_map 26 | BB2Base; // 默认映射最低层次的Loop 27 | 28 | int indexCount; 29 | std::vector stack; 30 | 31 | void buildCFG(Function *func, std::unordered_set &); 32 | CFGnode *findLoopBase(std::unordered_set *, 33 | std::unordered_set &); 34 | bool 35 | stronglyConnComponents(std::unordered_set &, 36 | std::unordered_set *> &); 37 | void traverse(CFGnode *, 38 | std::unordered_set *> &); 39 | std::string _printCFG(std::unordered_set &); 40 | 41 | public: 42 | explicit LoopFind(Module *m) : Pass(m) {} 43 | LoopFind(const LoopFind &) = delete; 44 | LoopFind &operator=(const LoopFind &) = delete; 45 | ~LoopFind(); 46 | BBset_t *getBaseLoop(BasicBlock *BB); 47 | BasicBlock *getLoopCond(BBset_t *set); 48 | BBset_t *getParentLoop(BBset_t *set); 49 | BasicBlock *getLoopOut(BBset_t *set); 50 | BasicBlock *getLoopEntry(BBset_t *set) { return getLoopCond(set); } 51 | bool isBaseLoop(BBset_t *); 52 | auto begin() { return loops.begin(); } 53 | auto end() { return loops.end(); } 54 | void run() override; 55 | /* 56 | LOOPFIND 调用方法 : 57 | 1. 对一个BB: getBaseLoop,getParentLoop 以嵌套层次向前 58 | 2. 对一个循环set, getLoopCond得到条件BB,通过集合直接遍历 59 | 3. 遍历循环: begin,end遍历,若需要识别嵌套结构,可以调用isBaseLoop识 60 | 别,使用(1)中方法查找,但需要小心在begin,end的重复遍历 61 | 4. 62 | */ 63 | }; 64 | 65 | #endif //__LOOOFIND_H__ 66 | -------------------------------------------------------------------------------- /include/OptimizePass/LoopInvariant.h: -------------------------------------------------------------------------------- 1 | #ifndef __LOOPINVARIANT_H__ 2 | #define __LOOPINVARIANT_H__ 3 | #include "LoopFind.h" 4 | #include "PassManager.h" 5 | #include 6 | #include 7 | #include 8 | 9 | class LoopInvariant : public Pass { 10 | std::vector< 11 | std::pair::iterator>> 12 | invariant; 13 | // TODO 待确认 14 | std::unique_ptr finder; 15 | int areaCount; 16 | // std::unordered_set definedInLoop; 17 | void findInvariants(BBset_t *); 18 | void buildPrehead(); 19 | void appendTo(); 20 | void moveInvariantsOut(BBset_t *); 21 | bool definedOut(); // TODO 22 | bool definedIn_invariant(); // TODO 23 | 24 | BasicBlock *buildBB(); 25 | 26 | public: 27 | LoopInvariant(Module *m) : Pass(m) {} 28 | void run() override; 29 | }; 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /include/OptimizePass/LowerIR.h: -------------------------------------------------------------------------------- 1 | #ifndef SYSYC_LOWERIR_H 2 | #define SYSYC_LOWERIR_H 3 | 4 | #include "PassManager.h" 5 | 6 | class LowerIR : public Transform { 7 | public: 8 | LowerIR(Module *m) : Transform(m) {} 9 | void run() override; 10 | void fuseCmpBr(BasicBlock *bb); 11 | void fuseMulAdd(BasicBlock *bb); 12 | void splitGEP(BasicBlock *bb); 13 | void convertMulDivToShift(BasicBlock *bb); 14 | void convertRemToAnd(BasicBlock *bb); 15 | void fuseConstShift(BasicBlock *bb); 16 | void fuseAddLoadStore(BasicBlock *bb); 17 | // addr + offset < shift, 1 <= shift <= 31 18 | void fuseShiftLoadStore(BasicBlock *bb); 19 | void removeUnusedOp(BasicBlock *bb); 20 | void fuseShiftArithmetic(BasicBlock *bb); 21 | void splitRem(BasicBlock *bb); 22 | }; 23 | 24 | #endif // SYSYC_LOWERIR_H 25 | -------------------------------------------------------------------------------- /include/OptimizePass/MergeCond.h: -------------------------------------------------------------------------------- 1 | #include "BasicBlock.h" 2 | #include "Function.h" 3 | #include "HighBlock.h" 4 | #include "IRBuilder.h" 5 | #include "Instruction.h" 6 | #include "Module.h" 7 | #include "PassManager.h" 8 | 9 | class MergeCond : public Transform { 10 | private: 11 | Function *func_; 12 | enum mother_type { FUNCTION, WHILE_BODY, IF_THEN, IF_ELSE }; 13 | 14 | public: 15 | MergeCond(Module *m) : Transform(m) {} 16 | ~MergeCond() {} 17 | 18 | void run() override; 19 | void runFun(); 20 | bool runIf(IfBlock *ifbb, mother_type ty); 21 | void runWhile(WhileBlock *whilebb, mother_type ty); 22 | }; -------------------------------------------------------------------------------- /include/OptimizePass/Multithreading.h: -------------------------------------------------------------------------------- 1 | #include "BasicBlock.h" 2 | #include "ConstFlod.h" 3 | #include "Function.h" 4 | #include "IRBuilder.h" 5 | #include "Instruction.h" 6 | #include "LoopFind.h" 7 | #include "Module.h" 8 | #include "PassManager.h" 9 | #include 10 | 11 | class Multithreading : public Pass { 12 | std::unique_ptr finder; 13 | Value *start, *end; 14 | Instruction *accu; 15 | Instruction *comparer; 16 | Instruction *phi; 17 | int accuValue = -1; 18 | int multithreadCount = 0; 19 | bool findAccumulator(BBset_t *); 20 | void wrapMultithreading(BasicBlock *loopBase, BBset_t *loop); 21 | 22 | public: 23 | Multithreading(Module *m) : Pass(m) {} 24 | ~Multithreading() {} 25 | void run() override; 26 | }; -------------------------------------------------------------------------------- /include/OptimizePass/PassManager.h: -------------------------------------------------------------------------------- 1 | #ifndef SYSYC_PASSMANAGER_H 2 | #define SYSYC_PASSMANAGER_H 3 | 4 | #include "Module.h" 5 | #include 6 | #include 7 | 8 | class Pass { 9 | public: 10 | Pass(Module *m) : m_(m) {} 11 | virtual void run() = 0; 12 | void setName(std::string name) { name_ = name; } 13 | std::string getName() { return name_; } 14 | void setPrintIR(bool print_ir) { print_ir_ = print_ir; } 15 | bool isPrintIR() { return print_ir_; } 16 | 17 | protected: 18 | Module *m_; 19 | std::string name_; 20 | bool print_ir_ = false; 21 | }; 22 | class Analysis : public Pass { 23 | public: 24 | Analysis(Module *m) : Pass(m) {} 25 | }; 26 | 27 | class Transform : public Pass { 28 | public: 29 | Transform(Module *m) : Pass(m) {} 30 | }; 31 | 32 | class IRCheck : public Analysis { 33 | public: 34 | IRCheck(Module *m) : Analysis(m) {} 35 | ~IRCheck(){}; 36 | void run() override; 37 | 38 | private: 39 | void CheckParent(); 40 | void CheckPhiPosition(); 41 | void CheckRetBrPostion(); 42 | void CheckTerminate(); 43 | void CheckPredSucc(); 44 | void CheckEntry(); 45 | void CheckUseList(); 46 | void CheckOperandExit(); 47 | }; 48 | 49 | class PassManager { 50 | public: 51 | PassManager(Module *m) : m_(m), ir_check(m) {} 52 | 53 | template void addPass(bool print_ir = false) { 54 | passes_.push_back(new PassTy(m_)); 55 | passes_.back()->setName(typeid(PassTy).name()); 56 | passes_.back()->setPrintIR(print_ir); 57 | // std::cout << typeid(PassTy).name() << std::endl; 58 | } 59 | 60 | void run(bool print_ir = false) { 61 | auto i = 0; 62 | // check ast 63 | try { 64 | ir_check.run(); 65 | } catch (...) { 66 | std::cerr << "IRCheck ERROR after SYSYCBuilder" << std::endl; 67 | exit(1); 68 | } 69 | for (auto pass : passes_) { 70 | i++; 71 | pass->run(); 72 | if (print_ir || pass->isPrintIR()) { 73 | std::cerr << ">>>>>>>>>>>> After pass " << pass->getName() 74 | << " <<<<<<<<<<<<" << std::endl; 75 | m_->print(); 76 | } 77 | try { 78 | ir_check.run(); 79 | } catch (...) { 80 | std::cerr << "IRCheck ERROR after pass " << pass->getName() 81 | << std::endl; 82 | exit(i * 2); 83 | } 84 | } 85 | } 86 | 87 | private: 88 | std::vector passes_; 89 | Module *m_; 90 | IRCheck ir_check; 91 | }; 92 | 93 | #endif // SYSYC_PASSMANAGER_H -------------------------------------------------------------------------------- /include/OptimizePass/PowerArray.h: -------------------------------------------------------------------------------- 1 | #include "BasicBlock.h" 2 | #include "ConstFlod.h" 3 | #include "Function.h" 4 | #include "IRBuilder.h" 5 | #include "Instruction.h" 6 | #include "Module.h" 7 | #include "PassManager.h" 8 | 9 | class PowerArray : public Transform { 10 | private: 11 | BasicBlock *bb_; 12 | 13 | public: 14 | PowerArray(Module *m) : Transform(m) {} 15 | ~PowerArray() {} 16 | void run() override; 17 | Value *getPowerArray(); 18 | void replaceWithShl(Value *); 19 | 20 | Value *getGepPtr(Instruction *instr); 21 | Value *getGepOffset(Instruction *instr); 22 | }; -------------------------------------------------------------------------------- /include/OptimizePass/ReachDefinitions.h: -------------------------------------------------------------------------------- 1 | #ifndef SYSYC_REACHDEFINITIONS_H 2 | #define SYSYC_REACHDEFINITIONS_H 3 | 4 | #include "BasicBlock.h" 5 | #include "Function.h" 6 | #include "Instruction.h" 7 | #include "Module.h" 8 | 9 | class ReachDefinitionsPass { 10 | private: 11 | Module *module_; 12 | 13 | public: 14 | ReachDefinitionsPass(Module *m); 15 | ~ReachDefinitionsPass(); 16 | 17 | void runModule(); // get IN and OUT 18 | void runFunction(Function *f); 19 | void runBasicBlock(BasicBlock *bb); 20 | void runStorePhiInst(Instruction *instr, 21 | std::map> &in); 22 | }; 23 | 24 | #endif -------------------------------------------------------------------------------- /include/OptimizePass/RefactorPartIns.h: -------------------------------------------------------------------------------- 1 | #ifndef __REFACTORPARTINS_H__ 2 | #define __REFACTORPARTINS_H__ 3 | 4 | #include "PassManager.h" 5 | 6 | class RefactorPartIns : public Pass { 7 | void refactor(Instruction *); 8 | 9 | public: 10 | RefactorPartIns(Module *m) : Pass(m) {} 11 | void run() override; 12 | }; 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /include/OptimizePass/RegisterAllocation.h: -------------------------------------------------------------------------------- 1 | #ifndef REGISTER_ALLOCATION_H 2 | #define REGISTER_ALLOCATION_H 3 | #include "Module.h" 4 | #include "Value.h" 5 | #include 6 | 7 | extern std::map *RegisterAllocation(Module *m); 8 | // extern std::unordered_map colorTable; 9 | 10 | #endif -------------------------------------------------------------------------------- /include/OptimizePass/ReturnVal.h: -------------------------------------------------------------------------------- 1 | #ifndef _RETURNVAL_H__ 2 | #define _RETURNVAL_H__ 3 | 4 | #include 5 | 6 | enum RETURN_VAL { 7 | _NORMAL, 8 | _PosNotFind_insertInstr_BasicBlock, 9 | _False_assertValid_BinaryInst, 10 | _False_assertValid_CmpInst, 11 | _ArgsNotMatch_Constructor_CallInst, 12 | _NotCondBr_fuseCmpInst_BranchInst, 13 | _cmpUsedMoreThanOnce_fuseCmpInst_BranchInst, 14 | _ElementIsArrayOrInterger_getElementType_GetElementPtrInst, 15 | _IndexError_getElementType_GetElementPtrInst, 16 | _LoadFromErrorType_Constructor_LodInst, 17 | _ElemIsNotTargetType_Constructor_LodInst, 18 | _Constructor_VVInst, 19 | _InvalidRetVal_Constructor_FunctionType, 20 | _InvalidArgType_Constructor_FunctionType, 21 | _InvalidElemType_Constructor_ArrayType, 22 | _OutOfIndex_setOperand_User, 23 | _EmptyUse_replaceAllUseWith_Value, 24 | _CantFindUse_removeUse_Value, 25 | _CantGetDefVal_getDefVal_BBConstPropagation, 26 | _CantSetDefVal_setDefVal_BBConstPropagation, 27 | _CantFindSuitableOp_compute_ConstFlod, 28 | _DeadInsButNotDelete_deleteDeadInst_DeadCodeEliminate, 29 | _deleteDeadStore_DeadCodeEliminate, 30 | _assertPredFalse_createIDom_Dominators, 31 | _getIDomFalse_intersect_Dominators, 32 | _CantGetMain_run_FunctionInline, 33 | _funcUsedByNonCall_createFuncSucc_FunctionInline, 34 | _NotCallInst_inlining_FunctionInline, 35 | _copyhasWrong_copyBasicBlocks_FunctionInline, 36 | _NewBBEmpty_copyBasicBlocks_FunctionInline, 37 | _NewInsEmpty_copyBasicBlocks_FunctionInline, 38 | _ConvBBfalse_splitBasicBlock_FunctionInline, 39 | _CantGetTerminotor_handleReturns_FunctionInline, 40 | _RetHasMoreThanOneOp_handleReturns_FunctionInline, 41 | _caeateStoreErr_handleReturns_FunctionInline, 42 | _createBrErr_handleReturns_FunctionInline, 43 | _deleteBr_handleReturns_FunctionInline, 44 | _handleVoidReturn_FunctionInline, 45 | _handlePHIReturns_FunctionInline, 46 | _ConvInsErr_run_GlobalVarivaleLocal, 47 | _whileExit_genBaseBlock_HIRTOMIR, 48 | _whileEntry_genBaseBlock_HIRTOMIR, 49 | _condSizeMoreThanOne_genBaseBlock_HIRTOMIR, 50 | _CondBegin_genBaseBlock_HIRTOMIR, 51 | _notSecheduleInst_schedule_InstructionSchedule, 52 | _ReadyEmpty_schedule_InstructionSchedule, 53 | _Eq_schedule_InstructionSchedule, 54 | _assertEqual_InstructionSchedule, 55 | _NodesEmpty_run_LoopFind, 56 | _hadBeen_findLoopBase_LoopFind, 57 | _baseEmpty_findLoopBase_LoopFind, 58 | _getParentLoop_LoopFind, 59 | _fuseCmpBr_LowerIR, 60 | _convertMulDivToShift_LowerIR, 61 | _convertRemToAnd_LowerIR, 62 | _fuseAddLoadStore_LowerIR, 63 | _removeUnusedOp_LowerIR, 64 | _refactor_RefactorPartIns, 65 | _MergeSinglePredecessorBB_SimplifyCFG, 66 | _EliminateSingleUnCondBrBB_SimplifyCFG, 67 | _GenPhi_Mem2RegPass, 68 | _createAdd_BinaryInst, 69 | _getFunction_Function, 70 | _getArgNo_Argument, 71 | _splitGEP_LowerIR, 72 | _UnoknowBaseBB_genBaseBlock_HIRTOMIR, 73 | _EliminateSinglePredecessorPhi_SimplifyCFG, 74 | _getFromSpecificReg_CodeGen, 75 | _generateFunctionEntryCode_CodeGen, 76 | _op2Const_generateInstructionCode_CodeGen, 77 | _shift_generateInstructionCode_CodeGen, 78 | _op3Const_generateInstructionCode_CodeGen, 79 | _shift3_generateInstructionCode_CodeGen, 80 | 81 | _ABORT_MANAL = 255, 82 | }; 83 | 84 | static void exit_ifnot(RETURN_VAL ret, bool cond) { 85 | if (cond == false) 86 | exit(ret); 87 | } 88 | 89 | #endif -------------------------------------------------------------------------------- /include/OptimizePass/SimplifyCFG.h: -------------------------------------------------------------------------------- 1 | #include "BasicBlock.h" 2 | #include "Function.h" 3 | #include "IRBuilder.h" 4 | #include "Instruction.h" 5 | #include "Module.h" 6 | #include "PassManager.h" 7 | 8 | class SimplifyCFG : public Transform { 9 | private: 10 | Function *func_; 11 | SimplifyCFG(); 12 | 13 | public: 14 | SimplifyCFG(Module *m) : Transform(m) {} 15 | ~SimplifyCFG(){}; 16 | void run() override; 17 | void RemoveNoPredecessorBB(); 18 | void MergeSinglePredecessorBB(); 19 | void EliminateSinglePredecessorPhi(); 20 | void EliminateSingleUnCondBrBB(); 21 | void RemoveSelfLoopBB(); 22 | }; -------------------------------------------------------------------------------- /include/OptimizePass/SparseCondConstPropagation.h: -------------------------------------------------------------------------------- 1 | #include "BasicBlock.h" 2 | #include "Function.h" 3 | #include "IRBuilder.h" 4 | #include "Instruction.h" 5 | #include "Module.h" 6 | #include "PassManager.h" 7 | 8 | class SparseCondConstPropagation : Transform { 9 | private: 10 | public: 11 | SparseCondConstPropagation(Module *m) : Transform(m) {} 12 | ~SparseCondConstPropagation() {} 13 | 14 | void run() override; 15 | void VisitPhi(PhiInst *phi); 16 | void VisitInst(Instruction *instr); 17 | }; 18 | -------------------------------------------------------------------------------- /include/OptimizePass/Vectorization.h: -------------------------------------------------------------------------------- 1 | #ifndef SYSYC_VECTORIZATION_H 2 | #define SYSYC_VECTORIZATION_H 3 | 4 | #include "LoopFind.h" 5 | #include "PassManager.h" 6 | 7 | class Vectorization : public Transform { 8 | public: 9 | const int MIN_LOOP_ITERS = 400; 10 | const int VECTORIZATE_INT32_NUM = 8; 11 | 12 | public: 13 | Vectorization(Module *m) : Transform(m) {} 14 | void run() override; 15 | bool tryVectorizate(BasicBlock *cond, BasicBlock *body); 16 | void vectorizate(BasicBlock *body, Instruction *mul, Instruction *iter); 17 | 18 | private: 19 | int vectorizate_loops = 0; 20 | }; 21 | 22 | #endif // SYSYC_VECTORIZATION_H 23 | -------------------------------------------------------------------------------- /include/OptimizePass/mem2reg.h: -------------------------------------------------------------------------------- 1 | #ifndef SYSYC_MEM2REG_H 2 | #define SYSYC_MEM2REG_H 3 | 4 | #include "BasicBlock.h" 5 | #include "Function.h" 6 | #include "IRBuilder.h" 7 | #include "Instruction.h" 8 | #include "Module.h" 9 | #include "PassManager.h" 10 | 11 | class Mem2RegPass : public Transform { 12 | private: 13 | Function *func_; 14 | IRBuilder *builder; 15 | 16 | public: 17 | Mem2RegPass(Module *m) : Transform(m) {} 18 | ~Mem2RegPass(){}; 19 | void run() override; 20 | void GenPhi(); 21 | void ReName(BasicBlock *bb); 22 | // void DeleteLS(); 23 | //可加一个遍历删除空phi节点 24 | }; 25 | 26 | #endif -------------------------------------------------------------------------------- /include/front/FlexLexer.h: -------------------------------------------------------------------------------- 1 | // -*-C++-*- 2 | // FlexLexer.h -- define interfaces for lexical analyzer classes generated 3 | // by flex 4 | 5 | // Copyright (c) 1993 The Regents of the University of California. 6 | // All rights reserved. 7 | // 8 | // This code is derived from software contributed to Berkeley by 9 | // Kent Williams and Tom Epperly. 10 | // 11 | // Redistribution and use in source and binary forms, with or without 12 | // modification, are permitted provided that the following conditions 13 | // are met: 14 | 15 | // 1. Redistributions of source code must retain the above copyright 16 | // notice, this list of conditions and the following disclaimer. 17 | // 2. Redistributions in binary form must reproduce the above copyright 18 | // notice, this list of conditions and the following disclaimer in the 19 | // documentation and/or other materials provided with the distribution. 20 | 21 | // Neither the name of the University nor the names of its contributors 22 | // may be used to endorse or promote products derived from this software 23 | // without specific prior written permission. 24 | 25 | // THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 26 | // IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 27 | // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 28 | // PURPOSE. 29 | 30 | // This file defines FlexLexer, an abstract class which specifies the 31 | // external interface provided to flex C++ lexer objects, and yyFlexLexer, 32 | // which defines a particular lexer class. 33 | // 34 | // If you want to create multiple lexer classes, you use the -P flag 35 | // to rename each yyFlexLexer to some other xxFlexLexer. You then 36 | // include in your other sources once per lexer class: 37 | // 38 | // #undef yyFlexLexer 39 | // #define yyFlexLexer xxFlexLexer 40 | // #include 41 | // 42 | // #undef yyFlexLexer 43 | // #define yyFlexLexer zzFlexLexer 44 | // #include 45 | // ... 46 | 47 | #ifndef __FLEX_LEXER_H 48 | // Never included before - need to define base class. 49 | #define __FLEX_LEXER_H 50 | 51 | #include 52 | 53 | extern "C++" { 54 | 55 | struct yy_buffer_state; 56 | typedef int yy_state_type; 57 | 58 | class FlexLexer { 59 | public: 60 | virtual ~FlexLexer() {} 61 | 62 | const char *YYText() const { return yytext; } 63 | int YYLeng() const { return yyleng; } 64 | 65 | virtual void yy_switch_to_buffer(yy_buffer_state *new_buffer) = 0; 66 | virtual yy_buffer_state *yy_create_buffer(std::istream *s, int size) = 0; 67 | virtual yy_buffer_state *yy_create_buffer(std::istream &s, int size) = 0; 68 | virtual void yy_delete_buffer(yy_buffer_state *b) = 0; 69 | virtual void yyrestart(std::istream *s) = 0; 70 | virtual void yyrestart(std::istream &s) = 0; 71 | 72 | virtual int yylex() = 0; 73 | 74 | // Call yylex with new input/output sources. 75 | int yylex(std::istream &new_in, std::ostream &new_out) { 76 | switch_streams(new_in, new_out); 77 | return yylex(); 78 | } 79 | 80 | int yylex(std::istream *new_in, std::ostream *new_out = 0) { 81 | switch_streams(new_in, new_out); 82 | return yylex(); 83 | } 84 | 85 | // Switch to new input/output streams. A nil stream pointer 86 | // indicates "keep the current one". 87 | virtual void switch_streams(std::istream *new_in, std::ostream *new_out) = 0; 88 | virtual void switch_streams(std::istream &new_in, std::ostream &new_out) = 0; 89 | 90 | int lineno() const { return yylineno; } 91 | 92 | int debug() const { return yy_flex_debug; } 93 | void set_debug(int flag) { yy_flex_debug = flag; } 94 | 95 | protected: 96 | char *yytext; 97 | int yyleng; 98 | int yylineno; // only maintained if you use %option yylineno 99 | int yy_flex_debug; // only has effect with -d or "%option debug" 100 | }; 101 | } 102 | #endif // FLEXLEXER_H 103 | 104 | #if defined(yyFlexLexer) || !defined(yyFlexLexerOnce) 105 | // Either this is the first time through (yyFlexLexerOnce not defined), 106 | // or this is a repeated include to define a different flavor of 107 | // yyFlexLexer, as discussed in the flex manual. 108 | #define yyFlexLexerOnce 109 | 110 | extern "C++" { 111 | 112 | class yyFlexLexer : public FlexLexer { 113 | public: 114 | // arg_yyin and arg_yyout default to the cin and cout, but we 115 | // only make that assignment when initializing in yylex(). 116 | yyFlexLexer(std::istream &arg_yyin, std::ostream &arg_yyout); 117 | yyFlexLexer(std::istream *arg_yyin = 0, std::ostream *arg_yyout = 0); 118 | 119 | private: 120 | void ctor_common(); 121 | 122 | public: 123 | virtual ~yyFlexLexer(); 124 | 125 | void yy_switch_to_buffer(yy_buffer_state *new_buffer); 126 | yy_buffer_state *yy_create_buffer(std::istream *s, int size); 127 | yy_buffer_state *yy_create_buffer(std::istream &s, int size); 128 | void yy_delete_buffer(yy_buffer_state *b); 129 | void yyrestart(std::istream *s); 130 | void yyrestart(std::istream &s); 131 | 132 | void yypush_buffer_state(yy_buffer_state *new_buffer); 133 | void yypop_buffer_state(); 134 | 135 | virtual int yylex(); 136 | virtual void switch_streams(std::istream &new_in, std::ostream &new_out); 137 | virtual void switch_streams(std::istream *new_in = 0, 138 | std::ostream *new_out = 0); 139 | virtual int yywrap(); 140 | 141 | protected: 142 | virtual int LexerInput(char *buf, int max_size); 143 | virtual void LexerOutput(const char *buf, int size); 144 | virtual void LexerError(const char *msg); 145 | 146 | void yyunput(int c, char *buf_ptr); 147 | int yyinput(); 148 | 149 | void yy_load_buffer_state(); 150 | void yy_init_buffer(yy_buffer_state *b, std::istream &s); 151 | void yy_flush_buffer(yy_buffer_state *b); 152 | 153 | int yy_start_stack_ptr; 154 | int yy_start_stack_depth; 155 | int *yy_start_stack; 156 | 157 | void yy_push_state(int new_state); 158 | void yy_pop_state(); 159 | int yy_top_state(); 160 | 161 | yy_state_type yy_get_previous_state(); 162 | yy_state_type yy_try_NUL_trans(yy_state_type current_state); 163 | int yy_get_next_buffer(); 164 | 165 | std::istream yyin; // input source for default LexerInput 166 | std::ostream yyout; // output sink for default LexerOutput 167 | 168 | // yy_hold_char holds the character lost when yytext is formed. 169 | char yy_hold_char; 170 | 171 | // Number of characters read into yy_ch_buf. 172 | int yy_n_chars; 173 | 174 | // Points to current character in buffer. 175 | char *yy_c_buf_p; 176 | 177 | int yy_init; // whether we need to initialize 178 | int yy_start; // start state number 179 | 180 | // Flag which is used to allow yywrap()'s to do buffer switches 181 | // instead of setting up a fresh yyin. A bit of a hack ... 182 | int yy_did_buffer_switch_on_eof; 183 | 184 | size_t yy_buffer_stack_top; /**< index of top of stack. */ 185 | size_t yy_buffer_stack_max; /**< capacity of stack. */ 186 | yy_buffer_state **yy_buffer_stack; /**< Stack as an array. */ 187 | void yyensure_buffer_stack(void); 188 | 189 | // The following are not always needed, but may be depending 190 | // on use of certain flex features (like REJECT or yymore()). 191 | 192 | yy_state_type yy_last_accepting_state; 193 | char *yy_last_accepting_cpos; 194 | 195 | yy_state_type *yy_state_buf; 196 | yy_state_type *yy_state_ptr; 197 | 198 | char *yy_full_match; 199 | int *yy_full_state; 200 | int yy_full_lp; 201 | 202 | int yy_lp; 203 | int yy_looking_for_trail_begin; 204 | 205 | int yy_more_flag; 206 | int yy_more_len; 207 | int yy_more_offset; 208 | int yy_prev_more_offset; 209 | }; 210 | } 211 | 212 | #endif // yyFlexLexer || ! yyFlexLexerOnce 213 | -------------------------------------------------------------------------------- /include/front/location.hh: -------------------------------------------------------------------------------- 1 | // A Bison parser, made by GNU Bison 3.0.4. 2 | 3 | // Locations for Bison parsers in C++ 4 | 5 | // Copyright (C) 2002-2015 Free Software Foundation, Inc. 6 | 7 | // This program is free software: you can redistribute it and/or modify 8 | // it under the terms of the GNU General Public License as published by 9 | // the Free Software Foundation, either version 3 of the License, or 10 | // (at your option) any later version. 11 | 12 | // This program is distributed in the hope that it will be useful, 13 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | // GNU General Public License for more details. 16 | 17 | // You should have received a copy of the GNU General Public License 18 | // along with this program. If not, see . 19 | 20 | // As a special exception, you may create a larger work that contains 21 | // part or all of the Bison parser skeleton and distribute that work 22 | // under terms of your choice, so long as that work isn't itself a 23 | // parser generator using the skeleton or a modified version thereof 24 | // as a parser skeleton. Alternatively, if you modify or redistribute 25 | // the parser skeleton itself, you may (at your option) remove this 26 | // special exception, which will cause the skeleton and the resulting 27 | // Bison output files to be licensed under the GNU General Public 28 | // License without this special exception. 29 | 30 | // This special exception was added by the Free Software Foundation in 31 | // version 2.2 of Bison. 32 | 33 | /** 34 | ** \file location.hh 35 | ** Define the yy::location class. 36 | */ 37 | 38 | #ifndef YY_YY_LOCATION_HH_INCLUDED 39 | #define YY_YY_LOCATION_HH_INCLUDED 40 | 41 | #include "position.hh" 42 | 43 | namespace yy { 44 | #line 46 "location.hh" // location.cc:296 45 | /// Abstract a location. 46 | class location { 47 | public: 48 | /// Construct a location from \a b to \a e. 49 | location(const position &b, const position &e) : begin(b), end(e) {} 50 | 51 | /// Construct a 0-width location in \a p. 52 | explicit location(const position &p = position()) : begin(p), end(p) {} 53 | 54 | /// Construct a 0-width location in \a f, \a l, \a c. 55 | explicit location(std::string *f, unsigned int l = 1u, unsigned int c = 1u) 56 | : begin(f, l, c), end(f, l, c) {} 57 | 58 | /// Initialization. 59 | void initialize(std::string *f = YY_NULLPTR, unsigned int l = 1u, 60 | unsigned int c = 1u) { 61 | begin.initialize(f, l, c); 62 | end = begin; 63 | } 64 | 65 | /** \name Line and Column related manipulators 66 | ** \{ */ 67 | public: 68 | /// Reset initial location to final location. 69 | void step() { begin = end; } 70 | 71 | /// Extend the current location to the COUNT next columns. 72 | void columns(int count = 1) { end += count; } 73 | 74 | /// Extend the current location to the COUNT next lines. 75 | void lines(int count = 1) { end.lines(count); } 76 | /** \} */ 77 | 78 | public: 79 | /// Beginning of the located region. 80 | position begin; 81 | /// End of the located region. 82 | position end; 83 | }; 84 | 85 | /// Join two locations, in place. 86 | inline location &operator+=(location &res, const location &end) { 87 | res.end = end.end; 88 | return res; 89 | } 90 | 91 | /// Join two locations. 92 | inline location operator+(location res, const location &end) { 93 | return res += end; 94 | } 95 | 96 | /// Add \a width columns to the end position, in place. 97 | inline location &operator+=(location &res, int width) { 98 | res.columns(width); 99 | return res; 100 | } 101 | 102 | /// Add \a width columns to the end position. 103 | inline location operator+(location res, int width) { return res += width; } 104 | 105 | /// Subtract \a width columns to the end position, in place. 106 | inline location &operator-=(location &res, int width) { return res += -width; } 107 | 108 | /// Subtract \a width columns to the end position. 109 | inline location operator-(location res, int width) { return res -= width; } 110 | 111 | /// Compare two location objects. 112 | inline bool operator==(const location &loc1, const location &loc2) { 113 | return loc1.begin == loc2.begin && loc1.end == loc2.end; 114 | } 115 | 116 | /// Compare two location objects. 117 | inline bool operator!=(const location &loc1, const location &loc2) { 118 | return !(loc1 == loc2); 119 | } 120 | 121 | /** \brief Intercept output stream redirection. 122 | ** \param ostr the destination output stream 123 | ** \param loc a reference to the location to redirect 124 | ** 125 | ** Avoid duplicate information. 126 | */ 127 | template 128 | inline std::basic_ostream &operator<<(std::basic_ostream &ostr, 129 | const location &loc) { 130 | unsigned int end_col = 0 < loc.end.column ? loc.end.column - 1 : 0; 131 | ostr << loc.begin; 132 | if (loc.end.filename && 133 | (!loc.begin.filename || *loc.begin.filename != *loc.end.filename)) 134 | ostr << '-' << loc.end.filename << ':' << loc.end.line << '.' << end_col; 135 | else if (loc.begin.line < loc.end.line) 136 | ostr << '-' << loc.end.line << '.' << end_col; 137 | else if (loc.begin.column < end_col) 138 | ostr << '-' << end_col; 139 | return ostr; 140 | } 141 | 142 | } // namespace yy 143 | #line 192 "location.hh" // location.cc:296 144 | #endif // !YY_YY_LOCATION_HH_INCLUDED 145 | -------------------------------------------------------------------------------- /include/front/position.hh: -------------------------------------------------------------------------------- 1 | // A Bison parser, made by GNU Bison 3.0.4. 2 | 3 | // Positions for Bison parsers in C++ 4 | 5 | // Copyright (C) 2002-2015 Free Software Foundation, Inc. 6 | 7 | // This program is free software: you can redistribute it and/or modify 8 | // it under the terms of the GNU General Public License as published by 9 | // the Free Software Foundation, either version 3 of the License, or 10 | // (at your option) any later version. 11 | 12 | // This program is distributed in the hope that it will be useful, 13 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | // GNU General Public License for more details. 16 | 17 | // You should have received a copy of the GNU General Public License 18 | // along with this program. If not, see . 19 | 20 | // As a special exception, you may create a larger work that contains 21 | // part or all of the Bison parser skeleton and distribute that work 22 | // under terms of your choice, so long as that work isn't itself a 23 | // parser generator using the skeleton or a modified version thereof 24 | // as a parser skeleton. Alternatively, if you modify or redistribute 25 | // the parser skeleton itself, you may (at your option) remove this 26 | // special exception, which will cause the skeleton and the resulting 27 | // Bison output files to be licensed under the GNU General Public 28 | // License without this special exception. 29 | 30 | // This special exception was added by the Free Software Foundation in 31 | // version 2.2 of Bison. 32 | 33 | /** 34 | ** \file position.hh 35 | ** Define the yy::position class. 36 | */ 37 | 38 | #ifndef YY_YY_POSITION_HH_INCLUDED 39 | #define YY_YY_POSITION_HH_INCLUDED 40 | 41 | #include // std::max 42 | #include 43 | #include 44 | 45 | #ifndef YY_NULLPTR 46 | #if defined __cplusplus && 201103L <= __cplusplus 47 | #define YY_NULLPTR nullptr 48 | #else 49 | #define YY_NULLPTR 0 50 | #endif 51 | #endif 52 | 53 | namespace yy { 54 | #line 56 "position.hh" // location.cc:296 55 | /// Abstract a position. 56 | class position { 57 | public: 58 | /// Construct a position. 59 | explicit position(std::string *f = YY_NULLPTR, unsigned int l = 1u, 60 | unsigned int c = 1u) 61 | : filename(f), line(l), column(c) {} 62 | 63 | /// Initialization. 64 | void initialize(std::string *fn = YY_NULLPTR, unsigned int l = 1u, 65 | unsigned int c = 1u) { 66 | filename = fn; 67 | line = l; 68 | column = c; 69 | } 70 | 71 | /** \name Line and Column related manipulators 72 | ** \{ */ 73 | /// (line related) Advance to the COUNT next lines. 74 | void lines(int count = 1) { 75 | if (count) { 76 | column = 1u; 77 | line = add_(line, count, 1); 78 | } 79 | } 80 | 81 | /// (column related) Advance to the COUNT next columns. 82 | void columns(int count = 1) { column = add_(column, count, 1); } 83 | /** \} */ 84 | 85 | /// File name to which this position refers. 86 | std::string *filename; 87 | /// Current line number. 88 | unsigned int line; 89 | /// Current column number. 90 | unsigned int column; 91 | 92 | private: 93 | /// Compute max(min, lhs+rhs) (provided min <= lhs). 94 | static unsigned int add_(unsigned int lhs, int rhs, unsigned int min) { 95 | return (0 < rhs || -static_cast(rhs) < lhs ? rhs + lhs : min); 96 | } 97 | }; 98 | 99 | /// Add \a width columns, in place. 100 | inline position &operator+=(position &res, int width) { 101 | res.columns(width); 102 | return res; 103 | } 104 | 105 | /// Add \a width columns. 106 | inline position operator+(position res, int width) { return res += width; } 107 | 108 | /// Subtract \a width columns, in place. 109 | inline position &operator-=(position &res, int width) { return res += -width; } 110 | 111 | /// Subtract \a width columns. 112 | inline position operator-(position res, int width) { return res -= width; } 113 | 114 | /// Compare two position objects. 115 | inline bool operator==(const position &pos1, const position &pos2) { 116 | return ( 117 | pos1.line == pos2.line && pos1.column == pos2.column && 118 | (pos1.filename == pos2.filename || 119 | (pos1.filename && pos2.filename && *pos1.filename == *pos2.filename))); 120 | } 121 | 122 | /// Compare two position objects. 123 | inline bool operator!=(const position &pos1, const position &pos2) { 124 | return !(pos1 == pos2); 125 | } 126 | 127 | /** \brief Intercept output stream redirection. 128 | ** \param ostr the destination output stream 129 | ** \param pos a reference to the position to redirect 130 | */ 131 | template 132 | inline std::basic_ostream &operator<<(std::basic_ostream &ostr, 133 | const position &pos) { 134 | if (pos.filename) 135 | ostr << *pos.filename << ':'; 136 | return ostr << pos.line << '.' << pos.column; 137 | } 138 | 139 | } // namespace yy 140 | #line 180 "position.hh" // location.cc:296 141 | #endif // !YY_YY_POSITION_HH_INCLUDED 142 | -------------------------------------------------------------------------------- /include/front/stack.hh: -------------------------------------------------------------------------------- 1 | // A Bison parser, made by GNU Bison 3.0.4. 2 | 3 | // Stack handling for Bison parsers in C++ 4 | 5 | // Copyright (C) 2002-2015 Free Software Foundation, Inc. 6 | 7 | // This program is free software: you can redistribute it and/or modify 8 | // it under the terms of the GNU General Public License as published by 9 | // the Free Software Foundation, either version 3 of the License, or 10 | // (at your option) any later version. 11 | 12 | // This program is distributed in the hope that it will be useful, 13 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | // GNU General Public License for more details. 16 | 17 | // You should have received a copy of the GNU General Public License 18 | // along with this program. If not, see . 19 | 20 | // As a special exception, you may create a larger work that contains 21 | // part or all of the Bison parser skeleton and distribute that work 22 | // under terms of your choice, so long as that work isn't itself a 23 | // parser generator using the skeleton or a modified version thereof 24 | // as a parser skeleton. Alternatively, if you modify or redistribute 25 | // the parser skeleton itself, you may (at your option) remove this 26 | // special exception, which will cause the skeleton and the resulting 27 | // Bison output files to be licensed under the GNU General Public 28 | // License without this special exception. 29 | 30 | // This special exception was added by the Free Software Foundation in 31 | // version 2.2 of Bison. 32 | 33 | /** 34 | ** \file stack.hh 35 | ** Define the yy::stack class. 36 | */ 37 | 38 | #ifndef YY_YY_STACK_HH_INCLUDED 39 | #define YY_YY_STACK_HH_INCLUDED 40 | 41 | #include 42 | 43 | namespace yy { 44 | #line 46 "stack.hh" // stack.hh:132 45 | template > class stack { 46 | public: 47 | // Hide our reversed order. 48 | typedef typename S::reverse_iterator iterator; 49 | typedef typename S::const_reverse_iterator const_iterator; 50 | 51 | stack() : seq_() { seq_.reserve(200); } 52 | 53 | stack(unsigned int n) : seq_(n) {} 54 | 55 | inline T &operator[](unsigned int i) { return seq_[seq_.size() - 1 - i]; } 56 | 57 | inline const T &operator[](unsigned int i) const { 58 | return seq_[seq_.size() - 1 - i]; 59 | } 60 | 61 | /// Steal the contents of \a t. 62 | /// 63 | /// Close to move-semantics. 64 | inline void push(T &t) { 65 | seq_.push_back(T()); 66 | operator[](0).move(t); 67 | } 68 | 69 | inline void pop(unsigned int n = 1) { 70 | for (; n; --n) 71 | seq_.pop_back(); 72 | } 73 | 74 | void clear() { seq_.clear(); } 75 | 76 | inline typename S::size_type size() const { return seq_.size(); } 77 | 78 | inline const_iterator begin() const { return seq_.rbegin(); } 79 | 80 | inline const_iterator end() const { return seq_.rend(); } 81 | 82 | private: 83 | stack(const stack &); 84 | stack &operator=(const stack &); 85 | /// The wrapped container. 86 | S seq_; 87 | }; 88 | 89 | /// Present a slice of the top of a stack. 90 | template > class slice { 91 | public: 92 | slice(const S &stack, unsigned int range) : stack_(stack), range_(range) {} 93 | 94 | inline const T &operator[](unsigned int i) const { 95 | return stack_[range_ - i]; 96 | } 97 | 98 | private: 99 | const S &stack_; 100 | unsigned int range_; 101 | }; 102 | 103 | } // namespace yy 104 | #line 156 "stack.hh" // stack.hh:132 105 | 106 | #endif // !YY_YY_STACK_HH_INCLUDED 107 | -------------------------------------------------------------------------------- /include/front/sysyFlexLexer.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifndef YY_DECL 4 | #define YY_DECL \ 5 | yy::sysy_parser::symbol_type sysyFlexLexer::yylex(sysy_driver &driver) 6 | #endif 7 | 8 | // We need this for yyFlexLexer. If we don't #undef yyFlexLexer, the 9 | // preprocessor chokes on the line `#define yyFlexLexer yyFlexLexer` 10 | // in `FlexLexer.h`: 11 | #undef yyFlexLexer 12 | #include 13 | 14 | // We need this for the yy::calcxx_parser::symbol_type: 15 | #include "sysy_parser.hh" 16 | 17 | // We need this for the yy::location type: 18 | #include "location.hh" 19 | 20 | class sysyFlexLexer : public yyFlexLexer { 21 | public: 22 | // Use the superclass's constructor: 23 | using yyFlexLexer::yyFlexLexer; 24 | 25 | // Provide the interface to `yylex`; `flex` will emit the 26 | // definition into `calc++-scanner.cc`: 27 | yy::sysy_parser::symbol_type yylex(sysy_driver &driver); 28 | 29 | // This seems like a reasonable place to put the location object 30 | // rather than it being static (in the sense of having internal 31 | // linkage at translation unit scope, not in the sense of being a 32 | // class variable): 33 | yy::location loc; 34 | }; 35 | -------------------------------------------------------------------------------- /include/front/sysy_driver.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // CHANGE: added for new std::ifstream member "instream": 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | // Generated by bison: 10 | #include "sysy_parser.hh" 11 | 12 | // CHANGE: replaced `#define YY_DECL ...` here with #include of new 13 | // lexer class: 14 | #include "sysyFlexLexer.hh" 15 | 16 | // Conducting the whole scanning and parsing of Calc++. 17 | class sysy_driver { 18 | public: 19 | sysy_driver(); 20 | virtual ~sysy_driver(); 21 | 22 | std::map variables; 23 | 24 | int result; 25 | 26 | // CHANGE: add lexer object as a member 27 | sysyFlexLexer lexer; 28 | 29 | // CHANGE: add ifstream object as a member 30 | std::ifstream instream; 31 | 32 | // Handling the scanner. 33 | void scan_begin(); 34 | void scan_end(); 35 | bool trace_scanning; 36 | 37 | // Run the parser on file F. 38 | // Return 0 on success. 39 | SyntaxCompUnit *parse(const std::string &f); 40 | // The name of the file being parsed. 41 | // Used later to pass the file name to the location tracker. 42 | std::string file; 43 | // Whether parser traces should be generated. 44 | bool trace_parsing; 45 | 46 | // std::istream poss_stream; 47 | // preprocess 48 | std::string preprocess(); 49 | 50 | // Error handling. 51 | void error(const yy::location &l, const std::string &m); 52 | void error(const std::string &m); 53 | 54 | SyntaxCompUnit *root = nullptr; 55 | }; 56 | -------------------------------------------------------------------------------- /libsysy.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlzeng/CSC2020-USTC-FlammingMyCompiler/ed205c0a5bc013a888a8c37c80ccffd1ae1134e0/libsysy.a -------------------------------------------------------------------------------- /mt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mlzeng/CSC2020-USTC-FlammingMyCompiler/ed205c0a5bc013a888a8c37c80ccffd1ae1134e0/mt.png -------------------------------------------------------------------------------- /src/CodeGen/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_library( 2 | CodeGen 3 | CodeGen.cc 4 | InstructionsGen.cc 5 | RegAlloc.cc 6 | Analyzer.cc 7 | ) -------------------------------------------------------------------------------- /src/IR/BaseBlock.cc: -------------------------------------------------------------------------------- 1 | #include "BaseBlock.h" 2 | #include "Function.h" 3 | 4 | // this will auto add this to function's baseblock list 5 | // don't use this in nested structure 6 | BaseBlock::BaseBlock(BlockType ty, Module *m, const std::string &name, 7 | Function *func) 8 | : block_ty_(ty), Value(Type::getLabelTy(m), name), father_(nullptr), 9 | func_(func) { 10 | func->addBaseBlock(this); 11 | } -------------------------------------------------------------------------------- /src/IR/BasicBlock.cc: -------------------------------------------------------------------------------- 1 | #include "BasicBlock.h" 2 | #include "Function.h" 3 | #include "Module.h" 4 | #include "ReturnVal.h" 5 | #include 6 | 7 | BasicBlock::BasicBlock(Module *m, const std::string &name) 8 | : BaseBlock(BaseBlock::Basic, m, name) { 9 | // assert(parent && "currently parent should not be nullptr"); 10 | // if (func) 11 | // func->addBasicBlock(this); 12 | } 13 | 14 | BasicBlock::BasicBlock(Module *m, const std::string &name, Function *func) 15 | : BaseBlock(BaseBlock::Basic, m, name, func) {} 16 | 17 | Module *BasicBlock::getModule() const { return getParent()->getParent(); } 18 | 19 | void BasicBlock::addInstruction(Instruction *instr) { 20 | // auto seq = atoi(this->getName().c_str()); 21 | // seq += instr_list_.size(); 22 | // instr->setName(std::to_string(seq)); 23 | instr_list_.push_back(instr); 24 | instr->setParent(this); 25 | } 26 | 27 | void BasicBlock::addInstrBegin(Instruction *instr) { 28 | instr_list_.push_front(instr); 29 | instr->setParent(this); 30 | } 31 | 32 | void BasicBlock::insertInstr(Instruction *pos, Instruction *insert) { 33 | insert->setParent(pos->getParent()); 34 | for (auto instr = instr_list_.begin(); instr != instr_list_.end(); instr++) { 35 | if (*instr == pos) { 36 | instr_list_.insert(instr, insert); 37 | return; 38 | } 39 | } 40 | // abort(); 41 | exit_ifnot(_PosNotFind_insertInstr_BasicBlock, false); 42 | } 43 | 44 | void BasicBlock::deleteInstr(Instruction *instr) { 45 | instr_list_.remove(instr); 46 | instr->removeUseOfOps(); 47 | } 48 | 49 | const Instruction *BasicBlock::getTerminator() const { 50 | if (instr_list_.empty()) { 51 | return nullptr; 52 | } 53 | switch (instr_list_.back()->getInstrType()) { 54 | case Instruction::Ret: 55 | return instr_list_.back(); 56 | break; 57 | 58 | case Instruction::Br: 59 | return instr_list_.back(); 60 | break; 61 | 62 | default: 63 | return nullptr; 64 | break; 65 | } 66 | return nullptr; 67 | } 68 | 69 | void BasicBlock::print() { 70 | this->getType()->print(); 71 | std::cerr << " %" << this->getName() << " "; 72 | return; 73 | } 74 | 75 | bool BasicBlock::hasRet() { return getTerminator()->isRet(); } -------------------------------------------------------------------------------- /src/IR/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_library( 2 | IR_lib STATIC 3 | Type.cc 4 | User.cc 5 | Value.cc 6 | BasicBlock.cc 7 | Constant.cc 8 | Function.cc 9 | GlobalVariable.cc 10 | Instruction.cc 11 | Module.cc 12 | BaseBlock.cc 13 | ) -------------------------------------------------------------------------------- /src/IR/Constant.cc: -------------------------------------------------------------------------------- 1 | #include "Constant.h" 2 | #include "Module.h" 3 | 4 | ConstantInt *ConstantInt::get(int val, Module *m) { 5 | return new ConstantInt(Type::getInt32Ty(m), val); 6 | } 7 | 8 | ConstantArray::ConstantArray(ArrayType *ty, const std::vector &val) 9 | : Constant(ty, "", val.size()) { 10 | for (int i = 0; i < val.size(); i++) 11 | setOperand(i, val[i]); 12 | this->const_array.assign(val.begin(), val.end()); 13 | } 14 | 15 | Constant *ConstantArray::getElementValue(int index) { 16 | return this->const_array[index]; 17 | } 18 | 19 | ConstantArray *ConstantArray::get(ArrayType *ty, 20 | const std::vector &val) { 21 | return new ConstantArray(ty, val); 22 | } 23 | 24 | void Constant::print() { 25 | if (this->getType()->isArrayTy()) { 26 | static_cast(this)->print(); 27 | } else { 28 | static_cast(this)->print(); 29 | } 30 | } 31 | 32 | void ConstantInt::print() { 33 | this->getType()->print(); 34 | std::cerr << " " << this->getValue() << " "; 35 | } 36 | 37 | void ConstantArray::print() { 38 | this->getType()->print(); 39 | std::cerr << " [ "; 40 | for (auto const_val : const_array) { 41 | if (const_val->getType()->isArrayTy()) { 42 | static_cast(const_val)->print(); 43 | } else { 44 | static_cast(const_val)->print(); 45 | } 46 | } 47 | std::cerr << " ] "; 48 | } -------------------------------------------------------------------------------- /src/IR/GlobalVariable.cc: -------------------------------------------------------------------------------- 1 | // 2 | // Created by cqy on 2020/6/29. 3 | // 4 | #include "GlobalVariable.h" 5 | 6 | GlobalVariable::GlobalVariable(std::string name, Module *m, Type *ty, 7 | bool is_const, Constant *init) 8 | : User(ty, name, init != nullptr), is_const_(is_const), init_val_(init) { 9 | m->addGlobalVariable(this); 10 | if (init) { 11 | this->setOperand(0, init); 12 | } 13 | } // global操作数为initval 14 | 15 | GlobalVariable *GlobalVariable::create(std::string name, Module *m, Type *ty, 16 | bool is_const, 17 | Constant *init = nullptr) { 18 | return new GlobalVariable(name, m, PointerType::get(ty), is_const, init); 19 | } 20 | 21 | void GlobalVariable::print() { 22 | this->getType()->print(); 23 | std::cerr << " @" << this->getName() << " "; 24 | } -------------------------------------------------------------------------------- /src/IR/Module.cc: -------------------------------------------------------------------------------- 1 | #include "Module.h" 2 | 3 | Module::Module(std::string name) : module_name_(name) { 4 | void_ty_ = new Type(Type::VoidTyID); 5 | label_ty_ = new Type(Type::LabelTyID); 6 | int1_ty_ = new IntegerType(1); 7 | int32_ty_ = new IntegerType(32); 8 | int32ptr_ty_ = new PointerType(int32_ty_); 9 | } 10 | 11 | Module::~Module() { 12 | delete void_ty_; 13 | delete label_ty_; 14 | delete int1_ty_; 15 | delete int32_ty_; 16 | delete int32ptr_ty_; 17 | } 18 | 19 | Type *Module::getVoidTy() { return void_ty_; } 20 | 21 | Type *Module::getLabelTy() { return label_ty_; } 22 | 23 | IntegerType *Module::getInt1Ty() { return int1_ty_; } 24 | 25 | IntegerType *Module::getInt32Ty() { return int32_ty_; } 26 | 27 | PointerType *Module::getInt32PtrTy() { return int32ptr_ty_; } 28 | 29 | void Module::addFunction(Function *f) { function_list_.push_back(f); } 30 | 31 | void Module::addGlobalVariable(GlobalVariable *g) { global_list_.push_back(g); } 32 | 33 | void Module::print() { 34 | std::cerr << "; Module name: " 35 | << "\'" << module_name_ << "\'" << std::endl; 36 | std::cerr << "source_filename: " 37 | << "\"" << source_file_name_ << "\"" << std::endl; 38 | for (auto gobal_var : global_list_) { 39 | gobal_var->print(); 40 | std::cerr << " = " 41 | << "global "; 42 | gobal_var->getInit()->print(); 43 | std::cerr << std::endl; 44 | } 45 | for (auto func : function_list_) { 46 | func->print(); 47 | } 48 | } 49 | 50 | void Module::HighIRprint() { 51 | std::cerr << "; Module name: " 52 | << "\'" << module_name_ << "\'" << std::endl; 53 | std::cerr << "source_filename: " 54 | << "\"" << source_file_name_ << "\"" << std::endl; 55 | for (auto gobal_var : global_list_) { 56 | gobal_var->print(); 57 | std::cerr << " = " 58 | << "global "; 59 | gobal_var->getInit()->print(); 60 | std::cerr << std::endl; 61 | } 62 | for (auto func : function_list_) { 63 | func->HighIRprint(); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/IR/Type.cc: -------------------------------------------------------------------------------- 1 | #include "Type.h" 2 | #include "Module.h" 3 | #include "ReturnVal.h" 4 | #include 5 | 6 | Type::Type(TypeID tid) { tid_ = tid; } 7 | 8 | bool Type::isInt1() { 9 | if (getTypeID() == IntegerTyID) { 10 | if (static_cast(this)->getNumBits() == 1) { 11 | return true; 12 | } else { 13 | return false; 14 | } 15 | } else { 16 | return false; 17 | } 18 | } 19 | 20 | bool Type::isInt32() { 21 | if (getTypeID() == IntegerTyID) { 22 | if (static_cast(this)->getNumBits() == 32) { 23 | return true; 24 | } else { 25 | return false; 26 | } 27 | } else { 28 | return false; 29 | } 30 | } 31 | 32 | Type *Type::getVoidTy(Module *m) { return m->getVoidTy(); } 33 | 34 | Type *Type::getLabelTy(Module *m) { return m->getLabelTy(); } 35 | 36 | IntegerType *Type::getInt1Ty(Module *m) { return m->getInt1Ty(); } 37 | 38 | IntegerType *Type::getInt32Ty(Module *m) { return m->getInt32Ty(); } 39 | 40 | PointerType *Type::getInt32PtrTy(Module *m) { return m->getInt32PtrTy(); } 41 | 42 | Type *Type::getPointerElementType() { 43 | if (this->isPointerTy()) 44 | return static_cast(this)->getElementType(); 45 | else 46 | return nullptr; 47 | } 48 | 49 | int Type::getSize(bool extended) { 50 | if (this->isIntegerTy()) { 51 | auto bits = static_cast(this)->getNumBits() / 8; 52 | return bits > 0 ? bits : 1; 53 | } 54 | if (this->isArrayTy()) { 55 | auto element_size = 56 | static_cast(this)->getElementType()->getSize(); 57 | auto num_elements = static_cast(this)->getNumOfElements(); 58 | return element_size * num_elements; 59 | } 60 | if (this->isPointerTy()) { 61 | if (extended && this->getPointerElementType()->isArrayTy()) { 62 | return this->getPointerElementType()->getSize(); 63 | } else { 64 | return 4; 65 | } 66 | } 67 | return 0; 68 | } 69 | 70 | void Type::print() { 71 | switch (tid_) { 72 | case LabelTyID: 73 | std::cerr << "