From 7c3ce334d6914f73165eb66e253a2176c77d69d6 Mon Sep 17 00:00:00 2001 From: Jeroen van Rijn Date: Mon, 25 Nov 2024 15:27:35 +0100 Subject: Fix #4508 for abs, min, max (#4516) * Fix #4508 for abs, min, max and the rest of the builtins. None of these segfault now: ```odin package bug main :: proc() { p :: proc() {} // _ = len(p()) // _ = cap(p()) // _ = size_of(p()) // _ = align_of(p()) // T :: struct {} // _ = offset_of(p()) // _ = offset_of(T, p()) // _ = offset_of(p(), foo) // _ = offset_of(p(), "") // _ = type_of(p()) // _ = type_info_of(p()) // _ = typeid_of(p()) // A: [4]int // _ = swizzle(p()) // :: proc(x: [N]T, indices: ..int) -> [len(indices)]T --- // _ = swizzle(A, p()) // :: proc(x: [N]T, indices: ..int) -> [len(indices)]T --- // _ = complex(p(), p()) // _ = quaternion(p(), p(), p(), p()) // _ = quaternion(w=p(), x=p(), y=p(), z=p()) // _ = real(p()) // _ = imag(p()) // _ = jmag(p()) // _ = kmag(p()) // _ = conj(p()) // _ = expand_values(p()) // _ = min(p()) // _ = max(p()) // _ = abs(p()) // _ = clamp(p(), p(), p()) // _ = soa_zip(p()) // _ = soa_unzip(p()) } ``` --- src/check_builtin.cpp | 39 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) (limited to 'src/check_builtin.cpp') diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp index c86503093..ea902387b 100644 --- a/src/check_builtin.cpp +++ b/src/check_builtin.cpp @@ -2551,6 +2551,10 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As case BuiltinProc_swizzle: { // swizzle :: proc(v: [N]T, ..int) -> [M]T + if (!operand->type) { + return false; + } + Type *original_type = operand->type; Type *type = base_type(original_type); i64 max_count = 0; @@ -2908,6 +2912,10 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As // imag :: proc(x: type) -> float_type Operand *x = operand; + if (!x->type) { + return false; + } + if (is_type_untyped(x->type)) { if (x->mode == Addressing_Constant) { if (is_type_numeric(x->type)) { @@ -2968,6 +2976,10 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As // kmag :: proc(x: type) -> float_type Operand *x = operand; + if (!x->type) { + return false; + } + if (is_type_untyped(x->type)) { if (x->mode == Addressing_Constant) { if (is_type_numeric(x->type)) { @@ -3017,6 +3029,10 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As case BuiltinProc_conj: { // conj :: proc(x: type) -> type Operand *x = operand; + if (!x->type) { + return false; + } + Type *t = x->type; Type *elem = core_array_type(t); @@ -3057,10 +3073,14 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As } case BuiltinProc_expand_values: { + if (!operand->type) { + return false; + } + Type *type = base_type(operand->type); if (!is_type_struct(type) && !is_type_array(type)) { gbString type_str = type_to_string(operand->type); - error(call, "Expected a struct or array type, got '%s'", type_str); + error(call, "Expected a struct or array type to 'expand_values', got '%s'", type_str); gb_string_free(type_str); return false; } @@ -3096,8 +3116,13 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As check_multi_expr_or_type(c, operand, ce->args[0]); + if (!operand->type) { + return false; + } + Type *original_type = operand->type; Type *type = base_type(operand->type); + if (operand->mode == Addressing_Type && is_type_enumerated_array(type)) { // Okay } else if (!is_type_ordered(type) || !(is_type_numeric(type) || is_type_string(type))) { @@ -3268,6 +3293,10 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As check_multi_expr_or_type(c, operand, ce->args[0]); + if (!operand->type) { + return false; + } + Type *original_type = operand->type; Type *type = base_type(operand->type); @@ -3443,6 +3472,10 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As case BuiltinProc_abs: { // abs :: proc(n: numeric) -> numeric + if (!operand->type) { + return false; + } + if (!(is_type_numeric(operand->type) && !is_type_array(operand->type))) { gbString type_str = type_to_string(operand->type); error(call, "Expected a numeric type to 'abs', got '%s'", type_str); @@ -3498,6 +3531,10 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As case BuiltinProc_clamp: { // clamp :: proc(a, min, max: ordered) -> ordered + if (!operand->type) { + return false; + } + Type *type = operand->type; if (!is_type_ordered(type) || !(is_type_numeric(type) || is_type_string(type))) { gbString type_str = type_to_string(operand->type); -- cgit v1.2.3 From 1281303ff756ce4a83dcdb20be6154c7a72f278f Mon Sep 17 00:00:00 2001 From: korvahkh <92224397+korvahkh@users.noreply.github.com> Date: Mon, 3 Feb 2025 16:08:19 -0600 Subject: Preserve `#no_nil` in `intrinsics.type_convert_variants_to_pointers` Previously the newly returned type would not be marked as `#no_nil`. This caused `reflect.get_union_as_ptr_variants` to break on `#no_nil` unions. --- src/check_builtin.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/check_builtin.cpp') diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp index ea902387b..7d0ce3aef 100644 --- a/src/check_builtin.cpp +++ b/src/check_builtin.cpp @@ -5544,6 +5544,9 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As // NOTE(bill): Is this even correct? new_type->Union.node = operand->expr; new_type->Union.scope = bt->Union.scope; + if (bt->Union.kind == UnionType_no_nil) { + new_type->Union.kind = UnionType_no_nil; + } operand->type = new_type; } -- cgit v1.2.3 From de83ad2a251ec126a02378b83e4cae5b853e34ac Mon Sep 17 00:00:00 2001 From: Laytan Laats Date: Thu, 6 Feb 2025 21:06:25 +0100 Subject: apply abs fix to constant system too --- src/check_builtin.cpp | 7 +++++-- src/llvm_backend_proc.cpp | 6 +++--- 2 files changed, 8 insertions(+), 5 deletions(-) (limited to 'src/check_builtin.cpp') diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp index ea902387b..bf4c004d7 100644 --- a/src/check_builtin.cpp +++ b/src/check_builtin.cpp @@ -3488,9 +3488,12 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As case ExactValue_Integer: mp_abs(&operand->value.value_integer, &operand->value.value_integer); break; - case ExactValue_Float: - operand->value.value_float = gb_abs(operand->value.value_float); + case ExactValue_Float: { + u64 abs = bit_cast(operand->value.value_float); + abs &= 0x7FFFFFFFFFFFFFFF; + operand->value.value_float = bit_cast(abs); break; + } case ExactValue_Complex: { f64 r = operand->value.value_complex->real; f64 i = operand->value.value_complex->imag; diff --git a/src/llvm_backend_proc.cpp b/src/llvm_backend_proc.cpp index 2a6c1414e..fe7a85fee 100644 --- a/src/llvm_backend_proc.cpp +++ b/src/llvm_backend_proc.cpp @@ -2175,9 +2175,9 @@ gb_internal lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValu } GB_PANIC("Unknown complex type"); } else if (is_type_float(t)) { - Type *t_float; - Type *t_unsigned; - lbValue mask; + Type *t_float = nullptr; + Type *t_unsigned = nullptr; + lbValue mask = {0}; switch (type_size_of(t)) { case 2: t_float = t_f16; -- cgit v1.2.3 From 33a3aab7914fbed9abb0abfa696590ae25d03f4f Mon Sep 17 00:00:00 2001 From: Barinzaya Date: Tue, 15 Oct 2024 18:13:35 -0400 Subject: Added simd_extract_msbs intrinsic. --- base/intrinsics/intrinsics.odin | 2 ++ core/simd/simd.odin | 2 ++ src/check_builtin.cpp | 32 ++++++++++++++++++++++++++++++++ src/checker_builtin_procs.hpp | 4 ++++ src/llvm_backend_proc.cpp | 24 ++++++++++++++++++++++++ 5 files changed, 64 insertions(+) (limited to 'src/check_builtin.cpp') diff --git a/base/intrinsics/intrinsics.odin b/base/intrinsics/intrinsics.odin index ee0d357e4..64fc08a30 100644 --- a/base/intrinsics/intrinsics.odin +++ b/base/intrinsics/intrinsics.odin @@ -285,6 +285,8 @@ simd_reduce_xor :: proc(a: #simd[N]T) -> T where type_is_integer(T) || t simd_reduce_any :: proc(a: #simd[N]T) -> T where type_is_boolean(T) --- simd_reduce_all :: proc(a: #simd[N]T) -> T where type_is_boolean(T) --- +simd_extract_msbs :: proc(a: #simd[N]T) -> bit_set[0.. #simd[N]T where type_is_integer(U) || type_is_boolean(U) --- simd_scatter :: proc(ptr: #simd[N]rawptr, val: #simd[N]T, mask: #simd[N]U) where type_is_integer(U) || type_is_boolean(U) --- diff --git a/core/simd/simd.odin b/core/simd/simd.odin index 01d11dfbe..517cef656 100644 --- a/core/simd/simd.odin +++ b/core/simd/simd.odin @@ -135,6 +135,8 @@ reduce_xor :: intrinsics.simd_reduce_xor reduce_any :: intrinsics.simd_reduce_any reduce_all :: intrinsics.simd_reduce_all +extract_msbs :: intrinsics.simd_extract_msbs + // swizzle :: proc(a: #simd[N]T, indices: ..int) -> #simd[len(indices)]T swizzle :: builtin.swizzle diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp index 5aa4cf027..12124096f 100644 --- a/src/check_builtin.cpp +++ b/src/check_builtin.cpp @@ -888,6 +888,38 @@ gb_internal bool check_builtin_simd_operation(CheckerContext *c, Operand *operan return true; } + case BuiltinProc_simd_extract_msbs: + { + Operand x = {}; + check_expr(c, &x, ce->args[0]); if (x.mode == Addressing_Invalid) return false; + + if (!is_type_simd_vector(x.type)) { + gbString xs = type_to_string(x.type); + error(x.expr, "'%.*s' expected a simd vector type, got '%s'", LIT(builtin_name), xs); + gb_string_free(xs); + return false; + } + + Type *elem = base_array_type(x.type); + if (!is_type_integer_like(elem)) { + gbString xs = type_to_string(x.type); + error(x.expr, "'%.*s' expected a #simd type with integer or boolean elements, got '%s'", LIT(builtin_name), xs); + gb_string_free(xs); + return false; + } + + i64 num_elems = get_array_type_count(x.type); + + Type *result_type = alloc_type_bit_set(); + result_type->BitSet.elem = t_int; + result_type->BitSet.lower = 0; + result_type->BitSet.upper = num_elems - 1; + + operand->mode = Addressing_Value; + operand->type = result_type; + return true; + } + case BuiltinProc_simd_shuffle: { diff --git a/src/checker_builtin_procs.hpp b/src/checker_builtin_procs.hpp index 2dfd570e4..92f9f1602 100644 --- a/src/checker_builtin_procs.hpp +++ b/src/checker_builtin_procs.hpp @@ -181,6 +181,8 @@ BuiltinProc__simd_begin, BuiltinProc_simd_reduce_any, BuiltinProc_simd_reduce_all, + BuiltinProc_simd_extract_msbs, + BuiltinProc_simd_shuffle, BuiltinProc_simd_select, @@ -523,6 +525,8 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = { {STR_LIT("simd_reduce_any"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("simd_reduce_all"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("simd_extract_msbs"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("simd_shuffle"), 2, true, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("simd_select"), 3, false, Expr_Expr, BuiltinProcPkg_intrinsics}, diff --git a/src/llvm_backend_proc.cpp b/src/llvm_backend_proc.cpp index e5c04852c..eea0fe03e 100644 --- a/src/llvm_backend_proc.cpp +++ b/src/llvm_backend_proc.cpp @@ -1564,6 +1564,30 @@ gb_internal lbValue lb_build_builtin_simd_proc(lbProcedure *p, Ast *expr, TypeAn return res; } + case BuiltinProc_simd_extract_msbs: + { + Type *vt = arg0.type; + GB_ASSERT(vt->kind == Type_SimdVector); + + i64 elem_bits = 8*type_size_of(elem); + i64 num_elems = get_array_type_count(vt); + + LLVMTypeRef word_type = lb_type(m, elem); + LLVMValueRef shift_value = llvm_splat_int(num_elems, word_type, elem_bits - 1); + LLVMValueRef broadcast_value = LLVMBuildAShr(p->builder, arg0.value, shift_value, ""); + + LLVMTypeRef bitvec_type = LLVMVectorType(LLVMInt1TypeInContext(m->ctx), (unsigned)num_elems); + LLVMValueRef bitvec_value = LLVMBuildTrunc(p->builder, broadcast_value, bitvec_type, ""); + + LLVMTypeRef mask_type = LLVMIntTypeInContext(m->ctx, (unsigned)num_elems); + LLVMValueRef mask_value = LLVMBuildBitCast(p->builder, bitvec_value, mask_type, ""); + + LLVMTypeRef result_type = lb_type(m, res.type); + res.value = LLVMBuildZExtOrBitCast(p->builder, mask_value, result_type, ""); + + return res; + } + case BuiltinProc_simd_shuffle: { -- cgit v1.2.3 From 4afedbc051e92647c9003d33b1a231330fe3b025 Mon Sep 17 00:00:00 2001 From: Barinzaya Date: Mon, 24 Feb 2025 08:49:57 -0500 Subject: Added simd_extract_lsbs intrinsic as well. Equivalent to the simd_extract_msbs intrinsic, except it extracts the least significant bit of each element instead. --- base/intrinsics/intrinsics.odin | 1 + core/simd/simd.odin | 1 + src/check_builtin.cpp | 1 + src/checker_builtin_procs.hpp | 2 ++ src/llvm_backend_proc.cpp | 10 +++++++--- 5 files changed, 12 insertions(+), 3 deletions(-) (limited to 'src/check_builtin.cpp') diff --git a/base/intrinsics/intrinsics.odin b/base/intrinsics/intrinsics.odin index 64fc08a30..bec452007 100644 --- a/base/intrinsics/intrinsics.odin +++ b/base/intrinsics/intrinsics.odin @@ -285,6 +285,7 @@ simd_reduce_xor :: proc(a: #simd[N]T) -> T where type_is_integer(T) || t simd_reduce_any :: proc(a: #simd[N]T) -> T where type_is_boolean(T) --- simd_reduce_all :: proc(a: #simd[N]T) -> T where type_is_boolean(T) --- +simd_extract_lsbs :: proc(a: #simd[N]T) -> bit_set[0.. bit_set[0.. #simd[len(indices)]T diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp index 12124096f..023aeff73 100644 --- a/src/check_builtin.cpp +++ b/src/check_builtin.cpp @@ -888,6 +888,7 @@ gb_internal bool check_builtin_simd_operation(CheckerContext *c, Operand *operan return true; } + case BuiltinProc_simd_extract_lsbs: case BuiltinProc_simd_extract_msbs: { Operand x = {}; diff --git a/src/checker_builtin_procs.hpp b/src/checker_builtin_procs.hpp index 92f9f1602..40dde8240 100644 --- a/src/checker_builtin_procs.hpp +++ b/src/checker_builtin_procs.hpp @@ -181,6 +181,7 @@ BuiltinProc__simd_begin, BuiltinProc_simd_reduce_any, BuiltinProc_simd_reduce_all, + BuiltinProc_simd_extract_lsbs, BuiltinProc_simd_extract_msbs, BuiltinProc_simd_shuffle, @@ -525,6 +526,7 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = { {STR_LIT("simd_reduce_any"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("simd_reduce_all"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("simd_extract_lsbs"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("simd_extract_msbs"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, diff --git a/src/llvm_backend_proc.cpp b/src/llvm_backend_proc.cpp index eea0fe03e..b41f4723c 100644 --- a/src/llvm_backend_proc.cpp +++ b/src/llvm_backend_proc.cpp @@ -1564,6 +1564,7 @@ gb_internal lbValue lb_build_builtin_simd_proc(lbProcedure *p, Ast *expr, TypeAn return res; } + case BuiltinProc_simd_extract_lsbs: case BuiltinProc_simd_extract_msbs: { Type *vt = arg0.type; @@ -1572,9 +1573,12 @@ gb_internal lbValue lb_build_builtin_simd_proc(lbProcedure *p, Ast *expr, TypeAn i64 elem_bits = 8*type_size_of(elem); i64 num_elems = get_array_type_count(vt); - LLVMTypeRef word_type = lb_type(m, elem); - LLVMValueRef shift_value = llvm_splat_int(num_elems, word_type, elem_bits - 1); - LLVMValueRef broadcast_value = LLVMBuildAShr(p->builder, arg0.value, shift_value, ""); + LLVMValueRef broadcast_value = arg0.value; + if (builtin_id == BuiltinProc_simd_extract_msbs) { + LLVMTypeRef word_type = lb_type(m, elem); + LLVMValueRef shift_value = llvm_splat_int(num_elems, word_type, elem_bits - 1); + broadcast_value = LLVMBuildAShr(p->builder, broadcast_value, shift_value, ""); + } LLVMTypeRef bitvec_type = LLVMVectorType(LLVMInt1TypeInContext(m->ctx), (unsigned)num_elems); LLVMValueRef bitvec_value = LLVMBuildTrunc(p->builder, broadcast_value, bitvec_type, ""); -- cgit v1.2.3 From acb578f184c55f0d1b20ef844a506185684efeba Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 24 Mar 2025 11:35:10 +0000 Subject: Fix #4962 --- src/check_builtin.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'src/check_builtin.cpp') diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp index 023aeff73..a49302a69 100644 --- a/src/check_builtin.cpp +++ b/src/check_builtin.cpp @@ -1675,12 +1675,16 @@ gb_internal bool check_builtin_procedure_directive(CheckerContext *c, Operand *o } if (ce->args.count > 0) { Ast *arg = ce->args[0]; - Operand o = {}; - Entity *e = check_ident(c, &o, arg, nullptr, nullptr, true); - if (e == nullptr || (e->flags & EntityFlag_Param) == 0) { - error(ce->args[0], "'#caller_expression' expected a valid earlier parameter name"); + if (arg->kind != Ast_Ident) { + error(arg, "'#caller_expression' expected an identifier"); + } else { + Operand o = {}; + Entity *e = check_ident(c, &o, arg, nullptr, nullptr, true); + if (e == nullptr || (e->flags & EntityFlag_Param) == 0) { + error(arg, "'#caller_expression' expected a valid earlier parameter name"); + } + arg->Ident.entity = e; } - arg->Ident.entity = e; } operand->type = t_string; -- cgit v1.2.3 From ce026ff2c4ef1b29d3876f1ab5c866eda7995679 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 24 Mar 2025 13:13:25 +0000 Subject: Fix #4949 --- src/check_builtin.cpp | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'src/check_builtin.cpp') diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp index a49302a69..fa3218759 100644 --- a/src/check_builtin.cpp +++ b/src/check_builtin.cpp @@ -645,6 +645,13 @@ gb_internal bool check_builtin_simd_operation(CheckerContext *c, Operand *operan break; } + if (!are_types_identical(x.type, y.type)) { + gbString tx = type_to_string(x.type); + gbString ty = type_to_string(y.type); + error(call, "Mismatched types to '%.*s', '%s' vs '%s'", LIT(builtin_name), tx, ty); + gb_string_free(ty); + gb_string_free(tx); + } Type *vt = base_type(x.type); GB_ASSERT(vt->kind == Type_SimdVector); -- cgit v1.2.3 From 04807309b7c0f7cb6326d0be1458ebfba90c015d Mon Sep 17 00:00:00 2001 From: Jeroen van Rijn Date: Fri, 11 Apr 2025 21:49:48 +0200 Subject: Allow intrinsics.type_elem_type(simd_vector) to return the element type. Make `type_elem_type(#simd[4]f32)` return `f32`, same as it would for `[4]f32`. --- src/check_builtin.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src/check_builtin.cpp') diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp index fa3218759..f66a8605c 100644 --- a/src/check_builtin.cpp +++ b/src/check_builtin.cpp @@ -5550,6 +5550,7 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As case Type_EnumeratedArray: operand->type = bt->EnumeratedArray.elem; break; case Type_Slice: operand->type = bt->Slice.elem; break; case Type_DynamicArray: operand->type = bt->DynamicArray.elem; break; + case Type_SimdVector: operand->type = bt->SimdVector.elem; break; } } operand->mode = Addressing_Type; -- cgit v1.2.3