203 lines
4.9 KiB
C++
203 lines
4.9 KiB
C++
#pragma once
|
|
|
|
#include "common.h"
|
|
#include <cassert>
|
|
#include <memory>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
namespace CompSysY
|
|
{
|
|
|
|
DEF_PTR_T(Type);
|
|
DEF_PTR_T(IntegerType);
|
|
DEF_PTR_T(VoidType);
|
|
DEF_PTR_T(LabelType);
|
|
DEF_PTR_T(ArrayType);
|
|
DEF_PTR_T(PointerType);
|
|
DEF_PTR_T(FunctionType);
|
|
|
|
class Type
|
|
{
|
|
public:
|
|
enum class TypeTag
|
|
{
|
|
IntegerType,
|
|
FunctionType,
|
|
ArrayType,
|
|
PointerType,
|
|
VectorType,
|
|
VoidType,
|
|
LabelType,
|
|
};
|
|
TypeTag type_tag;
|
|
Type(TypeTag type_tag) : type_tag(type_tag) {}
|
|
virtual ~Type() = default;
|
|
virtual std::string to_string()
|
|
{
|
|
switch (type_tag)
|
|
{
|
|
case TypeTag::IntegerType: return "IntegerType";
|
|
case TypeTag::FunctionType: return "FunctionType";
|
|
case TypeTag::ArrayType: return "ArrayType";
|
|
case TypeTag::PointerType: return "PointerType";
|
|
case TypeTag::VectorType: return "VectorType";
|
|
case TypeTag::VoidType: return "VoidType";
|
|
case TypeTag::LabelType: return "LabelType";
|
|
}
|
|
}
|
|
template <typename TT>
|
|
static bool isType(std::shared_ptr<Type> ptr)
|
|
{
|
|
if (ptr)
|
|
{
|
|
return dynamic_cast<TT *>(ptr.get()) != nullptr;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
template <typename TT>
|
|
static std::shared_ptr<TT> asType(std::shared_ptr<Type> ptr)
|
|
{
|
|
return std::dynamic_pointer_cast<TT>(ptr);
|
|
}
|
|
virtual std::string to_IR_string() = 0;
|
|
};
|
|
|
|
class IntegerType : public Type
|
|
{
|
|
public:
|
|
enum class IntTypes
|
|
{
|
|
I32,
|
|
I1
|
|
};
|
|
IntTypes int_type = IntTypes::I32;
|
|
IntegerType(IntTypes int_type = IntTypes::I32) : Type(TypeTag::IntegerType), int_type(int_type) {}
|
|
bool isI32()
|
|
{
|
|
return int_type == IntTypes::I32;
|
|
}
|
|
bool isI1()
|
|
{
|
|
return int_type == IntTypes::I1;
|
|
}
|
|
static bool isIntegerType(TypePtr_t type)
|
|
{
|
|
return (type->type_tag == Type::TypeTag::IntegerType);
|
|
}
|
|
static bool isIntegerTypeI32(TypePtr_t type)
|
|
{
|
|
return isIntegerType(type) && std::dynamic_pointer_cast<IntegerType>(type)->isI32();
|
|
}
|
|
static bool isIntegerTypeI1(TypePtr_t &type)
|
|
{
|
|
return isIntegerType(type) && std::dynamic_pointer_cast<IntegerType>(type)->isI1();
|
|
}
|
|
virtual std::string to_IR_string() override
|
|
{
|
|
if (isI1())
|
|
return "i1";
|
|
else
|
|
return "i32";
|
|
}
|
|
};
|
|
|
|
class VoidType : public Type
|
|
{
|
|
public:
|
|
VoidType() : Type(TypeTag::VoidType) {}
|
|
virtual std::string to_IR_string() override
|
|
{
|
|
return "void";
|
|
}
|
|
};
|
|
|
|
class LabelType : public Type
|
|
{
|
|
public:
|
|
LabelType() : Type(TypeTag::LabelType) {}
|
|
virtual std::string to_IR_string() override
|
|
{
|
|
panic("Cannot generate LabelType");
|
|
}
|
|
};
|
|
|
|
class TypeHelper
|
|
{
|
|
public:
|
|
inline static TypePtr_t TYPE_I32 = std::make_shared<IntegerType>();
|
|
inline static TypePtr_t TYPE_I1 = std::make_shared<IntegerType>(IntegerType::IntTypes::I1);
|
|
inline static TypePtr_t TYPE_LABEL = std::make_shared<LabelType>();
|
|
inline static TypePtr_t TYPE_VOID = std::make_shared<VoidType>();
|
|
};
|
|
|
|
class ArrayType : public Type
|
|
{
|
|
public:
|
|
TypePtr_t elem_type = TypeHelper::TYPE_I32;
|
|
int elem_count = 0; // current dim size
|
|
int type_size = 0; // = dim_size * size(elem_type)
|
|
ArrayType() : Type(TypeTag::ArrayType) {}
|
|
ArrayType(TypePtr_t element_type, int element_count)
|
|
: Type(TypeTag::ArrayType), elem_type(element_type), elem_count(element_count)
|
|
{
|
|
}
|
|
static std::shared_ptr<ArrayType> build_from_list(const std::vector<int> &dim_list)
|
|
{
|
|
TypePtr_t array_type = TypeHelper::TYPE_I32;
|
|
sysy_assert(dim_list.size() != 0);
|
|
for (auto itr = dim_list.rbegin(); itr != dim_list.rend(); ++itr)
|
|
{
|
|
array_type = std::make_shared<ArrayType>(array_type, *itr);
|
|
}
|
|
return std::dynamic_pointer_cast<ArrayType>(array_type);
|
|
}
|
|
virtual std::string to_string() override
|
|
{
|
|
return "Array[" + std::to_string(elem_count) + " x " + elem_type->to_string() + "]";
|
|
}
|
|
virtual std::string to_IR_string() override
|
|
{
|
|
return "[" + std::to_string(elem_count) + " x " + elem_type->to_IR_string() + "]";
|
|
}
|
|
};
|
|
|
|
class PointerType : public Type
|
|
{
|
|
public:
|
|
TypePtr_t pointed_type = TypeHelper::TYPE_I32;
|
|
PointerType(TypePtr_t pointed_type) : Type(TypeTag::PointerType), pointed_type(pointed_type) {}
|
|
static auto make_shared(TypePtr_t pointed_type)
|
|
{
|
|
return std::make_shared<PointerType>(pointed_type);
|
|
}
|
|
virtual std::string to_string() override
|
|
{
|
|
return "Pointer->" + pointed_type->to_string();
|
|
}
|
|
virtual std::string to_IR_string() override
|
|
{
|
|
return pointed_type->to_IR_string() + "*";
|
|
}
|
|
};
|
|
|
|
class FunctionType : public Type
|
|
{
|
|
public:
|
|
TypePtr_t return_type = TypeHelper::TYPE_I32;
|
|
std::vector<TypePtr_t> params_type;
|
|
FunctionType(TypePtr_t return_type) : Type(TypeTag::FunctionType), return_type(return_type) {}
|
|
FunctionType(TypePtr_t return_type, const std::vector<TypePtr_t> ¶ms_type)
|
|
: Type(TypeTag::FunctionType), return_type(return_type), params_type(params_type)
|
|
{
|
|
}
|
|
virtual std::string to_IR_string() override
|
|
{
|
|
panic("Cannot generate FunctionType");
|
|
}
|
|
};
|
|
|
|
} // namespace CompSysY
|