Improve binop result calculation

This commit is contained in:
Sofia 2026-04-13 23:50:07 +03:00
parent 57dc022241
commit 48a3eb0e85
5 changed files with 46 additions and 20 deletions

View File

@ -16,45 +16,69 @@ namespace types {
for (auto& ty : { int_ty, char_ty, bool_ty }) {
definitions.push_back(BinopDefinition{
ty, types::BinOp::Add, ty,
ty, [](codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) {
[](codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) {
return builder.builder->CreateAdd(lhs, rhs, "add");
} });
},
[](BinopDefinition& def, std::shared_ptr<types::Type>, std::shared_ptr<types::Type>) {return def.lhs;}
});
definitions.push_back(BinopDefinition{
ty, types::BinOp::Sub, ty,
ty, [](codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) {
[](codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) {
return builder.builder->CreateSub(lhs, rhs, "sub");
} });
},
[](BinopDefinition& def, std::shared_ptr<types::Type>, std::shared_ptr<types::Type>) {return def.lhs;}
});
}
// Signed comparisons
for (auto& ty : { int_ty }) {
definitions.push_back(BinopDefinition{
ty, types::BinOp::LessThan, ty,
bool_ty, [](codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) {
[](codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) {
return builder.builder->CreateICmpSLT(lhs, rhs, "icmpslt");
} });
},
[](BinopDefinition&, std::shared_ptr<types::Type>, std::shared_ptr<types::Type>) {
return std::shared_ptr<types::Type>{
new types::FundamentalType{ types::FundamentalTypeKind::Bool } };
}
});
definitions.push_back(BinopDefinition{
ty, types::BinOp::GreaterThan, ty,
bool_ty, [](codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) {
[](codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) {
return builder.builder->CreateICmpSGT(lhs, rhs, "icmpsgt");
} });
},
[](BinopDefinition&, std::shared_ptr<types::Type>, std::shared_ptr<types::Type>) {
return std::shared_ptr<types::Type>{
new types::FundamentalType{ types::FundamentalTypeKind::Bool } };
}
});
}
// Unsigned comparisons
for (auto& ty : { bool_ty, char_ty }) {
definitions.push_back(BinopDefinition{
ty, types::BinOp::LessThan, ty,
bool_ty, [](codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) {
[](codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) {
return builder.builder->CreateICmpULT(lhs, rhs, "icmpslt");
} });
},
[](BinopDefinition&, std::shared_ptr<types::Type>, std::shared_ptr<types::Type>) {
return std::shared_ptr<types::Type>{
new types::FundamentalType{ types::FundamentalTypeKind::Bool } };
}
});
definitions.push_back(BinopDefinition{
ty, types::BinOp::GreaterThan, ty,
bool_ty, [](codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) {
[](codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) {
return builder.builder->CreateICmpUGT(lhs, rhs, "icmpsgt");
} });
},
[](BinopDefinition&, std::shared_ptr<types::Type>, std::shared_ptr<types::Type>) {
return std::shared_ptr<types::Type>{
new types::FundamentalType{ types::FundamentalTypeKind::Bool } };
}
});
}
return definitions;

View File

@ -22,8 +22,8 @@ namespace types {
std::shared_ptr<Type> lhs;
BinOp op;
std::shared_ptr<Type> rhs;
std::shared_ptr<Type> result;
llvm::Value* (*codegen)(codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs);
std::shared_ptr<Type>(*result)(BinopDefinition& def, std::shared_ptr<Type> lhs, std::shared_ptr<Type> rhs);
};
std::vector<BinopDefinition> create_binops();

View File

@ -74,7 +74,7 @@ namespace AST {
if (binop) {
return codegen::StackValue{
binop->codegen(builder, lhs.value, rhs.value),
binop->result
binop->result(*binop, lhs.ty, rhs.ty)
};
}
throw CompileError("invalid binop", this->m_meta);

View File

@ -133,7 +133,7 @@ namespace AST {
);
if (binop) {
return binop->result;
return binop->result(*binop, lhs_ty, rhs_ty);
}
// If that fails, try to find binop that matches on one side perfectly
@ -143,7 +143,7 @@ namespace AST {
if (expected_ty) {
// Skip any binops that would not be immediately assignable to
// the expected type
if (!types::types_equal(binop.result, *expected_ty)) {
if (!types::types_equal(binop.result(binop, lhs_ty, rhs_ty), *expected_ty)) {
continue;
}
}
@ -153,7 +153,7 @@ namespace AST {
// Skip if not implicitly castable to lhs
continue;
this->m_rhs = handle_res(std::move(this->m_rhs), rhs_res, state);
return binop.result;
return binop.result(binop, lhs_ty, rhs_ty);
}
else if (types::types_equal(binop.rhs, rhs_ty)) {
auto lhs_res = check_type(state, lhs_ty, binop.lhs);
@ -161,7 +161,7 @@ namespace AST {
// Skip if not implicitly castable to rhs
continue;
this->m_lhs = handle_res(std::move(this->m_lhs), lhs_res, state);
return binop.result;
return binop.result(binop, lhs_ty, rhs_ty);
}
}
@ -171,7 +171,7 @@ namespace AST {
if (expected_ty) {
// Skip any binops that would not even be implicitly castable to
// the expected result
auto result_res = check_type(state, binop.result, *expected_ty);
auto result_res = check_type(state, binop.result(binop, lhs_ty, rhs_ty), *expected_ty);
if (!result_res.ok())
continue;
}
@ -179,7 +179,7 @@ namespace AST {
auto rhs_result = check_type(state, rhs_ty, binop.rhs);
this->m_lhs = handle_res(std::move(this->m_lhs), lhs_result, state);
this->m_rhs = handle_res(std::move(this->m_rhs), lhs_result, state);
return binop.result;
return binop.result(binop, lhs_ty, rhs_ty);
}
// No suitable binops found :(

View File

@ -18,6 +18,8 @@ namespace types {
Bool,
Char,
Void,
/// @brief Mainly used for binop resolution
Any,
};
class Type {