Commit a6d37a3d authored by Yang's avatar Yang

switch to clang

parent 5d4ea841
CompileFlags:
Add: [-std=c++17]
\ No newline at end of file
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()
......
#ifndef UTIL_HPP
#define UTIL_HPP
#include "string"
std::string ptr_to_str(const void* ptr);
#endif
\ No newline at end of file
......@@ -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);
......
......@@ -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:
};
......
......@@ -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<BasicBlock*> basic_blocks_;
std::list<Argument> 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.
......
......@@ -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;
......
......@@ -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 <typename Inst> class BaseInst : public Instruction {
protected:
template <typename... Args> static Inst *create(Args &&...args) {
return new Inst(std::forward<Args>(args)...);
}
template <typename... Args>
BaseInst(Args &&...args) : Instruction(std::forward<Args>(args)...) {}
};
class IBinaryInst : public BaseInst<IBinaryInst> {
friend BaseInst<IBinaryInst>;
class IBinaryInst : public Instruction {
private:
IBinaryInst(OpID id, Value *v1, Value *v2, BasicBlock *bb);
......@@ -141,8 +132,7 @@ class IBinaryInst : public BaseInst<IBinaryInst> {
std::string print() override;
};
class FBinaryInst : public BaseInst<FBinaryInst> {
friend BaseInst<FBinaryInst>;
class FBinaryInst : public Instruction {
private:
FBinaryInst(OpID id, Value *v1, Value *v2, BasicBlock *bb);
......@@ -156,13 +146,13 @@ class FBinaryInst : public BaseInst<FBinaryInst> {
std::string print() override;
};
class ICmpInst : public BaseInst<ICmpInst> {
friend BaseInst<ICmpInst>;
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<ICmpInst> {
std::string print() override;
};
class FCmpInst : public BaseInst<FCmpInst> {
friend BaseInst<FCmpInst>;
class FCmpInst : public Instruction {
private:
FCmpInst(OpID id, Value *lhs, Value *rhs, BasicBlock *bb);
......@@ -190,8 +179,7 @@ class FCmpInst : public BaseInst<FCmpInst> {
std::string print() override;
};
class CallInst : public BaseInst<CallInst> {
friend BaseInst<CallInst>;
class CallInst : public Instruction {
protected:
CallInst(Function *func, const std::vector<Value *>& args, BasicBlock *bb);
......@@ -204,15 +192,14 @@ class CallInst : public BaseInst<CallInst> {
std::string print() override;
};
class BranchInst : public BaseInst<BranchInst> {
friend BaseInst<BranchInst>;
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<ReturnInst> {
friend BaseInst<ReturnInst>;
class ReturnInst : public Instruction {
private:
ReturnInst(Value *val, BasicBlock *bb);
......@@ -243,8 +229,7 @@ class ReturnInst : public BaseInst<ReturnInst> {
std::string print() override;
};
class GetElementPtrInst : public BaseInst<GetElementPtrInst> {
friend BaseInst<GetElementPtrInst>;
class GetElementPtrInst : public Instruction {
private:
GetElementPtrInst(Value *ptr, const std::vector<Value *>& idxs, BasicBlock *bb);
......@@ -258,8 +243,7 @@ class GetElementPtrInst : public BaseInst<GetElementPtrInst> {
std::string print() override;
};
class StoreInst : public BaseInst<StoreInst> {
friend BaseInst<StoreInst>;
class StoreInst : public Instruction {
StoreInst(Value *val, Value *ptr, BasicBlock *bb);
......@@ -272,8 +256,7 @@ class StoreInst : public BaseInst<StoreInst> {
std::string print() override;
};
class LoadInst : public BaseInst<LoadInst> {
friend BaseInst<LoadInst>;
class LoadInst : public Instruction {
LoadInst(Value *ptr, BasicBlock *bb);
......@@ -286,8 +269,7 @@ class LoadInst : public BaseInst<LoadInst> {
std::string print() override;
};
class AllocaInst : public BaseInst<AllocaInst> {
friend BaseInst<AllocaInst>;
class AllocaInst : public Instruction {
AllocaInst(Type *ty, BasicBlock *bb);
......@@ -302,8 +284,7 @@ class AllocaInst : public BaseInst<AllocaInst> {
std::string print() override;
};
class ZextInst : public BaseInst<ZextInst> {
friend BaseInst<ZextInst>;
class ZextInst : public Instruction {
private:
ZextInst(Value *val, Type *ty, BasicBlock *bb);
......@@ -317,8 +298,7 @@ class ZextInst : public BaseInst<ZextInst> {
std::string print() override;
};
class FpToSiInst : public BaseInst<FpToSiInst> {
friend BaseInst<FpToSiInst>;
class FpToSiInst : public Instruction {
private:
FpToSiInst(Value *val, Type *ty, BasicBlock *bb);
......@@ -332,8 +312,7 @@ class FpToSiInst : public BaseInst<FpToSiInst> {
std::string print() override;
};
class SiToFpInst : public BaseInst<SiToFpInst> {
friend BaseInst<SiToFpInst>;
class SiToFpInst : public Instruction {
private:
SiToFpInst(Value *val, Type *ty, BasicBlock *bb);
......@@ -346,8 +325,7 @@ class SiToFpInst : public BaseInst<SiToFpInst> {
std::string print() override;
};
class PhiInst : public BaseInst<PhiInst> {
friend BaseInst<PhiInst>;
class PhiInst : public Instruction {
private:
PhiInst(Type *ty, const std::vector<Value *>& vals,
......
......@@ -53,6 +53,9 @@ class Type {
std::string print() const;
// 用于 lldb 调试生成 summary
std::string safe_print() const;
private:
TypeID tid_;
Module *m_;
......
......@@ -57,6 +57,8 @@ class Value {
return dynamic_cast<const T*>(this);
}
// 用于 lldb 调试生成 summary
std::string safe_get_name_or_ptr() const;
private:
Type *type_;
std::list<Use> use_list_; // who use this value
......
......@@ -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
......@@ -2,7 +2,7 @@ add_library(common STATIC
syntax_tree.c
ast.cpp
logging.cpp
)
util.cpp)
target_link_libraries(common)
#include "util.hpp"
std::string ptr_to_str(const void* ptr)
{
const char* translate = "0123456789abcdef";
uintptr_t addr = reinterpret_cast<uintptr_t>(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], '>'};
}
......@@ -3,6 +3,7 @@
#include "Function.hpp"
#include "IRprinter.hpp"
#include "Module.hpp"
#include "util.hpp"
#include <cassert>
......@@ -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<null>");
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;
......
......@@ -31,6 +31,53 @@ static std::unordered_map<Type *, std::unique_ptr<ConstantZero>> cached_zero;
Constant::~Constant() = default;
std::string Constant::safe_print() const
{
Type* ty = this->get_type();
return (ty == nullptr ? "<null>" : get_type()->safe_print()) + " " + safe_print_help();
}
std::string Constant::safe_print_help() const
{
if (dynamic_cast<const ConstantZero*>(this))
{
return "zeroinitializer";
}
if (auto constant = dynamic_cast<const ConstantInt*>(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<const ConstantFP*>(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<const ConstantArray*>(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 ? "<null>" : element->safe_print_help());
if (i < constant->get_size_of_array()) {
const_ir += ", ";
}
}
const_ir += "]";
return const_ir;
}
return "<error>";
}
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<IntegerType *>(ty)->get_num_bits() == 1) {
dynamic_cast<IntegerType *>(ty)->get_num_bits() == 1) {
// int1
const_ir += (this->get_value() == 0) ? "false" : "true";
} else {
......
......@@ -6,7 +6,7 @@
#include <unordered_set>
#include <queue>
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<FunctionType *>(get_type());
FunctionType* Function::get_function_type() const {
return dynamic_cast<FunctionType*>(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<unsigned>(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<Value *, int> seq;
for (auto &arg : this->get_args()) {
std::map<Value*, int> 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<FunctionType *>(this->get_type())
func_ir += dynamic_cast<FunctionType*>(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 "@<null> arg" + std::to_string(arg_no_) + " <unknow type>";
}
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_) + " <unknow type>";
auto ty2 = ty->get_param_type(arg_no_);
return "@" + parent->get_name() + " arg" + std::to_string(arg_no_) + " " + (ty2 == nullptr ? "<null>" : 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<BasicBlock*> suc_table;
std::unordered_set<BasicBlock*> 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<BasicBlock*>(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;
}
......@@ -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 ? "<null>" : 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 ? "<null>" : ty3->safe_print());
}
return func_ir + ") " + std::to_string(basic_blocks_.size()) + "b";
}
......@@ -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 += "<null> ";
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) {
......
This diff is collapsed.
This diff is collapsed.
......@@ -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<const IntegerType*>(this);
if (ty == nullptr) return "<not IntegerType>";
return "i" + std::to_string(ty->get_num_bits());
}
case FunctionTyID:
{
auto ty = dynamic_cast<const FunctionType*>(this);
if (ty == nullptr) return "<not FunctionType>";
auto ty2 = ty->get_return_type();
std::string type_ir = (ty2 == nullptr ? "<null>" : 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 ? "<null>" : ty2->safe_print());
}
return type_ir + ")";
}
case PointerTyID:
{
auto ty = dynamic_cast<const PointerType*>(this);
if (ty == nullptr) return "<not PointerType>";
auto ty2 = ty->get_element_type();
return (ty2 == nullptr ? "<null>" : ty2->safe_print()) + "*";
}
case ArrayTyID:
{
auto ty = dynamic_cast<const ArrayType*>(this);
if (ty == nullptr) return "<not ArrayType>";
auto ty2 = ty->get_element_type();
return "[" + std::to_string(ty->get_num_of_elements()) + "x" + (ty2 == nullptr ? "<null>" : ty2->safe_print()) + "]";
}
case FloatTyID:
return "float";
}
return "<error>";
}
IntegerType::IntegerType(unsigned num_bits, Module *m)
: Type(Type::IntegerTyID, m), num_bits_(num_bits)
{
......
#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_;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment