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 }) {
|
for (auto& ty : { int_ty, char_ty, bool_ty }) {
|
||||||
definitions.push_back(BinopDefinition{
|
definitions.push_back(BinopDefinition{
|
||||||
ty, types::BinOp::Add, ty,
|
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");
|
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{
|
definitions.push_back(BinopDefinition{
|
||||||
ty, types::BinOp::Sub, ty,
|
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");
|
return builder.builder->CreateSub(lhs, rhs, "sub");
|
||||||
} });
|
},
|
||||||
|
[](BinopDefinition& def, std::shared_ptr<types::Type>, std::shared_ptr<types::Type>) {return def.lhs;}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Signed comparisons
|
// Signed comparisons
|
||||||
for (auto& ty : { int_ty }) {
|
for (auto& ty : { int_ty }) {
|
||||||
definitions.push_back(BinopDefinition{
|
definitions.push_back(BinopDefinition{
|
||||||
ty, types::BinOp::LessThan, ty,
|
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");
|
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{
|
definitions.push_back(BinopDefinition{
|
||||||
ty, types::BinOp::GreaterThan, ty,
|
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");
|
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
|
// Unsigned comparisons
|
||||||
for (auto& ty : { bool_ty, char_ty }) {
|
for (auto& ty : { bool_ty, char_ty }) {
|
||||||
definitions.push_back(BinopDefinition{
|
definitions.push_back(BinopDefinition{
|
||||||
ty, types::BinOp::LessThan, ty,
|
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");
|
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{
|
definitions.push_back(BinopDefinition{
|
||||||
ty, types::BinOp::GreaterThan, ty,
|
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");
|
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;
|
return definitions;
|
||||||
|
|||||||
@ -22,8 +22,8 @@ namespace types {
|
|||||||
std::shared_ptr<Type> lhs;
|
std::shared_ptr<Type> lhs;
|
||||||
BinOp op;
|
BinOp op;
|
||||||
std::shared_ptr<Type> rhs;
|
std::shared_ptr<Type> rhs;
|
||||||
std::shared_ptr<Type> result;
|
|
||||||
llvm::Value* (*codegen)(codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs);
|
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();
|
std::vector<BinopDefinition> create_binops();
|
||||||
|
|||||||
@ -74,7 +74,7 @@ namespace AST {
|
|||||||
if (binop) {
|
if (binop) {
|
||||||
return codegen::StackValue{
|
return codegen::StackValue{
|
||||||
binop->codegen(builder, lhs.value, rhs.value),
|
binop->codegen(builder, lhs.value, rhs.value),
|
||||||
binop->result
|
binop->result(*binop, lhs.ty, rhs.ty)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
throw CompileError("invalid binop", this->m_meta);
|
throw CompileError("invalid binop", this->m_meta);
|
||||||
|
|||||||
@ -133,7 +133,7 @@ namespace AST {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (binop) {
|
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
|
// If that fails, try to find binop that matches on one side perfectly
|
||||||
@ -143,7 +143,7 @@ namespace AST {
|
|||||||
if (expected_ty) {
|
if (expected_ty) {
|
||||||
// Skip any binops that would not be immediately assignable to
|
// Skip any binops that would not be immediately assignable to
|
||||||
// the expected type
|
// 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;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -153,7 +153,7 @@ namespace AST {
|
|||||||
// Skip if not implicitly castable to lhs
|
// Skip if not implicitly castable to lhs
|
||||||
continue;
|
continue;
|
||||||
this->m_rhs = handle_res(std::move(this->m_rhs), rhs_res, state);
|
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)) {
|
else if (types::types_equal(binop.rhs, rhs_ty)) {
|
||||||
auto lhs_res = check_type(state, lhs_ty, binop.lhs);
|
auto lhs_res = check_type(state, lhs_ty, binop.lhs);
|
||||||
@ -161,7 +161,7 @@ namespace AST {
|
|||||||
// Skip if not implicitly castable to rhs
|
// Skip if not implicitly castable to rhs
|
||||||
continue;
|
continue;
|
||||||
this->m_lhs = handle_res(std::move(this->m_lhs), lhs_res, state);
|
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) {
|
if (expected_ty) {
|
||||||
// Skip any binops that would not even be implicitly castable to
|
// Skip any binops that would not even be implicitly castable to
|
||||||
// the expected result
|
// 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())
|
if (!result_res.ok())
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -179,7 +179,7 @@ namespace AST {
|
|||||||
auto rhs_result = check_type(state, rhs_ty, binop.rhs);
|
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_lhs = handle_res(std::move(this->m_lhs), lhs_result, state);
|
||||||
this->m_rhs = handle_res(std::move(this->m_rhs), 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 :(
|
// No suitable binops found :(
|
||||||
|
|||||||
@ -18,6 +18,8 @@ namespace types {
|
|||||||
Bool,
|
Bool,
|
||||||
Char,
|
Char,
|
||||||
Void,
|
Void,
|
||||||
|
/// @brief Mainly used for binop resolution
|
||||||
|
Any,
|
||||||
};
|
};
|
||||||
|
|
||||||
class Type {
|
class Type {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user