c-compiler/src/types.cpp
2026-04-13 21:28:50 +03:00

225 lines
6.8 KiB
C++

#include <sstream>
#include "types.h"
#include "binops.h"
namespace types {
int operator_precedence(BinOp& op) {
switch (op) {
case BinOp::Add:
case BinOp::Sub:
return 10;
case BinOp::LessThan:
case BinOp::GreaterThan:
return 20;
case BinOp::Assignment:
return 1000;
default:
return 1000;
}
}
std::string format_operator(BinOp& op) {
switch (op) {
case BinOp::Assignment:
return "=";
case BinOp::Add:
return "+";
case BinOp::Sub:
return "-";
case BinOp::LessThan:
return "<";
case BinOp::GreaterThan:
return ">";
default:
return "??";
}
}
std::string FundamentalType::formatted() {
switch (this->m_ty) {
case FundamentalTypeKind::Int:
return "Int";
case FundamentalTypeKind::Bool:
return "Bool";
case FundamentalTypeKind::Char:
return "Char";
case FundamentalTypeKind::Void:
return "Void";
default:
return "Unknown";
}
}
llvm::Value* Type::add(codegen::Builder&, llvm::Value*, llvm::Value*) {
throw std::runtime_error("Invalid operation for this type");
}
llvm::Value* Type::sub(codegen::Builder&, llvm::Value*, llvm::Value*) {
throw std::runtime_error("Invalid operation for this type");
}
llvm::Value* Type::lt(codegen::Builder&, llvm::Value*, llvm::Value*) {
throw std::runtime_error("Invalid operation for this type");
}
llvm::Value* Type::gt(codegen::Builder&, llvm::Value*, llvm::Value*) {
throw std::runtime_error("Invalid operation for this type");
}
std::optional<std::shared_ptr<Type>> Type::return_type() {
return {};
}
bool Type::is_signed() {
false;
}
std::pair<llvm::Value*, std::shared_ptr<Type>> FundamentalType::load(codegen::Builder&, llvm::Value* ptr) {
auto self = std::make_shared<FundamentalType>(*this);
return std::pair(ptr, self);
}
llvm::Value* FundamentalType::add(codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) {
switch (this->m_ty) {
case FundamentalTypeKind::Int:
case FundamentalTypeKind::Bool:
case FundamentalTypeKind::Char:
return builder.builder->CreateAdd(lhs, rhs, "add");
default:
throw std::runtime_error("Invalid type for add");
}
}
llvm::Value* FundamentalType::sub(codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) {
switch (this->m_ty) {
case FundamentalTypeKind::Int:
case FundamentalTypeKind::Bool:
case FundamentalTypeKind::Char:
return builder.builder->CreateSub(lhs, rhs, "sub");
default:
throw std::runtime_error("Invalid type");
}
}
llvm::Value* FundamentalType::lt(codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) {
switch (this->m_ty) {
case FundamentalTypeKind::Int:
case FundamentalTypeKind::Bool:
case FundamentalTypeKind::Char:
return builder.builder->CreateCmp(llvm::CmpInst::Predicate::ICMP_SLT, lhs, rhs, "cmp");
default:
throw std::runtime_error("Invalid type");
}
}
llvm::Value* FundamentalType::gt(codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) {
switch (this->m_ty) {
case FundamentalTypeKind::Int:
case FundamentalTypeKind::Bool:
case FundamentalTypeKind::Char:
return builder.builder->CreateCmp(llvm::CmpInst::Predicate::ICMP_SGT, lhs, rhs);
default:
throw std::runtime_error("Invalid type");
}
}
bool FundamentalType::is_signed() {
switch (this->m_ty) {
case FundamentalTypeKind::Int:
return true;
case FundamentalTypeKind::Bool:
case FundamentalTypeKind::Char:
return false;
default:
throw std::runtime_error("Invalid type");
}
}
std::string FunctionType::formatted() {
std::stringstream out{ "" };
out << "(";
int counter = 0;
for (auto& param : this->m_param_tys) {
if (counter++ > 0)
out << ", ";
out << param->formatted();
}
if (this->m_vararg) {
if (counter > 0)
out << ", ";
out << "...";
}
out << ") -> " << this->m_ret_ty->formatted();
return out.str();
}
std::optional<std::shared_ptr<Type>> FunctionType::return_type() {
return this->m_ret_ty;
}
std::pair<llvm::Value*, std::shared_ptr<Type>> FunctionType::load(codegen::Builder&, llvm::Value* ptr) {
auto self = std::make_shared<FunctionType>(*this);
return std::pair(ptr, self);
}
std::string PointerType::formatted() {
std::stringstream out{ "" };
out << this->m_inner->formatted() << "*";
return out.str();
}
std::pair<llvm::Value*, std::shared_ptr<Type>> PointerType::load(codegen::Builder& builder, llvm::Value* ptr) {
return std::pair(
builder.builder->CreateLoad(this->m_inner->codegen(builder), ptr),
this->m_inner
);
}
bool types_equal(std::shared_ptr<types::Type> type1, std::shared_ptr<types::Type> type2) {
if (type1->m_kind != type2->m_kind)
return false;
if (type1->m_kind == TypeKind::Fundamental) {
auto ty1 = dynamic_cast<FundamentalType*>(type1.get());
auto ty2 = dynamic_cast<FundamentalType*>(type2.get());
return ty1->m_ty == ty2->m_ty;
}
else if (type1->m_kind == TypeKind::Function) {
auto ty1 = dynamic_cast<FunctionType*>(type1.get());
auto ty2 = dynamic_cast<FunctionType*>(type2.get());
if (!types_equal(ty1->m_ret_ty, ty2->m_ret_ty))
return false;
if (ty1->m_vararg != ty2->m_vararg)
return false;
if (ty1->m_param_tys.size() != ty2->m_param_tys.size())
return false;
for (int i = 0; i < static_cast<int>(ty1->m_param_tys.size()); i++) {
auto param1 = ty1->m_param_tys[i];
auto param2 = ty2->m_param_tys[i];
if (!types_equal(param1, param2))
return false;
}
return true;
}
else if (type1->m_kind == TypeKind::Pointer) {
auto ty1 = dynamic_cast<PointerType*>(type1.get());
auto ty2 = dynamic_cast<PointerType*>(type2.get());
return types_equal(ty1->m_inner, ty2->m_inner);
}
else {
return false;
}
}
}