diff options
Diffstat (limited to 'src/check_builtin.cpp')
| -rw-r--r-- | src/check_builtin.cpp | 135 |
1 files changed, 130 insertions, 5 deletions
diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp index 00963487f..1acb9732f 100644 --- a/src/check_builtin.cpp +++ b/src/check_builtin.cpp @@ -87,7 +87,7 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 case BuiltinProc_DIRECTIVE: { ast_node(bd, BasicDirective, ce->proc); - String name = bd->name; + String name = bd->name.string; if (name == "defined") { break; } @@ -124,7 +124,7 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 case BuiltinProc_DIRECTIVE: { ast_node(bd, BasicDirective, ce->proc); - String name = bd->name; + String name = bd->name.string; if (name == "location") { if (ce->args.count > 1) { error(ce->args[0], "'#location' expects either 0 or 1 arguments, got %td", ce->args.count); @@ -1509,6 +1509,10 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 { Type *bt = base_type(x.type); + if (are_types_identical(bt, t_f16)) { + add_package_dependency(c, "runtime", "min_f16"); + add_package_dependency(c, "runtime", "max_f16"); + } if (are_types_identical(bt, t_f32)) { add_package_dependency(c, "runtime", "min_f32"); add_package_dependency(c, "runtime", "max_f32"); @@ -2017,11 +2021,92 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 } } + operand->mode = Addressing_OptionalOk; + operand->type = default_type(x.type); + } + break; + + case BuiltinProc_sqrt: + { + Operand x = {}; + check_expr(c, &x, ce->args[0]); + if (x.mode == Addressing_Invalid) { + return false; + } + if (!is_type_float(x.type)) { + gbString xts = type_to_string(x.type); + error(x.expr, "Expected a floating point value for '%.*s', got %s", LIT(builtin_procs[id].name), xts); + gb_string_free(xts); + return false; + } + + if (x.mode == Addressing_Constant) { + f64 v = exact_value_to_f64(x.value); + + operand->mode = Addressing_Constant; + operand->type = x.type; + operand->value = exact_value_float(gb_sqrt(v)); + break; + } operand->mode = Addressing_Value; - operand->type = make_optional_ok_type(default_type(x.type), false); // Just reusing this procedure, it's not optional + operand->type = default_type(x.type); } break; + case BuiltinProc_mem_copy: + case BuiltinProc_mem_copy_non_overlapping: + { + operand->mode = Addressing_NoValue; + operand->type = t_invalid; + + Operand dst = {}; + Operand src = {}; + Operand len = {}; + check_expr(c, &dst, ce->args[0]); + check_expr(c, &src, ce->args[1]); + check_expr(c, &len, ce->args[2]); + if (dst.mode == Addressing_Invalid) { + return false; + } + if (src.mode == Addressing_Invalid) { + return false; + } + if (len.mode == Addressing_Invalid) { + return false; + } + + + if (!is_type_pointer(dst.type)) { + gbString str = type_to_string(dst.type); + error(dst.expr, "Expected a pointer value for '%.*s', got %s", LIT(builtin_procs[id].name), str); + gb_string_free(str); + return false; + } + if (!is_type_pointer(src.type)) { + gbString str = type_to_string(src.type); + error(src.expr, "Expected a pointer value for '%.*s', got %s", LIT(builtin_procs[id].name), str); + gb_string_free(str); + return false; + } + if (!is_type_integer(len.type)) { + gbString str = type_to_string(len.type); + error(len.expr, "Expected an integer value for the number of bytes for '%.*s', got %s", LIT(builtin_procs[id].name), str); + gb_string_free(str); + return false; + } + + if (len.mode == Addressing_Constant) { + i64 n = exact_value_to_i64(len.value); + if (n < 0) { + gbString str = expr_to_string(len.expr); + error(len.expr, "Expected a non-negative integer value for the number of bytes for '%.*s', got %s", LIT(builtin_procs[id].name), str); + gb_string_free(str); + } + } + } + break; + + case BuiltinProc_atomic_fence: case BuiltinProc_atomic_fence_acq: case BuiltinProc_atomic_fence_rel: @@ -2149,8 +2234,8 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 check_assignment(c, &x, elem, builtin_name); check_assignment(c, &y, elem, builtin_name); - operand->mode = Addressing_Value; - operand->type = make_optional_ok_type(elem, /*typed*/false); + operand->mode = Addressing_OptionalOk; + operand->type = elem; break; } break; @@ -2425,6 +2510,46 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 } break; + case BuiltinProc_type_is_variant_of: + { + if (operand->mode != Addressing_Type) { + error(operand->expr, "Expected a type for '%.*s'", LIT(builtin_name)); + operand->mode = Addressing_Invalid; + operand->type = t_invalid; + return false; + } + + + Type *u = operand->type; + + if (!is_type_union(u)) { + error(operand->expr, "Expected a union type for '%.*s'", LIT(builtin_name)); + operand->mode = Addressing_Invalid; + operand->type = t_invalid; + return false; + } + + Type *v = check_type(c, ce->args[1]); + + u = base_type(u); + GB_ASSERT(u->kind == Type_Union); + + bool is_variant = false; + + for_array(i, u->Union.variants) { + Type *vt = u->Union.variants[i]; + if (are_types_identical(v, vt)) { + is_variant = true; + break; + } + } + + operand->mode = Addressing_Constant; + operand->type = t_untyped_bool; + operand->value = exact_value_bool(is_variant); + } + break; + case BuiltinProc_type_struct_field_count: operand->value = exact_value_i64(0); if (operand->mode != Addressing_Type) { |