├── lib ├── libsysy.a └── libsysy.so ├── images ├── ast_node_class_uml.png └── compiler_architecture.png ├── include ├── Pass │ ├── loop_unroll.h │ ├── simplify_armcode.h │ ├── loop.h │ ├── arm_offset_fixup.h │ ├── ssa_simple_optimize.h │ ├── constant_propagation.h │ ├── instruction_combining.h │ ├── dead_function_eliminate.h │ ├── cond_br_to_insts.h │ ├── simplify_cfg.h │ ├── reach_define.h │ ├── arm_liveness_analysis.h │ ├── ir_liveness_analysis.h │ ├── dead_code_eliminate.h │ ├── allocate_register.h │ ├── dominant.h │ ├── convert_ssa.h │ ├── pass_manager.h │ ├── generate_arm_from_ssa.h │ └── global_value_numbering.h ├── myassert.h ├── general_struct.h ├── arm_struct.h ├── ir_struct.h ├── ssa_struct.h ├── ir.h └── arm.h ├── .gitignore ├── Readme.md ├── makefile ├── LICENSE ├── src ├── Pass │ ├── simplify_cfg.cpp │ ├── cond_br_to_insts.cpp │ ├── simplify_armcode.cpp │ ├── dead_function_eliminate.cpp │ ├── dominant.cpp │ ├── constant_propagation.cpp │ ├── arm_offset_fixup.cpp │ ├── arm_liveness_analysis.cpp │ ├── ssa_simple_optimize.cpp │ ├── dead_code_eliminate.cpp │ ├── ir_liveness_analysis.cpp │ ├── instruction_combining.cpp │ └── reach_define.cpp ├── parser.hpp ├── scanner.l ├── ir_struct.cpp ├── construct_ir_module.cpp ├── evaluate.cpp ├── arm_struct.cpp ├── ssa_struct.cpp ├── main.cpp ├── arm.cpp ├── ssa.cpp └── ir.cpp └── utils └── test_script.py /lib/libsysy.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luooofan/hblzbd_compiler/HEAD/lib/libsysy.a -------------------------------------------------------------------------------- /lib/libsysy.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luooofan/hblzbd_compiler/HEAD/lib/libsysy.so -------------------------------------------------------------------------------- /images/ast_node_class_uml.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luooofan/hblzbd_compiler/HEAD/images/ast_node_class_uml.png -------------------------------------------------------------------------------- /images/compiler_architecture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luooofan/hblzbd_compiler/HEAD/images/compiler_architecture.png -------------------------------------------------------------------------------- /include/Pass/loop_unroll.h: -------------------------------------------------------------------------------- 1 | #include "pass_manager.h" 2 | 3 | class LoopUnroll : public Pass { 4 | public: 5 | int x; 6 | LoopUnroll(Module** m) : Pass(m) {} 7 | void Run(); 8 | }; -------------------------------------------------------------------------------- /include/Pass/simplify_armcode.h: -------------------------------------------------------------------------------- 1 | #include "../arm_struct.h" 2 | #include "pass_manager.h" 3 | 4 | class SimplifyArm : public Transform { 5 | public: 6 | SimplifyArm(Module **m) : Transform(m) {} 7 | void Run(); 8 | }; -------------------------------------------------------------------------------- /include/Pass/loop.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "pass_manager.h" 4 | 5 | class InvariantExtrapolation : public Pass { 6 | public: 7 | int x; 8 | InvariantExtrapolation(Module** m) : Pass(m) {} 9 | void Run(); 10 | }; -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | sysyruntimelibrary*/ 2 | autotest*/ 3 | /*.sh 4 | *.out* 5 | /*.sy 6 | *.txt 7 | /*compiler 8 | test/* 9 | !test/test_*.sy 10 | docs/ 11 | src/ast_* 12 | .vscode/ 13 | *.s 14 | temp* 15 | /test* 16 | *.zip 17 | build/ 18 | output/ 19 | *gitlab* 20 | generate_DAG.png 21 | -------------------------------------------------------------------------------- /include/Pass/arm_offset_fixup.h: -------------------------------------------------------------------------------- 1 | #include "./pass_manager.h" 2 | class ArmFunction; 3 | 4 | class SPOffsetFixup : public Transform { 5 | public: 6 | SPOffsetFixup(Module** m) : Transform(m) {} 7 | void Run() override; 8 | 9 | private: 10 | void Fixup4Func(ArmFunction* func); 11 | }; -------------------------------------------------------------------------------- /include/Pass/ssa_simple_optimize.h: -------------------------------------------------------------------------------- 1 | #ifndef __SIMPLE_OPTIMIZE_H__ 2 | #define __SIMPLE_OPTIMIZE_H__ 3 | #include "./pass_manager.h" 4 | 5 | class Module; 6 | class SimpleOptimize : public Transform { 7 | public: 8 | SimpleOptimize(Module** m) : Transform(m) {} 9 | void Run() override; 10 | }; 11 | 12 | #endif -------------------------------------------------------------------------------- /include/Pass/constant_propagation.h: -------------------------------------------------------------------------------- 1 | #ifndef __CONSTANT_PROPAGATION_H__ 2 | #define __CONSTANT_PROPAGATION_H__ 3 | 4 | #include "./pass_manager.h" 5 | #include "./reach_define.h" 6 | 7 | class ConstantPropagation : public Transform { 8 | public: 9 | ConstantPropagation(Module **m) : Transform(m) {} 10 | 11 | void Run(); 12 | }; 13 | 14 | #endif -------------------------------------------------------------------------------- /include/Pass/instruction_combining.h: -------------------------------------------------------------------------------- 1 | #ifndef __INSTRUCTION_COMBINING__ 2 | #define __INSTRUCTION_COMBINING__ 3 | 4 | #include "../ir.h" 5 | #include "../ir_struct.h" 6 | #include "./pass_manager.h" 7 | 8 | class Instruction_Combining : public Transform { 9 | public: 10 | Instruction_Combining(Module **m) : Transform(m) {} 11 | 12 | void Run(); 13 | }; 14 | 15 | #endif -------------------------------------------------------------------------------- /include/Pass/dead_function_eliminate.h: -------------------------------------------------------------------------------- 1 | #ifndef __DEAD_FUNCTION_ELIMINATE__ 2 | #define __DEAD_FUNCTION_ELIMINATE__ 3 | 4 | #include "./pass_manager.h" 5 | #include "../ir_struct.h" 6 | #include "../ir.h" 7 | 8 | class DeadFunctionEliminate : public Transform{ 9 | public: 10 | DeadFunctionEliminate(Module **m) : Transform(m) { } 11 | 12 | void Run(); 13 | }; 14 | 15 | #endif -------------------------------------------------------------------------------- /include/Pass/cond_br_to_insts.h: -------------------------------------------------------------------------------- 1 | #ifndef __ARM_COND_BR_TO_INSTS_H__ 2 | #define __ARM_COND_BR_TO_INSTS_H__ 3 | 4 | #include "./pass_manager.h" 5 | 6 | class Module; 7 | class ArmFunction; 8 | class CondBrToInsts : public Transform { 9 | public: 10 | CondBrToInsts(Module** m) : Transform(m) {} 11 | void Run() override; 12 | void Run4Func(ArmFunction* func); 13 | }; 14 | 15 | #endif -------------------------------------------------------------------------------- /include/Pass/simplify_cfg.h: -------------------------------------------------------------------------------- 1 | #ifndef __SIMPLIFY_CFG_H__ 2 | #define __SIMPLIFY_CFG_H__ 3 | 4 | #include "../ir_struct.h" 5 | #include "../ssa_struct.h" 6 | #include "pass_manager.h" 7 | 8 | class SimplifyCFG : public Transform { 9 | public: 10 | SimplifyCFG(Module** m) : Transform(m) {} 11 | void Run() override; 12 | void Run4IRFunc(IRFunction* func); 13 | void Run4SSAFunc(SSAFunction* func); 14 | }; 15 | #endif -------------------------------------------------------------------------------- /include/Pass/reach_define.h: -------------------------------------------------------------------------------- 1 | #ifndef __REACH_DEFINE__ 2 | #define __REACH_DEFINE__ 3 | 4 | #include "../ir.h" 5 | #include "../ir_struct.h" 6 | #include "pass_manager.h" 7 | 8 | class ReachDefine : public Analysis { 9 | public: 10 | ReachDefine(Module **m) : Analysis(m) {} 11 | 12 | void Run(); 13 | void Run4Func(IRFunction *f); 14 | void GetGenKill4Func(IRFunction *f); 15 | std::pair, std::unordered_set> GetGenKill(ir::IR *ir, IRFunction *func); 16 | void GetUseDefChain(IRModule *m); 17 | }; 18 | 19 | #endif -------------------------------------------------------------------------------- /include/Pass/arm_liveness_analysis.h: -------------------------------------------------------------------------------- 1 | #include "../arm_struct.h" 2 | #include "pass_manager.h" 3 | // 4 | using namespace arm; 5 | using RegId = int; 6 | 7 | std::pair, std::vector> GetDefUse(Instruction *inst); 8 | std::pair, std::vector> GetDefUsePtr(Instruction *inst); 9 | 10 | class ArmLivenessAnalysis : public Analysis { 11 | public: 12 | ArmLivenessAnalysis(Module **m) : Analysis(m) {} 13 | // 对一个arm function做活跃变量分析 14 | static void Run4Func(ArmFunction *f); 15 | // 对整个module做活跃变量分析 16 | void Run(); 17 | }; -------------------------------------------------------------------------------- /include/myassert.h: -------------------------------------------------------------------------------- 1 | #ifndef __MYASSERT_H__ 2 | #define __MYASSERT_H__ 3 | 4 | // #include 5 | // #define ASSERT_ENABLE 6 | // assert(res); 7 | #include 8 | #ifdef ASSERT_ENABLE 9 | #define MyAssert(res) \ 10 | if (!(res)) { \ 11 | std::cerr << "Assert: " << __FILE__ << ":" << __LINE__ << std::endl; \ 12 | exit(255); \ 13 | } 14 | #else 15 | #define MyAssert(res) ; 16 | #endif 17 | 18 | #endif -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | # hblzbd_compiler 2 | 3 | ![compiler architecture](./images/compiler_architecture.png) 4 | 5 | ## Build 6 | 7 | ```shell 8 | make -j 9 | ``` 10 | 11 | ## Run 12 | 13 | **Usage: ./compiler [-S] [-l log_file] [-o output_file] [-O level] input_file** 14 | 15 | ```shell 16 | ./compiler -S -o testcase.s testcase.sy 17 | ``` 18 | 19 | ## Test 20 | 21 | **Usage: test_script.py [-h] [-l] [-a] [-r] [-v] [-L LINKED_LIBRARY_PATH] test_path** 22 | 23 | ```shell 24 | python3 ./utils/test_script.py "./functional_test/*.sy" -rv 25 | python3 ./utils/test_script.py "./performance_test/*.sy" -rav 26 | ``` -------------------------------------------------------------------------------- /include/Pass/ir_liveness_analysis.h: -------------------------------------------------------------------------------- 1 | #ifndef __IR_LIVENESS_ANALYSIS__ 2 | #define __IR_LIVENESS_ANALYSIS__ 3 | 4 | #include "../ir_struct.h" 5 | #include "pass_manager.h" 6 | // 7 | using namespace ir; 8 | // using RegId = int; 9 | 10 | std::pair, std::vector> GetDefUsePtr(IR *ir, bool consider = true); 11 | std::pair, std::vector> GetDefUse(IR *ir, bool consider = true); 12 | 13 | class IRLivenessAnalysis : public Analysis { 14 | public: 15 | IRLivenessAnalysis(Module **m) : Analysis(m) {} 16 | static void GetDefUse4Func(IRFunction *f, bool consider = true); 17 | // 对一个ir function做活跃变量分析 18 | static void Run4Func(IRFunction *f); 19 | // 对整个module做活跃变量分析 20 | void Run(); 21 | }; 22 | 23 | #endif -------------------------------------------------------------------------------- /include/general_struct.h: -------------------------------------------------------------------------------- 1 | #ifndef __GENERAL_STRUCT_H__ 2 | #define __GENERAL_STRUCT_H__ 3 | 4 | // define general moudle, function and basicblock 5 | #include 6 | #include 7 | #include 8 | 9 | // TODO: not use ir::Scope. 10 | #include "../include/ir.h" // global scope 11 | 12 | class Module { 13 | public: 14 | // module name. actually file name. 15 | std::string name_; 16 | // global declaration 17 | // ir::Scope& global_scope_; 18 | 19 | public: 20 | // Module(const std::string& name, ir::Scope& global_scope) : name_(name), global_scope_(global_scope) {} 21 | // Module(ir::Scope& global_scope) : name_("module"), global_scope_(global_scope) {} 22 | Module(const std::string& name) : name_(name) {} 23 | Module() : name_("module") {} 24 | virtual ~Module() {} 25 | virtual void EmitCode(std::ostream& out = std::cout) = 0; 26 | }; 27 | 28 | #endif -------------------------------------------------------------------------------- /makefile: -------------------------------------------------------------------------------- 1 | vpath %.cpp src 2 | vpath %.cpp src/Pass 3 | 4 | CC := clang++ 5 | CPPFLAGS := -std=c++17 -O2 6 | SOURCES := $(wildcard src/*.cpp src/Pass/*.cpp) 7 | OBJECTS := $(patsubst %.cpp,build/%.o,$(notdir $(SOURCES))) 8 | DEPENDS := $(patsubst %.o,%.d,$(OBJECTS)) 9 | TARGETS := compiler 10 | $(shell mkdir -p build) 11 | 12 | .PHONY:all 13 | all: $(TARGETS) 14 | @echo Build Successfully. 15 | 16 | $(TARGETS):$(OBJECTS) 17 | $(CC) $(CPPFLAGS) -lm $^ -o $@ 18 | 19 | src/parser.cpp: src/parser.y 20 | bison -o $@ -d $< 21 | 22 | src/scanner.cpp: src/scanner.l 23 | flex -o $@ $< 24 | 25 | build/%.o: %.cpp 26 | $(CC) $(CPPFLAGS) -c $< -o $@ 27 | 28 | -include $(DEPENDS) 29 | 30 | build/%.d: %.cpp 31 | @set -e; rm -f $@; \ 32 | $(CC) -MM $< > $@.$$$$; \ 33 | sed 's,\($*\)\.o[ :]*,build/\1.o $@ : ,g' < $@.$$$$ > $@; \ 34 | rm -f $@.$$$$ 35 | 36 | .PHONY:clean 37 | clean: 38 | rm -f build/* -------------------------------------------------------------------------------- /include/Pass/dead_code_eliminate.h: -------------------------------------------------------------------------------- 1 | #ifndef __DEAD_CODE_ELIMINATE_H__ 2 | #define __DEAD_CODE_ELIMINATE_H__ 3 | #include 4 | 5 | #include "./pass_manager.h" 6 | class SSAModule; 7 | class SSAFunction; 8 | class SSAInstruction; 9 | class Value; 10 | // DeadCodeEliminat: one of SSA-Pass 11 | class DeadCodeEliminate : public Transform { 12 | public: 13 | DeadCodeEliminate(Module** m) : Transform(m) {} 14 | void Run() override; 15 | static void RemoveFromNoSideEffectFuncs(SSAFunction* func, std::unordered_set& no_side_effect_funcs); 16 | static void FindNoSideEffectFunc(SSAModule* m, std::unordered_set& no_side_effect_funcs); 17 | 18 | private: 19 | std::unordered_set no_side_effect_funcs; 20 | 21 | bool IsSideEffect(Value* val); 22 | bool IsSideEffect(SSAInstruction* inst); 23 | void DeleteDeadFunc(SSAModule* m); 24 | void DeleteDeadInst(SSAFunction* func); 25 | void DeleteDeadStore(SSAFunction* func); 26 | // void FindNoSideEffectFunc(SSAModule* m); 27 | }; 28 | 29 | #endif -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 胡编乱造不队 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /include/Pass/allocate_register.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "../arm_struct.h" 10 | #include "pass_manager.h" 11 | class RegAlloc : public Transform { 12 | public: 13 | RegAlloc(Module **m) : Transform(m) {} 14 | 15 | using RegId = int; 16 | // 工作表 一个工作表是一些寄存器RegId的集合 17 | using WorkList = std::unordered_set; 18 | // using RegSet = ... 19 | // 邻接表 20 | using AdjList = std::unordered_map>; 21 | // using Reg2AdjList = ... 22 | // 冲突边的偶数对集 23 | using AdjSet = std::set>; 24 | // 结点的度数 25 | using Degree = std::unordered_map; 26 | 27 | // mov指令集 28 | using MovSet = std::unordered_set; 29 | // 一个reg相关的mov指令 30 | using MovList = std::unordered_map; 31 | // using Reg2MovList = ... 32 | WorkList ValidAdjacentSet(RegId reg, AdjList &adj_list, std::vector &select_stack, WorkList &coalesced_nodes); 33 | void AllocateRegister(ArmModule *m, std::ostream &outfile = std::clog); 34 | void Run(); 35 | }; 36 | -------------------------------------------------------------------------------- /include/Pass/dominant.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "../ir_struct.h" 4 | #include "pass_manager.h" 5 | using namespace ir; 6 | 7 | class ComputeDominance : public Analysis { 8 | public: 9 | using BB = IRBasicBlock; 10 | ComputeDominance(Module** m) : Analysis(m) {} 11 | void ResetTempInfo(IRFunction* f); 12 | void ComputeIDomInfo(IRFunction* f); 13 | void ComputeDomFrontier(BB* bb); 14 | void Run(); 15 | 16 | public: 17 | int N; 18 | std::vector vertex; // i->BB* 生成树编号为i的是哪个bb 19 | std::unordered_map dfnum; // BB*->treeid 第i个bb的深度优先生成树编号 20 | std::unordered_map parent; // BB*->BB* bb在生成树中的父bb 21 | std::unordered_map ancestor; // BB*->BB* 生成树森林 22 | std::unordered_map best; // best[a]=y represents a node y:(ancestor[a],a]:min(dfnum[semi[y]]) 23 | std::unordered_map semi; // BB*->BB* bb的半必经结点bb 24 | // std::unordered_map idom; // BB*->BB* bb的直接必经结点bb 25 | std::unordered_map samedom; // BB*->BB* 两个bb的idom一致 26 | std::unordered_map> bucket; // BB*->array(BB*) bb的直接必经结点bb 27 | void DFS(BB* p, BB* n); 28 | void Link(BB* p, BB* n); 29 | BB* AncestorWithLowestSemi(BB* v); 30 | }; -------------------------------------------------------------------------------- /src/Pass/simplify_cfg.cpp: -------------------------------------------------------------------------------- 1 | #include "../../include/Pass/simplify_cfg.h" 2 | 3 | #include 4 | 5 | #define ASSERT_ENABLE 6 | #include "../../include/myassert.h" 7 | 8 | // #define DEBUG_SIMPLIFY_CFG_PROCESS 9 | 10 | void SimplifyCFG::Run() { 11 | if (auto m = dynamic_cast(*(this->m_))) { 12 | // 13 | for (auto func : m->func_list_) { 14 | Run4IRFunc(func); 15 | } 16 | } else if (auto m = dynamic_cast(*(this->m_))) { 17 | // 18 | for (auto func : m->GetFuncList()) { 19 | Run4SSAFunc(func); 20 | } 21 | } else { 22 | MyAssert(0); 23 | } 24 | } 25 | 26 | // 删除没有前驱结点的基本块 27 | void SimplifyCFG::Run4IRFunc(IRFunction* func) { 28 | #ifdef DEBUG_SIMPLIFY_CFG_PROCESS 29 | std::cout << "========Before Simplyfy:========" << std::endl; 30 | func->EmitCode(std::cout); 31 | #endif 32 | std::unordered_set worklist; 33 | std::unordered_set wait; 34 | for (auto bb : func->bb_list_) { 35 | if (bb->pred_.size() == 0) worklist.insert(bb); 36 | } 37 | if (func->bb_list_.size() > 0) worklist.erase(func->bb_list_[0]); 38 | while (!worklist.empty()) { 39 | auto bb = *worklist.begin(); 40 | worklist.erase(bb); 41 | wait.insert(bb); 42 | for (auto succ : bb->succ_) { 43 | succ->pred_.erase(std::find(succ->pred_.begin(), succ->pred_.end(), bb)); 44 | if (succ->pred_.size() == 0) worklist.insert(succ); 45 | } 46 | } 47 | for (auto it = func->bb_list_.begin(); it != func->bb_list_.end();) { 48 | if (wait.count(*it)) 49 | it = func->bb_list_.erase(it); 50 | else 51 | ++it; 52 | } 53 | } 54 | 55 | void SimplifyCFG::Run4SSAFunc(SSAFunction* func) {} 56 | 57 | #undef ASSERT_ENABLE -------------------------------------------------------------------------------- /include/Pass/convert_ssa.h: -------------------------------------------------------------------------------- 1 | #ifndef __CONVERT_SSA_H__ 2 | #define __CONVERT_SSA_H__ 3 | 4 | #include 5 | #include 6 | 7 | #include "../ir_struct.h" 8 | #include "../ssa.h" 9 | #include "../ssa_struct.h" 10 | #include "pass_manager.h" 11 | using namespace ir; 12 | 13 | class ConvertSSA : public Transform { 14 | public: 15 | ConvertSSA(Module** m) : Transform(m) {} 16 | void Run() override; 17 | 18 | private: 19 | // string用来标识一个变量 form: varname#scope_id 20 | std::unordered_map count_; // 变量的ssa id计数 21 | std::unordered_map> stack_; // 变量的最近定值栈 22 | 23 | private: 24 | void Rename(IRBasicBlock* bb); 25 | void InsertPhiIR(IRFunction* f); 26 | void ProcessGlobalVariable(IRModule* irm, SSAModule* ssam); 27 | void AddBuiltInFunction(SSAModule* m); 28 | void ProcessResValue(const std::string& comp_name, Opn* opn, Value* val, SSABasicBlock* ssabb); 29 | void GenerateSSABasicBlocks(IRFunction* func, SSAFunction* ssafunc, 30 | std::unordered_map& bb_map); 31 | SSAModule* ConstructSSA(IRModule* module); 32 | void ConstructSSA4BB(IRBasicBlock* bb, SSAFunction* ssafunc, 33 | std::unordered_map& bb_map); 34 | void FillPhiInst(IRFunction* irfunc, SSAFunction* ssafunc, std::unordered_map& bb_map); 35 | Value* ResolveOpn2Value(Opn* opn, SSABasicBlock* ssabb); 36 | Value* FindValueFromOpn(Opn* opn, bool is_global); 37 | Value* FindValueFromCompName(const std::string& comp_name, bool is_global); 38 | // 变量的唯一性是由变量名+作用域+SSA编号一起决定的 把三个整合为一个string 同一变量映射到同一value 39 | // 全局变量不加多余字符 40 | std::unordered_map work_map; 41 | std::unordered_map glob_map; // 跨函数使用 全局量 包括函数 42 | }; 43 | 44 | #endif -------------------------------------------------------------------------------- /include/Pass/pass_manager.h: -------------------------------------------------------------------------------- 1 | #ifndef __PASS_MANAGER_H__ 2 | #define __PASS_MANAGER_H__ 3 | 4 | #include 5 | 6 | #define DEBUG_PASSES_PROCESS 7 | 8 | #include "../general_struct.h" 9 | 10 | class Pass { 11 | protected: 12 | Module** const m_; 13 | std::string name_; 14 | bool emit_ = false; 15 | 16 | public: 17 | Pass(Module** const m) : m_(m) {} 18 | 19 | virtual void Run() = 0; 20 | void SetName(std::string name) { name_ = name; } 21 | std::string GetName() { return name_; } 22 | void SetEmit(bool emit) { emit_ = emit; } 23 | bool IsEmit() { return emit_; } 24 | }; 25 | 26 | class Analysis : public Pass { 27 | public: 28 | Analysis(Module** m) : Pass(m) {} 29 | }; 30 | 31 | class Transform : public Pass { 32 | public: 33 | Transform(Module** m) : Pass(m) {} 34 | }; 35 | 36 | class PassManager { 37 | private: 38 | std::vector passes_; 39 | Module** const m_; 40 | 41 | public: 42 | PassManager(Module** const m) : m_(m) {} 43 | 44 | template 45 | void AddPass(bool emit = false) { 46 | try { 47 | Pass* pass = new PassTy(m_); 48 | pass->SetName(typeid(PassTy).name()); 49 | pass->SetEmit(emit); 50 | passes_.push_back(pass); 51 | } catch (...) { 52 | std::cerr << "ERROR class type:" << typeid(PassTy).name() << " be passed to AddPass();" << std::endl; 53 | exit(255); 54 | } 55 | } 56 | 57 | void Run(bool emit = false, std::ostream& out = std::cout) { 58 | int i = 1; 59 | for (auto pass : this->passes_) { 60 | #ifdef DEBUG_PASSES_PROCESS 61 | std::cout << ">>>>>>>>>>>> Start pass " << pass->GetName() << " <<<<<<<<<<<<" << std::endl; 62 | #endif 63 | pass->Run(); 64 | 65 | if (emit || pass->IsEmit()) { 66 | out << ">>>>>>>>>>>> After pass " << pass->GetName() << " <<<<<<<<<<<<" << std::endl; 67 | (*m_)->EmitCode(out); 68 | } 69 | } 70 | } 71 | }; 72 | 73 | #endif -------------------------------------------------------------------------------- /include/Pass/generate_arm_from_ssa.h: -------------------------------------------------------------------------------- 1 | #ifndef __GENERATE_ARM_FROM_SSA_H__ 2 | #define __GENERATE_ARM_FROM_SSA_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include "../arm.h" 9 | #include "../ssa.h" 10 | #include "../ssa_struct.h" 11 | #include "pass_manager.h" 12 | class SSAModule; 13 | class Value; 14 | class ArmBasicBlock; 15 | class ArmFunction; 16 | class ArmModule; 17 | using namespace arm; 18 | 19 | class GenerateArmFromSSA : public Transform { 20 | public: 21 | GenerateArmFromSSA(Module** m); 22 | // will change *m: SSAModule -> ArmModule 23 | void Run(); 24 | ArmModule* GenCode(SSAModule* module); 25 | 26 | protected: 27 | // these data is valid in one function. they should be reset at the beginning of every function. 28 | std::vector machine_regs; 29 | int virtual_reg_id = 16; 30 | std::unordered_map var_map; 31 | int stack_size = 0; 32 | std::unordered_set sp_arg_fixup; 33 | std::unordered_set sp_fixup; 34 | ArmBasicBlock* prologue = nullptr; 35 | ArmBasicBlock* epilogue = nullptr; 36 | 37 | protected: 38 | // used for generate arm code. 39 | Cond GetCondType(BranchInst::Cond cond, bool exchange = false); 40 | Reg* NewVirtualReg(); 41 | Reg* ResolveValue2Reg(ArmBasicBlock* armbb, Value* val); 42 | Reg* ResolveImm2Reg(ArmBasicBlock* armbb, int imm, bool record = false); 43 | Operand2* ResolveValue2Operand2(ArmBasicBlock* armbb, Value* val); 44 | Operand2* ResolveImm2Operand2(ArmBasicBlock* armbb, int imm, bool record = false); 45 | void GenImmLdrStrInst(ArmBasicBlock* armbb, LdrStr::OpKind opkind, Reg* rd, Reg* rn, int imm, bool record = false); 46 | bool ConvertMul2Shift(ArmBasicBlock* armbb, Reg* rd, Value* val, int imm); 47 | bool ConvertDiv2Shift(ArmBasicBlock* armbb, Reg* rd, Value* val, int imm); 48 | bool ConvertMod2And(ArmBasicBlock* armbb, Reg* rd, Value* val, int imm); 49 | void AddEpilogue(ArmBasicBlock* armbb); 50 | void AddPrologue(ArmFunction* func, FunctionValue* func_val); 51 | void AddEpilogue(ArmFunction* func); 52 | void ResetFuncData(); 53 | void GenerateArmBasicBlocks(ArmFunction* armfunc, SSAFunction* func, 54 | std::unordered_map& bb_map); 55 | }; 56 | 57 | #endif -------------------------------------------------------------------------------- /include/Pass/global_value_numbering.h: -------------------------------------------------------------------------------- 1 | #ifndef __GLOBAL_VALUE_NUMBERING_H__ 2 | #define __GLOBAL_VALUE_NUMBERING_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include "./pass_manager.h" 9 | class Value; 10 | class Module; 11 | class SSABasicBlock; 12 | class SSAFunction; 13 | class SSAInstruction; 14 | 15 | // Require: def-use info. dom tree info. no_side_effect_functions info. 16 | class GlobalValueNumbering : public Transform { 17 | public: 18 | GlobalValueNumbering(Module** m) : Transform(m) {} 19 | void Run() override; 20 | void Run4Func(SSAFunction* func); 21 | void CommenExpressionEliminate(SSABasicBlock* bb); 22 | 23 | // actually useless 24 | static void DFS(std::vector& po, std::unordered_set& vis, SSABasicBlock* bb, 25 | bool succ = true); 26 | static std::vector ComputeRPO(SSAFunction* func); 27 | 28 | private: 29 | // 一个Value唯一标识一个值(except ConstantInt) 所以Value*可作为number 不必真正地编号 30 | // 创建一个表达式类型 有op和oprands 如果op值相等 operands(value*)也都一致 就认为表达式一致 要考虑符合交换律的情况 31 | // 一个有定值能被使用[used]的语句被认为是一个表达式 32 | // 暂时不处理mov和phi表达式 load表达式待定(可以从store传播到load 也可以从load传播到load) 33 | // 所以其实目前只处理binary unary call表达式 34 | // 需要记录表达式到value*的映射 一旦发现冗余表达式 删除 替换值即可 35 | // 虽然值编号也可以删除值冗余 但由于已经在SimpleOptimizePass中实现 所以此实现只关注冗余表达式 36 | // 如果此Pass之前已经做过SimpleOptimizePass 因为此Pass不会生成新的mov语句 也不会传播常数 所以不会带来新的优化机会 37 | 38 | struct Expression { 39 | enum OpKind { 40 | // BinaryOperator 41 | ADD, 42 | SUB, 43 | MUL, 44 | DIV, 45 | MOD, 46 | // UnaryOperator 47 | NEG, 48 | NOT, 49 | // Others 50 | CALL, 51 | LOAD 52 | }; 53 | OpKind op_; 54 | std::vector operands_; 55 | SSAInstruction* inst_ = nullptr; 56 | // Expression() = default; 57 | // Expression(OpKind op) : op_(op) {} 58 | Expression(SSAInstruction* inst) : inst_(inst) {} 59 | ~Expression() = default; 60 | bool operator<(const Expression& exp) const; 61 | explicit operator std::string() const; 62 | }; 63 | 64 | std::unordered_set no_side_effect_funcs; 65 | std::unordered_set bbs_in_loop; 66 | std::vector> exp_val_vec; 67 | }; 68 | 69 | #endif -------------------------------------------------------------------------------- /include/arm_struct.h: -------------------------------------------------------------------------------- 1 | // Reference: https://developer.arm.com/documentation/100076/0200 2 | #ifndef __ARM_STRUCT_H__ 3 | #define __ARM_STRUCT_H__ 4 | #include 5 | #include 6 | 7 | #include "../include/arm.h" 8 | #include "../include/general_struct.h" 9 | #include "../include/ir.h" 10 | using namespace arm; 11 | class ArmBasicBlock; 12 | class ArmFunction; 13 | 14 | class ArmModule : public Module { 15 | public: 16 | // functions: ordered 17 | std::vector func_list_; 18 | ir::Scope& global_scope_; // FIXME: terrible design 19 | 20 | public: 21 | ArmModule(const std::string& name, ir::Scope& global_scope) : Module(name), global_scope_(global_scope) {} 22 | ArmModule(ir::Scope& global_scope) : global_scope_(global_scope) {} 23 | virtual ~ArmModule() {} 24 | void EmitCode(std::ostream& out = std::cout); 25 | }; 26 | 27 | class ArmFunction { 28 | public: 29 | std::string name_; 30 | int arg_num_; 31 | int stack_size_; 32 | int virtual_reg_max = 16; // rx x+1 33 | // basicblocks: ordered 34 | std::vector bb_list_; 35 | std::vector call_func_list_; 36 | std::unordered_set sp_arg_fixup_; // a ldr-pseudo inst 37 | std::unordered_set sp_fixup_; 38 | std::set used_callee_saved_regs; 39 | 40 | ArmFunction(const std::string& name, int arg_num, int stack_size) 41 | : name_(name), arg_num_(arg_num), stack_size_(stack_size) {} 42 | virtual ~ArmFunction() {} 43 | bool IsLeaf() { 44 | // return false; 45 | return call_func_list_.empty(); 46 | } 47 | void EmitCode(std::ostream& out = std::cout); 48 | }; 49 | 50 | class ArmBasicBlock { 51 | public: 52 | std::string label_; 53 | // only used for emitting 54 | ArmFunction* func_; 55 | 56 | // all instructions 57 | std::vector inst_list_; 58 | 59 | std::vector pred_; 60 | std::vector succ_; 61 | 62 | // used for reg alloc 63 | std::unordered_set def_; // 基本块的def 可看作是def中去掉liveuse 64 | std::unordered_set use_; // 基本块的use 可看作是活跃的use 65 | std::unordered_set livein_; 66 | std::unordered_set liveout_; 67 | 68 | ArmBasicBlock() {} 69 | ArmBasicBlock(std::string* label) : label_(*label) {} 70 | ArmBasicBlock(const std::string& label) : label_(label) {} 71 | virtual ~ArmBasicBlock() {} 72 | 73 | bool HasLabel() { return !label_.empty(); } 74 | void EmitCode(std::ostream& out = std::cout); 75 | int IndexInFunc(); 76 | }; 77 | 78 | #endif -------------------------------------------------------------------------------- /include/ir_struct.h: -------------------------------------------------------------------------------- 1 | #ifndef __IR_STRUCT_H__ 2 | #define __IR_STRUCT_H__ 3 | #include 4 | #include 5 | #include 6 | 7 | #include "./general_struct.h" 8 | #include "./ir.h" 9 | class IRBasicBlock; 10 | class IRFunction; 11 | 12 | class IRModule : public Module { 13 | public: 14 | // functions: ordered 15 | std::vector func_list_; 16 | ir::Scope& global_scope_; 17 | 18 | public: 19 | IRModule(const std::string& name, ir::Scope& global_scope) : Module(name), global_scope_(global_scope) {} 20 | IRModule(ir::Scope& global_scope) : global_scope_(global_scope) {} 21 | virtual ~IRModule(); 22 | void EmitCode(std::ostream& out = std::cout); 23 | }; 24 | 25 | class IRFunction { 26 | public: 27 | std::string name_; 28 | int arg_num_; 29 | // basicblocks: ordered 30 | std::vector bb_list_; 31 | std::vector call_func_list_; 32 | 33 | // 用于到达定值分析 34 | std::unordered_map> def_pre_var_; 35 | 36 | public: 37 | IRFunction(const std::string& name, int arg_num) : name_(name), arg_num_(arg_num) {} 38 | virtual ~IRFunction(); 39 | bool IsLeaf() { return call_func_list_.empty(); } 40 | void EmitCode(std::ostream& out = std::cout); 41 | }; 42 | 43 | class IRBasicBlock { 44 | public: 45 | // all irs 46 | std::vector ir_list_; 47 | // only used for emitting 48 | IRFunction* func_; 49 | 50 | std::vector pred_; 51 | std::vector succ_; 52 | 53 | std::unordered_set def_; 54 | std::unordered_set use_; 55 | std::unordered_set livein_; 56 | std::unordered_set liveout_; 57 | 58 | // 用于到达定值分析 59 | std::unordered_set gen_; 60 | std::unordered_set kill_; 61 | std::unordered_set reach_in_; 62 | std::unordered_set reach_out_; 63 | std::vector>> use_def_chains_; 64 | 65 | //记录下这个基本块的Label,在基本块中就不处理label语句了 66 | //形式:Label_#label or Label_#Func 67 | std::string bb_label_; 68 | 69 | // used for ssa 70 | IRBasicBlock* idom_ = nullptr; // 直接支配结点 即支配结点树中的父节点 71 | std::vector doms_; // 所直接支配的结点 即支配结点树中的子节点 72 | std::unordered_set df_; // 支配节点边界 73 | // std::unordered_set dom_by_; 74 | // int dom_level_; 75 | bool IsByDom(IRBasicBlock* bb); // 该bb是不是被这个参数bb所支配 或者说参数bb是不是该bb的必经结点 76 | 77 | IRBasicBlock() : func_(nullptr) {} 78 | IRBasicBlock(IRFunction* func) : func_(func) {} 79 | virtual ~IRBasicBlock(); 80 | void EmitCode(std::ostream& out = std::cout); 81 | void EmitBackupCode(std::ostream& out = std::cout); 82 | int IndexInFunc(); 83 | }; 84 | 85 | IRModule* ConstructModule(const std::string& module_name, std::vector& gIRList); 86 | 87 | #endif 88 | -------------------------------------------------------------------------------- /src/Pass/cond_br_to_insts.cpp: -------------------------------------------------------------------------------- 1 | #include "../../include/Pass/cond_br_to_insts.h" 2 | 3 | #include "../../include/arm.h" 4 | #include "../../include/arm_struct.h" 5 | 6 | #define ASSERT_ENABLE 7 | #include "../../include/myassert.h" 8 | 9 | // #define DEBUG_CONDBRTOINSTS_PROCESS 10 | // #define OUTPUT_CONDBRTOINSTS_EFFECT 11 | 12 | // NOTE: 限制最大指令数 不过因为mov32汇编宏的存在可能实际上不止4条 13 | static const int kMaxInstNumInBB = 4; // [HYPERPARAMETER] 14 | static int kCount = 0; 15 | 16 | void CondBrToInsts::Run() { 17 | kCount = 0; 18 | auto m = dynamic_cast(*(this->m_)); 19 | MyAssert(nullptr != m); 20 | for (auto func : m->func_list_) { 21 | Run4Func(func); 22 | } 23 | #ifdef OUTPUT_CONDBRTOINSTS_EFFECT 24 | std::cout << "CondBrToInsts Pass works on: " << kCount << " ArmBBs" << std::endl; 25 | #endif 26 | } 27 | 28 | void CondBrToInsts::Run4Func(ArmFunction* func) { 29 | #ifdef DEBUG_CONDBRTOINSTS_PROCESS 30 | std::cout << "Run CondBrToInsts In Func: " << func->name_ << std::endl; 31 | // if (func->name_ != "reduce") return; // debug for single function in single testcase 32 | #endif 33 | // 实际上也是简化arm的一种 但是simplify arm会给CondBrToInsts带来更多的优化机会 所以建议在simplify arm后跟CondBrToInsts 34 | // pass 35 | for (auto bb_it = func->bb_list_.begin(); bb_it != func->bb_list_.end(); ++bb_it) { 36 | auto bb = *bb_it; 37 | for (auto it = bb->inst_list_.begin(); it != bb->inst_list_.end();) { 38 | if (auto src_inst = dynamic_cast(*it)) { 39 | ArmBasicBlock *next_bb = nullptr, *next_next_bb = nullptr; 40 | if (bb_it + 1 != func->bb_list_.end()) next_bb = *(bb_it + 1); 41 | if (bb_it + 2 != func->bb_list_.end()) next_next_bb = *(bb_it + 2); 42 | // 有以下限制条件: 43 | // 1. 该指令必须是有条件的跳转指令 44 | // 2. 该基本块之后至少有两个基本块 并且该跳转指令跳转到之后的第二个基本块 45 | // 3. 该基本块之后的第一个基本块只能有一个前驱 即该基本块 46 | // 4. [HYPERPARAMETER] 下一个基本块内最多5条语句 47 | // 5. 下一个基本块内的指令如果有条件则不能带有跟该指令不同的条件 除最后一条语句外不能有函数调用 即bl(x)语句 48 | if (src_inst->cond_ != Cond::AL && nullptr != next_bb && nullptr != next_next_bb && 49 | src_inst->label_ == next_next_bb->label_ && next_bb->pred_.size() == 1 && next_bb->pred_.front() == bb && 50 | next_bb->inst_list_.size() <= kMaxInstNumInBB) { 51 | bool can_delete = true; 52 | auto cond = GetOppositeCond(src_inst->cond_); 53 | for (auto next_it = next_bb->inst_list_.begin(); next_it != next_bb->inst_list_.end(); ++next_it) { 54 | auto inst = *next_it; 55 | if (inst->cond_ != Cond::AL && inst->cond_ != cond) { 56 | can_delete = false; 57 | break; 58 | } 59 | if (next_it + 1 == next_bb->inst_list_.end()) break; 60 | if (auto src_inst = dynamic_cast(inst)) { 61 | if (src_inst->has_l_) { 62 | can_delete = false; 63 | break; 64 | } 65 | } 66 | } 67 | #ifdef DEBUG_CONDBRTOINSTS_PROCESS 68 | std::cout << "Check If to Cond BB:" << std::endl; 69 | next_bb->EmitCode(std::cout); 70 | std::cout << " Result: " << can_delete << " " << CondToString(cond) << std::endl; 71 | #endif 72 | if (can_delete) { 73 | ++kCount; 74 | for (auto inst : next_bb->inst_list_) { 75 | inst->cond_ = cond; 76 | } 77 | it = bb->inst_list_.erase(it); // pop_back 78 | continue; 79 | } 80 | } 81 | ++it; 82 | } 83 | // 其他直接跳过 84 | else { 85 | ++it; 86 | } 87 | } 88 | } 89 | } -------------------------------------------------------------------------------- /src/Pass/simplify_armcode.cpp: -------------------------------------------------------------------------------- 1 | #include "../../include/Pass/simplify_armcode.h" 2 | 3 | #include 4 | #define ASSERT_ENABLE 5 | #include "../../include/myassert.h" 6 | 7 | void SimplifyArm::Run() { 8 | auto m = dynamic_cast(*(this->m_)); 9 | MyAssert(nullptr != m); 10 | for (auto func : m->func_list_) { 11 | for (auto bb_it = func->bb_list_.begin(); bb_it != func->bb_list_.end(); ++bb_it) { 12 | // for (auto bb : func->bb_list_) { 13 | auto bb = *bb_it; 14 | for (auto it = bb->inst_list_.begin(); it != bb->inst_list_.end();) { 15 | // (*it)->EmitCode(std::cout); 16 | // Move语句 两种简化可能 17 | if (auto src_inst = dynamic_cast(*it)) { 18 | // 1 删除自己到自己的mov语句 19 | auto mov_op2 = src_inst->op2_; 20 | if (!mov_op2->is_imm_ && nullptr == mov_op2->shift_ && src_inst->rd_->reg_id_ == mov_op2->reg_->reg_id_) { 21 | // 删了之后检查下一条指令 22 | it = bb->inst_list_.erase(it); 23 | continue; 24 | } 25 | // 2 带偏移的 rd只作为一个无偏移的op2被使用的 所有使用和定值都在一个块内的 mov语句 可以和其所有使用合为一句 26 | // NOTE: 可以在一定程度上更利于寄存器分配 TODO: 需要确保使用中间没有新的定值 27 | // e.g. mov rd, rn LSL #2; add rd2, rn2, rd; -> add rd2, rn2, rn LSL #2 28 | // mov rd, rn LSL #2; ldr/str rd2, [rn2, rd]; -> ldr/str rd2, [rn2, rn LSL #2] 29 | auto mov_rd = src_inst->rd_; 30 | if (mov_op2->HasShift() && mov_rd->reg_id_ > 15 /*4?*/ && 31 | src_inst->cond_ == Cond::AL) { // NOTE HERE! 预着色的寄存器可能有其他作用 32 | bool can_delete = true; 33 | for (auto used_inst : mov_rd->GetUsedInsts()) { 34 | // 如果有一条语句不是把它用作一个没有偏移的op2 那么就不执行替换 35 | if (!used_inst->HasUsedAsOp2WithoutShift(mov_rd) || used_inst->parent_ != bb) { 36 | can_delete = false; 37 | break; 38 | } 39 | } 40 | if (can_delete) { 41 | // bb->EmitCode(std::cout); 42 | // 替换所有使用 43 | for (auto used_inst : mov_rd->GetUsedInsts()) { 44 | used_inst->ReplaceOp2With(mov_op2); 45 | } 46 | // 删除move语句 47 | // std::cout << "will delete:", src_inst->EmitCode(std::cout); 48 | it = bb->inst_list_.erase(it); 49 | continue; 50 | } 51 | } 52 | ++it; 53 | } 54 | // 3 代数化简 55 | else if (auto src_inst = dynamic_cast(*it)) { 56 | // 2.1 add 0 sub 0 转换成mov指令 但是不能在sp_fixup中的指令 57 | if (src_inst->opcode_ == BinaryInst::OpCode::ADD || src_inst->opcode_ == BinaryInst::OpCode::SUB) { 58 | if (src_inst->op2_->is_imm_ && 0 == src_inst->op2_->imm_num_ && !func->sp_fixup_.count(src_inst)) { 59 | it = bb->inst_list_.erase(it); 60 | it = bb->inst_list_.insert( 61 | it, new Move(false, Cond::AL, src_inst->rd_, new Operand2(src_inst->rn_), bb, false, false)); 62 | // new Move(src_inst->rd_, new Operand2(src_inst->rn_), src_inst); 63 | // it = std::find(bb->inst_list_.begin(), bb->inst_list_.end(), src_inst); 64 | // MyAssert(it != bb->inst_list_.end()); 65 | // it = bb->inst_list_.erase(it); 66 | // 继续检查新加的这条mov指令 67 | continue; 68 | } 69 | } 70 | ++it; 71 | } 72 | // 4 无条件跳转到下一个基本的跳转语句化简 73 | else if (auto src_inst = dynamic_cast(*it)) { 74 | if (src_inst->cond_ == Cond::AL && bb_it + 1 != func->bb_list_.end() && 75 | src_inst->label_ == (*(bb_it + 1))->label_) { 76 | it = bb->inst_list_.erase(it); 77 | continue; 78 | } 79 | ++it; 80 | } 81 | // 其他无法简化直接跳过 82 | else { 83 | ++it; 84 | } 85 | } 86 | // std::cout << "BB End" << std::endl; 87 | } 88 | // std::cout << "Function End" << std::endl; 89 | } 90 | } -------------------------------------------------------------------------------- /src/Pass/dead_function_eliminate.cpp: -------------------------------------------------------------------------------- 1 | #include "../../include/Pass/dead_function_eliminate.h" 2 | #define ASSERT_ENABLE 3 | #include 4 | 5 | #include "../../include/Pass/ir_liveness_analysis.h" 6 | #include "../../include/ast.h" 7 | #include "../../include/myassert.h" 8 | #include "../parser.hpp" 9 | 10 | // #define PRINT_DEAD_RET_FUNCTION 11 | // #define PRINT_FUNCTABLE 12 | // #define PRINT_DEBUG 13 | // #define PRINT_CALL_IR 14 | // #define PRINT_ALL_INT_FUNCTION 15 | 16 | void print_set(std::unordered_set func_set) { 17 | for (auto name : func_set) { 18 | std::cout << name << std::endl; 19 | } 20 | } 21 | 22 | bool isLiveness(IRBasicBlock *bb, ir::IR *end_ir, ir::Opn opn) { 23 | std::unordered_set keepalive = bb->liveout_; 24 | auto it = find(bb->ir_list_.begin(), bb->ir_list_.end(), end_ir); 25 | std::string opn_str = opn.name_ + "." + std::to_string(opn.scope_id_); 26 | 27 | for (auto iter = it + 1; iter != bb->ir_list_.end(); ++iter) { 28 | auto ir = *iter; 29 | 30 | auto [def, use] = GetDefUse(ir); 31 | 32 | if (find(def.begin(), def.end(), opn_str) != def.end()) { 33 | return false; 34 | } 35 | 36 | if (find(use.begin(), use.end(), opn_str) != use.end()) { 37 | return true; 38 | } 39 | } 40 | 41 | if (keepalive.find(opn_str) != keepalive.end()) { 42 | return true; 43 | } else { 44 | return false; 45 | } 46 | } 47 | 48 | void DeadFunctionEliminate::Run() { 49 | auto m = dynamic_cast(*m_); 50 | IRLivenessAnalysis livenessanalysis = IRLivenessAnalysis(m_); 51 | livenessanalysis.Run(); 52 | 53 | std::unordered_set dead_ret_function; 54 | 55 | for (auto func_item : ir::gFuncTable) { 56 | if (func_item.second.ret_type_ == INT && func_item.first != "main") { 57 | dead_ret_function.insert(func_item.first); 58 | } 59 | } 60 | 61 | // #ifdef PRINT_ALL_INT_FUNCTION 62 | // for(auto func_name : dead_ret_function){ 63 | // std::cout << func_name << std::endl; 64 | // } 65 | // #endif 66 | 67 | for (auto func : m->func_list_) { 68 | for (auto bb : func->bb_list_) { 69 | for (auto ir : bb->ir_list_) { 70 | if (ir->op_ == ir::IR::OpKind::CALL) { 71 | #ifdef PRINT_CALL_IR 72 | ir->PrintIR(); 73 | #endif 74 | auto func_table_item = ir::gFuncTable[ir->opn1_.name_]; 75 | if (func_table_item.ret_type_ == INT) { 76 | #ifdef PRINT_DEBUG 77 | if (!isLiveness(bb, ir, ir->res_)) { 78 | ir->PrintIR(); 79 | printf("/********* 不活跃,可以删除\n"); 80 | } else if (dead_ret_function.find(ir->opn1_.name_) != dead_ret_function.end()) { 81 | ir->PrintIR(); 82 | printf("/********* 活跃,不可以删除\n"); 83 | } 84 | #endif 85 | if (!isLiveness(bb, ir, ir->res_)) { 86 | } else { 87 | dead_ret_function.erase(ir->opn1_.name_); 88 | // std::cout << ir->opn1_.name_ << std::endl; 89 | } 90 | } 91 | } 92 | } // for ir 93 | } // for bb 94 | } // for func 95 | 96 | #ifdef PRINT_DEAD_RET_FUNCTION 97 | print_set(dead_ret_function); 98 | #endif 99 | 100 | for (auto func : m->func_list_) { 101 | if (dead_ret_function.find(func->name_) != dead_ret_function.end()) { 102 | ir::gFuncTable[func->name_].ret_type_ = VOID; 103 | for (auto bb : func->bb_list_) { 104 | for (int i = 0; i < bb->ir_list_.size(); ++i) { 105 | auto ir = bb->ir_list_[i]; 106 | 107 | if (ir->op_ == ir::IR::OpKind::RET) { 108 | bb->ir_list_[i] = new ir::IR(ir::IR::OpKind::RET); 109 | } 110 | } 111 | } 112 | } 113 | } 114 | 115 | #ifdef PRINT_FUNCTABLE 116 | ir::PrintFuncTable(); 117 | #endif 118 | } 119 | 120 | #undef MyAssert 121 | #ifdef ASSERT_ENABLE 122 | #undef ASSERT_ENABLE 123 | #endif -------------------------------------------------------------------------------- /src/parser.hpp: -------------------------------------------------------------------------------- 1 | /* A Bison parser, made by GNU Bison 3.3.2. */ 2 | 3 | /* Bison interface for Yacc-like parsers in C 4 | 5 | Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2019 Free Software Foundation, 6 | Inc. 7 | 8 | This program is free software: you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation, either version 3 of the License, or 11 | (at your option) any later version. 12 | 13 | This program is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with this program. If not, see . */ 20 | 21 | /* As a special exception, you may create a larger work that contains 22 | part or all of the Bison parser skeleton and distribute that work 23 | under terms of your choice, so long as that work isn't itself a 24 | parser generator using the skeleton or a modified version thereof 25 | as a parser skeleton. Alternatively, if you modify or redistribute 26 | the parser skeleton itself, you may (at your option) remove this 27 | special exception, which will cause the skeleton and the resulting 28 | Bison output files to be licensed under the GNU General Public 29 | License without this special exception. 30 | 31 | This special exception was added by the Free Software Foundation in 32 | version 2.2 of Bison. */ 33 | 34 | /* Undocumented macros, especially those whose name start with YY_, 35 | are private implementation details. Do not rely on them. */ 36 | 37 | #ifndef YY_YY_SRC_PARSER_HPP_INCLUDED 38 | # define YY_YY_SRC_PARSER_HPP_INCLUDED 39 | /* Debug traces. */ 40 | #ifndef YYDEBUG 41 | # define YYDEBUG 0 42 | #endif 43 | #if YYDEBUG 44 | extern int yydebug; 45 | #endif 46 | 47 | /* Token type. */ 48 | #ifndef YYTOKENTYPE 49 | # define YYTOKENTYPE 50 | enum yytokentype 51 | { 52 | ADD = 258, 53 | SUB = 259, 54 | NOT = 260, 55 | MUL = 261, 56 | DIV = 262, 57 | MOD = 263, 58 | LT = 264, 59 | LE = 265, 60 | GT = 266, 61 | GE = 267, 62 | EQ = 268, 63 | NE = 269, 64 | AND = 270, 65 | OR = 271, 66 | ASSIGN = 272, 67 | LPAREN = 273, 68 | RPAREN = 274, 69 | LBRACE = 275, 70 | RBRACE = 276, 71 | LSQUARE = 277, 72 | RSQUARE = 278, 73 | COMMA = 279, 74 | SEMI = 280, 75 | IF = 281, 76 | ELSE = 282, 77 | WHILE = 283, 78 | FOR = 284, 79 | BREAK = 285, 80 | CONTINUE = 286, 81 | RETURN = 287, 82 | CONST = 288, 83 | INT = 289, 84 | VOID = 290, 85 | IDENT = 291, 86 | NUMBER = 292 87 | }; 88 | #endif 89 | 90 | /* Value type. */ 91 | #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED 92 | 93 | union YYSTYPE 94 | { 95 | #line 30 "src/parser.y" /* yacc.c:1921 */ 96 | 97 | int token; 98 | std::string* string; 99 | ast::Root* root; 100 | ast::CompUnit* compile_unit; 101 | ast::DeclareStatement* declare; 102 | ast::Define* define; 103 | ast::Expression* expr; 104 | ast::ConditionExpression* cond_expr; 105 | ast::Number* number; 106 | ast::LeftValue* left_val; 107 | ast::Identifier* ident; 108 | ast::ArrayIdentifier* array_ident; 109 | ast::ArrayInitVal* array_initval; 110 | std::vector* array_initval_list; 111 | ast::Statement* statement; 112 | ast::Block* block; 113 | ast::FunctionDefine* funcdef; 114 | ast::FunctionCall* funccall; 115 | ast::FunctionFormalParameter* funcfparam; 116 | ast::FunctionFormalParameterList* funcfparams; 117 | ast::FunctionActualParameterList* funcaparams; 118 | 119 | #line 120 "src/parser.hpp" /* yacc.c:1921 */ 120 | }; 121 | 122 | typedef union YYSTYPE YYSTYPE; 123 | # define YYSTYPE_IS_TRIVIAL 1 124 | # define YYSTYPE_IS_DECLARED 1 125 | #endif 126 | 127 | 128 | extern YYSTYPE yylval; 129 | 130 | int yyparse (void); 131 | 132 | #endif /* !YY_YY_SRC_PARSER_HPP_INCLUDED */ 133 | -------------------------------------------------------------------------------- /src/scanner.l: -------------------------------------------------------------------------------- 1 | %option noyywrap nodefault yylineno 2 | %x COMMENT 3 | %x SINGLELINECOMMENT 4 | 5 | UCN (\\u[0-9a-fA-F]{4}|\\U[0-9a-fA-F]{8}) 6 | ILEN ([Uu](L|l|LL|ll)?|(L|l|LL|ll)[Uu]?) 7 | 8 | %{ 9 | 10 | #include "../include/ast.h" 11 | #include 12 | #include "parser.hpp" 13 | 14 | #define SAVE_TOKEN yylval.string = new std::string(yytext, yyleng) 15 | 16 | int cal8(char *s); 17 | int cal10(char *s); 18 | int cal16(char *s); 19 | 20 | %} 21 | 22 | %% 23 | 24 | "/*" {BEGIN(COMMENT);} 25 | "*/" {BEGIN(INITIAL);} 26 | ([^*]|\n)+|. 27 | <> {printf("Unterminated comment\n"); return 0;} 28 | "//" {BEGIN(SINGLELINECOMMENT);} 29 | .* 30 | \n {BEGIN(INITIAL);} 31 | <> {BEGIN(INITIAL);} 32 | 33 | 34 | int { yylval.token = INT; return INT; } 35 | void { yylval.token = VOID; return VOID; } 36 | 37 | const { yylval.token = CONST; return CONST; } 38 | 39 | break { yylval.token = BREAK; return BREAK; } 40 | continue { yylval.token = CONTINUE; return CONTINUE; } 41 | if { yylval.token = IF; return IF; } 42 | else { yylval.token = ELSE; return ELSE; } 43 | return { yylval.token = RETURN; return RETURN; } 44 | while { yylval.token = WHILE; return WHILE; } 45 | 46 | "starttime"[ \t\n]*"(" { yylval.string = new std::string("_sysy_starttime"); *yy_cp = yy_hold_char; yy_hold_char='(';yy_cp--; yyleng--; yy_c_buf_p--; *yy_c_buf_p='_';yy_c_buf_p--; *yy_c_buf_p='_'; yy_c_buf_p--; *yy_c_buf_p='E';yy_c_buf_p--; *yy_c_buf_p='N'; yy_c_buf_p--; *yy_c_buf_p='I';yy_c_buf_p--; *yy_c_buf_p='L'; yy_c_buf_p--; *yy_c_buf_p='_';yy_c_buf_p--; *yy_c_buf_p='_'; yy_c_buf_p--; return IDENT; } 47 | 48 | "stoptime"[ \t\n]*"(" { yylval.string = new std::string("_sysy_stoptime"); *yy_cp = yy_hold_char; yy_hold_char='(';yy_cp--; yyleng--; yy_c_buf_p--; *yy_c_buf_p='_';yy_c_buf_p--; *yy_c_buf_p='_'; yy_c_buf_p--; *yy_c_buf_p='E';yy_c_buf_p--; *yy_c_buf_p='N'; yy_c_buf_p--; *yy_c_buf_p='I';yy_c_buf_p--; *yy_c_buf_p='L'; yy_c_buf_p--; *yy_c_buf_p='_';yy_c_buf_p--; *yy_c_buf_p='_'; yy_c_buf_p--; return IDENT; } 49 | 50 | "__LINE__" { yylval.string = new std::string(std::to_string(yyget_lineno())); yylval.token = yyget_lineno(); return NUMBER; } 51 | "_SYSY_N" { yylval.string = new std::string(std::to_string(1024)); yylval.token = 1024; return NUMBER; } 52 | 53 | "+" { yylval.token = ADD; return ADD; } 54 | "-" { yylval.token = SUB; return SUB; } 55 | "*" { yylval.token = MUL; return MUL; } 56 | "/" { yylval.token = DIV; return DIV; } 57 | "%" { yylval.token = MOD; return MOD; } 58 | "=" { yylval.token = ASSIGN; return ASSIGN; } 59 | "==" { yylval.token = EQ; return EQ; } 60 | "!=" { yylval.token = NE; return NE; } 61 | "<" { yylval.token = LT; return LT; } 62 | ">" { yylval.token = GT; return GT; } 63 | "<=" { yylval.token = LE; return LE; } 64 | ">=" { yylval.token = GE; return GE; } 65 | "!" { yylval.token = NOT; return NOT; } 66 | "&&" { yylval.token = AND; return AND; } 67 | "||" { yylval.token = OR; return OR; } 68 | "[" { yylval.token = LSQUARE; return LSQUARE; } 69 | "]" { yylval.token = RSQUARE; return RSQUARE; } 70 | "(" { yylval.token = LPAREN; return LPAREN; } 71 | ")" { yylval.token = RPAREN; return RPAREN; } 72 | "{" { yylval.token = LBRACE; return LBRACE; } 73 | "}" { yylval.token = RBRACE; return RBRACE; } 74 | "," { yylval.token = COMMA; return COMMA; } 75 | ";" { yylval.token = SEMI; return SEMI; } 76 | 77 | 0[0-7]*{ILEN}? { yylval.token = cal8(yytext); return NUMBER; } 78 | [1-9][0-9]*{ILEN}? { yylval.token = cal10(yytext); return NUMBER; } 79 | 0[Xx][0-9a-fA-F]+{ILEN}? { yylval.token = cal16(yytext); return NUMBER; } 80 | 81 | ([_a-zA-Z]|{UCN})([_a-zA-Z0-9]|{UCN})* { SAVE_TOKEN; return IDENT; } 82 | 83 | [ \t\n\r]+ { /*忽略空白符*/ } 84 | . { printf("mystery chacators in %d lines: %d\n", yylineno, atoi(yytext));} 85 | 86 | %% 87 | 88 | int cal10(char *s) 89 | { 90 | int ans=0,len=strlen(s); 91 | for(int i=0;i 4 | 5 | #define ASSERT_ENABLE 6 | #include "../include/myassert.h" 7 | 8 | // #define GENIR_WITH_COMMENT 9 | 10 | IRModule::~IRModule() { 11 | for (auto func : func_list_) 12 | if (nullptr != func) delete func; 13 | } 14 | void IRModule::EmitCode(std::ostream& out) { 15 | out << "@ module: " << this->name_ << std::endl; 16 | // this->global_scope_.Print(out); 17 | for (auto func : this->func_list_) { 18 | func->EmitCode(out); 19 | out << std::endl; 20 | } 21 | } 22 | 23 | IRFunction::~IRFunction() { 24 | for (auto bb : bb_list_) 25 | if (nullptr != bb) delete bb; 26 | } 27 | void IRFunction::EmitCode(std::ostream& out) { 28 | out << "@ Function: " << this->name_ << std::endl; 29 | #ifdef GENIR_WITH_COMMENT 30 | out << "@ call_func: "; 31 | for (auto func : this->call_func_list_) { 32 | out << func->name_ << " "; 33 | } 34 | out << std::endl; 35 | #endif 36 | out << "@ Function Begin:" << std::endl; 37 | out << std::endl; 38 | for (auto bb : this->bb_list_) { 39 | bb->EmitCode(out); 40 | out << std::endl; 41 | } 42 | out << "@ Function End." << std::endl; 43 | } 44 | 45 | IRBasicBlock::~IRBasicBlock() { 46 | for (auto ir : ir_list_) 47 | if (nullptr != ir) delete ir; 48 | } 49 | int IRBasicBlock::IndexInFunc() { 50 | MyAssert(nullptr != this->func_); 51 | auto& bbs = this->func_->bb_list_; 52 | MyAssert(std::find(bbs.begin(), bbs.end(), this) != bbs.end()); 53 | return std::distance(bbs.begin(), std::find(bbs.begin(), bbs.end(), this)); 54 | } 55 | // 该bb是不是被这个参数bb所支配 或者说参数bb是不是该bb的必经结点 56 | bool IRBasicBlock::IsByDom(IRBasicBlock* bb) { 57 | auto n = this; 58 | while (nullptr != n) { 59 | if (bb == n) return true; 60 | n = n->idom_; 61 | } 62 | return false; 63 | } 64 | void IRBasicBlock::EmitCode(std::ostream& out) { 65 | #ifdef GENIR_WITH_COMMENT 66 | out << "@ BasicBlock: id:" << this->IndexInFunc() << std::endl; 67 | out << "@ pred bbs: "; 68 | for (auto pred : this->pred_) { 69 | out << pred->IndexInFunc() << " "; 70 | } 71 | // out << std::endl; 72 | out << "@ succ bbs: "; 73 | for (auto succ : this->succ_) { 74 | out << succ->IndexInFunc() << " "; 75 | } 76 | out << std::endl; 77 | out << "@ idom: " << (nullptr == this->idom_ ? "" : std::to_string(this->idom_->IndexInFunc()) + " "); 78 | // out << std::endl; 79 | out << "@ doms: "; 80 | for (auto dom : this->doms_) { 81 | out << dom->IndexInFunc() << " "; 82 | } 83 | // out << std::endl; 84 | out << "@ df: "; 85 | for (auto df : this->df_) { 86 | out << df->IndexInFunc() << " "; 87 | } 88 | out << std::endl; 89 | out << "@ def: "; 90 | for (auto def : this->def_) { 91 | out << def << " "; 92 | } 93 | out << "@ use: "; 94 | for (auto use : this->use_) { 95 | out << use << " "; 96 | } 97 | out << "@ livein: "; 98 | for (auto livein : this->livein_) { 99 | out << livein << " "; 100 | } 101 | out << "@ liveout: "; 102 | for (auto liveout : this->liveout_) { 103 | out << liveout << " "; 104 | } 105 | out << std::endl; 106 | #endif 107 | for (auto ir : this->ir_list_) { 108 | ir->PrintIR(out); 109 | } 110 | } 111 | 112 | void IRBasicBlock::EmitBackupCode(std::ostream& out) { 113 | #ifdef GENIR_WITH_COMMENT 114 | out << "@ BasicBlock: id:" << this->IndexInFunc() << std::endl; 115 | out << "@ pred bbs: "; 116 | for (auto pred : this->pred_) { 117 | out << pred->IndexInFunc() << " "; 118 | } 119 | // out << std::endl; 120 | out << "@ succ bbs: "; 121 | for (auto succ : this->succ_) { 122 | out << succ->IndexInFunc() << " "; 123 | } 124 | out << std::endl; 125 | out << "@ idom: " << (nullptr == this->idom_ ? "" : std::to_string(this->idom_->IndexInFunc()) + " "); 126 | // out << std::endl; 127 | out << "@ doms: "; 128 | for (auto dom : this->doms_) { 129 | out << dom->IndexInFunc() << " "; 130 | } 131 | // out << std::endl; 132 | out << "@ df: "; 133 | for (auto df : this->df_) { 134 | out << df->IndexInFunc() << " "; 135 | } 136 | out << std::endl; 137 | out << "@ def: "; 138 | for (auto def : this->def_) { 139 | out << def << " "; 140 | } 141 | out << "@ use: "; 142 | for (auto use : this->use_) { 143 | out << use << " "; 144 | } 145 | out << "@ livein: "; 146 | for (auto livein : this->livein_) { 147 | out << livein << " "; 148 | } 149 | out << "@ liveout: "; 150 | for (auto liveout : this->liveout_) { 151 | out << liveout << " "; 152 | } 153 | out << std::endl; 154 | #endif 155 | } 156 | 157 | #undef ASSERT_ENABLE // disable assert. this should be placed at the end of every file. 158 | -------------------------------------------------------------------------------- /src/construct_ir_module.cpp: -------------------------------------------------------------------------------- 1 | #include "../include/ir_struct.h" 2 | using namespace ir; 3 | 4 | IRModule* ConstructModule(const std::string& module_name, std::vector& gIRList) { 5 | // Construct BasicBlocks Functions and Module from gIRList 6 | 7 | // 基本块的首指令 8 | // 由于IR中使用了label 所有跳转语句都跳到某个label 9 | // 并且每个出现在四元式中的label都有跳转到该label的指令(不一定) 10 | // 所以首指令为每个label和每个跳转语句(call,ret,goto,jxx)的下一句 11 | // (即便不一定为真正的首指令也可以接受) 12 | 13 | // 先遍历一遍IR 把所有func和有label的BB创建完成 创建两个map 14 | std::unordered_map label2bb; 15 | std::unordered_map label2func; 16 | 17 | // add library function to label2func 18 | // not add them to module 19 | label2func.insert({"getint", new IRFunction("getint", 0)}); 20 | label2func.insert({"getch", new IRFunction("getch", 0)}); 21 | label2func.insert({"getarray", new IRFunction("getarray", 0)}); 22 | label2func.insert({"putint", new IRFunction("putint", 1)}); 23 | label2func.insert({"putch", new IRFunction("putch", 1)}); 24 | label2func.insert({"putarray", new IRFunction("putarray", 1)}); 25 | label2func.insert({"_sysy_starttime", new IRFunction("_sysy_starttime", 1)}); 26 | label2func.insert({"_sysy_stoptime", new IRFunction("_sysy_stoptime", 1)}); 27 | label2func.insert({"memset", new IRFunction("memset", 3)}); 28 | 29 | IRModule* module = new IRModule(module_name, gScopes[0]); 30 | 31 | // fill label2bb label2func. every bb has its first ir. every func has it first bb. module has all funs. 32 | for (int i = 0; i < gIRList.size(); ++i) { 33 | auto& ir = *gIRList[i]; 34 | if (ir.op_ == IR::OpKind::LABEL) { 35 | auto& label_name = ir.opn1_.name_; 36 | IRBasicBlock* bb = new IRBasicBlock(); 37 | bb->ir_list_.push_back(&ir); 38 | label2bb.insert({label_name, bb}); 39 | if (ir.opn1_.type_ == Opn::Type::Func) { // is a function begin 40 | auto& func_item = (*ir::gFuncTable.find(label_name)).second; 41 | IRFunction* func = new IRFunction(label_name, func_item.shape_list_.size()); 42 | func->bb_list_.push_back(bb); 43 | bb->func_ = func; 44 | label2func.insert({label_name, func}); 45 | module->func_list_.push_back(func); 46 | } 47 | } 48 | } 49 | 50 | bool is_leader = false; 51 | bool is_succ = true; 52 | IRFunction* curr_func = nullptr; 53 | IRBasicBlock* pre_bb = nullptr; 54 | IRBasicBlock* curr_bb = nullptr; 55 | // for every ir 56 | for (int i = 0; i < gIRList.size(); ++i) { 57 | auto& ir = *gIRList[i]; 58 | if (ir.op_ == IR::OpKind::LABEL) { 59 | is_leader = true; // 表示这条一定是首指令 60 | } 61 | if (is_leader) { // 一定已经或者将要把该ir放入到基本块中 62 | pre_bb = curr_bb; 63 | // 更新curr_bb curr_func 64 | if (ir.op_ == IR::OpKind::LABEL) { 65 | curr_bb = label2bb[ir.opn1_.name_]; 66 | if (ir.opn1_.type_ == Opn::Type::Func) { 67 | curr_func = label2func[ir.opn1_.name_]; 68 | is_leader = false; // 下一条语句非首指令 69 | continue; 70 | } 71 | } else { 72 | // new BB 73 | curr_bb = new IRBasicBlock(); 74 | curr_bb->ir_list_.push_back(&ir); 75 | } 76 | curr_func->bb_list_.push_back(curr_bb); 77 | curr_bb->func_ = curr_func; 78 | // 维护两个基本块之间的关系 79 | if (nullptr != pre_bb && is_succ) { 80 | pre_bb->succ_.push_back(curr_bb); 81 | curr_bb->pred_.push_back(pre_bb); 82 | } 83 | } else { 84 | curr_bb->ir_list_.push_back(&ir); 85 | } 86 | is_succ = true; 87 | // 维护当前基本块和跳转目标基本块之间的关系 维护is_leader 之后is_leader表示下一条ir是否为首指令 88 | switch (ir.op_) { 89 | case IR::OpKind::RET: 90 | is_leader = true; 91 | is_succ = false; 92 | break; 93 | case IR::OpKind::CALL: // NOTE: 此时不维护调用双方两个基本块之间的关系 TODO: call语句的下一条语句是首指令吗 94 | curr_func->call_func_list_.push_back(label2func[ir.opn1_.name_]); 95 | is_leader = false; 96 | break; 97 | case IR::OpKind::GOTO: { 98 | auto succ_bb = label2bb[ir.opn1_.name_]; 99 | curr_bb->succ_.push_back(succ_bb); 100 | succ_bb->pred_.push_back(curr_bb); 101 | is_leader = true; 102 | is_succ = false; 103 | break; 104 | } 105 | case IR::OpKind::JEQ: 106 | case IR::OpKind::JNE: 107 | case IR::OpKind::JLT: 108 | case IR::OpKind::JLE: 109 | case IR::OpKind::JGT: 110 | case IR::OpKind::JGE: { 111 | auto succ_bb = label2bb[ir.res_.name_]; 112 | curr_bb->succ_.push_back(succ_bb); 113 | succ_bb->pred_.push_back(curr_bb); 114 | is_leader = true; 115 | break; 116 | } 117 | default: 118 | is_leader = false; 119 | break; 120 | } 121 | } 122 | 123 | return module; 124 | } 125 | -------------------------------------------------------------------------------- /src/Pass/dominant.cpp: -------------------------------------------------------------------------------- 1 | #define ASSERT_ENABLE // enable assert for this file. place this at the top of a file. 2 | #include "../../include/Pass/dominant.h" 3 | 4 | #include "../../include/myassert.h" 5 | 6 | void ComputeDominance::DFS(BB* p, BB* n) { 7 | if (dfnum.find(n) != dfnum.end()) return; 8 | dfnum.insert({n, N}); 9 | vertex[N] = n; 10 | parent.insert({n, p}); // NOTE: parent[root]=nullptr 11 | ++N; 12 | for (auto succ : n->succ_) { 13 | DFS(n, succ); 14 | } 15 | } 16 | 17 | void ComputeDominance::Link(BB* p, BB* n) { 18 | ancestor.insert({n, p}); // 此时此刻的生成树森林状态为 dfnum比n大的都在 19 | best.insert({n, n}); 20 | } 21 | 22 | ComputeDominance::BB* ComputeDominance::AncestorWithLowestSemi(ComputeDominance::BB* v) { 23 | MyAssert(ancestor.find(v) != ancestor.end()); 24 | // 从a到v(included)这段已经算过了 存在best[v]里 compute min(dfnum[semi[y]]) 25 | auto a = ancestor[v]; 26 | MyAssert(nullptr != a); // 不会出现a为空的情况 根节点不会被链入到ancestor中 27 | if (ancestor.find(a) != ancestor.end()) { 28 | // 把当前生成树森林中v的最小的祖先到a(included)这段也算了 存在best[a]里 即b 29 | auto b = AncestorWithLowestSemi(a); 30 | // 更新 使更新后从ancestor[a]到v(included)这段都算过 存在best[v]里 31 | ancestor[v] = ancestor[a]; 32 | if (dfnum[semi[b]] < dfnum[semi[best[v]]]) { 33 | best[v] = b; 34 | } 35 | } 36 | return best[v]; 37 | } 38 | 39 | void ComputeDominance::ResetTempInfo(IRFunction* f) { 40 | // 初始化数据 9 41 | vertex.clear(); 42 | dfnum.clear(); 43 | parent.clear(); 44 | semi.clear(); 45 | // idom.clear(); 46 | bucket.clear(); 47 | ancestor.clear(); 48 | samedom.clear(); 49 | best.clear(); 50 | vertex.resize(f->bb_list_.size()); 51 | N = 0; 52 | } 53 | 54 | // Lengauer-Tarjan算法 ref: https://dl.acm.org/doi/10.1145/357062.357071 55 | // 填写f中每个bb的idom和doms信息 56 | void ComputeDominance::ComputeIDomInfo(IRFunction* f) { 57 | // 构造深度优先生成树 构造完后 保证vertex dfnum有效完整 parent[r]为空 58 | DFS(nullptr, f->bb_list_.front()); 59 | // std::cout << N << " " << f->bb_list_.size() << std::endl; 60 | // MyAssert(N == f->bb_list_.size()); 61 | 62 | // 基于半必经结点定理计算所有 非根节点 的半必经结点 63 | for (int i = N - 1; i > 0; --i) { 64 | BB* n = vertex[i]; 65 | auto p = parent[n]; 66 | MyAssert(nullptr != p); 67 | auto s = p; // s即n的半必经结点 68 | for (auto pred : n->pred_) { 69 | BB* s_temp = nullptr; 70 | if (dfnum[pred] <= dfnum[n]) { // 该前驱在生成树上是n的祖先 71 | s_temp = pred; // 则该结点是semi[n]的候选 72 | } else { // 该前驱在生成树上不是n的祖先 73 | s_temp = semi[AncestorWithLowestSemi(pred)]; 74 | // 则该前驱到其公共祖先的路径上的y:min(dfnum[semi[y]]) semi[y]成为semi[n]候选 75 | } 76 | if (dfnum[s_temp] < dfnum[s]) { // 半必经结点是dfnum最小的 77 | s = s_temp; 78 | } 79 | } 80 | semi.insert({n, s}); // semi和bucket和ancestor中不会有key为root的pair 81 | bucket[s].insert(n); 82 | Link(p, n); // 把p->n链入到生成树森林 83 | 84 | // 计算 以p为半必经结点的 结点v 的 必经结点 这里可以保证会把semi为root结点的结点的idom都计算到 85 | for (auto v : bucket[p]) { 86 | BB* y = AncestorWithLowestSemi(v); // min(dfnum[semi[y]]) y: from p to v(included). dfnum[v]>dfnum[y]. 87 | if (semi[y] == p /*semi[v]*/) { // 没有旁路p的分支 88 | // idom.insert({v, p}); 89 | v->idom_ = p; 90 | p->doms_.push_back(v); 91 | } else { 92 | samedom.insert({v, y}); // fill idom[samedom.key]=idom[samedom.value] later. 93 | } 94 | } 95 | bucket[p].clear(); 96 | } 97 | 98 | // fill idom[samedom.key]=idom[samedom.value] 99 | for (int i = 1; i < N; ++i) { 100 | auto n = vertex[i]; 101 | if (samedom.find(n) != samedom.end()) { 102 | auto idom = samedom[n]->idom_; 103 | // MyAssert(idom.find(samedom[n]) != idom.end()); 104 | // idom.insert({n, idom[samedom[n]]}); 105 | MyAssert(nullptr != idom); 106 | n->idom_ = idom; 107 | idom->doms_.push_back(n); 108 | } 109 | } 110 | } 111 | 112 | // 填写该结点和该结点的支配结点的df信息 113 | void ComputeDominance::ComputeDomFrontier(ComputeDominance::BB* bb) { 114 | for (auto succ : bb->succ_) { 115 | if (succ->idom_ != bb) { // bb一定不是该succ的必经结点 116 | bb->df_.insert(succ); 117 | } 118 | } 119 | for (auto child : bb->doms_) { 120 | ComputeDomFrontier(child); 121 | for (auto child_df : child->df_) { 122 | if (!child_df->IsByDom(bb) || child_df == bb) { // bb不是child_df的严格必经结点 123 | bb->df_.insert(child_df); 124 | } 125 | } 126 | } 127 | } 128 | 129 | void ComputeDominance::Run() { 130 | auto m = dynamic_cast(*(this->m_)); 131 | MyAssert(nullptr != m); 132 | for (auto func : m->func_list_) { 133 | ResetTempInfo(func); 134 | ComputeIDomInfo(func); // 填写func中每个bb的idom和doms信息 135 | ComputeDomFrontier(func->bb_list_.front()); // 填写func中每个bb的df信息 136 | } 137 | } 138 | 139 | #undef ASSERT_ENABLE // disable assert. this should be placed at the end of every file. -------------------------------------------------------------------------------- /src/Pass/constant_propagation.cpp: -------------------------------------------------------------------------------- 1 | #include "../../include/Pass/constant_propagation.h" 2 | 3 | #include "../../include/Pass/reach_define.h" 4 | #define ASSERT_ENABLE 5 | #include "../../include/myassert.h" 6 | // #define PRINT_DEBUG 7 | 8 | void ConstantPropagation::Run() { 9 | auto m = dynamic_cast(*m_); 10 | 11 | MyAssert(nullptr != m); 12 | 13 | bool changed = true; 14 | 15 | while (changed) { 16 | ReachDefine reachdefine = ReachDefine(m_); 17 | reachdefine.Run(); 18 | changed = false; 19 | for (auto func : m->func_list_) { 20 | for (auto bb : func->bb_list_) { 21 | for (int i = 0; i < bb->ir_list_.size(); ++i) { 22 | auto ir = bb->ir_list_[i]; 23 | auto map_this_ir = bb->use_def_chains_[i]; 24 | 25 | auto process_opn = [&bb, &ir, &map_this_ir, &changed](ir::Opn *opn, int opn_num) { 26 | if (opn->type_ == ir::Opn::Type::Var) { 27 | auto opn_set = map_this_ir[opn]; 28 | if (opn_set.size() == 1) { 29 | auto ir_opn = *opn_set.begin(); 30 | if (ir_opn->op_ == ir::IR::OpKind::ASSIGN && ir_opn->opn1_.type_ == ir::Opn::Type::Imm) { 31 | #ifdef PRINT_DEBUG 32 | std::cout << "将变量: " << opn->name_ + "_#" + std::to_string(opn->scope_id_) << " 变为常数" 33 | << ir_opn->opn1_.imm_num_ << std::endl; 34 | #endif 35 | changed = true; 36 | if (opn_num == 1) { 37 | ir->opn1_ = ir_opn->opn1_; 38 | } else if (opn_num == 2) { 39 | ir->opn2_ = ir_opn->opn1_; 40 | } 41 | } 42 | } 43 | } 44 | }; 45 | 46 | process_opn(&(ir->opn1_), 1); 47 | 48 | process_opn(&(ir->opn2_), 2); 49 | 50 | if (ir::IR::OpKind::ADD == ir->op_) { 51 | if (ir->opn1_.type_ == ir::Opn::Type::Imm && ir->opn2_.type_ == ir::Opn::Type::Imm) { 52 | int res = ir->opn1_.imm_num_ + ir->opn2_.imm_num_; 53 | ir::Opn opn1 = ir::Opn(ir::Opn::Type::Imm, res); 54 | ir::Opn res_opn = ir->res_; 55 | bb->ir_list_[i] = new ir::IR(ir::IR::OpKind::ASSIGN, opn1, res_opn); 56 | changed = true; 57 | // if(changed) printf("/*******\n"); 58 | } 59 | } else if (ir::IR::OpKind::SUB == ir->op_) { 60 | if (ir->opn1_.type_ == ir::Opn::Type::Imm && ir->opn2_.type_ == ir::Opn::Type::Imm) { 61 | int res = ir->opn1_.imm_num_ - ir->opn2_.imm_num_; 62 | ir::Opn opn1 = ir::Opn(ir::Opn::Type::Imm, res); 63 | ir::Opn res_opn = ir->res_; 64 | bb->ir_list_[i] = new ir::IR(ir::IR::OpKind::ASSIGN, opn1, res_opn); 65 | changed = true; 66 | } 67 | } else if (ir::IR::OpKind::MUL == ir->op_) { 68 | if (ir->opn1_.type_ == ir::Opn::Type::Imm && ir->opn2_.type_ == ir::Opn::Type::Imm) { 69 | int res = ir->opn1_.imm_num_ * ir->opn2_.imm_num_; 70 | ir::Opn opn1 = ir::Opn(ir::Opn::Type::Imm, res); 71 | ir::Opn res_opn = ir->res_; 72 | bb->ir_list_[i] = new ir::IR(ir::IR::OpKind::ASSIGN, opn1, res_opn); 73 | changed = true; 74 | } 75 | } else if (ir::IR::OpKind::DIV == ir->op_) { 76 | if (ir->opn1_.type_ == ir::Opn::Type::Imm && ir->opn2_.type_ == ir::Opn::Type::Imm) { 77 | // 没有加对除0的限制,应该没有必要 78 | int res = ir->opn1_.imm_num_ / ir->opn2_.imm_num_; 79 | ir::Opn opn1 = ir::Opn(ir::Opn::Type::Imm, res); 80 | ir::Opn res_opn = ir->res_; 81 | bb->ir_list_[i] = new ir::IR(ir::IR::OpKind::ASSIGN, opn1, res_opn); 82 | changed = true; 83 | } 84 | } else if (ir::IR::OpKind::MOD == ir->op_) { 85 | if (ir->opn1_.type_ == ir::Opn::Type::Imm && ir->opn2_.type_ == ir::Opn::Type::Imm) { 86 | int res = ir->opn1_.imm_num_ % ir->opn2_.imm_num_; 87 | ir::Opn opn1 = ir::Opn(ir::Opn::Type::Imm, res); 88 | ir::Opn res_opn = ir->res_; 89 | bb->ir_list_[i] = new ir::IR(ir::IR::OpKind::ASSIGN, opn1, res_opn); 90 | changed = true; 91 | } 92 | } else if (ir::IR::OpKind::NOT == ir->op_) { 93 | if (ir->opn1_.type_ == ir::Opn::Type::Imm) { 94 | int res = !ir->opn1_.imm_num_; 95 | ir::Opn opn1 = ir::Opn(ir::Opn::Type::Imm, res); 96 | ir::Opn res_opn = ir->res_; 97 | bb->ir_list_[i] = new ir::IR(ir::IR::OpKind::ASSIGN, opn1, res_opn); 98 | changed = true; 99 | } 100 | } else if (ir::IR::OpKind::NEG == ir->op_) { 101 | if (ir->opn1_.type_ == ir::Opn::Type::Imm) { 102 | int res = -ir->opn1_.imm_num_; 103 | ir::Opn opn1 = ir::Opn(ir::Opn::Type::Imm, res); 104 | ir::Opn res_opn = ir->res_; 105 | bb->ir_list_[i] = new ir::IR(ir::IR::OpKind::ASSIGN, opn1, res_opn); 106 | changed = true; 107 | } 108 | } 109 | } 110 | } 111 | } 112 | // if(changed) printf("/*******\n"); 113 | } 114 | } 115 | 116 | #undef MyAssert 117 | #ifdef ASSERT_ENABLE 118 | #undef ASSERT_ENABLE 119 | #endif -------------------------------------------------------------------------------- /utils/test_script.py: -------------------------------------------------------------------------------- 1 | from glob import glob 2 | import subprocess 3 | from os import path 4 | import re 5 | import os 6 | import time 7 | import argparse 8 | 9 | if __name__ == '__main__': 10 | parser = argparse.ArgumentParser(description='Automaticly test. Output in ./build.', formatter_class=argparse.RawDescriptionHelpFormatter) 11 | parser.add_argument("test_path", type=str, help="the path of the test cases with glob style.") 12 | parser.add_argument("-l", "--log", help="generate log file for every test case.", action="store_true") 13 | parser.add_argument("-a", "--all", help="output the results for all test cases.", action="store_true") 14 | parser.add_argument("-r", "--run", help="link the asm files and run the executable files.", action="store_true") 15 | parser.add_argument("-v", "--verbose", help="print compile time (and exec time when the option [-r] is specified) for only incorrect test cases (or every test case when the option [-a] is specified).", action="store_true") 16 | parser.add_argument("-L", "--linked_library_path", type=str, help="the path of the linked library.", default="lib") 17 | args = parser.parse_args() 18 | 19 | CompilerPath = './compiler' 20 | CompileArgs = '-S -O1' 21 | GccArgs = f'-march=armv7-a -L {args.linked_library_path} -lsysy -static' 22 | OutputFolder = './output' 23 | 24 | if not path.exists(OutputFolder): 25 | os.system(f"mkdir {OutputFolder}") 26 | else: 27 | os.system(f"rm -rf {OutputFolder}/*") 28 | 29 | make_res = subprocess.call("make -j8", shell=True) 30 | if make_res != 0: 31 | print("build compiler failed.") 32 | exit() 33 | print() 34 | 35 | files = glob(args.test_path, recursive=True) 36 | files.sort() 37 | bug_num = len(files) 38 | all_time_seconds=0 39 | all_time_useconds=0 40 | 41 | for file in files: 42 | filepath_noext, _ = path.splitext(file) 43 | _, filename = path.split(file) 44 | filename_noext, _=path.splitext(filename) 45 | asm_file = OutputFolder+"/"+filename_noext+".s" 46 | exec_file = OutputFolder+"/"+filename_noext+".o" 47 | log_file = OutputFolder+"/"+filename_noext+".log" 48 | stdin_file = filepath_noext+".in" 49 | stdout_file = filepath_noext+".out" 50 | 51 | print("{:10s}:{:35s}{:10s}:{}".format("Processing",filename,"full path",file)) 52 | 53 | # Compile 54 | time_start = time.time() 55 | if subprocess.call(f"{CompilerPath} {file} -o {asm_file} {CompileArgs} -l {log_file}".split()) != 0: 56 | print("compile failed.") 57 | continue 58 | time_end = time.time() 59 | compile_time = (time_end - time_start) # s 60 | if args.all and args.verbose: 61 | print("{:10s}:{:.6f}s".format("compile tm",compile_time)) 62 | 63 | if not args.run: 64 | bug_num-=1 65 | print("{:10s}:{}".format("status","OK!")) 66 | else: 67 | # GCC Link 68 | link_cmd = f"gcc -o {exec_file} {asm_file} {GccArgs}" 69 | # time_start = time.time() 70 | if subprocess.call(link_cmd.split()) != 0: 71 | print("link failed.") 72 | continue 73 | time_end = time.time() 74 | # link_time = (time_end - time_start) # s 75 | # print("{:10s}:{:.6f}s".format("link time",link_time)) 76 | 77 | # Exec 78 | exec_cmd = f"{exec_file}" 79 | if path.exists(stdin_file): 80 | stdin = open(stdin_file, 'r') 81 | else: 82 | stdin = None 83 | time_start = time.time() 84 | subp = subprocess.Popen(exec_cmd.split(), bufsize=0, stdin=stdin, stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding='utf-8') 85 | exec_out, exec_err = subp.communicate() 86 | ret_code = subp.returncode 87 | time_end = time.time() 88 | run_time = (time_end - time_start) # s 89 | exec_time = (re.search("[0-9]+H.*us",exec_err)) 90 | 91 | if args.all and args.verbose: 92 | print("{:10s}:{:.6f}s".format("run time",run_time)) 93 | if exec_time != None: 94 | exec_time=exec_time.group() 95 | detail_time =re.search(("-([0-9]+)S-([0-9]+)us"), exec_time) 96 | if detail_time != None: 97 | all_time_seconds+=int(detail_time.group(1)) 98 | all_time_useconds+=int(detail_time.group(2)) 99 | print("{:10s}:{}".format("exec time",exec_time)) 100 | 101 | # Exec output 102 | exec_out_list = exec_out.split() 103 | exec_out_list.append(str(ret_code)) 104 | # print(exec_out_list) 105 | 106 | # Status 107 | status="" 108 | if not path.exists(stdout_file): 109 | print("{:10s}:{}".format("exec out", exec_out_list)) 110 | print("output file not exist.") 111 | continue 112 | else: 113 | # Standard output 114 | with open(stdout_file, "r") as f: 115 | stdout_list = f.read().split() 116 | # print(stdout_list) 117 | if exec_out_list == stdout_list: 118 | status="OK!" 119 | bug_num-=1 120 | else: 121 | status="ERROR!!!" 122 | print("{:10s}:{}".format("std out", stdout_list)) 123 | print("{:10s}:{}".format("exec out", exec_out_list)) 124 | # print("{:10s}:{}".format("exec err", exec_err)) 125 | if (args.all and args.verbose) or status!="OK!": 126 | print("{:10s}:{}".format("status",status)) 127 | print() 128 | 129 | print("{:10s}:{:3d}".format("bug num",bug_num)) 130 | if args.all and args.verbose and args.run: 131 | all_time_seconds+=all_time_useconds//1000000 132 | all_time_useconds%=1000000 133 | print("{:10s}:{:3d}s {:6d}us".format("all time",all_time_seconds, all_time_useconds)) 134 | print("finish.") 135 | -------------------------------------------------------------------------------- /src/evaluate.cpp: -------------------------------------------------------------------------------- 1 | #include "../include/ast.h" 2 | #include "../include/ir.h" 3 | 4 | #define ASSERT_ENABLE 5 | #include "../include/myassert.h" 6 | 7 | namespace ast { 8 | 9 | // 若计算成功 返回一个立即数形式的ir::Opn 10 | void Number::Evaluate(ir::ContextInfo& ctx, std::vector& gIRList) { 11 | ctx.opn_ = ir::Opn(ir::Opn::Type::Imm, value_); 12 | } 13 | 14 | void Identifier::Evaluate(ir::ContextInfo& ctx, std::vector& gIRList) { 15 | ir::SymbolTableItem* s = nullptr; 16 | int scope_id = ir::FindSymbol(ctx.scope_id_, name_, s); 17 | if (!s) { 18 | ir::SemanticError(line_no_, name_ + ": undefined variable"); 19 | } 20 | 21 | if (!s->is_const_) { 22 | ir::SemanticError(line_no_, name_ + ": not const type"); 23 | } 24 | 25 | ctx.opn_ = ir::Opn(ir::Opn::Type::Imm, s->initval_[0]); 26 | } 27 | void ArrayIdentifier::Evaluate(ir::ContextInfo& ctx, std::vector& gIRList) { 28 | ir::SymbolTableItem* s = nullptr; 29 | int scope_id = ir::FindSymbol(ctx.scope_id_, name_.name_, s); 30 | if (!s) { 31 | ir::SemanticError(line_no_, name_.name_ + ": undefined variable"); 32 | } 33 | if (shape_list_.size() != s->shape_.size()) { 34 | ir::SemanticError(line_no_, name_.name_ + ": the dimension of array is not correct"); 35 | } 36 | 37 | int index, t; 38 | 39 | for (int i = 0; i < shape_list_.size(); ++i) { 40 | shape_list_[i]->Evaluate(ctx, gIRList); 41 | t = ctx.opn_.imm_num_; 42 | if (i == shape_list_.size() - 1) { 43 | index += t * 4; 44 | } else { 45 | index += t * s->width_[i + 1]; 46 | } 47 | } 48 | 49 | ctx.opn_ = ir::Opn(ir::Opn::Type::Imm, s->initval_[index / 4]); 50 | } 51 | void ConditionExpression::Evaluate(ir::ContextInfo& ctx, std::vector& gIRList) { 52 | ir::RuntimeError("条件表达式不实现Evaluate函数"); 53 | } 54 | void BinaryExpression::Evaluate(ir::ContextInfo& ctx, std::vector& gIRList) { 55 | int l, r, res; 56 | 57 | // lhs_.Evaluate(ctx, gIRList); 58 | lhs_->Evaluate(ctx, gIRList); 59 | l = ctx.opn_.imm_num_; 60 | rhs_.Evaluate(ctx, gIRList); 61 | r = ctx.opn_.imm_num_; 62 | 63 | switch (op_) { 64 | case 258: 65 | res = l + r; 66 | break; 67 | case 259: 68 | res = l - r; 69 | break; 70 | case 261: 71 | res = l * r; 72 | break; 73 | case 262: 74 | res = l / r; 75 | break; 76 | case 263: 77 | res = l % r; 78 | break; 79 | case 270: 80 | res = l && r; 81 | break; 82 | case 271: 83 | res = l || r; 84 | break; 85 | default: 86 | // printf("mystery operator code: %d", op_); 87 | MyAssert(0); 88 | break; 89 | } 90 | 91 | ctx.opn_ = ir::Opn(ir::Opn::Type::Imm, res); 92 | } 93 | void UnaryExpression::Evaluate(ir::ContextInfo& ctx, std::vector& gIRList) { 94 | int r, res; 95 | 96 | rhs_.Evaluate(ctx, gIRList); 97 | r = ctx.opn_.imm_num_; 98 | 99 | switch (op_) { 100 | case 258: 101 | res = r; 102 | break; 103 | case 259: 104 | res = -r; 105 | break; 106 | case 260: 107 | res = !r; 108 | break; 109 | default: 110 | // printf("mystery operator code: %d", op_); 111 | MyAssert(0); 112 | break; 113 | } 114 | 115 | ctx.opn_ = ir::Opn(ir::Opn::Type::Imm, res); 116 | } 117 | void FunctionCall::Evaluate(ir::ContextInfo& ctx, 118 | std::vector& gIRList) { // 不应该试图对Function调用evaluate函数 119 | MyAssert(0); 120 | } 121 | 122 | // 填写initval信息 123 | void ArrayInitVal::Evaluate(ir::ContextInfo& ctx, std::vector& gIRList) { 124 | auto& symbol_item = (*ir::gScopes[ctx.scope_id_].symbol_table_.find(ctx.array_name_)).second; 125 | if (this->is_exp_) { 126 | this->value_->Evaluate(ctx, gIRList); 127 | if (ctx.opn_.type_ != ir::Opn::Type::Imm) { // 语义错误 非常量表达式 128 | ir::SemanticError(this->line_no_, ctx.opn_.name_ + "非常量表达式"); 129 | } 130 | 131 | symbol_item.initval_.push_back(ctx.opn_.imm_num_); 132 | ++ctx.array_offset_; 133 | } else { 134 | // 此时该结点表示一对大括号 {} 135 | int& offset = ctx.array_offset_; 136 | int& brace_num = ctx.brace_num_; 137 | 138 | // 根据offset和brace_num算出finaloffset 139 | int temp_level = 0; 140 | const auto& dim_total_num = ctx.dim_total_num_; 141 | for (int i = 0; i < dim_total_num.size(); ++i) { 142 | if (offset % dim_total_num[i] == 0) { 143 | temp_level = i; 144 | break; 145 | } 146 | } 147 | temp_level += brace_num; 148 | 149 | if (temp_level > dim_total_num.size()) { // 语义错误 大括号过多 150 | ir::SemanticError(this->line_no_, "多余大括号"); 151 | } else { 152 | int final_offset = offset + dim_total_num[temp_level - 1]; 153 | if (!this->initval_list_.empty()) { 154 | ++brace_num; 155 | this->initval_list_[0]->Evaluate(ctx, gIRList); 156 | 157 | for (int i = 1; i < this->initval_list_.size(); ++i) { 158 | brace_num = 1; 159 | this->initval_list_[i]->Evaluate(ctx, gIRList); 160 | } 161 | } 162 | // 补0补到finaloffset 163 | // while (offset < final_offset) { 164 | // symbol_item.initval_.push_back(0); 165 | // ++offset; 166 | // } 167 | // 语义检查 168 | if (offset > final_offset) { // 语义错误 初始值设定项值太多 169 | ir::SemanticError(this->line_no_, "初始值设定项值太多"); 170 | } 171 | symbol_item.initval_.insert(symbol_item.initval_.end(), final_offset - offset, 0); 172 | offset = final_offset; 173 | } 174 | } 175 | } 176 | } // namespace ast 177 | 178 | #undef MyAssert 179 | #ifdef ASSERT_ENABLE 180 | #undef ASSERT_ENABLE 181 | #endif -------------------------------------------------------------------------------- /src/arm_struct.cpp: -------------------------------------------------------------------------------- 1 | #include "../include/arm_struct.h" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #define ASSERT_ENABLE 8 | #include "../include/myassert.h" 9 | 10 | // #define GENARM_WITH_COMMENT 11 | 12 | #define GET_BB_LABEL_STR(bb_ptr) (bb_ptr->HasLabel() ? bb_ptr->label_ : ("UnamedBB")) 13 | #define GET_BB_IDENT(bb_ptr) (GET_BB_LABEL_STR(bb_ptr) + ":" + std::to_string(bb_ptr->IndexInFunc())) 14 | 15 | void ArmModule::EmitCode(std::ostream& out) { 16 | out << ".arch armv7ve" << std::endl; 17 | out << ".arm" << std::endl; 18 | out << "@ module: " << this->name_ << std::endl; 19 | out << std::endl; 20 | out << R"( 21 | .macro mov32, cond, reg, val 22 | movw\cond \reg, #:lower16:\val 23 | movt\cond \reg, #:upper16:\val 24 | .endm 25 | )" << std::endl; 26 | out << std::endl; 27 | // .data 28 | auto& global_symtab = this->global_scope_.symbol_table_; 29 | if (!global_symtab.empty()) { 30 | // out << ".section .data" << std::endl; 31 | // out << ".align 4" << std::endl; 32 | // out << std::endl; 33 | // TODO: order? 34 | for (auto& symbol : global_symtab) { 35 | if (symbol.first == "_sysy_idx" || symbol.first == "_sysy_l1" || symbol.first == "_sysy_l2" || 36 | symbol.first == "_sysy_h" || symbol.first == "_sysy_m" || symbol.first == "_sysy_s" || 37 | symbol.first == "_sysy_us") 38 | continue; 39 | // NOTE: 数组常量不能删 可能会用到变量下标 40 | if (symbol.second.is_const_ && !symbol.second.is_array_) continue; 41 | bool in_bss = true; 42 | int last_not0 = 0; 43 | for (int i = 0; i < symbol.second.initval_.size(); ++i) { 44 | if (0 != symbol.second.initval_[i]) { 45 | in_bss = false; 46 | last_not0 = i; 47 | } 48 | } 49 | if (in_bss) { 50 | // .comm symbol length align 51 | out << ".comm " << symbol.first << ", " << (symbol.second.width_.empty() ? 4 : symbol.second.width_[0]) << ", 4" 52 | << std::endl; 53 | } else { 54 | out << "\t.global " << symbol.first << std::endl; 55 | out << "\t.data" << std::endl; 56 | out << "\t.align 4" << std::endl; 57 | out << "\t.type " << symbol.first << ", %object" << std::endl; 58 | out << symbol.first << ":" << std::endl; 59 | int cnt0 = 0; 60 | for (int i = 0; i < symbol.second.initval_.size(); ++i) { 61 | if (0 == symbol.second.initval_[i]) { 62 | ++cnt0; 63 | } else { 64 | if (0 != cnt0) { 65 | out << "\t.space " << cnt0 * 4 << std::endl; 66 | cnt0 = 0; 67 | } 68 | out << "\t.word " << symbol.second.initval_[i] << std::endl; 69 | } 70 | if (i == last_not0) break; 71 | } 72 | int space = (symbol.second.initval_.size() - last_not0 - 1) * 4; 73 | if (0 != space) { 74 | out << "\t.space " << space << std::endl; 75 | } 76 | } 77 | out << std::endl; 78 | } 79 | } 80 | 81 | // .text 82 | out << ".section .text" << std::endl; 83 | out << std::endl; 84 | // out << ".syntax unified" << std::endl << std::endl; 85 | for (auto func : this->func_list_) { 86 | func->EmitCode(out); 87 | out << std::endl; 88 | } 89 | } 90 | 91 | void ArmFunction::EmitCode(std::ostream& out) { 92 | out << ".global " << this->name_ << std::endl; 93 | out << "\t.type " << this->name_ << ", %function" << std::endl; 94 | out << this->name_ << ":" << std::endl; 95 | #ifdef GENARM_WITH_COMMENT 96 | out << "@ call_func: "; 97 | for (auto func : this->call_func_list_) { 98 | out << func->name_ << " "; 99 | } 100 | out << std::endl; 101 | out << "@ arg_num: " << this->arg_num_ << " "; // << std::endl; 102 | out << "@ stack_size: " << this->stack_size_ << " "; // << std::endl; 103 | out << "@ virtual_reg_max: " << this->virtual_reg_max << " "; 104 | out << std::endl; 105 | #endif 106 | out << "@ Function Begin:" << std::endl; 107 | for (auto bb : bb_list_) { 108 | bb->EmitCode(out); 109 | out << std::endl; 110 | } 111 | out << "@ Function End." << std::endl; 112 | } 113 | void ArmBasicBlock::EmitCode(std::ostream& out) { 114 | if (this->HasLabel()) { 115 | out << this->label_ << ":" << std::endl; 116 | } 117 | #ifdef GENARM_WITH_COMMENT 118 | out << " @ ID: " << this->IndexInFunc() << std::endl; 119 | out << " @ BasicBlock Begin:" << std::endl; 120 | out << " @ pred: "; 121 | for (auto pred : this->pred_) { 122 | out << GET_BB_IDENT(pred) << " "; 123 | } 124 | // out << std::endl; 125 | out << " @ succ: "; 126 | for (auto succ : this->succ_) { 127 | out << GET_BB_IDENT(succ) << " "; 128 | } 129 | // out << std::endl; 130 | out << " @ use: "; 131 | for (auto use : this->use_) { 132 | out << "r" << use << " "; 133 | } 134 | // out << std::endl; 135 | out << " @ def: "; 136 | for (auto def : this->def_) { 137 | out << "r" << def << " "; 138 | } 139 | // out << std::endl; 140 | out << " @ livein: "; 141 | for (auto livein : this->livein_) { 142 | out << "r" << livein << " "; 143 | } 144 | // out << std::endl; 145 | out << " @ liveout: "; 146 | for (auto liveout : this->liveout_) { 147 | out << "r" << liveout << " "; 148 | } 149 | out << std::endl; 150 | #endif 151 | for (auto inst : this->inst_list_) { 152 | inst->EmitCode(out); 153 | } 154 | #ifdef GENARM_WITH_COMMENT 155 | out << " @ BasicBlock End." << std::endl; 156 | #endif 157 | } 158 | int ArmBasicBlock::IndexInFunc() { 159 | MyAssert(nullptr != this->func_); 160 | auto& bbs = this->func_->bb_list_; 161 | MyAssert(std::find(bbs.begin(), bbs.end(), this) != bbs.end()); 162 | return std::distance(bbs.begin(), std::find(bbs.begin(), bbs.end(), this)); 163 | } 164 | 165 | #undef ASSERT_ENABLE // disable assert. this should be placed at the end of every file. -------------------------------------------------------------------------------- /include/ssa_struct.h: -------------------------------------------------------------------------------- 1 | #ifndef __SSA_STRUCT_H__ 2 | #define __SSA_STRUCT_H__ 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "./general_struct.h" 10 | class Value; 11 | class SSAInstruction; 12 | class GlobalVariable; 13 | class SSABasicBlock; 14 | class SSAFunction; 15 | class FunctionValue; 16 | class BasicBlockValue; 17 | class Scope; 18 | 19 | class SSAModule : public Module { 20 | private: 21 | std::list glob_var_list_; 22 | std::list func_list_; 23 | std::list builtin_func_list_; 24 | 25 | public: 26 | ir::Scope& global_scope_; // FIXME: terrible design 27 | // a symbol table 28 | std::string name_; 29 | SSAModule(ir::Scope& global_scope, std::string name = "") : Module(name), name_(name), global_scope_(global_scope){}; 30 | // SSAModule(std::string name = "") : Module(name), name_(name){}; 31 | ~SSAModule(); 32 | 33 | std::list& GetFuncList() { return func_list_; } 34 | std::list& GetBuiltinFuncList() { return builtin_func_list_; } 35 | const std::list& GetFuncList() const { return func_list_; } 36 | const std::list& GetBuiltinFuncList() const { return builtin_func_list_; } 37 | const std::list& GetGlobVarList() const { return glob_var_list_; } 38 | void AddFunction(SSAFunction* f); 39 | void AddBuiltinFunction(SSAFunction* f); 40 | void RemoveFunction(SSAFunction* f); 41 | void AddGlobalVariable(GlobalVariable* g); 42 | void RemoveGlobalVariable(GlobalVariable* g); 43 | 44 | void EmitCode(std::ostream& out = std::cout); 45 | }; 46 | 47 | class SSAFunction { 48 | private: 49 | std::string func_name_; 50 | SSAModule* m_ = nullptr; 51 | FunctionValue* value_ = nullptr; 52 | 53 | // need to maintain these data structure in every ssa-transform pass 54 | std::list bb_list_; 55 | std::unordered_set call_func_list_; // may can be unorderd 56 | std::unordered_set used_glob_var_list_; // may can be unorderd 57 | 58 | public: 59 | SSAFunction(const std::string& func_name, SSAModule* m) : func_name_(func_name), m_(m) { m->AddFunction(this); } 60 | SSAFunction(const std::string& func_name) : func_name_(func_name) {} // builtin function will not be added to module 61 | ~SSAFunction(); 62 | 63 | bool IsCalled(); 64 | void Remove(); 65 | 66 | const std::string& GetFuncName() const { return func_name_; } 67 | 68 | void BindValue(FunctionValue* value) { value_ = value; } 69 | FunctionValue* GetValue() const { return value_; } 70 | 71 | const std::list& GetBBList() const { return bb_list_; } 72 | 73 | void AddCallFunc(SSAFunction* func); 74 | void AddCallFunc(FunctionValue* func_val); 75 | void MaintainCallFunc(); 76 | std::unordered_set& GetCallFuncList() { return call_func_list_; } 77 | 78 | void AddUsedGlobVar(GlobalVariable* glob_var); 79 | std::unordered_set& GetUsedGlobVarList() { return used_glob_var_list_; } 80 | 81 | void SetModule(SSAModule* m) { m_ = m; } 82 | SSAModule* GetModule() const { return m_; } 83 | 84 | std::list& GetBasicBlocks() { return bb_list_; } 85 | void AddBasicBlock(SSABasicBlock* bb); 86 | void RemoveBasicBlock(SSABasicBlock* bb); 87 | 88 | void EmitCode(std::ostream& out = std::cout); 89 | }; 90 | 91 | class SSABasicBlock { 92 | private: 93 | SSAFunction* func_; 94 | std::string label_; 95 | 96 | std::list inst_list_; 97 | std::list pred_; 98 | std::list succ_; 99 | 100 | SSABasicBlock* idom_ = nullptr; 101 | std::vector doms_; 102 | std::unordered_set df_; 103 | 104 | BasicBlockValue* value_ = nullptr; 105 | 106 | public: 107 | void BindValue(BasicBlockValue* value) { value_ = value; } 108 | BasicBlockValue* GetValue() const { return value_; } 109 | 110 | SSABasicBlock(const std::string& label, SSAFunction* func) : label_(label), func_(func) { func->AddBasicBlock(this); } 111 | SSABasicBlock(SSAFunction* func) : func_(func) { func->AddBasicBlock(this); } 112 | ~SSABasicBlock(); 113 | 114 | const std::list& GetInstList() const { return inst_list_; } 115 | std::list& GetInstList() { return inst_list_; } 116 | 117 | std::string& GetLabel() { return label_; } 118 | void SetLabel(const std::string& label) { label_ = label; } 119 | 120 | void SetFunction(SSAFunction* func) { func_ = func; } 121 | SSAFunction* GetFunction() const { return func_; } 122 | 123 | SSABasicBlock* GetNextBB(); 124 | 125 | std::list& GetInstructions() { return inst_list_; } 126 | void AddInstruction(SSAInstruction* inst); 127 | void AddInstruction(SSAInstruction* inst, SSAInstruction* insert_before); 128 | void RemoveInstruction(SSAInstruction* inst); 129 | std::list& GetPredBB() { return pred_; } 130 | std::list& GetSuccBB() { return succ_; } 131 | void AddPredBB(SSABasicBlock* pred) { pred_.push_back(pred); } 132 | void AddSuccBB(SSABasicBlock* succ) { succ_.push_back(succ); } 133 | void RemovePredBB(SSABasicBlock* pred) { 134 | pred_.remove(pred); // only remove relationship 135 | } 136 | void RemoveSuccBB(SSABasicBlock* succ) { 137 | succ_.remove(succ); // only remove relationship 138 | } 139 | 140 | void SetIDom(SSABasicBlock* idom) { idom_ = idom; } 141 | SSABasicBlock* GetIDom() const { return idom_; } 142 | 143 | void AddDomBB(SSABasicBlock* dom) { doms_.push_back(dom); } 144 | std::vector& GetDoms() { return doms_; } 145 | std::unordered_set GetDomSet(); 146 | 147 | void AddDF(SSABasicBlock* df) { df_.insert(df); } 148 | std::unordered_set& GetDF() { return df_; } 149 | 150 | void EmitCode(std::ostream& out = std::cout); 151 | }; 152 | 153 | #endif -------------------------------------------------------------------------------- /include/ir.h: -------------------------------------------------------------------------------- 1 | #ifndef __IR__H_ 2 | #define __IR__H_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | namespace ir { 11 | 12 | class SymbolTableItem { 13 | public: 14 | bool is_array_; 15 | bool is_const_; 16 | std::vector shape_; // int为空 否则表示数组的各个维度 17 | std::vector width_; // int为空 否则表示数组的各个维度的宽度 18 | std::vector initval_; // 用于记录全局变量的初始值 int为一个值 // 数组则转换为一维数组存储 19 | SymbolTableItem(bool is_array, bool is_const) : is_array_(is_array), is_const_(is_const) { 20 | shape_.reserve(5), width_.reserve(5), initval_.reserve(5); 21 | } 22 | SymbolTableItem() { shape_.reserve(5), width_.reserve(5), initval_.reserve(5); } 23 | void Print(std::ostream &outfile = std::clog); 24 | }; 25 | 26 | class FuncTableItem { 27 | public: 28 | int ret_type_; // VOID INT 29 | int scope_id_; 30 | std::vector> shape_list_; 31 | // TODO: 如何处理库函数的size 32 | FuncTableItem(int ret_type, int scope_id) : ret_type_(ret_type), scope_id_(scope_id) {} 33 | FuncTableItem() {} 34 | void Print(std::ostream &outfile = std::clog); 35 | }; 36 | 37 | //每个作用域一个符号表 38 | class Scope { 39 | public: 40 | std::unordered_map symbol_table_; 41 | int scope_id_; // 作用域id 42 | int parent_scope_id_; // 父作用域id 43 | // 往符号表中插入中间变量时不改变该值 44 | bool IsFunc() { return parent_scope_id_ == 0 ? true : false; } 45 | // Scope() {} 46 | Scope(int scope_id, int parent_scope_id) : scope_id_(scope_id), parent_scope_id_(parent_scope_id) {} 47 | void Print(std::ostream &outfile = std::clog); 48 | bool IsSubScope(int scope_id); 49 | }; 50 | 51 | int FindSymbol(int scope_id, std::string name, SymbolTableItem *&res_symbol_item); 52 | 53 | using Scopes = std::vector; 54 | using FuncTable = std::unordered_map; 55 | 56 | class Opn { 57 | public: 58 | enum class Type { 59 | Var, 60 | Imm, 61 | Label, 62 | Func, 63 | Null, // 无操作数 64 | Array, 65 | }; 66 | Type type_; 67 | int imm_num_; // 立即数 68 | std::string name_; // 69 | int scope_id_ = -1; // 标识所在作用域 -1表示全局作用域的父作用域 70 | Opn *offset_ = nullptr; 71 | int ssa_id_ = -1; 72 | // Opn Type: IMM 73 | Opn(Type type, int imm_num) : type_(type), imm_num_(imm_num), name_("#" + std::to_string(imm_num)) {} 74 | // Opn Type: Var 75 | Opn(Type type, std::string name, int scope_id) : type_(type), name_(name), scope_id_(scope_id) {} 76 | // Opn Type: Label or Func 77 | Opn(Type type, std::string name) : type_(type), name_(name) {} 78 | // Opn Type: Null 79 | Opn(Type type) : type_(type), name_("-") {} 80 | // Opn Type: Array 81 | Opn(Type type, std::string name, int scope_id, Opn *offset) 82 | : type_(type), name_(name), scope_id_(scope_id), offset_(offset) {} 83 | Opn() : type_(Type::Null), name_("-") {} 84 | Opn(const Opn &opn); 85 | Opn &operator=(const Opn &opn); 86 | Opn(Opn &&opn); 87 | Opn &operator=(Opn &&opn); 88 | std::string GetCompName(); 89 | explicit operator std::string(); 90 | }; 91 | 92 | class IR { 93 | public: 94 | enum class OpKind { 95 | ADD, // (+,) 96 | SUB, // (-,) 97 | MUL, // (*,) 98 | DIV, // (/,) 99 | MOD, // (%,) 100 | NOT, // (!,) 101 | NEG, // (-,)负 102 | LABEL, // (label,) 103 | PARAM, // (param,) 104 | CALL, // (call, func, num, res|-) 105 | RET, // (ret,) or (ret,opn1,) 106 | GOTO, // (goto,label) 107 | ASSIGN, // (assign, opn1,-,res) 108 | JEQ, // == 109 | JNE, // != 110 | JLT, // < 111 | JLE, // <= 112 | JGT, // > 113 | JGE, // >= 114 | VOID, // useless 115 | ASSIGN_OFFSET, // =[] NOTE: 这个操作符不可省略 不可合并到assign中 因为数组地址和数组取值是不一样的 116 | PHI, // 117 | ALLOCA, // 118 | DECLARE, // 函数参数声明 119 | }; 120 | OpKind op_; 121 | Opn opn1_, opn2_, res_; 122 | std::vector phi_args_; 123 | IR(OpKind op, Opn res, int size) : op_(op), res_(res) { phi_args_.resize(size); } 124 | IR(OpKind op, Opn opn1, Opn opn2, Opn res) : op_(op), opn1_(opn1), opn2_(opn2), res_(res) {} 125 | IR(OpKind op, Opn opn1, Opn res) : op_(op), opn1_(opn1), res_(res) {} 126 | IR(OpKind op, Opn opn1) : op_(op), opn1_(opn1) {} 127 | IR(OpKind op) : op_(op) {} 128 | IR() = default; 129 | IR(const IR &ir) = default; 130 | IR &operator=(const IR &ir) = default; 131 | IR(IR &&ir); 132 | IR &operator=(IR &&ir); 133 | void PrintIR(std::ostream &outfile = std::clog); 134 | }; 135 | 136 | class ContextInfo { 137 | public: 138 | int scope_id_; 139 | Opn opn_; 140 | bool has_return; 141 | // Used for type check 142 | std::vector shape_; 143 | // Used for ArrayInitVal 144 | std::string array_name_; 145 | int array_offset_; 146 | int brace_num_; // 当前位置(array_offset_)有几个大括号 147 | std::vector dim_total_num_; // a[2][3][4] -> 24,12,4,1 148 | // Used for Break Continue 149 | std::stack break_label_; 150 | std::stack continue_label_; 151 | // Used for Condition Expresson 152 | std::stack true_label_; 153 | std::stack false_label_; 154 | // Used for Return Statement 155 | std::string current_func_name_; 156 | // Used for Block 157 | bool has_aug_scope; //函数形参也要加在block的作用域里 158 | // Used for ArrayIdentifier []= 159 | bool is_assigned_ = false; 160 | 161 | ContextInfo() : scope_id_(0) { shape_.reserve(5); } 162 | }; 163 | 164 | extern Scopes gScopes; 165 | extern FuncTable gFuncTable; 166 | // extern std::vector gIRList; 167 | extern const int kIntWidth; 168 | 169 | std::string NewTemp(); 170 | std::string NewLabel(); 171 | 172 | IR::OpKind GetOpKind(int op, bool reverse); 173 | 174 | void PrintScopes(std::ostream &outfile = std::clog); 175 | void PrintFuncTable(std::ostream &outfile = std::clog); 176 | void SemanticError(int line_no, const std::string &&error_msg); 177 | void RuntimeError(const std::string &&error_msg); 178 | 179 | } // namespace ir 180 | #endif 181 | -------------------------------------------------------------------------------- /src/ssa_struct.cpp: -------------------------------------------------------------------------------- 1 | #include "../include/ssa_struct.h" 2 | 3 | #include 4 | #include 5 | 6 | #include "../include/ssa.h" 7 | #define ASSERT_ENABLE 8 | #include "../include/myassert.h" 9 | 10 | void SSAModule::AddFunction(SSAFunction* f) { 11 | func_list_.push_back(f); 12 | f->SetModule(this); 13 | } 14 | void SSAModule::AddBuiltinFunction(SSAFunction* f) { 15 | builtin_func_list_.push_back(f); 16 | // f->SetModule(this); 17 | } 18 | void SSAModule::RemoveFunction(SSAFunction* f) { 19 | func_list_.remove(f); 20 | // TODO: manage memory 21 | }; 22 | void SSAModule::AddGlobalVariable(GlobalVariable* g) { 23 | glob_var_list_.push_back(g); 24 | // g->set... 25 | } 26 | void SSAModule::RemoveGlobalVariable(GlobalVariable* g) { 27 | glob_var_list_.remove(g); 28 | // TODO: manage memory 29 | } 30 | SSAModule::~SSAModule() { 31 | // glob_var_list_.clear(); 32 | for (auto func : func_list_) delete func; 33 | // func_list_.clear(); 34 | } 35 | 36 | void SSAFunction::AddBasicBlock(SSABasicBlock* bb) { 37 | bb_list_.push_back(bb); 38 | bb->SetFunction(this); 39 | } 40 | void SSAFunction::RemoveBasicBlock(SSABasicBlock* bb) { 41 | bb_list_.remove(bb); 42 | // TODO: manage memory 43 | for (auto pred : bb->GetPredBB()) { 44 | pred->RemoveSuccBB(bb); 45 | } 46 | for (auto succ : bb->GetSuccBB()) { 47 | succ->RemovePredBB(bb); 48 | } 49 | } 50 | void SSAFunction::MaintainCallFunc() { 51 | call_func_list_.clear(); 52 | for (auto bb : bb_list_) { 53 | for (auto inst : bb->GetInstList()) { 54 | if (auto call_inst = dynamic_cast(inst)) { 55 | auto func_val = dynamic_cast(call_inst->GetOperand(0)); 56 | MyAssert(nullptr != func_val); 57 | call_func_list_.insert(func_val->GetFunction()); 58 | } 59 | } 60 | } 61 | } 62 | void SSAFunction::AddCallFunc(SSAFunction* func) { 63 | MyAssert(nullptr != func); 64 | call_func_list_.insert(func); 65 | } 66 | void SSAFunction::AddCallFunc(FunctionValue* func_val) { 67 | MyAssert(nullptr != func_val->GetFunction()); 68 | call_func_list_.insert(func_val->GetFunction()); 69 | } 70 | void SSAFunction::AddUsedGlobVar(GlobalVariable* glob_var) { 71 | MyAssert(nullptr != glob_var); 72 | used_glob_var_list_.insert(glob_var); 73 | } 74 | bool SSAFunction::IsCalled() { return value_->IsUsed(); } 75 | void SSAFunction::Remove() { 76 | // 要删除该函数 必须保证module内没有调用该函数的语句 77 | MyAssert(GetValue()->GetUses().empty()); 78 | // 首先需要移除该函数在其调用的函数和使用的全局量中的使用信息 然后从module中删除它 79 | // 该函数调用的函数对应的value的uselist中存着该函数对应的value 是在生成call语句的时候加进去的 80 | for (auto call_func : call_func_list_) { 81 | std::cout << call_func->GetFuncName() << std::endl; 82 | call_func->GetValue()->KillUse(this); 83 | } 84 | // 该函数使用的globalvariable的uselist中存着该函数中所有对该globvar的load和store 85 | for (auto glob_var : used_glob_var_list_) { 86 | glob_var->KillUse(this); 87 | } 88 | m_->RemoveFunction(this); 89 | // FIXME: 在该函数中清空信息还是放到析构函数中清空??? 90 | } 91 | SSAFunction::~SSAFunction() { 92 | // m_ = nullptr; 93 | // delete value_; // FIXME: should be delete and remove all use 94 | for (auto bb : bb_list_) delete bb; 95 | // bb_list_.clear(); 96 | // call_func_list_.clear(); 97 | // used_glob_var_list_.clear(); 98 | } 99 | 100 | SSABasicBlock* SSABasicBlock::GetNextBB() { 101 | // maybe return nullptr 102 | auto& bb_list = func_->GetBBList(); 103 | auto it = ++std::find(bb_list.begin(), bb_list.end(), this); 104 | if (it == bb_list.end()) 105 | return nullptr; 106 | else 107 | return *it; 108 | } 109 | void SSABasicBlock::AddInstruction(SSAInstruction* inst) { 110 | inst_list_.push_back(inst); 111 | inst->SetParent(this); 112 | } 113 | void SSABasicBlock::AddInstruction(SSAInstruction* inst, SSAInstruction* insert_before) { 114 | // NOTE HERE 115 | inst_list_.insert(std::find(inst_list_.begin(), inst_list_.end(), insert_before), inst); 116 | inst->SetParent(this); 117 | } 118 | void SSABasicBlock::RemoveInstruction(SSAInstruction* inst) { 119 | inst_list_.remove(inst); 120 | // TODO: manage memory and use used. 121 | } 122 | std::unordered_set SSABasicBlock::GetDomSet() { 123 | // all ancestor in dom tree, including itself 124 | std::unordered_set res; 125 | auto temp = this; 126 | while (nullptr != temp) { 127 | res.insert(temp); 128 | temp = temp->GetIDom(); 129 | } 130 | return res; 131 | } 132 | 133 | SSABasicBlock::~SSABasicBlock() { 134 | // func_ = nullptr; 135 | // delete value_; // FIXME: should be delete and remove all use 136 | for (auto inst : inst_list_) { 137 | delete inst; 138 | // std::cout << "ok\n"; 139 | } 140 | // inst_list_.clear(); 141 | // pred_.clear(); 142 | // succ_.clear(); 143 | } 144 | 145 | void SSAModule::EmitCode(std::ostream& out) { 146 | for (auto glob : glob_var_list_) { 147 | glob->Print(out); 148 | } 149 | out << std::endl; 150 | // for (auto func : builtin_func_list_) { 151 | // func->EmitCode(out); 152 | // out << std::endl; 153 | // } 154 | for (auto func : func_list_) { 155 | func->EmitCode(out); 156 | out << std::endl; 157 | } 158 | } 159 | 160 | void SSAFunction::EmitCode(std::ostream& out) { 161 | out << func_name_ << ":" << std::endl; 162 | out << "; Function Begin:" << std::endl; 163 | out << " ; called by func: "; 164 | for (auto called_func_use : value_->GetUses()) { 165 | // called_func_use->Get()->Print(); 166 | auto inst = dynamic_cast(called_func_use->GetUser()); 167 | MyAssert(nullptr != inst); 168 | out << inst->GetParent()->GetFunction()->GetFuncName() << " "; 169 | } 170 | out << std::endl; 171 | out << " ; call func: "; 172 | for (auto call_func : call_func_list_) { 173 | out << call_func->GetFuncName() << " "; 174 | } 175 | out << std::endl; 176 | out << " ; used global var: "; 177 | for (auto glob_var : used_glob_var_list_) { 178 | out << glob_var->GetName() << " "; 179 | } 180 | out << std::endl; 181 | for (auto bb : bb_list_) { 182 | bb->EmitCode(out); 183 | out << std::endl; 184 | } 185 | out << "; Function End." << std::endl; 186 | } 187 | 188 | void SSABasicBlock::EmitCode(std::ostream& out) { 189 | out << label_ << ":" << std::endl; 190 | out << "; BB Begin:" << std::endl; 191 | for (auto inst : inst_list_) { 192 | inst->Print(out); 193 | } 194 | out << "; BB End." << std::endl; 195 | } 196 | 197 | #undef ASSERT_ENABLE -------------------------------------------------------------------------------- /src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "../include/Pass/allocate_register.h" 8 | #include "../include/Pass/arm_liveness_analysis.h" 9 | #include "../include/Pass/arm_offset_fixup.h" 10 | #include "../include/Pass/cond_br_to_insts.h" 11 | #include "../include/Pass/constant_propagation.h" 12 | #include "../include/Pass/convert_ssa.h" 13 | #include "../include/Pass/dead_code_eliminate.h" 14 | #include "../include/Pass/dead_function_eliminate.h" 15 | #include "../include/Pass/dominant.h" 16 | #include "../include/Pass/generate_arm_from_ssa.h" 17 | #include "../include/Pass/global_value_numbering.h" 18 | #include "../include/Pass/instruction_combining.h" 19 | #include "../include/Pass/loop.h" 20 | #include "../include/Pass/loop_unroll.h" 21 | #include "../include/Pass/pass_manager.h" 22 | #include "../include/Pass/reach_define.h" 23 | #include "../include/Pass/simplify_armcode.h" 24 | #include "../include/Pass/simplify_cfg.h" 25 | #include "../include/Pass/ssa_simple_optimize.h" 26 | #include "../include/arm.h" 27 | #include "../include/arm_struct.h" 28 | #include "../include/ast.h" 29 | #include "../include/ir.h" 30 | #include "../include/ir_struct.h" 31 | #include "../include/ssa.h" 32 | #include "../include/ssa_struct.h" 33 | #include "parser.hpp" 34 | ast::Root *ast_root; // the root node of final AST 35 | extern int yyparse(); 36 | extern int yylex_destroy(); 37 | extern void yyset_lineno(int _line_number); 38 | 39 | #define DEBUG_PROCESS 40 | 41 | bool AST_LOG = false; 42 | bool IRLIST_LOG = true; 43 | bool PASS_LOG = false; 44 | 45 | 46 | #define ASSERT_ENABLE 47 | #include "../include/myassert.h" 48 | 49 | int main(int argc, char **argv) { 50 | // MyAssert(0); 51 | bool opt = false, print_usage = false; 52 | char *src = nullptr, *output = nullptr, *log_file = nullptr; 53 | // parse command line options and check 54 | for (int ch; (ch = getopt(argc, argv, "Sl:o:O:h")) != -1;) { 55 | switch (ch) { 56 | case 'S': 57 | // do nothing 58 | break; 59 | case 'l': 60 | log_file = strdup(optarg); 61 | break; 62 | case 'o': 63 | output = strdup(optarg); 64 | break; 65 | case 'O': 66 | opt = atoi(optarg) > 0; 67 | break; 68 | case 'h': 69 | print_usage = true; 70 | break; 71 | default: 72 | break; 73 | } 74 | } 75 | 76 | if (optind <= argc) { 77 | src = argv[optind]; 78 | } 79 | 80 | if (src == nullptr || print_usage) { 81 | std::cerr << "Usage: " << argv[0] << " [-S] [-l log_file] [-o output_file] [-O level] input_file" << std::endl; 82 | return 1; 83 | } 84 | 85 | if (nullptr != src) { 86 | freopen(src, "r", stdin); 87 | } 88 | std::ofstream logfile; 89 | if (nullptr != log_file) { 90 | logfile.open(log_file); 91 | } 92 | 93 | #ifdef DEBUG_PROCESS 94 | std::cout << "Parser Start:" << std::endl; 95 | #endif 96 | yyset_lineno(1); 97 | yyparse(); // if success, ast_root is valid 98 | // MyAssert(0); 99 | #ifdef DEBUG_PROCESS 100 | std::cout << "Parser End." << std::endl; 101 | #endif 102 | yylex_destroy(); 103 | 104 | MyAssert(nullptr != ast_root); 105 | if (logfile.is_open() && AST_LOG) { 106 | logfile << "AST:" << std::endl; 107 | ast_root->PrintNode(0, logfile); 108 | } 109 | 110 | #ifdef DEBUG_PROCESS 111 | std::cout << "Generate IR Start:" << std::endl; 112 | #endif 113 | std::vector *ir_list_ptr = new std::vector(); 114 | { 115 | ir::ContextInfo ctx; 116 | ast_root->GenerateIR(ctx, *ir_list_ptr); 117 | } 118 | #ifdef DEBUG_PROCESS 119 | std::cout << "Generate IR End." << std::endl; 120 | #endif 121 | // MyAssert(0); 122 | delete ast_root; 123 | 124 | if (logfile.is_open() && IRLIST_LOG) { 125 | ir::PrintFuncTable(logfile); 126 | ir::PrintScopes(logfile); 127 | logfile << "IRList:" << std::endl; 128 | for (auto ir : *ir_list_ptr) { 129 | ir->PrintIR(logfile); 130 | } 131 | } 132 | 133 | // it represents IRModule before GenerateArm Pass and ArmModule after GenerateArm Pass. 134 | // the source space will be released when running GenerateArm Pass. 135 | Module *module_ptr = static_cast(ConstructModule(std::string(src), *ir_list_ptr)); 136 | delete ir_list_ptr; 137 | // module_ptr->EmitCode(std::cout); 138 | Module **const module_ptr_addr = &module_ptr; 139 | 140 | #ifdef DEBUG_PROCESS 141 | std::cout << "Passes Start:" << std::endl; 142 | #endif 143 | PassManager pm(module_ptr_addr); 144 | 145 | // ==================Add Quad-Pass Below================== 146 | pm.AddPass(true); 147 | pm.AddPass(true); 148 | // pm.AddPass(false); 149 | pm.AddPass(true); 150 | pm.AddPass(true); 151 | pm.AddPass(true); 152 | pm.AddPass(true); 153 | // ==================Add Quad-Pass Above================== 154 | pm.AddPass(true); // necessary 155 | pm.AddPass(false); 156 | pm.AddPass(true); 157 | // ==================Add SSA-Pass Below================== 158 | pm.AddPass(false); 159 | pm.AddPass(true); 160 | pm.AddPass(false); 161 | pm.AddPass(true); // actually redundant common expression eliminate 162 | pm.AddPass(true); 163 | pm.AddPass(false); 164 | // ==================Add SSA-Pass Above================== 165 | pm.AddPass(true); // define macro control MUL_TO_SHIFT DIV_TO_SHIFT MOD_TO_AND optimize 166 | // ==================Add Arm(vreg)-Pass Below================== 167 | pm.AddPass(true); 168 | pm.AddPass(true); 169 | // ==================Add Arm(vreg)-Pass Above================== 170 | pm.AddPass(true); 171 | pm.AddPass(true); 172 | // ==================Add Arm-Pass Below================== 173 | pm.AddPass(false); 174 | pm.AddPass(true); 175 | // ==================Add Arm-Pass Above================== 176 | if (logfile.is_open()) { 177 | pm.Run(PASS_LOG, logfile); 178 | } else { 179 | pm.Run(); 180 | } 181 | 182 | // exit(0); 183 | #ifdef DEBUG_PROCESS 184 | std::cout << "Passes End." << std::endl; 185 | #endif 186 | MyAssert(typeid(*module_ptr) == typeid(ArmModule)); 187 | 188 | #ifdef DEBUG_PROCESS 189 | std::cout << "Emit Start:" << std::endl; 190 | #endif 191 | { 192 | std::ofstream outfile; 193 | std::string file_name = ""; 194 | if (nullptr == output) { 195 | file_name = std::string(src, src + strlen(src) - 1); 196 | } else { 197 | file_name = std::string(output); 198 | } 199 | outfile.open(file_name); 200 | if (logfile.is_open()) { 201 | logfile << "Emitting code to file: " << file_name << std::endl; 202 | } 203 | module_ptr->EmitCode(outfile); 204 | MyAssert(outfile.is_open()); 205 | outfile << std::endl; 206 | if (logfile.is_open()) { 207 | logfile << "EmitCode finish." << std::endl; 208 | } 209 | outfile.close(); 210 | } 211 | #ifdef DEBUG_PROCESS 212 | std::cout << "Emit End." << std::endl; 213 | #endif 214 | 215 | if (logfile.is_open()) { 216 | logfile.close(); 217 | } 218 | 219 | // release the arm module space. 220 | delete module_ptr; 221 | module_ptr = nullptr; 222 | 223 | return 0; 224 | } 225 | 226 | #undef ASSERT_ENABLE -------------------------------------------------------------------------------- /src/Pass/arm_offset_fixup.cpp: -------------------------------------------------------------------------------- 1 | #include "../../include/Pass/arm_offset_fixup.h" 2 | 3 | #include "../../include/arm.h" 4 | #include "../../include/arm_struct.h" 5 | 6 | #define ASSERT_ENABLE 7 | #include "../../include/myassert.h" 8 | 9 | // #define DEBUG_FIXUP_PROCESS 10 | 11 | void SPOffsetFixup::Run() { 12 | auto m = dynamic_cast(*(this->m_)); 13 | MyAssert(nullptr != m); 14 | for (auto func : m->func_list_) { 15 | Fixup4Func(func); 16 | } 17 | } 18 | 19 | void SPOffsetFixup::Fixup4Func(ArmFunction *func) { 20 | #ifdef DEBUG_FIXUP_PROCESS 21 | std::cout << "Prune Instruction Start:" << std::endl; 22 | #endif 23 | // 每一个函数确定了之后 更改push/pop指令 更改add/sub sp sp stack_size指令 24 | int offset_fixup_diff = func->used_callee_saved_regs.size() * 4 + func->stack_size_; 25 | bool is_lr_used = func->used_callee_saved_regs.find(ArmReg::lr) != func->used_callee_saved_regs.end(); 26 | 27 | #ifdef DEBUG_FIXUP_PROCESS 28 | std::cout << "Modify Push Pop Start:" << std::endl; 29 | #endif 30 | for (auto bb : func->bb_list_) { 31 | for (auto iter = bb->inst_list_.begin(); iter != bb->inst_list_.end();) { 32 | if (auto pushpop_inst = dynamic_cast(*iter)) { 33 | // pushpop_inst->EmitCode(outfile); 34 | pushpop_inst->reg_list_.clear(); 35 | Cond cond = pushpop_inst->cond_; 36 | for (auto reg : func->used_callee_saved_regs) { 37 | pushpop_inst->reg_list_.push_back(new Reg(reg)); 38 | } 39 | if (pushpop_inst->opkind_ == PushPop::OpKind::PUSH) { 40 | if (pushpop_inst->reg_list_.empty()) { 41 | iter = bb->inst_list_.erase(iter); 42 | continue; 43 | } 44 | } else { 45 | if (is_lr_used) { // 把pop lr 改为pop pc 46 | MyAssert(pushpop_inst->reg_list_.back()->reg_id_ == ArmReg::lr); 47 | pushpop_inst->reg_list_.back()->reg_id_ = ArmReg::pc; 48 | } 49 | if (pushpop_inst->reg_list_.empty()) { 50 | iter = bb->inst_list_.erase(iter); 51 | } else { 52 | ++iter; 53 | } 54 | // 此时iter指向原pop指令的下一条指令 55 | if (!is_lr_used) { // 不在push中 插入一条 bx lr 56 | iter = bb->inst_list_.insert(iter, new Branch(false, true, cond, "lr", bb, false)); 57 | } 58 | continue; 59 | } 60 | ++iter; 61 | } else { 62 | ++iter; 63 | } 64 | } 65 | } 66 | #ifdef DEBUG_FIXUP_PROCESS 67 | std::cout << "Modify Push Pop End." << std::endl; 68 | #endif 69 | 70 | #ifdef DEBUG_FIXUP_PROCESS 71 | std::cout << "Fixup sp_arg Start:" << std::endl; 72 | #endif 73 | 74 | auto merge_ldrpseudo_with_ldr = [&func](std::unordered_set::iterator it) { 75 | // 把ldrpseudo和后面的ldr合起来 76 | for (auto bb : func->bb_list_) { 77 | for (auto inst_it = bb->inst_list_.begin(); inst_it != bb->inst_list_.end(); ++inst_it) { 78 | if (*inst_it == *it) { 79 | int imm = 0; 80 | auto src_inst = dynamic_cast(*inst_it); 81 | MyAssert(nullptr != src_inst && src_inst->IsImm()); 82 | imm = src_inst->imm_; 83 | inst_it = bb->inst_list_.erase(inst_it); 84 | // inst_it现在指向了ldr vreg sp op2指令 要把op2改为立即数类型 85 | auto ldr_inst = dynamic_cast(*inst_it); 86 | MyAssert(nullptr != ldr_inst && !ldr_inst->is_offset_imm_ && nullptr != ldr_inst->offset_ && 87 | ldr_inst->rn_->reg_id_ == ArmReg::sp && !ldr_inst->offset_->is_imm_ && 88 | ldr_inst->offset_->reg_->reg_id_ == src_inst->rd_->reg_id_); 89 | // TODO delete src op2 90 | ldr_inst->offset_ = new Operand2(imm); 91 | // *it = ldr_inst; // 之后sp_arg_fixup中会出现ldr指令 92 | return; 93 | } 94 | } 95 | } 96 | MyAssert(0); 97 | }; 98 | 99 | // 针对sp_arg的修复 需要修复栈中高处实参的位置 一定是一条ldr-pseudo指令 100 | for (auto it = func->sp_arg_fixup_.begin(); it != func->sp_arg_fixup_.end(); ++it) { 101 | auto src_inst = dynamic_cast(*it); 102 | MyAssert(nullptr != src_inst && src_inst->IsImm()); 103 | src_inst->imm_ += offset_fixup_diff; 104 | if (LdrStr::CheckImm12(src_inst->imm_)) { 105 | merge_ldrpseudo_with_ldr(it); 106 | } 107 | } 108 | 109 | func->sp_arg_fixup_.clear(); 110 | 111 | #ifdef DEBUG_FIXUP_PROCESS 112 | std::cout << "Fixup sp_arg End." << std::endl; 113 | std::cout << "Fixup sp Start:" << std::endl; 114 | #endif 115 | 116 | auto convert_imm_inst = [&func](std::unordered_set::iterator it) { 117 | // 把mov/mvn转换成ldrpseudo 118 | for (auto bb : func->bb_list_) { 119 | for (auto inst_it = bb->inst_list_.begin(); inst_it != bb->inst_list_.end(); ++inst_it) { 120 | if (*inst_it == *it) { 121 | auto src_inst = dynamic_cast(*it); 122 | MyAssert(nullptr != src_inst && src_inst->op2_->is_imm_); 123 | inst_it = bb->inst_list_.erase(inst_it); 124 | int imm = 0; 125 | if (src_inst->is_mvn_) { 126 | imm = -src_inst->op2_->imm_num_ - 1; 127 | } else { 128 | imm = src_inst->op2_->imm_num_; 129 | } 130 | auto pseudo_ldr_inst = new LdrPseudo(Cond::AL, src_inst->rd_, imm, bb); 131 | inst_it = bb->inst_list_.insert(inst_it, pseudo_ldr_inst); 132 | // TODO: delete 133 | // *it = pseudo_ldr_inst; 134 | return; 135 | } 136 | } 137 | } 138 | MyAssert(0); 139 | }; 140 | 141 | auto merge_with_addsub = [&func](std::unordered_set::iterator it) { 142 | // 把mov/ldrpseudo和后面的addsub sp sp 合起来 143 | for (auto bb : func->bb_list_) { 144 | for (auto inst_it = bb->inst_list_.begin(); inst_it != bb->inst_list_.end(); ++inst_it) { 145 | if (*inst_it == *it) { 146 | int imm = 0; 147 | if (auto src_inst = dynamic_cast(*it)) { 148 | MyAssert(src_inst->op2_->is_imm_); 149 | if (src_inst->is_mvn_) return; 150 | imm = src_inst->op2_->imm_num_; 151 | } else if (auto src_inst = dynamic_cast(*it)) { 152 | MyAssert(src_inst->IsImm()); 153 | imm = src_inst->imm_; 154 | } else { 155 | MyAssert(0); 156 | } 157 | inst_it = bb->inst_list_.erase(inst_it); 158 | // inst_it现在指向了add或sub sp sp op2指令 要把op2改为立即数类型 159 | auto addsub_inst = dynamic_cast(*inst_it); 160 | MyAssert(nullptr != addsub_inst && addsub_inst->rd_->reg_id_ == ArmReg::sp && 161 | addsub_inst->rn_->reg_id_ == ArmReg::sp); 162 | // TODO delete src op2 163 | addsub_inst->op2_ = new Operand2(imm); 164 | // *it = addsub_inst; // 之后sp_fixup中会出现addsub指令 165 | return; 166 | } 167 | } 168 | } 169 | MyAssert(0); 170 | }; 171 | 172 | // 针对function prologue和epilogue中sp的修复 原来都是0 可能是mov mvn或者pseudo ldr 173 | for (auto it = func->sp_fixup_.begin(); it != func->sp_fixup_.end(); ++it) { 174 | if (auto src_inst = dynamic_cast(*it)) { 175 | MyAssert(src_inst->op2_->is_imm_); 176 | if (src_inst->is_mvn_) { 177 | MyAssert(0); 178 | src_inst->op2_->imm_num_ = -func->stack_size_; 179 | } else { 180 | src_inst->op2_->imm_num_ = func->stack_size_; 181 | } 182 | if (!Operand2::CheckImm8m(src_inst->op2_->imm_num_)) { 183 | convert_imm_inst(it); 184 | } else { 185 | // 满足op2 可以和后面的add/sub合为一条语句 186 | merge_with_addsub(it); 187 | } 188 | } else if (auto src_inst = dynamic_cast(*it)) { 189 | MyAssert(src_inst->IsImm()); 190 | src_inst->imm_ = func->stack_size_; 191 | if (Operand2::CheckImm8m(src_inst->imm_)) { 192 | // 满足op2 可以和后面的add/sub合为一条语句 193 | merge_with_addsub(it); 194 | } 195 | } else { 196 | MyAssert(0); 197 | } 198 | } 199 | 200 | func->sp_fixup_.clear(); 201 | 202 | #ifdef DEBUG_FIXUP_PROCESS 203 | std::cout << "Fixup sp End." << std::endl; 204 | #endif 205 | } 206 | 207 | #undef ASSERT_ENABLE -------------------------------------------------------------------------------- /src/Pass/arm_liveness_analysis.cpp: -------------------------------------------------------------------------------- 1 | #include "../../include/Pass/arm_liveness_analysis.h" 2 | 3 | #define ASSERT_ENABLE 4 | #include "../../include/myassert.h" 5 | 6 | std::pair, std::vector> GetDefUse(Instruction *inst) { 7 | std::vector def; 8 | std::vector use; 9 | 10 | auto process_op2 = [&use](Operand2 *op2) { 11 | if (nullptr == op2) return; 12 | if (op2->is_imm_) return; 13 | use.push_back(op2->reg_->reg_id_); 14 | if (nullptr != op2->shift_ && !op2->shift_->is_imm_) { 15 | use.push_back(op2->shift_->shift_reg_->reg_id_); 16 | } 17 | return; 18 | }; 19 | 20 | if (auto src_inst = dynamic_cast(inst)) { 21 | if (nullptr != src_inst->rd_) { 22 | def.push_back(src_inst->rd_->reg_id_); 23 | } 24 | use.push_back(src_inst->rn_->reg_id_); 25 | process_op2(src_inst->op2_); 26 | } else if (auto src_inst = dynamic_cast(inst)) { 27 | def.push_back(src_inst->rd_->reg_id_); 28 | process_op2(src_inst->op2_); 29 | } else if (auto src_inst = dynamic_cast(inst)) { 30 | // call可先视为对前面已经定义的参数寄存器的使用 再视作对调用者保护的寄存器的定义 不管之后这些寄存器有没有被使用 31 | // caller save regs: r0-r3, lr, ip 32 | // ret可视为对r0和lr的使用 但需要保证armcode是正确的 i.e. 如果前面有bl xxx指令的话 后面不能用bx lr指令返回 33 | // 如果b后面是个函数label就是call 如果b后面是lr就是ret 34 | auto &label = src_inst->label_; 35 | if (src_inst->IsRet()) { // bx lr 36 | use.push_back(static_cast(ArmReg::r0)); 37 | use.push_back(static_cast(ArmReg::lr)); 38 | } else if (src_inst->IsCall()) { // call 39 | int callee_param_num = ir::gFuncTable[label].shape_list_.size(); 40 | for (RegId i = 0; i < std::min(callee_param_num, 4); ++i) { 41 | use.push_back(i); 42 | } 43 | for (RegId i = 0; i < 4; ++i) { 44 | def.push_back(i); 45 | } 46 | def.push_back(static_cast(ArmReg::ip)); 47 | def.push_back(static_cast(ArmReg::lr)); 48 | } 49 | } else if (auto src_inst = dynamic_cast(inst)) { 50 | if (src_inst->opkind_ == LdrStr::OpKind::LDR) { 51 | def.push_back(src_inst->rd_->reg_id_); 52 | } else { 53 | use.push_back(src_inst->rd_->reg_id_); 54 | } 55 | use.push_back(src_inst->rn_->reg_id_); 56 | process_op2(src_inst->offset_); 57 | } else if (auto src_inst = dynamic_cast(inst)) { 58 | def.push_back(src_inst->rd_->reg_id_); 59 | } else if (auto src_inst = dynamic_cast(inst)) { 60 | if (src_inst->opkind_ == PushPop::OpKind::PUSH) { 61 | for (auto reg : src_inst->reg_list_) { 62 | use.push_back(reg->reg_id_); 63 | } 64 | } else { 65 | for (auto reg : src_inst->reg_list_) { 66 | if (reg->reg_id_ == static_cast(ArmReg::pc)) { 67 | // 此时作为ret语句 视为对r0的使用以及对pc的定义 68 | use.push_back(static_cast(ArmReg::r0)); 69 | } 70 | def.push_back(reg->reg_id_); 71 | } 72 | } 73 | } else { // 未实现其他指令 74 | MyAssert(0); 75 | } 76 | 77 | return {def, use}; 78 | } 79 | 80 | std::pair, std::vector> GetDefUsePtr(Instruction *inst) { 81 | std::vector def; 82 | std::vector use; 83 | 84 | auto process_op2 = [&use](Operand2 *op2) { 85 | if (nullptr == op2) return; 86 | if (op2->is_imm_) return; 87 | use.push_back(op2->reg_); 88 | if (nullptr != op2->shift_ && !op2->shift_->is_imm_) { 89 | use.push_back(op2->shift_->shift_reg_); 90 | } 91 | return; 92 | }; 93 | 94 | if (auto src_inst = dynamic_cast(inst)) { 95 | if (nullptr != src_inst->rd_) { 96 | def.push_back(src_inst->rd_); 97 | } 98 | use.push_back(src_inst->rn_); 99 | process_op2(src_inst->op2_); 100 | } else if (auto src_inst = dynamic_cast(inst)) { 101 | def.push_back(src_inst->rd_); 102 | process_op2(src_inst->op2_); 103 | } else if (auto src_inst = dynamic_cast(inst)) { 104 | // call可先视为对前面已经定义的参数寄存器的使用 再视作对调用者保护的寄存器的定义 不管之后这些寄存器有没有被使用 105 | // caller save regs: r0-r3, lr, ip 106 | // ret可视为对r0和lr的使用 但需要保证armcode是正确的 i.e. 如果前面有bl xxx指令的话 后面不能用bx lr指令返回 107 | // 如果b后面是个函数label就是call 如果b后面是lr就是ret 108 | auto &label = src_inst->label_; 109 | if (src_inst->IsRet()) { // bx lr 110 | use.push_back(new Reg(ArmReg::r0)); 111 | use.push_back(new Reg(ArmReg::lr)); 112 | } else if (src_inst->IsCall()) { // call 113 | int callee_param_num = ir::gFuncTable[label].shape_list_.size(); 114 | for (RegId i = 0; i < std::min(callee_param_num, 4); ++i) { 115 | use.push_back(new Reg(i)); 116 | } 117 | for (RegId i = 0; i < 4; ++i) { 118 | def.push_back(new Reg(i)); 119 | } 120 | def.push_back(new Reg(ArmReg::ip)); 121 | def.push_back(new Reg(ArmReg::lr)); 122 | } 123 | } else if (auto src_inst = dynamic_cast(inst)) { 124 | if (src_inst->opkind_ == LdrStr::OpKind::LDR) { 125 | def.push_back(src_inst->rd_); 126 | } else { 127 | use.push_back(src_inst->rd_); 128 | } 129 | use.push_back(src_inst->rn_); 130 | process_op2(src_inst->offset_); 131 | } else if (auto src_inst = dynamic_cast(inst)) { 132 | def.push_back(src_inst->rd_); 133 | } else if (auto src_inst = dynamic_cast(inst)) { 134 | if (src_inst->opkind_ == PushPop::OpKind::PUSH) { 135 | for (auto reg : src_inst->reg_list_) { 136 | use.push_back(reg); 137 | } 138 | } else { 139 | for (auto reg : src_inst->reg_list_) { 140 | if (reg->reg_id_ == static_cast(ArmReg::pc)) { 141 | // 此时作为ret语句 视为对r0的使用以及对pc的定义 142 | use.push_back(new Reg(ArmReg::r0)); 143 | } 144 | def.push_back(reg); 145 | } 146 | } 147 | } else { // 未实现其他指令 148 | MyAssert(0); 149 | } 150 | 151 | return {def, use}; 152 | } 153 | 154 | void ArmLivenessAnalysis::Run4Func(ArmFunction *f) { 155 | for (auto bb : f->bb_list_) { 156 | // NOTE: 发生实际溢出时会重新分析 需要先清空 157 | bb->livein_.clear(); 158 | bb->liveout_.clear(); 159 | bb->def_.clear(); 160 | bb->use_.clear(); 161 | // 对于每一条指令 取def和use并记录到basicblock中 加快数据流分析 162 | for (auto inst : bb->inst_list_) { 163 | auto [def, use] = GetDefUse(inst); 164 | for (auto &u : use) { 165 | // liveuse not use. if in def, not liveuse 166 | if (bb->def_.find(u) == bb->def_.end()) { 167 | bb->use_.insert(u); 168 | } 169 | } 170 | for (auto &d : def) { 171 | if (bb->use_.find(d) == bb->use_.end()) { 172 | bb->def_.insert(d); 173 | } 174 | } 175 | } 176 | // liveuse是入口活跃的那些use 177 | // def是非入口活跃use的那些def 178 | bb->livein_ = bb->use_; 179 | } 180 | 181 | // 为每一个basicblock计算livein和liveout 182 | bool changed = true; 183 | while (changed) { 184 | changed = false; 185 | for (auto bb : f->bb_list_) { 186 | std::unordered_set new_out; 187 | // out[s]=U(succ:i)in[i] 188 | // 对每一个后继基本块 189 | // std::cout<succ_.size()<succ_) { 191 | // if(succ){ 192 | new_out.insert(succ->livein_.begin(), succ->livein_.end()); 193 | // } 194 | } 195 | 196 | if (new_out != bb->liveout_) { 197 | // 还未到达不动点 198 | changed = true; 199 | bb->liveout_ = new_out; 200 | // in[s]=use[s]U(out[s]-def[s]) 可增量添加 201 | for (auto s : bb->liveout_) { 202 | if (bb->def_.find(s) == bb->def_.end()) { 203 | bb->livein_.insert(s); // 重复元素插入无副作用 204 | } 205 | } 206 | } 207 | } // for every bb 208 | } // while end} 209 | } 210 | 211 | void ArmLivenessAnalysis::Run() { 212 | auto m = dynamic_cast(*(this->m_)); 213 | MyAssert(nullptr != m); 214 | for (auto func : m->func_list_) { 215 | this->Run4Func(func); 216 | } 217 | } 218 | 219 | #undef ASSERT_ENABLE -------------------------------------------------------------------------------- /src/Pass/ssa_simple_optimize.cpp: -------------------------------------------------------------------------------- 1 | #include "../../include/Pass/ssa_simple_optimize.h" 2 | 3 | #include "../../include/ssa.h" 4 | #include "../../include/ssa_struct.h" 5 | 6 | #define ASSERT_ENABLE 7 | #include "../../include/myassert.h" 8 | 9 | // #define DEBUG_SIMPLE_OPTIMIZE_PROCESS 10 | // #define DEBUG_SIMPLE_OPTIMIZE_EFFECT 11 | static int kCount = 0; 12 | 13 | void SimpleOptimize::Run() { 14 | kCount = 0; 15 | auto m = dynamic_cast(*(this->m_)); 16 | MyAssert(nullptr != m); 17 | std::unordered_set worklist; 18 | #ifdef DEBUG_SIMPLE_OPTIMIZE_PROCESS 19 | std::cout << "SimpleOptimize :" << std::endl; 20 | #endif 21 | for (auto func : m->GetFuncList()) { 22 | for (auto bb : func->GetBasicBlocks()) { 23 | for (auto inst : bb->GetInstList()) { 24 | worklist.insert(inst); 25 | } 26 | } 27 | } 28 | 29 | auto replace = [&worklist](SSAInstruction* from, SSAInstruction* to) { 30 | #ifdef DEBUG_SIMPLE_OPTIMIZE_PROCESS 31 | std::cout << "Convert :", from->Print(std::cout); 32 | std::cout << " ==>", to->Print(std::cout); 33 | #endif 34 | from->ReplaceAllUseWith(to); 35 | worklist.insert(to); 36 | from->Remove(); 37 | delete from; 38 | }; 39 | 40 | while (!worklist.empty()) { 41 | auto inst = *worklist.begin(); 42 | MyAssert(nullptr != inst); 43 | worklist.erase(inst); 44 | // 如果phi语句的参数全是一个常数 或者phi语句只有一个参数 45 | // NOTE HERE!!! 应该不用考虑phi指令间的并行赋值 会打破phi指令一定是bb中最前面几条的性质 46 | if (auto src_inst = dynamic_cast(inst)) { 47 | // 考虑只有一个参数 48 | if (2 == src_inst->GetNumOperands()) { 49 | ++kCount; 50 | auto mov_inst = new MovInst(src_inst->GetType(), src_inst->GetName(), src_inst->GetOperand(0), src_inst); 51 | replace(src_inst, mov_inst); 52 | continue; 53 | } 54 | // 考虑参数全是常数 55 | auto constint = dynamic_cast(src_inst->GetOperand(0)); 56 | if (nullptr == constint) continue; 57 | int i = 2; 58 | for (; i < src_inst->GetNumOperands(); i += 2) { 59 | auto operand = src_inst->GetOperand(i); 60 | auto constint2 = dynamic_cast(operand); 61 | if (nullptr == constint2) break; 62 | if (constint2->GetImm() != constint->GetImm()) break; 63 | } 64 | if (i == src_inst->GetNumOperands()) { 65 | auto mov_inst = new MovInst(src_inst->GetType(), src_inst->GetName(), constint, src_inst); 66 | replace(src_inst, mov_inst); 67 | ++kCount; 68 | continue; 69 | } 70 | } 71 | // 如果是一条mov语句 该mov可删 用其操作数代替它自己 72 | else if (auto src_inst = dynamic_cast(inst)) { 73 | ++kCount; 74 | #ifdef DEBUG_SIMPLE_OPTIMIZE_PROCESS 75 | std::cout << "Remove :", src_inst->Print(std::cout); 76 | #endif 77 | // 把所有使用该value的加入工作表 实际上只加入mov和phi语句即可 78 | for (auto use : src_inst->GetUses()) { 79 | worklist.insert(dynamic_cast(use->GetUser())); 80 | } 81 | src_inst->ReplaceAllUseWith(src_inst->GetOperand(0)); 82 | src_inst->Remove(); // 从基本块中移除 83 | delete src_inst; 84 | } 85 | // 如果是二元运算语句 并且两个操作数都是常数 则转化为一条mov语句 86 | else if (auto src_inst = dynamic_cast(inst)) { 87 | // TODO: 如果有一个数是常数并且为0 并且操作符是mul div mod那么直接转为一条mov语句即可 88 | auto const_lhs = dynamic_cast(src_inst->GetOperand(0)); 89 | auto const_rhs = dynamic_cast(src_inst->GetOperand(1)); 90 | if (nullptr == const_lhs && nullptr == const_rhs) continue; 91 | MovInst* mov_inst = nullptr; 92 | if (nullptr != const_lhs && 0 == const_lhs->GetImm() && 93 | (src_inst->op_ == BinaryOperator::DIV || src_inst->op_ == BinaryOperator::MOD || 94 | src_inst->op_ == BinaryOperator::MUL)) { 95 | new MovInst(src_inst->GetType(), src_inst->GetName(), new ConstantInt(0), src_inst); 96 | } else if (nullptr != const_rhs && 0 == const_rhs->GetImm() && src_inst->op_ == BinaryOperator::MUL) { 97 | new MovInst(src_inst->GetType(), src_inst->GetName(), new ConstantInt(0), src_inst); 98 | } else if (nullptr != const_lhs && nullptr != const_rhs) { 99 | int res = src_inst->ComputeConstInt(const_lhs->GetImm(), const_rhs->GetImm()); 100 | new MovInst(src_inst->GetType(), src_inst->GetName(), new ConstantInt(res), src_inst); 101 | } 102 | if (nullptr != mov_inst) { 103 | ++kCount; 104 | replace(src_inst, mov_inst); 105 | } 106 | } 107 | // 如果是一元运算语句 并且操作数是常数 则转化为一条mov语句 108 | else if (auto src_inst = dynamic_cast(inst)) { 109 | auto const_lhs = dynamic_cast(src_inst->GetOperand(0)); 110 | if (nullptr == const_lhs) continue; 111 | ++kCount; 112 | int res = src_inst->ComputeConstInt(const_lhs->GetImm()); 113 | auto mov_inst = new MovInst(src_inst->GetType(), src_inst->GetName(), new ConstantInt(res), src_inst); 114 | replace(src_inst, mov_inst); 115 | } 116 | // 如果是条件跳转语句 并且两个操作数都是立即数 可转换为无条件跳转或者删除 117 | // NOTE: 还必须修改基本块的前驱后继关系 118 | else if (auto src_inst = dynamic_cast(inst)) { 119 | if (3 == src_inst->GetNumOperands()) { 120 | auto const_lhs = dynamic_cast(src_inst->GetOperand(0)); 121 | if (nullptr == const_lhs) continue; 122 | auto const_rhs = dynamic_cast(src_inst->GetOperand(1)); 123 | if (nullptr == const_rhs) continue; 124 | auto bb_val = dynamic_cast(src_inst->GetOperand(2)); 125 | MyAssert(nullptr != bb_val); 126 | auto bb = src_inst->GetParent(), target_bb = bb_val->GetBB(); 127 | // continue; 128 | if (src_inst->ComputeConstInt(const_lhs->GetImm(), const_rhs->GetImm())) { 129 | ++kCount; 130 | // 条件判断永远为真 转换为无条件跳转 131 | auto new_inst = new BranchInst(bb_val, src_inst); 132 | #ifdef DEBUG_SIMPLE_OPTIMIZE_PROCESS 133 | std::cout << "Convert :", src_inst->Print(std::cout); 134 | std::cout << " ==>", new_inst->Print(std::cout); 135 | #endif 136 | auto next_bb = bb->GetNextBB(); 137 | MyAssert(nullptr != next_bb); 138 | bb->RemoveSuccBB(next_bb); 139 | next_bb->RemovePredBB(bb); 140 | // 修复next bb中的phi指令 141 | for (auto inst : next_bb->GetInstList()) { 142 | auto phi_inst = dynamic_cast(inst); 143 | if (nullptr == phi_inst) break; 144 | for (int i = 1; i < phi_inst->GetNumOperands(); i += 2) { 145 | auto bb_val = dynamic_cast(phi_inst->GetOperand(i)); 146 | MyAssert(nullptr != bb_val); 147 | if (bb_val->GetBB() == bb) { 148 | // NOTE: order and break 149 | phi_inst->RemoveOperand(i); 150 | phi_inst->RemoveOperand(i - 1); 151 | break; 152 | } 153 | } 154 | } 155 | src_inst->Remove(); 156 | delete src_inst; 157 | } else { 158 | ++kCount; 159 | // 条件判断永远为假 直接删除 160 | #ifdef DEBUG_SIMPLE_OPTIMIZE_PROCESS 161 | std::cout << "Remove :", src_inst->Print(std::cout); 162 | #endif 163 | target_bb->RemovePredBB(bb); 164 | bb->RemoveSuccBB(target_bb); 165 | // 修复target bb中的phi指令 166 | for (auto inst : target_bb->GetInstList()) { 167 | auto phi_inst = dynamic_cast(inst); 168 | if (nullptr == phi_inst) break; 169 | for (int i = 1; i < phi_inst->GetNumOperands(); i += 2) { 170 | auto bb_val = dynamic_cast(phi_inst->GetOperand(i)); 171 | MyAssert(nullptr != bb_val); 172 | if (bb_val->GetBB() == bb) { 173 | // NOTE: order and break 174 | phi_inst->RemoveOperand(i); 175 | phi_inst->RemoveOperand(i - 1); 176 | break; 177 | } 178 | } 179 | } 180 | src_inst->Remove(); 181 | delete src_inst; 182 | } 183 | } 184 | } 185 | } 186 | #ifdef DEBUG_SIMPLE_OPTIMIZE_EFFECT 187 | std::cout << "SSA_SIMPLE_OPTIMIZE Pass works on " << kCount << " insts" << std::endl; 188 | #endif 189 | } -------------------------------------------------------------------------------- /src/arm.cpp: -------------------------------------------------------------------------------- 1 | #include "../include/arm.h" 2 | 3 | #include 4 | #include 5 | 6 | #include "../include/arm_struct.h" 7 | #define ASSERT_ENABLE 8 | #include "../include/myassert.h" 9 | 10 | namespace arm { 11 | 12 | Cond GetOppositeCond(Cond cond) { 13 | switch (cond) { 14 | case Cond::AL: 15 | return Cond::AL; 16 | case Cond::EQ: 17 | return Cond::NE; 18 | case Cond::NE: 19 | return Cond::EQ; 20 | case Cond::GT: 21 | return Cond::LE; 22 | case Cond::GE: 23 | return Cond::LT; 24 | case Cond::LT: 25 | return Cond::GE; 26 | case Cond::LE: 27 | return Cond::GT; 28 | default: 29 | MyAssert(0); 30 | break; 31 | } 32 | } 33 | 34 | std::string CondToString(Cond cond) { 35 | switch (cond) { 36 | case Cond::AL: 37 | return ""; 38 | case Cond::EQ: 39 | return "eq"; 40 | case Cond::NE: 41 | return "ne"; 42 | case Cond::GT: 43 | return "gt"; 44 | case Cond::GE: 45 | return "ge"; 46 | case Cond::LT: 47 | return "lt"; 48 | case Cond::LE: 49 | return "le"; 50 | default: 51 | MyAssert(0); 52 | break; 53 | } 54 | return ""; 55 | } 56 | 57 | Shift::operator std::string() { 58 | std::string opcode = ""; 59 | switch (opcode_) { 60 | case OpCode::ASR: 61 | opcode = "asr"; 62 | break; 63 | case OpCode::LSL: 64 | opcode = "lsl"; 65 | break; 66 | case OpCode::LSR: 67 | opcode = "lsr"; 68 | break; 69 | case OpCode::ROR: 70 | opcode = "ror"; 71 | break; 72 | case OpCode::RRX: 73 | return "rrx"; 74 | default: 75 | MyAssert(0); 76 | break; 77 | } 78 | if (is_imm_) { 79 | return opcode + " #" + std::to_string(shift_imm_); 80 | } else { 81 | return opcode + " " + std::string(*shift_reg_); 82 | } 83 | } 84 | 85 | Operand2::operator std::string() { 86 | return is_imm_ ? ("#" + std::to_string(imm_num_)) 87 | : (std::string(*reg_) + (nullptr == shift_ || shift_->IsNone() ? "" : ", " + std::string(*shift_))); 88 | } 89 | bool Operand2::CheckImm8m(int imm) { 90 | // NOTE: assign a int to unsigned int 91 | unsigned int encoding = imm; 92 | for (int ror = 0; ror < 32; ror += 2) { 93 | // 如果encoding的前24bit都是0 说明imm能被表示成一个8bit循环右移偶数位得到 94 | if (!(encoding & ~0xFFu)) { 95 | return true; 96 | } 97 | encoding = (encoding << 30u) | (encoding >> 2u); 98 | } 99 | return false; 100 | } 101 | 102 | Instruction::Instruction(Cond cond, ArmBasicBlock* parent, bool push_back) : cond_(cond), parent_(parent) { 103 | if (push_back) parent_->inst_list_.push_back(this); 104 | } 105 | Instruction::Instruction(ArmBasicBlock* parent, bool push_back) : parent_(parent) { 106 | if (push_back) parent_->inst_list_.push_back(this); 107 | } 108 | Instruction::Instruction(Instruction* inst) : parent_(inst->parent_) { 109 | auto& inst_list = parent_->inst_list_; 110 | auto it = std::find(inst_list.begin(), inst_list.end(), inst); 111 | MyAssert(it != inst_list.end()); 112 | inst_list.insert(it, this); 113 | } 114 | 115 | BinaryInst::~BinaryInst() {} 116 | void BinaryInst::EmitCode(std::ostream& outfile) { 117 | std::string opcode; 118 | switch (this->opcode_) { 119 | case OpCode::ADD: 120 | opcode = "add"; 121 | break; 122 | case OpCode::SUB: 123 | opcode = "sub"; 124 | break; 125 | case OpCode::RSB: 126 | opcode = "rsb"; 127 | break; 128 | case OpCode::MUL: 129 | opcode = "mul"; 130 | break; 131 | case OpCode::SMMUL: 132 | opcode = "smmul"; 133 | break; 134 | case OpCode::AND: 135 | opcode = "and"; 136 | break; 137 | case OpCode::EOR: 138 | opcode = "eor"; 139 | break; 140 | case OpCode::ORR: 141 | opcode = "orr"; 142 | break; 143 | case OpCode::RON: 144 | opcode = "ron"; 145 | break; 146 | case OpCode::BIC: 147 | opcode = "bic"; 148 | break; 149 | case OpCode::SDIV: 150 | opcode = "sdiv"; 151 | break; 152 | case OpCode::CMP: 153 | opcode = "cmp"; 154 | break; 155 | case OpCode::CMN: 156 | opcode = "cmn"; 157 | break; 158 | case OpCode::TST: 159 | opcode = "tst"; 160 | break; 161 | case OpCode::TEQ: 162 | opcode = "teq"; 163 | break; 164 | default: 165 | MyAssert(0); 166 | break; 167 | } 168 | if (this->HasS()) opcode += "s"; 169 | opcode += CondToString(this->cond_); 170 | outfile << "\t" << opcode << " " << (nullptr != this->rd_ ? (std::string(*this->rd_) + ", ") : "") 171 | << std::string(*this->rn_) << ", " << std::string(*this->op2_) << std::endl; 172 | } 173 | 174 | Move::~Move() {} 175 | void Move::EmitCode(std::ostream& outfile) { 176 | std::string opcode = this->is_mvn_ ? "mvn" : "mov"; 177 | if (this->HasS()) opcode += "s"; 178 | opcode += CondToString(this->cond_); 179 | outfile << "\t" << opcode << " " << std::string(*this->rd_); 180 | outfile << ", " << std::string(*this->op2_) << std::endl; 181 | } 182 | 183 | Branch::~Branch() {} 184 | bool Branch::IsCall() { 185 | // 所有的标签都要由.开头 186 | if (this->has_l_ && this->label_.size() > 0 && this->label_ != "lr" && this->label_[0] != '.') { 187 | return true; 188 | } else { 189 | return false; 190 | } 191 | } 192 | bool Branch::IsRet() { return this->has_x_ && this->label_ == "lr"; } 193 | void Branch::EmitCode(std::ostream& outfile) { 194 | std::string opcode = "b"; 195 | if (this->has_l_) opcode += "l"; 196 | // NOTE: only for bx lr 197 | if (this->has_x_) opcode += "x"; 198 | opcode += CondToString(this->cond_); 199 | outfile << "\t" << opcode << " " << this->label_ << std::endl; 200 | } 201 | 202 | LdrStr::~LdrStr() {} 203 | void LdrStr::EmitCode(std::ostream& outfile) { 204 | std::string prefix = this->opkind_ == OpKind::LDR ? "ldr" : "str"; 205 | prefix += CondToString(this->cond_) + " " + std::string(*(this->rd_)) + ", "; 206 | std::string offset = this->is_offset_imm_ ? "#" + std::to_string(offset_imm_) : std::string(*(this->offset_)); 207 | switch (this->type_) { 208 | case Type::Norm: { 209 | prefix += "[" + std::string(*(this->rn_)) + ", " + offset + "]"; 210 | break; 211 | } 212 | case Type::Pre: { 213 | prefix += "[" + std::string(*(this->rn_)) + ", " + offset + "]!"; 214 | break; 215 | } 216 | case Type::Post: { 217 | prefix += "[" + std::string(*(this->rn_)) + "], " + offset; 218 | break; 219 | } 220 | default: { 221 | MyAssert(0); 222 | break; 223 | } 224 | } 225 | outfile << "\t" << prefix << std::endl; 226 | } 227 | 228 | LdrPseudo::~LdrPseudo() {} 229 | void LdrPseudo::EmitCode(std::ostream& outfile) { 230 | // convert ldr-pseudo inst to movw&movt 231 | // https://community.arm.com/developer/ip-products/processors/b/processors-ip-blog/posts/how-to-load-constants-in-assembly-for-arm-architecture 232 | if (!this->is_imm_) { 233 | outfile << "\tmov32 " << CondToString(this->cond_) << ", " << std::string(*(this->rd_)) + ", " << this->literal_ 234 | << std::endl; 235 | } else if (0 == ((this->imm_ >> 16) & 0xFFFF)) { 236 | outfile << "\tmovw" << CondToString(this->cond_) << " " << std::string(*(this->rd_)) + ", #" 237 | << (this->imm_ & 0xFFFF) << std::endl; 238 | } else { 239 | outfile << "\tmov32 " << CondToString(this->cond_) << ", " << std::string(*(this->rd_)) + ", " << this->imm_ 240 | << std::endl; 241 | } 242 | // outfile << "\tmov32 " << std::string(*(this->rd_)) << ", " 243 | // << (this->is_imm_ ? std::to_string(this->imm_) : this->literal_) << std::endl; 244 | } 245 | PushPop::~PushPop() {} 246 | void PushPop::EmitCode(std::ostream& outfile) { 247 | MyAssert(!this->reg_list_.empty()); 248 | std::string opcode = this->opkind_ == OpKind::PUSH ? "push" : "pop"; 249 | opcode += CondToString(this->cond_); 250 | outfile << "\t" << opcode << " { " << std::string(*(this->reg_list_[0])); 251 | for (auto iter = this->reg_list_.begin() + 1; iter != this->reg_list_.end(); ++iter) { 252 | outfile << ", " << std::string(**iter); 253 | } 254 | outfile << " }" << std::endl; 255 | } 256 | 257 | } // namespace arm 258 | 259 | #undef ASSERT_ENABLE 260 | -------------------------------------------------------------------------------- /src/ssa.cpp: -------------------------------------------------------------------------------- 1 | #include "../include/ssa.h" 2 | 3 | #include 4 | 5 | #include "../include/ssa_struct.h" 6 | #define INDENT 12 7 | #define ASSERT_ENABLE 8 | #include "../include/myassert.h" 9 | 10 | void Value::KillUse(Value *val) { 11 | for (auto it = use_list_.begin(); it != use_list_.end();) { 12 | if (val == (*it)->Get()) { 13 | it = use_list_.erase(it); 14 | } else { 15 | ++it; 16 | } 17 | } 18 | } 19 | void Value::KillUse(FunctionValue *val) { KillUse(val->GetFunction()); } 20 | void Value::KillUse(SSAFunction *func) { 21 | // 删除该值在该函数中的全部使用 22 | for (auto it = use_list_.begin(); it != use_list_.end();) { 23 | auto inst = dynamic_cast((*it)->Get()); 24 | if (nullptr != inst && inst->GetParent()->GetFunction() == func) { 25 | it = use_list_.erase(it); 26 | } else { 27 | ++it; 28 | } 29 | } 30 | } 31 | void Value::ReplaceAllUseWith(Value *val) { 32 | auto uses = GetUses(); 33 | for (auto use : uses) { 34 | use->Set(val); 35 | } 36 | MyAssert(!IsUsed()); 37 | } 38 | Value::~Value() { 39 | auto uses = GetUses(); // necessary. can't use reference 40 | for (auto use : uses) { 41 | use->Set(nullptr); // necessary. when destruct a use instance, must ensure that its value_ is a valid pointer. 42 | } 43 | // 并没有删除使用它的那个user的operand 只是让operand的use中的value变为nullptr了 44 | MyAssert(!IsUsed()); 45 | } 46 | 47 | // FunctionValue::FunctionValue(FunctionType *type, const std::string &name, SSAFunction *func) : Value(type, name) { 48 | // func->BindValue(this); 49 | // } 50 | // FunctionValue::FunctionValue(const std::string &name) : Value(new Type(Type::FunctionTyID), name) {} 51 | 52 | FunctionValue::FunctionValue(const std::string &name, SSAFunction *func) 53 | : Value(new Type(Type::FunctionTyID), name), func_(func) { 54 | func->BindValue(this); 55 | } 56 | 57 | BasicBlockValue::BasicBlockValue(const std::string &name, SSABasicBlock *bb) 58 | : Value(new Type(Type::LabelTyID), name), bb_(bb) { 59 | bb->BindValue(this); 60 | } 61 | 62 | User::~User() { 63 | // MyAssert(!IsUsed()); // delete module 或者 function时 才允许仍有使用 64 | } 65 | Value *User::GetOperand(unsigned i) { 66 | MyAssert(i < GetNumOperands()); 67 | return operands_[i].Get(); 68 | } 69 | void User::RemoveOperand(unsigned i) { 70 | MyAssert(i < GetNumOperands()); 71 | operands_.erase(operands_.begin() + i); 72 | } 73 | 74 | SSAInstruction::SSAInstruction(Type *type, const std::string &name, SSABasicBlock *parent) 75 | : User(type, name), parent_(nullptr) { 76 | parent->AddInstruction(this); 77 | }; 78 | SSAInstruction::SSAInstruction(Type *type, const std::string &name, SSAInstruction *inst) 79 | : User(type, name), parent_(nullptr) { 80 | inst->parent_->AddInstruction(this, inst); 81 | }; 82 | void SSAInstruction::Remove() { GetParent()->RemoveInstruction(this); } 83 | 84 | int BinaryOperator::ComputeConstInt(int lhs, int rhs) { 85 | switch (op_) { 86 | case ADD: 87 | return lhs + rhs; 88 | case SUB: 89 | return lhs - rhs; 90 | case MUL: 91 | return lhs * rhs; 92 | case DIV: 93 | return lhs / rhs; 94 | case MOD: 95 | return lhs % rhs; 96 | default: 97 | MyAssert(0); 98 | break; 99 | } 100 | return 0; 101 | } 102 | 103 | int UnaryOperator::ComputeConstInt(int lhs) { 104 | switch (op_) { 105 | case NEG: 106 | return -lhs; 107 | case NOT: 108 | return !lhs; 109 | default: 110 | MyAssert(0); 111 | break; 112 | } 113 | return 0; 114 | } 115 | 116 | bool BranchInst::ComputeConstInt(int lhs, int rhs) { 117 | switch (cond_) { 118 | case EQ: 119 | return lhs == rhs; 120 | case NE: 121 | return lhs != rhs; 122 | case GT: 123 | return lhs > rhs; 124 | case GE: 125 | return lhs >= rhs; 126 | case LT: 127 | return lhs < rhs; 128 | case LE: 129 | return lhs <= rhs; 130 | default: 131 | MyAssert(0); 132 | return false; 133 | } 134 | } 135 | 136 | void Value::Print(std::ostream &outfile) { outfile << std::setw(INDENT) << "%" + name_; } 137 | 138 | void ConstantInt::Print(std::ostream &outfile) { outfile << std::setw(INDENT) << "#" + std::to_string(imm_); } 139 | 140 | void GlobalVariable::Print(std::ostream &outfile) { 141 | outfile << "@_glob_var_" << GetName() << " size: " << size_ << std::endl; 142 | } 143 | 144 | void UndefVariable::Print(std::ostream &outfile) { Value::Print(outfile); } 145 | 146 | void Argument::Print(std::ostream &outfile) { Value::Print(outfile); } 147 | 148 | void FunctionValue::Print(std::ostream &outfile) { outfile << std::setw(INDENT) << GetName(); } 149 | 150 | void BasicBlockValue::Print(std::ostream &outfile) { Value::Print(outfile); } 151 | 152 | void User::Print(std::ostream &outfile) { 153 | for (auto &opn : operands_) { 154 | auto val = opn.Get(); 155 | outfile << std::setw(INDENT); 156 | if (nullptr == val) { 157 | outfile << "nullptr"; 158 | } else if (dynamic_cast(val)) { 159 | outfile << "%g:" + val->GetName(); 160 | } else if (auto src_val = dynamic_cast(val)) { 161 | outfile << "#" + std::to_string(src_val->GetImm()); 162 | } else if (dynamic_cast(val) || dynamic_cast(val)) { 163 | outfile << "" + val->GetName(); 164 | } else if (auto src_val = dynamic_cast(val)) { 165 | outfile << "%a" + std::to_string(src_val->GetArgNo()) + ":" + val->GetName(); 166 | } else { 167 | outfile << "%" + val->GetName(); 168 | } 169 | } 170 | } 171 | 172 | void BinaryOperator::Print(std::ostream &outfile) { 173 | std::string op = ""; 174 | switch (op_) { 175 | case ADD: 176 | op = "add"; 177 | break; 178 | case SUB: 179 | op = "sub"; 180 | break; 181 | case MUL: 182 | op = "mul"; 183 | break; 184 | case DIV: 185 | op = "div"; 186 | break; 187 | case MOD: 188 | op = "mod"; 189 | break; 190 | default: 191 | break; 192 | } 193 | Value::Print(outfile); 194 | outfile << std::setw(INDENT) << "=" + op; 195 | User::Print(outfile); 196 | outfile << std::endl; 197 | } 198 | void UnaryOperator::Print(std::ostream &outfile) { 199 | std::string op = ""; 200 | switch (op_) { 201 | case NEG: 202 | op = "neg"; 203 | break; 204 | case NOT: 205 | op = "not"; 206 | break; 207 | default: 208 | break; 209 | } 210 | Value::Print(outfile); 211 | outfile << std::setw(INDENT) << "=" + op; 212 | User::Print(outfile); 213 | outfile << std::endl; 214 | } 215 | void BranchInst::Print(std::ostream &outfile) { 216 | std::string cond = "b"; 217 | switch (cond_) { 218 | case AL: 219 | cond += ""; 220 | break; 221 | case EQ: 222 | cond += "eq"; 223 | break; 224 | case NE: 225 | cond += "ne"; 226 | break; 227 | case GT: 228 | cond += "gt"; 229 | break; 230 | case GE: 231 | cond += "ge"; 232 | break; 233 | case LT: 234 | cond += "lt"; 235 | break; 236 | case LE: 237 | cond += "le"; 238 | break; 239 | default: 240 | break; 241 | } 242 | outfile << std::setw(INDENT) << cond; 243 | User::Print(outfile); 244 | outfile << std::endl; 245 | } 246 | void CallInst::Print(std::ostream &outfile) { 247 | std::string prefix = ""; 248 | if (!GetType()->IsVoid()) { 249 | Value::Print(outfile); 250 | prefix = "="; 251 | } 252 | prefix += "call"; 253 | outfile << std::setw(INDENT) << prefix; 254 | User::Print(outfile); 255 | outfile << std::endl; 256 | } 257 | void ReturnInst::Print(std::ostream &outfile) { 258 | outfile << std::setw(INDENT) << "return"; 259 | User::Print(outfile); 260 | outfile << std::endl; 261 | } 262 | void AllocaInst::Print(std::ostream &outfile) { 263 | outfile << std::setw(INDENT) << "alloca"; 264 | // outfile << (dynamic_cast(GetType()))->num_elements_; 265 | User::Print(outfile); 266 | outfile << std::endl; 267 | } 268 | void LoadInst::Print(std::ostream &outfile) { 269 | Value::Print(outfile); 270 | outfile << std::setw(INDENT) << "=load"; 271 | User::Print(outfile); 272 | outfile << std::endl; 273 | } 274 | void StoreInst::Print(std::ostream &outfile) { 275 | outfile << std::setw(INDENT) << "store"; 276 | User::Print(outfile); 277 | outfile << std::endl; 278 | } 279 | void MovInst::Print(std::ostream &outfile) { 280 | Value::Print(outfile); 281 | outfile << std::setw(INDENT) << "=mov"; 282 | User::Print(outfile); 283 | outfile << std::endl; 284 | } 285 | void PhiInst::Print(std::ostream &outfile) { 286 | Value::Print(outfile); 287 | outfile << std::setw(INDENT) << "=phi"; 288 | User::Print(outfile); 289 | outfile << std::endl; 290 | } 291 | 292 | #undef ASSERT_ENABLE -------------------------------------------------------------------------------- /src/Pass/dead_code_eliminate.cpp: -------------------------------------------------------------------------------- 1 | #include "../../include/Pass/dead_code_eliminate.h" 2 | 3 | #include 4 | #include 5 | 6 | #include "../../include/ssa.h" 7 | #include "../../include/ssa_struct.h" 8 | #define ASSERT_ENABLE 9 | #include "../../include/myassert.h" 10 | 11 | // #define DEBUG_DEAD_CODE_ELIMINATE_PROCESS 12 | // #define DEBUG_DEAD_STORE_ELIMINATE_PROCESS 13 | 14 | void DeadCodeEliminate::Run() { 15 | auto m = dynamic_cast(*(this->m_)); 16 | MyAssert(nullptr != m); 17 | DeleteDeadFunc(m); 18 | FindNoSideEffectFunc(m, no_side_effect_funcs); 19 | for (auto func : m->GetFuncList()) { 20 | DeleteDeadInst(func); 21 | func->MaintainCallFunc(); // 有可能删除call语句 22 | DeleteDeadStore(func); 23 | } 24 | DeleteDeadFunc(m); 25 | } 26 | 27 | void DeadCodeEliminate::DeleteDeadFunc(SSAModule* m) { 28 | #ifdef DEBUG_DEAD_CODE_ELIMINATE_PROCESS 29 | std::cout << "Try To Remove Function: " << std::endl; 30 | #endif 31 | std::unordered_set worklist; 32 | for (auto func : m->GetFuncList()) { 33 | if ("main" == func->GetFuncName()) continue; 34 | worklist.insert(func); 35 | } 36 | while (!worklist.empty()) { 37 | auto func = *worklist.begin(); 38 | worklist.erase(func); 39 | if (!func->IsCalled()) { 40 | // 应该把该函数调用的函数加入工作表 41 | for (auto call_func : func->GetCallFuncList()) { 42 | if ("main" == call_func->GetFuncName()) continue; 43 | worklist.insert(call_func); 44 | } 45 | // 说明该函数没被调用过 是dead function可以被删除 应该维护的信息全交由Remove函数完成 46 | #ifdef DEBUG_DEAD_CODE_ELIMINATE_PROCESS 47 | std::cout << " Remove Function: " << func->GetFuncName() << std::endl; 48 | #endif 49 | func->Remove(); 50 | delete func; 51 | } 52 | } 53 | } 54 | 55 | bool DeadCodeEliminate::IsSideEffect(Value* val) { 56 | auto inst_val = dynamic_cast(val); 57 | return IsSideEffect(inst_val); 58 | } 59 | bool DeadCodeEliminate::IsSideEffect(SSAInstruction* inst) { 60 | if (nullptr == inst) return true; 61 | // 除callinst外 如果本身无定值[no used]视为有副作用 62 | if (dynamic_cast(inst) || dynamic_cast(inst) || dynamic_cast(inst) || 63 | dynamic_cast(inst) || dynamic_cast(inst)) { 64 | return false; 65 | } else if (auto call_inst = dynamic_cast(inst)) { 66 | // 如果call语句无副作用 即便没有定值 也可删除 67 | auto func_val = dynamic_cast(call_inst->GetOperand(0)); 68 | MyAssert(nullptr != func_val); 69 | if (no_side_effect_funcs.find(func_val->GetFunction()) != no_side_effect_funcs.end()) return false; 70 | } 71 | return true; 72 | } 73 | 74 | void DeadCodeEliminate::DeleteDeadInst(SSAFunction* func) { 75 | #ifdef DEBUG_DEAD_CODE_ELIMINATE_PROCESS 76 | std::cout << "Try To Remove Instruction in function: " << func->GetFuncName() << std::endl; 77 | #endif 78 | // 没有使用过的一个定值value 如果其定值语句没有副作用 就可删除 79 | std::unordered_set worklist; 80 | for (auto bb : func->GetBasicBlocks()) { 81 | for (auto inst : bb->GetInstList()) { 82 | // 把有定值的 无副作用的语句加入到工作表中 有的指令是一次定值(在ssa.h中指定了[used]的) 有的不是([no used]) 83 | if (!IsSideEffect(inst)) worklist.insert({inst}); 84 | } 85 | } 86 | 87 | while (!worklist.empty()) { 88 | auto inst = *worklist.begin(); 89 | auto bb = inst->GetParent(); 90 | worklist.erase(inst); 91 | if (inst->IsUsed()) continue; 92 | #ifdef DEBUG_DEAD_CODE_ELIMINATE_PROCESS 93 | std::cout << " remove: "; 94 | inst->Print(std::cout); 95 | #endif 96 | // 其使用可能优化 97 | for (auto& use : inst->GetOperands()) { 98 | auto src_inst = dynamic_cast(use.Get()); 99 | if (!IsSideEffect(src_inst)) { 100 | worklist.insert(src_inst); 101 | } 102 | } 103 | bb->RemoveInstruction(inst); // FIXME 只是从指令列表中移除 并未释放内存 104 | delete inst; // delete会删除inst的所有操作数 移除其操作数对应的使用 还会维护所有被使用信息 105 | } 106 | } 107 | 108 | void DeadCodeEliminate::RemoveFromNoSideEffectFuncs(SSAFunction* func, 109 | std::unordered_set& no_side_effect_funcs) { 110 | // 如果已经删了说明已经访问过直接返回 111 | if (no_side_effect_funcs.find(func) == no_side_effect_funcs.end()) return; 112 | // 先把func删了 113 | no_side_effect_funcs.erase(func); 114 | // 再把func的每个caller都删了 115 | for (auto use : func->GetValue()->GetUses()) { 116 | auto call_inst = dynamic_cast(use->GetUser()); 117 | MyAssert(nullptr != call_inst); 118 | auto caller = call_inst->GetParent()->GetFunction(); 119 | // no_side_effect_funcs.erase(caller); 120 | RemoveFromNoSideEffectFuncs(caller, no_side_effect_funcs); 121 | } 122 | } 123 | 124 | void DeadCodeEliminate::FindNoSideEffectFunc(SSAModule* m, std::unordered_set& no_side_effect_funcs) { 125 | // NOTE: 这里并没有把副作用的信息记录到函数中 126 | // 没有副作用的函数为 1.函数自身没有对数组类型参数和全局量有赋值(store)行为 2.同时没有调用有副作用的函数 127 | // 具体来说 如果函数pointer类型的argument的使用没有store语句 用了的globalvariable的使用也只有load语句即满足第一点 128 | no_side_effect_funcs.clear(); 129 | for (auto func : m->GetFuncList()) { 130 | no_side_effect_funcs.insert(func); 131 | } 132 | 133 | // 每个builtin函数都是有副作用的 134 | for (auto builtin_func : m->GetBuiltinFuncList()) { 135 | no_side_effect_funcs.insert(builtin_func); 136 | RemoveFromNoSideEffectFuncs(builtin_func, no_side_effect_funcs); 137 | } 138 | 139 | for (auto func : m->GetFuncList()) { 140 | if (no_side_effect_funcs.find(func) == no_side_effect_funcs.end()) continue; 141 | bool has_side_effect = false; 142 | for (Argument* arg : func->GetValue()->GetArgList()) { 143 | for (Use* use : arg->GetUses()) { 144 | if (nullptr != dynamic_cast(use->GetUser())) goto setflag; 145 | } 146 | } 147 | for (GlobalVariable* glo : func->GetUsedGlobVarList()) { 148 | for (Use* use : glo->GetUses()) { 149 | auto inst = dynamic_cast(use->GetUser()); 150 | MyAssert(nullptr != inst); 151 | if (func == inst->GetParent()->GetFunction()) { 152 | if (nullptr != dynamic_cast(inst)) goto setflag; 153 | } 154 | } 155 | } 156 | continue; 157 | setflag: 158 | has_side_effect = true; 159 | // propagate to caller 160 | RemoveFromNoSideEffectFuncs(func, no_side_effect_funcs); 161 | } 162 | #ifdef DEBUG_DEAD_CODE_ELIMINATE_PROCESS 163 | std::cout << "No side effect functions: "; 164 | for (auto func : no_side_effect_funcs) { 165 | std::cout << func->GetFuncName() << " "; 166 | } 167 | std::cout << std::endl; 168 | #endif 169 | } 170 | 171 | void DeadCodeEliminate::DeleteDeadStore(SSAFunction* func) { 172 | #ifdef DEBUG_DEAD_STORE_ELIMINATE_PROCESS 173 | std::cout << "Dead Store Eliminate for Function: " << func->GetFuncName() << std::endl; 174 | #endif 175 | 176 | for (auto bb : func->GetBasicBlocks()) { 177 | #ifdef DEBUG_DEAD_STORE_ELIMINATE_PROCESS 178 | std::cout << " BB: " << bb->GetLabel() << std::endl; 179 | #endif 180 | 181 | for (auto it = bb->GetInstList().begin(); it != bb->GetInstList().end(); ++it) { 182 | auto store_inst = dynamic_cast(*it); 183 | if (nullptr != store_inst) { 184 | auto it2 = ++it; 185 | --it; 186 | for (; it2 != bb->GetInstList().end(); ++it2) { 187 | // 如果是一条load指令 并且操作同一块内存区域 除非两个都是立即数且不相同 否则直接break 188 | if (auto src_inst = dynamic_cast(*it2)) { 189 | if (store_inst->GetNumOperands() - 1 == src_inst->GetNumOperands() && 190 | src_inst->GetOperand(0) == store_inst->GetOperand(1)) { 191 | if (store_inst->GetNumOperands() == 3) { 192 | auto constint = dynamic_cast(store_inst->GetOperand(2)); 193 | auto constint2 = dynamic_cast(src_inst->GetOperand(1)); 194 | if (nullptr != constint && nullptr != constint2 && constint->GetImm() != constint2->GetImm()) { 195 | continue; 196 | } 197 | } 198 | break; 199 | } 200 | } 201 | // 如果是一条call指令 并且调用的是有副作用的函数 直接break 202 | else if (auto src_inst = dynamic_cast(*it2)) { 203 | if (!no_side_effect_funcs.count(dynamic_cast(src_inst->GetOperand(0))->GetFunction())) 204 | break; 205 | } 206 | // 如果是一条操作同一内存位置的store指令 则前面这条store可删除 207 | else if (auto src_inst = dynamic_cast(*it2)) { 208 | if (store_inst->GetNumOperands() == src_inst->GetNumOperands() && 209 | src_inst->GetOperand(1) == store_inst->GetOperand(1)) { 210 | if (store_inst->GetNumOperands() == 3) { 211 | auto constint = dynamic_cast(store_inst->GetOperand(2)); 212 | auto constint2 = dynamic_cast(src_inst->GetOperand(2)); 213 | if (store_inst->GetOperand(2) == src_inst->GetOperand(2) || 214 | (nullptr != constint && nullptr != constint2 && constint->GetImm() == constint2->GetImm())) { 215 | #ifdef DEBUG_DEAD_STORE_ELIMINATE_PROCESS 216 | std::cout << " find dead store: ", store_inst->Print(std::cout); 217 | std::cout << " ==> ", src_inst->Print(std::cout); 218 | #endif 219 | 220 | it = bb->GetInstList().erase(it); 221 | --it; 222 | delete store_inst; 223 | break; 224 | } 225 | } else { 226 | #ifdef DEBUG_DEAD_STORE_ELIMINATE_PROCESS 227 | std::cout << " find dead store: ", store_inst->Print(std::cout); 228 | std::cout << " ==> ", src_inst->Print(std::cout); 229 | #endif 230 | 231 | it = bb->GetInstList().erase(it); 232 | --it; 233 | delete store_inst; 234 | break; 235 | } 236 | } 237 | } 238 | } 239 | } 240 | } 241 | } 242 | } -------------------------------------------------------------------------------- /src/Pass/ir_liveness_analysis.cpp: -------------------------------------------------------------------------------- 1 | #include "../../include/Pass/ir_liveness_analysis.h" 2 | #define ASSERT_ENABLE 3 | #include "../../include/myassert.h" 4 | 5 | std::pair, std::vector> GetDefUsePtr(IR *ir, bool consider) { 6 | std::vector def; 7 | std::vector use; 8 | 9 | auto process_opn = [&use, &consider](Opn *op) { 10 | if (nullptr == op) return; 11 | if (op->type_ == Opn::Type::Imm || op->type_ == Opn::Type::Label || op->type_ == Opn::Type::Func || 12 | op->type_ == Opn::Type::Null) 13 | return; 14 | if (op->type_ == Opn::Type::Array) { 15 | if (consider) use.push_back(op); 16 | if (op->offset_->type_ == Opn::Type::Var) 17 | if (consider || 0 != op->offset_->scope_id_) use.push_back(op->offset_); 18 | } else { // var 19 | if (!consider && 0 == op->scope_id_) return; 20 | use.push_back(op); 21 | } 22 | }; 23 | 24 | auto process_res = [&def, &use, &consider](Opn *res) { 25 | if (nullptr == res) return; 26 | if (res->type_ == Opn::Type::Label || res->type_ == Opn::Type::Func || res->type_ == Opn::Type::Null) return; 27 | if (res->type_ == Opn::Type::Array) { 28 | if (consider) def.push_back(res); 29 | if (res->offset_->type_ == Opn::Type::Var) 30 | if (consider || 0 != res->offset_->scope_id_) use.push_back(res->offset_); 31 | } else { // var 32 | if (!consider && 0 == res->scope_id_) return; 33 | def.push_back(res); 34 | } 35 | }; 36 | 37 | if (ir->op_ == IR::OpKind::ADD || ir->op_ == IR::OpKind::SUB || ir->op_ == IR::OpKind::MUL || 38 | ir->op_ == IR::OpKind::DIV || ir->op_ == IR::OpKind::MOD) { 39 | process_opn(&(ir->opn1_)); 40 | process_opn(&(ir->opn2_)); 41 | process_res(&(ir->res_)); 42 | } else if (ir->op_ == IR::OpKind::NOT || ir->op_ == IR::OpKind::NEG) { 43 | process_opn(&(ir->opn1_)); 44 | process_res(&(ir->res_)); 45 | } else if (ir->op_ == IR::OpKind::LABEL) { 46 | return {def, use}; 47 | } else if (ir->op_ == IR::OpKind::PARAM) { 48 | process_opn(&(ir->opn1_)); 49 | } else if (ir->op_ == IR::OpKind::CALL) { 50 | process_res(&(ir->res_)); 51 | } else if (ir->op_ == IR::OpKind::RET) { 52 | process_opn(&(ir->opn1_)); 53 | } else if (ir->op_ == IR::OpKind::GOTO) { 54 | return {def, use}; 55 | } else if (ir->op_ == IR::OpKind::ASSIGN) { 56 | process_opn(&(ir->opn1_)); 57 | process_res(&(ir->res_)); 58 | } else if (ir->op_ == IR::OpKind::JEQ || ir->op_ == IR::OpKind::JNE || ir->op_ == IR::OpKind::JLT || 59 | ir->op_ == IR::OpKind::JLE || ir->op_ == IR::OpKind::JGT || ir->op_ == IR::OpKind::JGE) { 60 | process_opn(&(ir->opn1_)); 61 | process_opn(&(ir->opn2_)); 62 | } else if (ir->op_ == IR::OpKind::VOID) { 63 | return {def, use}; 64 | } else if (ir->op_ == IR::OpKind::ASSIGN_OFFSET) { 65 | process_opn(&(ir->opn1_)); 66 | process_res(&(ir->res_)); 67 | } else if (ir->op_ == IR::OpKind::PHI) { 68 | for (auto &arg : ir->phi_args_) { 69 | process_opn(&(arg)); 70 | } 71 | process_res(&(ir->res_)); 72 | } else if (ir->op_ == IR::OpKind::ALLOCA) { 73 | process_res(&(ir->opn1_)); 74 | } else if (ir->op_ == IR::OpKind::DECLARE) { 75 | process_res(&(ir->opn1_)); 76 | } else { 77 | MyAssert(0); 78 | } 79 | 80 | return {def, use}; 81 | } 82 | 83 | //变量形式:变量名_#scope_id 84 | std::pair, std::vector> GetDefUse(IR *ir, bool consider) { 85 | std::vector def; 86 | std::vector use; 87 | 88 | auto process_opn = [&use, &consider](Opn *op) { 89 | if (nullptr == op) return; 90 | if (op->type_ == Opn::Type::Imm || op->type_ == Opn::Type::Label || op->type_ == Opn::Type::Func || 91 | op->type_ == Opn::Type::Null) 92 | return; 93 | if (op->type_ == Opn::Type::Array) { 94 | if (consider) use.push_back(op->name_ + "." + std::to_string(op->scope_id_)); 95 | if (op->offset_->type_ == Opn::Type::Var) 96 | if (consider || 0 != op->offset_->scope_id_) 97 | use.push_back(op->offset_->name_ + "." + std::to_string(op->offset_->scope_id_)); 98 | } else { // var 99 | if (!consider && 0 == op->scope_id_) return; 100 | use.push_back(op->name_ + "." + std::to_string(op->scope_id_)); 101 | } 102 | }; 103 | 104 | auto process_res = [&def, &use, &consider](Opn *res) { 105 | if (nullptr == res) return; 106 | if (res->type_ == Opn::Type::Label || res->type_ == Opn::Type::Func || res->type_ == Opn::Type::Null) return; 107 | if (res->type_ == Opn::Type::Array) { 108 | if (consider) def.push_back(res->name_ + "." + std::to_string(res->scope_id_)); 109 | if (res->offset_->type_ == Opn::Type::Var) 110 | if (consider || 0 != res->offset_->scope_id_) 111 | use.push_back(res->offset_->name_ + "." + std::to_string(res->offset_->scope_id_)); 112 | } else { 113 | if (!consider && 0 == res->scope_id_) return; 114 | def.push_back(res->name_ + "." + std::to_string(res->scope_id_)); 115 | } 116 | }; 117 | 118 | if (ir->op_ == IR::OpKind::ADD || ir->op_ == IR::OpKind::SUB || ir->op_ == IR::OpKind::MUL || 119 | ir->op_ == IR::OpKind::DIV || ir->op_ == IR::OpKind::MOD) { 120 | process_opn(&(ir->opn1_)); 121 | process_opn(&(ir->opn2_)); 122 | process_res(&(ir->res_)); 123 | } else if (ir->op_ == IR::OpKind::NOT || ir->op_ == IR::OpKind::NEG) { 124 | process_opn(&(ir->opn1_)); 125 | process_res(&(ir->res_)); 126 | } else if (ir->op_ == IR::OpKind::LABEL) { 127 | return {def, use}; 128 | } else if (ir->op_ == IR::OpKind::PARAM) { 129 | process_opn(&(ir->opn1_)); 130 | } else if (ir->op_ == IR::OpKind::CALL) { 131 | process_res(&(ir->res_)); 132 | } else if (ir->op_ == IR::OpKind::RET) { 133 | process_opn(&(ir->opn1_)); 134 | } else if (ir->op_ == IR::OpKind::GOTO) { 135 | return {def, use}; 136 | } else if (ir->op_ == IR::OpKind::ASSIGN) { 137 | process_opn(&(ir->opn1_)); 138 | process_res(&(ir->res_)); 139 | } else if (ir->op_ == IR::OpKind::JEQ || ir->op_ == IR::OpKind::JNE || ir->op_ == IR::OpKind::JLT || 140 | ir->op_ == IR::OpKind::JLE || ir->op_ == IR::OpKind::JGT || ir->op_ == IR::OpKind::JGE) { 141 | process_opn(&(ir->opn1_)); 142 | process_opn(&(ir->opn2_)); 143 | } else if (ir->op_ == IR::OpKind::VOID) { 144 | return {def, use}; 145 | } else if (ir->op_ == IR::OpKind::ASSIGN_OFFSET) { 146 | process_opn(&(ir->opn1_)); 147 | process_res(&(ir->res_)); 148 | } else if (ir->op_ == IR::OpKind::PHI) { 149 | for (auto &arg : ir->phi_args_) { 150 | process_opn(&(arg)); 151 | } 152 | process_res(&(ir->res_)); 153 | } else if (ir->op_ == IR::OpKind::ALLOCA) { 154 | process_res(&(ir->opn1_)); 155 | } else if (ir->op_ == IR::OpKind::DECLARE) { 156 | process_res(&(ir->opn1_)); 157 | } else { 158 | MyAssert(0); 159 | } 160 | 161 | return {def, use}; 162 | } 163 | 164 | bool isFound(std::unordered_set &inbb, Opn *inir) { 165 | for (auto i : inbb) { 166 | if (i->name_ == inir->name_ && i->scope_id_ == inir->scope_id_) { 167 | return true; 168 | } 169 | } 170 | return false; 171 | } 172 | 173 | void IRLivenessAnalysis::GetDefUse4Func(IRFunction *f, bool consider) { 174 | for (auto bb : f->bb_list_) { 175 | // bb->livein_.clear(); 176 | // bb->liveout_.clear(); 177 | bb->def_.clear(); 178 | bb->use_.clear(); 179 | 180 | for (auto ir : bb->ir_list_) { 181 | auto [def, use] = GetDefUse(ir, consider); 182 | 183 | for (auto &u : use) { 184 | bb->use_.insert(u); 185 | } 186 | 187 | for (auto &d : def) { 188 | bb->def_.insert(d); 189 | } 190 | } 191 | // bb->livein_ = bb->use_; 192 | } // for bb 193 | } 194 | 195 | void IRLivenessAnalysis::Run4Func(IRFunction *f) { 196 | for (auto bb : f->bb_list_) { 197 | bb->livein_.clear(); 198 | bb->liveout_.clear(); 199 | bb->def_.clear(); 200 | bb->use_.clear(); 201 | 202 | for (auto ir : bb->ir_list_) { 203 | auto [def, use] = GetDefUse(ir); 204 | 205 | for (auto &u : use) { 206 | if (bb->def_.find(u) == 207 | bb->def_.end()) { // 如果在use之前没有def,则将其插入use中,说明该变量在bb中首次出现是以use的形式出现 208 | bb->use_.insert(u); 209 | } 210 | } // for use 211 | 212 | for (auto &d : def) { 213 | if (bb->use_.find(d) == 214 | bb->use_.end()) { // 如果在def之前没有use,则将其插入def中,说明该变量首次出现是以def形式出现 215 | bb->def_.insert(d); 216 | } 217 | } // for def 218 | } // for ir 219 | bb->livein_ = bb->use_; 220 | } // for bb 221 | 222 | bool changed = true; 223 | while (changed) { 224 | changed = false; 225 | for (auto bb : f->bb_list_) { 226 | std::unordered_set new_out; 227 | 228 | for (auto succ : bb->succ_) { // 每个bb的liveout是其后继bb的livein的并集 229 | new_out.insert(succ->livein_.begin(), succ->livein_.end()); 230 | } 231 | 232 | if (new_out != bb->liveout_) { 233 | changed = true; 234 | bb->liveout_ = new_out; 235 | 236 | for (auto s : bb->liveout_) { // IN[B] = use[B]U(out[B] - def[B]) 237 | if (bb->def_.find(s) == bb->def_.end()) { 238 | bb->livein_.insert(s); 239 | } 240 | } 241 | } 242 | } // for bb 243 | } // while changed 244 | } 245 | 246 | void IRLivenessAnalysis::Run() { 247 | auto m = dynamic_cast(*(this->m_)); 248 | 249 | MyAssert(nullptr != m); 250 | 251 | for (auto func : m->func_list_) { 252 | // std::cout << "analysis func:" << func->name_ << std::endl; 253 | this->Run4Func(func); 254 | } 255 | } 256 | 257 | #undef MyAssert 258 | #ifdef ASSERT_ENABLE 259 | #undef ASSERT_ENABLE 260 | #endif -------------------------------------------------------------------------------- /src/ir.cpp: -------------------------------------------------------------------------------- 1 | #include "../include/ir.h" 2 | 3 | #include 4 | #include 5 | 6 | #include "../include/ast.h" 7 | #include "parser.hpp" // EQOP RELOP 8 | #define TYPE_STRING(type) ((type) == INT ? "int" : ((type) == VOID ? "void" : "undefined")) 9 | #define PRINT_IR(op_name) \ 10 | outfile << "(" << std::setw(15) << op_name << std::setw(15) << std::string(opn1_) << std::setw(15) \ 11 | << std::string(opn2_) << std::setw(15) << std::string(res_) << ")" << std::endl; 12 | 13 | #define ASSERT_ENABLE 14 | #include "../include/myassert.h" 15 | 16 | namespace ir { 17 | 18 | Scopes gScopes; 19 | FuncTable gFuncTable; 20 | // std::vector gIRList; 21 | 22 | const int kIntWidth = 4; 23 | 24 | void PrintScopes(std::ostream &outfile) { 25 | for (auto &symbol_table : gScopes) { 26 | symbol_table.Print(outfile); 27 | } 28 | } 29 | 30 | void PrintFuncTable(std::ostream &outfile) { 31 | outfile << "FuncTable:" << std::endl; 32 | outfile << std::setw(10) << "name" << std::setw(10) << "ret_type" << std::setw(10) << "size" << std::setw(10) 33 | << "scope_id" << std::endl; 34 | for (auto &symbol : gFuncTable) { 35 | outfile << std::setw(10) << symbol.first; 36 | symbol.second.Print(outfile); 37 | } 38 | } 39 | 40 | void SymbolTableItem::Print(std::ostream &outfile) { 41 | outfile << std::setw(10) << (this->is_array_ ? "√" : "×") << std::setw(10) << (this->is_const_ ? "√" : "×"); 42 | if (this->is_array_) { 43 | outfile << std::setw(10) << "shape: "; 44 | for (const auto &shape : this->shape_) { 45 | outfile << "[" << shape << "]"; 46 | } 47 | } 48 | if (!this->initval_.empty()) { 49 | } 50 | outfile << std::endl; 51 | } 52 | 53 | void FuncTableItem::Print(std::ostream &outfile) { 54 | outfile << std::setw(10) << TYPE_STRING(this->ret_type_) << std::setw(10) << this->scope_id_ << std::endl; 55 | } 56 | 57 | void Scope::Print(std::ostream &outfile) { 58 | outfile << "Scope:" << std::endl 59 | << " scope_id: " << this->scope_id_ << " parent_scope_id: " << this->parent_scope_id_ << std::endl; 60 | if (!this->symbol_table_.empty()) { 61 | outfile << std::setw(10) << "name" << std::setw(10) << "is_array" << std::setw(10) << "is_const" << std::endl; 62 | } 63 | for (auto &symbol : this->symbol_table_) { 64 | outfile << std::setw(10) << symbol.first; 65 | symbol.second.Print(outfile); 66 | } 67 | } 68 | 69 | bool Scope::IsSubScope(int scope_id) { 70 | MyAssert(scope_id >= 0); 71 | // <0无意义 72 | int sid = this->scope_id_; 73 | while (-1 != sid) { 74 | if (sid == scope_id) { 75 | return true; 76 | } else { 77 | sid = gScopes[sid].parent_scope_id_; 78 | } 79 | } 80 | return false; 81 | } 82 | 83 | int FindSymbol(int scope_id, std::string name, SymbolTableItem *&res_symbol_item) { 84 | while (-1 != scope_id) { 85 | auto ¤t_scope = gScopes[scope_id]; 86 | auto ¤t_symbol_table = current_scope.symbol_table_; 87 | auto symbol_iter = current_symbol_table.find(name); 88 | if (symbol_iter == current_symbol_table.end()) { 89 | scope_id = current_scope.parent_scope_id_; 90 | } else { 91 | res_symbol_item = &((*symbol_iter).second); 92 | return scope_id; 93 | } 94 | } 95 | res_symbol_item = nullptr; 96 | return -1; 97 | }; 98 | 99 | static const std::string kTempPrefix = "temp-"; 100 | static const std::string kLabelPrefix = ".label"; 101 | std::string NewTemp() { 102 | static int i = 0; 103 | return kTempPrefix + std::to_string(i++); 104 | } 105 | 106 | std::string NewLabel() { 107 | static int i = 0; 108 | return kLabelPrefix + std::to_string(i++); 109 | } 110 | 111 | Opn::Opn(const Opn &opn) : type_(opn.type_), imm_num_(opn.imm_num_), scope_id_(opn.scope_id_), ssa_id_(opn.ssa_id_) { 112 | name_ = opn.name_; 113 | if (nullptr != opn.offset_) offset_ = new Opn(*opn.offset_); 114 | } 115 | Opn &Opn::operator=(const Opn &opn) { 116 | type_ = opn.type_, imm_num_ = opn.imm_num_, scope_id_ = opn.scope_id_, ssa_id_ = opn.ssa_id_; 117 | name_ = opn.name_; 118 | if (nullptr != offset_) { 119 | delete offset_; 120 | offset_ = nullptr; 121 | } 122 | if (nullptr != opn.offset_) offset_ = new Opn(*opn.offset_); 123 | return *this; 124 | } 125 | Opn::Opn(Opn &&opn) 126 | : type_(opn.type_), imm_num_(opn.imm_num_), scope_id_(opn.scope_id_), offset_(opn.offset_), ssa_id_(opn.ssa_id_) { 127 | name_ = std::move(opn.name_); 128 | } 129 | Opn &Opn::operator=(Opn &&opn) { 130 | type_ = opn.type_, imm_num_ = opn.imm_num_, scope_id_ = opn.scope_id_, ssa_id_ = opn.ssa_id_; 131 | if (nullptr != offset_) { 132 | delete offset_; 133 | offset_ = nullptr; 134 | } 135 | offset_ = opn.offset_; 136 | name_ = std::move(opn.name_); 137 | return *this; 138 | } 139 | IR::OpKind GetOpKind(int op, bool reverse) { 140 | if (reverse) { 141 | switch (op) { 142 | case EQ: 143 | return IR::OpKind::JNE; 144 | case NE: 145 | return IR::OpKind::JEQ; 146 | case LT: 147 | return IR::OpKind::JGE; 148 | case LE: 149 | return IR::OpKind::JGT; 150 | case GT: 151 | return IR::OpKind::JLE; 152 | case GE: 153 | return IR::OpKind::JLT; 154 | default: 155 | return IR::OpKind::VOID; 156 | } 157 | } else { 158 | switch (op) { 159 | case EQ: 160 | return IR::OpKind::JEQ; 161 | case NE: 162 | return IR::OpKind::JNE; 163 | case LT: 164 | return IR::OpKind::JLT; 165 | case LE: 166 | return IR::OpKind::JLE; 167 | case GT: 168 | return IR::OpKind::JGT; 169 | case GE: 170 | return IR::OpKind::JGE; 171 | default: 172 | return IR::OpKind::VOID; 173 | } 174 | } 175 | return IR::OpKind::VOID; 176 | } 177 | std::string Opn::GetCompName() { // 对于全局变量直接返回原name_ 对于局部变量返回复合name 178 | if (type_ == Type::Imm || type_ == Type::Null) MyAssert(0); 179 | if (type_ == Type::Label || type_ == Type::Func || scope_id_ == 0) return name_; 180 | auto res = scope_id_ == -1 ? name_ : name_ + "." + std::to_string(scope_id_); 181 | return ssa_id_ == -1 ? res : res + "." + std::to_string(ssa_id_); 182 | } 183 | Opn::operator std::string() { 184 | switch (type_) { 185 | case Type::Var: { 186 | if (scope_id_ == 0) return name_; 187 | auto ret = scope_id_ == -1 ? name_ : name_ + "." + std::to_string(scope_id_); 188 | return ssa_id_ == -1 ? ret : ret + "." + std::to_string(ssa_id_); 189 | } 190 | case Type::Array: { 191 | auto ret = scope_id_ == -1 ? name_ : name_ + "." + std::to_string(scope_id_); 192 | ret += (ssa_id_ == -1 ? "" : "." + std::to_string(ssa_id_)); 193 | if (scope_id_ == 0) ret = name_; 194 | return nullptr == offset_ ? ret : ret + "[" + std::string(*offset_) + "]"; 195 | } 196 | default: { 197 | return name_; 198 | } 199 | } 200 | } 201 | 202 | IR::IR(IR &&ir) : op_(ir.op_) { 203 | opn1_ = std::move(ir.opn1_), opn2_ = std::move(ir.opn2_), res_ = std::move(ir.res_); 204 | phi_args_ = std::move(ir.phi_args_); 205 | } 206 | IR &IR::operator=(IR &&ir) { 207 | opn1_ = std::move(ir.opn1_), opn2_ = std::move(ir.opn2_), res_ = std::move(ir.res_); 208 | phi_args_ = std::move(ir.phi_args_); 209 | return *this; 210 | } 211 | 212 | void IR::PrintIR(std::ostream &outfile) { 213 | switch (op_) { 214 | case IR::OpKind::ADD: 215 | PRINT_IR("add"); 216 | break; 217 | case IR::OpKind::SUB: 218 | PRINT_IR("sub"); 219 | break; 220 | case IR::OpKind::MUL: 221 | PRINT_IR("mul"); 222 | break; 223 | case IR::OpKind::DIV: 224 | PRINT_IR("div"); 225 | break; 226 | case IR::OpKind::MOD: 227 | PRINT_IR("mod"); 228 | break; 229 | case IR::OpKind::NEG: 230 | PRINT_IR("neg"); 231 | break; 232 | case IR::OpKind::NOT: 233 | PRINT_IR("not"); 234 | break; 235 | case IR::OpKind::RET: 236 | PRINT_IR("return"); 237 | break; 238 | case IR::OpKind::ASSIGN: 239 | PRINT_IR("assign"); 240 | break; 241 | case IR::OpKind::LABEL: 242 | PRINT_IR("label"); 243 | break; 244 | case IR::OpKind::GOTO: 245 | PRINT_IR("goto"); 246 | break; 247 | case IR::OpKind::JEQ: 248 | PRINT_IR("jeq"); 249 | break; 250 | case IR::OpKind::JNE: 251 | PRINT_IR("jne"); 252 | break; 253 | case IR::OpKind::JLT: 254 | PRINT_IR("jlt"); 255 | break; 256 | case IR::OpKind::JLE: 257 | PRINT_IR("jle"); 258 | break; 259 | case IR::OpKind::JGT: 260 | PRINT_IR("jgt"); 261 | break; 262 | case IR::OpKind::JGE: 263 | PRINT_IR("jge"); 264 | break; 265 | case IR::OpKind::PARAM: 266 | PRINT_IR("param"); 267 | break; 268 | case IR::OpKind::CALL: 269 | PRINT_IR("call"); 270 | break; 271 | case IR::OpKind::ASSIGN_OFFSET: 272 | PRINT_IR("=[]"); 273 | break; 274 | case IR::OpKind::PHI: 275 | outfile << "(" << std::setw(15) << "phi"; 276 | for (auto &arg : phi_args_) outfile << std::setw(15) << std::string(arg); 277 | outfile << std::setw(15) << std::string(res_) << ")" << std::endl; 278 | break; 279 | case IR::OpKind::ALLOCA: 280 | PRINT_IR("alloca"); 281 | break; 282 | case IR::OpKind::DECLARE: 283 | PRINT_IR("declare"); 284 | break; 285 | default: 286 | MyAssert(0); 287 | break; 288 | } 289 | } 290 | 291 | void SemanticError(int line_no, const std::string &&error_msg) { 292 | std::cerr << "语义错误 at line " << line_no << " : " << error_msg << std::endl; 293 | exit(255); 294 | } 295 | 296 | void RuntimeError(const std::string &&error_msg) { 297 | std::cerr << "运行时错误: " << error_msg << std::endl; 298 | exit(255); 299 | } 300 | 301 | } // namespace ir 302 | 303 | #undef ASSERT_ENABLE 304 | -------------------------------------------------------------------------------- /src/Pass/instruction_combining.cpp: -------------------------------------------------------------------------------- 1 | #include "../../include/Pass/instruction_combining.h" 2 | 3 | static bool isSameOpn(ir::Opn opn1, ir::Opn opn2) { 4 | if (opn1.type_ == opn2.type_ && opn1.type_ == ir::Opn::Type::Var) { 5 | if (opn1.name_ == opn2.name_ && opn1.scope_id_ == opn2.scope_id_) { 6 | return true; 7 | } 8 | return false; 9 | } else if (opn1.type_ == opn2.type_ && opn1.type_ == ir::Opn::Type::Array) { 10 | //先不考虑数组的情况,这里什么也没有 11 | } else if (opn1.type_ == opn2.type_ && opn1.type_ == ir::Opn::Type::Imm) { 12 | return opn1.imm_num_ == opn2.imm_num_; 13 | } 14 | 15 | return false; 16 | } 17 | 18 | bool isImm(ir::Opn opn) { return opn.type_ == ir::Opn::Type::Imm; } 19 | 20 | void Instruction_Combining::Run() { 21 | auto m = dynamic_cast(*m_); 22 | 23 | for (auto func : m->func_list_) { 24 | for (auto bb : func->bb_list_) { 25 | for (auto iter = bb->ir_list_.begin(); iter != bb->ir_list_.end() - 1; ++iter) { 26 | auto ir = *iter; 27 | auto ir_next = *(iter + 1); 28 | 29 | if (ir::IR::OpKind::ADD == ir->op_) { 30 | if (ir::IR::OpKind::ADD == ir_next->op_) { 31 | if (isSameOpn(ir->res_, ir_next->opn1_)) { 32 | if (isImm(ir_next->opn2_)) { 33 | if (isImm(ir->opn1_)) { 34 | int opn_num = ir_next->opn2_.imm_num_ + ir->opn1_.imm_num_; 35 | auto new_opn = ir::Opn(ir::Opn::Type::Imm, opn_num); 36 | auto new_ir = new ir::IR(ir::IR::OpKind::ADD, new_opn, ir->opn2_, ir_next->res_); 37 | 38 | *(iter + 1) = new_ir; 39 | // bb->ir_list_.erase(iter + 1); 40 | 41 | } else if (isImm(ir->opn2_)) { 42 | int opn_num = ir_next->opn2_.imm_num_ + ir->opn2_.imm_num_; 43 | auto new_opn = ir::Opn(ir::Opn::Type::Imm, opn_num); 44 | auto new_ir = new ir::IR(ir::IR::OpKind::ADD, new_opn, ir->opn1_, ir_next->res_); 45 | 46 | *(iter + 1) = new_ir; 47 | 48 | // bb->ir_list_.erase(iter + 1); 49 | } 50 | } 51 | } else if (isSameOpn(ir->res_, ir_next->opn2_)) { 52 | if (isImm(ir_next->opn1_)) { 53 | if (isImm(ir->opn1_)) { 54 | int opn_num = ir_next->opn1_.imm_num_ + ir->opn1_.imm_num_; 55 | auto new_opn = ir::Opn(ir::Opn::Type::Imm, opn_num); 56 | auto new_ir = new ir::IR(ir::IR::OpKind::ADD, new_opn, ir->opn2_, ir_next->res_); 57 | 58 | *(iter + 1) = new_ir; 59 | 60 | // bb->ir_list_.erase(iter + 1); 61 | } else if (isImm(ir->opn2_)) { 62 | int opn_num = ir_next->opn1_.imm_num_ + ir->opn2_.imm_num_; 63 | auto new_opn = ir::Opn(ir::Opn::Type::Imm, opn_num); 64 | auto new_ir = new ir::IR(ir::IR::OpKind::ADD, new_opn, ir->opn1_, ir_next->res_); 65 | 66 | *(iter + 1) = new_ir; 67 | 68 | // bb->ir_list_.erase(iter + 1); 69 | } 70 | } 71 | } 72 | } else if (ir::IR::OpKind::SUB == ir_next->op_) { 73 | if (isSameOpn(ir->res_, ir_next->opn1_)) { 74 | if (isSameOpn(ir_next->opn2_, ir->opn1_)) { 75 | auto new_ir = new ir::IR(ir::IR::OpKind::ASSIGN, ir->opn2_, ir_next->res_); 76 | 77 | *(iter + 1) = new_ir; 78 | 79 | } else if (isSameOpn(ir_next->opn2_, ir->opn2_)) { 80 | auto new_ir = new ir::IR(ir::IR::OpKind::ASSIGN, ir->opn1_, ir_next->res_); 81 | 82 | *(iter + 1) = new_ir; 83 | } 84 | } else if (isSameOpn(ir->res_, ir_next->opn2_)) { 85 | if (isSameOpn(ir_next->opn2_, ir->opn1_)) { 86 | auto new_ir = new ir::IR(ir::IR::OpKind::NEG, ir->opn2_, ir_next->res_); 87 | 88 | *(iter + 1) = new_ir; 89 | 90 | } else if (isSameOpn(ir_next->opn2_, ir->opn1_)) { 91 | auto new_ir = new ir::IR(ir::IR::OpKind::NEG, ir->opn1_, ir_next->res_); 92 | 93 | *(iter + 1) = new_ir; 94 | } 95 | } 96 | } 97 | } else if (ir::IR::OpKind::SUB == ir->op_) { 98 | if (ir::IR::OpKind::SUB == ir_next->op_) { 99 | if (isSameOpn(ir->res_, ir_next->opn1_)) { 100 | if (isImm(ir_next->opn2_)) { 101 | if (isImm(ir->opn1_)) { 102 | int opn_num = ir->opn1_.imm_num_ - ir_next->opn2_.imm_num_; 103 | auto new_opn = ir::Opn(ir::Opn::Type::Imm, opn_num); 104 | auto new_ir = new ir::IR(ir::IR::OpKind::SUB, new_opn, ir->opn2_, ir_next->res_); 105 | 106 | *(iter + 1) = new_ir; 107 | 108 | // bb->ir_list_.erase(iter + 1); 109 | } else if (isImm(ir->opn2_)) { 110 | int opn_num = ir_next->opn2_.imm_num_ + ir->opn2_.imm_num_; 111 | auto new_opn = ir::Opn(ir::Opn::Type::Imm, opn_num); 112 | auto new_ir = new ir::IR(ir::IR::OpKind::SUB, ir->opn1_, new_opn, ir_next->res_); 113 | 114 | *(iter + 1) = new_ir; 115 | 116 | // bb->ir_list_.erase(iter + 1); 117 | } 118 | } 119 | } 120 | } else if (ir::IR::OpKind::ADD == ir_next->op_) { 121 | if (isSameOpn(ir->res_, ir_next->opn1_)) { 122 | if (isSameOpn(ir->opn2_, ir_next->opn2_)) { 123 | auto new_ir = new ir::IR(ir::IR::OpKind::ASSIGN, ir->opn1_, ir_next->res_); 124 | 125 | *(iter + 1) = new_ir; 126 | } 127 | } else if (isSameOpn(ir->res_, ir_next->opn2_)) { 128 | if (isSameOpn(ir->opn2_, ir_next->opn1_)) { 129 | auto new_ir = new ir::IR(ir::IR::OpKind::ASSIGN, ir->opn1_, ir_next->res_); 130 | 131 | *(iter + 1) = new_ir; 132 | } 133 | } 134 | } 135 | } else if (ir::IR::OpKind::MUL == ir->op_) { 136 | if (ir::IR::OpKind::MUL == ir_next->op_) { 137 | if (isSameOpn(ir->res_, ir_next->opn1_)) { 138 | if (isImm(ir_next->opn2_)) { 139 | if (isImm(ir->opn1_)) { 140 | int opn_num = ir_next->opn2_.imm_num_ * ir->opn1_.imm_num_; 141 | auto new_opn = ir::Opn(ir::Opn::Type::Imm, opn_num); 142 | auto new_ir = new ir::IR(ir::IR::OpKind::MUL, new_opn, ir->opn2_, ir_next->res_); 143 | 144 | *(iter + 1) = new_ir; 145 | 146 | // bb->ir_list_.erase(iter + 1); 147 | } else if (isImm(ir->opn2_)) { 148 | int opn_num = ir_next->opn2_.imm_num_ * ir->opn2_.imm_num_; 149 | auto new_opn = ir::Opn(ir::Opn::Type::Imm, opn_num); 150 | auto new_ir = new ir::IR(ir::IR::OpKind::MUL, new_opn, ir->opn1_, ir_next->res_); 151 | 152 | *(iter + 1) = new_ir; 153 | 154 | // bb->ir_list_.erase(iter + 1); 155 | } 156 | } 157 | } else if (isSameOpn(ir->res_, ir_next->opn2_)) { 158 | if (isImm(ir_next->opn1_)) { 159 | if (isImm(ir->opn1_)) { 160 | int opn_num = ir_next->opn1_.imm_num_ * ir->opn1_.imm_num_; 161 | auto new_opn = ir::Opn(ir::Opn::Type::Imm, opn_num); 162 | auto new_ir = new ir::IR(ir::IR::OpKind::MUL, new_opn, ir->opn2_, ir_next->res_); 163 | 164 | *(iter + 1) = new_ir; 165 | 166 | // bb->ir_list_.erase(iter + 1); 167 | } else if (isImm(ir->opn2_)) { 168 | int opn_num = ir_next->opn1_.imm_num_ * ir->opn2_.imm_num_; 169 | auto new_opn = ir::Opn(ir::Opn::Type::Imm, opn_num); 170 | auto new_ir = new ir::IR(ir::IR::OpKind::MUL, new_opn, ir->opn1_, ir_next->res_); 171 | 172 | *(iter + 1) = new_ir; 173 | 174 | // bb->ir_list_.erase(iter + 1); 175 | } 176 | } 177 | } 178 | } else if (ir::IR::OpKind::DIV == ir_next->op_) { 179 | if (isSameOpn(ir->res_, ir_next->opn1_)) { 180 | if (isSameOpn(ir_next->opn2_, ir->opn1_)) { 181 | auto new_ir = new ir::IR(ir::IR::OpKind::ASSIGN, ir->opn2_, ir_next->res_); 182 | 183 | *(iter + 1) = new_ir; 184 | 185 | } else if (isSameOpn(ir_next->opn2_, ir->opn2_)) { 186 | auto new_ir = new ir::IR(ir::IR::OpKind::ASSIGN, ir->opn1_, ir_next->res_); 187 | 188 | *(iter + 1) = new_ir; 189 | } 190 | // }else if(isSameOpn(ir->res_, ir_next->opn2_)){ 191 | // if(isSameOpn(ir_next->opn2_, ir->opn1_)){ 192 | // auto new_ir = new ir::IR(ir::IR::OpKind::NEG, ir->opn2_, ir_next->res_); 193 | 194 | // *(iter + 1) = new_ir; 195 | // }else if(isSameOpn(ir_next->opn2_, ir->opn1_)){ 196 | // auto new_ir = new ir::IR(ir::IR::OpKind::NEG, ir->opn1_, ir_next->res_); 197 | 198 | // *(iter + 1) = new_ir; 199 | // } 200 | } 201 | } 202 | } else if (ir::IR::OpKind::DIV == ir->op_) { 203 | if (ir::IR::OpKind::DIV == ir_next->op_) { 204 | if (isSameOpn(ir->res_, ir_next->opn1_)) { 205 | if (isImm(ir_next->opn2_)) { 206 | if (isImm(ir->opn1_)) { 207 | int opn_num = ir->opn1_.imm_num_ / ir_next->opn2_.imm_num_; 208 | auto new_opn = ir::Opn(ir::Opn::Type::Imm, opn_num); 209 | auto new_ir = new ir::IR(ir::IR::OpKind::DIV, new_opn, ir->opn2_, ir_next->res_); 210 | 211 | *(iter + 1) = new_ir; 212 | 213 | // bb->ir_list_.erase(iter + 1); 214 | } else if (isImm(ir->opn2_)) { 215 | int opn_num = ir_next->opn2_.imm_num_ * ir->opn2_.imm_num_; 216 | auto new_opn = ir::Opn(ir::Opn::Type::Imm, opn_num); 217 | auto new_ir = new ir::IR(ir::IR::OpKind::DIV, ir->opn1_, new_opn, ir_next->res_); 218 | 219 | *(iter + 1) = new_ir; 220 | 221 | // bb->ir_list_.erase(iter + 1); 222 | } 223 | } 224 | } 225 | } else if (ir::IR::OpKind::MUL == ir_next->op_) { 226 | if (isSameOpn(ir->res_, ir_next->opn1_)) { 227 | if (isSameOpn(ir->opn2_, ir_next->opn2_)) { 228 | auto new_ir = new ir::IR(ir::IR::OpKind::ASSIGN, ir->opn1_, ir_next->res_); 229 | 230 | *(iter + 1) = new_ir; 231 | } 232 | } else if (isSameOpn(ir->res_, ir_next->opn2_)) { 233 | if (isSameOpn(ir->opn2_, ir_next->opn1_)) { 234 | auto new_ir = new ir::IR(ir::IR::OpKind::ASSIGN, ir->opn1_, ir_next->res_); 235 | 236 | *(iter + 1) = new_ir; 237 | } 238 | } 239 | } 240 | } else if (ir::IR::OpKind::NEG == ir->op_) { 241 | if (ir::IR::OpKind::NEG == ir_next->op_) { 242 | if (isSameOpn(ir->res_, ir_next->opn1_)) { 243 | auto new_ir = new ir::IR(ir::IR::OpKind::ASSIGN, ir->opn1_, ir_next->res_); 244 | 245 | *(iter + 1) = new_ir; 246 | } 247 | } 248 | } 249 | } 250 | } 251 | } 252 | } -------------------------------------------------------------------------------- /src/Pass/reach_define.cpp: -------------------------------------------------------------------------------- 1 | #include "../../include/Pass/reach_define.h" 2 | #define ASSERT_ENABLE 3 | #include 4 | 5 | #include "../../include/myassert.h" 6 | 7 | // #define PRINT_USE_DEF_CHAIN 8 | // #define PRINT_SET 9 | 10 | void print_map(std::unordered_map> umap) { 11 | for (auto iter : umap) { 12 | std::cout << iter.first << ": " << iter.second.size() << std::endl; 13 | for (auto ir : iter.second) { 14 | ir->PrintIR(); 15 | } 16 | } 17 | } 18 | 19 | void print_use_def_chain(IRModule *m) { 20 | for (auto func : m->func_list_) { 21 | for (auto bb : func->bb_list_) { 22 | for (auto map_ir : bb->use_def_chains_) { 23 | for (auto map_opn : map_ir) { 24 | auto opn = map_opn.first; 25 | 26 | std::cout << "变量:" << opn->name_ + "_#" + std::to_string(opn->scope_id_) << "的使用-定值链" << std::endl; 27 | 28 | for (auto ir : map_opn.second) { 29 | ir->PrintIR(); 30 | } 31 | } 32 | std::cout << "\n"; 33 | } 34 | } 35 | } 36 | } 37 | 38 | void print_set(IRModule *m) { 39 | for (auto func : m->func_list_) { 40 | for (auto bb : func->bb_list_) { 41 | std::cout << "BasicBlock: " << bb->IndexInFunc() << std::endl; 42 | std::cout << "reach_in_: \n"; 43 | for (auto ir : bb->reach_in_) { 44 | ir->PrintIR(); 45 | } 46 | std::cout << "reach_out_: \n"; 47 | for (auto ir : bb->reach_out_) { 48 | ir->PrintIR(); 49 | } 50 | std::cout << "gen_: \n"; 51 | for (auto ir : bb->gen_) { 52 | ir->PrintIR(); 53 | } 54 | std::cout << "kill_: \n"; 55 | for (auto ir : bb->kill_) { 56 | ir->PrintIR(); 57 | } 58 | } 59 | } 60 | } 61 | 62 | void ReachDefine::Run() { 63 | auto m = dynamic_cast(*m_); 64 | 65 | MyAssert(nullptr != m); 66 | 67 | for (auto func : m->func_list_) { 68 | for (auto bb : func->bb_list_) { 69 | for (auto ir : bb->ir_list_) { 70 | if (ir->res_.type_ == ir::Opn::Type::Var && ir->res_.scope_id_ != 0) { 71 | std::string var_name = ir->res_.name_ + "_#" + std::to_string(ir->res_.scope_id_); 72 | if (0 == func->def_pre_var_.count(var_name)) { 73 | std::unordered_set temp_set; 74 | temp_set.insert(ir); 75 | func->def_pre_var_.emplace(var_name, temp_set); 76 | } else { 77 | func->def_pre_var_[var_name].insert(ir); 78 | } 79 | } 80 | } 81 | // print_map(func->def_pre_var_); 82 | } 83 | } 84 | 85 | for (auto func : m->func_list_) { 86 | // std::cout << "analysis func:" << func->name_ << std::endl; 87 | Run4Func(func); 88 | } 89 | 90 | // 计算每个程序点处的使用-定值链 91 | GetUseDefChain(m); 92 | 93 | #ifdef PRINT_USE_DEF_CHAIN 94 | print_use_def_chain(m); 95 | #endif 96 | 97 | #ifdef PRINT_SET 98 | print_set(m); 99 | #endif 100 | } 101 | 102 | bool isSameOpn(ir::Opn opn1, ir::Opn opn2) { 103 | if (opn1.type_ == opn2.type_) { 104 | if (ir::Opn::Type::Var == opn1.type_) { 105 | // std::cout << "opn1:" << opn1.name_ + "_#" + std::to_string(opn1.scope_id_) + "\n"; 106 | // std::cout << "opn2:" << opn2.name_ + "_#" + std::to_string(opn2.scope_id_) + "\n"; 107 | return opn1.name_ == opn2.name_ && opn1.scope_id_ == opn2.scope_id_; 108 | } 109 | return false; 110 | } 111 | 112 | return false; 113 | } 114 | 115 | ir::IR *finddef(IRBasicBlock *bb, ir::IR *ir, ir::Opn *opn) { 116 | auto it = find(bb->ir_list_.begin(), bb->ir_list_.end(), ir); 117 | 118 | for (auto iter = it - 1; iter != bb->ir_list_.begin() - 1; --iter) { 119 | auto def = *iter; 120 | 121 | if (isSameOpn(def->res_, *opn)) { 122 | // printf("/*************************\n"); 123 | return def; 124 | } 125 | } 126 | 127 | return nullptr; 128 | } 129 | 130 | void ReachDefine::GetUseDefChain(IRModule *m) { 131 | for (auto func : m->func_list_) { 132 | for (auto bb : func->bb_list_) { 133 | bb->use_def_chains_.clear(); 134 | for (auto ir : bb->ir_list_) { 135 | std::unordered_map> map_this_ir; 136 | auto process_opn = [&bb, &map_this_ir](ir::IR *ir, ir::Opn *opn) { 137 | if (opn->type_ != ir::Opn::Type::Var) return; 138 | if (opn->scope_id_ == 0) return; 139 | ir::IR *def_opn = finddef(bb, ir, opn); 140 | std::unordered_set opn_set; 141 | 142 | if (nullptr != def_opn) { 143 | opn_set.insert(def_opn); 144 | map_this_ir.emplace(opn, opn_set); 145 | } else { 146 | for (auto in : bb->reach_in_) { 147 | if (isSameOpn(in->res_, *opn)) { 148 | opn_set.insert(in); 149 | } 150 | } 151 | map_this_ir.emplace(opn, opn_set); 152 | } 153 | }; 154 | if (ir::IR::OpKind::ADD == ir->op_ || ir::IR::OpKind::SUB == ir->op_ || ir::IR::OpKind::MUL == ir->op_ || 155 | ir::IR::OpKind::DIV == ir->op_ || ir::IR::OpKind::MOD == ir->op_) { 156 | map_this_ir.clear(); 157 | process_opn(ir, &(ir->opn1_)); 158 | process_opn(ir, &(ir->opn2_)); 159 | 160 | bb->use_def_chains_.push_back(map_this_ir); 161 | } else if (ir::IR::OpKind::NOT == ir->op_ || ir::IR::OpKind::NEG == ir->op_) { 162 | map_this_ir.clear(); 163 | process_opn(ir, &(ir->opn1_)); 164 | 165 | bb->use_def_chains_.push_back(map_this_ir); 166 | } else if (ir::IR::OpKind::LABEL == ir->op_) { 167 | map_this_ir.clear(); 168 | bb->use_def_chains_.push_back(map_this_ir); 169 | } else if (ir::IR::OpKind::PARAM == ir->op_) { 170 | map_this_ir.clear(); 171 | process_opn(ir, &(ir->opn1_)); 172 | 173 | bb->use_def_chains_.push_back(map_this_ir); 174 | } else if (ir::IR::OpKind::CALL == ir->op_) { 175 | map_this_ir.clear(); 176 | 177 | bb->use_def_chains_.push_back(map_this_ir); 178 | } else if (ir::IR::OpKind::RET == ir->op_) { 179 | map_this_ir.clear(); 180 | // TODO: 关于return语句返回立即数的处理 181 | if (ir->opn1_.type_ == ir::Opn::Type::Var || ir->opn1_.type_ == ir::Opn::Type::Array) { 182 | process_opn(ir, &(ir->opn1_)); 183 | } 184 | bb->use_def_chains_.push_back(map_this_ir); 185 | } else if (ir::IR::OpKind::GOTO == ir->op_) { 186 | map_this_ir.clear(); 187 | bb->use_def_chains_.push_back(map_this_ir); 188 | } else if (ir::IR::OpKind::ASSIGN == ir->op_) { 189 | map_this_ir.clear(); 190 | process_opn(ir, &(ir->opn1_)); 191 | bb->use_def_chains_.push_back(map_this_ir); 192 | } else if (ir::IR::OpKind::JEQ == ir->op_ || ir::IR::OpKind::JNE == ir->op_ || ir::IR::OpKind::JLT == ir->op_ || 193 | ir::IR::OpKind::JLE == ir->op_ || ir::IR::OpKind::JGT == ir->op_ || ir::IR::OpKind::JGE == ir->op_) { 194 | map_this_ir.clear(); 195 | process_opn(ir, &(ir->opn1_)); 196 | process_opn(ir, &(ir->opn2_)); 197 | 198 | bb->use_def_chains_.push_back(map_this_ir); 199 | } else if (ir::IR::OpKind::VOID == ir->op_) { 200 | map_this_ir.clear(); 201 | bb->use_def_chains_.push_back(map_this_ir); 202 | } else if (ir::IR::OpKind::ASSIGN_OFFSET == ir->op_) { 203 | map_this_ir.clear(); 204 | 205 | process_opn(ir, &(ir->opn1_)); 206 | bb->use_def_chains_.push_back(map_this_ir); 207 | } else if (ir::IR::OpKind::PHI == ir->op_) { 208 | map_this_ir.clear(); 209 | bb->use_def_chains_.push_back(map_this_ir); 210 | printf("我就不信我这个pass会有PHI\n"); 211 | } else if (ir::IR::OpKind::ALLOCA == ir->op_) { 212 | map_this_ir.clear(); 213 | bb->use_def_chains_.push_back(map_this_ir); 214 | } else if (ir::IR::OpKind::DECLARE == ir->op_) { 215 | map_this_ir.clear(); 216 | bb->use_def_chains_.push_back(map_this_ir); 217 | } else { 218 | MyAssert(0); 219 | } 220 | } 221 | } 222 | } 223 | } 224 | 225 | void ReachDefine::Run4Func(IRFunction *f) { 226 | for (auto bb : f->bb_list_) { 227 | bb->gen_.clear(); 228 | bb->kill_.clear(); 229 | bb->reach_in_.clear(); 230 | bb->reach_out_.clear(); 231 | 232 | // 反向遍历bb的ir_list,对于得到的gen和kill 233 | // 如果kill中的元素不在bb的gen中,说明它未被后面的生成语句取代,所以才可以加入到bb的kill中 234 | // 而对于gen中的元素,如果被后面的kill杀死,则就不能加进去 235 | for (auto iter = bb->ir_list_.rbegin(); iter != bb->ir_list_.rend(); ++iter) { 236 | auto ir = *iter; 237 | 238 | auto [gen, kill] = GetGenKill(ir, f); 239 | 240 | for (auto k : kill) { 241 | if (bb->gen_.find(k) == bb->gen_.end()) { 242 | bb->kill_.insert(k); 243 | } 244 | } 245 | 246 | for (auto g : gen) { 247 | if (bb->kill_.find(g) == bb->kill_.end()) { 248 | bb->gen_.insert(g); 249 | } 250 | } 251 | 252 | bb->reach_out_ = bb->gen_; 253 | } 254 | } 255 | 256 | bool changed = true; 257 | while (changed) { 258 | changed = false; 259 | for (auto bb : f->bb_list_) { 260 | std::unordered_set new_in; 261 | 262 | for (auto pred : bb->pred_) { 263 | new_in.insert(pred->reach_out_.begin(), pred->reach_out_.end()); 264 | } 265 | 266 | if (new_in != bb->reach_in_) { 267 | changed = true; 268 | bb->reach_in_ = new_in; 269 | 270 | for (auto s : bb->reach_in_) { 271 | if (bb->kill_.find(s) == bb->kill_.end()) { 272 | bb->reach_out_.insert(s); 273 | } 274 | } 275 | for (auto g : bb->gen_) { 276 | bb->reach_out_.insert(g); 277 | } 278 | } 279 | } 280 | } 281 | } 282 | 283 | std::pair, std::unordered_set> ReachDefine::GetGenKill(ir::IR *ir, 284 | IRFunction *func) { 285 | std::unordered_set gen; 286 | std::unordered_set kill; 287 | 288 | if (ir->res_.scope_id_ == 0) return {gen, kill}; 289 | 290 | if (ir::IR::OpKind::ADD == ir->op_ || ir::IR::OpKind::SUB == ir->op_ || ir::IR::OpKind::MUL == ir->op_ || 291 | ir::IR::OpKind::DIV == ir->op_ || ir::IR::OpKind::MOD == ir->op_) { 292 | gen.insert(ir); 293 | 294 | std::string res_str = ir->res_.name_ + "_#" + std::to_string(ir->res_.scope_id_); 295 | for (auto m : func->def_pre_var_[res_str]) { 296 | if (ir != m) { 297 | kill.insert(m); 298 | } 299 | } 300 | } else if (ir::IR::OpKind::NOT == ir->op_ || ir::IR::OpKind::NEG == ir->op_) { 301 | gen.insert(ir); 302 | 303 | std::string res_str = ir->res_.name_ + "_#" + std::to_string(ir->res_.scope_id_); 304 | 305 | for (auto m : func->def_pre_var_[res_str]) { 306 | if (ir != m) { 307 | kill.insert(m); 308 | } 309 | } 310 | } else if (ir::IR::OpKind::LABEL == ir->op_) { 311 | return {gen, kill}; 312 | } else if (ir::IR::OpKind::PARAM == ir->op_) { 313 | return {gen, kill}; 314 | } else if (ir::IR::OpKind::CALL == ir->op_) { 315 | return {gen, kill}; 316 | } else if (ir::IR::OpKind::RET == ir->op_) { 317 | return {gen, kill}; 318 | } else if (ir::IR::OpKind::GOTO == ir->op_) { 319 | return {gen, kill}; 320 | } else if (ir::IR::OpKind::ASSIGN == ir->op_) { 321 | gen.insert(ir); 322 | std::string res_str = ir->res_.name_ + "_#" + std::to_string(ir->res_.scope_id_); 323 | 324 | for (auto m : func->def_pre_var_[res_str]) { 325 | if (ir != m) { 326 | kill.insert(m); 327 | } 328 | } 329 | } else if (ir::IR::OpKind::JEQ == ir->op_ || ir::IR::OpKind::JNE == ir->op_ || ir::IR::OpKind::JLT == ir->op_ || 330 | ir::IR::OpKind::JLE == ir->op_ || ir::IR::OpKind::JGT == ir->op_ || ir::IR::OpKind::JGE == ir->op_) { 331 | return {gen, kill}; 332 | } else if (ir::IR::OpKind::VOID == ir->op_) { 333 | return {gen, kill}; 334 | } else if (ir::IR::OpKind::ASSIGN_OFFSET == ir->op_) { 335 | gen.insert(ir); 336 | std::string res_str = ir->res_.name_ + "_#" + std::to_string(ir->res_.scope_id_); 337 | 338 | for (auto m : func->def_pre_var_[res_str]) { 339 | if (ir != m) { 340 | kill.insert(m); 341 | } 342 | } 343 | } else if (ir::IR::OpKind::PHI == ir->op_) { 344 | printf("我就不信我这个pass会有PHI\n"); 345 | } else if (ir::IR::OpKind::ALLOCA == ir->op_) { 346 | return {gen, kill}; 347 | } else if (ir::IR::OpKind::DECLARE == ir->op_) { 348 | return {gen, kill}; 349 | } else { 350 | MyAssert(0); 351 | } 352 | 353 | return {gen, kill}; 354 | } 355 | 356 | #undef MyAssert 357 | #ifdef ASSERT_ENABLE 358 | #undef ASSERT_ENABLE 359 | #endif -------------------------------------------------------------------------------- /include/arm.h: -------------------------------------------------------------------------------- 1 | #ifndef __ARM_H__ 2 | #define __ARM_H__ 3 | #include 4 | #include 5 | #include 6 | class ArmBasicBlock; 7 | 8 | namespace arm { 9 | // ref: https://en.wikipedia.org/wiki/Calling_convention#ARM_(A32) 10 | // ref: https://developer.arm.com/documentation/ihi0042/j/ 11 | // ref: https://developer.arm.com/documentation/ddi0406/latest 12 | 13 | enum ArmReg { 14 | // args and return value (caller saved) 15 | r0, 16 | r1, 17 | r2, 18 | r3, 19 | // local variables (callee saved) 20 | r4, 21 | r5, 22 | r6, 23 | r7, 24 | r8, 25 | r9, 26 | r10, 27 | r11, 28 | // special purposes 29 | r12, 30 | r13, 31 | r14, 32 | r15, 33 | // some aliases 34 | fp = r11, // frame pointer (omitted), allocatable 35 | ip = r12, // ipc scratch register, used in some instructions (caller saved) 36 | sp = r13, // stack pointer 37 | lr = r14, // link register (caller saved) 38 | pc = r15, // program counter 39 | }; 40 | 41 | class Instruction; 42 | 43 | class Reg { 44 | private: 45 | std::unordered_set used_inst_set; 46 | 47 | public: 48 | // ArmReg reg_; 49 | int reg_id_; 50 | Reg(int reg_id) : reg_id_(reg_id) {} 51 | Reg(ArmReg armreg) : reg_id_(static_cast(armreg)) {} 52 | explicit operator std::string() { return "r" + std::to_string(reg_id_); } 53 | // NOTE: only used for final check. 54 | void AddUsedInst(Instruction* inst) { used_inst_set.insert(inst); } 55 | const std::unordered_set& GetUsedInsts() const { return used_inst_set; } 56 | const unsigned GetUsedInstNum() const { return used_inst_set.size(); } 57 | }; 58 | 59 | class Shift { 60 | public: 61 | enum class OpCode { 62 | ASR, // arithmetic right 63 | LSL, // logic left 64 | LSR, // logic right 65 | ROR, // rotate right 66 | RRX // rotate right one bit with extend 67 | }; 68 | OpCode opcode_ = OpCode::LSL; 69 | bool is_imm_ = true; 70 | int shift_imm_ = 0; 71 | Reg* shift_reg_ = nullptr; 72 | 73 | Shift() {} 74 | Shift(OpCode opcode, Reg* shift_reg) : opcode_(opcode), is_imm_(false), shift_reg_(shift_reg) {} 75 | Shift(OpCode opcode, int shift) : opcode_(opcode), shift_imm_(shift) {} 76 | bool IsNone() { return opcode_ == OpCode::LSL && is_imm_ && 0 == shift_imm_; } 77 | explicit operator std::string(); 78 | void AddUsedInst(Instruction* inst) { 79 | if (!is_imm_) shift_reg_->AddUsedInst(inst); 80 | } 81 | }; 82 | 83 | // Operand2 is a flexible second operand. 84 | // Operand2 can be a: 85 | // - Constant. 86 | // - Register with optional shift. Reg {, } or Reg, LSL/LSR/ASR/ROR Rs 87 | class Operand2 { 88 | public: 89 | bool is_imm_ = true; 90 | int imm_num_ = 0; 91 | Reg* reg_ = nullptr; 92 | Shift* shift_ = nullptr; 93 | Operand2(int imm_num) : imm_num_(imm_num) {} 94 | Operand2(Reg* reg) : is_imm_(false), reg_(reg) {} 95 | Operand2(Reg* reg, Shift* shift) : is_imm_(false), reg_(reg), shift_(shift) {} 96 | explicit operator std::string(); 97 | static bool CheckImm8m(int imm); 98 | bool HasShift() { return /*!is_imm_ &&*/ nullptr != shift_; } 99 | bool HasUsedAsOp2(Reg* reg) { return reg_ == reg; } 100 | bool HasUsedAsOp2WithoutShift(Reg* reg) { return !HasShift() && HasUsedAsOp2(reg); } 101 | void AddUsedInst(Instruction* inst) { 102 | if (!is_imm_) reg_->AddUsedInst(inst); 103 | if (nullptr != shift_) shift_->AddUsedInst(inst); 104 | } 105 | }; 106 | 107 | enum class Cond { 108 | AL, // 无条件执行,通常省略 109 | EQ, 110 | NE, 111 | GT, 112 | GE, 113 | LT, 114 | LE, 115 | }; 116 | 117 | Cond GetOppositeCond(Cond cond); 118 | std::string CondToString(Cond cond); 119 | 120 | class Instruction { 121 | public: 122 | ArmBasicBlock* parent_; 123 | Cond cond_ = Cond::AL; 124 | bool IsAL() { return cond_ == Cond::AL; } 125 | Instruction(Cond cond, ArmBasicBlock* parent, bool push_back = true); 126 | Instruction(ArmBasicBlock* parent, bool push_back = true); 127 | Instruction(Instruction* inst); 128 | virtual ~Instruction() = default; 129 | virtual void EmitCode(std::ostream& outfile = std::clog) = 0; 130 | virtual void AddUsedInst(){}; 131 | 132 | // 这几个函数其实只实际作用于Binaryinst Move和LdrStr语句 为了方便才提升到Instruction中 133 | virtual bool HasUsedAsOp2(Reg* reg) { return false; } 134 | virtual bool HasUsedAsOp2WithoutShift(Reg* reg) { return false; } 135 | virtual void ReplaceOp2With(Operand2* op2) {} 136 | }; 137 | 138 | // BinaryInstruction: {S}{Cond} {Rd,} Rn, 139 | class BinaryInst : public Instruction { 140 | public: 141 | enum class OpCode { 142 | ADD, // 减法 143 | SUB, // 减法 144 | RSB, // 反向减法 working for imm - Rn 145 | MUL, // Operand2 can only be Rs. 146 | SMMUL, // Used for 除常数优化 147 | 148 | // Logical 149 | AND, // 与 150 | EOR, // 异或 151 | ORR, // 或 152 | RON, // 或非 153 | BIC, // 位清零 154 | 155 | SDIV, // 有符号除法 156 | // UDIV, // 无符号除法 157 | 158 | // no Rd. omit S. 159 | CMP, // 比较 160 | CMN, // 与负数比较 161 | TST, // 测试 162 | TEQ, // 相等测试 163 | 164 | // convert shift-inst to mov-inst 165 | }; 166 | OpCode opcode_; 167 | bool has_s_ = false; // only mean if opcode has char 'S'. don't mean the instruction whether updates CPSR or not. 168 | // for CMP, CMN, TST, TEQ 169 | Reg* rd_ = nullptr; // Note: rd may nullptr 170 | Reg* rn_; 171 | Operand2* op2_; 172 | 173 | BinaryInst(OpCode opcode, bool has_s, Cond cond, Reg* rd, Reg* rn, Operand2* op2, ArmBasicBlock* parent) 174 | : Instruction(cond, parent), opcode_(opcode), has_s_(has_s), rd_(rd), rn_(rn), op2_(op2) { 175 | AddUsedInst(); 176 | } 177 | BinaryInst(OpCode opcode, Reg* rd, Reg* rn, Operand2* op2, ArmBasicBlock* parent) 178 | : Instruction(parent), opcode_(opcode), rd_(rd), rn_(rn), op2_(op2) { 179 | AddUsedInst(); 180 | } 181 | 182 | // for TST TEQ CMP CMN: no rd. omit S. 183 | BinaryInst(OpCode opcode, Cond cond, Reg* rn, Operand2* op2, ArmBasicBlock* parent) 184 | : Instruction(cond, parent), opcode_(opcode), rn_(rn), op2_(op2) { 185 | AddUsedInst(); 186 | } 187 | BinaryInst(OpCode opcode, Reg* rn, Operand2* op2, ArmBasicBlock* parent) 188 | : Instruction(parent), opcode_(opcode), rn_(rn), op2_(op2) { 189 | AddUsedInst(); 190 | } 191 | 192 | virtual ~BinaryInst(); 193 | 194 | bool HasS() { return has_s_; } 195 | virtual void EmitCode(std::ostream& outfile = std::clog) override; 196 | virtual void AddUsedInst() override { rn_->AddUsedInst(this), op2_->AddUsedInst(this); } 197 | virtual bool HasUsedAsOp2(Reg* reg) override { return op2_->HasUsedAsOp2(reg); } 198 | virtual bool HasUsedAsOp2WithoutShift(Reg* reg) override { return op2_->HasUsedAsOp2WithoutShift(reg); } 199 | virtual void ReplaceOp2With(Operand2* op2) override { op2_ = op2; } 200 | }; 201 | 202 | // Move: MOV{S}{Cond} Rd, 203 | class Move : public Instruction { 204 | public: 205 | bool is_mvn_; 206 | bool has_s_ = false; 207 | Reg* rd_; 208 | Operand2* op2_; 209 | 210 | Move(bool has_s, Cond cond, Reg* rd, Operand2* op2, ArmBasicBlock* parent, bool is_mvn = false, bool push_back = true) 211 | : Instruction(cond, parent, push_back), has_s_(has_s), rd_(rd), op2_(op2), is_mvn_(is_mvn) { 212 | AddUsedInst(); 213 | } 214 | Move(Reg* rd, Operand2* op2, ArmBasicBlock* parent, bool is_mvn = false, bool push_back = true) 215 | : Instruction(parent, push_back), rd_(rd), op2_(op2), is_mvn_(is_mvn) { 216 | AddUsedInst(); 217 | } 218 | Move(Reg* rd, Operand2* op2, Instruction* inst, bool is_mvn = false) 219 | : Instruction(inst), rd_(rd), op2_(op2), is_mvn_(is_mvn) { 220 | AddUsedInst(); 221 | } 222 | virtual ~Move(); 223 | 224 | bool HasS() { return has_s_; } 225 | virtual void EmitCode(std::ostream& outfile = std::clog) override; 226 | virtual void AddUsedInst() override { op2_->AddUsedInst(this); } 227 | virtual bool HasUsedAsOp2(Reg* reg) override { return op2_->HasUsedAsOp2(reg); } 228 | virtual bool HasUsedAsOp2WithoutShift(Reg* reg) override { return op2_->HasUsedAsOp2WithoutShift(reg); } 229 | virtual void ReplaceOp2With(Operand2* op2) override { op2_ = op2; } 230 | }; 231 | 232 | // Branch: B{L}{Cond}