From c20230509f61755698e4c0761bc721e0ee016b83 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 2 Nov 2021 23:56:19 +0000 Subject: [PATCH 01/10] Correct index to offset calculation for matrix compound literals --- src/llvm_backend_const.cpp | 6 +++--- src/llvm_backend_expr.cpp | 6 +++--- src/types.cpp | 7 ++++--- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/llvm_backend_const.cpp b/src/llvm_backend_const.cpp index e3e43a31e..82b409573 100644 --- a/src/llvm_backend_const.cpp +++ b/src/llvm_backend_const.cpp @@ -1013,7 +1013,7 @@ lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, bool allow_loc TypeAndValue tav = fv->value->tav; LLVMValueRef val = lb_const_value(m, elem_type, tav.value, allow_local).value; for (i64 k = lo; k < hi; k++) { - i64 offset = matrix_index_to_offset(type, k); + i64 offset = matrix_row_major_index_to_offset(type, k); GB_ASSERT(values[offset] == nullptr); values[offset] = val; } @@ -1023,7 +1023,7 @@ lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, bool allow_loc i64 index = exact_value_to_i64(index_tav.value); TypeAndValue tav = fv->value->tav; LLVMValueRef val = lb_const_value(m, elem_type, tav.value, allow_local).value; - i64 offset = matrix_index_to_offset(type, index); + i64 offset = matrix_row_major_index_to_offset(type, index); GB_ASSERT(values[offset] == nullptr); values[offset] = val; } @@ -1045,7 +1045,7 @@ lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, bool allow_loc for_array(i, cl->elems) { TypeAndValue tav = cl->elems[i]->tav; GB_ASSERT(tav.mode != Addressing_Invalid); - i64 offset = matrix_index_to_offset(type, i); + i64 offset = matrix_row_major_index_to_offset(type, i); values[offset] = lb_const_value(m, elem_type, tav.value, allow_local).value; } for (isize i = 0; i < total_count; i++) { diff --git a/src/llvm_backend_expr.cpp b/src/llvm_backend_expr.cpp index fd9b10a4f..4b3e8fed1 100644 --- a/src/llvm_backend_expr.cpp +++ b/src/llvm_backend_expr.cpp @@ -4465,7 +4465,7 @@ lbAddr lb_build_addr(lbProcedure *p, Ast *expr) { lbCompoundLitElemTempData data = {}; data.value = value; - data.elem_index = cast(i32)matrix_index_to_offset(bt, k); + data.elem_index = cast(i32)matrix_row_major_index_to_offset(bt, k); array_add(&temp_data, data); } @@ -4479,7 +4479,7 @@ lbAddr lb_build_addr(lbProcedure *p, Ast *expr) { data.value = lb_emit_conv(p, value, et); data.expr = fv->value; - data.elem_index = cast(i32)matrix_index_to_offset(bt, index); + data.elem_index = cast(i32)matrix_row_major_index_to_offset(bt, index); array_add(&temp_data, data); } @@ -4489,7 +4489,7 @@ lbAddr lb_build_addr(lbProcedure *p, Ast *expr) { } lbCompoundLitElemTempData data = {}; data.expr = elem; - data.elem_index = cast(i32)matrix_index_to_offset(bt, i); + data.elem_index = cast(i32)matrix_row_major_index_to_offset(bt, i); array_add(&temp_data, data); } } diff --git a/src/types.cpp b/src/types.cpp index bfedb5381..52bb2e324 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -1408,12 +1408,13 @@ i64 matrix_indices_to_offset(Type *t, i64 row_index, i64 column_index) { i64 stride_elems = matrix_type_stride_in_elems(t); return stride_elems*column_index + row_index; } -i64 matrix_index_to_offset(Type *t, i64 index) { + +i64 matrix_row_major_index_to_offset(Type *t, i64 index) { t = base_type(t); GB_ASSERT(t->kind == Type_Matrix); - i64 row_index = index%t->Matrix.row_count; - i64 column_index = index/t->Matrix.row_count; + i64 column_index = index%t->Matrix.column_count; + i64 row_index = index/t->Matrix.column_count; return matrix_indices_to_offset(t, row_index, column_index); } From dcc5697a48807b0e7512ab7389d8350a19198d49 Mon Sep 17 00:00:00 2001 From: Jeroen van Rijn Date: Wed, 3 Nov 2021 11:01:18 +0100 Subject: [PATCH 02/10] Fix error message. --- src/check_type.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/check_type.cpp b/src/check_type.cpp index 7c01bd5ba..05d5c674a 100644 --- a/src/check_type.cpp +++ b/src/check_type.cpp @@ -2692,7 +2692,7 @@ bool check_type_internal(CheckerContext *ctx, Ast *e, Type **type, Type *named_t if (!is_partial && t->EnumeratedArray.count > bt->Enum.fields.count) { error(e, "Non-contiguous enumeration used as an index in an enumerated array"); long long ea_count = cast(long long)t->EnumeratedArray.count; - long long enum_count = cast(long long)t->Enum.fields.count; + long long enum_count = cast(long long)bt->Enum.fields.count; error_line("\tenumerated array length: %lld\n", ea_count); error_line("\tenum field count: %lld\n", enum_count); error_line("\tSuggestion: prepend #partial to the enumerated array to allow for non-named elements\n"); From 73648bb2d85962461119df7c215a879f90a71c63 Mon Sep 17 00:00:00 2001 From: Jeroen van Rijn Date: Wed, 3 Nov 2021 11:36:24 +0100 Subject: [PATCH 03/10] Fix #1268. Error message for enumerated arrays going out of bounds was not yet updated for the Enum change. --- src/check_expr.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/check_expr.cpp b/src/check_expr.cpp index d8ca190b7..1e8c24fd6 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -3660,8 +3660,11 @@ bool check_index_value(CheckerContext *c, Type *main_type, bool open_range, Ast String lo_str = {}; String hi_str = {}; if (bt->Enum.fields.count > 0) { - lo_str = bt->Enum.fields[bt->Enum.min_value_index]->token.string; - hi_str = bt->Enum.fields[bt->Enum.max_value_index]->token.string; + isize lo_idx = gb_clamp(bt->Enum.min_value_index, 0, bt->Enum.fields.count - 1); + isize hi_idx = gb_clamp(bt->Enum.max_value_index, 0, bt->Enum.fields.count - 1); + + lo_str = bt->Enum.fields[lo_idx]->token.string; + hi_str = bt->Enum.fields[hi_idx]->token.string; } bool out_of_bounds = false; From 229c98309e01e2d6bb893063943add86f925c3d6 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 3 Nov 2021 11:02:47 +0000 Subject: [PATCH 04/10] Correct assertion usage --- src/check_decl.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/check_decl.cpp b/src/check_decl.cpp index 127bb67fd..33e85edf7 100644 --- a/src/check_decl.cpp +++ b/src/check_decl.cpp @@ -1345,8 +1345,9 @@ void check_proc_body(CheckerContext *ctx_, Token token, DeclInfo *decl, Type *ty for_array(j, vd->names) { Ast *name = vd->names[j]; if (!is_blank_ident(name)) { - GB_ASSERT(name->kind == Ast_Ident); - GB_ASSERT(name->Ident.entity != nullptr); + if (name->kind == Ast_Ident) { + GB_ASSERT(name->Ident.entity != nullptr); + } } } } From 69f978f22bb3ab7db1ecf967147b9f6063ac35ef Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 3 Nov 2021 11:07:35 +0000 Subject: [PATCH 05/10] Correct `lb_emit_matrix_flatten` --- src/llvm_backend_expr.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/llvm_backend_expr.cpp b/src/llvm_backend_expr.cpp index 4b3e8fed1..d49863c2a 100644 --- a/src/llvm_backend_expr.cpp +++ b/src/llvm_backend_expr.cpp @@ -671,7 +671,7 @@ lbValue lb_emit_matrix_flatten(lbProcedure *p, lbValue m, Type *type) { for (i64 j = 0; j < column_count; j++) { for (i64 i = 0; i < row_count; i++) { lbValue src = lb_emit_matrix_ev(p, m, i, j); - lbValue dst = lb_emit_matrix_epi(p, res.addr, i, j); + lbValue dst = lb_emit_array_epi(p, res.addr, i + j*row_count); lb_emit_store(p, dst, src); } } From edd12d505d5dd1a5199596d52d17a0011e8f83dc Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 3 Nov 2021 11:20:04 +0000 Subject: [PATCH 06/10] Correct fmt for matrices --- core/fmt/fmt.odin | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/core/fmt/fmt.odin b/core/fmt/fmt.odin index 2cf032b73..21aa1efcf 100644 --- a/core/fmt/fmt.odin +++ b/core/fmt/fmt.odin @@ -1934,7 +1934,7 @@ fmt_value :: proc(fi: ^Info, v: any, verb: rune) { for col in 0.. 0 { io.write_string(fi.writer, ", ") } - offset := (row + col*info.elem_stride)*info.elem_size + offset := (col + row*info.elem_stride)*info.elem_size data := uintptr(v.data) + uintptr(offset) fmt_arg(fi, any{rawptr(data), info.elem.id}, verb) @@ -1943,11 +1943,11 @@ fmt_value :: proc(fi: ^Info, v: any, verb: rune) { } } else { for row in 0.. 0 { io.write_string(fi.writer, ", ") } + if row > 0 { io.write_string(fi.writer, "; ") } for col in 0.. 0 { io.write_string(fi.writer, "; ") } + if col > 0 { io.write_string(fi.writer, ", ") } - offset := (row + col*info.elem_stride)*info.elem_size + offset := (col + row*info.elem_stride)*info.elem_size data := uintptr(v.data) + uintptr(offset) fmt_arg(fi, any{rawptr(data), info.elem.id}, verb) From 842994356936ee2b8a14166b39052672eb2211d2 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 3 Nov 2021 11:27:21 +0000 Subject: [PATCH 07/10] Represent matrices in `fmt` as expected --- core/fmt/fmt.odin | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/core/fmt/fmt.odin b/core/fmt/fmt.odin index 21aa1efcf..10b62d51b 100644 --- a/core/fmt/fmt.odin +++ b/core/fmt/fmt.odin @@ -1929,23 +1929,23 @@ fmt_value :: proc(fi: ^Info, v: any, verb: rune) { if fi.hash { io.write_byte(fi.writer, '\n') // TODO(bill): Should this render it like in written form? e.g. tranposed - for row in 0.. 0 { io.write_string(fi.writer, ", ") } + for row in 0.. 0 { io.write_string(fi.writer, ", ") } offset := (col + row*info.elem_stride)*info.elem_size data := uintptr(v.data) + uintptr(offset) fmt_arg(fi, any{rawptr(data), info.elem.id}, verb) } - io.write_string(fi.writer, ";\n") + io.write_string(fi.writer, ",\n") } } else { - for row in 0.. 0 { io.write_string(fi.writer, "; ") } - for col in 0.. 0 { io.write_string(fi.writer, ", ") } + for col in 0.. 0 { io.write_string(fi.writer, "; ") } + for row in 0.. 0 { io.write_string(fi.writer, ", ") } offset := (col + row*info.elem_stride)*info.elem_size From 8a626ef56476c698c4985859238a76dd53901b6f Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 3 Nov 2021 11:34:47 +0000 Subject: [PATCH 08/10] Minor comments about matrix printing --- core/fmt/fmt.odin | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/fmt/fmt.odin b/core/fmt/fmt.odin index 10b62d51b..1c32c3ce7 100644 --- a/core/fmt/fmt.odin +++ b/core/fmt/fmt.odin @@ -1927,8 +1927,8 @@ fmt_value :: proc(fi: ^Info, v: any, verb: rune) { fi.indent += 1 if fi.hash { + // Printed as it is written io.write_byte(fi.writer, '\n') - // TODO(bill): Should this render it like in written form? e.g. tranposed for col in 0.. 0 { io.write_string(fi.writer, "; ") } for row in 0.. Date: Wed, 3 Nov 2021 12:44:34 +0000 Subject: [PATCH 09/10] Make runtime builtin matrix procedures `contextless` --- core/runtime/core_builtin_matrix.odin | 38 +++++++++++++-------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/core/runtime/core_builtin_matrix.odin b/core/runtime/core_builtin_matrix.odin index 4091e6197..08dca288e 100644 --- a/core/runtime/core_builtin_matrix.odin +++ b/core/runtime/core_builtin_matrix.odin @@ -38,12 +38,12 @@ inverse :: proc{ } @(builtin) -hermitian_adjoint :: proc(m: $M/matrix[$N, N]$T) -> M where intrinsics.type_is_complex(T), N >= 1 { +hermitian_adjoint :: proc "contextless" (m: $M/matrix[$N, N]$T) -> M where intrinsics.type_is_complex(T), N >= 1 { return conj(transpose(m)) } @(builtin) -matrix_trace :: proc(m: $M/matrix[$N, N]$T) -> (trace: T) { +matrix_trace :: proc "contextless" (m: $M/matrix[$N, N]$T) -> (trace: T) { for i in 0.. (trace: T) { } @(builtin) -matrix_minor :: proc(m: $M/matrix[$N, N]$T, row, column: int) -> (minor: T) where N > 1 { +matrix_minor :: proc "contextless" (m: $M/matrix[$N, N]$T, row, column: int) -> (minor: T) where N > 1 { K :: N-1 cut_down: matrix[K, K]T for col_idx in 0.. (minor: T) wher @(builtin) -matrix1x1_determinant :: proc(m: $M/matrix[1, 1]$T) -> (det: T) { +matrix1x1_determinant :: proc "contextless" (m: $M/matrix[1, 1]$T) -> (det: T) { return m[0, 0] } @(builtin) -matrix2x2_determinant :: proc(m: $M/matrix[2, 2]$T) -> (det: T) { +matrix2x2_determinant :: proc "contextless" (m: $M/matrix[2, 2]$T) -> (det: T) { return m[0, 0]*m[1, 1] - m[0, 1]*m[1, 0] } @(builtin) -matrix3x3_determinant :: proc(m: $M/matrix[3, 3]$T) -> (det: T) { +matrix3x3_determinant :: proc "contextless" (m: $M/matrix[3, 3]$T) -> (det: T) { a := +m[0, 0] * (m[1, 1] * m[2, 2] - m[1, 2] * m[2, 1]) b := -m[0, 1] * (m[1, 0] * m[2, 2] - m[1, 2] * m[2, 0]) c := +m[0, 2] * (m[1, 0] * m[2, 1] - m[1, 1] * m[2, 0]) return a + b + c } @(builtin) -matrix4x4_determinant :: proc(m: $M/matrix[4, 4]$T) -> (det: T) { +matrix4x4_determinant :: proc "contextless" (m: $M/matrix[4, 4]$T) -> (det: T) { a := adjugate(m) #no_bounds_check for i in 0..<4 { det += m[0, i] * a[0, i] @@ -95,13 +95,13 @@ matrix4x4_determinant :: proc(m: $M/matrix[4, 4]$T) -> (det: T) { @(builtin) -matrix1x1_adjugate :: proc(x: $M/matrix[1, 1]$T) -> (y: M) { +matrix1x1_adjugate :: proc "contextless" (x: $M/matrix[1, 1]$T) -> (y: M) { y = x return } @(builtin) -matrix2x2_adjugate :: proc(x: $M/matrix[2, 2]$T) -> (y: M) { +matrix2x2_adjugate :: proc "contextless" (x: $M/matrix[2, 2]$T) -> (y: M) { y[0, 0] = +x[1, 1] y[0, 1] = -x[1, 0] y[1, 0] = -x[0, 1] @@ -110,7 +110,7 @@ matrix2x2_adjugate :: proc(x: $M/matrix[2, 2]$T) -> (y: M) { } @(builtin) -matrix3x3_adjugate :: proc(m: $M/matrix[3, 3]$T) -> (y: M) { +matrix3x3_adjugate :: proc "contextless" (m: $M/matrix[3, 3]$T) -> (y: M) { y[0, 0] = +(m[1, 1] * m[2, 2] - m[2, 1] * m[1, 2]) y[0, 1] = -(m[1, 0] * m[2, 2] - m[2, 0] * m[1, 2]) y[0, 2] = +(m[1, 0] * m[2, 1] - m[2, 0] * m[1, 1]) @@ -125,7 +125,7 @@ matrix3x3_adjugate :: proc(m: $M/matrix[3, 3]$T) -> (y: M) { @(builtin) -matrix4x4_adjugate :: proc(x: $M/matrix[4, 4]$T) -> (y: M) { +matrix4x4_adjugate :: proc "contextless" (x: $M/matrix[4, 4]$T) -> (y: M) { for i in 0..<4 { for j in 0..<4 { sign: T = 1 if (i + j) % 2 == 0 else -1 @@ -136,13 +136,13 @@ matrix4x4_adjugate :: proc(x: $M/matrix[4, 4]$T) -> (y: M) { } @(builtin) -matrix1x1_inverse_transpose :: proc(x: $M/matrix[1, 1]$T) -> (y: M) { +matrix1x1_inverse_transpose :: proc "contextless" (x: $M/matrix[1, 1]$T) -> (y: M) { y[0, 0] = 1/x[0, 0] return } @(builtin) -matrix2x2_inverse_transpose :: proc(x: $M/matrix[2, 2]$T) -> (y: M) { +matrix2x2_inverse_transpose :: proc "contextless" (x: $M/matrix[2, 2]$T) -> (y: M) { d := x[0, 0]*x[1, 1] - x[0, 1]*x[1, 0] when intrinsics.type_is_integer(T) { y[0, 0] = +x[1, 1] / d @@ -160,7 +160,7 @@ matrix2x2_inverse_transpose :: proc(x: $M/matrix[2, 2]$T) -> (y: M) { } @(builtin) -matrix3x3_inverse_transpose :: proc(x: $M/matrix[3, 3]$T) -> (y: M) #no_bounds_check { +matrix3x3_inverse_transpose :: proc "contextless" (x: $M/matrix[3, 3]$T) -> (y: M) #no_bounds_check { a := adjugate(x) d := determinant(x) when intrinsics.type_is_integer(T) { @@ -181,7 +181,7 @@ matrix3x3_inverse_transpose :: proc(x: $M/matrix[3, 3]$T) -> (y: M) #no_bounds_c } @(builtin) -matrix4x4_inverse_transpose :: proc(x: $M/matrix[4, 4]$T) -> (y: M) #no_bounds_check { +matrix4x4_inverse_transpose :: proc "contextless" (x: $M/matrix[4, 4]$T) -> (y: M) #no_bounds_check { a := adjugate(x) d: T for i in 0..<4 { @@ -205,13 +205,13 @@ matrix4x4_inverse_transpose :: proc(x: $M/matrix[4, 4]$T) -> (y: M) #no_bounds_c } @(builtin) -matrix1x1_inverse :: proc(x: $M/matrix[1, 1]$T) -> (y: M) { +matrix1x1_inverse :: proc "contextless" (x: $M/matrix[1, 1]$T) -> (y: M) { y[0, 0] = 1/x[0, 0] return } @(builtin) -matrix2x2_inverse :: proc(x: $M/matrix[2, 2]$T) -> (y: M) { +matrix2x2_inverse :: proc "contextless" (x: $M/matrix[2, 2]$T) -> (y: M) { d := x[0, 0]*x[1, 1] - x[0, 1]*x[1, 0] when intrinsics.type_is_integer(T) { y[0, 0] = x[1, 1] / d @@ -229,7 +229,7 @@ matrix2x2_inverse :: proc(x: $M/matrix[2, 2]$T) -> (y: M) { } @(builtin) -matrix3x3_inverse :: proc(x: $M/matrix[3, 3]$T) -> (y: M) #no_bounds_check { +matrix3x3_inverse :: proc "contextless" (x: $M/matrix[3, 3]$T) -> (y: M) #no_bounds_check { a := adjugate(x) d := determinant(x) when intrinsics.type_is_integer(T) { @@ -250,7 +250,7 @@ matrix3x3_inverse :: proc(x: $M/matrix[3, 3]$T) -> (y: M) #no_bounds_check { } @(builtin) -matrix4x4_inverse :: proc(x: $M/matrix[4, 4]$T) -> (y: M) #no_bounds_check { +matrix4x4_inverse :: proc "contextless" (x: $M/matrix[4, 4]$T) -> (y: M) #no_bounds_check { a := adjugate(x) d: T for i in 0..<4 { From 3d06dddb72e00409b14df36959bb3bcdc8d42999 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 3 Nov 2021 12:45:19 +0000 Subject: [PATCH 10/10] Allow casting from floats to quaternions --- src/check_expr.cpp | 3 +++ src/llvm_backend_expr.cpp | 17 +++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 1e8c24fd6..2139cd777 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -2453,6 +2453,9 @@ bool check_is_castable_to(CheckerContext *c, Operand *operand, Type *y) { return true; } + if (is_type_float(src) && is_type_quaternion(dst)) { + return true; + } if (is_type_complex(src) && is_type_quaternion(dst)) { return true; } diff --git a/src/llvm_backend_expr.cpp b/src/llvm_backend_expr.cpp index d49863c2a..8fd39fdb9 100644 --- a/src/llvm_backend_expr.cpp +++ b/src/llvm_backend_expr.cpp @@ -1658,6 +1658,23 @@ lbValue lb_emit_conv(lbProcedure *p, lbValue value, Type *t) { } return res; } + + if (is_type_float(src) && is_type_complex(dst)) { + Type *ft = base_complex_elem_type(dst); + lbAddr gen = lb_add_local_generated(p, dst, false); + 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_quaternion(dst)) { + Type *ft = base_complex_elem_type(dst); + lbAddr gen = lb_add_local_generated(p, dst, false); + 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_complex(src) && is_type_complex(dst)) { Type *ft = base_complex_elem_type(dst);