Просмотр исходного кода

Merge branch 'master' of https://github.com/odin-lang/Odin

gingerBill 1 месяц назад
Родитель
Сommit
2e4837bf37

+ 1 - 0
base/intrinsics/intrinsics.odin

@@ -384,6 +384,7 @@ objc_register_selector :: proc($name: string) -> objc_SEL   ---
 objc_find_class        :: proc($name: string) -> objc_Class ---
 objc_register_class    :: proc($name: string) -> objc_Class ---
 objc_ivar_get          :: proc(self: ^$T) -> ^$U ---
+objc_block             :: proc(invoke: $T, ..any) -> ^Objc_Block(T) where type_is_proc(T) ---
 
 valgrind_client_request :: proc(default: uintptr, request: uintptr, a0, a1, a2, a3, a4: uintptr) -> uintptr ---
 

+ 5 - 0
base/runtime/core_builtin.odin

@@ -5,6 +5,11 @@ import "base:intrinsics"
 @builtin
 Maybe :: union($T: typeid) {T}
 
+/*
+Represents an Objective-C block with a given procedure signature T
+*/
+@builtin
+Objc_Block :: struct($T: typeid) where intrinsics.type_is_proc(T) { using _: intrinsics.objc_object }
 
 /*
 Recovers the containing/parent struct from a pointer to one of its fields.

+ 11 - 1
base/runtime/procs_darwin.odin

@@ -1,9 +1,12 @@
 #+private
 package runtime
 
-@(priority_index=-1e6)
+@(priority_index=-1e5)
 foreign import ObjC "system:objc"
 
+@(priority_index=-1e6)
+foreign import libSystem "system:System"
+
 import "base:intrinsics"
 
 objc_id    :: ^intrinsics.objc_object
@@ -34,3 +37,10 @@ foreign ObjC {
 	object_getClass           :: proc "c" (obj: objc_id) -> objc_Class ---
 }
 
+foreign libSystem {
+	_NSConcreteGlobalBlock: intrinsics.objc_class
+	_NSConcreteStackBlock:  intrinsics.objc_class
+
+	_Block_object_assign  :: proc "c" (rawptr, rawptr, i32) ---
+	_Block_object_dispose :: proc "c" (rawptr, i32) ---
+}

+ 224 - 0
src/check_builtin.cpp

@@ -457,6 +457,229 @@ gb_internal bool check_builtin_objc_procedure(CheckerContext *c, Operand *operan
 		return true;
 
 	} break;
+
+	case BuiltinProc_objc_block:
+	{
+		// NOTE(harold): The last argument specified in the call is the handler proc,
+		//               any other arguments before it are capture by-copy arguments.
+		auto param_operands = slice_make<Operand>(permanent_allocator(), ce->args.count);
+
+		isize capture_arg_count = ce->args.count - 1;
+
+		// NOTE(harold): The first parameter is already checked at check_builtin_procedure().
+		// Checking again would invalidate the Entity -> Value map for direct parameters if it's the handler proc.
+		param_operands[0] = *operand;
+
+		for (isize i = 0; i < ce->args.count-1; i++) {
+			Operand x = {};
+			check_expr(c, &x, ce->args[i]);
+
+			switch (x.mode) {
+			case Addressing_Value:
+			case Addressing_Context:
+			case Addressing_Variable:
+			case Addressing_Constant:
+				param_operands[i] = x;
+				break;
+
+			default:
+				gbString e = expr_to_string(x.expr);
+				gbString t = type_to_string(x.type);
+				error(x.expr, "'%.*s' capture arguments must be values, but got %s of type %s", LIT(builtin_name), e, t);
+				gb_string_free(t);
+				gb_string_free(e);
+				return false;
+			}
+		}
+
+		// Validate handler proc
+		Operand handler = {};
+
+		if (capture_arg_count == 0) {
+			// It's already been checked and assigned
+			handler = param_operands[0];
+		} else {
+			check_expr_or_type(c, &handler, ce->args[capture_arg_count]);
+			param_operands[capture_arg_count] = handler;
+		}
+
+		if (!is_operand_value(handler) || handler.type->kind != Type_Proc) {
+			gbString e = expr_to_string(handler.expr);
+			gbString t = type_to_string(handler.type);
+			error(handler.expr, "'%.*s' expected a procedure, but got '%s' of type %s", LIT(builtin_name), e, t);
+			gb_string_free(t);
+			gb_string_free(e);
+			return false;
+		}
+
+		Ast *handler_node = unparen_expr(handler.expr);
+
+		// Only direct reference to procs are allowed
+		switch (handler_node->kind) {
+		case Ast_ProcLit: break; // ok
+		case Ast_Ident: {
+			auto& ident = handler_node->Ident;
+
+			if (ident.entity == nullptr) {
+				error(handler.expr, "'%.*s' failed to resolve entity from expression", LIT(builtin_name));
+				return false;
+			}
+
+			if (ident.entity->kind != Entity_Procedure) {
+				gbString e = expr_to_string(handler_node);
+
+				ERROR_BLOCK();
+				error(handler.expr, "'%.*s' expected a direct reference to a procedure", LIT(builtin_name));
+				if(ident.entity->kind == Entity_Variable) {
+					error_line("\tSuggestion: Variables referencing a procedure are not allowed, they are not a direct procedure reference.");
+				} else {
+					error_line("\tSuggestion: Ensure '%s' is not a runtime-evaluated expression.", e); // NOTE(harold): Is this case possible to hit?
+				}
+				error_line("\n\t            Refer to a procedure directly by its name or declare it anonymously: %.*s(proc(){})", LIT(builtin_name));
+
+				gb_string_free(e);
+				return false;
+			}
+		} break;
+
+		default: {
+			gbString e = expr_to_string(handler_node);
+			ERROR_BLOCK();
+			error(handler.expr, "'%.*s' expected a direct reference to a procedure", LIT(builtin_name));
+			if( handler_node->kind == Ast_CallExpr) {
+				error_line("\tSuggestion: Do not use a procedure returned from another procedure.");
+			} else {
+				error_line("\tSuggestion: Ensure '%s' is not a runtime-evaluated expression.", e);
+			}
+			error_line("\n\t            Refer to a procedure directly by its name or declare it anonymously: %.*s(proc(){})", LIT(builtin_name));
+
+			gb_string_free(e);
+		} return false;
+		} // End switch
+
+		auto& handler_type_proc = handler.type->Proc;
+
+		if (capture_arg_count > handler_type_proc.param_count) {
+			error(handler.expr, "'%.*s' captured arguments exceeded the handler's parameter count", LIT(builtin_name));
+			return false;
+		}
+
+		// If the handler proc is odin calling convention, but there must be a context defined in this scope.
+		if (handler_type_proc.calling_convention == ProcCC_Odin) {
+			if ((c->scope->flags & ScopeFlag_ContextDefined) == 0) {
+				ERROR_BLOCK();
+				error(handler.expr, "The handler procedure for '%.*s' requires a context, but no context is defined in the current scope", LIT(builtin_name));
+				error_line("\tSuggestion: 'context = runtime.default_context()', or use the \"c\" calling convention for the handler procedure");
+				return false;
+			}
+		}
+
+		// At most a single return value is supported
+		if (handler_type_proc.result_count > 1) {
+			error(handler_type_proc.node->ProcType.results, "Handler procedures for '%.*s' cannot have multiple return values", LIT(builtin_name));
+			return false;
+		}
+
+		// Ensure that captured args are assignable to the handler's corresponding capture params
+		if (handler_type_proc.param_count > 0) {
+			auto&			handler_param_types         = handler.type->Proc.params->Tuple.variables;
+			Slice<Entity *> handler_capture_param_types = slice(handler_param_types, handler_param_types.count - capture_arg_count, handler_param_types.count);
+
+			for (isize i = 0; i < capture_arg_count; i++) {
+				Operand op = param_operands[i];
+				if (!check_is_assignable_to(c, &op, handler_capture_param_types[i]->type)) {
+					gbString e   = expr_to_string(op.expr);
+					gbString src = type_to_string(op.type);
+					gbString dst = type_to_string(handler_capture_param_types[i]->type);
+					error(op.expr, "'%.*s' captured value '%s' of type '%s' is not assignable to type '%s'", LIT(builtin_name), e, src, dst);
+					gb_string_free(e);
+					gb_string_free(src);
+					gb_string_free(dst);
+					return false;
+				}
+			}
+		}
+
+		ProcCallingConvention cc = handler_type_proc.calling_convention;
+		switch (cc) {
+		case ProcCC_Odin:
+		case ProcCC_Contextless:
+		case ProcCC_CDecl:
+			break; // ok
+		default:
+			ERROR_BLOCK();
+
+			error(handler.expr, "'%.*s' Invalid calling convention for block procedure.", LIT(builtin_name));
+			error_line("\tSuggestion: Do not specify a calling convention ot else use \"c\" or \"cotextless\"");
+			return false;
+		}
+
+		if (handler_type_proc.is_polymorphic) {
+			error(handler.expr, "'%.*s' Unspecialized polymorphic procedures are not allowed.", LIT(builtin_name));
+			return false;
+		}
+
+		// Create the specialized Objc_Block type that this intrinsic will return
+		Token ident = {};
+		ident.kind   = Token_Ident;
+		ident.string = str_lit("Objc_Block");
+		ident.pos    = ast_token(call).pos;
+
+		Token l_paren = {};
+		l_paren.kind   = Token_OpenParen;
+		l_paren.string = str_lit("(");
+		l_paren.pos    = ident.pos;
+
+		Token r_paren = {};
+		r_paren.kind   = Token_CloseParen;
+		l_paren.string = str_lit(")");
+		r_paren.pos    = ident.pos;
+
+		// Remove the capture args from the resulting Objc_Block type signature
+		Ast* handler_proc_type_copy = clone_ast(handler_type_proc.node);
+		handler_proc_type_copy->ProcType.params->FieldList.list.count -= capture_arg_count;
+
+		// Make sure the Objc_Block's specialized proc is always "c" calling conv,
+		// even if we have a context, as the invoker is always "c".
+		// This allows us to have compatibility with the target block types with either calling convention used.
+		handler_proc_type_copy->ProcType.calling_convention = ProcCC_CDecl;
+
+		Array<Ast *> poly_args = {};
+		array_init(&poly_args, permanent_allocator(), 1, 1);
+		poly_args[0] = handler_proc_type_copy;
+
+
+		Type *t_Objc_Block = find_core_type(c->checker, str_lit("Objc_Block"));
+		Operand poly_op = {};
+		poly_op.type = t_Objc_Block;
+		poly_op.mode = Addressing_Type;
+
+		Ast *poly_call = ast_call_expr(nullptr, ast_ident(nullptr, ident), poly_args, l_paren, r_paren, {});
+
+		auto err = check_polymorphic_record_type(c, &poly_op, poly_call);
+
+		if (err != 0) {
+			operand->mode = Addressing_Invalid;
+			operand->type = t_invalid;
+			error(handler.expr, "'%.*s' failed to determine resulting Objc_Block handler procedure", LIT(builtin_name));
+			return false;
+		}
+
+		GB_ASSERT(poly_op.type != t_Objc_Block);
+		GB_ASSERT(poly_op.mode == Addressing_Type);
+
+		bool is_global_block = capture_arg_count == 0 && handler_type_proc.calling_convention != ProcCC_Odin;
+		if (is_global_block) {
+			try_to_add_package_dependency(c, "runtime", "_NSConcreteGlobalBlock");
+		} else {
+			try_to_add_package_dependency(c, "runtime", "_NSConcreteStackBlock");
+		}
+
+		*operand = poly_op;
+		operand->type = alloc_type_pointer(operand->type);
+		operand->mode = Addressing_Value;
+		return true;
+	} break;
 	}
 }
 
@@ -2291,6 +2514,7 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As
 	case BuiltinProc_objc_register_selector: 
 	case BuiltinProc_objc_register_class:
 	case BuiltinProc_objc_ivar_get:
+	case BuiltinProc_objc_block:
 		return check_builtin_objc_procedure(c, operand, call, id, type_hint);
 
 	case BuiltinProc___entry_point:

+ 4 - 0
src/checker.cpp

@@ -1460,6 +1460,10 @@ gb_internal void destroy_checker_info(CheckerInfo *i) {
 	mpsc_destroy(&i->foreign_decls_to_check);
 
 	map_destroy(&i->objc_msgSend_types);
+	string_set_destroy(&i->obcj_class_name_set);
+	mpsc_destroy(&i->objc_class_implementations);
+	map_destroy(&i->objc_method_implementations);
+
 	string_map_destroy(&i->load_file_cache);
 	string_map_destroy(&i->load_directory_cache);
 	map_destroy(&i->load_directory_map);

+ 2 - 0
src/checker_builtin_procs.hpp

@@ -353,6 +353,7 @@ BuiltinProc__type_end,
 	BuiltinProc_objc_register_selector,
 	BuiltinProc_objc_register_class,
 	BuiltinProc_objc_ivar_get,
+	BuiltinProc_objc_block,
 
 	BuiltinProc_constant_utf16_cstring,
 
@@ -714,6 +715,7 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = {
 	{STR_LIT("objc_register_selector"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics, false, true},
 	{STR_LIT("objc_register_class"),    1, false, Expr_Expr, BuiltinProcPkg_intrinsics, false, true},
 	{STR_LIT("objc_ivar_get"),          1, false, Expr_Expr, BuiltinProcPkg_intrinsics, false, true},
+	{STR_LIT("objc_block"),             1, true,  Expr_Expr, BuiltinProcPkg_intrinsics, false, true},
 
 	{STR_LIT("constant_utf16_cstring"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
 

+ 5 - 1
src/llvm_backend.hpp

@@ -198,6 +198,7 @@ struct lbModule {
 	StringMap<lbAddr> objc_classes;
 	StringMap<lbAddr> objc_selectors;
 	StringMap<lbAddr> objc_ivars;
+	isize             objc_next_block_id;  // Used to name objective-c blocks, per module
 
 	PtrMap<u64/*type hash*/, lbAddr> map_cell_info_map; // address of runtime.Map_Info
 	PtrMap<u64/*type hash*/, lbAddr> map_info_map;      // address of runtime.Map_Cell_Info
@@ -483,7 +484,10 @@ gb_internal void lb_emit_if(lbProcedure *p, lbValue cond, lbBlock *true_block, l
 gb_internal void lb_start_block(lbProcedure *p, lbBlock *b);
 
 gb_internal lbValue lb_build_call_expr(lbProcedure *p, Ast *expr);
-
+gb_internal lbProcedure *lb_create_dummy_procedure(lbModule *m, String link_name, Type *type);
+gb_internal void lb_begin_procedure_body(lbProcedure *p);
+gb_internal void lb_end_procedure_body(lbProcedure *p);
+gb_internal lbValue lb_emit_call(lbProcedure *p, lbValue value, Array<lbValue> const &args, ProcInlining inlining);
 
 gb_internal lbAddr lb_find_or_generate_context_ptr(lbProcedure *p);
 gb_internal lbContextData *lb_push_context_onto_stack(lbProcedure *p, lbAddr ctx);

+ 1 - 0
src/llvm_backend_general.cpp

@@ -2944,6 +2944,7 @@ gb_internal lbValue lb_find_ident(lbProcedure *p, lbModule *m, Entity *e, Ast *e
 gb_internal lbValue lb_find_procedure_value_from_entity(lbModule *m, Entity *e) {
 	lbGenerator *gen = m->gen;
 
+	GB_ASSERT(e != nullptr);
 	GB_ASSERT(is_type_proc(e->type));
 	e = strip_entity_wrapping(e);
 	GB_ASSERT(e != nullptr);

+ 1 - 0
src/llvm_backend_proc.cpp

@@ -3746,6 +3746,7 @@ gb_internal lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValu
 	case BuiltinProc_objc_register_selector: return lb_handle_objc_register_selector(p, expr);
 	case BuiltinProc_objc_register_class:    return lb_handle_objc_register_class(p, expr);
 	case BuiltinProc_objc_ivar_get:          return lb_handle_objc_ivar_get(p, expr);
+	case BuiltinProc_objc_block:             return lb_handle_objc_block(p, expr);
 
 
 	case BuiltinProc_constant_utf16_cstring:

+ 391 - 0
src/llvm_backend_utility.cpp

@@ -2263,6 +2263,397 @@ gb_internal lbValue lb_handle_objc_ivar_get(lbProcedure *p, Ast *expr) {
 	return lb_handle_objc_ivar_for_objc_object_pointer(p, self);
 }
 
+gb_internal void lb_create_objc_block_helper_procs(
+	lbModule *m, LLVMTypeRef block_lit_type, isize capture_field_offset,
+	Slice<lbValue> capture_values, Slice<isize> objc_object_indices,
+	lbProcedure *&out_copy_helper, lbProcedure *&out_dispose_helper
+) {
+	gbString copy_helper_name    = gb_string_append_fmt(gb_string_make(temporary_allocator(), ""), "__$objc_block_copy_helper_%lld", m->objc_next_block_id);
+	gbString dispose_helper_name = gb_string_append_fmt(gb_string_make(temporary_allocator(), ""), "__$objc_block_dispose_helper_%lld", m->objc_next_block_id);
+
+	// copy:    Block_Literal *dst, Block_Literal *src, i32 field_apropos
+	// dispose: Block_Literal *src, i32 field_apropos
+	Type *types[3] = { t_rawptr, t_rawptr, t_i32 };
+
+	Type *copy_tuple    = alloc_type_tuple_from_field_types(types,     3, false, true);
+	Type *dispose_tuple = alloc_type_tuple_from_field_types(&types[1], 2, false, true);
+
+	Type *copy_proc_type    = alloc_type_proc(nullptr, copy_tuple,    3, nullptr, 0, false, ProcCC_CDecl);
+	Type *dispose_proc_type = alloc_type_proc(nullptr, dispose_tuple, 2, nullptr, 0, false, ProcCC_CDecl);
+
+	lbProcedure *copy_proc    = lb_create_dummy_procedure(m, make_string((u8*)copy_helper_name, gb_string_length(copy_helper_name)), copy_proc_type);
+	lbProcedure *dispose_proc = lb_create_dummy_procedure(m, make_string((u8*)dispose_helper_name, gb_string_length(dispose_helper_name)), dispose_proc_type);
+	LLVMSetLinkage(copy_proc->value, LLVMPrivateLinkage);
+	LLVMSetLinkage(dispose_proc->value, LLVMPrivateLinkage);
+
+
+	const int BLOCK_FIELD_IS_OBJECT = 3;  // id, NSObject, __attribute__((NSObject)), block, ...
+	const int BLOCK_FIELD_IS_BLOCK  = 7;  // a block variable
+
+	Type *block_base_type = find_core_type(m->info->checker, str_lit("Objc_Block"));
+
+	auto is_object_objc_block = [](Type *type, Type *block_base_type) -> bool {
+
+		Type *base = base_type(type_deref(type));
+		GB_ASSERT(base->kind == Type_Struct);
+
+		while (is_type_polymorphic_record_specialized(base)) {
+			if (base->Struct.polymorphic_parent) {
+				base = base->Struct.polymorphic_parent;
+
+				if (base == block_base_type) {
+					return true;
+				}
+				base = base_type(base);
+				GB_ASSERT(base->kind == Type_Struct);
+			}
+		}
+
+		return false;
+	};
+
+	lb_begin_procedure_body(copy_proc);
+	lb_begin_procedure_body(dispose_proc);
+	{
+		for (isize object_index : objc_object_indices) {
+			const auto field_offset = unsigned(capture_field_offset+object_index);
+
+			Type		*field_type    = capture_values[object_index].type;
+			LLVMTypeRef field_raw_type = lb_type(m, field_type);
+
+			GB_ASSERT(is_type_objc_object(field_type));
+			bool is_block_obj = is_object_objc_block(field_type, block_base_type);
+
+			auto copy_args    = array_make<lbValue>(temporary_allocator(), 3, 3);
+			auto dispose_args = array_make<lbValue>(temporary_allocator(), 2, 2);
+
+			// Copy helper
+			{
+				LLVMValueRef dst_field = LLVMBuildStructGEP2(copy_proc->builder, block_lit_type, copy_proc->raw_input_parameters[0], field_offset, "");
+				LLVMValueRef src_field = LLVMBuildStructGEP2(copy_proc->builder, block_lit_type, copy_proc->raw_input_parameters[1], field_offset, "");
+
+				lbValue dst_value = {}, src_value = {};
+				dst_value.type  = alloc_type_pointer(field_type);
+				dst_value.value = dst_field;
+
+				src_value.type  = field_type;
+				src_value.value = LLVMBuildLoad2(copy_proc->builder, field_raw_type, src_field, "");
+
+				copy_args[0] = dst_value;
+				copy_args[1] = src_value;
+				copy_args[2] = lb_const_int(m, t_i32, u64(is_block_obj ? BLOCK_FIELD_IS_BLOCK : BLOCK_FIELD_IS_OBJECT));
+
+				lb_emit_runtime_call(copy_proc, "_Block_object_assign", copy_args);
+			}
+
+			// Dispose helper
+			{
+				LLVMValueRef src_field = LLVMBuildStructGEP2(dispose_proc->builder, block_lit_type, dispose_proc->raw_input_parameters[0], field_offset, "");
+				lbValue src_value = {};
+				src_value.type  = field_type;
+				src_value.value = LLVMBuildLoad2(dispose_proc->builder, field_raw_type, src_field, "");
+
+				dispose_args[0] = src_value;
+				dispose_args[1] = lb_const_int(m, t_i32, u64(is_block_obj ? BLOCK_FIELD_IS_BLOCK : BLOCK_FIELD_IS_OBJECT));
+
+				lb_emit_runtime_call(dispose_proc, "_Block_object_dispose", dispose_args);
+			}
+		}
+	}
+	lb_end_procedure_body(copy_proc);
+	lb_end_procedure_body(dispose_proc);
+
+
+	out_copy_helper    = copy_proc;
+	out_dispose_helper = dispose_proc;
+}
+
+gb_internal lbValue lb_handle_objc_block(lbProcedure *p, Ast *expr) {
+	/// #See: https://clang.llvm.org/docs/Block-ABI-Apple.html
+	///       https://www.newosxbook.com/src.php?tree=xnu&file=/libkern/libkern/Block_private.h
+	///       https://github.com/llvm/llvm-project/blob/21f1f9558df3830ffa637def364e3c0cb0dbb3c0/compiler-rt/lib/BlocksRuntime/Block_private.h
+	///       https://github.com/apple-oss-distributions/libclosure/blob/3668b0837f47be3cc1c404fb5e360f4ff178ca13/runtime.cpp
+
+	ast_node(ce, CallExpr, expr);
+	GB_ASSERT(ce->args.count > 0);
+
+	lbModule *m = p->module;
+
+	m->objc_next_block_id += 1;
+
+	const isize capture_arg_count = ce->args.count - 1;
+
+	Type *block_result_type = type_of_expr(expr);
+	GB_ASSERT(block_result_type != nullptr && block_result_type->kind == Type_Pointer);
+
+	LLVMTypeRef lb_type_rawptr = lb_type(m, t_rawptr);
+	LLVMTypeRef lb_type_i32    = lb_type(m, t_i32);
+	LLVMTypeRef lb_type_int    = lb_type(m, t_int);
+
+	// Build user proc
+	// Type *   user_proc_type    = type_of_expr(ce->args[capture_arg_count]);
+	lbValue  user_proc_value   = lb_build_expr(p, ce->args[capture_arg_count]);
+	auto&    user_proc         = user_proc_value.type->Proc;
+	GB_ASSERT(user_proc_value.type->kind == Type_Proc);
+
+	const bool  is_global             = capture_arg_count == 0 && user_proc.calling_convention != ProcCC_Odin;
+	const isize block_forward_args    = user_proc.param_count - capture_arg_count;
+	const isize capture_fields_offset = user_proc.calling_convention != ProcCC_Odin ? 5 : 6;
+
+	Ast *proc_lit = unparen_expr(ce->args[capture_arg_count]);
+	if (proc_lit->kind == Ast_Ident) {
+		proc_lit = proc_lit->Ident.entity->decl_info->proc_lit;
+	}
+	GB_ASSERT(proc_lit->kind == Ast_ProcLit);
+
+	lbProcedure *copy_helper = {}, *dispose_helper = {};
+
+	// Build captured arguments & collect the ones that are Objective-C objects
+	auto captured_values = array_make<lbValue>(temporary_allocator(), capture_arg_count, capture_arg_count);
+	auto objc_captures   = array_make<isize>(temporary_allocator());
+
+	for (isize i = 0; i < capture_arg_count; i++) {
+		captured_values[i] = lb_build_expr(p, ce->args[i]);
+
+		if (is_type_pointer(captured_values[i].type) && is_type_objc_object(captured_values[i].type)) {
+			array_add(&objc_captures, i);
+		}
+	}
+
+	const bool has_objc_fields = objc_captures.count > 0;
+
+
+	// Create proc with the block signature
+	// (takes a block literal pointer as the first parameter, followed by any expected ones from the user's proc)
+	gbString block_invoker_name = gb_string_append_fmt(gb_string_make(permanent_allocator(), ""), "__$objc_block_invoker_%lld", m->objc_next_block_id);
+
+	// Add + 1 because the first parameter received is the block literal pointer itself
+	auto invoker_args = array_make<Type *>(temporary_allocator(), block_forward_args + 1, block_forward_args + 1);
+	invoker_args[0] = t_rawptr;
+
+	GB_ASSERT(block_forward_args <= user_proc.param_count);
+	if (user_proc.param_count > 0) {
+		Slice<Entity *> user_proc_param_types = user_proc.params->Tuple.variables;
+		for (isize i = 0; i < block_forward_args; i++) {
+			invoker_args[i+1] = user_proc_param_types[i]->type;
+		}
+	}
+
+	GB_ASSERT(user_proc.result_count <= 1);
+
+	Type *invoker_args_tuple    = alloc_type_tuple_from_field_types(invoker_args.data, invoker_args.count, false, true);
+	Type *invoker_results_tuple = nullptr;
+	if (user_proc.result_count > 0) {
+		invoker_results_tuple = alloc_type_tuple_from_field_types(&user_proc.results->Tuple.variables[0]->type, 1, false, true);
+	}
+
+	Type *invoker_proc_type = alloc_type_proc(nullptr, invoker_args_tuple, invoker_args_tuple->Tuple.variables.count,
+												invoker_results_tuple, user_proc.result_count, false, ProcCC_CDecl);
+
+	lbProcedure *invoker_proc = lb_create_dummy_procedure(m, make_string((u8*)block_invoker_name,
+									gb_string_length(block_invoker_name)), invoker_proc_type);
+	LLVMSetLinkage(invoker_proc->value, LLVMPrivateLinkage);
+
+	// Create the block descriptor and block literal
+	gbString block_lit_type_name = gb_string_make(temporary_allocator(), "__$ObjC_Block_Literal_");
+	block_lit_type_name = gb_string_append_fmt(block_lit_type_name, "%lld", m->objc_next_block_id);
+
+	gbString block_desc_type_name = gb_string_make(temporary_allocator(), "__$ObjC_Block_Descriptor_");
+	block_desc_type_name = gb_string_append_fmt(block_desc_type_name, "%lld", m->objc_next_block_id);
+
+	LLVMTypeRef  block_lit_type = {};
+	LLVMTypeRef  block_desc_type = {};
+	LLVMValueRef block_desc_initializer = {};
+
+	{
+		block_desc_type = LLVMStructCreateNamed(m->ctx, block_desc_type_name);
+
+		LLVMTypeRef fields_types[4] = {
+			lb_type_int,    // Reserved
+			lb_type_int,    // Block size
+			lb_type_rawptr, // Copy helper func pointer
+			lb_type_rawptr, // Dispose helper func pointer
+		};
+
+		LLVMStructSetBody(block_desc_type, fields_types, has_objc_fields ? 4 : 2, false);
+	}
+
+	{
+		block_lit_type = LLVMStructCreateNamed(m->ctx, block_lit_type_name);
+
+		auto fields = array_make<LLVMTypeRef>(temporary_allocator());
+
+		array_add(&fields, lb_type_rawptr);  // isa
+		array_add(&fields, lb_type_i32);     // flags
+		array_add(&fields, lb_type_i32);     // reserved
+		array_add(&fields, lb_type_rawptr);  // invoke
+		array_add(&fields, block_desc_type); // descriptor
+
+		if (user_proc.calling_convention == ProcCC_Odin) {
+			array_add(&fields, lb_type(m, t_context)); // context
+		}
+
+		// From here on, fields for the captured vars are added
+		for (lbValue cap_arg : captured_values) {
+			array_add(&fields, lb_type(m, cap_arg.type));
+		}
+
+		LLVMStructSetBody(block_lit_type, fields.data, (unsigned)fields.count, false);
+	}
+
+	// Generate copy and dispose helper functions for captured params that are Objective-C objects (or a Block)
+	if (has_objc_fields) {
+		lb_create_objc_block_helper_procs(m, block_lit_type, capture_fields_offset,
+			slice(captured_values, 0, captured_values.count),
+			slice(objc_captures, 0, objc_captures.count),
+			copy_helper, dispose_helper);
+	}
+
+	{
+		LLVMValueRef fields_values[4] = {
+			lb_const_int(m, t_int, 0).value,                               // Reserved
+			lb_const_int(m, t_int, u64(lb_sizeof(block_lit_type))).value,  // Block size
+			has_objc_fields ? copy_helper->value : nullptr,                // Copy helper
+			has_objc_fields ? dispose_helper->value : nullptr,             // Dispose helper
+		};
+
+		block_desc_initializer = LLVMConstNamedStruct(block_desc_type, fields_values, has_objc_fields ? 4 : 2);
+	}
+
+	// Create global block descriptor
+	gbString desc_global_name = gb_string_make(temporary_allocator(), "__$objc_block_desc_");
+	desc_global_name = gb_string_append_fmt(desc_global_name, "%lld", m->objc_next_block_id);
+
+	LLVMValueRef p_descriptor = LLVMAddGlobal(m->mod, block_desc_type, desc_global_name);
+	LLVMSetInitializer(p_descriptor, block_desc_initializer);
+
+
+	/// Invoker body
+	lb_begin_procedure_body(invoker_proc);
+	{
+		auto call_args = array_make<lbValue>(temporary_allocator(), user_proc.param_count, user_proc.param_count);
+
+		for (isize i = 1; i < invoker_proc->raw_input_parameters.count; i++) {
+			lbValue arg = {};
+			arg.type  = invoker_args[i];
+			arg.value = invoker_proc->raw_input_parameters[i],
+			call_args[i-1] = arg;
+		}
+
+		LLVMValueRef block_literal = invoker_proc->raw_input_parameters[0];
+
+		// Push context, if needed
+		if (user_proc.calling_convention == ProcCC_Odin) {
+			LLVMValueRef p_context = LLVMBuildStructGEP2(invoker_proc->builder, block_lit_type, block_literal, 5, "context");
+			lbValue ctx_val = {};
+			ctx_val.type  = t_context_ptr;
+			ctx_val.value = p_context;
+
+			lb_push_context_onto_stack(invoker_proc, lb_addr(ctx_val));
+		}
+
+		// Copy capture parameters from the block literal
+		for (isize i = 0; i < capture_arg_count; i++) {
+			LLVMValueRef cap_value = LLVMBuildStructGEP2(invoker_proc->builder, block_lit_type, block_literal, unsigned(capture_fields_offset + i), "");
+
+			lbValue cap_arg = {};
+			cap_arg.value = cap_value;
+			cap_arg.type  = alloc_type_pointer(captured_values[i].type);
+
+			lbValue arg = lb_emit_load(invoker_proc, cap_arg);
+			call_args[block_forward_args+i] = arg;
+		}
+
+		lbValue result = lb_emit_call(invoker_proc, user_proc_value, call_args, proc_lit->ProcLit.inlining);
+
+		GB_ASSERT(user_proc.result_count <= 1);
+		if (user_proc.result_count > 0) {
+			GB_ASSERT(result.value != nullptr);
+			LLVMBuildRet(p->builder, result.value);
+		}
+	}
+	lb_end_procedure_body(invoker_proc);
+
+
+	/// Create local block literal
+	const int BLOCK_HAS_COPY_DISPOSE = (1 << 25);
+	const int BLOCK_IS_GLOBAL        = (1 << 28);
+
+	int  raw_flags = is_global ? BLOCK_IS_GLOBAL : 0;
+	if (has_objc_fields) {
+		raw_flags |= BLOCK_HAS_COPY_DISPOSE;
+	}
+
+	gbString block_var_name = gb_string_make(temporary_allocator(), "__$objc_block_literal_");
+	block_var_name = gb_string_append_fmt(block_var_name, "%lld", m->objc_next_block_id);
+
+	lbValue result = {};
+	result.type = block_result_type;
+
+	lbValue isa_val      = lb_find_runtime_value(m, is_global ? str_lit("_NSConcreteGlobalBlock") : str_lit("_NSConcreteStackBlock"));
+	lbValue flags_val    = lb_const_int(m, t_i32, (u64)raw_flags);
+	lbValue reserved_val = lb_const_int(m, t_i32, 0);
+
+	if (is_global) {
+		LLVMValueRef p_block_lit = LLVMAddGlobal(m->mod, block_lit_type, block_var_name);
+		result.value = p_block_lit;
+
+		LLVMValueRef fields_values[5] = {
+			isa_val.value,       // isa
+			flags_val.value,     // flags
+			reserved_val.value,  // reserved
+			invoker_proc->value, // invoke
+			p_descriptor         // descriptor
+		};
+
+		LLVMValueRef g_block_lit_initializer = LLVMConstNamedStruct(block_lit_type, fields_values, gb_count_of(fields_values));
+		LLVMSetInitializer(p_block_lit, g_block_lit_initializer);
+
+	} else {
+		LLVMValueRef p_block_lit = llvm_alloca(p, block_lit_type, lb_alignof(block_lit_type), block_var_name);
+		result.value = p_block_lit;
+
+		// Initialize it
+		LLVMValueRef f_isa        = LLVMBuildStructGEP2(p->builder, block_lit_type, p_block_lit, 0, "isa");
+		LLVMValueRef f_flags      = LLVMBuildStructGEP2(p->builder, block_lit_type, p_block_lit, 1, "flags");
+		LLVMValueRef f_reserved   = LLVMBuildStructGEP2(p->builder, block_lit_type, p_block_lit, 2, "reserved");
+		LLVMValueRef f_invoke     = LLVMBuildStructGEP2(p->builder, block_lit_type, p_block_lit, 3, "invoke");
+		LLVMValueRef f_descriptor = LLVMBuildStructGEP2(p->builder, block_lit_type, p_block_lit, 4, "descriptor");
+
+		LLVMBuildStore(p->builder, isa_val.value,       f_isa);
+		LLVMBuildStore(p->builder, flags_val.value,     f_flags);
+		LLVMBuildStore(p->builder, reserved_val.value,  f_reserved);
+		LLVMBuildStore(p->builder, invoker_proc->value, f_invoke);
+		LLVMBuildStore(p->builder, p_descriptor,        f_descriptor);
+
+		// Store current context, if there is one
+		if (user_proc.calling_convention == ProcCC_Odin) {
+			LLVMValueRef f_context = LLVMBuildStructGEP2(p->builder, block_lit_type, p_block_lit, 5, "context");
+			lbAddr p_current_context = lb_find_or_generate_context_ptr(p);
+
+			LLVMValueRef context_size = LLVMConstInt(LLVMInt64TypeInContext(m->ctx), (u64)lb_sizeof(lb_type(m, t_context)), false);
+			LLVMBuildMemCpy(p->builder, f_context, lb_try_get_alignment(f_context, 1),
+							p_current_context.addr.value, lb_try_get_alignment(p_current_context.addr.value, 1), context_size);
+		}
+
+		// Store captured args into the block
+		for (isize i = 0; i < captured_values.count; i++) {
+			lbValue capture_arg = captured_values[i];
+
+			unsigned field_index = unsigned(capture_fields_offset + i);
+			LLVMValueRef f_capture = LLVMBuildStructGEP2(p->builder, block_lit_type, p_block_lit, field_index, "capture_arg");
+
+			lbValue f_capture_val = {};
+			f_capture_val.type  = alloc_type_pointer(capture_arg.type);
+			f_capture_val.value = f_capture;
+
+			lb_emit_store(p, f_capture_val, capture_arg);
+		}
+	}
+
+	return result;
+}
+
 gb_internal lbValue lb_handle_objc_find_selector(lbProcedure *p, Ast *expr) {
 	ast_node(ce, CallExpr, expr);
 

+ 264 - 63
vendor/darwin/Metal/MetalClasses.odin

@@ -2767,6 +2767,14 @@ RenderPipelineDescriptor_fragmentBuffers :: #force_inline proc "c" (self: ^Rende
 RenderPipelineDescriptor_fragmentFunction :: #force_inline proc "c" (self: ^RenderPipelineDescriptor) -> ^Function {
 	return msgSend(^Function, self, "fragmentFunction")
 }
+@(objc_type=RenderPipelineDescriptor, objc_name="vertexLinkedFunctions")
+RenderPipelineDescriptor_vertexLinkedFunctions :: #force_inline proc "c" (self: ^RenderPipelineDescriptor) -> ^LinkedFunctions {
+	return msgSend(^LinkedFunctions, self, "vertexLinkedFunctions")
+}
+@(objc_type=RenderPipelineDescriptor, objc_name="fragmentLinkedFunctions")
+RenderPipelineDescriptor_fragmentLinkedFunctions :: #force_inline proc "c" (self: ^RenderPipelineDescriptor) -> ^LinkedFunctions {
+	return msgSend(^LinkedFunctions, self, "fragmentLinkedFunctions")
+}
 @(objc_type=RenderPipelineDescriptor, objc_name="inputPrimitiveTopology")
 RenderPipelineDescriptor_inputPrimitiveTopology :: #force_inline proc "c" (self: ^RenderPipelineDescriptor) -> PrimitiveTopologyClass {
 	return msgSend(PrimitiveTopologyClass, self, "inputPrimitiveTopology")
@@ -2831,6 +2839,14 @@ RenderPipelineDescriptor_setDepthAttachmentPixelFormat :: #force_inline proc "c"
 RenderPipelineDescriptor_setFragmentFunction :: #force_inline proc "c" (self: ^RenderPipelineDescriptor, fragmentFunction: ^Function) {
 	msgSend(nil, self, "setFragmentFunction:", fragmentFunction)
 }
+@(objc_type=RenderPipelineDescriptor, objc_name="setVertexLinkedFunctions")
+RenderPipelineDescriptor_setVertexLinkedFunctions :: #force_inline proc "c" (self: ^RenderPipelineDescriptor, vertexLinkedFunctions: ^LinkedFunctions) {
+	msgSend(nil, self, "setVertexLinkedFunctions:", vertexLinkedFunctions)
+}
+@(objc_type=RenderPipelineDescriptor, objc_name="setFragmentLinkedFunctions")
+RenderPipelineDescriptor_setFragmentLinkedFunctions :: #force_inline proc "c" (self: ^RenderPipelineDescriptor, fragmentLinkedFunctions: ^LinkedFunctions) {
+	msgSend(nil, self, "setFragmentLinkedFunctions:", fragmentLinkedFunctions)
+}
 @(objc_type=RenderPipelineDescriptor, objc_name="setInputPrimitiveTopology")
 RenderPipelineDescriptor_setInputPrimitiveTopology :: #force_inline proc "c" (self: ^RenderPipelineDescriptor, inputPrimitiveTopology: PrimitiveTopologyClass) {
 	msgSend(nil, self, "setInputPrimitiveTopology:", inputPrimitiveTopology)
@@ -2940,98 +2956,284 @@ RenderPipelineDescriptor_vertexFunction :: #force_inline proc "c" (self: ^Render
 	return msgSend(^Function, self, "vertexFunction")
 }
 
-@(objc_type=RenderPipelineDescriptor, objc_name="objectFunction")
-RenderPipelineDescriptor_objectFunction :: #force_inline proc "c" (self: ^RenderPipelineDescriptor) -> ^Function {
-	return msgSend(^Function, self, "objectFunction")
+@(objc_type=RenderPipelineDescriptor, objc_name="alphaToCoverageEnabled")
+RenderPipelineDescriptor_alphaToCoverageEnabled :: #force_inline proc "c" (self: ^RenderPipelineDescriptor) -> BOOL {
+	return msgSend(BOOL, self, "alphaToCoverageEnabled")
 }
-@(objc_type=RenderPipelineDescriptor, objc_name="setObjectFunction")
-RenderPipelineDescriptor_setObjectFunction :: #force_inline proc "c" (self: ^RenderPipelineDescriptor, objectFunction: ^Function) {
-	msgSend(nil, self, "setObjectFunction:", objectFunction)
+@(objc_type=RenderPipelineDescriptor, objc_name="alphaToOneEnabled")
+RenderPipelineDescriptor_alphaToOneEnabled :: #force_inline proc "c" (self: ^RenderPipelineDescriptor) -> BOOL {
+	return msgSend(BOOL, self, "alphaToOneEnabled")
 }
-@(objc_type=RenderPipelineDescriptor, objc_name="meshFunction")
-RenderPipelineDescriptor_meshFunction :: #force_inline proc "c" (self: ^RenderPipelineDescriptor) -> ^Function {
-	return msgSend(^Function, self, "meshFunction")
+
+@(objc_type=RenderPipelineDescriptor, objc_name="rasterizationEnabled")
+RenderPipelineDescriptor_rasterizationEnabled :: #force_inline proc "c" (self: ^RenderPipelineDescriptor) -> BOOL {
+	return msgSend(BOOL, self, "rasterizationEnabled")
 }
-@(objc_type=RenderPipelineDescriptor, objc_name="setMeshFunction")
-RenderPipelineDescriptor_setMeshFunction :: #force_inline proc "c" (self: ^RenderPipelineDescriptor, meshFunction: ^Function) {
-	msgSend(nil, self, "setMeshFunction:", meshFunction)
+
+@(objc_type=RenderPipelineDescriptor, objc_name="shaderValidation")
+RenderPipelineDescriptor_shaderValidation :: #force_inline proc "c" (self: ^RenderPipelineDescriptor) -> ShaderValidation {
+	return msgSend(ShaderValidation, self, "shaderValidation")
+}
+@(objc_type=RenderPipelineDescriptor, objc_name="setShaderValidation")
+RenderPipelineDescriptor_setShaderValidation :: #force_inline proc "c" (self: ^RenderPipelineDescriptor, shaderValidation: ShaderValidation) {
+	msgSend(nil, self, "setShaderValidation:", shaderValidation)
 }
 
-@(objc_type=RenderPipelineDescriptor, objc_name="maxTotalThreadsPerObjectThreadgroup")
-RenderPipelineDescriptor_maxTotalThreadsPerObjectThreadgroup :: #force_inline proc "c" (self: ^RenderPipelineDescriptor) -> NS.UInteger {
-	return msgSend(NS.UInteger, self, "maxTotalThreadsPerObjectThreadgroup")
+
+////////////////////////////////////////////////////////////////////////////////
+
+
+@(objc_class="MTLMeshRenderPipelineDescriptor")
+MeshRenderPipelineDescriptor :: struct{ using _: NS.Copying(MeshRenderPipelineDescriptor) }
+
+@(objc_type=MeshRenderPipelineDescriptor, objc_name="alloc", objc_is_class_method=true)
+MeshRenderPipelineDescriptor_alloc :: #force_inline proc "c" () -> ^MeshRenderPipelineDescriptor {
+	return msgSend(^MeshRenderPipelineDescriptor, MeshRenderPipelineDescriptor, "alloc")
 }
-@(objc_type=RenderPipelineDescriptor, objc_name="setMaxTotalThreadsPerObjectThreadgroup")
-RenderPipelineDescriptor_setMaxTotalThreadsPerObjectThreadgroup :: #force_inline proc "c" (self: ^RenderPipelineDescriptor, maxTotalThreadsPerObjectThreadgroup: NS.UInteger) {
-	msgSend(nil, self, "setMaxTotalThreadsPerObjectThreadgroup:", maxTotalThreadsPerObjectThreadgroup)
+
+@(objc_type=MeshRenderPipelineDescriptor, objc_name="init")
+MeshRenderPipelineDescriptor_init :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) -> ^MeshRenderPipelineDescriptor {
+	return msgSend(^MeshRenderPipelineDescriptor, self, "init")
+}
+
+@(objc_type=MeshRenderPipelineDescriptor, objc_name="binaryArchives")
+MeshRenderPipelineDescriptor_binaryArchives :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) -> ^NS.Array {
+	return msgSend(^NS.Array, self, "binaryArchives")
+}
+@(objc_type=MeshRenderPipelineDescriptor, objc_name="setBinaryArchives")
+MeshRenderPipelineDescriptor_setBinaryArchives :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor, binaryArchives: ^NS.Array) {
+	msgSend(nil, self, "setBinaryArchives:", binaryArchives)
+}
+
+@(objc_type=MeshRenderPipelineDescriptor, objc_name="colorAttachments")
+MeshRenderPipelineDescriptor_colorAttachments :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) -> ^RenderPipelineColorAttachmentDescriptorArray {
+	return msgSend(^RenderPipelineColorAttachmentDescriptorArray, self, "colorAttachments")
+}
+
+@(objc_type=MeshRenderPipelineDescriptor, objc_name="depthAttachmentPixelFormat")
+MeshRenderPipelineDescriptor_depthAttachmentPixelFormat :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) -> PixelFormat {
+	return msgSend(PixelFormat, self, "depthAttachmentPixelFormat")
+}
+@(objc_type=MeshRenderPipelineDescriptor, objc_name="setDepthAttachmentPixelFormat")
+MeshRenderPipelineDescriptor_setDepthAttachmentPixelFormat :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor, depthAttachmentPixelFormat: PixelFormat) {
+	msgSend(nil, self, "setDepthAttachmentPixelFormat:", depthAttachmentPixelFormat)
+}
+
+@(objc_type=MeshRenderPipelineDescriptor, objc_name="fragmentBuffers")
+MeshRenderPipelineDescriptor_fragmentBuffers :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) -> ^PipelineBufferDescriptorArray {
+	return msgSend(^PipelineBufferDescriptorArray, self, "fragmentBuffers")
+}
+
+@(objc_type=MeshRenderPipelineDescriptor, objc_name="fragmentFunction")
+MeshRenderPipelineDescriptor_fragmentFunction :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) -> ^Function {
+	return msgSend(^Function, self, "fragmentFunction")
+}
+@(objc_type=MeshRenderPipelineDescriptor, objc_name="setFragmentFunction")
+MeshRenderPipelineDescriptor_setFragmentFunction :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor, fragmentFunction: ^Function) {
+	msgSend(nil, self, "setFragmentFunction:", fragmentFunction)
+}
+
+@(objc_type=MeshRenderPipelineDescriptor, objc_name="fragmentLinkedFunctions")
+MeshRenderPipelineDescriptor_fragmentLinkedFunctions :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) -> ^LinkedFunctions {
+	return msgSend(^LinkedFunctions, self, "fragmentLinkedFunctions")
+}
+@(objc_type=MeshRenderPipelineDescriptor, objc_name="setFragmentLinkedFunctions")
+MeshRenderPipelineDescriptor_setFragmentLinkedFunctions :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor, fragmentLinkedFunctions: ^LinkedFunctions) {
+	msgSend(nil, self, "setFragmentLinkedFunctions:", fragmentLinkedFunctions)
+}
+
+@(objc_type=MeshRenderPipelineDescriptor, objc_name="alphaToCoverageEnabled")
+MeshRenderPipelineDescriptor_alphaToCoverageEnabled :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) -> BOOL {
+	return msgSend(BOOL, self, "alphaToCoverageEnabled")
+}
+@(objc_type=MeshRenderPipelineDescriptor, objc_name="isAlphaToCoverageEnabled")
+MeshRenderPipelineDescriptor_isAlphaToCoverageEnabled :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) -> BOOL {
+	return msgSend(BOOL, self, "isAlphaToCoverageEnabled")
+}
+@(objc_type=MeshRenderPipelineDescriptor, objc_name="setAlphaToCoverageEnabled")
+MeshRenderPipelineDescriptor_setAlphaToCoverageEnabled :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor, alphaToCoverageEnabled: BOOL) {
+	msgSend(nil, self, "setAlphaToCoverageEnabled:", alphaToCoverageEnabled)
+}
+
+@(objc_type=MeshRenderPipelineDescriptor, objc_name="alphaToOneEnabled")
+MeshRenderPipelineDescriptor_alphaToOneEnabled :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) -> BOOL {
+	return msgSend(BOOL, self, "alphaToOneEnabled")
+}
+@(objc_type=MeshRenderPipelineDescriptor, objc_name="isAlphaToOneEnabled")
+MeshRenderPipelineDescriptor_isAlphaToOneEnabled :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) -> BOOL {
+	return msgSend(BOOL, self, "isAlphaToOneEnabled")
+}
+@(objc_type=MeshRenderPipelineDescriptor, objc_name="setAlphaToOneEnabled")
+MeshRenderPipelineDescriptor_setAlphaToOneEnabled :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor, alphaToOneEnabled: BOOL) {
+	msgSend(nil, self, "setAlphaToOneEnabled:", alphaToOneEnabled)
+}
+
+@(objc_type=MeshRenderPipelineDescriptor, objc_name="rasterizationEnabled")
+MeshRenderPipelineDescriptor_rasterizationEnabled :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) -> BOOL {
+	return msgSend(BOOL, self, "rasterizationEnabled")
+}
+@(objc_type=MeshRenderPipelineDescriptor, objc_name="isRasterizationEnabled")
+MeshRenderPipelineDescriptor_isRasterizationEnabled :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) -> BOOL {
+	return msgSend(BOOL, self, "isRasterizationEnabled")
 }
-@(objc_type=RenderPipelineDescriptor, objc_name="maxTotalThreadsPerMeshThreadgroup")
-RenderPipelineDescriptor_maxTotalThreadsPerMeshThreadgroup :: #force_inline proc "c" (self: ^RenderPipelineDescriptor) -> NS.UInteger {
+@(objc_type=MeshRenderPipelineDescriptor, objc_name="setRasterizationEnabled")
+MeshRenderPipelineDescriptor_setRasterizationEnabled :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor, rasterizationEnabled: BOOL) {
+	msgSend(nil, self, "setRasterizationEnabled:", rasterizationEnabled)
+}
+
+@(objc_type=MeshRenderPipelineDescriptor, objc_name="label")
+MeshRenderPipelineDescriptor_label :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) -> ^NS.String {
+	return msgSend(^NS.String, self, "label")
+}
+
+@(objc_type=MeshRenderPipelineDescriptor, objc_name="maxTotalThreadgroupsPerMeshGrid")
+MeshRenderPipelineDescriptor_maxTotalThreadgroupsPerMeshGrid :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) -> NS.UInteger {
+	return msgSend(NS.UInteger, self, "maxTotalThreadgroupsPerMeshGrid")
+}
+@(objc_type=MeshRenderPipelineDescriptor, objc_name="setMaxTotalThreadgroupsPerMeshGrid")
+MeshRenderPipelineDescriptor_setMaxTotalThreadgroupsPerMeshGrid :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor, maxTotalThreadgroupsPerMeshGrid: NS.UInteger) {
+	msgSend(nil, self, "setMaxTotalThreadgroupsPerMeshGrid:", maxTotalThreadgroupsPerMeshGrid)
+}
+
+@(objc_type=MeshRenderPipelineDescriptor, objc_name="maxTotalThreadsPerMeshThreadgroup")
+MeshRenderPipelineDescriptor_maxTotalThreadsPerMeshThreadgroup :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) -> NS.UInteger {
 	return msgSend(NS.UInteger, self, "maxTotalThreadsPerMeshThreadgroup")
 }
-@(objc_type=RenderPipelineDescriptor, objc_name="setMaxTotalThreadsPerMeshThreadgroup")
-RenderPipelineDescriptor_setMaxTotalThreadsPerMeshThreadgroup :: #force_inline proc "c" (self: ^RenderPipelineDescriptor, maxTotalThreadsPerMeshThreadgroup: NS.UInteger) {
+@(objc_type=MeshRenderPipelineDescriptor, objc_name="setMaxTotalThreadsPerMeshThreadgroup")
+MeshRenderPipelineDescriptor_setMaxTotalThreadsPerMeshThreadgroup :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor, maxTotalThreadsPerMeshThreadgroup: NS.UInteger) {
 	msgSend(nil, self, "setMaxTotalThreadsPerMeshThreadgroup:", maxTotalThreadsPerMeshThreadgroup)
 }
-@(objc_type=RenderPipelineDescriptor, objc_name="objectThreadgroupSizeIsMultipleOfThreadExecutionWidth")
-RenderPipelineDescriptor_objectThreadgroupSizeIsMultipleOfThreadExecutionWidth :: #force_inline proc "c" (self: ^RenderPipelineDescriptor) -> NS.UInteger {
-	return msgSend(NS.UInteger, self, "objectThreadgroupSizeIsMultipleOfThreadExecutionWidth")
+
+@(objc_type=MeshRenderPipelineDescriptor, objc_name="maxTotalThreadsPerObjectThreadgroup")
+MeshRenderPipelineDescriptor_maxTotalThreadsPerObjectThreadgroup :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) -> NS.UInteger {
+	return msgSend(NS.UInteger, self, "maxTotalThreadsPerObjectThreadgroup")
 }
-@(objc_type=RenderPipelineDescriptor, objc_name="setObjectThreadgroupSizeIsMultipleOfThreadExecutionWidth")
-RenderPipelineDescriptor_setObjectThreadgroupSizeIsMultipleOfThreadExecutionWidth :: #force_inline proc "c" (self: ^RenderPipelineDescriptor, objectThreadgroupSizeIsMultipleOfThreadExecutionWidth: NS.UInteger) {
-	msgSend(nil, self, "setObjectThreadgroupSizeIsMultipleOfThreadExecutionWidth:", objectThreadgroupSizeIsMultipleOfThreadExecutionWidth)
+@(objc_type=MeshRenderPipelineDescriptor, objc_name="setMaxTotalThreadsPerObjectThreadgroup")
+MeshRenderPipelineDescriptor_setMaxTotalThreadsPerObjectThreadgroup :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor, maxTotalThreadsPerObjectThreadgroup: NS.UInteger) {
+	msgSend(nil, self, "setMaxTotalThreadsPerObjectThreadgroup:", maxTotalThreadsPerObjectThreadgroup)
 }
 
-@(objc_type=RenderPipelineDescriptor, objc_name="meshThreadgroupSizeIsMultipleOfThreadExecutionWidth")
-RenderPipelineDescriptor_meshThreadgroupSizeIsMultipleOfThreadExecutionWidth :: #force_inline proc "c" (self: ^RenderPipelineDescriptor) -> BOOL {
+@(objc_type=MeshRenderPipelineDescriptor, objc_name="maxVertexAmplificationCount")
+MeshRenderPipelineDescriptor_maxVertexAmplificationCount :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) -> NS.UInteger {
+	return msgSend(NS.UInteger, self, "maxVertexAmplificationCount")
+}
+@(objc_type=MeshRenderPipelineDescriptor, objc_name="setMaxVertexAmplificationCount")
+MeshRenderPipelineDescriptor_setMaxVertexAmplificationCount :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor, maxVertexAmplificationCount: NS.UInteger) {
+	msgSend(nil, self, "setMaxVertexAmplificationCount:", maxVertexAmplificationCount)
+}
+
+@(objc_type=MeshRenderPipelineDescriptor, objc_name="meshBuffers")
+MeshRenderPipelineDescriptor_meshBuffers :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) -> ^PipelineBufferDescriptorArray {
+	return msgSend(^PipelineBufferDescriptorArray, self, "meshBuffers")
+}
+
+@(objc_type=MeshRenderPipelineDescriptor, objc_name="meshFunction")
+MeshRenderPipelineDescriptor_meshFunction :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) -> ^Function {
+	return msgSend(^Function, self, "meshFunction")
+}
+@(objc_type=MeshRenderPipelineDescriptor, objc_name="setMeshFunction")
+MeshRenderPipelineDescriptor_setMeshFunction :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor, meshFunction: ^Function) {
+	msgSend(nil, self, "setMeshFunction:", meshFunction)
+}
+
+@(objc_type=MeshRenderPipelineDescriptor, objc_name="meshLinkedFunctions")
+MeshRenderPipelineDescriptor_meshLinkedFunctions :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) -> ^LinkedFunctions {
+	return msgSend(^LinkedFunctions, self, "meshLinkedFunctions")
+}
+@(objc_type=MeshRenderPipelineDescriptor, objc_name="setMeshLinkedFunctions")
+MeshRenderPipelineDescriptor_setMeshLinkedFunctions :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor, meshLinkedFunctions: ^LinkedFunctions) {
+	msgSend(nil, self, "setMeshLinkedFunctions:", meshLinkedFunctions)
+}
+
+@(objc_type=MeshRenderPipelineDescriptor, objc_name="meshThreadgroupSizeIsMultipleOfThreadExecutionWidth")
+MeshRenderPipelineDescriptor_meshThreadgroupSizeIsMultipleOfThreadExecutionWidth :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) -> BOOL {
 	return msgSend(BOOL, self, "meshThreadgroupSizeIsMultipleOfThreadExecutionWidth")
 }
-@(objc_type=RenderPipelineDescriptor, objc_name="setMeshThreadgroupSizeIsMultipleOfThreadExecutionWidth")
-RenderPipelineDescriptor_setMeshThreadgroupSizeIsMultipleOfThreadExecutionWidth :: #force_inline proc "c" (self: ^RenderPipelineDescriptor, meshThreadgroupSizeIsMultipleOfThreadExecutionWidth: BOOL) {
+@(objc_type=MeshRenderPipelineDescriptor, objc_name="setMeshThreadgroupSizeIsMultipleOfThreadExecutionWidth")
+MeshRenderPipelineDescriptor_setMeshThreadgroupSizeIsMultipleOfThreadExecutionWidth :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor, meshThreadgroupSizeIsMultipleOfThreadExecutionWidth: BOOL) {
 	msgSend(nil, self, "setMeshThreadgroupSizeIsMultipleOfThreadExecutionWidth:", meshThreadgroupSizeIsMultipleOfThreadExecutionWidth)
 }
 
+@(objc_type=MeshRenderPipelineDescriptor, objc_name="objectBuffers")
+MeshRenderPipelineDescriptor_objectBuffers :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) -> ^PipelineBufferDescriptorArray {
+	return msgSend(^PipelineBufferDescriptorArray, self, "objectBuffers")
+}
+
+@(objc_type=MeshRenderPipelineDescriptor, objc_name="objectFunction")
+MeshRenderPipelineDescriptor_objectFunction :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) -> ^Function {
+	return msgSend(^Function, self, "objectFunction")
+}
+@(objc_type=MeshRenderPipelineDescriptor, objc_name="setObjectFunction")
+MeshRenderPipelineDescriptor_setObjectFunction :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor, objectFunction: ^Function) {
+	msgSend(nil, self, "setObjectFunction:", objectFunction)
+}
+
+@(objc_type=MeshRenderPipelineDescriptor, objc_name="objectLinkedFunctions")
+MeshRenderPipelineDescriptor_objectLinkedFunctions :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) -> ^LinkedFunctions {
+	return msgSend(^LinkedFunctions, self, "objectLinkedFunctions")
+}
+@(objc_type=MeshRenderPipelineDescriptor, objc_name="setObjectLinkedFunctions")
+MeshRenderPipelineDescriptor_setObjectLinkedFunctions :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor, objectLinkedFunctions: ^LinkedFunctions) {
+	msgSend(nil, self, "setObjectLinkedFunctions:", objectLinkedFunctions)
+}
+
+@(objc_type=MeshRenderPipelineDescriptor, objc_name="objectThreadgroupSizeIsMultipleOfThreadExecutionWidth")
+MeshRenderPipelineDescriptor_objectThreadgroupSizeIsMultipleOfThreadExecutionWidth :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) -> BOOL {
+	return msgSend(BOOL, self, "objectThreadgroupSizeIsMultipleOfThreadExecutionWidth")
+}
+@(objc_type=MeshRenderPipelineDescriptor, objc_name="setObjectThreadgroupSizeIsMultipleOfThreadExecutionWidth")
+MeshRenderPipelineDescriptor_setObjectThreadgroupSizeIsMultipleOfThreadExecutionWidth :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor, objectThreadgroupSizeIsMultipleOfThreadExecutionWidth: BOOL) {
+	msgSend(nil, self, "setObjectThreadgroupSizeIsMultipleOfThreadExecutionWidth:", objectThreadgroupSizeIsMultipleOfThreadExecutionWidth)
+}
 
-@(objc_type=RenderPipelineDescriptor, objc_name="payloadMemoryLength")
-RenderPipelineDescriptor_payloadMemoryLength :: #force_inline proc "c" (self: ^RenderPipelineDescriptor) -> NS.UInteger {
+@(objc_type=MeshRenderPipelineDescriptor, objc_name="payloadMemoryLength")
+MeshRenderPipelineDescriptor_payloadMemoryLength :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) -> NS.UInteger {
 	return msgSend(NS.UInteger, self, "payloadMemoryLength")
 }
-@(objc_type=RenderPipelineDescriptor, objc_name="setPayloadMemoryLength")
-RenderPipelineDescriptor_setPayloadMemoryLength :: #force_inline proc "c" (self: ^RenderPipelineDescriptor, payloadMemoryLength: NS.UInteger) {
+@(objc_type=MeshRenderPipelineDescriptor, objc_name="setPayloadMemoryLength")
+MeshRenderPipelineDescriptor_setPayloadMemoryLength :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor, payloadMemoryLength: NS.UInteger) {
 	msgSend(nil, self, "setPayloadMemoryLength:", payloadMemoryLength)
 }
-@(objc_type=RenderPipelineDescriptor, objc_name="maxTotalThreadgroupsPerMeshGrid")
-RenderPipelineDescriptor_maxTotalThreadgroupsPerMeshGrid :: #force_inline proc "c" (self: ^RenderPipelineDescriptor) -> NS.UInteger {
-	return msgSend(NS.UInteger, self, "maxTotalThreadgroupsPerMeshGrid")
+
+@(objc_type=MeshRenderPipelineDescriptor, objc_name="rasterSampleCount")
+MeshRenderPipelineDescriptor_rasterSampleCount :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) -> NS.UInteger {
+	return msgSend(NS.UInteger, self, "rasterSampleCount")
 }
-@(objc_type=RenderPipelineDescriptor, objc_name="setMaxTotalThreadgroupsPerMeshGrid")
-RenderPipelineDescriptor_setMaxTotalThreadgroupsPerMeshGrid :: #force_inline proc "c" (self: ^RenderPipelineDescriptor, maxTotalThreadgroupsPerMeshGrid: NS.UInteger) {
-	msgSend(nil, self, "setMaxTotalThreadgroupsPerMeshGrid:", maxTotalThreadgroupsPerMeshGrid)
+@(objc_type=MeshRenderPipelineDescriptor, objc_name="setRasterSampleCount")
+MeshRenderPipelineDescriptor_setRasterSampleCount :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor, rasterSampleCount: NS.UInteger) {
+	msgSend(nil, self, "setRasterSampleCount:", rasterSampleCount)
 }
 
-@(objc_type=RenderPipelineDescriptor, objc_name="objectBuffers")
-RenderPipelineDescriptor_objectBuffers :: #force_inline proc "c" (self: ^RenderPipelineDescriptor) -> ^PipelineBufferDescriptorArray {
-	return msgSend(^PipelineBufferDescriptorArray, self, "objectBuffers")
+@(objc_type=MeshRenderPipelineDescriptor, objc_name="shaderValidation")
+MeshRenderPipelineDescriptor_shaderValidation :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) -> ShaderValidation {
+	return msgSend(ShaderValidation, self, "shaderValidation")
 }
-@(objc_type=RenderPipelineDescriptor, objc_name="meshBuffers")
-RenderPipelineDescriptor_meshBuffers :: #force_inline proc "c" (self: ^RenderPipelineDescriptor) -> ^PipelineBufferDescriptorArray {
-	return msgSend(^PipelineBufferDescriptorArray, self, "meshBuffers")
+@(objc_type=MeshRenderPipelineDescriptor, objc_name="setShaderValidation")
+MeshRenderPipelineDescriptor_setShaderValidation :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor, shaderValidation: ShaderValidation) {
+	msgSend(nil, self, "setShaderValidation:", shaderValidation)
 }
 
+@(objc_type=MeshRenderPipelineDescriptor, objc_name="stencilAttachmentPixelFormat")
+MeshRenderPipelineDescriptor_stencilAttachmentPixelFormat :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) -> PixelFormat {
+	return msgSend(PixelFormat, self, "stencilAttachmentPixelFormat")
+}
+@(objc_type=MeshRenderPipelineDescriptor, objc_name="setStencilAttachmentPixelFormat")
+MeshRenderPipelineDescriptor_setStencilAttachmentPixelFormat :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor, stencilAttachmentPixelFormat: PixelFormat) {
+	msgSend(nil, self, "setStencilAttachmentPixelFormat:", stencilAttachmentPixelFormat)
+}
 
-
-@(objc_type=RenderPipelineDescriptor, objc_name="alphaToCoverageEnabled")
-RenderPipelineDescriptor_alphaToCoverageEnabled :: #force_inline proc "c" (self: ^RenderPipelineDescriptor) -> BOOL {
-	return msgSend(BOOL, self, "alphaToCoverageEnabled")
+@(objc_type=MeshRenderPipelineDescriptor, objc_name="supportIndirectCommandBuffers")
+MeshRenderPipelineDescriptor_supportIndirectCommandBuffers :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) -> BOOL {
+	return msgSend(BOOL, self, "supportIndirectCommandBuffers")
 }
-@(objc_type=RenderPipelineDescriptor, objc_name="alphaToOneEnabled")
-RenderPipelineDescriptor_alphaToOneEnabled :: #force_inline proc "c" (self: ^RenderPipelineDescriptor) -> BOOL {
-	return msgSend(BOOL, self, "alphaToOneEnabled")
+@(objc_type=MeshRenderPipelineDescriptor, objc_name="setSupportIndirectCommandBuffers")
+MeshRenderPipelineDescriptor_setSupportIndirectCommandBuffers :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor, supportIndirectCommandBuffers: BOOL) {
+	msgSend(nil, self, "setSupportIndirectCommandBuffers:", supportIndirectCommandBuffers)
 }
 
-@(objc_type=RenderPipelineDescriptor, objc_name="rasterizationEnabled")
-RenderPipelineDescriptor_rasterizationEnabled :: #force_inline proc "c" (self: ^RenderPipelineDescriptor) -> BOOL {
-	return msgSend(BOOL, self, "rasterizationEnabled")
+@(objc_type=MeshRenderPipelineDescriptor, objc_name="reset")
+MeshRenderPipelineDescriptor_reset :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) {
+	msgSend(nil, self, "reset")
 }
 
 
@@ -5702,14 +5904,13 @@ Device_supportsVertexAmplificationCount :: #force_inline proc "c" (self: ^Device
 
 
 @(objc_type=Device, objc_name="newRenderPipelineStateWithMeshDescriptor")
-Device_newRenderPipelineStateWithMeshDescriptor :: #force_inline proc "contextless" (self: ^Device, options: PipelineOption, reflection: ^AutoreleasedRenderPipelineReflection) -> (state: ^RenderPipelineState, error: ^NS.Error) {
-	state = msgSend(^RenderPipelineState, self, "newRenderPipelineStateWithMeshDescriptor:options:reflection:error:", options, reflection, &error)
+Device_newRenderPipelineStateWithMeshDescriptor :: #force_inline proc "c" (self: ^Device, descriptor: ^MeshRenderPipelineDescriptor, options: PipelineOption, reflection: ^AutoreleasedRenderPipelineReflection) -> (state: ^RenderPipelineState, error: ^NS.Error) {
+	state = msgSend(^RenderPipelineState, self, "newRenderPipelineStateWithMeshDescriptor:options:reflection:error:", descriptor, options, reflection, &error)
 	return
 }
 @(objc_type=Device, objc_name="newRenderPipelineStateWithMeshDescriptorAndCompletionHandler")
-Device_newRenderPipelineStateWithMeshDescriptorAndCompletionHandler :: #force_inline proc "c" (self: ^Device, options: PipelineOption, completionHandler: ^NewRenderPipelineStateWithReflectionCompletionHandler) -> (state: ^RenderPipelineState) {
-	state = msgSend(^RenderPipelineState, self, "newRenderPipelineStateWithMeshDescriptor:options:completionHandler:", options, completionHandler)
-	return
+Device_newRenderPipelineStateWithMeshDescriptorAndCompletionHandler :: #force_inline proc "c" (self: ^Device, descriptor: ^MeshRenderPipelineDescriptor, options: PipelineOption, completionHandler: NewRenderPipelineStateWithReflectionCompletionHandler) {
+	msgSend(nil, self, "newRenderPipelineStateWithMeshDescriptor:options:completionHandler:", descriptor, options, completionHandler)
 }
 
 @(objc_type=Device, objc_name="newIOHandle")

+ 6 - 0
vendor/darwin/Metal/MetalEnums.odin

@@ -1050,3 +1050,9 @@ VertexStepFunction :: enum NS.UInteger {
 	PerPatch             = 3,
 	PerPatchControlPoint = 4,
 }
+
+ShaderValidation :: enum NS.UInteger {
+	Default  = 0,
+	Enabled  = 1,
+	Disabled = 2,
+}

+ 1 - 1
vendor/directx/d3d11/d3d11.odin

@@ -19,7 +19,7 @@ BOOL    :: dxgi.BOOL
 UINT    :: dxgi.UINT
 INT     :: dxgi.INT
 
-LPCWSTR  :: [^]u16
+LPCWSTR  :: windows.LPCWSTR
 
 RECT :: dxgi.RECT
 SIZE :: dxgi.SIZE

+ 20 - 18
vendor/directx/d3d12/d3d12.odin

@@ -22,6 +22,8 @@ BOOL    :: dxgi.BOOL
 
 RECT :: dxgi.RECT
 
+LPCWSTR :: win32.LPCWSTR
+
 IModuleInstance :: d3d_compiler.ID3D11ModuleInstance
 IBlob           :: d3d_compiler.ID3DBlob
 IModule         :: d3d_compiler.ID3D11Module
@@ -680,7 +682,7 @@ IObject_VTable :: struct {
 	GetPrivateData:          proc "system" (this: ^IObject, guid: ^GUID, pDataSize: ^u32, pData: rawptr) -> HRESULT,
 	SetPrivateData:          proc "system" (this: ^IObject, guid: ^GUID, DataSize: u32, pData: rawptr) -> HRESULT,
 	SetPrivateDataInterface: proc "system" (this: ^IObject, guid: ^GUID, pData: ^IUnknown) -> HRESULT,
-	SetName:                 proc "system" (this: ^IObject, Name: [^]u16) -> HRESULT,
+	SetName:                 proc "system" (this: ^IObject, Name: LPCWSTR) -> HRESULT,
 }
 
 
@@ -2714,9 +2716,9 @@ IDevice_VTable :: struct {
 	CreateHeap:                       proc "system" (this: ^IDevice, pDesc: ^HEAP_DESC, riid: ^IID, ppvHeap: ^rawptr) -> HRESULT,
 	CreatePlacedResource:             proc "system" (this: ^IDevice, pHeap: ^IHeap, HeapOffset: u64, pDesc: ^RESOURCE_DESC, InitialState: RESOURCE_STATES, pOptimizedClearValue: ^CLEAR_VALUE, riid: ^IID, ppvResource: ^rawptr) -> HRESULT,
 	CreateReservedResource:           proc "system" (this: ^IDevice, pDesc: ^RESOURCE_DESC, InitialState: RESOURCE_STATES, pOptimizedClearValue: ^CLEAR_VALUE, riid: ^IID, ppvResource: ^rawptr) -> HRESULT,
-	CreateSharedHandle:               proc "system" (this: ^IDevice, pObject: ^IDeviceChild, pAttributes: ^win32.SECURITY_ATTRIBUTES, Access: u32, Name: [^]u16, pHandle: ^HANDLE) -> HRESULT,
+	CreateSharedHandle:               proc "system" (this: ^IDevice, pObject: ^IDeviceChild, pAttributes: ^win32.SECURITY_ATTRIBUTES, Access: u32, Name: LPCWSTR, pHandle: ^HANDLE) -> HRESULT,
 	OpenSharedHandle:                 proc "system" (this: ^IDevice, NTHandle: HANDLE, riid: ^IID, ppvObj: ^rawptr) -> HRESULT,
-	OpenSharedHandleByName:           proc "system" (this: ^IDevice, Name: [^]u16, Access: u32, pNTHandle: ^HANDLE) -> HRESULT,
+	OpenSharedHandleByName:           proc "system" (this: ^IDevice, Name: LPCWSTR, Access: u32, pNTHandle: ^HANDLE) -> HRESULT,
 	MakeResident:                     proc "system" (this: ^IDevice, NumObjects: u32, ppObjects: [^]^IPageable) -> HRESULT,
 	Evict:                            proc "system" (this: ^IDevice, NumObjects: u32, ppObjects: [^]^IPageable) -> HRESULT,
 	CreateFence:                      proc "system" (this: ^IDevice, InitialValue: u64, Flags: FENCE_FLAGS, riid: ^IID, ppFence: ^rawptr) -> HRESULT,
@@ -2738,9 +2740,9 @@ IPipelineLibrary :: struct #raw_union {
 }
 IPipelineLibrary_VTable :: struct {
 	using id3d12devicechild_vtable: IDeviceChild_VTable,
-	StorePipeline:        proc "system" (this: ^IPipelineLibrary, pName: [^]u16, pPipeline: ^IPipelineState) -> HRESULT,
-	LoadGraphicsPipeline: proc "system" (this: ^IPipelineLibrary, pName: [^]u16, pDesc: ^GRAPHICS_PIPELINE_STATE_DESC, riid: ^IID, ppPipelineState: ^rawptr) -> HRESULT,
-	LoadComputePipeline:  proc "system" (this: ^IPipelineLibrary, pName: [^]u16, pDesc: ^COMPUTE_PIPELINE_STATE_DESC, riid: ^IID, ppPipelineState: ^rawptr) -> HRESULT,
+	StorePipeline:        proc "system" (this: ^IPipelineLibrary, pName: LPCWSTR, pPipeline: ^IPipelineState) -> HRESULT,
+	LoadGraphicsPipeline: proc "system" (this: ^IPipelineLibrary, pName: LPCWSTR, pDesc: ^GRAPHICS_PIPELINE_STATE_DESC, riid: ^IID, ppPipelineState: ^rawptr) -> HRESULT,
+	LoadComputePipeline:  proc "system" (this: ^IPipelineLibrary, pName: LPCWSTR, pDesc: ^COMPUTE_PIPELINE_STATE_DESC, riid: ^IID, ppPipelineState: ^rawptr) -> HRESULT,
 	GetSerializedSize:    proc "system" (this: ^IPipelineLibrary) -> SIZE_T,
 	Serialize:            proc "system" (this: ^IPipelineLibrary, pData: rawptr, DataSizeInBytes: SIZE_T) -> HRESULT,
 }
@@ -2754,7 +2756,7 @@ IPipelineLibrary1 :: struct #raw_union {
 }
 IPipelineLibrary1_VTable :: struct {
 	using id3d12pipelinelibrary_vtable: IPipelineLibrary_VTable,
-	LoadPipeline: proc "system" (this: ^IPipelineLibrary1, pName: [^]u16, pDesc: ^PIPELINE_STATE_STREAM_DESC, riid: ^IID, ppPipelineState: ^rawptr) -> HRESULT,
+	LoadPipeline: proc "system" (this: ^IPipelineLibrary1, pName: LPCWSTR, pDesc: ^PIPELINE_STATE_STREAM_DESC, riid: ^IID, ppPipelineState: ^rawptr) -> HRESULT,
 }
 
 MULTIPLE_FENCE_WAIT_FLAGS :: distinct bit_set[MULTIPLE_FENCE_WAIT_FLAG; u32]
@@ -2961,7 +2963,7 @@ META_COMMAND_PARAMETER_STAGE :: enum i32 {
 }
 
 META_COMMAND_PARAMETER_DESC :: struct {
-	Name:                  [^]u16,
+	Name:                  LPCWSTR,
 	Type:                  META_COMMAND_PARAMETER_TYPE,
 	Flags:                 META_COMMAND_PARAMETER_FLAGS,
 	RequiredResourceState: RESOURCE_STATES,
@@ -2991,7 +2993,7 @@ GRAPHICS_STATES :: enum i32 {
 
 META_COMMAND_DESC :: struct {
 	Id:                       GUID,
-	Name:                     [^]u16,
+	Name:                     LPCWSTR,
 	InitializationDirtyState: GRAPHICS_STATES,
 	ExecutionDirtyState:      GRAPHICS_STATES,
 }
@@ -3012,8 +3014,8 @@ IStateObjectProperties :: struct #raw_union {
 }
 IStateObjectProperties_VTable :: struct {
 	using iunknown_vtable: IUnknown_VTable,
-	GetShaderIdentifier:  proc "system" (this: ^IStateObjectProperties, pExportName: [^]u16) -> rawptr,
-	GetShaderStackSize:   proc "system" (this: ^IStateObjectProperties, pExportName: [^]u16) -> u64,
+	GetShaderIdentifier:  proc "system" (this: ^IStateObjectProperties, pExportName: LPCWSTR) -> rawptr,
+	GetShaderStackSize:   proc "system" (this: ^IStateObjectProperties, pExportName: LPCWSTR) -> u64,
 	GetPipelineStackSize: proc "system" (this: ^IStateObjectProperties) -> u64,
 	SetPipelineStackSize: proc "system" (this: ^IStateObjectProperties, PipelineStackSizeInBytes: u64),
 }
@@ -3067,8 +3069,8 @@ EXPORT_FLAG :: enum u32 {
 }
 
 EXPORT_DESC :: struct {
-	Name:           [^]u16,
-	ExportToRename: [^]u16,
+	Name:           LPCWSTR,
+	ExportToRename: LPCWSTR,
 	Flags:          EXPORT_FLAGS,
 }
 
@@ -3414,9 +3416,9 @@ AUTO_BREADCRUMB_OP :: enum i32 {
 
 AUTO_BREADCRUMB_NODE :: struct {
 	pCommandListDebugNameA:  cstring,
-	pCommandListDebugNameW:  [^]u16,
+	pCommandListDebugNameW:  LPCWSTR,
 	pCommandQueueDebugNameA: cstring,
-	pCommandQueueDebugNameW: [^]u16,
+	pCommandQueueDebugNameW: LPCWSTR,
 	pCommandList:            ^IGraphicsCommandList,
 	pCommandQueue:           ^ICommandQueue,
 	BreadcrumbCount:         u32,
@@ -3427,14 +3429,14 @@ AUTO_BREADCRUMB_NODE :: struct {
 
 DRED_BREADCRUMB_CONTEXT :: struct {
 	BreadcrumbIndex: u32,
-	pContextString:  [^]u16,
+	pContextString:  LPCWSTR,
 }
 
 AUTO_BREADCRUMB_NODE1 :: struct {
 	pCommandListDebugNameA:  cstring,
-	pCommandListDebugNameW:  [^]u16,
+	pCommandListDebugNameW:  LPCWSTR,
 	pCommandQueueDebugNameA: cstring,
-	pCommandQueueDebugNameW: [^]u16,
+	pCommandQueueDebugNameW: LPCWSTR,
 	pCommandList:            ^IGraphicsCommandList,
 	pCommandQueue:           ^ICommandQueue,
 	BreadcrumbCount:         u32,