c-compiler/src/casting.cpp
2026-04-14 18:26:33 +03:00

83 lines
3.3 KiB
C++

#include "casting.h"
#include <iostream>
namespace types {
std::vector<CastDefinition> create_casts() {
std::vector<CastDefinition> casts{};
auto int_ty = std::shared_ptr<Type>{
new FundamentalType{ FundamentalTypeKind::Int } };
auto char_ty = std::shared_ptr<Type>{
new FundamentalType{ FundamentalTypeKind::Char } };
auto bool_ty = std::shared_ptr<Type>{
new FundamentalType{ FundamentalTypeKind::Bool } };
auto numerical_types = { int_ty, char_ty, bool_ty };
for (auto& source_ty : numerical_types) {
for (auto& target_ty : numerical_types) {
if (types::types_equal(source_ty, target_ty)) {
casts.push_back(CastDefinition{ source_ty, target_ty, true,
[](codegen::Builder&, std::shared_ptr<Type>, llvm::Value* value) {
return value;
} });
continue;
}
bool allow_implicit = false;
if (target_ty->size() >= source_ty->size())
allow_implicit = true;
if (target_ty->is_signed()) {
casts.push_back(CastDefinition{ source_ty, target_ty, allow_implicit,
[](codegen::Builder& builder, std::shared_ptr<Type> target, llvm::Value* value) {
return builder.builder->CreateSExtOrTrunc(value, target->codegen(builder), "cast");
} });
}
else {
casts.push_back(CastDefinition{ source_ty, target_ty, allow_implicit,
[](codegen::Builder& builder, std::shared_ptr<Type> target, llvm::Value* value) {
return builder.builder->CreateZExtOrTrunc(value, target->codegen(builder), "cast");
} });
}
}
}
return casts;
}
std::optional<CastDefinition> find_cast(
std::vector<CastDefinition>& casts,
std::shared_ptr<Type> casted_ty,
std::shared_ptr<Type> target_ty) {
if (casted_ty->m_kind == types::TypeKind::Array && target_ty->m_kind == types::TypeKind::Pointer) {
auto array_ty = dynamic_cast<types::ArrayType*>(casted_ty.get());
auto ptr_ty = dynamic_cast<types::PointerType*>(target_ty.get());
if (!types_equal(array_ty->m_inner, ptr_ty->m_inner))
return {};
return CastDefinition{ casted_ty, target_ty, true,
[](codegen::Builder&, std::shared_ptr<Type>, llvm::Value* value) {
// auto ptr_ty = dynamic_cast<types::PointerType*>(target.get());
// std::vector<llvm::Value*> indices {};
// indices.push_back(llvm::ConstantInt::get(
// builder.builder->getInt32Ty(),
// 0
// ));
// return builder.builder->CreateGEP(ptr_ty->m_inner->codegen(builder), value, indices, "arraydecay");
return value;
} };
}
for (auto& cast : casts) {
if (types_equal(cast.casted_ty, casted_ty) && types_equal(cast.target_ty, target_ty)) {
return cast;
}
}
return {};
}
}