diff --git a/.clangd b/.clangd new file mode 100644 index 0000000000000000000000000000000000000000..adae8425d78d69ec3dcf5505959d72f6fae89942 --- /dev/null +++ b/.clangd @@ -0,0 +1,2 @@ +CompileFlags: + Add: [-std=c++17] \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 4566726651b6fc69bd7fedcd2287322b9fceb2d7..a2f0a85591e62fbcc93b674761152ad956d3a946 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,6 @@ cmake_minimum_required( VERSION 3.8 ) +include(CheckCXXCompilerFlag) + project(CMINUSF) set(CMAKE_C_FLAGS "${CMAKE_CXX_FLAGS} -std=c99") @@ -9,6 +11,20 @@ SET(CMAKE_CXX_FLAGS_ASAN "${CMAKE_CXX_FLAGS_DEBUG} -fsanitize=undefined -fsaniti set(default_build_type "Debug") +if(CMAKE_BUILD_TYPE STREQUAL "Debug") + if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") + check_cxx_compiler_flag("-fstandalone-debug" CXX_SUPPORTS_STANDALONE_DEBUG) + if(CXX_SUPPORTS_STANDALONE_DEBUG) + message(STATUS "Adding -fstandalone-debug for Clang") + set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fstandalone-debug") + else() + message(STATUS "Clang does not support -fstandalone-debug, skipping") + endif() + else() + message(STATUS "Use Gcc") + endif() +endif() + if(CMAKE_BUILD_TYPE STREQUAL "Debug") add_definitions(-DDEBUG_BUILD) endif() diff --git a/include/common/util.hpp b/include/common/util.hpp new file mode 100644 index 0000000000000000000000000000000000000000..060e98accaa72406d439ada35a0025650b96fa9e --- /dev/null +++ b/include/common/util.hpp @@ -0,0 +1,9 @@ +#ifndef UTIL_HPP +#define UTIL_HPP + +#include "string" + +std::string ptr_to_str(const void* ptr); + + +#endif \ No newline at end of file diff --git a/include/lightir/BasicBlock.hpp b/include/lightir/BasicBlock.hpp index bbefd6e9866116139181d0646c381c1357b649cf..f749309f449321e00fe65a0afe996730fac7118d 100755 --- a/include/lightir/BasicBlock.hpp +++ b/include/lightir/BasicBlock.hpp @@ -79,6 +79,8 @@ class BasicBlock : public Value { std::string print() override; + // 用于 lldb 调试生成 summary + std::string safe_print() const; private: explicit BasicBlock(Module *m, const std::string &name, Function *parent); diff --git a/include/lightir/Constant.hpp b/include/lightir/Constant.hpp index cacacd1e12cd8e513af2552e9ac5a9a95de5745d..84f11ea19f7c5ab85056b61fab716db89b34b012 100755 --- a/include/lightir/Constant.hpp +++ b/include/lightir/Constant.hpp @@ -15,6 +15,11 @@ public: Constant(Type *ty, const std::string &name = "") : User(ty, name) {} ~Constant() override; + + // 用于 lldb 调试生成 summary + std::string safe_print() const; + // 用于 lldb 调试生成 summary + std::string safe_print_help() const; protected: }; @@ -51,7 +56,7 @@ class ConstantArray : public Constant { static ConstantArray *get(ArrayType *ty, const std::vector &val); - std::string print() override; + std::string print() override; }; class ConstantZero : public Constant { diff --git a/include/lightir/Function.hpp b/include/lightir/Function.hpp index 95f26379644ec2aa61867d724512bf58ee9b6bde..f6e54308db3dee8d7befd08d6224ff7c838b6caf 100755 --- a/include/lightir/Function.hpp +++ b/include/lightir/Function.hpp @@ -47,6 +47,8 @@ class Function : public Value { // 用于检查函数的基本块是否存在问题 void check_for_block_relation_error() const; + // 用于 lldb 调试生成 summary + std::string safe_print() const; private: std::list basic_blocks_; std::list arguments_; @@ -77,6 +79,9 @@ class Argument : public Value { std::string print() override; + // 用于 lldb 调试生成 summary + std::string safe_print() const; + private: Function *parent_; unsigned arg_no_; // argument No. diff --git a/include/lightir/GlobalVariable.hpp b/include/lightir/GlobalVariable.hpp index b43327a545192dd36ef27efd5b9269c374064a79..a238f560606aef4eefb5d9b5f2d137db3aebb9b1 100755 --- a/include/lightir/GlobalVariable.hpp +++ b/include/lightir/GlobalVariable.hpp @@ -12,6 +12,8 @@ class GlobalVariable : public User { GlobalVariable(const std::string& name, Module *m, Type *ty, bool is_const, Constant *init = nullptr); + // 用于 lldb 调试生成 summary + std::string safe_print() const; public: GlobalVariable(const GlobalVariable& other) = delete; GlobalVariable(GlobalVariable&& other) noexcept = delete; diff --git a/include/lightir/Instruction.hpp b/include/lightir/Instruction.hpp index c642f0f753b337a89945519e14421ce5ab2aeecd..694acc33d4fc27f08c5d1c6e0810d93dd14af4e3 100755 --- a/include/lightir/Instruction.hpp +++ b/include/lightir/Instruction.hpp @@ -111,23 +111,14 @@ class Instruction : public User { bool isTerminator() const { return is_br() || is_ret(); } + // 用于 lldb 调试生成 summary + std::string safe_print() const; private: OpID op_id_; BasicBlock *parent_; }; -template class BaseInst : public Instruction { - protected: - template static Inst *create(Args &&...args) { - return new Inst(std::forward(args)...); - } - - template - BaseInst(Args &&...args) : Instruction(std::forward(args)...) {} -}; - -class IBinaryInst : public BaseInst { - friend BaseInst; +class IBinaryInst : public Instruction { private: IBinaryInst(OpID id, Value *v1, Value *v2, BasicBlock *bb); @@ -141,8 +132,7 @@ class IBinaryInst : public BaseInst { std::string print() override; }; -class FBinaryInst : public BaseInst { - friend BaseInst; +class FBinaryInst : public Instruction { private: FBinaryInst(OpID id, Value *v1, Value *v2, BasicBlock *bb); @@ -156,13 +146,13 @@ class FBinaryInst : public BaseInst { std::string print() override; }; -class ICmpInst : public BaseInst { - friend BaseInst; +class ICmpInst : public Instruction { private: ICmpInst(OpID id, Value *lhs, Value *rhs, BasicBlock *bb); public: + static ICmpInst *create_ge(Value *v1, Value *v2, BasicBlock *bb); static ICmpInst *create_gt(Value *v1, Value *v2, BasicBlock *bb); static ICmpInst *create_le(Value *v1, Value *v2, BasicBlock *bb); @@ -173,8 +163,7 @@ class ICmpInst : public BaseInst { std::string print() override; }; -class FCmpInst : public BaseInst { - friend BaseInst; +class FCmpInst : public Instruction { private: FCmpInst(OpID id, Value *lhs, Value *rhs, BasicBlock *bb); @@ -190,8 +179,7 @@ class FCmpInst : public BaseInst { std::string print() override; }; -class CallInst : public BaseInst { - friend BaseInst; +class CallInst : public Instruction { protected: CallInst(Function *func, const std::vector& args, BasicBlock *bb); @@ -204,15 +192,14 @@ class CallInst : public BaseInst { std::string print() override; }; -class BranchInst : public BaseInst { - friend BaseInst; +class BranchInst : public Instruction { private: BranchInst(Value *cond, BasicBlock *if_true, BasicBlock *if_false, BasicBlock *bb); - ~BranchInst() override; public: + ~BranchInst() override; BranchInst(const BranchInst& other) = delete; BranchInst(BranchInst&& other) noexcept = delete; BranchInst& operator=(const BranchInst& other) = delete; @@ -229,8 +216,7 @@ public: std::string print() override; }; -class ReturnInst : public BaseInst { - friend BaseInst; +class ReturnInst : public Instruction { private: ReturnInst(Value *val, BasicBlock *bb); @@ -243,8 +229,7 @@ class ReturnInst : public BaseInst { std::string print() override; }; -class GetElementPtrInst : public BaseInst { - friend BaseInst; +class GetElementPtrInst : public Instruction { private: GetElementPtrInst(Value *ptr, const std::vector& idxs, BasicBlock *bb); @@ -258,8 +243,7 @@ class GetElementPtrInst : public BaseInst { std::string print() override; }; -class StoreInst : public BaseInst { - friend BaseInst; +class StoreInst : public Instruction { StoreInst(Value *val, Value *ptr, BasicBlock *bb); @@ -272,8 +256,7 @@ class StoreInst : public BaseInst { std::string print() override; }; -class LoadInst : public BaseInst { - friend BaseInst; +class LoadInst : public Instruction { LoadInst(Value *ptr, BasicBlock *bb); @@ -286,8 +269,7 @@ class LoadInst : public BaseInst { std::string print() override; }; -class AllocaInst : public BaseInst { - friend BaseInst; +class AllocaInst : public Instruction { AllocaInst(Type *ty, BasicBlock *bb); @@ -302,8 +284,7 @@ class AllocaInst : public BaseInst { std::string print() override; }; -class ZextInst : public BaseInst { - friend BaseInst; +class ZextInst : public Instruction { private: ZextInst(Value *val, Type *ty, BasicBlock *bb); @@ -317,8 +298,7 @@ class ZextInst : public BaseInst { std::string print() override; }; -class FpToSiInst : public BaseInst { - friend BaseInst; +class FpToSiInst : public Instruction { private: FpToSiInst(Value *val, Type *ty, BasicBlock *bb); @@ -332,8 +312,7 @@ class FpToSiInst : public BaseInst { std::string print() override; }; -class SiToFpInst : public BaseInst { - friend BaseInst; +class SiToFpInst : public Instruction { private: SiToFpInst(Value *val, Type *ty, BasicBlock *bb); @@ -346,15 +325,14 @@ class SiToFpInst : public BaseInst { std::string print() override; }; -class PhiInst : public BaseInst { - friend BaseInst; +class PhiInst : public Instruction { private: PhiInst(Type *ty, const std::vector& vals, const std::vector& val_bbs, BasicBlock *bb); public: - // 新特性:指令表分为 {alloca, phi | other inst} 两段,创建和向基本块插入 alloca 和 phi,都只会插在第一段,它们在常规指令前面 + // 新特性:指令表分为 {alloca, phi | other inst} 两段,创建和向基本块插入 alloca 和 phi,都只会插在第一段,它们在常规指令前面 static PhiInst *create_phi(Type *ty, BasicBlock *bb, const std::vector& vals = {}, const std::vector& val_bbs = {}); diff --git a/include/lightir/Type.hpp b/include/lightir/Type.hpp index 48a715390968da1150635a7c214908cee7811569..2e0267149c95e8b1435f4c1bb85c5678ab42b00a 100755 --- a/include/lightir/Type.hpp +++ b/include/lightir/Type.hpp @@ -53,6 +53,9 @@ class Type { std::string print() const; + // 用于 lldb 调试生成 summary + std::string safe_print() const; + private: TypeID tid_; Module *m_; diff --git a/include/lightir/Value.hpp b/include/lightir/Value.hpp index dee7d29c10b05ce6a2f446e2dffb2a61d84b4289..adfb71efbe9885698b815584307a469a03b6f50f 100755 --- a/include/lightir/Value.hpp +++ b/include/lightir/Value.hpp @@ -57,6 +57,8 @@ class Value { return dynamic_cast(this); } + // 用于 lldb 调试生成 summary + std::string safe_get_name_or_ptr() const; private: Type *type_; std::list use_list_; // who use this value diff --git a/lldb_formatters.py b/lldb_formatters.py index 71b950635288fc93b60727179579c532acabc4ba..b4cc4c888c1e26ba2d4222d2b44e00598b8ca5e6 100644 --- a/lldb_formatters.py +++ b/lldb_formatters.py @@ -3,21 +3,24 @@ import lldb def parseString(val : lldb.SBValue): summary = val.GetSummary() or val.GetValue() if summary: - # 去掉两端引号,只留裸文本(可选) if summary.startswith('"') and summary.endswith('"'): summary = summary[1:-1] return summary return "" -def TypePrinterSummary(valobj: lldb.SBValue, internal_dict): - # 调用 print 函数进行显示 - name: lldb.SBValue = valobj.EvaluateExpression("print()"); +def SafePrintSummary(valobj: lldb.SBValue, internal_dict): + name: lldb.SBValue = valobj.EvaluateExpression("this->safe_print()") return parseString(name) def __lldb_init_module(debugger: lldb.SBDebugger, internal_dict): - types = ["Type", "IntegerType", "FunctionType", "ArrayType", "PointerType", "FloatType"] + types = ["Type", "IntegerType", "FunctionType", "ArrayType", "PointerType", "FloatType" + , "Constant", "ConstantInt", "ConstantArray", "ConstantZero", "ConstantFP" + , "Function", "Argument" + , "BasicBlock" + , "GlobalVariable" + , "Instruction", "IBinaryInst", "FBinaryInst", "ICmpInst", "FCmpInst", "CallInst", "BranchInst", "ReturnInst", "GetElementPtrInst", "StoreInst", "LoadInst", "AllocaInst", "ZextInst", "FpToSiInst", "SiToFpInst", "PhiInst" ] for i in types: debugger.HandleCommand( - f"type summary add -F lldb_formatters.TypePrinterSummary {i} -w my" + f"type summary add -F lldb_formatters.SafePrintSummary {i} -w my" ) debugger.HandleCommand("type category enable my") \ No newline at end of file diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 5fe66a7fe24ab42e40a7f15ef1b92680c34d07f1..1d576f6ec6de18571c989adfc446e1777f0ccfb1 100755 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -2,7 +2,7 @@ add_library(common STATIC syntax_tree.c ast.cpp logging.cpp -) + util.cpp) target_link_libraries(common) diff --git a/src/common/util.cpp b/src/common/util.cpp new file mode 100644 index 0000000000000000000000000000000000000000..242fff3ac01926e9a5c34e2f793f687c02dc7047 --- /dev/null +++ b/src/common/util.cpp @@ -0,0 +1,15 @@ +#include "util.hpp" + +std::string ptr_to_str(const void* ptr) +{ + const char* translate = "0123456789abcdef"; + + uintptr_t addr = reinterpret_cast(ptr); + + uintptr_t a = addr & 0xF; + uintptr_t b = (addr >> 4) & 0xF; + uintptr_t c = (addr >> 8) & 0xF; + uintptr_t d = (addr >> 12) & 0xF; + + return {'<', translate[d], translate[c], translate[b], translate[a], '>'}; +} diff --git a/src/lightir/BasicBlock.cpp b/src/lightir/BasicBlock.cpp index 4e698d8779b2c13eba4a5f2c71a128d2d51bad59..3ba36f3494189f9fc4281066e24c2540f3d63e4e 100755 --- a/src/lightir/BasicBlock.cpp +++ b/src/lightir/BasicBlock.cpp @@ -3,6 +3,7 @@ #include "Function.hpp" #include "IRprinter.hpp" #include "Module.hpp" +#include "util.hpp" #include @@ -102,6 +103,16 @@ std::string BasicBlock::print() { return bb_ir; } +std::string BasicBlock::safe_print() const +{ + Function* parent = parent_; + auto parentName = ((parent != nullptr) ? parent->get_name() : "f"); + auto name = get_name(); + if (name.empty()) name = "b" + ptr_to_str(this); + if (parentName.empty()) parentName = "f" + ptr_to_str(parent); + return parentName + ":" + name + " " + std::to_string(instr_list_.size()) + "inst pre " + std::to_string(pre_bbs_.size()) + "b suc " + std::to_string(succ_bbs_.size()) + "b"; +} + BasicBlock::~BasicBlock() { for (auto inst : instr_list_) delete inst; diff --git a/src/lightir/Constant.cpp b/src/lightir/Constant.cpp index 4e4edbbd29208999243fdd0736cc17dc0cb0ba52..7574ff529aad5bcd1d53c817521314835f7b0dba 100755 --- a/src/lightir/Constant.cpp +++ b/src/lightir/Constant.cpp @@ -31,6 +31,53 @@ static std::unordered_map> cached_zero; Constant::~Constant() = default; +std::string Constant::safe_print() const +{ + Type* ty = this->get_type(); + return (ty == nullptr ? "" : get_type()->safe_print()) + " " + safe_print_help(); +} + +std::string Constant::safe_print_help() const +{ + if (dynamic_cast(this)) + { + return "zeroinitializer"; + } + if (auto constant = dynamic_cast(this)) + { + Type* ty = this->get_type(); + if (ty != nullptr && ty->is_int1_type()) { + return constant->get_value() == 0 ? "false" : "true"; + } + return std::to_string(constant->get_value()); + } + if (auto constant = dynamic_cast(this)) + { + std::stringstream fp_ir_ss; + std::string fp_ir; + double val = constant->get_value(); + uint64_t uval; + memcpy(&uval, &val, sizeof(double)); + fp_ir_ss << "0x" << std::hex << uval << '\n'; + fp_ir_ss >> fp_ir; + return std::to_string(val) + "(" + fp_ir + ")"; + } + if (auto constant = dynamic_cast(this)) + { + std::string const_ir = "["; + for (int i = 0; i < constant->get_size_of_array(); i++) { + Constant* element = constant->get_element_value(i); + const_ir += (element == nullptr ? "" : element->safe_print_help()); + if (i < constant->get_size_of_array()) { + const_ir += ", "; + } + } + const_ir += "]"; + return const_ir; + } + return ""; +} + ConstantInt *ConstantInt::get(int val, Module *m) { if (cached_int.find(std::make_pair(val, m)) != cached_int.end()) return cached_int[std::make_pair(val, m)].get(); @@ -51,7 +98,7 @@ std::string ConstantInt::print() { std::string const_ir; Type *ty = this->get_type(); if (ty->is_integer_type() && - static_cast(ty)->get_num_bits() == 1) { + dynamic_cast(ty)->get_num_bits() == 1) { // int1 const_ir += (this->get_value() == 0) ? "false" : "true"; } else { diff --git a/src/lightir/Function.cpp b/src/lightir/Function.cpp index c1649dd91fe80dee0f1e80be5b1b771ac515eafa..813dd83f6ad5093746a9aad9037f6b4be3554369 100755 --- a/src/lightir/Function.cpp +++ b/src/lightir/Function.cpp @@ -6,7 +6,7 @@ #include #include -Function::Function(FunctionType *ty, const std::string &name, Module *parent) +Function::Function(FunctionType* ty, const std::string& name, Module* parent) : Value(ty, name), parent_(parent), seq_cnt_(0) { // num_args_ = ty->getNumParams(); parent->add_function(this); @@ -21,16 +21,16 @@ Function::~Function() for (auto bb : basic_blocks_) delete bb; } -Function *Function::create(FunctionType *ty, const std::string &name, - Module *parent) { +Function* Function::create(FunctionType* ty, const std::string& name, + Module* parent) { return new Function(ty, name, parent); } -FunctionType *Function::get_function_type() const { - return dynamic_cast(get_type()); +FunctionType* Function::get_function_type() const { + return dynamic_cast(get_type()); } -Type *Function::get_return_type() const { +Type* Function::get_return_type() const { return get_function_type()->get_return_type(); } @@ -40,9 +40,9 @@ unsigned Function::get_num_of_args() const { unsigned Function::get_num_basic_blocks() const { return static_cast(basic_blocks_.size()); } -Module *Function::get_parent() const { return parent_; } +Module* Function::get_parent() const { return parent_; } -void Function::remove(BasicBlock *bb) { +void Function::remove(BasicBlock* bb) { basic_blocks_.remove(bb); for (auto pre : bb->get_pre_basic_blocks()) { pre->remove_succ_basic_block(bb); @@ -52,15 +52,15 @@ void Function::remove(BasicBlock *bb) { } } -void Function::add_basic_block(BasicBlock *bb) { basic_blocks_.push_back(bb); } +void Function::add_basic_block(BasicBlock* bb) { basic_blocks_.push_back(bb); } void Function::set_instr_name() { - std::map seq; - for (auto &arg : this->get_args()) { + std::map seq; + for (auto& arg : this->get_args()) { if (seq.find(&arg) == seq.end()) { auto seq_num = seq.size() + seq_cnt_; if (arg.set_name("arg" + std::to_string(seq_num))) { - seq.insert({&arg, seq_num}); + seq.insert({ &arg, seq_num }); } } } @@ -68,14 +68,14 @@ void Function::set_instr_name() { if (seq.find(bb) == seq.end()) { auto seq_num = seq.size() + seq_cnt_; if (bb->set_name("label" + std::to_string(seq_num))) { - seq.insert({bb, seq_num}); + seq.insert({ bb, seq_num }); } } for (auto instr : bb->get_instructions()) { if (!instr->is_void() && seq.find(instr) == seq.end()) { auto seq_num = seq.size() + seq_cnt_; if (instr->set_name("op" + std::to_string(seq_num))) { - seq.insert({instr, seq_num}); + seq.insert({ instr, seq_num }); } } } @@ -88,7 +88,8 @@ std::string Function::print() { std::string func_ir; if (this->is_declaration()) { func_ir += "declare "; - } else { + } + else { func_ir += "define "; } @@ -102,12 +103,13 @@ std::string Function::print() { for (unsigned i = 0; i < this->get_num_of_args(); i++) { if (i) func_ir += ", "; - func_ir += dynamic_cast(this->get_type()) - ->get_param_type(i) - ->print(); + func_ir += dynamic_cast(this->get_type()) + ->get_param_type(i) + ->print(); } - } else { - for (auto &arg : get_args()) { + } + else { + for (auto& arg : get_args()) { if (&arg != &*get_args().begin()) func_ir += ", "; func_ir += arg.print(); @@ -118,7 +120,8 @@ std::string Function::print() { // print bb if (this->is_declaration()) { func_ir += "\n"; - } else { + } + else { func_ir += " {"; func_ir += "\n"; for (auto bb : this->get_basic_blocks()) { @@ -138,6 +141,19 @@ std::string Argument::print() { return arg_ir; } +std::string Argument::safe_print() const +{ + auto parent = parent_; + if (parent == nullptr) + { + return "@ arg" + std::to_string(arg_no_) + " "; + } + auto ty = parent->get_function_type(); + if (ty == nullptr || ty->get_num_of_args() <= arg_no_) return "@" + parent->get_name() + " arg" + std::to_string(arg_no_) + " "; + auto ty2 = ty->get_param_type(arg_no_); + return "@" + parent->get_name() + " arg" + std::to_string(arg_no_) + " " + (ty2 == nullptr ? "" : ty2->safe_print()); +} + void Function::check_for_block_relation_error() const { @@ -150,11 +166,11 @@ void Function::check_for_block_relation_error() const for (auto bb : basic_blocks_) { assert((bb->get_parent() == this) && "函数 F 的基本块表中包含基本块 a, 但 a 的 get_parent 方法不返回 F"); - for (auto i: bb->get_succ_basic_blocks()) + for (auto i : bb->get_succ_basic_blocks()) { assert((bbs.count(i)) && "函数 F 的基本块表中包含基本块 a, a 的后继块表中的某基本块 b 不在 F 的基本块表中"); } - for (auto i: bb->get_pre_basic_blocks()) + for (auto i : bb->get_pre_basic_blocks()) { assert((bbs.count(i)) && "函数 F 的基本块表中包含基本块 a, a 的前驱块表中的某基本块 b 不在 F 的基本块表中"); } @@ -170,7 +186,7 @@ void Function::check_for_block_relation_error() const // 检查基本块前驱后继关系是否是与 branch 指令对应 for (auto bb : basic_blocks_) { - if(!bb->get_succ_basic_blocks().empty()){ + if (!bb->get_succ_basic_blocks().empty()) { std::unordered_set suc_table; std::unordered_set br_get; for (auto suc : bb->get_succ_basic_blocks()) @@ -179,18 +195,18 @@ void Function::check_for_block_relation_error() const for (auto i : ops) { auto bb2 = dynamic_cast(i); - if(bb2 != nullptr) br_get.emplace(bb2); + if (bb2 != nullptr) br_get.emplace(bb2); } // 这三个检查保证有问题会报错,但不保证每次报错的基本块都相同 // 例如 A, B 两个基本块都存在问题,可能有时 A 报错有时 B 报错 - for(auto i : suc_table) + for (auto i : suc_table) assert(br_get.count(i) && "基本块 A 的后继块有 B,但 B 并未在 A 的 br 指令中出现"); - for(auto i : br_get) + for (auto i : br_get) assert(suc_table.count(i) && "基本块 A 的后继块没有 B,但 B 在 A 的 br 指令中出现了"); - for(auto i : suc_table) { + for (auto i : suc_table) { bool ok = false; - for(auto j : i->get_pre_basic_blocks()) { - if(j == bb){ + for (auto j : i->get_pre_basic_blocks()) { + if (j == bb) { ok = true; break; } @@ -213,7 +229,7 @@ void Function::check_for_block_relation_error() const break; } } - if (!ok) + if (!ok) assert(false && "基本块 A 的后继块表中没有 B,但 B 的前驱表中有 A"); } } @@ -222,7 +238,22 @@ void Function::check_for_block_relation_error() const { for (auto inst : bb->get_instructions()) { - assert ((inst->get_parent() == bb) && "基本块 A 指令表包含指令 b, 但是 b 的 get_parent 函数不返回 A"); + assert((inst->get_parent() == bb) && "基本块 A 指令表包含指令 b, 但是 b 的 get_parent 函数不返回 A"); } } } + +std::string Function::safe_print() const +{ + auto ty = this->get_function_type(); + if (ty == nullptr) return "unknown type @" + get_name(); + auto ty2 = ty->get_return_type(); + std::string func_ir = (ty2 == nullptr ? "" : ty2->safe_print()) + " @"; + func_ir += get_name() + "("; + for (unsigned i = 0; i < ty->get_num_of_args(); i++) { + if (i) func_ir += ", "; + auto ty3 = ty->get_param_type(i); + func_ir += (ty3 == nullptr ? "" : ty3->safe_print()); + } + return func_ir + ") " + std::to_string(basic_blocks_.size()) + "b"; +} diff --git a/src/lightir/GlobalVariable.cpp b/src/lightir/GlobalVariable.cpp index 6d0f60f5a62f483d0c039a37ac8003d8815d4624..ebc7af7d1a9d5f5c28967f8de9bce9073f51be75 100755 --- a/src/lightir/GlobalVariable.cpp +++ b/src/lightir/GlobalVariable.cpp @@ -11,6 +11,18 @@ GlobalVariable::GlobalVariable(const std::string& name, Module *m, Type *ty, } } // global操作数为initval +std::string GlobalVariable::safe_print() const +{ + std::string ret; + if (is_const_) ret += "const "; + auto ty = get_type(); + if (ty == nullptr) ret += " "; + else ret += ty->safe_print() + " "; + ret += get_name(); + if (init_val_ != nullptr) ret += " " + init_val_->safe_print_help(); + return ret; +} + GlobalVariable *GlobalVariable::create(const std::string& name, Module *m, Type *ty, bool is_const, Constant *init = nullptr) { diff --git a/src/lightir/IRprinter.cpp b/src/lightir/IRprinter.cpp index 53723648d890c1357d16226751732edcce24555f..0bcbbbadda6e08cbcc58949c15e2666fdbdf4fb9 100755 --- a/src/lightir/IRprinter.cpp +++ b/src/lightir/IRprinter.cpp @@ -23,6 +23,127 @@ std::string print_as_op(Value *v, bool print_ty) { return op_ir; } +static std::string safe_print_op_as_op(const Instruction* v, unsigned idx, bool print_ty) { + if (v->get_num_operand() <= idx) return "op"; + Value* val = v->get_operand(idx); + if (val == nullptr) return "op"; + std::string op_ir; + if (print_ty) { + auto ty = val->get_type(); + if (ty == nullptr) op_ir += "t "; + else + { + op_ir += ty->safe_print(); + op_ir += " "; + } + } + + if (dynamic_cast(val) || dynamic_cast(val)) { + op_ir += "@" + val->safe_get_name_or_ptr(); + } + else if (auto constant = dynamic_cast(val)) { + op_ir += constant->safe_print_help(); + } + else { + op_ir += "%" + val->safe_get_name_or_ptr(); + } + + return op_ir; +} + +static std::string safe_print_as_op(const Value* v, bool print_ty) { + std::string op_ir; + if (print_ty) { + auto ty = v->get_type(); + if (ty == nullptr) op_ir += "t "; + else + { + op_ir += ty->safe_print(); + op_ir += " "; + } + } + + if (dynamic_cast(v) || dynamic_cast(v)) { + op_ir += "@" + v->safe_get_name_or_ptr(); + } + else if (auto constant = dynamic_cast(v)) { + op_ir += constant->safe_print_help(); + } + else { + op_ir += "%" + v->safe_get_name_or_ptr(); + } + + return op_ir; +} + +static const char* safe_print_instr_op_name(Instruction::OpID id) { + switch (id) { + case Instruction::ret: + return "ret"; + case Instruction::br: + return "br"; + case Instruction::add: + return "add"; + case Instruction::sub: + return "sub"; + case Instruction::mul: + return "mul"; + case Instruction::sdiv: + return "sdiv"; + case Instruction::fadd: + return "fadd"; + case Instruction::fsub: + return "fsub"; + case Instruction::fmul: + return "fmul"; + case Instruction::fdiv: + return "fdiv"; + case Instruction::alloca: + return "alloca"; + case Instruction::load: + return "load"; + case Instruction::store: + return "store"; + case Instruction::ge: + return "sge"; + case Instruction::gt: + return "sgt"; + case Instruction::le: + return "sle"; + case Instruction::lt: + return "slt"; + case Instruction::eq: + return "eq"; + case Instruction::ne: + return "ne"; + case Instruction::fge: + return "uge"; + case Instruction::fgt: + return "ugt"; + case Instruction::fle: + return "ule"; + case Instruction::flt: + return "ult"; + case Instruction::feq: + return "ueq"; + case Instruction::fne: + return "une"; + case Instruction::phi: + return "phi"; + case Instruction::call: + return "call"; + case Instruction::getelementptr: + return "getelementptr"; + case Instruction::zext: + return "zext"; + case Instruction::fptosi: + return "fptosi"; + case Instruction::sitofp: + return "sitofp"; + } + return "inst"; +} + std::string print_instr_op_name(Instruction::OpID id) { switch (id) { case Instruction::ret: @@ -91,6 +212,236 @@ std::string print_instr_op_name(Instruction::OpID id) { assert(false && "Must be bug"); } +std::string Instruction::safe_print() const +{ + switch (op_id_) + { + case ret: + { + std::string instr_ir; + instr_ir += get_instr_op_name(); + instr_ir += " "; + if (!dynamic_cast(this)->is_void_ret()) { + instr_ir += this->get_operand(0)->get_type()->print(); + instr_ir += " "; + instr_ir += print_as_op(this->get_operand(0), false); + } + else { + instr_ir += "void"; + } + return instr_ir; + } + case br: + { + std::string instr_ir; + instr_ir += safe_print_instr_op_name(get_instr_type()); + instr_ir += " "; + instr_ir += safe_print_op_as_op(this, 0, true); + if (dynamic_cast(this)->is_cond_br()) { + instr_ir += ", "; + instr_ir += safe_print_op_as_op(this, 1, true); + instr_ir += ", "; + instr_ir += safe_print_op_as_op(this, 2, true); + } + return instr_ir; + } + case add: + case sub: + case mul: + case sdiv: + case fadd: + case fsub: + case fmul: + case fdiv: + { + std::string instr_ir; + instr_ir += safe_print_as_op(this, true); + instr_ir += " = "; + instr_ir += safe_print_instr_op_name(op_id_); + instr_ir += " "; + instr_ir += safe_print_op_as_op(this, 0, true); + instr_ir += ", "; + instr_ir += safe_print_op_as_op(this, 1, true); + return instr_ir; + } + case alloca: + { + std::string instr_ir; + instr_ir += safe_print_as_op(this, true); + instr_ir += " = "; + instr_ir += get_instr_op_name(); + instr_ir += " "; + auto ty = get_type(); + if (ty == nullptr || !ty->is_pointer_type()) + { + instr_ir += "t"; + } + else + { + auto ty2 = ty->get_pointer_element_type(); + if (ty2 == nullptr) + instr_ir += "t"; + else instr_ir += ty2->safe_print(); + } + return instr_ir; + } + case load: + { + std::string instr_ir; + instr_ir += safe_print_as_op(this, true); + instr_ir += " = "; + instr_ir += safe_print_instr_op_name(get_instr_type()); + instr_ir += " "; + instr_ir += safe_print_op_as_op(this, 0, true); + return instr_ir; + } + case store: + { + std::string instr_ir; + instr_ir += safe_print_instr_op_name(get_instr_type()); + instr_ir += " "; + instr_ir += safe_print_op_as_op(this, 0, true); + instr_ir += ", "; + instr_ir += safe_print_op_as_op(this, 1, true); + return instr_ir; + } + case ge: + case gt: + case le: + case lt: + case eq: + case ne: + { + std::string instr_ir; + instr_ir += safe_print_as_op(this, true); + instr_ir += " = icmp "; + instr_ir += safe_print_instr_op_name(op_id_); + instr_ir += " "; + instr_ir += safe_print_op_as_op(this, 0, true); + instr_ir += ", "; + instr_ir += safe_print_op_as_op(this, 1, true); + return instr_ir; + } + case fge: + case fgt: + case fle: + case flt: + case feq: + case fne: + { + std::string instr_ir; + instr_ir += safe_print_as_op(this, true); + instr_ir += " = fcmp "; + instr_ir += safe_print_instr_op_name(op_id_); + instr_ir += " "; + instr_ir += safe_print_op_as_op(this, 0, true); + instr_ir += ", "; + instr_ir += safe_print_op_as_op(this, 1, true); + return instr_ir; + } + case phi: + { + std::string instr_ir; + instr_ir += safe_print_as_op(this, true); + instr_ir += " = "; + instr_ir += safe_print_instr_op_name(get_instr_type()); + instr_ir += " "; + for (unsigned i = 0; i < this->get_num_operand() / 2; i++) { + if (i > 0) + instr_ir += ", "; + instr_ir += "[ "; + instr_ir += safe_print_op_as_op(this, i << 1, true); + instr_ir += ", "; + instr_ir += safe_print_op_as_op(this, (i << 1) + 1, true); + instr_ir += " ]"; + } + return instr_ir; + } + case call: + { + std::string instr_ir; + auto ty = get_type(); + if (ty == nullptr || !ty->is_void_type()) + { + instr_ir += safe_print_as_op(this, true); + instr_ir += " = "; + } + instr_ir += safe_print_instr_op_name(op_id_); + instr_ir += " "; + + if (get_num_operand() == 0) + { + return instr_ir + ""; + } + + auto op0 = get_operand(0); + + if (op0 == nullptr) + { + instr_ir += "ft "; + } + else + { + if (auto fty = dynamic_cast(ty)) + { + auto ty3 = fty->get_return_type(); + if (ty3 == nullptr) + instr_ir += "t "; + else + instr_ir += ty3->safe_print(); + } + else + { + instr_ir += " "; + instr_ir += safe_print_as_op(op0, true); + return instr_ir; + } + } + + instr_ir += " "; + instr_ir += safe_print_op_as_op(this, 0, false); + instr_ir += "("; + for (unsigned i = 1; i < this->get_num_operand(); i++) { + if (i > 1) + instr_ir += ", "; + instr_ir += safe_print_op_as_op(this, i, true); + } + instr_ir += ")"; + return instr_ir; + } + case getelementptr: + { + std::string instr_ir; + instr_ir += safe_print_as_op(this, true); + instr_ir += " = "; + instr_ir += safe_print_instr_op_name(get_instr_type()); + instr_ir += " "; + for (unsigned i = 0; i < this->get_num_operand(); i++) { + if (i > 0) + instr_ir += ", "; + instr_ir += safe_print_op_as_op(this, i, true); + } + return instr_ir; + } + case zext: + case fptosi: + case sitofp: + { + std::string instr_ir; + instr_ir += safe_print_as_op(this, true); + instr_ir += " = "; + instr_ir += safe_print_instr_op_name(get_instr_type()); + instr_ir += " "; + instr_ir += safe_print_op_as_op(this, 0, true); + return instr_ir; + } + } + std::string str; + str += safe_print_as_op(this, true); + str += " = unknown inst"; + return str; +} + template static std::string print_binary_inst(const BinInst &inst) { std::string instr_ir; @@ -111,6 +462,7 @@ static std::string print_binary_inst(const BinInst &inst) { return instr_ir; } std::string IBinaryInst::print() { return print_binary_inst(*this); } + std::string FBinaryInst::print() { return print_binary_inst(*this); } template @@ -140,6 +492,7 @@ static std::string print_cmp_inst(const CMP &inst) { return instr_ir; } std::string ICmpInst::print() { return print_cmp_inst(*this); } + std::string FCmpInst::print() { return print_cmp_inst(*this); } std::string CallInst::print() { @@ -185,12 +538,10 @@ std::string BranchInst::print() { std::string ReturnInst::print() { std::string instr_ir; - instr_ir += get_instr_op_name(); + instr_ir += safe_print_instr_op_name(get_instr_type()); instr_ir += " "; if (!is_void_ret()) { - instr_ir += this->get_operand(0)->get_type()->print(); - instr_ir += " "; - instr_ir += print_as_op(this->get_operand(0), false); + instr_ir += safe_print_op_as_op(this, 0, true); } else { instr_ir += "void"; } diff --git a/src/lightir/Instruction.cpp b/src/lightir/Instruction.cpp index ca79ca9db1c7437e3d1e1cfc087cc921fe06452a..9b06b4ca3c3b9412273a61ef74253e9d3b7e7568 100755 --- a/src/lightir/Instruction.cpp +++ b/src/lightir/Instruction.cpp @@ -26,7 +26,7 @@ std::string Instruction::get_instr_op_name() const { } IBinaryInst::IBinaryInst(OpID id, Value *v1, Value *v2, BasicBlock *bb) - : BaseInst(bb->get_module()->get_int32_type(), id, bb) { + : Instruction(bb->get_module()->get_int32_type(), id, bb) { assert(v1->get_type()->is_int32_type() && v2->get_type()->is_int32_type() && "IBinaryInst operands are not both i32"); add_operand(v1); @@ -34,20 +34,20 @@ IBinaryInst::IBinaryInst(OpID id, Value *v1, Value *v2, BasicBlock *bb) } IBinaryInst *IBinaryInst::create_add(Value *v1, Value *v2, BasicBlock *bb) { - return create(add, v1, v2, bb); + return new IBinaryInst(add, v1, v2, bb); } IBinaryInst *IBinaryInst::create_sub(Value *v1, Value *v2, BasicBlock *bb) { - return create(sub, v1, v2, bb); + return new IBinaryInst(sub, v1, v2, bb); } IBinaryInst *IBinaryInst::create_mul(Value *v1, Value *v2, BasicBlock *bb) { - return create(mul, v1, v2, bb); + return new IBinaryInst(mul, v1, v2, bb); } IBinaryInst *IBinaryInst::create_sdiv(Value *v1, Value *v2, BasicBlock *bb) { - return create(sdiv, v1, v2, bb); + return new IBinaryInst(sdiv, v1, v2, bb); } FBinaryInst::FBinaryInst(OpID id, Value *v1, Value *v2, BasicBlock *bb) - : BaseInst(bb->get_module()->get_float_type(), id, bb) { + : Instruction(bb->get_module()->get_float_type(), id, bb) { assert(v1->get_type()->is_float_type() && v2->get_type()->is_float_type() && "FBinaryInst operands are not both float"); add_operand(v1); @@ -55,20 +55,20 @@ FBinaryInst::FBinaryInst(OpID id, Value *v1, Value *v2, BasicBlock *bb) } FBinaryInst *FBinaryInst::create_fadd(Value *v1, Value *v2, BasicBlock *bb) { - return create(fadd, v1, v2, bb); + return new FBinaryInst(fadd, v1, v2, bb); } FBinaryInst *FBinaryInst::create_fsub(Value *v1, Value *v2, BasicBlock *bb) { - return create(fsub, v1, v2, bb); + return new FBinaryInst(fsub, v1, v2, bb); } FBinaryInst *FBinaryInst::create_fmul(Value *v1, Value *v2, BasicBlock *bb) { - return create(fmul, v1, v2, bb); + return new FBinaryInst(fmul, v1, v2, bb); } FBinaryInst *FBinaryInst::create_fdiv(Value *v1, Value *v2, BasicBlock *bb) { - return create(fdiv, v1, v2, bb); + return new FBinaryInst(fdiv, v1, v2, bb); } ICmpInst::ICmpInst(OpID id, Value *lhs, Value *rhs, BasicBlock *bb) - : BaseInst(bb->get_module()->get_int1_type(), id, bb) { + : Instruction(bb->get_module()->get_int1_type(), id, bb) { assert(lhs->get_type()->is_int32_type() && rhs->get_type()->is_int32_type() && "CmpInst operands are not both i32"); @@ -77,26 +77,26 @@ ICmpInst::ICmpInst(OpID id, Value *lhs, Value *rhs, BasicBlock *bb) } ICmpInst *ICmpInst::create_ge(Value *v1, Value *v2, BasicBlock *bb) { - return create(ge, v1, v2, bb); + return new ICmpInst(ge, v1, v2, bb); } ICmpInst *ICmpInst::create_gt(Value *v1, Value *v2, BasicBlock *bb) { - return create(gt, v1, v2, bb); + return new ICmpInst(gt, v1, v2, bb); } ICmpInst *ICmpInst::create_le(Value *v1, Value *v2, BasicBlock *bb) { - return create(le, v1, v2, bb); + return new ICmpInst(le, v1, v2, bb); } ICmpInst *ICmpInst::create_lt(Value *v1, Value *v2, BasicBlock *bb) { - return create(lt, v1, v2, bb); + return new ICmpInst(lt, v1, v2, bb); } ICmpInst *ICmpInst::create_eq(Value *v1, Value *v2, BasicBlock *bb) { - return create(eq, v1, v2, bb); + return new ICmpInst(eq, v1, v2, bb); } ICmpInst *ICmpInst::create_ne(Value *v1, Value *v2, BasicBlock *bb) { - return create(ne, v1, v2, bb); + return new ICmpInst(ne, v1, v2, bb); } FCmpInst::FCmpInst(OpID id, Value *lhs, Value *rhs, BasicBlock *bb) - : BaseInst(bb->get_module()->get_int1_type(), id, bb) { + : Instruction(bb->get_module()->get_int1_type(), id, bb) { assert(lhs->get_type()->is_float_type() && rhs->get_type()->is_float_type() && "FCmpInst operands are not both float"); @@ -105,26 +105,26 @@ FCmpInst::FCmpInst(OpID id, Value *lhs, Value *rhs, BasicBlock *bb) } FCmpInst *FCmpInst::create_fge(Value *v1, Value *v2, BasicBlock *bb) { - return create(fge, v1, v2, bb); + return new FCmpInst(fge, v1, v2, bb); } FCmpInst *FCmpInst::create_fgt(Value *v1, Value *v2, BasicBlock *bb) { - return create(fgt, v1, v2, bb); + return new FCmpInst(fgt, v1, v2, bb); } FCmpInst *FCmpInst::create_fle(Value *v1, Value *v2, BasicBlock *bb) { - return create(fle, v1, v2, bb); + return new FCmpInst(fle, v1, v2, bb); } FCmpInst *FCmpInst::create_flt(Value *v1, Value *v2, BasicBlock *bb) { - return create(flt, v1, v2, bb); + return new FCmpInst(flt, v1, v2, bb); } FCmpInst *FCmpInst::create_feq(Value *v1, Value *v2, BasicBlock *bb) { - return create(feq, v1, v2, bb); + return new FCmpInst(feq, v1, v2, bb); } FCmpInst *FCmpInst::create_fne(Value *v1, Value *v2, BasicBlock *bb) { - return create(fne, v1, v2, bb); + return new FCmpInst(fne, v1, v2, bb); } CallInst::CallInst(Function *func, const std::vector& args, BasicBlock *bb) - : BaseInst(func->get_return_type(), call, bb) { + : Instruction(func->get_return_type(), call, bb) { assert(func->get_type()->is_function_type() && "Not a function"); assert((func->get_num_of_args() == args.size()) && "Wrong number of args"); add_operand(func); @@ -138,7 +138,7 @@ CallInst::CallInst(Function *func, const std::vector& args, BasicBlock CallInst *CallInst::create_call(Function *func, const std::vector& args, BasicBlock *bb) { - return create(func, args, bb); + return new CallInst(func, args, bb); } FunctionType *CallInst::get_function_type() const { @@ -147,7 +147,7 @@ FunctionType *CallInst::get_function_type() const { BranchInst::BranchInst(Value *cond, BasicBlock *if_true, BasicBlock *if_false, BasicBlock *bb) - : BaseInst(bb->get_module()->get_void_type(), br, bb) { + : Instruction(bb->get_module()->get_void_type(), br, bb) { if (cond == nullptr) { // conditionless jump assert(if_false == nullptr && "Given false-bb on conditionless jump"); add_operand(if_true); @@ -186,15 +186,15 @@ BranchInst::~BranchInst() { BranchInst *BranchInst::create_cond_br(Value *cond, BasicBlock *if_true, BasicBlock *if_false, BasicBlock *bb) { - return create(cond, if_true, if_false, bb); + return new BranchInst(cond, if_true, if_false, bb); } BranchInst *BranchInst::create_br(BasicBlock *if_true, BasicBlock *bb) { - return create(nullptr, if_true, nullptr, bb); + return new BranchInst(nullptr, if_true, nullptr, bb); } ReturnInst::ReturnInst(Value *val, BasicBlock *bb) - : BaseInst(bb->get_module()->get_void_type(), ret, bb) { + : Instruction(bb->get_module()->get_void_type(), ret, bb) { if (val == nullptr) { assert(bb->get_parent()->get_return_type()->is_void_type()); } else { @@ -207,17 +207,17 @@ ReturnInst::ReturnInst(Value *val, BasicBlock *bb) } ReturnInst *ReturnInst::create_ret(Value *val, BasicBlock *bb) { - return create(val, bb); + return new ReturnInst(val, bb); } ReturnInst *ReturnInst::create_void_ret(BasicBlock *bb) { - return create(nullptr, bb); + return new ReturnInst(nullptr, bb); } bool ReturnInst::is_void_ret() const { return get_num_operand() == 0; } GetElementPtrInst::GetElementPtrInst(Value *ptr, const std::vector& idxs, BasicBlock *bb) - : BaseInst(PointerType::get(get_element_type(ptr, idxs)), + : Instruction(PointerType::get(get_element_type(ptr, idxs)), getelementptr, bb) { add_operand(ptr); for (auto idx : idxs) @@ -258,11 +258,11 @@ Type *GetElementPtrInst::get_element_type() const { GetElementPtrInst *GetElementPtrInst::create_gep(Value *ptr, const std::vector& idxs, BasicBlock *bb) { - return create(ptr, idxs, bb); + return new GetElementPtrInst(ptr, idxs, bb); } StoreInst::StoreInst(Value *val, Value *ptr, BasicBlock *bb) - : BaseInst(bb->get_module()->get_void_type(), store, bb) { + : Instruction(bb->get_module()->get_void_type(), store, bb) { assert((ptr->get_type()->get_pointer_element_type() == val->get_type()) && "StoreInst ptr is not a pointer to val type"); add_operand(val); @@ -270,11 +270,11 @@ StoreInst::StoreInst(Value *val, Value *ptr, BasicBlock *bb) } StoreInst *StoreInst::create_store(Value *val, Value *ptr, BasicBlock *bb) { - return create(val, ptr, bb); + return new StoreInst(val, ptr, bb); } LoadInst::LoadInst(Value *ptr, BasicBlock *bb) - : BaseInst(ptr->get_type()->get_pointer_element_type(), load, + : Instruction(ptr->get_type()->get_pointer_element_type(), load, bb) { assert((get_type()->is_integer_type() or get_type()->is_float_type() or get_type()->is_pointer_type()) && @@ -283,12 +283,12 @@ LoadInst::LoadInst(Value *ptr, BasicBlock *bb) } LoadInst *LoadInst::create_load(Value *ptr, BasicBlock *bb) { - return create(ptr, bb); + return new LoadInst(ptr, bb); } AllocaInst::AllocaInst(Type *ty, BasicBlock *bb) - : BaseInst(PointerType::get(ty), alloca, bb) { - static constexpr std::array allowed_alloc_type = { + : Instruction(PointerType::get(ty), alloca, bb) { + static constexpr std::array allowed_alloc_type = { Type::IntegerTyID, Type::FloatTyID, Type::ArrayTyID, Type::PointerTyID}; assert(std::find(allowed_alloc_type.begin(), allowed_alloc_type.end(), ty->get_type_id()) != allowed_alloc_type.end() && @@ -296,11 +296,11 @@ AllocaInst::AllocaInst(Type *ty, BasicBlock *bb) } AllocaInst *AllocaInst::create_alloca(Type *ty, BasicBlock *bb) { - return create(ty, bb); + return new AllocaInst(ty, bb); } ZextInst::ZextInst(Value *val, Type *ty, BasicBlock *bb) - : BaseInst(ty, zext, bb) { + : Instruction(ty, zext, bb) { assert(val->get_type()->is_integer_type() && "ZextInst operand is not integer"); assert(ty->is_integer_type() && "ZextInst destination type is not integer"); @@ -312,14 +312,14 @@ ZextInst::ZextInst(Value *val, Type *ty, BasicBlock *bb) } ZextInst *ZextInst::create_zext(Value *val, Type *ty, BasicBlock *bb) { - return create(val, ty, bb); + return new ZextInst(val, ty, bb); } ZextInst *ZextInst::create_zext_to_i32(Value *val, BasicBlock *bb) { - return create(val, bb->get_module()->get_int32_type(), bb); + return new ZextInst(val, bb->get_module()->get_int32_type(), bb); } FpToSiInst::FpToSiInst(Value *val, Type *ty, BasicBlock *bb) - : BaseInst(ty, fptosi, bb) { + : Instruction(ty, fptosi, bb) { assert(val->get_type()->is_float_type() && "FpToSiInst operand is not float"); assert(ty->is_integer_type() && @@ -328,14 +328,14 @@ FpToSiInst::FpToSiInst(Value *val, Type *ty, BasicBlock *bb) } FpToSiInst *FpToSiInst::create_fptosi(Value *val, Type *ty, BasicBlock *bb) { - return create(val, ty, bb); + return new FpToSiInst(val, ty, bb); } FpToSiInst *FpToSiInst::create_fptosi_to_i32(Value *val, BasicBlock *bb) { - return create(val, bb->get_module()->get_int32_type(), bb); + return new FpToSiInst(val, bb->get_module()->get_int32_type(), bb); } SiToFpInst::SiToFpInst(Value *val, Type *ty, BasicBlock *bb) - : BaseInst(ty, sitofp, bb) { + : Instruction(ty, sitofp, bb) { assert(val->get_type()->is_integer_type() && "SiToFpInst operand is not integer"); assert(ty->is_float_type() && "SiToFpInst destination type is not float"); @@ -343,12 +343,12 @@ SiToFpInst::SiToFpInst(Value *val, Type *ty, BasicBlock *bb) } SiToFpInst *SiToFpInst::create_sitofp(Value *val, BasicBlock *bb) { - return create(val, bb->get_module()->get_float_type(), bb); + return new SiToFpInst(val, bb->get_module()->get_float_type(), bb); } PhiInst::PhiInst(Type *ty, const std::vector& vals, const std::vector& val_bbs, BasicBlock *bb) - : BaseInst(ty, phi) { + : Instruction(ty, phi) { assert(vals.size() == val_bbs.size() && "Unmatched vals and bbs"); for (unsigned i = 0; i < vals.size(); i++) { assert(ty == vals[i]->get_type() && "Bad type for phi"); @@ -361,5 +361,5 @@ PhiInst::PhiInst(Type *ty, const std::vector& vals, PhiInst *PhiInst::create_phi(Type *ty, BasicBlock *bb, const std::vector& vals, const std::vector& val_bbs) { - return create(ty, vals, val_bbs, bb); + return new PhiInst(ty, vals, val_bbs, bb); } diff --git a/src/lightir/Type.cpp b/src/lightir/Type.cpp index d5106cba4a0d46005cc45f2eb7324081e8583363..bc84cf3965815a793575ed6274a7bc358ea712c9 100755 --- a/src/lightir/Type.cpp +++ b/src/lightir/Type.cpp @@ -111,6 +111,52 @@ std::string Type::print() const { return type_ir; } +std::string Type::safe_print() const +{ + switch (this->get_type_id()) { + case VoidTyID: + return "void"; + case LabelTyID: + return "label"; + case IntegerTyID: + { + auto ty = dynamic_cast(this); + if (ty == nullptr) return ""; + return "i" + std::to_string(ty->get_num_bits()); + } + case FunctionTyID: + { + auto ty = dynamic_cast(this); + if (ty == nullptr) return ""; + auto ty2 = ty->get_return_type(); + std::string type_ir = (ty2 == nullptr ? "" : ty2->safe_print()) + " ("; + for (unsigned i = 0; i < ty->get_num_of_args(); i++) { + if (i) type_ir += ", "; + ty2 = ty->get_param_type(i); + type_ir += (ty2 == nullptr ? "" : ty2->safe_print()); + } + return type_ir + ")"; + } + case PointerTyID: + { + auto ty = dynamic_cast(this); + if (ty == nullptr) return ""; + auto ty2 = ty->get_element_type(); + return (ty2 == nullptr ? "" : ty2->safe_print()) + "*"; + } + case ArrayTyID: + { + auto ty = dynamic_cast(this); + if (ty == nullptr) return ""; + auto ty2 = ty->get_element_type(); + return "[" + std::to_string(ty->get_num_of_elements()) + "x" + (ty2 == nullptr ? "" : ty2->safe_print()) + "]"; + } + case FloatTyID: + return "float"; + } + return ""; +} + IntegerType::IntegerType(unsigned num_bits, Module *m) : Type(Type::IntegerTyID, m), num_bits_(num_bits) { diff --git a/src/lightir/Value.cpp b/src/lightir/Value.cpp index 517457e6600cec6149851ee6c4f59ab0a303a55f..f41ec7a7174b09b44a1e8cf9a76469a040e4c1f6 100755 --- a/src/lightir/Value.cpp +++ b/src/lightir/Value.cpp @@ -1,5 +1,6 @@ #include "Value.hpp" #include "User.hpp" +#include "util.hpp" Value::~Value() { replace_all_use_with(nullptr); } @@ -42,3 +43,9 @@ void Value::replace_use_with_if(Value *new_val, use.val_->set_operand(use.arg_no_, new_val); } } + +std::string Value::safe_get_name_or_ptr() const +{ + if (name_.empty()) return ptr_to_str(this); + return name_; +}