Improve binop result calculation
This commit is contained in:
parent
57dc022241
commit
48a3eb0e85
@ -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;
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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 :(
|
||||
|
||||
@ -18,6 +18,8 @@ namespace types {
|
||||
Bool,
|
||||
Char,
|
||||
Void,
|
||||
/// @brief Mainly used for binop resolution
|
||||
Any,
|
||||
};
|
||||
|
||||
class Type {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user