瀏覽代碼

Merge branch 'master' into freestanding_amd64

gingerBill 3 年之前
父節點
當前提交
4b9324ff76

+ 336 - 0
core/crypto/siphash/siphash.odin

@@ -0,0 +1,336 @@
+package siphash
+
+/*
+    Copyright 2022 zhibog
+    Made available under the BSD-3 license.
+
+    List of contributors:
+        zhibog:  Initial implementation.
+
+    Implementation of the SipHash hashing algorithm, as defined at <https://github.com/veorq/SipHash> and <https://www.aumasson.jp/siphash/siphash.pdf>
+
+    Use the specific procedures for a certain setup. The generic procdedures will default to Siphash 2-4
+*/
+
+import "core:crypto"
+import "core:crypto/util"
+import "core:mem"
+
+/*
+    High level API
+*/
+
+KEY_SIZE    :: 16
+DIGEST_SIZE :: 8
+
+// sum_string_1_3 will hash the given message with the key and return
+// the computed hash as a u64
+sum_string_1_3 :: proc(msg, key: string) -> u64 {
+    return sum_bytes_1_3(transmute([]byte)(msg), transmute([]byte)(key))
+}
+
+// sum_bytes_1_3 will hash the given message with the key and return
+// the computed hash as a u64
+sum_bytes_1_3 :: proc (msg, key: []byte) -> u64 {
+    ctx: Context
+    hash: u64
+    init(&ctx, key, 1, 3)
+    update(&ctx, msg)
+    final(&ctx, &hash)
+    return hash
+}
+
+// sum_string_to_buffer_1_3 will hash the given message with the key and write
+// the computed hash into the provided destination buffer
+sum_string_to_buffer_1_3 :: proc(msg, key: string, dst: []byte) {
+    sum_bytes_to_buffer_1_3(transmute([]byte)(msg), transmute([]byte)(key), dst)
+}
+
+// sum_bytes_to_buffer_1_3 will hash the given message with the key and write
+// the computed hash into the provided destination buffer
+sum_bytes_to_buffer_1_3 :: proc(msg, key, dst: []byte) {
+    assert(len(dst) >= DIGEST_SIZE, "crypto/siphash: Destination buffer needs to be at least of size 8")
+    hash  := sum_bytes_1_3(msg, key)
+    _collect_output(dst[:], hash)
+}
+
+sum_1_3 :: proc {
+    sum_string_1_3,
+    sum_bytes_1_3,
+    sum_string_to_buffer_1_3,
+    sum_bytes_to_buffer_1_3,
+}
+
+// verify_u64_1_3 will check if the supplied tag matches with the output you 
+// will get from the provided message and key
+verify_u64_1_3 :: proc (tag: u64 msg, key: []byte) -> bool {
+    return sum_bytes_1_3(msg, key) == tag
+}
+
+// verify_bytes will check if the supplied tag matches with the output you 
+// will get from the provided message and key
+verify_bytes_1_3 :: proc (tag, msg, key: []byte) -> bool {
+    derived_tag: [8]byte
+    sum_bytes_to_buffer_1_3(msg, key, derived_tag[:])
+    return crypto.compare_constant_time(derived_tag[:], tag) == 1
+}
+
+verify_1_3 :: proc {
+    verify_bytes_1_3,
+    verify_u64_1_3,
+}
+
+// sum_string_2_4 will hash the given message with the key and return
+// the computed hash as a u64
+sum_string_2_4 :: proc(msg, key: string) -> u64 {
+    return sum_bytes_2_4(transmute([]byte)(msg), transmute([]byte)(key))
+}
+
+// sum_bytes_2_4 will hash the given message with the key and return
+// the computed hash as a u64
+sum_bytes_2_4 :: proc (msg, key: []byte) -> u64 {
+    ctx: Context
+    hash: u64
+    init(&ctx, key, 2, 4)
+    update(&ctx, msg)
+    final(&ctx, &hash)
+    return hash
+}
+
+// sum_string_to_buffer_2_4 will hash the given message with the key and write
+// the computed hash into the provided destination buffer
+sum_string_to_buffer_2_4 :: proc(msg, key: string, dst: []byte) {
+    sum_bytes_to_buffer_2_4(transmute([]byte)(msg), transmute([]byte)(key), dst)
+}
+
+// sum_bytes_to_buffer_2_4 will hash the given message with the key and write
+// the computed hash into the provided destination buffer
+sum_bytes_to_buffer_2_4 :: proc(msg, key, dst: []byte) {
+    assert(len(dst) >= DIGEST_SIZE, "crypto/siphash: Destination buffer needs to be at least of size 8")
+    hash  := sum_bytes_2_4(msg, key)
+    _collect_output(dst[:], hash)
+}
+
+sum_2_4 :: proc {
+    sum_string_2_4,
+    sum_bytes_2_4,
+    sum_string_to_buffer_2_4,
+    sum_bytes_to_buffer_2_4,
+}
+
+sum_string           :: sum_string_2_4
+sum_bytes            :: sum_bytes_2_4
+sum_string_to_buffer :: sum_string_to_buffer_2_4
+sum_bytes_to_buffer  :: sum_bytes_to_buffer_2_4
+sum :: proc {
+    sum_string,
+    sum_bytes,
+    sum_string_to_buffer,
+    sum_bytes_to_buffer,
+}
+
+// verify_u64_2_4 will check if the supplied tag matches with the output you 
+// will get from the provided message and key
+verify_u64_2_4 :: proc (tag: u64 msg, key: []byte) -> bool {
+    return sum_bytes_2_4(msg, key) == tag
+}
+
+// verify_bytes will check if the supplied tag matches with the output you 
+// will get from the provided message and key
+verify_bytes_2_4 :: proc (tag, msg, key: []byte) -> bool {
+    derived_tag: [8]byte
+    sum_bytes_to_buffer_2_4(msg, key, derived_tag[:])
+    return crypto.compare_constant_time(derived_tag[:], tag) == 1
+}
+
+verify_2_4 :: proc {
+    verify_bytes_2_4,
+    verify_u64_2_4,
+}
+
+verify_bytes :: verify_bytes_2_4
+verify_u64   :: verify_u64_2_4
+verify :: proc {
+    verify_bytes,
+    verify_u64,
+}
+
+// sum_string_4_8 will hash the given message with the key and return
+// the computed hash as a u64
+sum_string_4_8 :: proc(msg, key: string) -> u64 {
+    return sum_bytes_4_8(transmute([]byte)(msg), transmute([]byte)(key))
+}
+
+// sum_bytes_4_8 will hash the given message with the key and return
+// the computed hash as a u64
+sum_bytes_4_8 :: proc (msg, key: []byte) -> u64 {
+    ctx: Context
+    hash: u64
+    init(&ctx, key, 4, 8)
+    update(&ctx, msg)
+    final(&ctx, &hash)
+    return hash
+}
+
+// sum_string_to_buffer_4_8 will hash the given message with the key and write
+// the computed hash into the provided destination buffer
+sum_string_to_buffer_4_8 :: proc(msg, key: string, dst: []byte) {
+    sum_bytes_to_buffer_4_8(transmute([]byte)(msg), transmute([]byte)(key), dst)
+}
+
+// sum_bytes_to_buffer_4_8 will hash the given message with the key and write
+// the computed hash into the provided destination buffer
+sum_bytes_to_buffer_4_8 :: proc(msg, key, dst: []byte) {
+    assert(len(dst) >= DIGEST_SIZE, "crypto/siphash: Destination buffer needs to be at least of size 8")
+    hash  := sum_bytes_4_8(msg, key)
+    _collect_output(dst[:], hash)
+}
+
+sum_4_8 :: proc {
+    sum_string_4_8,
+    sum_bytes_4_8,
+    sum_string_to_buffer_4_8,
+    sum_bytes_to_buffer_4_8,
+}
+
+// verify_u64_4_8 will check if the supplied tag matches with the output you 
+// will get from the provided message and key
+verify_u64_4_8 :: proc (tag: u64 msg, key: []byte) -> bool {
+    return sum_bytes_4_8(msg, key) == tag
+}
+
+// verify_bytes will check if the supplied tag matches with the output you 
+// will get from the provided message and key
+verify_bytes_4_8 :: proc (tag, msg, key: []byte) -> bool {
+    derived_tag: [8]byte
+    sum_bytes_to_buffer_4_8(msg, key, derived_tag[:])
+    return crypto.compare_constant_time(derived_tag[:], tag) == 1
+}
+
+verify_4_8 :: proc {
+    verify_bytes_4_8,
+    verify_u64_4_8,
+}
+
+/*
+    Low level API
+*/
+
+init :: proc(ctx: ^Context, key: []byte, c_rounds, d_rounds: int) {
+    assert(len(key) == KEY_SIZE, "crypto/siphash: Invalid key size, want 16")
+    ctx.c_rounds = c_rounds
+    ctx.d_rounds = d_rounds
+    is_valid_setting := (ctx.c_rounds == 1 && ctx.d_rounds == 3) ||
+                        (ctx.c_rounds == 2 && ctx.d_rounds == 4) ||
+                        (ctx.c_rounds == 4 && ctx.d_rounds == 8)
+    assert(is_valid_setting, "crypto/siphash: Incorrect rounds set up. Valid pairs are (1,3), (2,4) and (4,8)")
+    ctx.k0 = util.U64_LE(key[:8])
+    ctx.k1 = util.U64_LE(key[8:])
+    ctx.v0 = 0x736f6d6570736575 ~ ctx.k0
+    ctx.v1 = 0x646f72616e646f6d ~ ctx.k1
+    ctx.v2 = 0x6c7967656e657261 ~ ctx.k0
+    ctx.v3 = 0x7465646279746573 ~ ctx.k1
+    ctx.is_initialized = true
+}
+
+update :: proc(ctx: ^Context, data: []byte) {
+    assert(ctx.is_initialized, "crypto/siphash: Context is not initalized")
+    ctx.last_block = len(data) / 8 * 8
+    ctx.buf = data
+    i := 0
+    m: u64
+    for i < ctx.last_block {
+        m = u64(ctx.buf[i] & 0xff)
+        i += 1
+
+        for r in u64(1)..<8 {
+            m |= u64(ctx.buf[i] & 0xff) << (r * 8)
+            i += 1
+        }
+
+        ctx.v3 ~= m
+        for _ in 0..<ctx.c_rounds {
+            _compress(ctx)
+        }
+
+        ctx.v0 ~= m
+    }
+}
+
+final :: proc(ctx: ^Context, dst: ^u64) {
+    m: u64
+    for i := len(ctx.buf) - 1; i >= ctx.last_block; i -= 1 {
+        m <<= 8
+        m |= u64(ctx.buf[i] & 0xff)
+    }
+    m |= u64(len(ctx.buf) << 56)
+
+    ctx.v3 ~= m
+
+    for _ in 0..<ctx.c_rounds {
+        _compress(ctx)
+    }
+
+    ctx.v0 ~= m
+    ctx.v2 ~= 0xff
+
+    for _ in 0..<ctx.d_rounds {
+        _compress(ctx)
+    }
+
+    dst^ = ctx.v0 ~ ctx.v1 ~ ctx.v2 ~ ctx.v3
+
+    reset(ctx)
+}
+
+reset :: proc(ctx: ^Context) {
+    ctx.k0, ctx.k1 = 0, 0
+    ctx.v0, ctx.v1 = 0, 0
+    ctx.v2, ctx.v3 = 0, 0
+    ctx.last_block = 0
+    ctx.c_rounds = 0
+    ctx.d_rounds = 0
+    ctx.is_initialized = false
+}
+
+Context :: struct {
+    v0, v1, v2, v3: u64,    // State values
+    k0, k1:         u64,    // Split key
+    c_rounds:       int,    // Number of message rounds
+    d_rounds:       int,    // Number of finalization rounds
+    buf:            []byte, // Provided data
+    last_block:     int,    // Offset from the last block
+    is_initialized: bool,
+}
+
+_get_byte :: #force_inline proc "contextless" (byte_num: byte, into: u64) -> byte {
+    return byte(into >> (((~byte_num) & (size_of(u64) - 1)) << 3))
+}
+
+_collect_output :: #force_inline proc "contextless" (dst: []byte, hash: u64) {
+    dst[0] = _get_byte(7, hash)
+    dst[1] = _get_byte(6, hash)
+    dst[2] = _get_byte(5, hash)
+    dst[3] = _get_byte(4, hash)
+    dst[4] = _get_byte(3, hash)
+    dst[5] = _get_byte(2, hash)
+    dst[6] = _get_byte(1, hash)
+    dst[7] = _get_byte(0, hash)
+}
+
+_compress :: #force_inline proc "contextless" (ctx: ^Context) {
+    ctx.v0 += ctx.v1
+    ctx.v1  = util.ROTL64(ctx.v1, 13)
+    ctx.v1 ~= ctx.v0
+    ctx.v0  = util.ROTL64(ctx.v0, 32)
+    ctx.v2 += ctx.v3
+    ctx.v3  = util.ROTL64(ctx.v3, 16)
+    ctx.v3 ~= ctx.v2
+    ctx.v0 += ctx.v3
+    ctx.v3  = util.ROTL64(ctx.v3, 21)
+    ctx.v3 ~= ctx.v0
+    ctx.v2 += ctx.v1
+    ctx.v1  = util.ROTL64(ctx.v1, 17)
+    ctx.v1 ~= ctx.v2
+    ctx.v2  = util.ROTL64(ctx.v2, 32)
+}

File diff suppressed because it is too large
+ 168 - 176
core/fmt/fmt.odin


+ 4 - 4
core/reflect/types.odin

@@ -334,11 +334,11 @@ is_relative_slice :: proc(info: ^Type_Info) -> bool {
 
 
 
 
 
 
-write_typeid_builder :: proc(buf: ^strings.Builder, id: typeid) {
-	write_type(buf, type_info_of(id))
+write_typeid_builder :: proc(buf: ^strings.Builder, id: typeid, n_written: ^int = nil) -> (n: int, err: io.Error) {
+	return write_type_writer(strings.to_writer(buf), type_info_of(id))
 }
 }
-write_typeid_writer :: proc(writer: io.Writer, id: typeid) {
-	write_type(writer, type_info_of(id))
+write_typeid_writer :: proc(writer: io.Writer, id: typeid, n_written: ^int = nil) -> (n: int, err: io.Error) {
+	return write_type_writer(writer, type_info_of(id), n_written)
 }
 }
 
 
 write_typeid :: proc{
 write_typeid :: proc{

+ 2 - 2
src/bug_report.cpp

@@ -473,11 +473,11 @@ void print_bug_report_help() {
 
 
 	#elif defined(GB_SYSTEM_LINUX)
 	#elif defined(GB_SYSTEM_LINUX)
 		/*
 		/*
-			Try to parse `/usr/lib/os-release` for `PRETTY_NAME="Ubuntu 20.04.3 LTS`
+			Try to parse `/etc/os-release` for `PRETTY_NAME="Ubuntu 20.04.3 LTS`
 		*/
 		*/
 		gbAllocator a = heap_allocator();
 		gbAllocator a = heap_allocator();
 
 
-		gbFileContents release = gb_file_read_contents(a, 1, "/usr/lib/os-release");
+		gbFileContents release = gb_file_read_contents(a, 1, "/etc/os-release");
 		defer (gb_file_free_contents(&release));
 		defer (gb_file_free_contents(&release));
 
 
 		b32 found = 0;
 		b32 found = 0;

+ 63 - 1
src/check_expr.cpp

@@ -132,6 +132,62 @@ void check_did_you_mean_print(DidYouMeanAnswers *d, char const *prefix = "") {
 	}
 	}
 }
 }
 
 
+void populate_check_did_you_mean_objc_entity(StringSet *set, Entity *e, bool is_type) {
+	if (e->kind != Entity_TypeName) {
+		return;
+	}
+	if (e->TypeName.objc_metadata == nullptr) {
+		return;
+	}
+	TypeNameObjCMetadata *objc_metadata = e->TypeName.objc_metadata;
+	Type *t = base_type(e->type);
+	GB_ASSERT(t->kind == Type_Struct);
+
+	if (is_type) {
+		for_array(i, objc_metadata->type_entries) {
+			String name = objc_metadata->type_entries[i].name;
+			string_set_add(set, name);
+		}
+	} else {
+		for_array(i, objc_metadata->value_entries) {
+			String name = objc_metadata->value_entries[i].name;
+			string_set_add(set, name);
+		}
+	}
+
+	for_array(i, t->Struct.fields) {
+		Entity *f = t->Struct.fields[i];
+		if (f->flags & EntityFlag_Using && f->type != nullptr) {
+			if (f->type->kind == Type_Named && f->type->Named.type_name) {
+				populate_check_did_you_mean_objc_entity(set, f->type->Named.type_name, is_type);
+			}
+		}
+	}
+}
+
+
+void check_did_you_mean_objc_entity(String const &name, Entity *e, bool is_type, char const *prefix = "") {
+	ERROR_BLOCK();
+	GB_ASSERT(e->kind == Entity_TypeName);
+	GB_ASSERT(e->TypeName.objc_metadata != nullptr);
+	auto *objc_metadata = e->TypeName.objc_metadata;
+	mutex_lock(objc_metadata->mutex);
+	defer (mutex_unlock(objc_metadata->mutex));
+
+	StringSet set = {};
+	string_set_init(&set, heap_allocator());
+	defer (string_set_destroy(&set));
+	populate_check_did_you_mean_objc_entity(&set, e, is_type);
+
+
+	DidYouMeanAnswers d = did_you_mean_make(heap_allocator(), set.entries.count, name);
+	defer (did_you_mean_destroy(&d));
+	for_array(i, set.entries) {
+		did_you_mean_append(&d, set.entries[i].value);
+	}
+	check_did_you_mean_print(&d, prefix);
+}
+
 void check_did_you_mean_type(String const &name, Array<Entity *> const &fields, char const *prefix = "") {
 void check_did_you_mean_type(String const &name, Array<Entity *> const &fields, char const *prefix = "") {
 	ERROR_BLOCK();
 	ERROR_BLOCK();
 
 
@@ -144,6 +200,7 @@ void check_did_you_mean_type(String const &name, Array<Entity *> const &fields,
 	check_did_you_mean_print(&d, prefix);
 	check_did_you_mean_print(&d, prefix);
 }
 }
 
 
+
 void check_did_you_mean_type(String const &name, Slice<Entity *> const &fields, char const *prefix = "") {
 void check_did_you_mean_type(String const &name, Slice<Entity *> const &fields, char const *prefix = "") {
 	ERROR_BLOCK();
 	ERROR_BLOCK();
 
 
@@ -4420,7 +4477,12 @@ Entity *check_selector(CheckerContext *c, Operand *operand, Ast *node, Type *typ
 		if (operand->type != nullptr && selector->kind == Ast_Ident) {
 		if (operand->type != nullptr && selector->kind == Ast_Ident) {
 			String const &name = selector->Ident.token.string;
 			String const &name = selector->Ident.token.string;
 			Type *bt = base_type(operand->type);
 			Type *bt = base_type(operand->type);
-			if (bt->kind == Type_Struct) {
+			if (operand->type->kind == Type_Named &&
+			    operand->type->Named.type_name &&
+			    operand->type->Named.type_name->kind == Entity_TypeName &&
+			    operand->type->Named.type_name->TypeName.objc_metadata) {
+				check_did_you_mean_objc_entity(name, operand->type->Named.type_name, operand->mode == Addressing_Type);
+			} else if (bt->kind == Type_Struct) {
 				check_did_you_mean_type(name, bt->Struct.fields);
 				check_did_you_mean_type(name, bt->Struct.fields);
 			} else if (bt->kind == Type_Enum) {
 			} else if (bt->kind == Type_Enum) {
 				check_did_you_mean_type(name, bt->Enum.fields);
 				check_did_you_mean_type(name, bt->Enum.fields);

+ 16 - 5
src/exact_value.cpp

@@ -50,9 +50,9 @@ struct ExactValue {
 	union {
 	union {
 		bool           value_bool;
 		bool           value_bool;
 		String         value_string;
 		String         value_string;
-		BigInt         value_integer; // NOTE(bill): This must be an integer and not a pointer
+		BigInt         value_integer;
 		f64            value_float;
 		f64            value_float;
-		i64            value_pointer;
+		i64            value_pointer; // NOTE(bill): This must be an integer and not a pointer
 		Complex128    *value_complex;
 		Complex128    *value_complex;
 		Quaternion256 *value_quaternion;
 		Quaternion256 *value_quaternion;
 		Ast *          value_compound;
 		Ast *          value_compound;
@@ -630,6 +630,9 @@ void match_exact_values(ExactValue *x, ExactValue *y) {
 	case ExactValue_Bool:
 	case ExactValue_Bool:
 	case ExactValue_String:
 	case ExactValue_String:
 	case ExactValue_Quaternion:
 	case ExactValue_Quaternion:
+	case ExactValue_Pointer:
+	case ExactValue_Procedure:
+	case ExactValue_Typeid:
 		return;
 		return;
 
 
 	case ExactValue_Integer:
 	case ExactValue_Integer:
@@ -671,9 +674,6 @@ void match_exact_values(ExactValue *x, ExactValue *y) {
 			return;
 			return;
 		}
 		}
 		break;
 		break;
-
-	case ExactValue_Procedure:
-		return;
 	}
 	}
 
 
 	compiler_error("match_exact_values: How'd you get here? Invalid ExactValueKind %d", x->kind);
 	compiler_error("match_exact_values: How'd you get here? Invalid ExactValueKind %d", x->kind);
@@ -932,6 +932,17 @@ bool compare_exact_values(TokenKind op, ExactValue x, ExactValue y) {
 		break;
 		break;
 	}
 	}
 
 
+	case ExactValue_Pointer: {
+		switch (op) {
+		case Token_CmpEq: return x.value_pointer == y.value_pointer;
+		case Token_NotEq: return x.value_pointer != y.value_pointer;
+		case Token_Lt:    return x.value_pointer <  y.value_pointer;
+		case Token_LtEq:  return x.value_pointer <= y.value_pointer;
+		case Token_Gt:    return x.value_pointer >  y.value_pointer;
+		case Token_GtEq:  return x.value_pointer >= y.value_pointer;
+		}
+	}
+
 	case ExactValue_Typeid:
 	case ExactValue_Typeid:
 		switch (op) {
 		switch (op) {
 		case Token_CmpEq: return are_types_identical(x.value_typeid, y.value_typeid);
 		case Token_CmpEq: return are_types_identical(x.value_typeid, y.value_typeid);

+ 1 - 0
src/gb/gb.h

@@ -6093,6 +6093,7 @@ gbFileContents gb_file_read_contents(gbAllocator a, b32 zero_terminate, char con
 }
 }
 
 
 void gb_file_free_contents(gbFileContents *fc) {
 void gb_file_free_contents(gbFileContents *fc) {
+    if (fc == NULL || fc->size == 0) return;
 	GB_ASSERT_NOT_NULL(fc->data);
 	GB_ASSERT_NOT_NULL(fc->data);
 	gb_free(fc->allocator, fc->data);
 	gb_free(fc->allocator, fc->data);
 	fc->data = NULL;
 	fc->data = NULL;

+ 46 - 48
src/parser.cpp

@@ -3015,64 +3015,62 @@ i32 token_precedence(AstFile *f, TokenKind t) {
 
 
 Ast *parse_binary_expr(AstFile *f, bool lhs, i32 prec_in) {
 Ast *parse_binary_expr(AstFile *f, bool lhs, i32 prec_in) {
 	Ast *expr = parse_unary_expr(f, lhs);
 	Ast *expr = parse_unary_expr(f, lhs);
-	for (i32 prec = token_precedence(f, f->curr_token.kind); prec >= prec_in; prec--) {
-		for (;;) {
-			Token op = f->curr_token;
-			i32 op_prec = token_precedence(f, op.kind);
-			if (op_prec != prec) {
-				// NOTE(bill): This will also catch operators that are not valid "binary" operators
-				break;
+	for (;;) {
+		Token op = f->curr_token;
+		i32 op_prec = token_precedence(f, op.kind);
+		if (op_prec < prec_in) {
+			// NOTE(bill): This will also catch operators that are not valid "binary" operators
+			break;
+		}
+		Token prev = f->prev_token;
+		switch (op.kind) {
+		case Token_if:
+		case Token_when:
+			if (prev.pos.line < op.pos.line) {
+				// NOTE(bill): Check to see if the `if` or `when` is on the same line of the `lhs` condition
+				goto loop_end;
 			}
 			}
-			Token prev = f->prev_token;
+			break;
+		}
+		expect_operator(f); // NOTE(bill): error checks too
+
+		if (op.kind == Token_Question) {
+			Ast *cond = expr;
+			// Token_Question
+			Ast *x = parse_expr(f, lhs);
+			Token token_c = expect_token(f, Token_Colon);
+			Ast *y = parse_expr(f, lhs);
+			expr = ast_ternary_if_expr(f, x, cond, y);
+		} else if (op.kind == Token_if || op.kind == Token_when) {
+			Ast *x = expr;
+			Ast *cond = parse_expr(f, lhs);
+			Token tok_else = expect_token(f, Token_else);
+			Ast *y = parse_expr(f, lhs);
+
 			switch (op.kind) {
 			switch (op.kind) {
 			case Token_if:
 			case Token_if:
+				expr = ast_ternary_if_expr(f, x, cond, y);
+				break;
 			case Token_when:
 			case Token_when:
-				if (prev.pos.line < op.pos.line) {
-					// NOTE(bill): Check to see if the `if` or `when` is on the same line of the `lhs` condition
-					goto loop_end;
-				}
+				expr = ast_ternary_when_expr(f, x, cond, y);
 				break;
 				break;
 			}
 			}
-			expect_operator(f); // NOTE(bill): error checks too
-
-			if (op.kind == Token_Question) {
-				Ast *cond = expr;
-				// Token_Question
-				Ast *x = parse_expr(f, lhs);
-				Token token_c = expect_token(f, Token_Colon);
-				Ast *y = parse_expr(f, lhs);
-				expr = ast_ternary_if_expr(f, x, cond, y);
-			} else if (op.kind == Token_if || op.kind == Token_when) {
-				Ast *x = expr;
-				Ast *cond = parse_expr(f, lhs);
-				Token tok_else = expect_token(f, Token_else);
-				Ast *y = parse_expr(f, lhs);
-				
-				switch (op.kind) {
-				case Token_if:
-					expr = ast_ternary_if_expr(f, x, cond, y);
-					break;
-				case Token_when:
-					expr = ast_ternary_when_expr(f, x, cond, y);
-					break;
-				}
+		} else {
+			Ast *right = parse_binary_expr(f, false, op_prec+1);
+			if (right == nullptr) {
+				syntax_error(op, "Expected expression on the right-hand side of the binary operator '%.*s'", LIT(op.string));
+			}
+			if (op.kind == Token_or_else) {
+				// NOTE(bill): easier to handle its logic different with its own AST kind
+				expr = ast_or_else_expr(f, expr, op, right);
 			} else {
 			} else {
-				Ast *right = parse_binary_expr(f, false, prec+1);
-				if (right == nullptr) {
-					syntax_error(op, "Expected expression on the right-hand side of the binary operator '%.*s'", LIT(op.string));
-				}
-				if (op.kind == Token_or_else) {
-					// NOTE(bill): easier to handle its logic different with its own AST kind
-					expr = ast_or_else_expr(f, expr, op, right);	
-				} else {
-					expr = ast_binary_expr(f, op, expr, right);
-				}
+				expr = ast_binary_expr(f, op, expr, right);
 			}
 			}
-
-			lhs = false;
 		}
 		}
-		loop_end:;
+
+		lhs = false;
 	}
 	}
+	loop_end:;
 	return expr;
 	return expr;
 }
 }
 
 

+ 11 - 0
src/types.cpp

@@ -2623,6 +2623,17 @@ i64 union_tag_size(Type *u) {
 
 
 	// TODO(bill): Is this an okay approach?
 	// TODO(bill): Is this an okay approach?
 	i64 max_align = 1;
 	i64 max_align = 1;
+
+	if (u->Union.variants.count < 1ull<<8) {
+		max_align = 1;
+	} else if (u->Union.variants.count < 1ull<<16) {
+		max_align = 2;
+	} else if (u->Union.variants.count < 1ull<<32) {
+		max_align = 4;
+	} else {
+		GB_PANIC("how many variants do you have?!");
+	}
+
 	for_array(i, u->Union.variants) {
 	for_array(i, u->Union.variants) {
 		Type *variant_type = u->Union.variants[i];
 		Type *variant_type = u->Union.variants[i];
 		i64 align = type_align_of(variant_type);
 		i64 align = type_align_of(variant_type);

+ 43 - 0
tests/core/crypto/test_core_crypto.odin

@@ -36,6 +36,7 @@ import "core:crypto/sm3"
 import "core:crypto/jh"
 import "core:crypto/jh"
 import "core:crypto/groestl"
 import "core:crypto/groestl"
 import "core:crypto/haval"
 import "core:crypto/haval"
+import "core:crypto/siphash"
 
 
 TEST_count := 0
 TEST_count := 0
 TEST_fail  := 0
 TEST_fail  := 0
@@ -114,6 +115,7 @@ main :: proc() {
     test_haval_192(&t)
     test_haval_192(&t)
     test_haval_224(&t)
     test_haval_224(&t)
     test_haval_256(&t)
     test_haval_256(&t)
+    test_siphash_2_4(&t)
 
 
     // "modern" crypto tests
     // "modern" crypto tests
     test_chacha20(&t)
     test_chacha20(&t)
@@ -1103,3 +1105,44 @@ test_haval_256 :: proc(t: ^testing.T) {
         expect(t, computed_str == v.hash, fmt.tprintf("Expected: %s for input of %s, but got %s instead", v.hash, v.str, computed_str))
         expect(t, computed_str == v.hash, fmt.tprintf("Expected: %s for input of %s, but got %s instead", v.hash, v.str, computed_str))
     }
     }
 }
 }
+
+@(test)
+test_siphash_2_4 :: proc(t: ^testing.T) {
+    // Test vectors from 
+    // https://github.com/veorq/SipHash/blob/master/vectors.h
+    test_vectors := [?]u64 {
+        0x726fdb47dd0e0e31, 0x74f839c593dc67fd, 0x0d6c8009d9a94f5a, 0x85676696d7fb7e2d,
+        0xcf2794e0277187b7, 0x18765564cd99a68d, 0xcbc9466e58fee3ce, 0xab0200f58b01d137,
+        0x93f5f5799a932462, 0x9e0082df0ba9e4b0, 0x7a5dbbc594ddb9f3, 0xf4b32f46226bada7,
+        0x751e8fbc860ee5fb, 0x14ea5627c0843d90, 0xf723ca908e7af2ee, 0xa129ca6149be45e5,
+        0x3f2acc7f57c29bdb, 0x699ae9f52cbe4794, 0x4bc1b3f0968dd39c, 0xbb6dc91da77961bd,
+        0xbed65cf21aa2ee98, 0xd0f2cbb02e3b67c7, 0x93536795e3a33e88, 0xa80c038ccd5ccec8,
+        0xb8ad50c6f649af94, 0xbce192de8a85b8ea, 0x17d835b85bbb15f3, 0x2f2e6163076bcfad,
+        0xde4daaaca71dc9a5, 0xa6a2506687956571, 0xad87a3535c49ef28, 0x32d892fad841c342,
+        0x7127512f72f27cce, 0xa7f32346f95978e3, 0x12e0b01abb051238, 0x15e034d40fa197ae,
+        0x314dffbe0815a3b4, 0x027990f029623981, 0xcadcd4e59ef40c4d, 0x9abfd8766a33735c,
+        0x0e3ea96b5304a7d0, 0xad0c42d6fc585992, 0x187306c89bc215a9, 0xd4a60abcf3792b95,
+        0xf935451de4f21df2, 0xa9538f0419755787, 0xdb9acddff56ca510, 0xd06c98cd5c0975eb,
+        0xe612a3cb9ecba951, 0xc766e62cfcadaf96, 0xee64435a9752fe72, 0xa192d576b245165a,
+        0x0a8787bf8ecb74b2, 0x81b3e73d20b49b6f, 0x7fa8220ba3b2ecea, 0x245731c13ca42499,
+        0xb78dbfaf3a8d83bd, 0xea1ad565322a1a0b, 0x60e61c23a3795013, 0x6606d7e446282b93,
+        0x6ca4ecb15c5f91e1, 0x9f626da15c9625f3, 0xe51b38608ef25f57, 0x958a324ceb064572,
+    }
+
+    key: [16]byte
+    for i in 0..<16 {
+        key[i] = byte(i)
+    }
+
+    for i in 0..<len(test_vectors) {
+        data := make([]byte, i)
+        for j in 0..<i {
+            data[j] = byte(j)
+        }
+
+        vector   := test_vectors[i]
+        computed := siphash.sum_2_4(data[:], key[:])
+
+        expect(t, computed == vector, fmt.tprintf("Expected: 0x%x for input of %v, but got 0x%x instead", vector, data, computed))
+    }  
+}

+ 43 - 0
tests/vendor/botan/test_vendor_botan.odin

@@ -30,6 +30,7 @@ import "vendor:botan/gost"
 import "vendor:botan/streebog"
 import "vendor:botan/streebog"
 import "vendor:botan/sm3"
 import "vendor:botan/sm3"
 import "vendor:botan/skein512"
 import "vendor:botan/skein512"
+import "vendor:botan/siphash"
 
 
 TEST_count := 0
 TEST_count := 0
 TEST_fail  := 0
 TEST_fail  := 0
@@ -82,6 +83,7 @@ main :: proc() {
     test_sm3(&t)
     test_sm3(&t)
     test_skein512_256(&t)
     test_skein512_256(&t)
     test_skein512_512(&t)
     test_skein512_512(&t)
+    test_siphash_2_4(&t)
 
 
     fmt.printf("%v/%v tests successful.\n", TEST_count - TEST_fail, TEST_count)
     fmt.printf("%v/%v tests successful.\n", TEST_count - TEST_fail, TEST_count)
 }
 }
@@ -575,3 +577,44 @@ test_skein512_512 :: proc(t: ^testing.T) {
         expect(t, computed_str == v.hash, fmt.tprintf("Expected: %s for input of %s, but got %s instead", v.hash, v.str, computed_str))
         expect(t, computed_str == v.hash, fmt.tprintf("Expected: %s for input of %s, but got %s instead", v.hash, v.str, computed_str))
     }
     }
 }
 }
+
+@(test)
+test_siphash_2_4 :: proc(t: ^testing.T) {
+    // Test vectors from 
+    // https://github.com/veorq/SipHash/blob/master/vectors.h
+    test_vectors := [?]u64 {
+        0x726fdb47dd0e0e31, 0x74f839c593dc67fd, 0x0d6c8009d9a94f5a, 0x85676696d7fb7e2d,
+        0xcf2794e0277187b7, 0x18765564cd99a68d, 0xcbc9466e58fee3ce, 0xab0200f58b01d137,
+        0x93f5f5799a932462, 0x9e0082df0ba9e4b0, 0x7a5dbbc594ddb9f3, 0xf4b32f46226bada7,
+        0x751e8fbc860ee5fb, 0x14ea5627c0843d90, 0xf723ca908e7af2ee, 0xa129ca6149be45e5,
+        0x3f2acc7f57c29bdb, 0x699ae9f52cbe4794, 0x4bc1b3f0968dd39c, 0xbb6dc91da77961bd,
+        0xbed65cf21aa2ee98, 0xd0f2cbb02e3b67c7, 0x93536795e3a33e88, 0xa80c038ccd5ccec8,
+        0xb8ad50c6f649af94, 0xbce192de8a85b8ea, 0x17d835b85bbb15f3, 0x2f2e6163076bcfad,
+        0xde4daaaca71dc9a5, 0xa6a2506687956571, 0xad87a3535c49ef28, 0x32d892fad841c342,
+        0x7127512f72f27cce, 0xa7f32346f95978e3, 0x12e0b01abb051238, 0x15e034d40fa197ae,
+        0x314dffbe0815a3b4, 0x027990f029623981, 0xcadcd4e59ef40c4d, 0x9abfd8766a33735c,
+        0x0e3ea96b5304a7d0, 0xad0c42d6fc585992, 0x187306c89bc215a9, 0xd4a60abcf3792b95,
+        0xf935451de4f21df2, 0xa9538f0419755787, 0xdb9acddff56ca510, 0xd06c98cd5c0975eb,
+        0xe612a3cb9ecba951, 0xc766e62cfcadaf96, 0xee64435a9752fe72, 0xa192d576b245165a,
+        0x0a8787bf8ecb74b2, 0x81b3e73d20b49b6f, 0x7fa8220ba3b2ecea, 0x245731c13ca42499,
+        0xb78dbfaf3a8d83bd, 0xea1ad565322a1a0b, 0x60e61c23a3795013, 0x6606d7e446282b93,
+        0x6ca4ecb15c5f91e1, 0x9f626da15c9625f3, 0xe51b38608ef25f57, 0x958a324ceb064572,
+    }
+
+    key: [16]byte
+    for i in 0..<16 {
+        key[i] = byte(i)
+    }
+
+    for i in 0..<len(test_vectors) {
+        data := make([]byte, i)
+        for j in 0..<i {
+            data[j] = byte(j)
+        }
+
+        vector   := test_vectors[i]
+        computed := siphash.sum_2_4(data[:], key[:])
+
+        expect(t, computed == vector, fmt.tprintf("Expected: 0x%x for input of %v, but got 0x%x instead", vector, data, computed))
+    }  
+}

+ 4 - 0
vendor/botan/bindings/botan.odin

@@ -99,6 +99,10 @@ MAC_HMAC_SHA_384 :: "HMAC(SHA-384)"
 MAC_HMAC_SHA_512 :: "HMAC(SHA-512)"
 MAC_HMAC_SHA_512 :: "HMAC(SHA-512)"
 MAC_HMAC_MD5     :: "HMAC(MD5)"
 MAC_HMAC_MD5     :: "HMAC(MD5)"
 
 
+MAC_SIPHASH_1_3  :: "SipHash(1,3)"
+MAC_SIPHASH_2_4  :: "SipHash(2,4)"
+MAC_SIPHASH_4_8  :: "SipHash(4,8)"
+
 hash_struct          :: struct{}
 hash_struct          :: struct{}
 hash_t               :: ^hash_struct
 hash_t               :: ^hash_struct
 rng_struct           :: struct{}
 rng_struct           :: struct{}

+ 1 - 1
vendor/botan/blake2b/blake2b.odin

@@ -44,7 +44,7 @@ hash_bytes :: proc "contextless" (data: []byte) -> [DIGEST_SIZE]byte {
 // computed hash to the second parameter.
 // computed hash to the second parameter.
 // It requires that the destination buffer is at least as big as the digest size
 // It requires that the destination buffer is at least as big as the digest size
 hash_string_to_buffer :: proc(data: string, hash: []byte) {
 hash_string_to_buffer :: proc(data: string, hash: []byte) {
-    hash_bytes_to_buffer(transmute([]byte)(data), hash);
+    hash_bytes_to_buffer(transmute([]byte)(data), hash)
 }
 }
 
 
 // hash_bytes_to_buffer will hash the given input and write the
 // hash_bytes_to_buffer will hash the given input and write the

+ 1 - 1
vendor/botan/gost/gost.odin

@@ -44,7 +44,7 @@ hash_bytes :: proc "contextless" (data: []byte) -> [DIGEST_SIZE]byte {
 // computed hash to the second parameter.
 // computed hash to the second parameter.
 // It requires that the destination buffer is at least as big as the digest size
 // It requires that the destination buffer is at least as big as the digest size
 hash_string_to_buffer :: proc(data: string, hash: []byte) {
 hash_string_to_buffer :: proc(data: string, hash: []byte) {
-    hash_bytes_to_buffer(transmute([]byte)(data), hash);
+    hash_bytes_to_buffer(transmute([]byte)(data), hash)
 }
 }
 
 
 // hash_bytes_to_buffer will hash the given input and write the
 // hash_bytes_to_buffer will hash the given input and write the

+ 1 - 1
vendor/botan/keccak/keccak.odin

@@ -44,7 +44,7 @@ hash_bytes_512 :: proc(data: []byte) -> [DIGEST_SIZE_512]byte {
 // computed hash to the second parameter.
 // computed hash to the second parameter.
 // It requires that the destination buffer is at least as big as the digest size
 // It requires that the destination buffer is at least as big as the digest size
 hash_string_to_buffer_512 :: proc(data: string, hash: []byte) {
 hash_string_to_buffer_512 :: proc(data: string, hash: []byte) {
-    hash_bytes_to_buffer_512(transmute([]byte)(data), hash);
+    hash_bytes_to_buffer_512(transmute([]byte)(data), hash)
 }
 }
 
 
 // hash_bytes_to_buffer_512 will hash the given input and write the
 // hash_bytes_to_buffer_512 will hash the given input and write the

+ 1 - 1
vendor/botan/md4/md4.odin

@@ -44,7 +44,7 @@ hash_bytes :: proc "contextless" (data: []byte) -> [DIGEST_SIZE]byte {
 // computed hash to the second parameter.
 // computed hash to the second parameter.
 // It requires that the destination buffer is at least as big as the digest size
 // It requires that the destination buffer is at least as big as the digest size
 hash_string_to_buffer :: proc(data: string, hash: []byte) {
 hash_string_to_buffer :: proc(data: string, hash: []byte) {
-    hash_bytes_to_buffer(transmute([]byte)(data), hash);
+    hash_bytes_to_buffer(transmute([]byte)(data), hash)
 }
 }
 
 
 // hash_bytes_to_buffer will hash the given input and write the
 // hash_bytes_to_buffer will hash the given input and write the

+ 1 - 1
vendor/botan/md5/md5.odin

@@ -44,7 +44,7 @@ hash_bytes :: proc "contextless" (data: []byte) -> [DIGEST_SIZE]byte {
 // computed hash to the second parameter.
 // computed hash to the second parameter.
 // It requires that the destination buffer is at least as big as the digest size
 // It requires that the destination buffer is at least as big as the digest size
 hash_string_to_buffer :: proc(data: string, hash: []byte) {
 hash_string_to_buffer :: proc(data: string, hash: []byte) {
-    hash_bytes_to_buffer(transmute([]byte)(data), hash);
+    hash_bytes_to_buffer(transmute([]byte)(data), hash)
 }
 }
 
 
 // hash_bytes_to_buffer will hash the given input and write the
 // hash_bytes_to_buffer will hash the given input and write the

+ 1 - 1
vendor/botan/ripemd/ripemd.odin

@@ -44,7 +44,7 @@ hash_bytes_160 :: proc(data: []byte) -> [DIGEST_SIZE_160]byte {
 // computed hash to the second parameter.
 // computed hash to the second parameter.
 // It requires that the destination buffer is at least as big as the digest size
 // It requires that the destination buffer is at least as big as the digest size
 hash_string_to_buffer_160 :: proc(data: string, hash: []byte) {
 hash_string_to_buffer_160 :: proc(data: string, hash: []byte) {
-    hash_bytes_to_buffer_160(transmute([]byte)(data), hash);
+    hash_bytes_to_buffer_160(transmute([]byte)(data), hash)
 }
 }
 
 
 // hash_bytes_to_buffer_160 will hash the given input and write the
 // hash_bytes_to_buffer_160 will hash the given input and write the

+ 1 - 1
vendor/botan/sha1/sha1.odin

@@ -44,7 +44,7 @@ hash_bytes :: proc "contextless" (data: []byte) -> [DIGEST_SIZE]byte {
 // computed hash to the second parameter.
 // computed hash to the second parameter.
 // It requires that the destination buffer is at least as big as the digest size
 // It requires that the destination buffer is at least as big as the digest size
 hash_string_to_buffer :: proc(data: string, hash: []byte) {
 hash_string_to_buffer :: proc(data: string, hash: []byte) {
-    hash_bytes_to_buffer(transmute([]byte)(data), hash);
+    hash_bytes_to_buffer(transmute([]byte)(data), hash)
 }
 }
 
 
 // hash_bytes_to_buffer will hash the given input and write the
 // hash_bytes_to_buffer will hash the given input and write the

+ 4 - 4
vendor/botan/sha2/sha2.odin

@@ -47,7 +47,7 @@ hash_bytes_224 :: proc(data: []byte) -> [DIGEST_SIZE_224]byte {
 // computed hash to the second parameter.
 // computed hash to the second parameter.
 // It requires that the destination buffer is at least as big as the digest size
 // It requires that the destination buffer is at least as big as the digest size
 hash_string_to_buffer_224 :: proc(data: string, hash: []byte) {
 hash_string_to_buffer_224 :: proc(data: string, hash: []byte) {
-    hash_bytes_to_buffer_224(transmute([]byte)(data), hash);
+    hash_bytes_to_buffer_224(transmute([]byte)(data), hash)
 }
 }
 
 
 // hash_bytes_to_buffer_224 will hash the given input and write the
 // hash_bytes_to_buffer_224 will hash the given input and write the
@@ -126,7 +126,7 @@ hash_bytes_256 :: proc(data: []byte) -> [DIGEST_SIZE_256]byte {
 // computed hash to the second parameter.
 // computed hash to the second parameter.
 // It requires that the destination buffer is at least as big as the digest size
 // It requires that the destination buffer is at least as big as the digest size
 hash_string_to_buffer_256 :: proc(data: string, hash: []byte) {
 hash_string_to_buffer_256 :: proc(data: string, hash: []byte) {
-    hash_bytes_to_buffer_256(transmute([]byte)(data), hash);
+    hash_bytes_to_buffer_256(transmute([]byte)(data), hash)
 }
 }
 
 
 // hash_bytes_to_buffer_256 will hash the given input and write the
 // hash_bytes_to_buffer_256 will hash the given input and write the
@@ -205,7 +205,7 @@ hash_bytes_384 :: proc(data: []byte) -> [DIGEST_SIZE_384]byte {
 // computed hash to the second parameter.
 // computed hash to the second parameter.
 // It requires that the destination buffer is at least as big as the digest size
 // It requires that the destination buffer is at least as big as the digest size
 hash_string_to_buffer_384 :: proc(data: string, hash: []byte) {
 hash_string_to_buffer_384 :: proc(data: string, hash: []byte) {
-    hash_bytes_to_buffer_384(transmute([]byte)(data), hash);
+    hash_bytes_to_buffer_384(transmute([]byte)(data), hash)
 }
 }
 
 
 // hash_bytes_to_buffer_384 will hash the given input and write the
 // hash_bytes_to_buffer_384 will hash the given input and write the
@@ -284,7 +284,7 @@ hash_bytes_512 :: proc(data: []byte) -> [DIGEST_SIZE_512]byte {
 // computed hash to the second parameter.
 // computed hash to the second parameter.
 // It requires that the destination buffer is at least as big as the digest size
 // It requires that the destination buffer is at least as big as the digest size
 hash_string_to_buffer_512 :: proc(data: string, hash: []byte) {
 hash_string_to_buffer_512 :: proc(data: string, hash: []byte) {
-    hash_bytes_to_buffer_512(transmute([]byte)(data), hash);
+    hash_bytes_to_buffer_512(transmute([]byte)(data), hash)
 }
 }
 
 
 // hash_bytes_to_buffer_512 will hash the given input and write the
 // hash_bytes_to_buffer_512 will hash the given input and write the

+ 4 - 4
vendor/botan/sha3/sha3.odin

@@ -47,7 +47,7 @@ hash_bytes_224 :: proc(data: []byte) -> [DIGEST_SIZE_224]byte {
 // computed hash to the second parameter.
 // computed hash to the second parameter.
 // It requires that the destination buffer is at least as big as the digest size
 // It requires that the destination buffer is at least as big as the digest size
 hash_string_to_buffer_224 :: proc(data: string, hash: []byte) {
 hash_string_to_buffer_224 :: proc(data: string, hash: []byte) {
-    hash_bytes_to_buffer_224(transmute([]byte)(data), hash);
+    hash_bytes_to_buffer_224(transmute([]byte)(data), hash)
 }
 }
 
 
 // hash_bytes_to_buffer_224 will hash the given input and write the
 // hash_bytes_to_buffer_224 will hash the given input and write the
@@ -126,7 +126,7 @@ hash_bytes_256 :: proc(data: []byte) -> [DIGEST_SIZE_256]byte {
 // computed hash to the second parameter.
 // computed hash to the second parameter.
 // It requires that the destination buffer is at least as big as the digest size
 // It requires that the destination buffer is at least as big as the digest size
 hash_string_to_buffer_256 :: proc(data: string, hash: []byte) {
 hash_string_to_buffer_256 :: proc(data: string, hash: []byte) {
-    hash_bytes_to_buffer_256(transmute([]byte)(data), hash);
+    hash_bytes_to_buffer_256(transmute([]byte)(data), hash)
 }
 }
 
 
 // hash_bytes_to_buffer_256 will hash the given input and write the
 // hash_bytes_to_buffer_256 will hash the given input and write the
@@ -205,7 +205,7 @@ hash_bytes_384 :: proc(data: []byte) -> [DIGEST_SIZE_384]byte {
 // computed hash to the second parameter.
 // computed hash to the second parameter.
 // It requires that the destination buffer is at least as big as the digest size
 // It requires that the destination buffer is at least as big as the digest size
 hash_string_to_buffer_384 :: proc(data: string, hash: []byte) {
 hash_string_to_buffer_384 :: proc(data: string, hash: []byte) {
-    hash_bytes_to_buffer_384(transmute([]byte)(data), hash);
+    hash_bytes_to_buffer_384(transmute([]byte)(data), hash)
 }
 }
 
 
 // hash_bytes_to_buffer_384 will hash the given input and write the
 // hash_bytes_to_buffer_384 will hash the given input and write the
@@ -284,7 +284,7 @@ hash_bytes_512 :: proc(data: []byte) -> [DIGEST_SIZE_512]byte {
 // computed hash to the second parameter.
 // computed hash to the second parameter.
 // It requires that the destination buffer is at least as big as the digest size
 // It requires that the destination buffer is at least as big as the digest size
 hash_string_to_buffer_512 :: proc(data: string, hash: []byte) {
 hash_string_to_buffer_512 :: proc(data: string, hash: []byte) {
-    hash_bytes_to_buffer_512(transmute([]byte)(data), hash);
+    hash_bytes_to_buffer_512(transmute([]byte)(data), hash)
 }
 }
 
 
 // hash_bytes_to_buffer_512 will hash the given input and write the
 // hash_bytes_to_buffer_512 will hash the given input and write the

+ 2 - 2
vendor/botan/shake/shake.odin

@@ -45,7 +45,7 @@ hash_bytes_128 :: proc(data: []byte) -> [DIGEST_SIZE_128]byte {
 // computed hash to the second parameter.
 // computed hash to the second parameter.
 // It requires that the destination buffer is at least as big as the digest size
 // It requires that the destination buffer is at least as big as the digest size
 hash_string_to_buffer_128 :: proc(data: string, hash: []byte) {
 hash_string_to_buffer_128 :: proc(data: string, hash: []byte) {
-    hash_bytes_to_buffer_128(transmute([]byte)(data), hash);
+    hash_bytes_to_buffer_128(transmute([]byte)(data), hash)
 }
 }
 
 
 // hash_bytes_to_buffer_128 will hash the given input and write the
 // hash_bytes_to_buffer_128 will hash the given input and write the
@@ -124,7 +124,7 @@ hash_bytes_256 :: proc(data: []byte) -> [DIGEST_SIZE_256]byte {
 // computed hash to the second parameter.
 // computed hash to the second parameter.
 // It requires that the destination buffer is at least as big as the digest size
 // It requires that the destination buffer is at least as big as the digest size
 hash_string_to_buffer_256 :: proc(data: string, hash: []byte) {
 hash_string_to_buffer_256 :: proc(data: string, hash: []byte) {
-    hash_bytes_to_buffer_256(transmute([]byte)(data), hash);
+    hash_bytes_to_buffer_256(transmute([]byte)(data), hash)
 }
 }
 
 
 // hash_bytes_to_buffer_256 will hash the given input and write the
 // hash_bytes_to_buffer_256 will hash the given input and write the

+ 253 - 0
vendor/botan/siphash/siphash.odin

@@ -0,0 +1,253 @@
+package siphash
+
+/*
+    Copyright 2022 zhibog
+    Made available under the BSD-3 license.
+
+    List of contributors:
+        zhibog:  Initial implementation.
+
+    Interface for the SipHash hashing algorithm.
+    The hash will be computed via bindings to the Botan crypto library
+
+    Use the specific procedures for a certain setup. The generic procdedures will default to Siphash 2-4
+*/
+
+import "core:crypto"
+import "core:crypto/util"
+
+import botan "../bindings"
+
+KEY_SIZE    :: 16
+DIGEST_SIZE :: 8
+
+// sum_string_1_3 will hash the given message with the key and return
+// the computed hash as a u64
+sum_string_1_3 :: proc(msg, key: string) -> u64 {
+    return sum_bytes_1_3(transmute([]byte)(msg), transmute([]byte)(key))
+}
+
+// sum_bytes_1_3 will hash the given message with the key and return
+// the computed hash as a u64
+sum_bytes_1_3 :: proc (msg, key: []byte) -> u64 {
+    dst: [8]byte
+    ctx: botan.mac_t
+    init(&ctx, key[:], 1, 3)
+    update(&ctx, msg[:])
+    final(&ctx, dst[:])
+    return util.U64_LE(dst[:])
+}
+
+// sum_string_to_buffer_1_3 will hash the given message with the key and write
+// the computed hash into the provided destination buffer
+sum_string_to_buffer_1_3 :: proc(msg, key: string, dst: []byte) {
+    sum_bytes_to_buffer_1_3(transmute([]byte)(msg), transmute([]byte)(key), dst)
+}
+
+// sum_bytes_to_buffer_1_3 will hash the given message with the key and write
+// the computed hash into the provided destination buffer
+sum_bytes_to_buffer_1_3 :: proc(msg, key, dst: []byte) {
+    assert(len(dst) >= DIGEST_SIZE, "vendor/botan: Destination buffer needs to be at least of size 8")
+    ctx: botan.mac_t
+    init(&ctx, key[:], 1, 3)
+    update(&ctx, msg[:])
+    final(&ctx, dst[:])
+}
+
+sum_1_3 :: proc {
+    sum_string_1_3,
+    sum_bytes_1_3,
+    sum_string_to_buffer_1_3,
+    sum_bytes_to_buffer_1_3,
+}
+
+// verify_u64_1_3 will check if the supplied tag matches with the output you 
+// will get from the provided message and key
+verify_u64_1_3 :: proc (tag: u64 msg, key: []byte) -> bool {
+    return sum_bytes_1_3(msg, key) == tag
+}
+
+// verify_bytes_1_3 will check if the supplied tag matches with the output you 
+// will get from the provided message and key
+verify_bytes_1_3 :: proc (tag, msg, key: []byte) -> bool {
+    derived_tag: [8]byte
+    sum_bytes_to_buffer_1_3(msg, key, derived_tag[:])
+    return crypto.compare_constant_time(derived_tag[:], tag) == 1
+}
+
+verify_1_3 :: proc {
+    verify_bytes_1_3,
+    verify_u64_1_3,
+}
+
+// sum_string_2_4 will hash the given message with the key and return
+// the computed hash as a u64
+sum_string_2_4 :: proc(msg, key: string) -> u64 {
+    return sum_bytes_2_4(transmute([]byte)(msg), transmute([]byte)(key))
+}
+
+// sum_bytes_2_4 will hash the given message with the key and return
+// the computed hash as a u64
+sum_bytes_2_4 :: proc (msg, key: []byte) -> u64 {
+    dst: [8]byte
+    ctx: botan.mac_t
+    init(&ctx, key[:])
+    update(&ctx, msg[:])
+    final(&ctx, dst[:])
+    return util.U64_LE(dst[:])
+}
+
+// sum_string_to_buffer_2_4 will hash the given message with the key and write
+// the computed hash into the provided destination buffer
+sum_string_to_buffer_2_4 :: proc(msg, key: string, dst: []byte) {
+    sum_bytes_to_buffer_2_4(transmute([]byte)(msg), transmute([]byte)(key), dst)
+}
+
+// sum_bytes_to_buffer_2_4 will hash the given message with the key and write
+// the computed hash into the provided destination buffer
+sum_bytes_to_buffer_2_4 :: proc(msg, key, dst: []byte) {
+    assert(len(dst) >= DIGEST_SIZE, "vendor/botan: Destination buffer needs to be at least of size 8")
+    ctx: botan.mac_t
+    init(&ctx, key[:])
+    update(&ctx, msg[:])
+    final(&ctx, dst[:])
+}
+
+sum_2_4 :: proc {
+    sum_string_2_4,
+    sum_bytes_2_4,
+    sum_string_to_buffer_2_4,
+    sum_bytes_to_buffer_2_4,
+}
+
+sum_string           :: sum_string_2_4
+sum_bytes            :: sum_bytes_2_4
+sum_string_to_buffer :: sum_string_to_buffer_2_4
+sum_bytes_to_buffer  :: sum_bytes_to_buffer_2_4
+sum :: proc {
+    sum_string,
+    sum_bytes,
+    sum_string_to_buffer,
+    sum_bytes_to_buffer,
+}
+
+
+// verify_u64_2_4 will check if the supplied tag matches with the output you 
+// will get from the provided message and key
+verify_u64_2_4 :: proc (tag: u64 msg, key: []byte) -> bool {
+    return sum_bytes_2_4(msg, key) == tag
+}
+
+// verify_bytes_2_4 will check if the supplied tag matches with the output you 
+// will get from the provided message and key
+verify_bytes_2_4 :: proc (tag, msg, key: []byte) -> bool {
+    derived_tag: [8]byte
+    sum_bytes_to_buffer_2_4(msg, key, derived_tag[:])
+    return crypto.compare_constant_time(derived_tag[:], tag) == 1
+}
+
+verify_2_4 :: proc {
+    verify_bytes_2_4,
+    verify_u64_2_4,
+}
+
+verify_bytes :: verify_bytes_2_4
+verify_u64   :: verify_u64_2_4
+verify :: proc {
+    verify_bytes,
+    verify_u64,
+}
+
+// sum_string_4_8 will hash the given message with the key and return
+// the computed hash as a u64
+sum_string_4_8 :: proc(msg, key: string) -> u64 {
+    return sum_bytes_4_8(transmute([]byte)(msg), transmute([]byte)(key))
+}
+
+// sum_bytes_4_8 will hash the given message with the key and return
+// the computed hash as a u64
+sum_bytes_4_8 :: proc (msg, key: []byte) -> u64 {
+    dst: [8]byte
+    ctx: botan.mac_t
+    init(&ctx, key[:], 4, 8)
+    update(&ctx, msg[:])
+    final(&ctx, dst[:])
+    return util.U64_LE(dst[:])
+}
+
+// sum_string_to_buffer_4_8 will hash the given message with the key and write
+// the computed hash into the provided destination buffer
+sum_string_to_buffer_4_8 :: proc(msg, key: string, dst: []byte) {
+    sum_bytes_to_buffer_2_4(transmute([]byte)(msg), transmute([]byte)(key), dst)
+}
+
+// sum_bytes_to_buffer_4_8 will hash the given message with the key and write
+// the computed hash into the provided destination buffer
+sum_bytes_to_buffer_4_8 :: proc(msg, key, dst: []byte) {
+    assert(len(dst) >= DIGEST_SIZE, "vendor/botan: Destination buffer needs to be at least of size 8")
+    ctx: botan.mac_t
+    init(&ctx, key[:], 4, 8)
+    update(&ctx, msg[:])
+    final(&ctx, dst[:])
+}
+
+sum_4_8 :: proc {
+    sum_string_4_8,
+    sum_bytes_4_8,
+    sum_string_to_buffer_4_8,
+    sum_bytes_to_buffer_4_8,
+}
+
+// verify_u64_4_8 will check if the supplied tag matches with the output you 
+// will get from the provided message and key
+verify_u64_4_8 :: proc (tag: u64 msg, key: []byte) -> bool {
+    return sum_bytes_4_8(msg, key) == tag
+}
+
+// verify_bytes_4_8 will check if the supplied tag matches with the output you 
+// will get from the provided message and key
+verify_bytes_4_8 :: proc (tag, msg, key: []byte) -> bool {
+    derived_tag: [8]byte
+    sum_bytes_to_buffer_4_8(msg, key, derived_tag[:])
+    return crypto.compare_constant_time(derived_tag[:], tag) == 1
+}
+
+verify_4_8 :: proc {
+    verify_bytes_4_8,
+    verify_u64_4_8,
+}
+
+/*
+    Low level API
+*/
+
+Context :: botan.mac_t
+
+init :: proc(ctx: ^botan.mac_t, key: []byte, c_rounds := 2, d_rounds := 4) {
+    assert(len(key) == KEY_SIZE, "vendor/botan: Invalid key size, want 16")
+    is_valid_setting := (c_rounds == 1 && d_rounds == 3) ||
+                        (c_rounds == 2 && d_rounds == 4) ||
+                        (c_rounds == 4 && d_rounds == 8) 
+    assert(is_valid_setting, "vendor/botan: Incorrect rounds set up. Valid pairs are (1,3), (2,4) and (4,8)")
+    if c_rounds == 1 && d_rounds == 3 {
+        botan.mac_init(ctx, botan.MAC_SIPHASH_1_3, 0)
+    } else if c_rounds == 2 && d_rounds == 4 {
+        botan.mac_init(ctx, botan.MAC_SIPHASH_2_4, 0)
+    } else if c_rounds == 4 && d_rounds == 8 {
+        botan.mac_init(ctx, botan.MAC_SIPHASH_4_8, 0)
+    }
+    botan.mac_set_key(ctx^, len(key) == 0 ? nil : &key[0], uint(len(key)))
+}
+
+update :: proc "contextless" (ctx: ^botan.mac_t, data: []byte) {
+    botan.mac_update(ctx^, len(data) == 0 ? nil : &data[0], uint(len(data)))
+}
+
+final :: proc(ctx: ^botan.mac_t, dst: []byte) {
+    botan.mac_final(ctx^, &dst[0])
+    reset(ctx)
+}
+
+reset :: proc(ctx: ^botan.mac_t) {
+    botan.mac_destroy(ctx^)
+}

+ 3 - 3
vendor/botan/skein512/skein512.odin

@@ -47,7 +47,7 @@ hash_bytes_256 :: proc(data: []byte) -> [DIGEST_SIZE_256]byte {
 // computed hash to the second parameter.
 // computed hash to the second parameter.
 // It requires that the destination buffer is at least as big as the digest size
 // It requires that the destination buffer is at least as big as the digest size
 hash_string_to_buffer_256 :: proc(data: string, hash: []byte) {
 hash_string_to_buffer_256 :: proc(data: string, hash: []byte) {
-    hash_bytes_to_buffer_256(transmute([]byte)(data), hash);
+    hash_bytes_to_buffer_256(transmute([]byte)(data), hash)
 }
 }
 
 
 // hash_bytes_to_buffer_256 will hash the given input and write the
 // hash_bytes_to_buffer_256 will hash the given input and write the
@@ -126,7 +126,7 @@ hash_bytes_512 :: proc(data: []byte) -> [DIGEST_SIZE_512]byte {
 // computed hash to the second parameter.
 // computed hash to the second parameter.
 // It requires that the destination buffer is at least as big as the digest size
 // It requires that the destination buffer is at least as big as the digest size
 hash_string_to_buffer_512 :: proc(data: string, hash: []byte) {
 hash_string_to_buffer_512 :: proc(data: string, hash: []byte) {
-    hash_bytes_to_buffer_512(transmute([]byte)(data), hash);
+    hash_bytes_to_buffer_512(transmute([]byte)(data), hash)
 }
 }
 
 
 // hash_bytes_to_buffer_512 will hash the given input and write the
 // hash_bytes_to_buffer_512 will hash the given input and write the
@@ -205,7 +205,7 @@ hash_bytes_slice :: proc(data: []byte, bit_size: int, allocator := context.alloc
 // computed hash to the second parameter.
 // computed hash to the second parameter.
 // It requires that the destination buffer is at least as big as the digest size
 // It requires that the destination buffer is at least as big as the digest size
 hash_string_to_buffer_slice :: proc(data: string, hash: []byte, bit_size: int, allocator := context.allocator) {
 hash_string_to_buffer_slice :: proc(data: string, hash: []byte, bit_size: int, allocator := context.allocator) {
-    hash_bytes_to_buffer_slice(transmute([]byte)(data), hash, bit_size, allocator);
+    hash_bytes_to_buffer_slice(transmute([]byte)(data), hash, bit_size, allocator)
 }
 }
 
 
 // hash_bytes_to_buffer_slice will hash the given input and write the
 // hash_bytes_to_buffer_slice will hash the given input and write the

+ 1 - 1
vendor/botan/sm3/sm3.odin

@@ -44,7 +44,7 @@ hash_bytes :: proc "contextless" (data: []byte) -> [DIGEST_SIZE]byte {
 // computed hash to the second parameter.
 // computed hash to the second parameter.
 // It requires that the destination buffer is at least as big as the digest size
 // It requires that the destination buffer is at least as big as the digest size
 hash_string_to_buffer :: proc(data: string, hash: []byte) {
 hash_string_to_buffer :: proc(data: string, hash: []byte) {
-    hash_bytes_to_buffer(transmute([]byte)(data), hash);
+    hash_bytes_to_buffer(transmute([]byte)(data), hash)
 }
 }
 
 
 // hash_bytes_to_buffer will hash the given input and write the
 // hash_bytes_to_buffer will hash the given input and write the

+ 2 - 2
vendor/botan/streebog/streebog.odin

@@ -45,7 +45,7 @@ hash_bytes_256 :: proc(data: []byte) -> [DIGEST_SIZE_256]byte {
 // computed hash to the second parameter.
 // computed hash to the second parameter.
 // It requires that the destination buffer is at least as big as the digest size
 // It requires that the destination buffer is at least as big as the digest size
 hash_string_to_buffer_256 :: proc(data: string, hash: []byte) {
 hash_string_to_buffer_256 :: proc(data: string, hash: []byte) {
-    hash_bytes_to_buffer_256(transmute([]byte)(data), hash);
+    hash_bytes_to_buffer_256(transmute([]byte)(data), hash)
 }
 }
 
 
 // hash_bytes_to_buffer_256 will hash the given input and write the
 // hash_bytes_to_buffer_256 will hash the given input and write the
@@ -124,7 +124,7 @@ hash_bytes_512 :: proc(data: []byte) -> [DIGEST_SIZE_512]byte {
 // computed hash to the second parameter.
 // computed hash to the second parameter.
 // It requires that the destination buffer is at least as big as the digest size
 // It requires that the destination buffer is at least as big as the digest size
 hash_string_to_buffer_512 :: proc(data: string, hash: []byte) {
 hash_string_to_buffer_512 :: proc(data: string, hash: []byte) {
-    hash_bytes_to_buffer_512(transmute([]byte)(data), hash);
+    hash_bytes_to_buffer_512(transmute([]byte)(data), hash)
 }
 }
 
 
 // hash_bytes_to_buffer_512 will hash the given input and write the
 // hash_bytes_to_buffer_512 will hash the given input and write the

+ 3 - 3
vendor/botan/tiger/tiger.odin

@@ -46,7 +46,7 @@ hash_bytes_128 :: proc(data: []byte) -> [DIGEST_SIZE_128]byte {
 // computed hash to the second parameter.
 // computed hash to the second parameter.
 // It requires that the destination buffer is at least as big as the digest size
 // It requires that the destination buffer is at least as big as the digest size
 hash_string_to_buffer_128 :: proc(data: string, hash: []byte) {
 hash_string_to_buffer_128 :: proc(data: string, hash: []byte) {
-    hash_bytes_to_buffer_128(transmute([]byte)(data), hash);
+    hash_bytes_to_buffer_128(transmute([]byte)(data), hash)
 }
 }
 
 
 // hash_bytes_to_buffer_128 will hash the given input and write the
 // hash_bytes_to_buffer_128 will hash the given input and write the
@@ -125,7 +125,7 @@ hash_bytes_160 :: proc(data: []byte) -> [DIGEST_SIZE_160]byte {
 // computed hash to the second parameter.
 // computed hash to the second parameter.
 // It requires that the destination buffer is at least as big as the digest size
 // It requires that the destination buffer is at least as big as the digest size
 hash_string_to_buffer_160 :: proc(data: string, hash: []byte) {
 hash_string_to_buffer_160 :: proc(data: string, hash: []byte) {
-    hash_bytes_to_buffer_160(transmute([]byte)(data), hash);
+    hash_bytes_to_buffer_160(transmute([]byte)(data), hash)
 }
 }
 
 
 // hash_bytes_to_buffer_160 will hash the given input and write the
 // hash_bytes_to_buffer_160 will hash the given input and write the
@@ -204,7 +204,7 @@ hash_bytes_192 :: proc(data: []byte) -> [DIGEST_SIZE_192]byte {
 // computed hash to the second parameter.
 // computed hash to the second parameter.
 // It requires that the destination buffer is at least as big as the digest size
 // It requires that the destination buffer is at least as big as the digest size
 hash_string_to_buffer_192 :: proc(data: string, hash: []byte) {
 hash_string_to_buffer_192 :: proc(data: string, hash: []byte) {
-    hash_bytes_to_buffer_192(transmute([]byte)(data), hash);
+    hash_bytes_to_buffer_192(transmute([]byte)(data), hash)
 }
 }
 
 
 // hash_bytes_to_buffer_192 will hash the given input and write the
 // hash_bytes_to_buffer_192 will hash the given input and write the

+ 1 - 1
vendor/botan/whirlpool/whirlpool.odin

@@ -44,7 +44,7 @@ hash_bytes :: proc "contextless" (data: []byte) -> [DIGEST_SIZE]byte {
 // computed hash to the second parameter.
 // computed hash to the second parameter.
 // It requires that the destination buffer is at least as big as the digest size
 // It requires that the destination buffer is at least as big as the digest size
 hash_string_to_buffer :: proc(data: string, hash: []byte) {
 hash_string_to_buffer :: proc(data: string, hash: []byte) {
-    hash_bytes_to_buffer(transmute([]byte)(data), hash);
+    hash_bytes_to_buffer(transmute([]byte)(data), hash)
 }
 }
 
 
 // hash_bytes_to_buffer will hash the given input and write the
 // hash_bytes_to_buffer will hash the given input and write the

+ 20 - 20
vendor/darwin/Metal/MetalClasses.odin

@@ -5508,8 +5508,8 @@ Buffer_newRemoteBufferViewForDevice :: #force_inline proc(self: ^Buffer, device:
 	return msgSend(^Buffer, self, "newRemoteBufferViewForDevice:", device)
 	return msgSend(^Buffer, self, "newRemoteBufferViewForDevice:", device)
 }
 }
 @(objc_type=Buffer, objc_name="newTexture")
 @(objc_type=Buffer, objc_name="newTexture")
-Buffer_newTexture :: #force_inline proc(self: ^Buffer, descriptor: ^TextureDescriptor, offset: NS.UInteger, bytesPerRow: NS.UInteger) -> ^Buffer {
-	return msgSend(^Buffer, self, "newTextureWithDescriptor:offset:bytesPerRow:", descriptor, offset, bytesPerRow)
+Buffer_newTexture :: #force_inline proc(self: ^Buffer, descriptor: ^TextureDescriptor, offset: NS.UInteger, bytesPerRow: NS.UInteger) -> ^Texture {
+	return msgSend(^Texture, self, "newTextureWithDescriptor:offset:bytesPerRow:", descriptor, offset, bytesPerRow)
 }
 }
 @(objc_type=Buffer, objc_name="remoteStorageBuffer")
 @(objc_type=Buffer, objc_name="remoteStorageBuffer")
 Buffer_remoteStorageBuffer :: #force_inline proc(self: ^Buffer) -> ^Buffer {
 Buffer_remoteStorageBuffer :: #force_inline proc(self: ^Buffer) -> ^Buffer {
@@ -6589,8 +6589,8 @@ Device_newRasterizationRateMap :: #force_inline proc(self: ^Device, descriptor:
 	return msgSend(^RasterizationRateMap, self, "newRasterizationRateMapWithDescriptor:", descriptor)
 	return msgSend(^RasterizationRateMap, self, "newRasterizationRateMapWithDescriptor:", descriptor)
 }
 }
 @(objc_type=Device, objc_name="newRenderPipelineStateWithDescriptorWithCompletionHandler")
 @(objc_type=Device, objc_name="newRenderPipelineStateWithDescriptorWithCompletionHandler")
-Device_newRenderPipelineStateWithDescriptorWithCompletionHandler :: #force_inline proc(self: ^Device, descriptor: ^RenderPipelineDescriptor, completionHandler: NewRenderPipelineStateCompletionHandler) {
-	msgSend(nil, self, "newRenderPipelineStateWithDescriptor:completionHandler:", descriptor, completionHandler)
+Device_newRenderPipelineStateWithDescriptorWithCompletionHandler :: #force_inline proc(self: ^Device, descriptor: ^RenderPipelineDescriptor, completionHandler: NewRenderPipelineStateCompletionHandler) -> ^RenderPipelineState {
+	return msgSend(^RenderPipelineState, self, "newRenderPipelineStateWithDescriptor:completionHandler:", descriptor, completionHandler)
 }
 }
 @(objc_type=Device, objc_name="newRenderPipelineState")
 @(objc_type=Device, objc_name="newRenderPipelineState")
 Device_newRenderPipelineState :: #force_inline proc(self: ^Device, descriptor: ^RenderPipelineDescriptor) -> (pipeline: ^RenderPipelineState, error: ^NS.Error) {
 Device_newRenderPipelineState :: #force_inline proc(self: ^Device, descriptor: ^RenderPipelineDescriptor) -> (pipeline: ^RenderPipelineState, error: ^NS.Error) {
@@ -6598,8 +6598,8 @@ Device_newRenderPipelineState :: #force_inline proc(self: ^Device, descriptor: ^
 	return
 	return
 }
 }
 @(objc_type=Device, objc_name="newRenderPipelineStateWithDescriptorWithOptionsAndCompletionHandler")
 @(objc_type=Device, objc_name="newRenderPipelineStateWithDescriptorWithOptionsAndCompletionHandler")
-Device_newRenderPipelineStateWithDescriptorWithOptionsAndCompletionHandler :: #force_inline proc(self: ^Device, descriptor: ^RenderPipelineDescriptor, options: PipelineOption, completionHandler: NewRenderPipelineStateWithReflectionCompletionHandler) {
-	msgSend(nil, self, "newRenderPipelineStateWithDescriptor:options:completionHandler:", descriptor, options, completionHandler)
+Device_newRenderPipelineStateWithDescriptorWithOptionsAndCompletionHandler :: #force_inline proc(self: ^Device, descriptor: ^RenderPipelineDescriptor, options: PipelineOption, completionHandler: NewRenderPipelineStateWithReflectionCompletionHandler) -> ^RenderPipelineState {
+	return msgSend(^RenderPipelineState, self, "newRenderPipelineStateWithDescriptor:options:completionHandler:", descriptor, options, completionHandler)
 }
 }
 @(objc_type=Device, objc_name="newRenderPipelineStateWithDescriptorWithReflection")
 @(objc_type=Device, objc_name="newRenderPipelineStateWithDescriptorWithReflection")
 Device_newRenderPipelineStateWithDescriptorWithReflection :: #force_inline proc(self: ^Device, descriptor: ^RenderPipelineDescriptor, options: PipelineOption, reflection: ^AutoreleasedRenderPipelineReflection) -> (pipeline: ^RenderPipelineState, error: ^NS.Error) {
 Device_newRenderPipelineStateWithDescriptorWithReflection :: #force_inline proc(self: ^Device, descriptor: ^RenderPipelineDescriptor, options: PipelineOption, reflection: ^AutoreleasedRenderPipelineReflection) -> (pipeline: ^RenderPipelineState, error: ^NS.Error) {
@@ -6607,8 +6607,8 @@ Device_newRenderPipelineStateWithDescriptorWithReflection :: #force_inline proc(
 	return
 	return
 }
 }
 @(objc_type=Device, objc_name="newRenderPipelineStateWithTileDescriptorWithCompletionHandler")
 @(objc_type=Device, objc_name="newRenderPipelineStateWithTileDescriptorWithCompletionHandler")
-Device_newRenderPipelineStateWithTileDescriptorWithCompletionHandler :: #force_inline proc(self: ^Device, descriptor: ^TileRenderPipelineDescriptor, options: PipelineOption, completionHandler: NewRenderPipelineStateWithReflectionCompletionHandler) {
-	msgSend(nil, self, "newRenderPipelineStateWithTileDescriptor:options:completionHandler:", descriptor, options, completionHandler)
+Device_newRenderPipelineStateWithTileDescriptorWithCompletionHandler :: #force_inline proc(self: ^Device, descriptor: ^TileRenderPipelineDescriptor, options: PipelineOption, completionHandler: NewRenderPipelineStateWithReflectionCompletionHandler) -> ^RenderPipelineState {
+	return msgSend(^RenderPipelineState, self, "newRenderPipelineStateWithTileDescriptor:options:completionHandler:", descriptor, options, completionHandler)
 }
 }
 @(objc_type=Device, objc_name="newRenderPipelineStateWithTileDescriptorWithReflection")
 @(objc_type=Device, objc_name="newRenderPipelineStateWithTileDescriptorWithReflection")
 Device_newRenderPipelineStateWithTileDescriptorWithReflection :: #force_inline proc(self: ^Device, descriptor: ^TileRenderPipelineDescriptor, options: PipelineOption, reflection: ^AutoreleasedRenderPipelineReflection) -> (pipeline: ^RenderPipelineState, error: ^NS.Error) {
 Device_newRenderPipelineStateWithTileDescriptorWithReflection :: #force_inline proc(self: ^Device, descriptor: ^TileRenderPipelineDescriptor, options: PipelineOption, reflection: ^AutoreleasedRenderPipelineReflection) -> (pipeline: ^RenderPipelineState, error: ^NS.Error) {
@@ -6636,8 +6636,8 @@ Device_newSharedTextureWithHandle :: #force_inline proc(self: ^Device, sharedHan
 	return msgSend(^SharedEvent, self, "newSharedTextureWithHandle:", sharedHandle)
 	return msgSend(^SharedEvent, self, "newSharedTextureWithHandle:", sharedHandle)
 }
 }
 @(objc_type=Device, objc_name="newTexture")
 @(objc_type=Device, objc_name="newTexture")
-Device_newTexture :: #force_inline proc(self: ^Device, desc: ^TextureDescriptor) -> ^SharedEvent {
-	return msgSend(^SharedEvent, self, "newTextureWithDescriptor:", desc)
+Device_newTexture :: #force_inline proc(self: ^Device, desc: ^TextureDescriptor) -> ^Texture {
+	return msgSend(^Texture, self, "newTextureWithDescriptor:", desc)
 }
 }
 @(objc_type=Device, objc_name="newTextureWithIOSurface")
 @(objc_type=Device, objc_name="newTextureWithIOSurface")
 Device_newTextureWithIOSurface :: #force_inline proc(self: ^Device, descriptor: ^TextureDescriptor, iosurface: IOSurfaceRef, plane: NS.UInteger) -> ^Texture {
 Device_newTextureWithIOSurface :: #force_inline proc(self: ^Device, descriptor: ^TextureDescriptor, iosurface: IOSurfaceRef, plane: NS.UInteger) -> ^Texture {
@@ -7101,24 +7101,24 @@ Heap_label :: #force_inline proc(self: ^Heap) -> ^NS.String {
 	return msgSend(^NS.String, self, "label")
 	return msgSend(^NS.String, self, "label")
 }
 }
 @(objc_type=Heap, objc_name="maxAvailableSizeWithAlignment")
 @(objc_type=Heap, objc_name="maxAvailableSizeWithAlignment")
-Heap_maxAvailableSizeWithAlignment :: #force_inline proc(self: ^Heap, alignment: NS.UInteger) -> ^Heap {
-	return msgSend(^Heap, self, "maxAvailableSizeWithAlignment:", alignment)
+Heap_maxAvailableSizeWithAlignment :: #force_inline proc(self: ^Heap, alignment: NS.UInteger) -> NS.UInteger {
+	return msgSend(NS.UInteger, self, "maxAvailableSizeWithAlignment:", alignment)
 }
 }
 @(objc_type=Heap, objc_name="newBuffer")
 @(objc_type=Heap, objc_name="newBuffer")
-Heap_newBuffer :: #force_inline proc(self: ^Heap, length: NS.UInteger, options: ResourceOptions) -> ^Heap {
-	return msgSend(^Heap, self, "newBufferWithLength:options:", length, options)
+Heap_newBuffer :: #force_inline proc(self: ^Heap, length: NS.UInteger, options: ResourceOptions) -> ^Buffer {
+	return msgSend(^Buffer, self, "newBufferWithLength:options:", length, options)
 }
 }
 @(objc_type=Heap, objc_name="newBufferWithOptions")
 @(objc_type=Heap, objc_name="newBufferWithOptions")
-Heap_newBufferWithOptions :: #force_inline proc(self: ^Heap, length: NS.UInteger, options: ResourceOptions, offset: NS.UInteger) -> ^Heap {
-	return msgSend(^Heap, self, "newBufferWithLength:options:offset:", length, options, offset)
+Heap_newBufferWithOptions :: #force_inline proc(self: ^Heap, length: NS.UInteger, options: ResourceOptions, offset: NS.UInteger) -> ^Buffer {
+	return msgSend(^Buffer, self, "newBufferWithLength:options:offset:", length, options, offset)
 }
 }
 @(objc_type=Heap, objc_name="newTexture")
 @(objc_type=Heap, objc_name="newTexture")
-Heap_newTexture :: #force_inline proc(self: ^Heap, desc: ^TextureDescriptor) -> ^Heap {
-	return msgSend(^Heap, self, "newTextureWithDescriptor:", desc)
+Heap_newTexture :: #force_inline proc(self: ^Heap, desc: ^TextureDescriptor) -> ^Texture {
+	return msgSend(^Texture, self, "newTextureWithDescriptor:", desc)
 }
 }
 @(objc_type=Heap, objc_name="newTextureWithOffset")
 @(objc_type=Heap, objc_name="newTextureWithOffset")
-Heap_newTextureWithOffset :: #force_inline proc(self: ^Heap, descriptor: ^TextureDescriptor, offset: NS.UInteger) -> ^Heap {
-	return msgSend(^Heap, self, "newTextureWithDescriptor:offset:", descriptor, offset)
+Heap_newTextureWithOffset :: #force_inline proc(self: ^Heap, descriptor: ^TextureDescriptor, offset: NS.UInteger) -> ^Texture {
+	return msgSend(^Texture, self, "newTextureWithDescriptor:offset:", descriptor, offset)
 }
 }
 @(objc_type=Heap, objc_name="resourceOptions")
 @(objc_type=Heap, objc_name="resourceOptions")
 Heap_resourceOptions :: #force_inline proc(self: ^Heap) -> ResourceOptions {
 Heap_resourceOptions :: #force_inline proc(self: ^Heap) -> ResourceOptions {

Some files were not shown because too many files changed in this diff