Merge remote-tracking branch 'offical/master'

This commit is contained in:
ed
2024-03-20 09:09:02 -04:00
22 changed files with 202 additions and 68 deletions
+4
View File
@@ -177,6 +177,10 @@ Type_Info_Matrix :: struct {
row_count: int, row_count: int,
column_count: int, column_count: int,
// Total element count = column_count * elem_stride // 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 { Type_Info_Soa_Pointer :: struct {
elem: ^Type_Info, elem: ^Type_Info,
+10 -2
View File
@@ -2396,7 +2396,11 @@ fmt_matrix :: proc(fi: ^Info, v: any, verb: rune, info: runtime.Type_Info_Matrix
for col in 0..<info.column_count { for col in 0..<info.column_count {
if col > 0 { io.write_string(fi.writer, ", ", &fi.n) } if col > 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) data := uintptr(v.data) + uintptr(offset)
fmt_arg(fi, any{rawptr(data), info.elem.id}, verb) 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..<info.column_count { for col in 0..<info.column_count {
if col > 0 { io.write_string(fi.writer, ", ", &fi.n) } if col > 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) data := uintptr(v.data) + uintptr(offset)
fmt_arg(fi, any{rawptr(data), info.elem.id}, verb) fmt_arg(fi, any{rawptr(data), info.elem.id}, verb)
+1
View File
@@ -2947,6 +2947,7 @@ parse_literal_value :: proc(p: ^Parser, type: ^ast.Expr) -> ^ast.Comp_Lit {
} }
p.expr_level -= 1 p.expr_level -= 1
skip_possible_newline(p)
close := expect_token_after(p, .Close_Brace, "compound literal") close := expect_token_after(p, .Close_Brace, "compound literal")
pos := type.pos if type != nil else open.pos pos := type.pos if type != nil else open.pos
+4
View File
@@ -173,6 +173,7 @@ are_types_identical :: proc(a, b: ^Type_Info) -> bool {
y := b.variant.(Type_Info_Matrix) or_return y := b.variant.(Type_Info_Matrix) or_return
if x.row_count != y.row_count { return false } if x.row_count != y.row_count { return false }
if x.column_count != y.column_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) return are_types_identical(x.elem, y.elem)
case Type_Info_Bit_Field: 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 write_type(w, info.pointer, &n) or_return
case Type_Info_Matrix: 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_string(w, "matrix[", &n) or_return
io.write_i64(w, i64(info.row_count), 10, &n) or_return io.write_i64(w, i64(info.row_count), 10, &n) or_return
io.write_string(w, ", ", &n) or_return io.write_string(w, ", ", &n) or_return
+5
View File
@@ -517,9 +517,14 @@ macos_release_map: map[string]Darwin_To_Release = {
"23A344" = {{23, 0, 0}, "macOS", {"Sonoma", {14, 0, 0}}}, "23A344" = {{23, 0, 0}, "macOS", {"Sonoma", {14, 0, 0}}},
"23B74" = {{23, 1, 0}, "macOS", {"Sonoma", {14, 1, 0}}}, "23B74" = {{23, 1, 0}, "macOS", {"Sonoma", {14, 1, 0}}},
"23B81" = {{23, 1, 0}, "macOS", {"Sonoma", {14, 1, 1}}}, "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}}}, "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}}}, "23C64" = {{23, 2, 0}, "macOS", {"Sonoma", {14, 2, 0}}},
"23C71" = {{23, 2, 0}, "macOS", {"Sonoma", {14, 2, 1}}}, "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) @(private)
+5
View File
@@ -880,9 +880,14 @@ gb_internal void report_os_info() {
{"23A344", {23, 0, 0}, "macOS", {"Sonoma", {14, 0, 0}}}, {"23A344", {23, 0, 0}, "macOS", {"Sonoma", {14, 0, 0}}},
{"23B74", {23, 1, 0}, "macOS", {"Sonoma", {14, 1, 0}}}, {"23B74", {23, 1, 0}, "macOS", {"Sonoma", {14, 1, 0}}},
{"23B81", {23, 1, 0}, "macOS", {"Sonoma", {14, 1, 1}}}, {"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}}}, {"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}}}, {"23C64", {23, 2, 0}, "macOS", {"Sonoma", {14, 2, 0}}},
{"23C71", {23, 2, 0}, "macOS", {"Sonoma", {14, 2, 1}}}, {"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}}},
}; };
+25 -2
View File
@@ -1191,13 +1191,24 @@ gb_internal String path_to_fullpath(gbAllocator a, String s, bool *ok_) {
char *p; char *p;
mutex_lock(&fullpath_mutex); mutex_lock(&fullpath_mutex);
p = realpath(cast(char *)s.text, 0); p = realpath(cast(char *)s.text, 0);
defer (free(p));
mutex_unlock(&fullpath_mutex); mutex_unlock(&fullpath_mutex);
if(p == nullptr) { if(p == nullptr) {
if (ok_) *ok_ = false; 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; if (ok_) *ok_ = true;
return make_string_c(p); return copy_string(a, make_string_c(p));
} }
#else #else
#error Implement system #error Implement system
@@ -1947,6 +1958,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) { if (bc->target_features_string.len != 0) {
enable_target_feature({}, bc->target_features_string); enable_target_feature({}, bc->target_features_string);
+2 -2
View File
@@ -3488,7 +3488,7 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As
} }
} else { } else {
GB_ASSERT(t->kind == Type_Matrix); 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); operand->type = check_matrix_type_hint(operand->type, type_hint);
break; break;
@@ -3556,7 +3556,7 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As
} }
operand->mode = Addressing_Value; 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); operand->type = check_matrix_type_hint(operand->type, type_hint);
break; break;
} }
+18 -5
View File
@@ -3397,6 +3397,13 @@ gb_internal Type *check_matrix_type_hint(Type *matrix, Type *type_hint) {
Type *th = base_type(type_hint); Type *th = base_type(type_hint);
if (are_types_identical(th, xt)) { if (are_types_identical(th, xt)) {
return type_hint; 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) { } else if (xt->kind == Type_Matrix && th->kind == Type_Array) {
if (!are_types_identical(xt->Matrix.elem, th->Array.elem)) { if (!are_types_identical(xt->Matrix.elem, th->Array.elem)) {
// ignore // ignore
@@ -3431,6 +3438,11 @@ gb_internal void check_binary_matrix(CheckerContext *c, Token const &op, Operand
if (xt->Matrix.column_count != yt->Matrix.row_count) { if (xt->Matrix.column_count != yt->Matrix.row_count) {
goto matrix_error; goto matrix_error;
} }
if (xt->Matrix.is_row_major != yt->Matrix.is_row_major) {
goto matrix_error;
}
x->mode = Addressing_Value; x->mode = Addressing_Value;
if (are_types_identical(xt, yt)) { if (are_types_identical(xt, yt)) {
if (!is_type_named(x->type) && is_type_named(y->type)) { if (!is_type_named(x->type) && is_type_named(y->type)) {
@@ -3438,7 +3450,8 @@ gb_internal void check_binary_matrix(CheckerContext *c, Token const &op, Operand
x->type = y->type; x->type = y->type;
} }
} else { } 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; goto matrix_success;
} else if (yt->kind == Type_Array) { } else if (yt->kind == Type_Array) {
@@ -3452,10 +3465,10 @@ gb_internal void check_binary_matrix(CheckerContext *c, Token const &op, Operand
// Treat arrays as column vectors // Treat arrays as column vectors
x->mode = Addressing_Value; 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; x->type = y->type;
} else { } 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; goto matrix_success;
} }
@@ -3483,10 +3496,10 @@ gb_internal void check_binary_matrix(CheckerContext *c, Token const &op, Operand
// Treat arrays as row vectors // Treat arrays as row vectors
x->mode = Addressing_Value; 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; x->type = x->type;
} else { } 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; goto matrix_success;
} else if (are_types_identical(yt->Matrix.elem, xt)) { } else if (are_types_identical(yt->Matrix.elem, xt)) {
+1 -1
View File
@@ -2658,7 +2658,7 @@ gb_internal void check_matrix_type(CheckerContext *ctx, Type **type, Ast *node)
} }
type_assign:; 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; return;
} }
+1
View File
@@ -670,6 +670,7 @@ gb_internal void print_all_errors(void) {
escape_char(f, file.text[k]); escape_char(f, file.text[k]);
} }
gb_fprintf(f, "\",\n"); 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\"line\": %d,\n", ev.pos.line);
gb_fprintf(f, "\t\t\t\t\"column\": %d,\n", ev.pos.column); gb_fprintf(f, "\t\t\t\t\"column\": %d,\n", ev.pos.column);
i32 end_column = gb_max(ev.end.column, ev.pos.column); i32 end_column = gb_max(ev.end.column, ev.pos.column);
+11 -3
View File
@@ -376,6 +376,10 @@ gb_internal i32 linker_stage(LinkerData *gen) {
LIT(obj_file), LIT(obj_file),
LIT(build_context.extra_assembler_flags) 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); array_add(&gen->output_object_paths, obj_file);
} else { } else {
@@ -383,9 +387,13 @@ gb_internal i32 linker_stage(LinkerData *gen) {
continue; continue;
} }
// NOTE(zangent): Sometimes, you have to use -framework on MacOS. // Do not add libc again, this is added later already, and omitted with
// This allows you to specify '-f' in a #foreign_system_library, // the `-no-crt` flag, not skipping here would cause duplicate library
// without having to implement any new syntax specifically for MacOS. // 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 (build_context.metrics.os == TargetOs_darwin) {
if (string_ends_with(lib, str_lit(".framework"))) { if (string_ends_with(lib, str_lit(".framework"))) {
// framework thingie // framework thingie
+3 -8
View File
@@ -1145,14 +1145,9 @@ namespace lbAbiArm64 {
i64 size = lb_sizeof(return_type); i64 size = lb_sizeof(return_type);
if (size <= 16) { if (size <= 16) {
LLVMTypeRef cast_type = nullptr; LLVMTypeRef cast_type = nullptr;
if (size <= 1) {
cast_type = LLVMInt8TypeInContext(c); if (size <= 8) {
} else if (size <= 2) { cast_type = LLVMIntTypeInContext(c, cast(unsigned)(size*8));
cast_type = LLVMInt16TypeInContext(c);
} else if (size <= 4) {
cast_type = LLVMInt32TypeInContext(c);
} else if (size <= 8) {
cast_type = LLVMInt64TypeInContext(c);
} else { } else {
unsigned count = cast(unsigned)((size+7)/8); unsigned count = cast(unsigned)((size+7)/8);
cast_type = llvm_array_type(LLVMInt64TypeInContext(c), count); cast_type = llvm_array_type(LLVMInt64TypeInContext(c), count);
+2 -2
View File
@@ -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); 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); LLVMValueRef *values = gb_alloc_array(temporary_allocator(), LLVMValueRef, cast(isize)total_count);
for_array(i, cl->elems) { for_array(i, cl->elems) {
TypeAndValue tav = cl->elems[i]->tav; TypeAndValue tav = cl->elems[i]->tav;
GB_ASSERT(tav.mode != Addressing_Invalid); 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; values[offset] = lb_const_value(m, elem_type, tav.value, allow_local).value;
} }
for (isize i = 0; i < total_count; i++) { for (isize i = 0; i < total_count; i++) {
+40 -12
View File
@@ -684,12 +684,6 @@ gb_internal lbValue lb_emit_matrix_flatten(lbProcedure *p, lbValue m, Type *type
Type *mt = base_type(m.type); Type *mt = base_type(m.type);
GB_ASSERT(mt->kind == Type_Matrix); 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); lbAddr res = lb_add_local_generated(p, type, true);
i64 row_count = mt->Matrix.row_count; 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(is_type_matrix(yt));
GB_ASSERT(xt->Matrix.column_count == yt->Matrix.row_count); GB_ASSERT(xt->Matrix.column_count == yt->Matrix.row_count);
GB_ASSERT(are_types_identical(xt->Matrix.elem, yt->Matrix.elem)); 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; 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 inner = cast(unsigned)xt->Matrix.column_count;
unsigned outer_columns = cast(unsigned)yt->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 x_stride = cast(unsigned)matrix_type_stride_in_elems(xt);
unsigned y_stride = cast(unsigned)matrix_type_stride_in_elems(yt); 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); return lb_addr_load(p, res);
} }
{ if (!xt->Matrix.is_row_major) {
lbAddr res = lb_add_local_generated(p, type, true); lbAddr res = lb_add_local_generated(p, type, true);
auto inners = slice_make<lbValue[2]>(permanent_allocator(), inner); auto inners = slice_make<lbValue[2]>(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<lbValue[2]>(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); 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; 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 stride = cast(unsigned)matrix_type_stride_in_elems(mt);
unsigned row_count = cast(unsigned)mt->Matrix.row_count; 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; 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 stride = cast(unsigned)matrix_type_stride_in_elems(mt);
unsigned row_count = cast(unsigned)mt->Matrix.row_count; unsigned row_count = cast(unsigned)mt->Matrix.row_count;
@@ -3971,12 +3990,21 @@ gb_internal lbAddr lb_build_addr_index_expr(lbProcedure *p, Ast *expr) {
} }
lbValue index = lb_build_expr(p, ie->index); lbValue index = lb_build_expr(p, ie->index);
index = lb_emit_conv(p, index, t_int); 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);
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))); elem = lb_emit_conv(p, elem, alloc_type_pointer(type_of_expr(expr)));
auto index_tv = type_and_value_of_expr(ie->index); auto index_tv = type_and_value_of_expr(ie->index);
if (index_tv.mode != Addressing_Constant) { 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); lb_emit_bounds_check(p, ast_token(ie->index), index, len);
} }
return lb_addr(elem); return lb_addr(elem);
+2 -1
View File
@@ -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; tag_type = t_type_info_matrix;
i64 ez = type_size_of(t->Matrix.elem); i64 ez = type_size_of(t->Matrix.elem);
LLVMValueRef vals[5] = { LLVMValueRef vals[6] = {
get_type_info_ptr(m, t->Matrix.elem), get_type_info_ptr(m, t->Matrix.elem),
lb_const_int(m, t_int, ez).value, 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, 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.row_count).value,
lb_const_int(m, t_int, t->Matrix.column_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)); variant_value = llvm_const_named_struct(m, tag_type, vals, gb_count_of(vals));
+15 -7
View File
@@ -1464,13 +1464,15 @@ gb_internal lbValue lb_emit_matrix_epi(lbProcedure *p, lbValue s, isize row, isi
Type *t = s.type; Type *t = s.type;
GB_ASSERT(is_type_pointer(t)); GB_ASSERT(is_type_pointer(t));
Type *mt = base_type(type_deref(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)); GB_ASSERT_MSG(is_type_matrix(mt), "%s", type_to_string(mt));
@@ -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); row = lb_emit_conv(p, row, t_int);
column = lb_emit_conv(p, column, 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] = { LLVMValueRef indices[2] = {
LLVMConstInt(lb_type(p->module, t_int), 0, false), LLVMConstInt(lb_type(p->module, t_int), 0, false),
+13
View File
@@ -2329,6 +2329,19 @@ gb_internal Ast *parse_operand(AstFile *f, bool lhs) {
break; break;
} }
return original_type; 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") { } else if (name.string == "partial") {
Ast *tag = ast_basic_directive(f, token, name); Ast *tag = ast_basic_directive(f, token, name);
Ast *original_expr = parse_expr(f, lhs); Ast *original_expr = parse_expr(f, lhs);
+1
View File
@@ -772,6 +772,7 @@ AST_KIND(_TypeBegin, "", bool) \
Ast *row_count; \ Ast *row_count; \
Ast *column_count; \ Ast *column_count; \
Ast *elem; \ Ast *elem; \
bool is_row_major; \
}) \ }) \
AST_KIND(_TypeEnd, "", bool) AST_KIND(_TypeEnd, "", bool)
+14 -3
View File
@@ -281,6 +281,7 @@ struct TypeProc {
Type *generic_row_count; \ Type *generic_row_count; \
Type *generic_column_count; \ Type *generic_column_count; \
i64 stride_in_bytes; \ i64 stride_in_bytes; \
bool is_row_major; \
}) \ }) \
TYPE_KIND(BitField, struct { \ TYPE_KIND(BitField, struct { \
Scope * scope; \ Scope * scope; \
@@ -1002,7 +1003,7 @@ gb_internal Type *alloc_type_array(Type *elem, i64 count, Type *generic_count =
return t; 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, Type *generic_column_count, bool is_row_major) {
if (generic_row_count != nullptr || generic_column_count != nullptr) { if (generic_row_count != nullptr || generic_column_count != nullptr) {
Type *t = alloc_type(Type_Matrix); Type *t = alloc_type(Type_Matrix);
t->Matrix.elem = elem; 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.column_count = column_count;
t->Matrix.generic_row_count = generic_row_count; t->Matrix.generic_row_count = generic_row_count;
t->Matrix.generic_column_count = generic_column_count; t->Matrix.generic_column_count = generic_column_count;
t->Matrix.is_row_major = is_row_major;
return t; return t;
} }
Type *t = alloc_type(Type_Matrix); Type *t = alloc_type(Type_Matrix);
t->Matrix.elem = elem; t->Matrix.elem = elem;
t->Matrix.row_count = row_count; t->Matrix.row_count = row_count;
t->Matrix.column_count = column_count; t->Matrix.column_count = column_count;
t->Matrix.is_row_major = is_row_major;
return t; return t;
} }
@@ -1512,8 +1515,12 @@ 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 <= row_index && row_index < t->Matrix.row_count);
GB_ASSERT(0 <= column_index && column_index < t->Matrix.column_count); GB_ASSERT(0 <= column_index && column_index < t->Matrix.column_count);
i64 stride_elems = matrix_type_stride_in_elems(t); i64 stride_elems = matrix_type_stride_in_elems(t);
// NOTE(bill): Column-major layout internally if (t->Matrix.is_row_major) {
return row_index + stride_elems*column_index; 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) { gb_internal i64 matrix_row_major_index_to_offset(Type *t, i64 index) {
@@ -2690,6 +2697,7 @@ gb_internal bool are_types_identical_internal(Type *x, Type *y, bool check_tuple
case Type_Matrix: case Type_Matrix:
return x->Matrix.row_count == y->Matrix.row_count && return x->Matrix.row_count == y->Matrix.row_count &&
x->Matrix.column_count == y->Matrix.column_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); are_types_identical(x->Matrix.elem, y->Matrix.elem);
case Type_DynamicArray: case Type_DynamicArray:
@@ -4735,6 +4743,9 @@ gb_internal gbString write_type_to_string(gbString str, Type *type, bool shortha
break; break;
case Type_Matrix: 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 = 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); str = write_type_to_string(str, type->Matrix.elem);
break; break;
+6 -6
View File
@@ -213,17 +213,17 @@ MAGENTA :: Color{ 255, 0, 255, 255 } // Magenta
RAYWHITE :: Color{ 245, 245, 245, 255 } // My own White (raylib logo) RAYWHITE :: Color{ 245, 245, 245, 255 } // My own White (raylib logo)
// Vector2 type // Vector2 type
Vector2 :: linalg.Vector2f32 Vector2 :: [2]f32
// Vector3 type // Vector3 type
Vector3 :: linalg.Vector3f32 Vector3 :: [3]f32
// Vector4 type // Vector4 type
Vector4 :: linalg.Vector4f32 Vector4 :: [4]f32
// Quaternion type // Quaternion type
Quaternion :: linalg.Quaternionf32 Quaternion :: quaternion128
// Matrix type (OpenGL style 4x4 - right handed, stored column major) // Matrix type (right handed, stored row major)
Matrix :: linalg.Matrix4x4f32 Matrix :: #row_major matrix[4, 4]f32
// Color, 4 components, R8G8B8A8 (32bit) // Color, 4 components, R8G8B8A8 (32bit)
+18 -13
View File
@@ -590,74 +590,79 @@ MatrixMultiply :: proc "c" (left, right: Matrix) -> Matrix {
// Get translation matrix // Get translation matrix
@(require_results) @(require_results)
MatrixTranslate :: proc "c" (x, y, z: f32) -> Matrix { 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 // Create rotation matrix from axis and angle
// NOTE: Angle should be provided in radians // NOTE: Angle should be provided in radians
@(require_results) @(require_results)
MatrixRotate :: proc "c" (axis: Vector3, angle: f32) -> Matrix { 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 // Get x-rotation matrix
// NOTE: Angle must be provided in radians // NOTE: Angle must be provided in radians
@(require_results) @(require_results)
MatrixRotateX :: proc "c" (angle: f32) -> Matrix { 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 // Get y-rotation matrix
// NOTE: Angle must be provided in radians // NOTE: Angle must be provided in radians
@(require_results) @(require_results)
MatrixRotateY :: proc "c" (angle: f32) -> Matrix { 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 // Get z-rotation matrix
// NOTE: Angle must be provided in radians // NOTE: Angle must be provided in radians
@(require_results) @(require_results)
MatrixRotateZ :: proc "c" (angle: f32) -> Matrix { 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 // Get xyz-rotation matrix
// NOTE: Angle must be provided in radians // NOTE: Angle must be provided in radians
@(require_results) @(require_results)
MatrixRotateXYZ :: proc "c" (angle: Vector3) -> Matrix { 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 // Get zyx-rotation matrix
// NOTE: Angle must be provided in radians // NOTE: Angle must be provided in radians
@(require_results) @(require_results)
MatrixRotateZYX :: proc "c" (angle: Vector3) -> Matrix { 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 // Get scaling matrix
@(require_results) @(require_results)
MatrixScale :: proc "c" (x, y, z: f32) -> Matrix { 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 // Get orthographic projection matrix
@(require_results) @(require_results)
MatrixOrtho :: proc "c" (left, right, bottom, top, near, far: f32) -> Matrix { 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 // Get perspective projection matrix
// NOTE: Fovy angle must be provided in radians // NOTE: Fovy angle must be provided in radians
@(require_results) @(require_results)
MatrixPerspective :: proc "c" (fovY, aspect, nearPlane, farPlane: f32) -> Matrix { 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) // Get camera look-at matrix (view matrix)
@(require_results) @(require_results)
MatrixLookAt :: proc "c" (eye, target, up: Vector3) -> Matrix { 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 // 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 // Get a quaternion for a given rotation matrix
@(require_results) @(require_results)
QuaternionFromMatrix :: proc "c" (mat: Matrix) -> Quaternion { 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 // Get a matrix for a given quaternion
@(require_results) @(require_results)
QuaternionToMatrix :: proc "c" (q: Quaternion) -> Matrix { 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 // Get rotation quaternion for an angle and axis NOTE: Angle must be provided in radians
@(require_results) @(require_results)