83 lines
3.3 KiB
C++
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 {};
|
|
|
|
}
|
|
} |