From 096b4f54543cc3048bb430317aa286a31f2204e6 Mon Sep 17 00:00:00 2001 From: Aaron Kavaler Date: Mon, 18 Mar 2024 20:32:30 -0700 Subject: [PATCH 01/10] fixed issue #3264 regarding core:odin/parser not allowing a newline at the end of a compound literal --- core/odin/parser/parser.odin | 1 + 1 file changed, 1 insertion(+) diff --git a/core/odin/parser/parser.odin b/core/odin/parser/parser.odin index fc7a2c792..ab723e145 100644 --- a/core/odin/parser/parser.odin +++ b/core/odin/parser/parser.odin @@ -2947,6 +2947,7 @@ parse_literal_value :: proc(p: ^Parser, type: ^ast.Expr) -> ^ast.Comp_Lit { } p.expr_level -= 1 + skip_possible_newline(p) close := expect_token_after(p, .Close_Brace, "compound literal") pos := type.pos if type != nil else open.pos From a5558625228045830b0e90b3922f684350ff9beb Mon Sep 17 00:00:00 2001 From: Laytan Laats Date: Tue, 19 Mar 2024 19:43:41 +0100 Subject: [PATCH 02/10] linker improvements `path_to_fullpath` did different things on Windows&Unix, an attempt to bring them closer together was made here. This was prompted by the compiler completely ignoring `foreign import "foo.dylib"` when `foo.dylib` does not exist (because `path_to_fullpath` returns an empty string). Causing just unresolved symbol errors, when on Windows it would pass along the path to the linker and actually say it doesn't exist, which is now also the case for Unix. This also fixes some checker errors that relied on the Windows behaviour, for example: `Error: File name, , cannot be as a library name as it is not a valid identifier`. Made `-no-crt` require either `-default-to-nil-allocator` or `-default-to-panic-allocator` on Unix, the current default allocators rely on libc and this was not obvious and would immediately bring up unresolved symbol errors for the linked memory management functions, or just link with libc anyways because it was foreign imported. Added a suggestion to install `nasm` with the user's package manager when assembling using `nasm` fails on Unix, I saw some confusion about it in the Discord. Ignore explicit foreign imports of libc. It is already linked in later on in the linking process and would otherwise (at least on macOS) cause linker warnings for duplicate libraries. This also makes it so when using `-no-crt` and importing something that requires libc, linker errors are given (like I would expect), instead of silently still linking with libc because it was foreign imported. --- src/build_settings.cpp | 27 +++++++++++++++++++++++++-- src/linker.cpp | 14 +++++++++++--- 2 files changed, 36 insertions(+), 5 deletions(-) diff --git a/src/build_settings.cpp b/src/build_settings.cpp index fdaa971f1..fa57e3809 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -1190,13 +1190,24 @@ gb_internal String path_to_fullpath(gbAllocator a, String s, bool *ok_) { char *p; mutex_lock(&fullpath_mutex); p = realpath(cast(char *)s.text, 0); + defer (free(p)); mutex_unlock(&fullpath_mutex); if(p == nullptr) { if (ok_) *ok_ = false; - return String{}; + + // Path doesn't exist or is malformed, Windows's `GetFullPathNameW` does not check for + // existence of the file where `realpath` does, which causes different behaviour between platforms. + // Two things could be done here: + // 1. clean the path and resolve it manually, just like the Windows function does, + // probably requires porting `filepath.clean` from Odin and doing some more processing. + // 2. just return a copy of the original path. + // + // I have opted for 2 because it is much simpler + we already return `ok = false` + further + // checks and processes will use the path and cause errors (which we want). + return copy_string(a, s); } if (ok_) *ok_ = true; - return make_string_c(p); + return copy_string(a, make_string_c(p)); } #else #error Implement system @@ -1939,6 +1950,18 @@ gb_internal bool init_build_paths(String init_filename) { } } + if (build_context.no_crt && !build_context.ODIN_DEFAULT_TO_NIL_ALLOCATOR && !build_context.ODIN_DEFAULT_TO_PANIC_ALLOCATOR) { + switch (build_context.metrics.os) { + case TargetOs_linux: + case TargetOs_darwin: + case TargetOs_essence: + case TargetOs_freebsd: + case TargetOs_openbsd: + case TargetOs_haiku: + gb_printf_err("-no-crt on unix systems requires either -default-to-nil-allocator or -default-to-panic-allocator to also be present because the default allocator requires crt\n"); + return false; + } + } if (bc->target_features_string.len != 0) { enable_target_feature({}, bc->target_features_string); diff --git a/src/linker.cpp b/src/linker.cpp index 0cdeaf8d9..9d7f16f1d 100644 --- a/src/linker.cpp +++ b/src/linker.cpp @@ -376,6 +376,10 @@ gb_internal i32 linker_stage(LinkerData *gen) { LIT(obj_file), LIT(build_context.extra_assembler_flags) ); + if (!result) { + gb_printf_err("executing `nasm` to assemble foreing import of %.*s failed.\n\tSuggestion: `nasm` does not ship with the compiler and should be installed with your system's package manager.\n", LIT(asm_file)); + return result; + } } array_add(&gen->output_object_paths, obj_file); } else { @@ -383,9 +387,13 @@ gb_internal i32 linker_stage(LinkerData *gen) { continue; } - // NOTE(zangent): Sometimes, you have to use -framework on MacOS. - // This allows you to specify '-f' in a #foreign_system_library, - // without having to implement any new syntax specifically for MacOS. + // Do not add libc again, this is added later already, and omitted with + // the `-no-crt` flag, not skipping here would cause duplicate library + // warnings when linking on darwin and might link libc silently even with `-no-crt`. + if (lib == str_lit("System.framework") || lib == str_lit("c")) { + continue; + } + if (build_context.metrics.os == TargetOs_darwin) { if (string_ends_with(lib, str_lit(".framework"))) { // framework thingie From a750fc0ba63c9f1461bba4cc0446b1b4c2d2b3a9 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 19 Mar 2024 21:05:23 +0000 Subject: [PATCH 03/10] Add `#row_major matrix[R, C]T` As well as `#column_major matrix[R, C]T` as an alias for just `matrix[R, C]T`. This is because some libraries require a row_major internal layout but still want to be used with row or major oriented vectors. --- base/runtime/core.odin | 4 ++++ core/fmt/fmt.odin | 12 +++++++++-- core/reflect/types.odin | 4 ++++ src/check_expr.cpp | 12 ++++++++--- src/check_type.cpp | 2 +- src/llvm_backend_const.cpp | 4 ++-- src/llvm_backend_expr.cpp | 39 +++++++++++++++++++++++++++--------- src/llvm_backend_type.cpp | 3 ++- src/llvm_backend_utility.cpp | 22 +++++++++++++------- src/parser.cpp | 13 ++++++++++++ src/parser.hpp | 1 + src/types.cpp | 19 ++++++++++++++---- 12 files changed, 105 insertions(+), 30 deletions(-) diff --git a/base/runtime/core.odin b/base/runtime/core.odin index 8f27ca674..7ad3ef1d6 100644 --- a/base/runtime/core.odin +++ b/base/runtime/core.odin @@ -177,6 +177,10 @@ Type_Info_Matrix :: struct { row_count: int, column_count: int, // Total element count = column_count * elem_stride + layout: enum u8 { + Column_Major, // array of column vectors + Row_Major, // array of row vectors + }, } Type_Info_Soa_Pointer :: struct { elem: ^Type_Info, diff --git a/core/fmt/fmt.odin b/core/fmt/fmt.odin index 02803f882..6f9801bc8 100644 --- a/core/fmt/fmt.odin +++ b/core/fmt/fmt.odin @@ -2396,7 +2396,11 @@ fmt_matrix :: proc(fi: ^Info, v: any, verb: rune, info: runtime.Type_Info_Matrix for col in 0.. 0 { io.write_string(fi.writer, ", ", &fi.n) } - offset := (row + col*info.elem_stride)*info.elem_size + offset: int + switch info.layout { + case .Column_Major: offset = (row + col*info.elem_stride)*info.elem_size + case .Row_Major: 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) @@ -2410,7 +2414,11 @@ fmt_matrix :: proc(fi: ^Info, v: any, verb: rune, info: runtime.Type_Info_Matrix for col in 0.. 0 { io.write_string(fi.writer, ", ", &fi.n) } - offset := (row + col*info.elem_stride)*info.elem_size + offset: int + switch info.layout { + case .Column_Major: offset = (row + col*info.elem_stride)*info.elem_size + case .Row_Major: 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) diff --git a/core/reflect/types.odin b/core/reflect/types.odin index 2b96dd4fb..9cff46a00 100644 --- a/core/reflect/types.odin +++ b/core/reflect/types.odin @@ -173,6 +173,7 @@ are_types_identical :: proc(a, b: ^Type_Info) -> bool { y := b.variant.(Type_Info_Matrix) or_return if x.row_count != y.row_count { return false } if x.column_count != y.column_count { return false } + if x.layout != y.layout { return false } return are_types_identical(x.elem, y.elem) case Type_Info_Bit_Field: @@ -689,6 +690,9 @@ write_type_writer :: proc(w: io.Writer, ti: ^Type_Info, n_written: ^int = nil) - write_type(w, info.pointer, &n) or_return case Type_Info_Matrix: + if info.layout == .Row_Major { + io.write_string(w, "#row_major ", &n) or_return + } io.write_string(w, "matrix[", &n) or_return io.write_i64(w, i64(info.row_count), 10, &n) or_return io.write_string(w, ", ", &n) or_return diff --git a/src/check_expr.cpp b/src/check_expr.cpp index f359d5a54..67c7f1a04 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -3431,6 +3431,11 @@ gb_internal void check_binary_matrix(CheckerContext *c, Token const &op, Operand if (xt->Matrix.column_count != yt->Matrix.row_count) { goto matrix_error; } + + if (xt->Matrix.is_row_major != yt->Matrix.is_row_major) { + goto matrix_error; + } + x->mode = Addressing_Value; if (are_types_identical(xt, yt)) { if (!is_type_named(x->type) && is_type_named(y->type)) { @@ -3438,7 +3443,8 @@ gb_internal void check_binary_matrix(CheckerContext *c, Token const &op, Operand x->type = y->type; } } else { - x->type = alloc_type_matrix(xt->Matrix.elem, xt->Matrix.row_count, yt->Matrix.column_count); + bool is_row_major = xt->Matrix.is_row_major && yt->Matrix.is_row_major; + x->type = alloc_type_matrix(xt->Matrix.elem, xt->Matrix.row_count, yt->Matrix.column_count, nullptr, nullptr, is_row_major); } goto matrix_success; } else if (yt->kind == Type_Array) { @@ -3452,7 +3458,7 @@ gb_internal void check_binary_matrix(CheckerContext *c, Token const &op, Operand // Treat arrays as column vectors x->mode = Addressing_Value; - if (type_hint == nullptr && xt->Matrix.row_count == yt->Array.count) { + if (xt->Matrix.row_count == yt->Array.count) { x->type = y->type; } else { x->type = alloc_type_matrix(xt->Matrix.elem, xt->Matrix.row_count, 1); @@ -3483,7 +3489,7 @@ gb_internal void check_binary_matrix(CheckerContext *c, Token const &op, Operand // Treat arrays as row vectors x->mode = Addressing_Value; - if (type_hint == nullptr && yt->Matrix.column_count == xt->Array.count) { + if (yt->Matrix.column_count == xt->Array.count) { x->type = x->type; } else { x->type = alloc_type_matrix(yt->Matrix.elem, 1, yt->Matrix.column_count); diff --git a/src/check_type.cpp b/src/check_type.cpp index d5cf187a4..3fe633892 100644 --- a/src/check_type.cpp +++ b/src/check_type.cpp @@ -2658,7 +2658,7 @@ gb_internal void check_matrix_type(CheckerContext *ctx, Type **type, Ast *node) } type_assign:; - *type = alloc_type_matrix(elem, row_count, column_count, generic_row, generic_column); + *type = alloc_type_matrix(elem, row_count, column_count, generic_row, generic_column, mt->is_row_major); return; } diff --git a/src/llvm_backend_const.cpp b/src/llvm_backend_const.cpp index 2291f24ac..bbb0b8387 100644 --- a/src/llvm_backend_const.cpp +++ b/src/llvm_backend_const.cpp @@ -1302,11 +1302,11 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, bo GB_ASSERT_MSG(elem_count == max_count, "%td != %td", elem_count, max_count); LLVMValueRef *values = gb_alloc_array(temporary_allocator(), LLVMValueRef, cast(isize)total_count); - for_array(i, cl->elems) { TypeAndValue tav = cl->elems[i]->tav; GB_ASSERT(tav.mode != Addressing_Invalid); - i64 offset = matrix_row_major_index_to_offset(type, i); + i64 offset = 0; + 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 98618798b..6eb8fdcc6 100644 --- a/src/llvm_backend_expr.cpp +++ b/src/llvm_backend_expr.cpp @@ -684,12 +684,6 @@ gb_internal lbValue lb_emit_matrix_flatten(lbProcedure *p, lbValue m, Type *type Type *mt = base_type(m.type); GB_ASSERT(mt->kind == Type_Matrix); - // TODO(bill): Determine why this fails on Windows sometimes - if (false && lb_is_matrix_simdable(mt)) { - LLVMValueRef vector = lb_matrix_to_trimmed_vector(p, m); - return lb_matrix_cast_vector_to_type(p, vector, type); - } - lbAddr res = lb_add_local_generated(p, type, true); i64 row_count = mt->Matrix.row_count; @@ -763,6 +757,7 @@ gb_internal lbValue lb_emit_matrix_mul(lbProcedure *p, lbValue lhs, lbValue rhs, GB_ASSERT(is_type_matrix(yt)); GB_ASSERT(xt->Matrix.column_count == yt->Matrix.row_count); GB_ASSERT(are_types_identical(xt->Matrix.elem, yt->Matrix.elem)); + GB_ASSERT(xt->Matrix.is_row_major == yt->Matrix.is_row_major); Type *elem = xt->Matrix.elem; @@ -770,7 +765,7 @@ gb_internal lbValue lb_emit_matrix_mul(lbProcedure *p, lbValue lhs, lbValue rhs, unsigned inner = cast(unsigned)xt->Matrix.column_count; unsigned outer_columns = cast(unsigned)yt->Matrix.column_count; - if (lb_is_matrix_simdable(xt)) { + if (!xt->Matrix.is_row_major && lb_is_matrix_simdable(xt)) { unsigned x_stride = cast(unsigned)matrix_type_stride_in_elems(xt); unsigned y_stride = cast(unsigned)matrix_type_stride_in_elems(yt); @@ -812,7 +807,7 @@ gb_internal lbValue lb_emit_matrix_mul(lbProcedure *p, lbValue lhs, lbValue rhs, return lb_addr_load(p, res); } - { + if (!xt->Matrix.is_row_major) { lbAddr res = lb_add_local_generated(p, type, true); auto inners = slice_make(permanent_allocator(), inner); @@ -835,6 +830,30 @@ gb_internal lbValue lb_emit_matrix_mul(lbProcedure *p, lbValue lhs, lbValue rhs, } } + return lb_addr_load(p, res); + } else { + lbAddr res = lb_add_local_generated(p, type, true); + + auto inners = slice_make(permanent_allocator(), inner); + + for (unsigned i = 0; i < outer_rows; i++) { + for (unsigned j = 0; j < outer_columns; j++) { + lbValue dst = lb_emit_matrix_epi(p, res.addr, i, j); + for (unsigned k = 0; k < inner; k++) { + inners[k][0] = lb_emit_matrix_ev(p, lhs, i, k); + inners[k][1] = lb_emit_matrix_ev(p, rhs, k, j); + } + + lbValue sum = lb_const_nil(p->module, elem); + for (unsigned k = 0; k < inner; k++) { + lbValue a = inners[k][0]; + lbValue b = inners[k][1]; + sum = lb_emit_mul_add(p, a, b, sum, elem); + } + lb_emit_store(p, dst, sum); + } + } + return lb_addr_load(p, res); } } @@ -855,7 +874,7 @@ gb_internal lbValue lb_emit_matrix_mul_vector(lbProcedure *p, lbValue lhs, lbVal Type *elem = mt->Matrix.elem; - if (lb_is_matrix_simdable(mt)) { + if (!mt->Matrix.is_row_major && lb_is_matrix_simdable(mt)) { unsigned stride = cast(unsigned)matrix_type_stride_in_elems(mt); unsigned row_count = cast(unsigned)mt->Matrix.row_count; @@ -924,7 +943,7 @@ gb_internal lbValue lb_emit_vector_mul_matrix(lbProcedure *p, lbValue lhs, lbVal Type *elem = mt->Matrix.elem; - if (lb_is_matrix_simdable(mt)) { + if (!mt->Matrix.is_row_major && lb_is_matrix_simdable(mt)) { unsigned stride = cast(unsigned)matrix_type_stride_in_elems(mt); unsigned row_count = cast(unsigned)mt->Matrix.row_count; diff --git a/src/llvm_backend_type.cpp b/src/llvm_backend_type.cpp index aec1fb201..de83f5058 100644 --- a/src/llvm_backend_type.cpp +++ b/src/llvm_backend_type.cpp @@ -979,12 +979,13 @@ gb_internal void lb_setup_type_info_data_giant_array(lbModule *m, i64 global_typ tag_type = t_type_info_matrix; i64 ez = type_size_of(t->Matrix.elem); - LLVMValueRef vals[5] = { + LLVMValueRef vals[6] = { get_type_info_ptr(m, t->Matrix.elem), lb_const_int(m, t_int, ez).value, lb_const_int(m, t_int, matrix_type_stride_in_elems(t)).value, lb_const_int(m, t_int, t->Matrix.row_count).value, lb_const_int(m, t_int, t->Matrix.column_count).value, + lb_const_int(m, t_u8, cast(u8)t->Matrix.is_row_major).value, }; variant_value = llvm_const_named_struct(m, tag_type, vals, gb_count_of(vals)); diff --git a/src/llvm_backend_utility.cpp b/src/llvm_backend_utility.cpp index f18aa5521..fb61c41c3 100644 --- a/src/llvm_backend_utility.cpp +++ b/src/llvm_backend_utility.cpp @@ -1464,14 +1464,16 @@ gb_internal lbValue lb_emit_matrix_epi(lbProcedure *p, lbValue s, isize row, isi Type *t = s.type; GB_ASSERT(is_type_pointer(t)); Type *mt = base_type(type_deref(t)); - if (column == 0) { - GB_ASSERT_MSG(is_type_matrix(mt) || is_type_array_like(mt), "%s", type_to_string(mt)); - return lb_emit_epi(p, s, row); - } else if (row == 0 && is_type_array_like(mt)) { - return lb_emit_epi(p, s, column); + + if (!mt->Matrix.is_row_major) { + if (column == 0) { + GB_ASSERT_MSG(is_type_matrix(mt) || is_type_array_like(mt), "%s", type_to_string(mt)); + return lb_emit_epi(p, s, row); + } else if (row == 0 && is_type_array_like(mt)) { + return lb_emit_epi(p, s, column); + } } - GB_ASSERT_MSG(is_type_matrix(mt), "%s", type_to_string(mt)); isize offset = matrix_indices_to_offset(mt, row, column); @@ -1491,7 +1493,13 @@ gb_internal lbValue lb_emit_matrix_ep(lbProcedure *p, lbValue s, lbValue row, lb row = lb_emit_conv(p, row, t_int); column = lb_emit_conv(p, column, t_int); - LLVMValueRef index = LLVMBuildAdd(p->builder, row.value, LLVMBuildMul(p->builder, column.value, stride_elems, ""), ""); + LLVMValueRef index = nullptr; + + if (mt->Matrix.is_row_major) { + index = LLVMBuildAdd(p->builder, column.value, LLVMBuildMul(p->builder, row.value, stride_elems, ""), ""); + } else { + index = LLVMBuildAdd(p->builder, row.value, LLVMBuildMul(p->builder, column.value, stride_elems, ""), ""); + } LLVMValueRef indices[2] = { LLVMConstInt(lb_type(p->module, t_int), 0, false), diff --git a/src/parser.cpp b/src/parser.cpp index 1aa40ccbf..eb9e73342 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -2329,6 +2329,19 @@ gb_internal Ast *parse_operand(AstFile *f, bool lhs) { break; } return original_type; + } else if (name.string == "row_major" || + name.string == "column_major") { + Ast *original_type = parse_type(f); + Ast *type = unparen_expr(original_type); + switch (type->kind) { + case Ast_MatrixType: + type->MatrixType.is_row_major = (name.string == "row_major"); + break; + default: + syntax_error(type, "Expected a matrix type after #%.*s, got %.*s", LIT(name.string), LIT(ast_strings[type->kind])); + break; + } + return original_type; } else if (name.string == "partial") { Ast *tag = ast_basic_directive(f, token, name); Ast *original_expr = parse_expr(f, lhs); diff --git a/src/parser.hpp b/src/parser.hpp index f5997c4bd..ff3c5eb34 100644 --- a/src/parser.hpp +++ b/src/parser.hpp @@ -772,6 +772,7 @@ AST_KIND(_TypeBegin, "", bool) \ Ast *row_count; \ Ast *column_count; \ Ast *elem; \ + bool is_row_major; \ }) \ AST_KIND(_TypeEnd, "", bool) diff --git a/src/types.cpp b/src/types.cpp index 5a3ad5d6b..ab5e4de03 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -281,6 +281,7 @@ struct TypeProc { Type *generic_row_count; \ Type *generic_column_count; \ i64 stride_in_bytes; \ + bool is_row_major; \ }) \ TYPE_KIND(BitField, struct { \ Scope * scope; \ @@ -1002,7 +1003,7 @@ gb_internal Type *alloc_type_array(Type *elem, i64 count, Type *generic_count = return t; } -gb_internal Type *alloc_type_matrix(Type *elem, i64 row_count, i64 column_count, Type *generic_row_count = nullptr, Type *generic_column_count = nullptr) { +gb_internal Type *alloc_type_matrix(Type *elem, i64 row_count, i64 column_count, Type *generic_row_count = nullptr, Type *generic_column_count = nullptr, bool is_row_major = false) { if (generic_row_count != nullptr || generic_column_count != nullptr) { Type *t = alloc_type(Type_Matrix); t->Matrix.elem = elem; @@ -1010,12 +1011,14 @@ gb_internal Type *alloc_type_matrix(Type *elem, i64 row_count, i64 column_count, t->Matrix.column_count = column_count; t->Matrix.generic_row_count = generic_row_count; t->Matrix.generic_column_count = generic_column_count; + t->Matrix.is_row_major = is_row_major; return t; } Type *t = alloc_type(Type_Matrix); t->Matrix.elem = elem; t->Matrix.row_count = row_count; t->Matrix.column_count = column_count; + t->Matrix.is_row_major = is_row_major; return t; } @@ -1512,14 +1515,18 @@ gb_internal i64 matrix_indices_to_offset(Type *t, i64 row_index, i64 column_inde GB_ASSERT(0 <= row_index && row_index < t->Matrix.row_count); GB_ASSERT(0 <= column_index && column_index < t->Matrix.column_count); i64 stride_elems = matrix_type_stride_in_elems(t); - // NOTE(bill): Column-major layout internally - return row_index + stride_elems*column_index; + if (t->Matrix.is_row_major) { + return column_index + stride_elems*row_index; + } else { + // NOTE(bill): Column-major layout internally + return row_index + stride_elems*column_index; + } } gb_internal 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.column_count; i64 column_index = index%t->Matrix.column_count; return matrix_indices_to_offset(t, row_index, column_index); @@ -2690,6 +2697,7 @@ gb_internal bool are_types_identical_internal(Type *x, Type *y, bool check_tuple case Type_Matrix: return x->Matrix.row_count == y->Matrix.row_count && x->Matrix.column_count == y->Matrix.column_count && + x->Matrix.is_row_major == y->Matrix.is_row_major && are_types_identical(x->Matrix.elem, y->Matrix.elem); case Type_DynamicArray: @@ -4735,6 +4743,9 @@ gb_internal gbString write_type_to_string(gbString str, Type *type, bool shortha break; case Type_Matrix: + if (type->Matrix.is_row_major) { + str = gb_string_appendc(str, "#row_major "); + } str = gb_string_appendc(str, gb_bprintf("matrix[%d, %d]", cast(int)type->Matrix.row_count, cast(int)type->Matrix.column_count)); str = write_type_to_string(str, type->Matrix.elem); break; From 18fb665bf684b6f55cc513eddd14e3224f9e70ad Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 19 Mar 2024 21:15:47 +0000 Subject: [PATCH 04/10] Correct matrix builtins for `#row_major` --- src/check_builtin.cpp | 4 ++-- src/check_expr.cpp | 11 +++++++++-- src/types.cpp | 2 +- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp index 6de3b27f2..d3158961e 100644 --- a/src/check_builtin.cpp +++ b/src/check_builtin.cpp @@ -3488,7 +3488,7 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As } } else { GB_ASSERT(t->kind == Type_Matrix); - operand->type = alloc_type_matrix(t->Matrix.elem, t->Matrix.column_count, t->Matrix.row_count); + operand->type = alloc_type_matrix(t->Matrix.elem, t->Matrix.column_count, t->Matrix.row_count, nullptr, nullptr, t->Matrix.is_row_major); } operand->type = check_matrix_type_hint(operand->type, type_hint); break; @@ -3556,7 +3556,7 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As } operand->mode = Addressing_Value; - operand->type = alloc_type_matrix(elem, xt->Array.count, yt->Array.count); + operand->type = alloc_type_matrix(elem, xt->Array.count, yt->Array.count, nullptr, nullptr, false); operand->type = check_matrix_type_hint(operand->type, type_hint); break; } diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 67c7f1a04..e9a6f5122 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -3397,6 +3397,13 @@ gb_internal Type *check_matrix_type_hint(Type *matrix, Type *type_hint) { Type *th = base_type(type_hint); if (are_types_identical(th, xt)) { return type_hint; + } else if (xt->kind == Type_Matrix && th->kind == Type_Matrix) { + if (!are_types_identical(xt->Matrix.elem, th->Matrix.elem)) { + // ignore + } if (xt->Matrix.row_count == th->Matrix.row_count && + xt->Matrix.column_count == th->Matrix.column_count) { + return type_hint; + } } else if (xt->kind == Type_Matrix && th->kind == Type_Array) { if (!are_types_identical(xt->Matrix.elem, th->Array.elem)) { // ignore @@ -3461,7 +3468,7 @@ gb_internal void check_binary_matrix(CheckerContext *c, Token const &op, Operand if (xt->Matrix.row_count == yt->Array.count) { x->type = y->type; } else { - x->type = alloc_type_matrix(xt->Matrix.elem, xt->Matrix.row_count, 1); + x->type = alloc_type_matrix(xt->Matrix.elem, xt->Matrix.row_count, 1, nullptr, nullptr, xt->Matrix.is_row_major); } goto matrix_success; } @@ -3492,7 +3499,7 @@ gb_internal void check_binary_matrix(CheckerContext *c, Token const &op, Operand if (yt->Matrix.column_count == xt->Array.count) { x->type = x->type; } else { - x->type = alloc_type_matrix(yt->Matrix.elem, 1, yt->Matrix.column_count); + x->type = alloc_type_matrix(yt->Matrix.elem, 1, yt->Matrix.column_count, nullptr, nullptr, yt->Matrix.is_row_major); } goto matrix_success; } else if (are_types_identical(yt->Matrix.elem, xt)) { diff --git a/src/types.cpp b/src/types.cpp index ab5e4de03..c2358056b 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -1003,7 +1003,7 @@ gb_internal Type *alloc_type_array(Type *elem, i64 count, Type *generic_count = return t; } -gb_internal Type *alloc_type_matrix(Type *elem, i64 row_count, i64 column_count, Type *generic_row_count = nullptr, Type *generic_column_count = nullptr, bool is_row_major = false) { +gb_internal Type *alloc_type_matrix(Type *elem, i64 row_count, i64 column_count, Type *generic_row_count, Type *generic_column_count, bool is_row_major) { if (generic_row_count != nullptr || generic_column_count != nullptr) { Type *t = alloc_type(Type_Matrix); t->Matrix.elem = elem; From cd7137af60ba2c3f1d95ae77d59e6663412eab4a Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 19 Mar 2024 21:16:04 +0000 Subject: [PATCH 05/10] Update raylib to use `#row_major` matrices --- vendor/raylib/raylib.odin | 12 ++++++------ vendor/raylib/raymath.odin | 31 ++++++++++++++++++------------- 2 files changed, 24 insertions(+), 19 deletions(-) diff --git a/vendor/raylib/raylib.odin b/vendor/raylib/raylib.odin index 0e4bf60dc..b98770271 100644 --- a/vendor/raylib/raylib.odin +++ b/vendor/raylib/raylib.odin @@ -213,17 +213,17 @@ MAGENTA :: Color{ 255, 0, 255, 255 } // Magenta RAYWHITE :: Color{ 245, 245, 245, 255 } // My own White (raylib logo) // Vector2 type -Vector2 :: linalg.Vector2f32 +Vector2 :: [2]f32 // Vector3 type -Vector3 :: linalg.Vector3f32 +Vector3 :: [3]f32 // Vector4 type -Vector4 :: linalg.Vector4f32 +Vector4 :: [4]f32 // Quaternion type -Quaternion :: linalg.Quaternionf32 +Quaternion :: quaternion128 -// Matrix type (OpenGL style 4x4 - right handed, stored column major) -Matrix :: linalg.Matrix4x4f32 +// Matrix type (right handed, stored row major) +Matrix :: #row_major matrix[4, 4]f32 // Color, 4 components, R8G8B8A8 (32bit) diff --git a/vendor/raylib/raymath.odin b/vendor/raylib/raymath.odin index c657152c1..beeda7989 100644 --- a/vendor/raylib/raymath.odin +++ b/vendor/raylib/raymath.odin @@ -590,74 +590,79 @@ MatrixMultiply :: proc "c" (left, right: Matrix) -> Matrix { // Get translation matrix @(require_results) MatrixTranslate :: proc "c" (x, y, z: f32) -> Matrix { - return linalg.matrix4_translate(Vector3{x, y, z}) + return { + 1, 0, 0, x, + 0, 1, 0, y, + 0, 0, 1, z, + 0, 0, 0, 1, + } } // Create rotation matrix from axis and angle // NOTE: Angle should be provided in radians @(require_results) MatrixRotate :: proc "c" (axis: Vector3, angle: f32) -> Matrix { - return linalg.matrix4_rotate(angle, axis) + return auto_cast linalg.matrix4_rotate(angle, axis) } // Get x-rotation matrix // NOTE: Angle must be provided in radians @(require_results) MatrixRotateX :: proc "c" (angle: f32) -> Matrix { - return linalg.matrix4_rotate(angle, Vector3{1, 0, 0}) + return auto_cast linalg.matrix4_rotate(angle, Vector3{1, 0, 0}) } // Get y-rotation matrix // NOTE: Angle must be provided in radians @(require_results) MatrixRotateY :: proc "c" (angle: f32) -> Matrix { - return linalg.matrix4_rotate(angle, Vector3{0, 1, 0}) + return auto_cast linalg.matrix4_rotate(angle, Vector3{0, 1, 0}) } // Get z-rotation matrix // NOTE: Angle must be provided in radians @(require_results) MatrixRotateZ :: proc "c" (angle: f32) -> Matrix { - return linalg.matrix4_rotate(angle, Vector3{0, 0, 1}) + return auto_cast linalg.matrix4_rotate(angle, Vector3{0, 0, 1}) } // Get xyz-rotation matrix // NOTE: Angle must be provided in radians @(require_results) MatrixRotateXYZ :: proc "c" (angle: Vector3) -> Matrix { - return linalg.matrix4_from_euler_angles_xyz(angle.x, angle.y, angle.z) + return auto_cast linalg.matrix4_from_euler_angles_xyz(angle.x, angle.y, angle.z) } // Get zyx-rotation matrix // NOTE: Angle must be provided in radians @(require_results) MatrixRotateZYX :: proc "c" (angle: Vector3) -> Matrix { - return linalg.matrix4_from_euler_angles_zyx(angle.x, angle.y, angle.z) + return auto_cast linalg.matrix4_from_euler_angles_zyx(angle.x, angle.y, angle.z) } // Get scaling matrix @(require_results) MatrixScale :: proc "c" (x, y, z: f32) -> Matrix { - return linalg.matrix4_scale(Vector3{x, y, z}) + return auto_cast linalg.matrix4_scale(Vector3{x, y, z}) } // Get orthographic projection matrix @(require_results) MatrixOrtho :: proc "c" (left, right, bottom, top, near, far: f32) -> Matrix { - return linalg.matrix_ortho3d(left, right, bottom, top, near, far) + return auto_cast linalg.matrix_ortho3d(left, right, bottom, top, near, far) } // Get perspective projection matrix // NOTE: Fovy angle must be provided in radians @(require_results) MatrixPerspective :: proc "c" (fovY, aspect, nearPlane, farPlane: f32) -> Matrix { - return linalg.matrix4_perspective(fovY, aspect, nearPlane, farPlane) + return auto_cast linalg.matrix4_perspective(fovY, aspect, nearPlane, farPlane) } // Get camera look-at matrix (view matrix) @(require_results) MatrixLookAt :: proc "c" (eye, target, up: Vector3) -> Matrix { - return linalg.matrix4_look_at(eye, target, up) + return auto_cast linalg.matrix4_look_at(eye, target, up) } // Get float array of matrix data @@ -755,12 +760,12 @@ QuaternionFromVector3ToVector3 :: proc "c" (from, to: Vector3) -> Quaternion { // Get a quaternion for a given rotation matrix @(require_results) QuaternionFromMatrix :: proc "c" (mat: Matrix) -> Quaternion { - return linalg.quaternion_from_matrix4(mat) + return linalg.quaternion_from_matrix4(linalg.Matrix4f32(mat)) } // Get a matrix for a given quaternion @(require_results) QuaternionToMatrix :: proc "c" (q: Quaternion) -> Matrix { - return linalg.matrix4_from_quaternion(q) + return auto_cast linalg.matrix4_from_quaternion(q) } // Get rotation quaternion for an angle and axis NOTE: Angle must be provided in radians @(require_results) From d0b3b18e26ca7b862b7bd2b90a3cd0d0ec97a3f6 Mon Sep 17 00:00:00 2001 From: Laytan Laats Date: Wed, 20 Mar 2024 00:14:01 +0100 Subject: [PATCH 06/10] update macOS releases for `core:sys/info` and `odin report` --- core/sys/info/platform_darwin.odin | 5 +++++ src/bug_report.cpp | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/core/sys/info/platform_darwin.odin b/core/sys/info/platform_darwin.odin index 4316b2ade..e8006d175 100644 --- a/core/sys/info/platform_darwin.odin +++ b/core/sys/info/platform_darwin.odin @@ -517,9 +517,14 @@ macos_release_map: map[string]Darwin_To_Release = { "23A344" = {{23, 0, 0}, "macOS", {"Sonoma", {14, 0, 0}}}, "23B74" = {{23, 1, 0}, "macOS", {"Sonoma", {14, 1, 0}}}, "23B81" = {{23, 1, 0}, "macOS", {"Sonoma", {14, 1, 1}}}, + "23B2082" = {{23, 1, 0}, "macOS", {"Sonoma", {14, 1, 1}}}, "23B92" = {{23, 1, 0}, "macOS", {"Sonoma", {14, 1, 2}}}, + "23B2091" = {{23, 1, 0}, "macOS", {"Sonoma", {14, 1, 2}}}, "23C64" = {{23, 2, 0}, "macOS", {"Sonoma", {14, 2, 0}}}, "23C71" = {{23, 2, 0}, "macOS", {"Sonoma", {14, 2, 1}}}, + "23D56" = {{23, 3, 0}, "macOS", {"Sonoma", {14, 3, 0}}}, + "23D60" = {{23, 3, 0}, "macOS", {"Sonoma", {14, 3, 1}}}, + "23E214" = {{23, 4, 0}, "macOS", {"Sonoma", {14, 4, 0}}}, } @(private) diff --git a/src/bug_report.cpp b/src/bug_report.cpp index b58d14bbf..7b4999943 100644 --- a/src/bug_report.cpp +++ b/src/bug_report.cpp @@ -880,9 +880,14 @@ gb_internal void report_os_info() { {"23A344", {23, 0, 0}, "macOS", {"Sonoma", {14, 0, 0}}}, {"23B74", {23, 1, 0}, "macOS", {"Sonoma", {14, 1, 0}}}, {"23B81", {23, 1, 0}, "macOS", {"Sonoma", {14, 1, 1}}}, + {"23B2082", {23, 1, 0}, "macOS", {"Sonoma", {14, 1, 1}}}, {"23B92", {23, 1, 0}, "macOS", {"Sonoma", {14, 1, 2}}}, + {"23B2091", {23, 1, 0}, "macOS", {"Sonoma", {14, 1, 2}}}, {"23C64", {23, 2, 0}, "macOS", {"Sonoma", {14, 2, 0}}}, {"23C71", {23, 2, 0}, "macOS", {"Sonoma", {14, 2, 1}}}, + {"23D56", {23, 3, 0}, "macOS", {"Sonoma", {14, 3, 0}}}, + {"23D60", {23, 3, 0}, "macOS", {"Sonoma", {14, 3, 1}}}, + {"23E214", {23, 4, 0}, "macOS", {"Sonoma", {14, 4, 0}}}, }; From 3bff922b6f066966c550cf6298ab3f2a564f6c5e Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 20 Mar 2024 10:23:57 +0000 Subject: [PATCH 07/10] `m[i]` on `#row_major` matrices will reduce the i-th row-vector --- src/llvm_backend_expr.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/llvm_backend_expr.cpp b/src/llvm_backend_expr.cpp index 6eb8fdcc6..06bf9fe1e 100644 --- a/src/llvm_backend_expr.cpp +++ b/src/llvm_backend_expr.cpp @@ -3990,7 +3990,13 @@ gb_internal lbAddr lb_build_addr_index_expr(lbProcedure *p, Ast *expr) { } lbValue index = lb_build_expr(p, ie->index); index = lb_emit_conv(p, index, t_int); - lbValue elem = lb_emit_matrix_ep(p, matrix, lb_const_int(p->module, t_int, 0), index); + + lbValue elem = {}; + if (t->Matrix.is_row_major) { + elem = lb_emit_matrix_ep(p, matrix, index, lb_const_int(p->module, t_int, 0)); + } else { + elem = lb_emit_matrix_ep(p, matrix, lb_const_int(p->module, t_int, 0), index); + } elem = lb_emit_conv(p, elem, alloc_type_pointer(type_of_expr(expr))); auto index_tv = type_and_value_of_expr(ie->index); From 553a244fec29f4bf2b32f9813ceb578fa46909fd Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 20 Mar 2024 10:24:39 +0000 Subject: [PATCH 08/10] Fix bounds checking --- src/llvm_backend_expr.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/llvm_backend_expr.cpp b/src/llvm_backend_expr.cpp index 06bf9fe1e..12949f0ab 100644 --- a/src/llvm_backend_expr.cpp +++ b/src/llvm_backend_expr.cpp @@ -3991,17 +3991,20 @@ gb_internal lbAddr lb_build_addr_index_expr(lbProcedure *p, Ast *expr) { lbValue index = lb_build_expr(p, ie->index); index = lb_emit_conv(p, index, t_int); + isize bounds_len = 0; lbValue elem = {}; if (t->Matrix.is_row_major) { + bounds_len = t->Matrix.row_count; elem = lb_emit_matrix_ep(p, matrix, index, lb_const_int(p->module, t_int, 0)); } else { + bounds_len = t->Matrix.column_count; elem = lb_emit_matrix_ep(p, matrix, lb_const_int(p->module, t_int, 0), index); } elem = lb_emit_conv(p, elem, alloc_type_pointer(type_of_expr(expr))); auto index_tv = type_and_value_of_expr(ie->index); if (index_tv.mode != Addressing_Constant) { - lbValue len = lb_const_int(p->module, t_int, t->Matrix.column_count); + lbValue len = lb_const_int(p->module, t_int, bounds_len); lb_emit_bounds_check(p, ast_token(ie->index), index, len); } return lb_addr(elem); From e4c502e79b4fba9924aac4ff029889a494d3f1ae Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 20 Mar 2024 11:06:02 +0000 Subject: [PATCH 09/10] Add `offset` (in bytes) field to `-json-errors` --- src/error.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/error.cpp b/src/error.cpp index 8d550e969..b96719420 100644 --- a/src/error.cpp +++ b/src/error.cpp @@ -670,6 +670,7 @@ gb_internal void print_all_errors(void) { escape_char(f, file.text[k]); } gb_fprintf(f, "\",\n"); + gb_fprintf(f, "\t\t\t\t\"offset\": %d,\n", ev.pos.offset); gb_fprintf(f, "\t\t\t\t\"line\": %d,\n", ev.pos.line); gb_fprintf(f, "\t\t\t\t\"column\": %d,\n", ev.pos.column); i32 end_column = gb_max(ev.end.column, ev.pos.column); From 1514d6496447506f7d8f43168a36147f9007b0d2 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 20 Mar 2024 11:12:43 +0000 Subject: [PATCH 10/10] Update ARM64 ABI return type --- src/llvm_abi.cpp | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/llvm_abi.cpp b/src/llvm_abi.cpp index 857b255f3..24e86fa64 100644 --- a/src/llvm_abi.cpp +++ b/src/llvm_abi.cpp @@ -1145,14 +1145,9 @@ namespace lbAbiArm64 { i64 size = lb_sizeof(return_type); if (size <= 16) { LLVMTypeRef cast_type = nullptr; - if (size <= 1) { - cast_type = LLVMInt8TypeInContext(c); - } else if (size <= 2) { - cast_type = LLVMInt16TypeInContext(c); - } else if (size <= 4) { - cast_type = LLVMInt32TypeInContext(c); - } else if (size <= 8) { - cast_type = LLVMInt64TypeInContext(c); + + if (size <= 8) { + cast_type = LLVMIntTypeInContext(c, cast(unsigned)(size*8)); } else { unsigned count = cast(unsigned)((size+7)/8); cast_type = llvm_array_type(LLVMInt64TypeInContext(c), count);