[midend-llvmirprint]实现了大部分函数的print方法,TODO:需要完善func和module的print方法以及重命名的逻辑
This commit is contained in:
@@ -83,6 +83,7 @@ class Type {
|
|||||||
auto as() const -> std::enable_if_t<std::is_base_of_v<Type, T>, T *> {
|
auto as() const -> std::enable_if_t<std::is_base_of_v<Type, T>, T *> {
|
||||||
return dynamic_cast<T *>(const_cast<Type *>(this));
|
return dynamic_cast<T *>(const_cast<Type *>(this));
|
||||||
}
|
}
|
||||||
|
virtual void print(std::ostream& os) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class PointerType : public Type {
|
class PointerType : public Type {
|
||||||
@@ -97,6 +98,7 @@ class PointerType : public Type {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
Type* getBaseType() const { return baseType; } ///< 获取指向的类型
|
Type* getBaseType() const { return baseType; } ///< 获取指向的类型
|
||||||
|
void print(std::ostream& os) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class FunctionType : public Type {
|
class FunctionType : public Type {
|
||||||
@@ -116,6 +118,7 @@ class FunctionType : public Type {
|
|||||||
Type* getReturnType() const { return returnType; } ///< 获取返回值类信息
|
Type* getReturnType() const { return returnType; } ///< 获取返回值类信息
|
||||||
auto getParamTypes() const { return make_range(paramTypes); } ///< 获取形参类型列表
|
auto getParamTypes() const { return make_range(paramTypes); } ///< 获取形参类型列表
|
||||||
unsigned getNumParams() const { return paramTypes.size(); } ///< 获取形参数量
|
unsigned getNumParams() const { return paramTypes.size(); } ///< 获取形参数量
|
||||||
|
void print(std::ostream& os) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ArrayType : public Type {
|
class ArrayType : public Type {
|
||||||
@@ -132,6 +135,7 @@ class ArrayType : public Type {
|
|||||||
: Type(Kind::kArray), elementType(elementType), numElements(numElements) {}
|
: Type(Kind::kArray), elementType(elementType), numElements(numElements) {}
|
||||||
Type *elementType;
|
Type *elementType;
|
||||||
unsigned numElements; // 当前维度的大小
|
unsigned numElements; // 当前维度的大小
|
||||||
|
void print(std::ostream& os) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -206,6 +210,7 @@ class Use {
|
|||||||
User* getUser() const { return user; } ///< 返回使用者
|
User* getUser() const { return user; } ///< 返回使用者
|
||||||
Value* getValue() const { return value; } ///< 返回被使用的值
|
Value* getValue() const { return value; } ///< 返回被使用的值
|
||||||
void setValue(Value *newValue) { value = newValue; } ///< 将被使用的值设置为newValue
|
void setValue(Value *newValue) { value = newValue; } ///< 将被使用的值设置为newValue
|
||||||
|
void print(std::ostream& os) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
//! The base class of all value types
|
//! The base class of all value types
|
||||||
@@ -238,6 +243,7 @@ class Value {
|
|||||||
uses.remove(use);
|
uses.remove(use);
|
||||||
} ///< 删除使用关系use
|
} ///< 删除使用关系use
|
||||||
void removeAllUses();
|
void removeAllUses();
|
||||||
|
virtual void print(std::ostream& os) const = 0; ///< 输出值信息到输出流
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -402,6 +408,7 @@ public:
|
|||||||
|
|
||||||
virtual bool isZero() const = 0;
|
virtual bool isZero() const = 0;
|
||||||
virtual bool isOne() const = 0;
|
virtual bool isOne() const = 0;
|
||||||
|
void print(std::ostream& os) const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ConstantInteger : public ConstantValue {
|
class ConstantInteger : public ConstantValue {
|
||||||
@@ -428,6 +435,7 @@ public:
|
|||||||
|
|
||||||
bool isZero() const override { return constVal == 0; }
|
bool isZero() const override { return constVal == 0; }
|
||||||
bool isOne() const override { return constVal == 1; }
|
bool isOne() const override { return constVal == 1; }
|
||||||
|
void print(std::ostream& os) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ConstantFloating : public ConstantValue {
|
class ConstantFloating : public ConstantValue {
|
||||||
@@ -454,6 +462,7 @@ public:
|
|||||||
|
|
||||||
bool isZero() const override { return constFVal == 0.0f; }
|
bool isZero() const override { return constFVal == 0.0f; }
|
||||||
bool isOne() const override { return constFVal == 1.0f; }
|
bool isOne() const override { return constFVal == 1.0f; }
|
||||||
|
void print(std::ostream& os) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class UndefinedValue : public ConstantValue {
|
class UndefinedValue : public ConstantValue {
|
||||||
@@ -485,6 +494,7 @@ public:
|
|||||||
|
|
||||||
bool isZero() const override { return false; }
|
bool isZero() const override { return false; }
|
||||||
bool isOne() const override { return false; }
|
bool isOne() const override { return false; }
|
||||||
|
void print(std::ostream& os) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- End of refactored ConstantValue and related classes ---
|
// --- End of refactored ConstantValue and related classes ---
|
||||||
@@ -625,6 +635,7 @@ public:
|
|||||||
}
|
}
|
||||||
} ///< 移除指定位置的指令
|
} ///< 移除指定位置的指令
|
||||||
iterator moveInst(iterator sourcePos, iterator targetPos, BasicBlock *block);
|
iterator moveInst(iterator sourcePos, iterator targetPos, BasicBlock *block);
|
||||||
|
void print(std::ostream& os) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
//! User is the abstract base type of `Value` types which use other `Value` as
|
//! User is the abstract base type of `Value` types which use other `Value` as
|
||||||
@@ -736,57 +747,57 @@ public:
|
|||||||
std::string getKindString() const{
|
std::string getKindString() const{
|
||||||
switch (kind) {
|
switch (kind) {
|
||||||
case kInvalid:
|
case kInvalid:
|
||||||
return "Invalid";
|
return "invalid";
|
||||||
case kAdd:
|
case kAdd:
|
||||||
return "Add";
|
return "add";
|
||||||
case kSub:
|
case kSub:
|
||||||
return "Sub";
|
return "sub";
|
||||||
case kMul:
|
case kMul:
|
||||||
return "Mul";
|
return "mul";
|
||||||
case kDiv:
|
case kDiv:
|
||||||
return "Div";
|
return "sdiv";
|
||||||
case kRem:
|
case kRem:
|
||||||
return "Rem";
|
return "srem";
|
||||||
case kICmpEQ:
|
case kICmpEQ:
|
||||||
return "ICmpEQ";
|
return "icmp eq";
|
||||||
case kICmpNE:
|
case kICmpNE:
|
||||||
return "ICmpNE";
|
return "icmp ne";
|
||||||
case kICmpLT:
|
case kICmpLT:
|
||||||
return "ICmpLT";
|
return "icmp slt";
|
||||||
case kICmpGT:
|
case kICmpGT:
|
||||||
return "ICmpGT";
|
return "icmp sgt";
|
||||||
case kICmpLE:
|
case kICmpLE:
|
||||||
return "ICmpLE";
|
return "icmp sle";
|
||||||
case kICmpGE:
|
case kICmpGE:
|
||||||
return "ICmpGE";
|
return "icmp sge";
|
||||||
case kFAdd:
|
case kFAdd:
|
||||||
return "FAdd";
|
return "fadd";
|
||||||
case kFSub:
|
case kFSub:
|
||||||
return "FSub";
|
return "fsub";
|
||||||
case kFMul:
|
case kFMul:
|
||||||
return "FMul";
|
return "fmul";
|
||||||
case kFDiv:
|
case kFDiv:
|
||||||
return "FDiv";
|
return "fdiv";
|
||||||
case kFCmpEQ:
|
case kFCmpEQ:
|
||||||
return "FCmpEQ";
|
return "fcmp oeq";
|
||||||
case kFCmpNE:
|
case kFCmpNE:
|
||||||
return "FCmpNE";
|
return "fcmp one";
|
||||||
case kFCmpLT:
|
case kFCmpLT:
|
||||||
return "FCmpLT";
|
return "fcmp olt";
|
||||||
case kFCmpGT:
|
case kFCmpGT:
|
||||||
return "FCmpGT";
|
return "fcmp ogt";
|
||||||
case kFCmpLE:
|
case kFCmpLE:
|
||||||
return "FCmpLE";
|
return "fcmp ole";
|
||||||
case kFCmpGE:
|
case kFCmpGE:
|
||||||
return "FCmpGE";
|
return "fcmp oge";
|
||||||
case kAnd:
|
case kAnd:
|
||||||
return "And";
|
return "and";
|
||||||
case kOr:
|
case kOr:
|
||||||
return "Or";
|
return "or";
|
||||||
case kNeg:
|
case kNeg:
|
||||||
return "Neg";
|
return "neg";
|
||||||
case kNot:
|
case kNot:
|
||||||
return "Not";
|
return "not";
|
||||||
case kFNeg:
|
case kFNeg:
|
||||||
return "FNeg";
|
return "FNeg";
|
||||||
case kFNot:
|
case kFNot:
|
||||||
@@ -794,27 +805,29 @@ public:
|
|||||||
case kFtoI:
|
case kFtoI:
|
||||||
return "FtoI";
|
return "FtoI";
|
||||||
case kItoF:
|
case kItoF:
|
||||||
return "IToF";
|
return "iToF";
|
||||||
case kCall:
|
case kCall:
|
||||||
return "Call";
|
return "call";
|
||||||
case kCondBr:
|
case kCondBr:
|
||||||
return "CondBr";
|
return "condBr";
|
||||||
case kBr:
|
case kBr:
|
||||||
return "Br";
|
return "br";
|
||||||
case kReturn:
|
case kReturn:
|
||||||
return "Return";
|
return "return";
|
||||||
|
case kUnreachable:
|
||||||
|
return "unreachable";
|
||||||
case kAlloca:
|
case kAlloca:
|
||||||
return "Alloca";
|
return "alloca";
|
||||||
case kLoad:
|
case kLoad:
|
||||||
return "Load";
|
return "load";
|
||||||
case kStore:
|
case kStore:
|
||||||
return "Store";
|
return "store";
|
||||||
case kGetElementPtr:
|
case kGetElementPtr:
|
||||||
return "GetElementPtr";
|
return "getElementPtr";
|
||||||
case kMemset:
|
case kMemset:
|
||||||
return "Memset";
|
return "memset";
|
||||||
case kPhi:
|
case kPhi:
|
||||||
return "Phi";
|
return "phi";
|
||||||
case kBitItoF:
|
case kBitItoF:
|
||||||
return "BitItoF";
|
return "BitItoF";
|
||||||
case kBitFtoI:
|
case kBitFtoI:
|
||||||
@@ -887,6 +900,7 @@ public:
|
|||||||
static constexpr uint64_t DefineOpMask = kAlloca | kStore | kPhi;
|
static constexpr uint64_t DefineOpMask = kAlloca | kStore | kPhi;
|
||||||
return (kind & DefineOpMask) != 0U;
|
return (kind & DefineOpMask) != 0U;
|
||||||
}
|
}
|
||||||
|
virtual void print(std::ostream& os) const = 0;
|
||||||
}; // class Instruction
|
}; // class Instruction
|
||||||
|
|
||||||
class Function;
|
class Function;
|
||||||
@@ -957,6 +971,7 @@ class PhiInst : public Instruction {
|
|||||||
}
|
}
|
||||||
} ///< 刷新块到值的映射关系
|
} ///< 刷新块到值的映射关系
|
||||||
auto getValues() { return make_range(std::next(operand_begin()), operand_end()); }
|
auto getValues() { return make_range(std::next(operand_begin()), operand_end()); }
|
||||||
|
void print(std::ostream& os) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -965,16 +980,20 @@ class CallInst : public Instruction {
|
|||||||
friend class IRBuilder;
|
friend class IRBuilder;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
CallInst(Function *callee, const std::vector<Value *> &args = {},
|
CallInst(Function *callee, const std::vector<Value *> &args, BasicBlock *parent = nullptr, const std::string &name = "")
|
||||||
BasicBlock *parent = nullptr, const std::string &name = "");
|
: Instruction(kCall, callee->getReturnType(), parent, name) {
|
||||||
|
addOperand(callee);
|
||||||
|
for (auto arg : args) {
|
||||||
|
addOperand(arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Function* getCallee() const;
|
Function *getCallee() const { return dynamic_cast<Function *>(getOperand(0)); }
|
||||||
auto getArguments() const {
|
auto getArguments() const {
|
||||||
return make_range(std::next(operand_begin()), operand_end());
|
return make_range(std::next(operand_begin()), operand_end());
|
||||||
}
|
}
|
||||||
|
void print(std::ostream& os) const override;
|
||||||
}; // class CallInst
|
}; // class CallInst
|
||||||
|
|
||||||
//! Unary instruction, includes '!', '-' and type conversion.
|
//! Unary instruction, includes '!', '-' and type conversion.
|
||||||
@@ -992,7 +1011,7 @@ protected:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
Value* getOperand() const { return User::getOperand(0); }
|
Value* getOperand() const { return User::getOperand(0); }
|
||||||
|
void print(std::ostream& os) const override;
|
||||||
}; // class UnaryInst
|
}; // class UnaryInst
|
||||||
|
|
||||||
//! Binary instruction, e.g., arithmatic, relation, logic, etc.
|
//! Binary instruction, e.g., arithmatic, relation, logic, etc.
|
||||||
@@ -1071,6 +1090,7 @@ public:
|
|||||||
// 后端处理数组访存操作时需要创建计算地址的指令,需要在外部构造 BinaryInst 对象
|
// 后端处理数组访存操作时需要创建计算地址的指令,需要在外部构造 BinaryInst 对象
|
||||||
return new BinaryInst(kind, type, lhs, rhs, parent, name);
|
return new BinaryInst(kind, type, lhs, rhs, parent, name);
|
||||||
}
|
}
|
||||||
|
void print(std::ostream& os) const override;
|
||||||
}; // class BinaryInst
|
}; // class BinaryInst
|
||||||
|
|
||||||
//! The return statement
|
//! The return statement
|
||||||
@@ -1091,6 +1111,7 @@ class ReturnInst : public Instruction {
|
|||||||
Value* getReturnValue() const {
|
Value* getReturnValue() const {
|
||||||
return hasReturnValue() ? getOperand(0) : nullptr;
|
return hasReturnValue() ? getOperand(0) : nullptr;
|
||||||
}
|
}
|
||||||
|
void print(std::ostream& os) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
//! Unconditional branch
|
//! Unconditional branch
|
||||||
@@ -1120,7 +1141,7 @@ public:
|
|||||||
}
|
}
|
||||||
return succs;
|
return succs;
|
||||||
}
|
}
|
||||||
|
void print(std::ostream& os) const override;
|
||||||
}; // class UncondBrInst
|
}; // class UncondBrInst
|
||||||
|
|
||||||
//! Conditional branch
|
//! Conditional branch
|
||||||
@@ -1160,7 +1181,7 @@ public:
|
|||||||
}
|
}
|
||||||
return succs;
|
return succs;
|
||||||
}
|
}
|
||||||
|
void print(std::ostream& os) const override;
|
||||||
}; // class CondBrInst
|
}; // class CondBrInst
|
||||||
|
|
||||||
class UnreachableInst : public Instruction {
|
class UnreachableInst : public Instruction {
|
||||||
@@ -1168,7 +1189,7 @@ public:
|
|||||||
// 构造函数:设置指令类型为 kUnreachable
|
// 构造函数:设置指令类型为 kUnreachable
|
||||||
explicit UnreachableInst(const std::string& name, BasicBlock *parent = nullptr)
|
explicit UnreachableInst(const std::string& name, BasicBlock *parent = nullptr)
|
||||||
: Instruction(kUnreachable, Type::getVoidType(), parent, "") {}
|
: Instruction(kUnreachable, Type::getVoidType(), parent, "") {}
|
||||||
|
void print(std::ostream& os) const { os << "unreachable"; }
|
||||||
};
|
};
|
||||||
|
|
||||||
//! Allocate memory for stack variables, used for non-global variable declartion
|
//! Allocate memory for stack variables, used for non-global variable declartion
|
||||||
@@ -1186,7 +1207,7 @@ public:
|
|||||||
Type* getAllocatedType() const {
|
Type* getAllocatedType() const {
|
||||||
return getType()->as<PointerType>()->getBaseType();
|
return getType()->as<PointerType>()->getBaseType();
|
||||||
} ///< 获取分配的类型
|
} ///< 获取分配的类型
|
||||||
|
void print(std::ostream& os) const override;
|
||||||
}; // class AllocaInst
|
}; // class AllocaInst
|
||||||
|
|
||||||
|
|
||||||
@@ -1224,6 +1245,7 @@ public:
|
|||||||
BasicBlock *parent = nullptr, const std::string &name = "") {
|
BasicBlock *parent = nullptr, const std::string &name = "") {
|
||||||
return new GetElementPtrInst(resultType, basePointer, indices, parent, name);
|
return new GetElementPtrInst(resultType, basePointer, indices, parent, name);
|
||||||
}
|
}
|
||||||
|
void print(std::ostream& os) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
//! Load a value from memory address specified by a pointer value
|
//! Load a value from memory address specified by a pointer value
|
||||||
@@ -1241,7 +1263,7 @@ protected:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
Value* getPointer() const { return getOperand(0); }
|
Value* getPointer() const { return getOperand(0); }
|
||||||
|
void print(std::ostream& os) const override;
|
||||||
}; // class LoadInst
|
}; // class LoadInst
|
||||||
|
|
||||||
//! Store a value to memory address specified by a pointer value
|
//! Store a value to memory address specified by a pointer value
|
||||||
@@ -1260,7 +1282,7 @@ protected:
|
|||||||
public:
|
public:
|
||||||
Value* getValue() const { return getOperand(0); }
|
Value* getValue() const { return getOperand(0); }
|
||||||
Value* getPointer() const { return getOperand(1); }
|
Value* getPointer() const { return getOperand(1); }
|
||||||
|
void print(std::ostream& os) const override;
|
||||||
}; // class StoreInst
|
}; // class StoreInst
|
||||||
|
|
||||||
//! Memset instruction
|
//! Memset instruction
|
||||||
@@ -1290,7 +1312,7 @@ public:
|
|||||||
Value* getBegin() const { return getOperand(1); }
|
Value* getBegin() const { return getOperand(1); }
|
||||||
Value* getSize() const { return getOperand(2); }
|
Value* getSize() const { return getOperand(2); }
|
||||||
Value* getValue() const { return getOperand(3); }
|
Value* getValue() const { return getOperand(3); }
|
||||||
|
void print(std::ostream& os) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class GlobalValue;
|
class GlobalValue;
|
||||||
@@ -1308,6 +1330,7 @@ public:
|
|||||||
public:
|
public:
|
||||||
Function* getParent() const { return func; }
|
Function* getParent() const { return func; }
|
||||||
int getIndex() const { return index; }
|
int getIndex() const { return index; }
|
||||||
|
void print(std::ostream& os) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -1385,6 +1408,7 @@ protected:
|
|||||||
blocks.emplace_front(block);
|
blocks.emplace_front(block);
|
||||||
return block;
|
return block;
|
||||||
}
|
}
|
||||||
|
void print(std::ostream& os) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
//! Global value declared at file scope
|
//! Global value declared at file scope
|
||||||
@@ -1450,6 +1474,7 @@ public:
|
|||||||
return getByIndex(index);
|
return getByIndex(index);
|
||||||
} ///< 通过多维索引indices获取初始值
|
} ///< 通过多维索引indices获取初始值
|
||||||
const ValueCounter& getInitValues() const { return initValues; }
|
const ValueCounter& getInitValues() const { return initValues; }
|
||||||
|
void print(std::ostream& os) const;
|
||||||
}; // class GlobalValue
|
}; // class GlobalValue
|
||||||
|
|
||||||
|
|
||||||
@@ -1507,6 +1532,8 @@ class ConstantVariable : public Value {
|
|||||||
return getByIndex(index);
|
return getByIndex(index);
|
||||||
} ///< 通过多维索引indices获取初始值
|
} ///< 通过多维索引indices获取初始值
|
||||||
const ValueCounter& getInitValues() const { return initValues; } ///< 获取初始值
|
const ValueCounter& getInitValues() const { return initValues; } ///< 获取初始值
|
||||||
|
void print(std::ostream& os) const;
|
||||||
|
void print_init(std::ostream& os) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
using SymbolTableNode = struct SymbolTableNode {
|
using SymbolTableNode = struct SymbolTableNode {
|
||||||
@@ -1620,6 +1647,8 @@ class Module {
|
|||||||
void leaveScope() { variableTable.leaveScope(); } ///< 离开作用域
|
void leaveScope() { variableTable.leaveScope(); } ///< 离开作用域
|
||||||
|
|
||||||
bool isInGlobalArea() const { return variableTable.isInGlobalScope(); } ///< 是否位于全局作用域
|
bool isInGlobalArea() const { return variableTable.isInGlobalScope(); } ///< 是否位于全局作用域
|
||||||
|
|
||||||
|
void print(std::ostream& os) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
|||||||
@@ -5,9 +5,11 @@
|
|||||||
#include <queue>
|
#include <queue>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include <iomanip>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "IRBuilder.h"
|
#include "IRBuilder.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
/**
|
/**
|
||||||
* @file IR.cpp
|
* @file IR.cpp
|
||||||
*
|
*
|
||||||
@@ -15,6 +17,64 @@
|
|||||||
*/
|
*/
|
||||||
namespace sysy {
|
namespace sysy {
|
||||||
|
|
||||||
|
/*相关打印函数*/
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
ostream &interleave(std::ostream &os, const T &container, const std::string sep = ", ") {
|
||||||
|
auto b = container.begin(), e = container.end();
|
||||||
|
if (b == e)
|
||||||
|
return os;
|
||||||
|
os << *b;
|
||||||
|
for (b = std::next(b); b != e; b = std::next(b))
|
||||||
|
os << sep << *b;
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
ostream &interleave_call(std::ostream &os, const T &container, const std::string sep = ", ") {
|
||||||
|
auto b = container.begin(), e = container.end();
|
||||||
|
b = std::next(b); // Skip the first element
|
||||||
|
if (b == e)
|
||||||
|
return os;
|
||||||
|
os << *b;
|
||||||
|
for (b = std::next(b); b != e; b = std::next(b))
|
||||||
|
os << sep << *b;
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline ostream &printVarName(ostream &os, const Value *var)
|
||||||
|
{
|
||||||
|
if (dynamic_cast<const GlobalValue*>(var) != nullptr) {
|
||||||
|
auto globalVal = dynamic_cast<const GlobalValue*>(var);
|
||||||
|
return os << "@" << globalVal->getName();
|
||||||
|
} else {
|
||||||
|
return os << "%" << var->getName();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static inline ostream &printBlockName(ostream &os, const BasicBlock *block) {
|
||||||
|
return os << block->getName();
|
||||||
|
}
|
||||||
|
static inline ostream &printFunctionName(ostream &os, const Function *fn) {
|
||||||
|
return os << '@' << fn->getName();
|
||||||
|
}
|
||||||
|
static inline ostream &printOperand(ostream &os, const Value *value) {
|
||||||
|
auto constValue = dynamic_cast<const ConstantValue*>(value);
|
||||||
|
if (constValue != nullptr) {
|
||||||
|
constValue->print(os);
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
return printVarName(os, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::ostream& operator<<(std::ostream& os, const Type& type) {
|
||||||
|
type.print(os);
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::ostream& operator<<(std::ostream& os, const Value& value) {
|
||||||
|
value.print(os);
|
||||||
|
return os;
|
||||||
|
}
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// Types
|
// Types
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
@@ -73,6 +133,37 @@ auto Type::getSize() const -> unsigned {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Type::print(ostream &os) const {
|
||||||
|
auto kind = getKind();
|
||||||
|
switch (kind){
|
||||||
|
case kInt: os << "i32"; break;
|
||||||
|
case kFloat: os << "float"; break;
|
||||||
|
case kVoid: os << "void"; break;
|
||||||
|
case kPointer:
|
||||||
|
static_cast<const PointerType *>(this)->getBaseType()->print(os);
|
||||||
|
os << "*";
|
||||||
|
break;
|
||||||
|
case kFunction:
|
||||||
|
static_cast<const FunctionType *>(this)->getReturnType()->print(os);
|
||||||
|
os << "(";
|
||||||
|
interleave(os, static_cast<const FunctionType *>(this)->getParamTypes());
|
||||||
|
os << ")";
|
||||||
|
break;
|
||||||
|
case kArray:
|
||||||
|
os << "[";
|
||||||
|
os << static_cast<const ArrayType *>(this)->getNumElements();
|
||||||
|
os << " x ";
|
||||||
|
static_cast<const ArrayType *>(this)->getElementType()->print(os);
|
||||||
|
os << "]";
|
||||||
|
break;
|
||||||
|
case kLabel:
|
||||||
|
default:
|
||||||
|
cerr << "error type\n";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
PointerType* PointerType::get(Type *baseType) {
|
PointerType* PointerType::get(Type *baseType) {
|
||||||
static std::map<Type *, std::unique_ptr<PointerType>> pointerTypes;
|
static std::map<Type *, std::unique_ptr<PointerType>> pointerTypes;
|
||||||
auto iter = pointerTypes.find(baseType);
|
auto iter = pointerTypes.find(baseType);
|
||||||
@@ -204,6 +295,214 @@ UndefinedValue* UndefinedValue::get(Type* type) {
|
|||||||
return newUndef;
|
return newUndef;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline std::string getMachineCode(float fval) {
|
||||||
|
uint32_t mrf = *reinterpret_cast<uint32_t*>(&fval);
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << std::hex << std::uppercase << std::setfill('0') << std::setw(8) << mrf;
|
||||||
|
return "0x" + ss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConstantValue::print(std::ostream &os) const {
|
||||||
|
if(dynamic_cast<const ConstantInteger*>(this)) {
|
||||||
|
dynamic_cast<const ConstantInteger*>(this)->print(os);
|
||||||
|
} else if(dynamic_cast<const ConstantFloating*>(this)) {
|
||||||
|
dynamic_cast<const ConstantFloating*>(this)->print(os);
|
||||||
|
} else if(dynamic_cast<const UndefinedValue*>(this)) {
|
||||||
|
dynamic_cast<const UndefinedValue*>(this)->print(os);
|
||||||
|
} else {
|
||||||
|
os << "unknown constant type";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConstantInteger::print(std::ostream &os) const {
|
||||||
|
os << "i32 " << this->getInt();
|
||||||
|
}
|
||||||
|
void ConstantFloating::print(std::ostream &os) const {
|
||||||
|
os << "float " << getMachineCode(this->getFloat());
|
||||||
|
}
|
||||||
|
void UndefinedValue::print(std::ostream &os) const {
|
||||||
|
os << this->getType() << " undef";
|
||||||
|
}
|
||||||
|
|
||||||
|
void BasicBlock::print(std::ostream &os) const {
|
||||||
|
assert(this->getName() != "" && "BasicBlock name cannot be empty");
|
||||||
|
os << " ";
|
||||||
|
printBlockName(os, this);
|
||||||
|
os << ":\n";
|
||||||
|
for (auto &inst : instructions) {
|
||||||
|
os << " " << *inst << '\n';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PhiInst::print(std::ostream &os) const {
|
||||||
|
printVarName(os, this);
|
||||||
|
os << " = " << getKindString() << " " << *getType() << " ";
|
||||||
|
for (unsigned i = 0; i < vsize; ++i) {
|
||||||
|
if (i > 0) {
|
||||||
|
os << ", ";
|
||||||
|
}
|
||||||
|
os << " [";
|
||||||
|
printOperand(os, getIncomingValue(i));
|
||||||
|
os << ", ";
|
||||||
|
printBlockName(os, getIncomingBlock(i));
|
||||||
|
os << "]";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CallInst::print(std::ostream &os) const {
|
||||||
|
if(!getType()->isVoid()) {
|
||||||
|
printVarName(os, this) << " = ";
|
||||||
|
}
|
||||||
|
os << getKindString() << *getType() << " " ;
|
||||||
|
printFunctionName(os, getCallee());
|
||||||
|
os << "(";
|
||||||
|
interleave_call(os, getOperands());
|
||||||
|
os << ")";
|
||||||
|
}
|
||||||
|
|
||||||
|
// 情况比较复杂就不用getkindstring了
|
||||||
|
void UnaryInst::print(std::ostream &os) const {
|
||||||
|
printVarName(os, this) << " = ";
|
||||||
|
switch (getKind()) {
|
||||||
|
case kNeg:
|
||||||
|
os << "sub i32 0, ";
|
||||||
|
printOperand(os, getOperand());
|
||||||
|
break;
|
||||||
|
case kFNeg:
|
||||||
|
os << "fsub float 0.0, ";
|
||||||
|
printOperand(os, getOperand());
|
||||||
|
break;
|
||||||
|
case kNot:
|
||||||
|
os << "xor " << *getOperand()->getType() << " ";
|
||||||
|
printOperand(os, getOperand());
|
||||||
|
os << ", -1";
|
||||||
|
return;
|
||||||
|
case kFNot:
|
||||||
|
os << "fcmp une " << *getOperand()->getType() << " ";
|
||||||
|
printOperand(os, getOperand());
|
||||||
|
os << ", 0.0";
|
||||||
|
return;
|
||||||
|
case kFtoI:
|
||||||
|
os << "fptosi " << *getOperand()->getType() << " ";
|
||||||
|
printOperand(os, getOperand());
|
||||||
|
os << " to " << *getType();
|
||||||
|
return;
|
||||||
|
case kItoF:
|
||||||
|
os << "sitofp " << *getOperand()->getType() << " ";
|
||||||
|
printOperand(os, getOperand());
|
||||||
|
os << " to " << *getType();
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
os << "error unary inst";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void AllocaInst::print(std::ostream &os) const {
|
||||||
|
PointerType *ptrType = dynamic_cast<PointerType *>(getType());
|
||||||
|
Type *baseType = ptrType->getBaseType();
|
||||||
|
printVarName(os, this);
|
||||||
|
os << " = " << getKindString() << " " << *baseType;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BinaryInst::print(std::ostream &os) const {
|
||||||
|
printVarName(os, this) << " = ";
|
||||||
|
|
||||||
|
auto kind = getKind();
|
||||||
|
|
||||||
|
// 检查是否为比较指令
|
||||||
|
if (kind == kICmpEQ || kind == kICmpNE || kind == kICmpLT ||
|
||||||
|
kind == kICmpGT || kind == kICmpLE || kind == kICmpGE) {
|
||||||
|
// 整数比较指令
|
||||||
|
os << getKindString() << " " << *getLhs()->getType() << " ";
|
||||||
|
printOperand(os, getLhs());
|
||||||
|
os << ", ";
|
||||||
|
printOperand(os, getRhs());
|
||||||
|
} else if (kind == kFCmpEQ || kind == kFCmpNE || kind == kFCmpLT ||
|
||||||
|
kind == kFCmpGT || kind == kFCmpLE || kind == kFCmpGE) {
|
||||||
|
// 浮点比较指令
|
||||||
|
os << getKindString() << " " << *getLhs()->getType() << " ";
|
||||||
|
printOperand(os, getLhs());
|
||||||
|
os << ", ";
|
||||||
|
printOperand(os, getRhs());
|
||||||
|
} else {
|
||||||
|
// 算术和逻辑指令
|
||||||
|
os << getKindString() << " " << *getType() << " ";
|
||||||
|
printOperand(os, getLhs());
|
||||||
|
os << ", ";
|
||||||
|
printOperand(os, getRhs());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReturnInst::print(std::ostream &os) const {
|
||||||
|
os << "ret ";
|
||||||
|
if (hasReturnValue()) {
|
||||||
|
os << *getReturnValue()->getType() << " ";
|
||||||
|
printOperand(os, getReturnValue());
|
||||||
|
} else {
|
||||||
|
os << "void";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UncondBrInst::print(std::ostream &os) const {
|
||||||
|
os << "br label %";
|
||||||
|
printBlockName(os, getBlock());
|
||||||
|
}
|
||||||
|
|
||||||
|
void CondBrInst::print(std::ostream &os) const {
|
||||||
|
os << "br " << *getCondition()->getType() << " ";
|
||||||
|
printOperand(os, getCondition());
|
||||||
|
os << ", label %";
|
||||||
|
printBlockName(os, getThenBlock());
|
||||||
|
os << ", label %";
|
||||||
|
printBlockName(os, getElseBlock());
|
||||||
|
}
|
||||||
|
|
||||||
|
void GetElementPtrInst::print(std::ostream &os) const {
|
||||||
|
printVarName(os, this) << " = getelementptr ";
|
||||||
|
|
||||||
|
// 获取基指针的基类型
|
||||||
|
auto basePtr = getBasePointer();
|
||||||
|
auto basePtrType = basePtr->getType()->as<PointerType>();
|
||||||
|
auto baseType = basePtrType->getBaseType();
|
||||||
|
|
||||||
|
os << *baseType << ", " << *basePtr->getType() << " ";
|
||||||
|
printOperand(os, basePtr);
|
||||||
|
|
||||||
|
// 打印索引 - 使用getIndex方法而不是getIndices
|
||||||
|
for (unsigned i = 0; i < getNumIndices(); ++i) {
|
||||||
|
auto index = getIndex(i);
|
||||||
|
os << ", " << *index->getType() << " ";
|
||||||
|
printOperand(os, index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoadInst::print(std::ostream &os) const {
|
||||||
|
printVarName(os, this) << " = load " << *getType() << ", " << *getPointer()->getType() << " ";
|
||||||
|
printOperand(os, getPointer());
|
||||||
|
}
|
||||||
|
|
||||||
|
void MemsetInst::print(std::ostream &os) const {
|
||||||
|
os << "call void @llvm.memset.p0i8.i32(i8* ";
|
||||||
|
printOperand(os, getPointer());
|
||||||
|
os << ", i8 ";
|
||||||
|
printOperand(os, getOperand(3)); // value
|
||||||
|
os << ", i32 ";
|
||||||
|
printOperand(os, getOperand(2)); // size
|
||||||
|
os << ", i1 false)";
|
||||||
|
}
|
||||||
|
|
||||||
|
void StoreInst::print(std::ostream &os) const {
|
||||||
|
os << "store " << *getValue()->getType() << " ";
|
||||||
|
printOperand(os, getValue());
|
||||||
|
os << ", " << *getPointer()->getType() << " ";
|
||||||
|
printOperand(os, getPointer());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
auto Function::getCalleesWithNoExternalAndSelf() -> std::set<Function *> {
|
auto Function::getCalleesWithNoExternalAndSelf() -> std::set<Function *> {
|
||||||
std::set<Function *> result;
|
std::set<Function *> result;
|
||||||
@@ -389,17 +688,6 @@ void PhiInst::replaceIncomingBlock(BasicBlock *oldBlock, BasicBlock *newBlock, V
|
|||||||
addIncoming(newValue, newBlock);
|
addIncoming(newValue, newBlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
CallInst::CallInst(Function *callee, const std::vector<Value *> &args, BasicBlock *parent, const std::string &name)
|
|
||||||
: Instruction(kCall, callee->getReturnType(), parent, name) {
|
|
||||||
addOperand(callee);
|
|
||||||
for (auto arg : args) {
|
|
||||||
addOperand(arg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* 获取被调用函数的指针
|
|
||||||
*/
|
|
||||||
Function * CallInst::getCallee() const { return dynamic_cast<Function *>(getOperand(0)); }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取变量指针
|
* 获取变量指针
|
||||||
|
|||||||
Reference in New Issue
Block a user