1728 lines
60 KiB
C++
1728 lines
60 KiB
C++
#pragma once
|
||
|
||
#include "range.h"
|
||
#include <cassert>
|
||
#include <cstdint>
|
||
#include <iterator>
|
||
#include <list>
|
||
#include <map>
|
||
#include <memory>
|
||
#include <ostream>
|
||
#include <string>
|
||
#include <type_traits>
|
||
#include <vector>
|
||
#include <variant>
|
||
#include <unordered_map>
|
||
#include <cmath>
|
||
#include <set>
|
||
#include <unordered_set>
|
||
#include <queue>
|
||
#include <algorithm>
|
||
|
||
namespace sysy {
|
||
|
||
// Global cleanup function to release all statically allocated IR objects
|
||
void cleanupIRPools();
|
||
|
||
/**
|
||
* \defgroup type Types
|
||
* @brief Sysy的类型系统
|
||
*
|
||
* 1. 基类`Type` 用来表示所有的原始标量类型,
|
||
* 包括 `int`, `float`, `void`, 和表示跳转目标的标签类型。
|
||
* 2. `PointerType` 和 `FunctionType` 派生自`Type` 并且分别表示指针和函数类型。
|
||
*
|
||
* \note `Type`和它的派生类的构造函数声明为'protected'.
|
||
* 用户必须使用Type::getXXXType()获得`Type` 指针。
|
||
* @{
|
||
*/
|
||
|
||
/**
|
||
*
|
||
* `Type`用来表示所有的原始标量类型,
|
||
* 包括`int`, `float`, `void`, 和表示跳转目标的标签类型。
|
||
*/
|
||
|
||
class Type {
|
||
public:
|
||
/// 定义了原始标量类型种类的枚举类型
|
||
enum Kind {
|
||
kInt,
|
||
kFloat,
|
||
kVoid,
|
||
kLabel,
|
||
kPointer,
|
||
kFunction,
|
||
kArray,
|
||
};
|
||
|
||
Kind kind; ///< 表示具体类型的变量
|
||
|
||
protected:
|
||
explicit Type(Kind kind) : kind(kind) {}
|
||
virtual ~Type() = default;
|
||
|
||
public:
|
||
static Type* getIntType(); ///< 返回表示Int类型的Type指针
|
||
static Type* getFloatType(); ///< 返回表示Float类型的Type指针
|
||
static Type* getVoidType(); ///< 返回表示Void类型的Type指针
|
||
static Type* getLabelType(); ///< 返回表示Label类型的Type指针
|
||
static Type* getPointerType(Type *baseType); ///< 返回表示指向baseType类型的Pointer类型的Type指针
|
||
static Type* getFunctionType(Type *returnType, const std::vector<Type *> ¶mTypes = {});
|
||
///< 返回表示返回类型为returnType,形参类型列表为paramTypes的函数类型的Type指针
|
||
static Type* getArrayType(Type *elementType, unsigned numElements);
|
||
|
||
public:
|
||
Kind getKind() const { return kind; } ///< 返回Type对象代表原始标量类型
|
||
bool isInt() const { return kind == kInt; } ///< 判定是否为Int类型
|
||
bool isFloat() const { return kind == kFloat; } ///< 判定是否为Float类型
|
||
bool isVoid() const { return kind == kVoid; } ///< 判定是否为Void类型
|
||
bool isLabel() const { return kind == kLabel; } ///< 判定是否为Label类型
|
||
bool isPointer() const { return kind == kPointer; } ///< 判定是否为Pointer类型
|
||
bool isFunction() const { return kind == kFunction; } ///< 判定是否为Function类型
|
||
bool isArray() const { return kind == Kind::kArray; }
|
||
unsigned getSize() const; ///< 返回类型所占的空间大小(字节)
|
||
/// 尝试将一个变量转换为给定的Type及其派生类类型的变量
|
||
template <typename T>
|
||
auto as() const -> std::enable_if_t<std::is_base_of_v<Type, T>, T *> {
|
||
return dynamic_cast<T *>(const_cast<Type *>(this));
|
||
}
|
||
virtual void print(std::ostream& os) const;
|
||
};
|
||
|
||
class PointerType : public Type {
|
||
protected:
|
||
Type *baseType; ///< 所指向的类型
|
||
|
||
protected:
|
||
explicit PointerType(Type *baseType) : Type(kPointer), baseType(baseType) {}
|
||
|
||
public:
|
||
static PointerType* get(Type *baseType); ///< 获取指向baseType的Pointer类型
|
||
|
||
// Cleanup method to release all cached pointer types (call at program exit)
|
||
static void cleanup();
|
||
|
||
public:
|
||
Type* getBaseType() const { return baseType; } ///< 获取指向的类型
|
||
};
|
||
|
||
class FunctionType : public Type {
|
||
private:
|
||
Type *returnType; ///< 返回值类型
|
||
std::vector<Type *> paramTypes; ///< 形参类型列表
|
||
|
||
protected:
|
||
explicit FunctionType(Type *returnType, std::vector<Type *> paramTypes = {})
|
||
: Type(kFunction), returnType(returnType), paramTypes(std::move(paramTypes)) {}
|
||
|
||
public:
|
||
/// 获取返回值类型为returnType, 形参类型列表为paramTypes的Function类型
|
||
static FunctionType* get(Type *returnType, const std::vector<Type *> ¶mTypes = {});
|
||
|
||
// Cleanup method to release all cached function types (call at program exit)
|
||
static void cleanup();
|
||
|
||
public:
|
||
Type* getReturnType() const { return returnType; } ///< 获取返回值类信息
|
||
auto getParamTypes() const { return make_range(paramTypes); } ///< 获取形参类型列表
|
||
unsigned getNumParams() const { return paramTypes.size(); } ///< 获取形参数量
|
||
};
|
||
|
||
class ArrayType : public Type {
|
||
public:
|
||
// elements:数组的元素类型 (例如,int[3] 的 elementType 是 int)
|
||
// numElements:该维度的大小 (例如,int[3] 的 numElements 是 3)
|
||
static ArrayType *get(Type *elementType, unsigned numElements);
|
||
|
||
// Cleanup method to release all cached array types (call at program exit)
|
||
static void cleanup();
|
||
|
||
Type *getElementType() const { return elementType; }
|
||
unsigned getNumElements() const { return numElements; }
|
||
|
||
protected:
|
||
ArrayType(Type *elementType, unsigned numElements)
|
||
: Type(Kind::kArray), elementType(elementType), numElements(numElements) {}
|
||
Type *elementType;
|
||
unsigned numElements; // 当前维度的大小
|
||
};
|
||
|
||
/*!
|
||
* @}
|
||
*/
|
||
|
||
/**
|
||
* \defgroup ir IR
|
||
*
|
||
* TSysY IR 是一种指令级别的语言. 它被组织为四层树型结构,如下所示:
|
||
*
|
||
* \dot IR Structure
|
||
* digraph IRStructure{
|
||
* node [shape="box"]
|
||
* a [label="Module"]
|
||
* b [label="GlobalValue"]
|
||
* c [label="Function"]
|
||
* d [label="BasicBlock"]
|
||
* e [label="Instruction"]
|
||
* a->{b,c}
|
||
* c->d->e
|
||
* }
|
||
*
|
||
* \enddot
|
||
*
|
||
* - `Module` 对应顶层"CompUnit"语法结构
|
||
* - `GlobalValue`对应"globalDecl"语法结构
|
||
* - `Function`对应"FuncDef"语法结构
|
||
* - `BasicBlock` 是一连串没有分支指令的指令。一个 `Function`
|
||
* 由一个或多个`BasicBlock`组成
|
||
* - `Instruction` 表示一个原始指令,例如, add 或 sub
|
||
*
|
||
* SysY IR中基础的数据概念是`Value`。一个 `Value` 像
|
||
* 一个寄存器。它充当`Instruction`的输入输出操作数。每个value
|
||
* 都有一个与之相联系的`Type`,以此说明Value所拥有值的类型。
|
||
*
|
||
* 大多数`Instruction`具有三地址代码的结构, 例如, 最多拥有两个输入操作数和一个输出操作数。
|
||
*
|
||
* SysY IR采用了Static-Single-Assignment (SSA)设计。`Value`作为一个输出操作数
|
||
* 被一些指令所定义, 并被另一些指令当作输入操作数使用。尽管一个Value可以被多个指令使用,其
|
||
* 定义只能发生一次。这导致一个value个定义它的指令存在一一对应关系。换句话说,任何定义一个Value的指令
|
||
* 都可以被看作被定义的指令本身。故在SysY IR中,`Instruction` 也是一个`Value`。查看 `Value` 以获取其继承
|
||
* 关系。
|
||
*
|
||
* @{
|
||
*/
|
||
|
||
|
||
class User;
|
||
class Value;
|
||
class AllocaInst;
|
||
|
||
//! `Use` 表示`Value`和它的`User`之间的使用关系。
|
||
|
||
class Use {
|
||
private:
|
||
/**
|
||
* value在User操作数中的位置,例如,
|
||
* user->getOperands[index] == value
|
||
*/
|
||
unsigned index;
|
||
User *user; ///< 使用者
|
||
Value *value; ///< 被使用的值
|
||
|
||
public:
|
||
Use() = default;
|
||
Use(unsigned index, User *user, Value *value) : index(index), user(user), value(value) {}
|
||
|
||
public:
|
||
unsigned getIndex() const { return index; } ///< 返回value在User操作数中的位置
|
||
void setIndex(int newIndex) { index = newIndex; } ///< 设置value在User操作数中的位置
|
||
User* getUser() const { return user; } ///< 返回使用者
|
||
Value* getValue() const { return value; } ///< 返回被使用的值
|
||
void setValue(Value *newValue) { value = newValue; } ///< 将被使用的值设置为newValue
|
||
void print(std::ostream& os) const;
|
||
};
|
||
|
||
//! The base class of all value types
|
||
|
||
class Value {
|
||
protected:
|
||
Type *type; ///< 值的类型
|
||
std::string name; ///< 值的名字
|
||
std::list<std::shared_ptr<Use>> uses; ///< 值的使用关系列表
|
||
|
||
protected:
|
||
explicit Value(Type *type, std::string name = "") : type(type), name(std::move(name)) {}
|
||
virtual ~Value() = default;
|
||
|
||
public:
|
||
void setName(const std::string &newName) { name = newName; } ///< 设置名字
|
||
const std::string& getName() const { return name; } ///< 获取名字
|
||
Type* getType() const { return type; } ///< 返回值的类型
|
||
bool isInt() const { return type->isInt(); } ///< 判定是否为Int类型
|
||
bool isFloat() const { return type->isFloat(); } ///< 判定是否为Float类型
|
||
bool isPointer() const { return type->isPointer(); } ///< 判定是否为Pointer类型
|
||
std::list<std::shared_ptr<Use>>& getUses() { return uses; } ///< 获取使用关系列表
|
||
void addUse(const std::shared_ptr<Use> &use) { uses.push_back(use); } ///< 添加使用关系
|
||
void replaceAllUsesWith(Value *value); ///< 将原来使用该value的使用者全变为使用给定参数value并修改相应use关系
|
||
void removeUse(const std::shared_ptr<Use> &use) {
|
||
assert(use != nullptr && "Use cannot be null");
|
||
assert(use->getValue() == this && "Use being removed does NOT point to this Value!");
|
||
auto it = std::find(uses.begin(), uses.end(), use);
|
||
assert(it != uses.end() && "Use not found in Value's uses");
|
||
uses.remove(use);
|
||
} ///< 删除使用关系use
|
||
void removeAllUses();
|
||
virtual void print(std::ostream& os) const = 0; ///< 输出值信息到输出流
|
||
};
|
||
|
||
/**
|
||
* ValueCounter 需要理解为一个Value *的计数器。
|
||
* 它的主要目的是为了节省存储空间和方便Memset指令的创建。
|
||
* ValueCounter记录了一列Value *的互异元素和每个元素的重复数量。
|
||
* 例如,假设有一列Value *为{v1, v1, v2, v3, v3, v3, v4},
|
||
* 那么ValueCounter将记录为:
|
||
* - __counterValues: {v1, v2, v3, v4}
|
||
* - __counterNumbers: {2, 1, 3, 1}
|
||
* - __size: 7
|
||
* 使得存储空间得到节省,方便Memset指令的创建。
|
||
*/
|
||
class ValueCounter {
|
||
private:
|
||
unsigned __size{}; ///< 总的Value数量
|
||
std::vector<Value *> __counterValues; ///< 记录的Value *列表(无重复元素)
|
||
std::vector<unsigned> __counterNumbers; ///< 记录的Value *重复数量列表
|
||
|
||
public:
|
||
ValueCounter() = default;
|
||
|
||
public:
|
||
unsigned size() const { return __size; } ///< 返回总的Value数量
|
||
Value* getValue(unsigned index) const {
|
||
if (index >= __size) {
|
||
return nullptr;
|
||
}
|
||
|
||
unsigned num = 0;
|
||
for (size_t i = 0; i < __counterNumbers.size(); i++) {
|
||
if (num <= index && index < num + __counterNumbers[i]) {
|
||
return __counterValues[i];
|
||
}
|
||
num += __counterNumbers[i];
|
||
}
|
||
|
||
return nullptr;
|
||
} ///< 根据位置index获取Value *
|
||
const std::vector<Value *>& getValues() const { return __counterValues; } ///< 获取互异Value *列表
|
||
const std::vector<unsigned>& getNumbers() const { return __counterNumbers; } ///< 获取Value *重复数量列表
|
||
void push_back(Value *value, unsigned num = 1) {
|
||
if (__size != 0 && __counterValues.back() == value) {
|
||
*(__counterNumbers.end() - 1) += num;
|
||
} else {
|
||
__counterValues.push_back(value);
|
||
__counterNumbers.push_back(num);
|
||
}
|
||
__size += num;
|
||
} ///< 向后插入num个value
|
||
void clear() {
|
||
__size = 0;
|
||
__counterValues.clear();
|
||
__counterNumbers.clear();
|
||
} ///< 清空ValueCounter
|
||
};
|
||
|
||
|
||
// --- Refactored ConstantValue and related classes start here ---
|
||
|
||
using ConstantValVariant = std::variant<int, float>;
|
||
|
||
// Helper for hashing std::variant
|
||
struct VariantHash {
|
||
template <class T>
|
||
std::size_t operator()(const T& val) const {
|
||
return std::hash<T>{}(val);
|
||
}
|
||
std::size_t operator()(const ConstantValVariant& v) const {
|
||
return std::visit(*this, v);
|
||
}
|
||
};
|
||
|
||
struct ConstantValueKey {
|
||
Type* type;
|
||
ConstantValVariant val;
|
||
|
||
bool operator==(const ConstantValueKey& other) const {
|
||
// Assuming Type objects are canonicalized, or add Type::isSame()
|
||
// If Type::isSame() is not available and Type objects are not canonicalized,
|
||
// this comparison might not be robust enough for structural equivalence of types.
|
||
return type == other.type && val == other.val;
|
||
}
|
||
};
|
||
|
||
struct ConstantValueHash {
|
||
std::size_t operator()(const ConstantValueKey& key) const {
|
||
std::size_t typeHash = std::hash<Type*>{}(key.type);
|
||
std::size_t valHash = VariantHash{}(key.val);
|
||
// A simple way to combine hashes
|
||
return typeHash ^ (valHash << 1);
|
||
}
|
||
};
|
||
|
||
struct ConstantValueEqual {
|
||
bool operator()(const ConstantValueKey& lhs, const ConstantValueKey& rhs) const {
|
||
// Assuming Type objects are canonicalized (e.g., Type::getIntType() always returns same pointer)
|
||
// If not, and Type::isSame() is intended, it should be added to Type class.
|
||
return lhs.type == rhs.type && lhs.val == rhs.val;
|
||
}
|
||
};
|
||
|
||
/*!
|
||
* Static constants known at compile time.
|
||
*
|
||
* `ConstantValue`s are not defined by instructions, and do not use any other
|
||
* `Value`s. It's type is either `int` or `float`.
|
||
* `ConstantValue`并不由指令定义, 也不使用任何Value。它的类型为int/float。
|
||
*/
|
||
|
||
template<class T> struct always_false : std::false_type {};
|
||
template<class T> constexpr bool always_false_v = always_false<T>::value;
|
||
|
||
class ConstantValue : public Value {
|
||
protected:
|
||
static std::unordered_map<ConstantValueKey, ConstantValue*, ConstantValueHash, ConstantValueEqual> mConstantPool;
|
||
|
||
public:
|
||
explicit ConstantValue(Type* type, const std::string& name = "") : Value(type, name) {}
|
||
virtual ~ConstantValue() = default;
|
||
|
||
virtual size_t hash() const = 0;
|
||
virtual ConstantValVariant getVal() const = 0;
|
||
|
||
// Static factory method to get a canonical ConstantValue from the pool
|
||
static ConstantValue* get(Type* type, ConstantValVariant val);
|
||
|
||
// Cleanup method to release all cached constants (call at program exit)
|
||
static void cleanup();
|
||
|
||
// Helper methods to access constant values with appropriate casting
|
||
int getInt() const {
|
||
auto val = getVal();
|
||
if (std::holds_alternative<int>(val)) {
|
||
return std::get<int>(val);
|
||
} else if (std::holds_alternative<float>(val)) {
|
||
return static_cast<int>(std::get<float>(val));
|
||
}
|
||
// Handle other possible types if needed
|
||
return 0; // Default fallback
|
||
}
|
||
|
||
float getFloat() const {
|
||
auto val = getVal();
|
||
if (std::holds_alternative<float>(val)) {
|
||
return std::get<float>(val);
|
||
} else if (std::holds_alternative<int>(val)) {
|
||
return static_cast<float>(std::get<int>(val));
|
||
}
|
||
// Handle other possible types if needed
|
||
return 0.0f; // Default fallback
|
||
}
|
||
|
||
template<typename T>
|
||
T getVal() const {
|
||
if constexpr (std::is_same_v<T, int>) {
|
||
return getInt();
|
||
} else if constexpr (std::is_same_v<T, float>) {
|
||
return getFloat();
|
||
} else {
|
||
// This ensures a compilation error if an unsupported type is used
|
||
static_assert(always_false_v<T>, "Unsupported type for ConstantValue::getValue()");
|
||
}
|
||
}
|
||
|
||
virtual bool isZero() const = 0;
|
||
virtual bool isOne() const = 0;
|
||
void print(std::ostream& os) const = 0;
|
||
};
|
||
|
||
class ConstantInteger : public ConstantValue {
|
||
int constVal;
|
||
public:
|
||
explicit ConstantInteger(Type* type, int val, const std::string& name = "")
|
||
: ConstantValue(type, name), constVal(val) {}
|
||
|
||
size_t hash() const override {
|
||
std::size_t typeHash = std::hash<Type*>{}(getType());
|
||
std::size_t valHash = std::hash<int>{}(constVal);
|
||
return typeHash ^ (valHash << 1);
|
||
}
|
||
int getInt() const { return constVal; }
|
||
ConstantValVariant getVal() const override { return constVal; }
|
||
|
||
static ConstantInteger* get(Type* type, int val);
|
||
static ConstantInteger* get(int val) { return get(Type::getIntType(), val); }
|
||
|
||
ConstantInteger* getNeg() const {
|
||
assert(getType()->isInt() && "Cannot negate non-integer constant");
|
||
return ConstantInteger::get(-constVal);
|
||
}
|
||
|
||
bool isZero() const override { return constVal == 0; }
|
||
bool isOne() const override { return constVal == 1; }
|
||
void print(std::ostream& os) const;
|
||
};
|
||
|
||
class ConstantFloating : public ConstantValue {
|
||
float constFVal;
|
||
public:
|
||
explicit ConstantFloating(Type* type, float val, const std::string& name = "")
|
||
: ConstantValue(type, name), constFVal(val) {}
|
||
|
||
size_t hash() const override {
|
||
std::size_t typeHash = std::hash<Type*>{}(getType());
|
||
std::size_t valHash = std::hash<float>{}(constFVal);
|
||
return typeHash ^ (valHash << 1);
|
||
}
|
||
float getFloat() const { return constFVal; }
|
||
ConstantValVariant getVal() const override { return constFVal; }
|
||
|
||
static ConstantFloating* get(Type* type, float val);
|
||
static ConstantFloating* get(float val) { return get(Type::getFloatType(), val); }
|
||
|
||
ConstantFloating* getNeg() const {
|
||
assert(getType()->isFloat() && "Cannot negate non-float constant");
|
||
return ConstantFloating::get(-constFVal);
|
||
}
|
||
|
||
bool isZero() const override { return constFVal == 0.0f; }
|
||
bool isOne() const override { return constFVal == 1.0f; }
|
||
void print(std::ostream& os) const;
|
||
};
|
||
|
||
class UndefinedValue : public ConstantValue {
|
||
private:
|
||
static std::unordered_map<Type*, UndefinedValue*> UndefValues;
|
||
|
||
protected:
|
||
explicit UndefinedValue(Type* type, const std::string& name = "")
|
||
: ConstantValue(type, name) {
|
||
assert(!type->isVoid() && "Cannot create UndefinedValue of void type!");
|
||
}
|
||
|
||
public:
|
||
static UndefinedValue* get(Type* type);
|
||
|
||
// Cleanup method to release all cached undefined values (call at program exit)
|
||
static void cleanup();
|
||
|
||
size_t hash() const override {
|
||
return std::hash<Type*>{}(getType());
|
||
}
|
||
|
||
ConstantValVariant getVal() const override {
|
||
if (getType()->isInt()) {
|
||
return 0; // Return 0 for undefined integer
|
||
} else if (getType()->isFloat()) {
|
||
return 0.0f; // Return 0.0f for undefined float
|
||
}
|
||
assert(false && "UndefinedValue has unexpected type for getValue()");
|
||
return 0; // Should not be reached
|
||
}
|
||
|
||
bool isZero() const override { return false; }
|
||
bool isOne() const override { return false; }
|
||
void print(std::ostream& os) const;
|
||
};
|
||
|
||
// --- End of refactored ConstantValue and related classes ---
|
||
|
||
class Instruction;
|
||
class Function;
|
||
class BasicBlock;
|
||
|
||
/*!
|
||
* The container for `Instruction` sequence.
|
||
*
|
||
* `BasicBlock` maintains a list of `Instruction`s, with the last one being
|
||
* a terminator (branch or return). Besides, `BasicBlock` stores its arguments
|
||
* and records its predecessor and successor `BasicBlock`s.
|
||
*/
|
||
class BasicBlock : public Value {
|
||
friend class Function;
|
||
|
||
public:
|
||
|
||
using inst_list = std::list<std::unique_ptr<Instruction>>;
|
||
using iterator = inst_list::iterator;
|
||
using block_list = std::vector<BasicBlock *>;
|
||
using block_set = std::unordered_set<BasicBlock *>;
|
||
|
||
protected:
|
||
|
||
Function *parent; ///< 从属的函数
|
||
inst_list instructions; ///< 拥有的指令序列
|
||
block_list successors; ///< 前驱列表
|
||
block_list predecessors; ///< 后继列表
|
||
bool reachable = false;
|
||
|
||
public:
|
||
explicit BasicBlock(Function *parent, const std::string &name = "")
|
||
: Value(Type::getLabelType(), name), parent(parent) {}
|
||
~BasicBlock() override {
|
||
// for (auto pre : predecessors) {
|
||
// pre->removeSuccessor(this);
|
||
// }
|
||
// for (auto suc : successors) {
|
||
// suc->removePredecessor(this);
|
||
// }
|
||
// 这些关系应该在 BasicBlock 被从 Function 中移除时,
|
||
// 由负责 CFG 优化的 Pass (例如 SCCP 的 RemoveDeadBlock) 显式地清理。
|
||
// 析构函数只负责清理 BasicBlock 自身拥有的资源(例如,指令列表)。
|
||
}
|
||
|
||
public:
|
||
|
||
unsigned getNumInstructions() const { return instructions.size(); }
|
||
unsigned getNumPredecessors() const { return predecessors.size(); }
|
||
unsigned getNumSuccessors() const { return successors.size(); }
|
||
Function* getParent() const { return parent; }
|
||
void setParent(Function *func) { parent = func; }
|
||
inst_list& getInstructions() { return instructions; }
|
||
auto getInstructions_Range() const { return make_range(instructions); }
|
||
block_list& getPredecessors() { return predecessors; }
|
||
void clearPredecessors() { predecessors.clear(); }
|
||
block_list& getSuccessors() { return successors; }
|
||
void clearSuccessors() { successors.clear(); }
|
||
iterator begin() { return instructions.begin(); }
|
||
iterator end() { return instructions.end(); }
|
||
iterator terminator() { return std::prev(end()); }
|
||
iterator findInstIterator(Instruction *inst) {
|
||
return std::find_if(instructions.begin(), instructions.end(),
|
||
[inst](const std::unique_ptr<Instruction> &i) { return i.get() == inst; });
|
||
} ///< 查找指定指令的迭代器
|
||
bool hasSuccessor(BasicBlock *block) const {
|
||
return std::find(successors.begin(), successors.end(), block) != successors.end();
|
||
} ///< 判断是否有后继块
|
||
bool hasPredecessor(BasicBlock *block) const {
|
||
return std::find(predecessors.begin(), predecessors.end(), block) != predecessors.end();
|
||
} ///< 判断是否有前驱块
|
||
void addPredecessor(BasicBlock *block) {
|
||
if (std::find(predecessors.begin(), predecessors.end(), block) == predecessors.end()) {
|
||
predecessors.push_back(block);
|
||
}
|
||
}
|
||
void addSuccessor(BasicBlock *block) {
|
||
if (std::find(successors.begin(), successors.end(), block) == successors.end()) {
|
||
successors.push_back(block);
|
||
}
|
||
}
|
||
void addPredecessor(const block_list &blocks) {
|
||
for (auto block : blocks) {
|
||
addPredecessor(block);
|
||
}
|
||
}
|
||
void addSuccessor(const block_list &blocks) {
|
||
for (auto block : blocks) {
|
||
addSuccessor(block);
|
||
}
|
||
}
|
||
void removePredecessor(BasicBlock *block) {
|
||
auto iter = std::find(predecessors.begin(), predecessors.end(), block);
|
||
if (iter != predecessors.end()) {
|
||
predecessors.erase(iter);
|
||
} else {
|
||
// 如果没有找到前驱块,可能是因为它已经被移除或不存在
|
||
// 这可能是一个错误情况,或者是因为在CFG优化过程中已经处理
|
||
// assert(false && "Predecessor block not found in BasicBlock");
|
||
}
|
||
}
|
||
void removeSuccessor(BasicBlock *block) {
|
||
auto iter = std::find(successors.begin(), successors.end(), block);
|
||
if (iter != successors.end()) {
|
||
successors.erase(iter);
|
||
} else {
|
||
// 如果没有找到后继块,可能是因为它已经被移除或不存在
|
||
// 这可能是一个错误情况,或者是因为在CFG优化过程中已经处理
|
||
// assert(false && "Successor block not found in BasicBlock");
|
||
}
|
||
}
|
||
void replacePredecessor(BasicBlock *oldBlock, BasicBlock *newBlock) {
|
||
for (auto &predecessor : predecessors) {
|
||
if (predecessor == oldBlock) {
|
||
predecessor = newBlock;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
void setreachableTrue() { reachable = true; } ///< 设置可达
|
||
void setreachableFalse() { reachable = false; } ///< 设置不可达
|
||
bool getreachable() { return reachable; } ///< 返回可达状态
|
||
static void conectBlocks(BasicBlock *prev, BasicBlock *next) {
|
||
prev->addSuccessor(next);
|
||
next->addPredecessor(prev);
|
||
}
|
||
iterator removeInst(iterator pos) { return instructions.erase(pos); }
|
||
void removeInst(Instruction *inst) {
|
||
auto pos = std::find_if(instructions.begin(), instructions.end(),
|
||
[inst](const std::unique_ptr<Instruction> &i) { return i.get() == inst; });
|
||
if (pos != instructions.end()) {
|
||
instructions.erase(pos);
|
||
} else {
|
||
assert(false && "Instruction not found in BasicBlock");
|
||
}
|
||
} ///< 移除指定位置的指令
|
||
iterator moveInst(iterator sourcePos, iterator targetPos, BasicBlock *block);
|
||
|
||
/// 清理基本块中的所有使用关系
|
||
void cleanup();
|
||
|
||
void print(std::ostream& os) const;
|
||
};
|
||
|
||
//! User is the abstract base type of `Value` types which use other `Value` as
|
||
//! operands. Currently, there are two kinds of `User`s, `Instruction` and
|
||
//! `GlobalValue`.
|
||
// User是`Value`的派生类型,其使用其他的`Value`作为操作数
|
||
|
||
|
||
class User : public Value {
|
||
protected:
|
||
std::vector<std::shared_ptr<Use>> operands; ///< 操作数/使用关系
|
||
|
||
protected:
|
||
explicit User(Type *type, const std::string &name = "") : Value(type, name) {}
|
||
|
||
public:
|
||
unsigned getNumOperands() const { return operands.size(); } ///< 获取操作数数量
|
||
auto operand_begin() const { return operands.begin(); } ///< 返回操作数列表的开头迭代器
|
||
auto operand_end() const { return operands.end(); } ///< 返回操作数列表的结尾迭代器
|
||
auto getOperands() const { return make_range(operand_begin(), operand_end()); } ///< 获取操作数列表
|
||
Value* getOperand(unsigned index) const { return operands[index]->getValue(); } ///< 获取位置为index的操作数
|
||
void addOperand(Value *value) {
|
||
operands.emplace_back(std::make_shared<Use>(operands.size(), this, value));
|
||
value->addUse(operands.back());
|
||
} ///< 增加操作数
|
||
void removeOperand(unsigned index);
|
||
template <typename ContainerT>
|
||
void addOperands(const ContainerT &newoperands) {
|
||
for (auto value : newoperands) {
|
||
addOperand(value);
|
||
}
|
||
} ///< 增加多个操作数
|
||
void replaceOperand(unsigned index, Value *value); ///< 替换操作数
|
||
void setOperand(unsigned index, Value *value); ///< 设置操作数
|
||
|
||
/// 清理用户的所有操作数使用关系
|
||
void cleanup();
|
||
};
|
||
|
||
/*!
|
||
* Base of all concrete instruction types.
|
||
*/
|
||
class Instruction : public User {
|
||
public:
|
||
/// 指令标识码
|
||
enum Kind : uint64_t {
|
||
kInvalid = 0x0UL,
|
||
// Binary
|
||
kAdd = 0x1UL << 0,
|
||
kSub = 0x1UL << 1,
|
||
kMul = 0x1UL << 2,
|
||
kDiv = 0x1UL << 3,
|
||
kRem = 0x1UL << 4,
|
||
kICmpEQ = 0x1UL << 5,
|
||
kICmpNE = 0x1UL << 6,
|
||
kICmpLT = 0x1UL << 7,
|
||
kICmpGT = 0x1UL << 8,
|
||
kICmpLE = 0x1UL << 9,
|
||
kICmpGE = 0x1UL << 10,
|
||
kFAdd = 0x1UL << 11,
|
||
kFSub = 0x1UL << 12,
|
||
kFMul = 0x1UL << 13,
|
||
kFDiv = 0x1UL << 14,
|
||
kFCmpEQ = 0x1UL << 15,
|
||
kFCmpNE = 0x1UL << 16,
|
||
kFCmpLT = 0x1UL << 17,
|
||
kFCmpGT = 0x1UL << 18,
|
||
kFCmpLE = 0x1UL << 19,
|
||
kFCmpGE = 0x1UL << 20,
|
||
kAnd = 0x1UL << 21,
|
||
kOr = 0x1UL << 22,
|
||
// kXor = 0x1UL << 46,
|
||
// Unary
|
||
kNeg = 0x1UL << 23,
|
||
kNot = 0x1UL << 24,
|
||
kFNeg = 0x1UL << 25,
|
||
kFNot = 0x1UL << 26,
|
||
kFtoI = 0x1UL << 27,
|
||
kItoF = 0x1UL << 28,
|
||
// call
|
||
kCall = 0x1UL << 29,
|
||
// terminator
|
||
kCondBr = 0x1UL << 30,
|
||
kBr = 0x1UL << 31,
|
||
kReturn = 0x1UL << 32,
|
||
kUnreachable = 0x1UL << 33,
|
||
// mem op
|
||
kAlloca = 0x1UL << 34,
|
||
kLoad = 0x1UL << 35,
|
||
kStore = 0x1UL << 36,
|
||
kGetElementPtr = 0x1UL << 37,
|
||
kMemset = 0x1UL << 38,
|
||
// phi
|
||
kPhi = 0x1UL << 39,
|
||
kBitItoF = 0x1UL << 40,
|
||
kBitFtoI = 0x1UL << 41,
|
||
kSrl = 0x1UL << 42, // 逻辑右移
|
||
kSll = 0x1UL << 43, // 逻辑左移
|
||
kSra = 0x1UL << 44, // 算术右移
|
||
kMulh = 0x1UL << 45
|
||
};
|
||
|
||
protected:
|
||
Kind kind;
|
||
BasicBlock *parent;
|
||
|
||
protected:
|
||
Instruction(Kind kind, Type *type, BasicBlock *parent = nullptr, const std::string &name = "")
|
||
: User(type, name), kind(kind), parent(parent) {}
|
||
|
||
public:
|
||
|
||
public:
|
||
Kind getKind() const { return kind; }
|
||
std::string getKindString() const{
|
||
switch (kind) {
|
||
case kInvalid:
|
||
return "invalid";
|
||
case kAdd:
|
||
return "add";
|
||
case kSub:
|
||
return "sub";
|
||
case kMul:
|
||
return "mul";
|
||
case kDiv:
|
||
return "sdiv";
|
||
case kRem:
|
||
return "srem";
|
||
case kICmpEQ:
|
||
return "icmp eq";
|
||
case kICmpNE:
|
||
return "icmp ne";
|
||
case kICmpLT:
|
||
return "icmp slt";
|
||
case kICmpGT:
|
||
return "icmp sgt";
|
||
case kICmpLE:
|
||
return "icmp sle";
|
||
case kICmpGE:
|
||
return "icmp sge";
|
||
case kFAdd:
|
||
return "fadd";
|
||
case kFSub:
|
||
return "fsub";
|
||
case kFMul:
|
||
return "fmul";
|
||
case kFDiv:
|
||
return "fdiv";
|
||
case kFCmpEQ:
|
||
return "fcmp oeq";
|
||
case kFCmpNE:
|
||
return "fcmp one";
|
||
case kFCmpLT:
|
||
return "fcmp olt";
|
||
case kFCmpGT:
|
||
return "fcmp ogt";
|
||
case kFCmpLE:
|
||
return "fcmp ole";
|
||
case kFCmpGE:
|
||
return "fcmp oge";
|
||
case kAnd:
|
||
return "and";
|
||
case kOr:
|
||
return "or";
|
||
case kNeg:
|
||
return "neg";
|
||
case kNot:
|
||
return "not";
|
||
case kFNeg:
|
||
return "FNeg";
|
||
case kFNot:
|
||
return "FNot";
|
||
case kFtoI:
|
||
return "FtoI";
|
||
case kItoF:
|
||
return "iToF";
|
||
case kCall:
|
||
return "call";
|
||
case kCondBr:
|
||
return "condBr";
|
||
case kBr:
|
||
return "br";
|
||
case kReturn:
|
||
return "return";
|
||
case kUnreachable:
|
||
return "unreachable";
|
||
case kAlloca:
|
||
return "alloca";
|
||
case kLoad:
|
||
return "load";
|
||
case kStore:
|
||
return "store";
|
||
case kGetElementPtr:
|
||
return "getElementPtr";
|
||
case kMemset:
|
||
return "memset";
|
||
case kPhi:
|
||
return "phi";
|
||
case kBitItoF:
|
||
return "BitItoF";
|
||
case kBitFtoI:
|
||
return "BitFtoI";
|
||
case kSrl:
|
||
return "lshr";
|
||
case kSll:
|
||
return "shl";
|
||
case kSra:
|
||
return "ashr";
|
||
case kMulh:
|
||
return "mulh";
|
||
default:
|
||
return "Unknown";
|
||
}
|
||
} ///< 根据指令标识码获取字符串
|
||
|
||
BasicBlock* getParent() const { return parent; }
|
||
Function* getFunction() const { return parent->getParent(); }
|
||
void setParent(BasicBlock *bb) { parent = bb; }
|
||
|
||
bool isBinary() const {
|
||
static constexpr uint64_t BinaryOpMask =
|
||
(kAdd | kSub | kMul | kDiv | kRem | kAnd | kOr | kSra | kSrl | kSll | kMulh) |
|
||
(kICmpEQ | kICmpNE | kICmpLT | kICmpGT | kICmpLE | kICmpGE);
|
||
return kind & BinaryOpMask;
|
||
}
|
||
bool isFPBinary() const {
|
||
static constexpr uint64_t FPBinaryOpMask =
|
||
(kFAdd | kFSub | kFMul | kFDiv) |
|
||
(kFCmpEQ | kFCmpNE | kFCmpLT | kFCmpGT | kFCmpLE | kFCmpGE);
|
||
return kind & FPBinaryOpMask;
|
||
}
|
||
bool isUnary() const {
|
||
static constexpr uint64_t UnaryOpMask =
|
||
kNeg | kNot | kFNeg | kFNot | kFtoI | kItoF | kBitFtoI | kBitItoF;
|
||
return kind & UnaryOpMask;
|
||
}
|
||
bool isMemory() const {
|
||
static constexpr uint64_t MemoryOpMask =
|
||
kAlloca | kLoad | kStore;
|
||
return kind & MemoryOpMask;
|
||
}
|
||
bool isTerminator() const {
|
||
static constexpr uint64_t TerminatorOpMask = kCondBr | kBr | kReturn | kUnreachable;
|
||
return kind & TerminatorOpMask;
|
||
}
|
||
bool isCmp() const {
|
||
static constexpr uint64_t CmpOpMask =
|
||
(kICmpEQ | kICmpNE | kICmpLT | kICmpGT | kICmpLE | kICmpGE) |
|
||
(kFCmpEQ | kFCmpNE | kFCmpLT | kFCmpGT | kFCmpLE | kFCmpGE);
|
||
return kind & CmpOpMask;
|
||
}
|
||
bool isBranch() const {
|
||
static constexpr uint64_t BranchOpMask = kBr | kCondBr;
|
||
return kind & BranchOpMask;
|
||
}
|
||
bool isCommutative() const {
|
||
static constexpr uint64_t CommutativeOpMask =
|
||
kAdd | kMul | kICmpEQ | kICmpNE | kFAdd | kFMul | kFCmpEQ | kFCmpNE | kAnd | kOr;
|
||
return kind & CommutativeOpMask;
|
||
}
|
||
bool isUnconditional() const { return kind == kBr; }
|
||
bool isConditional() const { return kind == kCondBr; }
|
||
bool isCondBr() const { return kind == kCondBr; }
|
||
bool isPhi() const { return kind == kPhi; }
|
||
bool isAlloca() const { return kind == kAlloca; }
|
||
bool isLoad() const { return kind == kLoad; }
|
||
bool isStore() const { return kind == kStore; }
|
||
bool isGetElementPtr() const { return kind == kGetElementPtr; }
|
||
bool isMemset() const { return kind == kMemset; }
|
||
bool isCall() const { return kind == kCall; }
|
||
bool isReturn() const { return kind == kReturn; }
|
||
bool isUnreachable() const { return kind == kUnreachable; }
|
||
bool isDefine() const {
|
||
static constexpr uint64_t DefineOpMask = kAlloca | kStore | kPhi;
|
||
return (kind & DefineOpMask) != 0U;
|
||
}
|
||
|
||
virtual ~Instruction() = default;
|
||
|
||
virtual void print(std::ostream& os) const = 0;
|
||
}; // class Instruction
|
||
|
||
class Function;
|
||
//! Function call.
|
||
|
||
class PhiInst : public Instruction {
|
||
friend class IRBuilder;
|
||
friend class Function;
|
||
|
||
protected:
|
||
|
||
std::unordered_map<BasicBlock *, Value *> blk2val; ///< 存储每个基本块对应的值
|
||
unsigned vsize; ///< 存储值的数量
|
||
|
||
PhiInst(Type *type,
|
||
const std::vector<Value *> &rhs = {},
|
||
const std::vector<BasicBlock*> &Blocks = {},
|
||
BasicBlock *parent = nullptr,
|
||
const std::string &name = "")
|
||
: Instruction(Kind::kPhi, type, parent, name), vsize(rhs.size()) {
|
||
assert(rhs.size() == Blocks.size() && "PhiInst: rhs and Blocks must have the same size");
|
||
for(size_t i = 0; i < vsize; ++i) {
|
||
addOperand(rhs[i]);
|
||
addOperand(Blocks[i]);
|
||
blk2val[Blocks[i]] = rhs[i];
|
||
}
|
||
}
|
||
|
||
public:
|
||
unsigned getNumIncomingValues() const { return vsize; } ///< 获取传入值的数量
|
||
Value *getIncomingValue(unsigned Idx) const { return getOperand(Idx * 2); } ///< 获取指定位置的传入值
|
||
BasicBlock *getIncomingBlock(unsigned Idx) const {return dynamic_cast<BasicBlock *>(getOperand(Idx * 2 + 1)); } ///< 获取指定位置的传入基本块
|
||
|
||
Value* getValfromBlk(BasicBlock* block);
|
||
BasicBlock* getBlkfromVal(Value* value);
|
||
auto getIncomingValues() const {
|
||
std::vector<std::pair<BasicBlock*, Value*>> result;
|
||
for (const auto& [block, value] : blk2val) {
|
||
result.emplace_back(block, value);
|
||
}
|
||
return result;
|
||
}
|
||
void addIncoming(Value *value, BasicBlock *block) {
|
||
assert(value && block && "PhiInst: value and block cannot be null");
|
||
addOperand(value);
|
||
addOperand(block);
|
||
blk2val[block] = value;
|
||
vsize++;
|
||
} ///< 添加传入值和对应的基本块
|
||
void removeIncoming(unsigned Idx) {
|
||
assert(Idx < vsize && "PhiInst: Index out of bounds");
|
||
auto blk = getIncomingBlock(Idx);
|
||
removeOperand(Idx * 2 + 1); // Remove block
|
||
removeOperand(Idx * 2); // Remove value
|
||
blk2val.erase(blk);
|
||
vsize--;
|
||
} ///< 移除指定位置的传入值和对应的基本块
|
||
// 移除指定的传入值或基本块
|
||
void removeIncomingValue(Value *value);
|
||
void removeIncomingBlock(BasicBlock *block);
|
||
// 设置指定位置的传入值或基本块
|
||
void setIncomingValue(unsigned Idx, Value *value);
|
||
void setIncomingBlock(unsigned Idx, BasicBlock *block);
|
||
// 替换指定位置的传入值或基本块(原理是删除再添加)保留旧块或者旧值
|
||
void replaceIncomingValue(Value *oldValue, Value *newValue);
|
||
void replaceIncomingBlock(BasicBlock *oldBlock, BasicBlock *newBlock);
|
||
// 替换指定位置的传入值或基本块(原理是删除再添加)
|
||
void replaceIncomingValue(Value *oldValue, Value *newValue, BasicBlock *newBlock);
|
||
void replaceIncomingBlock(BasicBlock *oldBlock, BasicBlock *newBlock, Value *newValue);
|
||
void refreshMap() {
|
||
blk2val.clear();
|
||
vsize = getNumOperands() / 2;
|
||
for (unsigned i = 0; i < vsize; ++i) {
|
||
blk2val[getIncomingBlock(i)] = getIncomingValue(i);
|
||
}
|
||
} ///< 刷新块到值的映射关系
|
||
auto getValues() { return make_range(std::next(operand_begin()), operand_end()); }
|
||
void print(std::ostream& os) const override;
|
||
};
|
||
|
||
|
||
class CallInst : public Instruction {
|
||
friend class Function;
|
||
friend class IRBuilder;
|
||
|
||
protected:
|
||
CallInst(Function *callee, const std::vector<Value *> &args, BasicBlock *parent = nullptr, const std::string &name = "");
|
||
|
||
public:
|
||
Function *getCallee() const;
|
||
auto getArguments() const {
|
||
return make_range(std::next(operand_begin()), operand_end());
|
||
}
|
||
void print(std::ostream& os) const override;
|
||
}; // class CallInst
|
||
|
||
//! Unary instruction, includes '!', '-' and type conversion.
|
||
class UnaryInst : public Instruction {
|
||
friend class Function;
|
||
friend class IRBuilder;
|
||
|
||
protected:
|
||
UnaryInst(Kind kind, Type *type, Value *operand, BasicBlock *parent = nullptr,
|
||
const std::string &name = "")
|
||
: Instruction(kind, type, parent, name) {
|
||
addOperand(operand);
|
||
}
|
||
|
||
|
||
public:
|
||
Value* getOperand() const { return User::getOperand(0); }
|
||
void print(std::ostream& os) const override;
|
||
}; // class UnaryInst
|
||
|
||
//! Binary instruction, e.g., arithmatic, relation, logic, etc.
|
||
class BinaryInst : public Instruction {
|
||
friend class IRBuilder;
|
||
friend class Function;
|
||
|
||
protected:
|
||
BinaryInst(Kind kind, Type *type, Value *lhs, Value *rhs, BasicBlock *parent, const std::string &name = "")
|
||
: Instruction(kind, type, parent, name) {
|
||
addOperand(lhs);
|
||
addOperand(rhs);
|
||
}
|
||
|
||
public:
|
||
Value* getLhs() const { return getOperand(0); }
|
||
Value* getRhs() const { return getOperand(1); }
|
||
template <typename T>
|
||
T eval(T lhs, T rhs) {
|
||
switch (getKind()) {
|
||
case kAdd:
|
||
return lhs + rhs;
|
||
case kSub:
|
||
return lhs - rhs;
|
||
case kMul:
|
||
return lhs * rhs;
|
||
case kDiv:
|
||
return lhs / rhs;
|
||
case kRem:
|
||
if constexpr (std::is_floating_point<T>::value) {
|
||
throw std::runtime_error("Remainder operation not supported for floating point types.");
|
||
} else {
|
||
return lhs % rhs;
|
||
}
|
||
case kICmpEQ:
|
||
return lhs == rhs;
|
||
case kICmpNE:
|
||
return lhs != rhs;
|
||
case kICmpLT:
|
||
return lhs < rhs;
|
||
case kICmpGT:
|
||
return lhs > rhs;
|
||
case kICmpLE:
|
||
return lhs <= rhs;
|
||
case kICmpGE:
|
||
return lhs >= rhs;
|
||
case kFAdd:
|
||
return lhs + rhs;
|
||
case kFSub:
|
||
return lhs - rhs;
|
||
case kFMul:
|
||
return lhs * rhs;
|
||
case kFDiv:
|
||
return lhs / rhs;
|
||
case kFCmpEQ:
|
||
return lhs == rhs;
|
||
case kFCmpNE:
|
||
return lhs != rhs;
|
||
case kFCmpLT:
|
||
return lhs < rhs;
|
||
case kFCmpGT:
|
||
return lhs > rhs;
|
||
case kFCmpLE:
|
||
return lhs <= rhs;
|
||
case kFCmpGE:
|
||
return lhs >= rhs;
|
||
case kAnd:
|
||
return lhs && rhs;
|
||
case kOr:
|
||
return lhs || rhs;
|
||
default:
|
||
assert(false);
|
||
}
|
||
} ///< 根据指令类型进行二元计算,eval template模板实现
|
||
static BinaryInst* create(Kind kind, Type *type, Value *lhs, Value *rhs, BasicBlock *parent, const std::string &name = "") {
|
||
// 后端处理数组访存操作时需要创建计算地址的指令,需要在外部构造 BinaryInst 对象
|
||
return new BinaryInst(kind, type, lhs, rhs, parent, name);
|
||
}
|
||
void print(std::ostream& os) const override;
|
||
}; // class BinaryInst
|
||
|
||
//! The return statement
|
||
class ReturnInst : public Instruction {
|
||
friend class IRBuilder;
|
||
friend class Function;
|
||
|
||
protected:
|
||
explicit ReturnInst(Value *value = nullptr, BasicBlock *parent = nullptr, const std::string &name = "")
|
||
: Instruction(kReturn, Type::getVoidType(), parent, name) {
|
||
if (value != nullptr) {
|
||
addOperand(value);
|
||
}
|
||
}
|
||
|
||
public:
|
||
bool hasReturnValue() const { return not operands.empty(); }
|
||
Value* getReturnValue() const {
|
||
return hasReturnValue() ? getOperand(0) : nullptr;
|
||
}
|
||
void print(std::ostream& os) const override;
|
||
};
|
||
|
||
//! Unconditional branch
|
||
class UncondBrInst : public Instruction {
|
||
friend class IRBuilder;
|
||
friend class Function;
|
||
|
||
protected:
|
||
UncondBrInst(BasicBlock *block,
|
||
BasicBlock *parent = nullptr)
|
||
: Instruction(kBr, Type::getVoidType(), parent, "") {
|
||
addOperand(block);
|
||
}
|
||
|
||
public:
|
||
BasicBlock* getBlock() const { return dynamic_cast<BasicBlock *>(getOperand(0)); }
|
||
auto getArguments() const {
|
||
return make_range(std::next(operand_begin()), operand_end());
|
||
}
|
||
std::vector<BasicBlock *> getSuccessors() const {
|
||
std::vector<BasicBlock *> succs;
|
||
// 假设无条件分支的目标块是它的第一个操作数
|
||
if (getNumOperands() > 0) {
|
||
if (auto target_bb = dynamic_cast<BasicBlock *>(getOperand(0))) {
|
||
succs.push_back(target_bb);
|
||
}
|
||
}
|
||
return succs;
|
||
}
|
||
void print(std::ostream& os) const override;
|
||
}; // class UncondBrInst
|
||
|
||
//! Conditional branch
|
||
// 这里的args是指向条件分支的两个分支的参数列表但是现在弃用了
|
||
// 通过mem2reg优化后,数据流分析将不会由arguments来传递
|
||
class CondBrInst : public Instruction {
|
||
friend class IRBuilder;
|
||
friend class Function;
|
||
|
||
protected:
|
||
CondBrInst(Value *condition, BasicBlock *thenBlock, BasicBlock *elseBlock,
|
||
BasicBlock *parent = nullptr)
|
||
: Instruction(kCondBr, Type::getVoidType(), parent, "") {
|
||
addOperand(condition);
|
||
addOperand(thenBlock);
|
||
addOperand(elseBlock);
|
||
}
|
||
public:
|
||
Value* getCondition() const { return getOperand(0); }
|
||
BasicBlock* getThenBlock() const {
|
||
return dynamic_cast<BasicBlock *>(getOperand(1));
|
||
}
|
||
BasicBlock* getElseBlock() const {
|
||
return dynamic_cast<BasicBlock *>(getOperand(2));
|
||
}
|
||
std::vector<BasicBlock *> getSuccessors() const {
|
||
std::vector<BasicBlock *> succs;
|
||
// 假设条件分支的真实块是第二个操作数,假块是第三个操作数
|
||
// 操作数通常是:[0] 条件值, [1] TrueTargetBlock, [2] FalseTargetBlock
|
||
if (getNumOperands() > 2) {
|
||
if (auto true_bb = getThenBlock()) {
|
||
succs.push_back(true_bb);
|
||
}
|
||
if (auto false_bb = getElseBlock()) {
|
||
succs.push_back(false_bb);
|
||
}
|
||
}
|
||
return succs;
|
||
}
|
||
void print(std::ostream& os) const override;
|
||
}; // class CondBrInst
|
||
|
||
class UnreachableInst : public Instruction {
|
||
public:
|
||
// 构造函数:设置指令类型为 kUnreachable
|
||
explicit UnreachableInst(const std::string& name, BasicBlock *parent = nullptr)
|
||
: Instruction(kUnreachable, Type::getVoidType(), parent, "") {}
|
||
void print(std::ostream& os) const { os << "unreachable"; }
|
||
};
|
||
|
||
//! Allocate memory for stack variables, used for non-global variable declartion
|
||
class AllocaInst : public Instruction {
|
||
friend class IRBuilder;
|
||
friend class Function;
|
||
protected:
|
||
AllocaInst(Type *type,
|
||
BasicBlock *parent = nullptr, const std::string &name = "")
|
||
: Instruction(kAlloca, type, parent, name) {
|
||
}
|
||
|
||
public:
|
||
//! 获取分配的类型
|
||
Type* getAllocatedType() const {
|
||
return getType()->as<PointerType>()->getBaseType();
|
||
} ///< 获取分配的类型
|
||
void print(std::ostream& os) const override;
|
||
}; // class AllocaInst
|
||
|
||
|
||
class GetElementPtrInst : public Instruction {
|
||
friend class IRBuilder;
|
||
|
||
protected:
|
||
// GEP的构造函数:
|
||
// resultType: GEP计算出的地址的类型 (通常是指向目标元素类型的指针)
|
||
// basePointer: 基指针 (第一个操作数)
|
||
// indices: 索引列表 (后续操作数)
|
||
GetElementPtrInst(Type *resultType,
|
||
Value *basePointer,
|
||
const std::vector<Value *> &indices = {},
|
||
BasicBlock *parent = nullptr, const std::string &name = "")
|
||
: Instruction(Kind::kGetElementPtr, resultType, parent, name) {
|
||
assert(basePointer && "GEP base pointer cannot be null!");
|
||
// TODO : 安全检查
|
||
assert(basePointer->getType()->isPointer() );
|
||
addOperand(basePointer); // 第一个操作数是基指针
|
||
addOperands(indices); // 随后的操作数是索引
|
||
}
|
||
public:
|
||
Value* getBasePointer() const { return getOperand(0); }
|
||
unsigned getNumIndices() const { return getNumOperands() - 1; }
|
||
auto getIndices() const { return make_range(std::next(operand_begin()), operand_end());}
|
||
Value* getIndex(unsigned index) const {
|
||
assert(index < getNumIndices() && "Index out of bounds for GEP!");
|
||
return getOperand(index + 1);
|
||
}
|
||
|
||
// 静态工厂方法,用于创建GEP指令 (如果需要外部直接创建而非通过IRBuilder)
|
||
static GetElementPtrInst* create(Type *resultType, Value *basePointer,
|
||
const std::vector<Value *> &indices = {},
|
||
BasicBlock *parent = nullptr, const std::string &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
|
||
class LoadInst : public Instruction {
|
||
friend class IRBuilder;
|
||
friend class Function;
|
||
|
||
protected:
|
||
LoadInst(Value *pointer,
|
||
BasicBlock *parent = nullptr, const std::string &name = "")
|
||
: Instruction(kLoad, pointer->getType()->as<PointerType>()->getBaseType(),
|
||
parent, name) {
|
||
addOperand(pointer);
|
||
}
|
||
|
||
public:
|
||
Value* getPointer() const { return getOperand(0); }
|
||
void print(std::ostream& os) const override;
|
||
}; // class LoadInst
|
||
|
||
//! Store a value to memory address specified by a pointer value
|
||
class StoreInst : public Instruction {
|
||
friend class IRBuilder;
|
||
friend class Function;
|
||
|
||
protected:
|
||
StoreInst(Value *value, Value *pointer,
|
||
BasicBlock *parent = nullptr, const std::string &name = "")
|
||
: Instruction(kStore, Type::getVoidType(), parent, name) {
|
||
addOperand(value);
|
||
addOperand(pointer);
|
||
}
|
||
|
||
public:
|
||
Value* getValue() const { return getOperand(0); }
|
||
Value* getPointer() const { return getOperand(1); }
|
||
void print(std::ostream& os) const override;
|
||
}; // class StoreInst
|
||
|
||
//! Memset instruction
|
||
class MemsetInst : public Instruction {
|
||
friend class IRBuilder;
|
||
friend class Function;
|
||
|
||
protected:
|
||
//! Create a memset instruction.
|
||
//! \param pointer The pointer to the memory location to be set.
|
||
//! \param begin The starting address of the memory region to be set.
|
||
//! \param size The size of the memory region to be set.
|
||
//! \param value The value to set the memory region to.
|
||
//! \param parent The parent basic block of this instruction.
|
||
//! \param name The name of this instruction.
|
||
MemsetInst(Value *pointer, Value *begin, Value *size, Value *value,
|
||
BasicBlock *parent = nullptr, const std::string &name = "")
|
||
: Instruction(kMemset, Type::getVoidType(), parent, name) {
|
||
addOperand(pointer);
|
||
addOperand(begin);
|
||
addOperand(size);
|
||
addOperand(value);
|
||
}
|
||
|
||
public:
|
||
Value* getPointer() const { return getOperand(0); }
|
||
Value* getBegin() const { return getOperand(1); }
|
||
Value* getSize() const { return getOperand(2); }
|
||
Value* getValue() const { return getOperand(3); }
|
||
void print(std::ostream& os) const override;
|
||
};
|
||
|
||
class GlobalValue;
|
||
|
||
|
||
class Argument : public Value {
|
||
protected:
|
||
Function *func;
|
||
int index;
|
||
|
||
public:
|
||
Argument(Type *type, Function *func, int index, const std::string &name = "")
|
||
: Value(type, name), func(func), index(index) {}
|
||
|
||
public:
|
||
Function* getParent() const { return func; }
|
||
int getIndex() const { return index; }
|
||
|
||
/// 清理参数的使用关系
|
||
void cleanup();
|
||
|
||
void print(std::ostream& os) const;
|
||
};
|
||
|
||
|
||
class Module;
|
||
//! Function definitionclass
|
||
class Function : public Value {
|
||
friend class Module;
|
||
protected:
|
||
Function(Module *parent, Type *type, const std::string &name) : Value(type, name), parent(parent) {
|
||
blocks.emplace_back(new BasicBlock(this, "entry_" + name)); ///< 创建一个入口基本块
|
||
}
|
||
|
||
public:
|
||
using block_list = std::list<std::unique_ptr<BasicBlock>>;
|
||
using arg_list = std::vector<Argument *>;
|
||
enum FunctionAttribute : uint64_t {
|
||
PlaceHolder = 0x0UL,
|
||
Pure = 0x1UL << 0,
|
||
SelfRecursive = 0x1UL << 1,
|
||
SideEffect = 0x1UL << 2,
|
||
NoPureCauseMemRead = 0x1UL << 3
|
||
};
|
||
|
||
protected:
|
||
Module *parent; ///< 函数的父模块
|
||
block_list blocks; ///< 函数包含的基本块列表
|
||
arg_list arguments; ///< 函数参数列表
|
||
FunctionAttribute attribute = PlaceHolder; ///< 函数属性
|
||
std::set<Function *> callees; ///< 函数调用的函数集合
|
||
public:
|
||
static unsigned getcloneIndex() {
|
||
static unsigned cloneIndex = 0;
|
||
cloneIndex += 1;
|
||
return cloneIndex - 1;
|
||
}
|
||
Function* clone(const std::string &suffix = "_" + std::to_string(getcloneIndex()) + "@") const;
|
||
const std::set<Function *>& getCallees() { return callees; }
|
||
void addCallee(Function *callee) { callees.insert(callee); }
|
||
void removeCallee(Function *callee) { callees.erase(callee); }
|
||
void clearCallees() { callees.clear(); }
|
||
std::set<Function *> getCalleesWithNoExternalAndSelf();
|
||
FunctionAttribute getAttribute() const { return attribute; }
|
||
void setAttribute(FunctionAttribute attr) {
|
||
attribute = static_cast<FunctionAttribute>(attribute | attr);
|
||
}
|
||
void clearAttribute() { attribute = PlaceHolder; }
|
||
Type* getReturnType() const { return getType()->as<FunctionType>()->getReturnType(); }
|
||
auto getParamTypes() const { return getType()->as<FunctionType>()->getParamTypes(); }
|
||
auto getBasicBlocks() { return make_range(blocks); }
|
||
block_list& getBasicBlocks_NoRange() { return blocks; }
|
||
BasicBlock* getEntryBlock() { return blocks.front().get(); }
|
||
void insertArgument(Argument *arg) { arguments.push_back(arg); }
|
||
arg_list& getArguments() { return arguments; }
|
||
unsigned getNumArguments() const { return arguments.size(); }
|
||
Argument* getArgument(unsigned index) const {
|
||
assert(index < arguments.size() && "Argument index out of bounds");
|
||
return arguments[index];
|
||
} ///< 获取位置为index的参数
|
||
auto getArgumentsRange() const {
|
||
return make_range(arguments.begin(), arguments.end());
|
||
} ///< 获取参数列表的范围
|
||
void removeBasicBlock(BasicBlock *blockToRemove) {
|
||
auto is_same_ptr = [blockToRemove](const std::unique_ptr<BasicBlock> &ptr) { return ptr.get() == blockToRemove; };
|
||
blocks.remove_if(is_same_ptr);
|
||
}
|
||
BasicBlock* addBasicBlock(const std::string &name, BasicBlock *before) {
|
||
// 在指定的基本块之前添加一个新的基本块
|
||
auto it = std::find_if(blocks.begin(), blocks.end(),
|
||
[before](const std::unique_ptr<BasicBlock> &ptr) { return ptr.get() == before; });
|
||
if (it != blocks.end()) {
|
||
auto newblk = blocks.emplace(it, std::make_unique<BasicBlock>(this, name));
|
||
return newblk->get(); // 返回新添加的基本块指针
|
||
}
|
||
assert(false && "BasicBlock to insert before not found!");
|
||
return nullptr; // 如果没有找到指定的基本块,则返回nullptr
|
||
} ///< 添加一个新的基本块到某个基本块之前
|
||
BasicBlock* addBasicBlock(const std::string &name = "") {
|
||
blocks.emplace_back(std::make_unique<BasicBlock>(this, name));
|
||
return blocks.back().get();
|
||
}
|
||
BasicBlock* addBasicBlock(BasicBlock *block) {
|
||
blocks.emplace_back(block);
|
||
return block;
|
||
}
|
||
BasicBlock* addBasicBlockFront(BasicBlock *block) {
|
||
blocks.emplace_front(block);
|
||
return block;
|
||
}
|
||
|
||
/// 清理函数中的所有使用关系
|
||
void cleanup();
|
||
|
||
void print(std::ostream& os) const;
|
||
};
|
||
|
||
//! Global value declared at file scope
|
||
class GlobalValue : public Value {
|
||
friend class Module;
|
||
|
||
protected:
|
||
Module *parent; ///< 父模块
|
||
unsigned numDims; ///< 维度数量
|
||
ValueCounter initValues; ///< 初值
|
||
|
||
protected:
|
||
GlobalValue(Module *parent, Type *type, const std::string &name,
|
||
ValueCounter init = {})
|
||
: Value(type, name), parent(parent) {
|
||
assert(type->isPointer());
|
||
// 维度信息已经被记录到Type中,dim只是为了方便初始化
|
||
numDims = 0;
|
||
if (init.size() == 0) {
|
||
unsigned num = 1;
|
||
auto arrayType = type->as<ArrayType>();
|
||
while (arrayType) {
|
||
numDims++;
|
||
num *= arrayType->getNumElements();
|
||
arrayType = arrayType->getElementType()->as<ArrayType>();
|
||
}
|
||
if (dynamic_cast<PointerType *>(type)->getBaseType() == Type::getFloatType()) {
|
||
init.push_back(ConstantFloating::get(0.0F), num); // Use new constant factory
|
||
} else {
|
||
init.push_back(ConstantInteger::get(0), num); // Use new constant factory
|
||
}
|
||
}
|
||
initValues = init;
|
||
}
|
||
|
||
public:
|
||
unsigned getNumIndices() const {
|
||
return numDims;
|
||
} ///< 获取维度数量
|
||
unsigned getIndex(unsigned index) const {
|
||
assert(index < getNumIndices() && "Index out of bounds for GlobalValue!");
|
||
Type *GlobalValueType = getType()->as<PointerType>()->getBaseType();
|
||
for (unsigned i = 0; i < index; i++) {
|
||
GlobalValueType = GlobalValueType->as<ArrayType>()->getElementType();
|
||
}
|
||
return GlobalValueType->as<ArrayType>()->getNumElements();
|
||
} ///< 获取维度大小(从第0个开始)
|
||
Value* getByIndex(unsigned index) const {
|
||
return initValues.getValue(index);
|
||
} ///< 通过一维偏移量index获取初始值
|
||
Value* getByIndices(const std::vector<Value *> &indices) const {
|
||
int index = 0;
|
||
Type *GlobalValueType = getType()->as<PointerType>()->getBaseType();
|
||
for (size_t i = 0; i < indices.size(); i++) {
|
||
// Ensure dims[i] and indices[i] are ConstantInteger and retrieve their values correctly
|
||
// GlobalValueType->as<ArrayType>()->getNumElements();
|
||
auto dim_val = GlobalValueType->as<ArrayType>()->getNumElements();
|
||
auto idx_val = dynamic_cast<ConstantInteger*>(indices[i]);
|
||
assert(dim_val && idx_val && "Dims and indices must be constant integers");
|
||
index = dim_val * index + idx_val->getInt();
|
||
GlobalValueType = GlobalValueType->as<ArrayType>()->getElementType();
|
||
}
|
||
return getByIndex(index);
|
||
} ///< 通过多维索引indices获取初始值
|
||
const ValueCounter& getInitValues() const { return initValues; }
|
||
void print(std::ostream& os) const;
|
||
}; // class GlobalValue
|
||
|
||
|
||
class ConstantVariable : public Value {
|
||
friend class Module;
|
||
|
||
protected:
|
||
Module *parent; ///< 父模块
|
||
unsigned numDims; ///< 维度数量
|
||
ValueCounter initValues; ///< 值
|
||
|
||
protected:
|
||
ConstantVariable(Module *parent, Type *type, const std::string &name, const ValueCounter &init)
|
||
: Value(type, name), parent(parent) {
|
||
assert(type->isPointer());
|
||
// numDims = dims.size();
|
||
numDims = 0;
|
||
if(type->as<PointerType>()->getBaseType()->isArray()) {
|
||
auto arrayType = type->as<ArrayType>();
|
||
while (arrayType) {
|
||
numDims++;
|
||
arrayType = arrayType->getElementType()->as<ArrayType>();
|
||
}
|
||
}
|
||
initValues = init;
|
||
}
|
||
|
||
public:
|
||
unsigned getNumIndices() const {
|
||
return numDims;
|
||
} ///< 获取索引数量
|
||
unsigned getIndex(unsigned index) const {
|
||
assert(index < getNumIndices() && "Index out of bounds for ConstantVariable!");
|
||
Type *ConstantVariableType = getType()->as<PointerType>()->getBaseType();
|
||
for (unsigned i = 0; i < index; i++) {
|
||
ConstantVariableType = ConstantVariableType->as<ArrayType>()->getElementType();
|
||
}
|
||
return ConstantVariableType->as<ArrayType>()->getNumElements();
|
||
} ///< 获取索引个数(从第0个开始)
|
||
Value* getByIndex(unsigned index) const { return initValues.getValue(index); } ///< 通过一维位置index获取值
|
||
Value* getByIndices(const std::vector<Value *> &indices) const {
|
||
int index = 0;
|
||
// 计算偏移量
|
||
Type *ConstantVariableType = getType()->as<PointerType>()->getBaseType();
|
||
for (size_t i = 0; i < indices.size(); i++) {
|
||
// Ensure dims[i] and indices[i] are ConstantInteger and retrieve their values correctly
|
||
// ConstantVariableType->as<ArrayType>()->getNumElements();
|
||
auto dim_val = ConstantVariableType->as<ArrayType>()->getNumElements();
|
||
auto idx_val = dynamic_cast<ConstantInteger*>(indices[i]);
|
||
assert(dim_val && idx_val && "Dims and indices must be constant integers");
|
||
index = dim_val * index + idx_val->getInt();
|
||
ConstantVariableType = ConstantVariableType->as<ArrayType>()->getElementType();
|
||
}
|
||
|
||
return getByIndex(index);
|
||
} ///< 通过多维索引indices获取初始值
|
||
const ValueCounter& getInitValues() const { return initValues; } ///< 获取初始值
|
||
void print(std::ostream& os) const;
|
||
void print_init(std::ostream& os) const;
|
||
};
|
||
|
||
using SymbolTableNode = struct SymbolTableNode {
|
||
SymbolTableNode *pNode; ///< 父节点
|
||
std::vector<SymbolTableNode *> children; ///< 子节点列表
|
||
std::map<std::string, Value *> varList; ///< 变量列表
|
||
};
|
||
|
||
|
||
class SymbolTable {
|
||
private:
|
||
SymbolTableNode *curNode{}; ///< 当前所在的作用域(符号表节点)
|
||
std::map<std::string, unsigned> variableIndex; ///< 变量命名索引表
|
||
std::vector<std::unique_ptr<GlobalValue>> globals; ///< 全局变量列表
|
||
std::vector<std::unique_ptr<ConstantVariable>> globalconsts; ///< 全局常量列表
|
||
std::vector<std::unique_ptr<SymbolTableNode>> nodeList; ///< 符号表节点列表
|
||
|
||
public:
|
||
SymbolTable() = default;
|
||
|
||
Value* getVariable(const std::string &name) const; ///< 根据名字name以及当前作用域获取变量
|
||
Value* addVariable(const std::string &name, Value *variable); ///< 添加变量
|
||
void registerParameterName(const std::string &name); ///< 注册函数参数名字,避免alloca重名
|
||
void addVariableDirectly(const std::string &name, Value *variable); ///< 直接添加变量到当前作用域,不重命名
|
||
std::vector<std::unique_ptr<GlobalValue>>& getGlobals(); ///< 获取全局变量列表
|
||
const std::vector<std::unique_ptr<ConstantVariable>>& getConsts() const; ///< 获取全局常量列表
|
||
void enterNewScope(); ///< 进入新的作用域
|
||
void leaveScope(); ///< 离开作用域
|
||
bool isInGlobalScope() const; ///< 是否位于全局作用域
|
||
void enterGlobalScope(); ///< 进入全局作用域
|
||
bool isCurNodeNull() { return curNode == nullptr; }
|
||
|
||
/// 清理符号表中的所有内容
|
||
void cleanup();
|
||
};
|
||
|
||
//! IR unit for representing a SysY compile unit
|
||
class Module {
|
||
protected:
|
||
std::map<std::string, std::unique_ptr<Function>> externalFunctions; ///< 外部函数表
|
||
std::map<std::string, std::unique_ptr<Function>> functions; ///< 函数表
|
||
SymbolTable variableTable; ///< 符号表
|
||
|
||
public:
|
||
Module() = default;
|
||
|
||
public:
|
||
Function* createFunction(const std::string &name, Type *type) {
|
||
auto result = functions.try_emplace(name, new Function(this, type, name));
|
||
if (!result.second) {
|
||
return nullptr;
|
||
}
|
||
return result.first->second.get();
|
||
} ///< 创建函数
|
||
Function* createExternalFunction(const std::string &name, Type *type) {
|
||
auto result = externalFunctions.try_emplace(name, new Function(this, type, name));
|
||
if (!result.second) {
|
||
return nullptr;
|
||
}
|
||
return result.first->second.get();
|
||
} ///< 创建外部函数
|
||
///< 变量创建伴随着符号表的更新
|
||
GlobalValue* createGlobalValue(const std::string &name, Type *type, const ValueCounter &init = {}) {
|
||
bool isFinished = variableTable.isCurNodeNull();
|
||
if (isFinished) {
|
||
variableTable.enterGlobalScope();
|
||
}
|
||
auto result = variableTable.addVariable(name, new GlobalValue(this, type, name, init));
|
||
if (isFinished) {
|
||
variableTable.leaveScope();
|
||
}
|
||
if (result == nullptr) {
|
||
return nullptr;
|
||
}
|
||
return dynamic_cast<GlobalValue *>(result);
|
||
} ///< 创建全局变量
|
||
ConstantVariable* createConstVar(const std::string &name, Type *type, const ValueCounter &init) {
|
||
auto result = variableTable.addVariable(name, new ConstantVariable(this, type, name, init));
|
||
if (result == nullptr) {
|
||
return nullptr;
|
||
}
|
||
return dynamic_cast<ConstantVariable *>(result);
|
||
} ///< 创建常量
|
||
void addVariable(const std::string &name, AllocaInst *variable) {
|
||
variableTable.addVariable(name, variable);
|
||
} ///< 添加变量
|
||
void addVariableDirectly(const std::string &name, AllocaInst *variable) {
|
||
variableTable.addVariableDirectly(name, variable);
|
||
} ///< 直接添加变量到当前作用域,不重命名
|
||
void registerParameterName(const std::string &name) {
|
||
variableTable.registerParameterName(name);
|
||
} ///< 注册函数参数名字,避免alloca重名
|
||
Value* getVariable(const std::string &name) {
|
||
return variableTable.getVariable(name);
|
||
} ///< 根据名字name和当前作用域获取变量
|
||
Function* getFunction(const std::string &name) const {
|
||
auto result = functions.find(name);
|
||
if (result == functions.end()) {
|
||
return nullptr;
|
||
}
|
||
return result->second.get();
|
||
} ///< 获取函数
|
||
Function* getExternalFunction(const std::string &name) const {
|
||
auto result = externalFunctions.find(name);
|
||
if (result == externalFunctions.end()) {
|
||
return nullptr;
|
||
}
|
||
return result->second.get();
|
||
} ///< 获取外部函数
|
||
std::map<std::string, std::unique_ptr<Function>>& getFunctions() { return functions; } ///< 获取函数列表
|
||
const std::map<std::string, std::unique_ptr<Function>>& getExternalFunctions() const {
|
||
return externalFunctions;
|
||
} ///< 获取外部函数列表
|
||
std::vector<std::unique_ptr<GlobalValue>>& getGlobals() {
|
||
return variableTable.getGlobals();
|
||
} ///< 获取全局变量列表
|
||
const std::vector<std::unique_ptr<ConstantVariable>>& getConsts() const {
|
||
return variableTable.getConsts();
|
||
} ///< 获取常量列表
|
||
void enterNewScope() { variableTable.enterNewScope(); } ///< 进入新的作用域
|
||
|
||
void leaveScope() { variableTable.leaveScope(); } ///< 离开作用域
|
||
|
||
bool isInGlobalArea() const { return variableTable.isInGlobalScope(); } ///< 是否位于全局作用域
|
||
|
||
/// 清理模块中的所有对象,包括函数、基本块、指令等
|
||
void cleanup();
|
||
|
||
void print(std::ostream& os) const;
|
||
};
|
||
|
||
/*!
|
||
* @}
|
||
*/
|
||
|
||
} // namespace sysy
|