aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2021-07-11 00:51:56 +0100
committergingerBill <bill@gingerbill.org>2021-07-11 00:51:56 +0100
commitebcabb8a27ace67c3cd869a573df62b260000ee8 (patch)
treee5c4b439cc6fad052731ebfab37d87b7f65cd19a
parent257b749e9d5016d3dd583fa3d1ed7537a5104b6e (diff)
Add sanity conversion check for integer to quaternion
-rw-r--r--src/check_expr.cpp44
-rw-r--r--src/llvm_backend.cpp19
2 files changed, 42 insertions, 21 deletions
diff --git a/src/check_expr.cpp b/src/check_expr.cpp
index 04da20ea5..54d610c0f 100644
--- a/src/check_expr.cpp
+++ b/src/check_expr.cpp
@@ -2929,6 +2929,7 @@ void check_binary_expr(CheckerContext *c, Operand *x, Ast *node, Type *type_hint
void update_expr_type(CheckerContext *c, Ast *e, Type *type, bool final) {
GB_ASSERT(e != nullptr);
gb_mutex_lock(&c->info->untyped_mutex);
+ defer (gb_mutex_unlock(&c->info->untyped_mutex));
ExprInfo *old = check_get_expr_info(c->info, e);
if (old == nullptr) {
if (type != nullptr && type != t_invalid) {
@@ -2939,26 +2940,6 @@ void update_expr_type(CheckerContext *c, Ast *e, Type *type, bool final) {
return;
}
- if (!final && is_type_untyped(type)) {
- old->type = base_type(type);
- } else {
-
- // We need to remove it and then give it a new one
- map_remove(&c->info->untyped, hash_node(e));
-
- if (old->is_lhs && !is_type_integer(type)) {
- gbString expr_str = expr_to_string(e);
- gbString type_str = type_to_string(type);
- error(e, "Shifted operand %s must be an integer, got %s", expr_str, type_str);
- gb_string_free(type_str);
- gb_string_free(expr_str);
- return;
- }
-
- add_type_and_value(c->info, e, old->mode, type, old->value);
- }
- gb_mutex_unlock(&c->info->untyped_mutex);
-
switch (e->kind) {
case_ast_node(ue, UnaryExpr, e);
if (old->value.kind != ExactValue_Invalid) {
@@ -3009,6 +2990,25 @@ void update_expr_type(CheckerContext *c, Ast *e, Type *type, bool final) {
update_expr_type(c, pe->expr, type, final);
case_end;
}
+
+ if (!final && is_type_untyped(type)) {
+ old->type = base_type(type);
+ return;
+ }
+
+ // We need to remove it and then give it a new one
+ map_remove(&c->info->untyped, hash_node(e));
+
+ if (old->is_lhs && !is_type_integer(type)) {
+ gbString expr_str = expr_to_string(e);
+ gbString type_str = type_to_string(type);
+ error(e, "Shifted operand %s must be an integer, got %s", expr_str, type_str);
+ gb_string_free(type_str);
+ gb_string_free(expr_str);
+ return;
+ }
+
+ add_type_and_value(c->info, e, old->mode, type, old->value);
}
void update_expr_value(CheckerContext *c, Ast *e, ExactValue value) {
@@ -3247,7 +3247,9 @@ void convert_to_typed(CheckerContext *c, Operand *operand, Type *target_type) {
if (i > 0 && count > 2) error_line(", ");
if (i == count-1) {
if (count == 2) error_line(" ");
- error_line("or ");
+ if (count > 1) {
+ error_line("or ");
+ }
}
gbString str = type_to_string(v);
error_line("'%s'", str);
diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp
index a457f5c57..c351876d4 100644
--- a/src/llvm_backend.cpp
+++ b/src/llvm_backend.cpp
@@ -8106,6 +8106,14 @@ lbValue lb_emit_conv(lbProcedure *p, lbValue value, Type *t) {
return lb_addr_load(p, gen);
}
+ if (is_type_integer(src) && is_type_complex(dst)) {
+ Type *ft = base_complex_elem_type(dst);
+ lbAddr gen = lb_add_local_generated(p, dst, true);
+ lbValue gp = lb_addr_get_ptr(p, gen);
+ lbValue real = lb_emit_conv(p, value, ft);
+ lb_emit_store(p, lb_emit_struct_ep(p, gp, 0), real);
+ return lb_addr_load(p, gen);
+ }
if (is_type_float(src) && is_type_complex(dst)) {
Type *ft = base_complex_elem_type(dst);
lbAddr gen = lb_add_local_generated(p, dst, true);
@@ -8114,6 +8122,17 @@ lbValue lb_emit_conv(lbProcedure *p, lbValue value, Type *t) {
lb_emit_store(p, lb_emit_struct_ep(p, gp, 0), real);
return lb_addr_load(p, gen);
}
+
+
+ if (is_type_integer(src) && is_type_quaternion(dst)) {
+ Type *ft = base_complex_elem_type(dst);
+ lbAddr gen = lb_add_local_generated(p, dst, true);
+ lbValue gp = lb_addr_get_ptr(p, gen);
+ lbValue real = lb_emit_conv(p, value, ft);
+ // @QuaternionLayout
+ lb_emit_store(p, lb_emit_struct_ep(p, gp, 3), real);
+ return lb_addr_load(p, gen);
+ }
if (is_type_float(src) && is_type_quaternion(dst)) {
Type *ft = base_complex_elem_type(dst);
lbAddr gen = lb_add_local_generated(p, dst, true);