From 3d7d3471924574beee08fc304a6daf6a8707d723 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 20 Jan 2022 19:56:05 +0000 Subject: Convert `ODIN_OS` and `ODIN_ARCH` to use enums rather than use strings --- src/checker.cpp | 37 ++++++++++++++++++++++++++++++++++--- 1 file changed, 34 insertions(+), 3 deletions(-) (limited to 'src/checker.cpp') diff --git a/src/checker.cpp b/src/checker.cpp index 63a697072..055d0d356 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -856,11 +856,42 @@ void init_universal(void) { add_global_bool_constant("false", false); // TODO(bill): Set through flags in the compiler - add_global_string_constant("ODIN_OS", bc->ODIN_OS); - add_global_string_constant("ODIN_ARCH", bc->ODIN_ARCH); add_global_string_constant("ODIN_VENDOR", bc->ODIN_VENDOR); add_global_string_constant("ODIN_VERSION", bc->ODIN_VERSION); add_global_string_constant("ODIN_ROOT", bc->ODIN_ROOT); + + { + GlobalEnumValue values[TargetOs_COUNT] = { + {"Unknown", TargetOs_Invalid}, + {"Windows", TargetOs_windows}, + {"Darwin", TargetOs_darwin}, + {"Linux", TargetOs_linux}, + {"Essence", TargetOs_essence}, + {"FreeBSD", TargetOs_freebsd}, + {"WASI", TargetOs_wasi}, + {"JS", TargetOs_js}, + {"Freestanding", TargetOs_freestanding}, + }; + + auto fields = add_global_enum_type(str_lit("Odin_OS_Type"), values, gb_count_of(values)); + add_global_enum_constant(fields, "ODIN_OS", bc->metrics.os); + add_global_string_constant("ODIN_OS_STRING", target_os_names[bc->metrics.os]); + } + + { + GlobalEnumValue values[TargetArch_COUNT] = { + {"Unknown", TargetArch_Invalid}, + {"amd64", TargetArch_amd64}, + {"i386", TargetArch_i386}, + {"arm64", TargetArch_arm64}, + {"wasm32", TargetArch_wasm32}, + {"wasm64", TargetArch_wasm64}, + }; + + auto fields = add_global_enum_type(str_lit("Odin_Arch_Type"), values, gb_count_of(values)); + add_global_enum_constant(fields, "ODIN_ARCH", bc->metrics.arch); + add_global_string_constant("ODIN_ARCH_STRING", target_arch_names[bc->metrics.arch]); + } { GlobalEnumValue values[BuildMode_COUNT] = { @@ -875,7 +906,6 @@ void init_universal(void) { add_global_enum_constant(fields, "ODIN_BUILD_MODE", bc->build_mode); } - add_global_string_constant("ODIN_ENDIAN_STRING", target_endian_names[target_endians[bc->metrics.arch]]); { GlobalEnumValue values[TargetEndian_COUNT] = { {"Unknown", TargetEndian_Invalid}, @@ -886,6 +916,7 @@ void init_universal(void) { auto fields = add_global_enum_type(str_lit("Odin_Endian_Type"), values, gb_count_of(values)); add_global_enum_constant(fields, "ODIN_ENDIAN", target_endians[bc->metrics.arch]); + add_global_string_constant("ODIN_ENDIAN_STRING", target_endian_names[target_endians[bc->metrics.arch]]); } -- cgit v1.2.3 From 42ab882db4a6d5765c68021ade010b468ff4531e Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 24 Jan 2022 15:56:26 +0000 Subject: Remove debug code --- src/check_expr.cpp | 1 - src/checker.cpp | 3 --- 2 files changed, 4 deletions(-) (limited to 'src/checker.cpp') diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 81f69055a..1742ef2d8 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -3419,7 +3419,6 @@ void convert_untyped_error(CheckerContext *c, Operand *operand, Type *target_typ if (operand->value.kind == ExactValue_String) { String key = operand->value.value_string; if (is_type_string(operand->type) && is_type_enum(target_type)) { - gb_printf_err("HERE!\n"); Type *et = base_type(target_type); check_did_you_mean_type(key, et->Enum.fields, "."); } diff --git a/src/checker.cpp b/src/checker.cpp index 55a3892e5..b81d9987b 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -1618,9 +1618,6 @@ void add_type_info_type_internal(CheckerContext *c, Type *t) { // NOTE(bill): map entries grow linearly and in order ti_index = c->info->type_info_types.count; array_add(&c->info->type_info_types, t); - if (t->kind == Type_Named && t->Named.name == "A") { - gb_printf_err("HERE!\n"); - } } map_set(&c->checker->info.type_info_map, t, ti_index); -- cgit v1.2.3 From f6a087775e0a7baf97bce7b1ebb59b223b10d047 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 25 Jan 2022 12:39:06 +0000 Subject: Disable early return from `check_proc_info` --- src/checker.cpp | 13 +++++++------ src/llvm_backend_proc.cpp | 2 +- 2 files changed, 8 insertions(+), 7 deletions(-) (limited to 'src/checker.cpp') diff --git a/src/checker.cpp b/src/checker.cpp index b81d9987b..9be64e369 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -4855,12 +4855,13 @@ bool check_proc_info(Checker *c, ProcInfo *pi, UntypedExprInfoMap *untyped, Proc return false; } - if (pt->is_polymorphic && pt->is_poly_specialized) { - if ((e->flags & EntityFlag_Used) == 0) { - // NOTE(bill, 2019-08-31): It was never used, don't check - return false; - } - } + // NOTE(bill, 2022-01-25): Appears to be not needed any more + // if (pt->is_polymorphic && pt->is_poly_specialized) { + // if ((e->flags & EntityFlag_Used) == 0) { + // // NOTE(bill, 2019-08-31): It was never used, don't check + // return false; + // } + // } bool bounds_check = (pi->tags & ProcTag_bounds_check) != 0; bool no_bounds_check = (pi->tags & ProcTag_no_bounds_check) != 0; diff --git a/src/llvm_backend_proc.cpp b/src/llvm_backend_proc.cpp index b35c6c304..9f9fe7c7a 100644 --- a/src/llvm_backend_proc.cpp +++ b/src/llvm_backend_proc.cpp @@ -61,7 +61,7 @@ lbProcedure *lb_create_procedure(lbModule *m, Entity *entity, bool ignore_body) GB_ASSERT(entity != nullptr); GB_ASSERT(entity->kind == Entity_Procedure); if (!entity->Procedure.is_foreign) { - GB_ASSERT(entity->flags & EntityFlag_ProcBodyChecked); + GB_ASSERT_MSG(entity->flags & EntityFlag_ProcBodyChecked, "%.*s :: %s", LIT(entity->token.string), type_to_string(entity->type)); } String link_name = {}; -- cgit v1.2.3 From a3e7b2baa1ede7ba328a9ec6b249051347ef4cae Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 25 Jan 2022 12:42:45 +0000 Subject: Revert change --- src/checker.cpp | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'src/checker.cpp') diff --git a/src/checker.cpp b/src/checker.cpp index 9be64e369..b81d9987b 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -4855,13 +4855,12 @@ bool check_proc_info(Checker *c, ProcInfo *pi, UntypedExprInfoMap *untyped, Proc return false; } - // NOTE(bill, 2022-01-25): Appears to be not needed any more - // if (pt->is_polymorphic && pt->is_poly_specialized) { - // if ((e->flags & EntityFlag_Used) == 0) { - // // NOTE(bill, 2019-08-31): It was never used, don't check - // return false; - // } - // } + if (pt->is_polymorphic && pt->is_poly_specialized) { + if ((e->flags & EntityFlag_Used) == 0) { + // NOTE(bill, 2019-08-31): It was never used, don't check + return false; + } + } bool bounds_check = (pi->tags & ProcTag_bounds_check) != 0; bool no_bounds_check = (pi->tags & ProcTag_no_bounds_check) != 0; -- cgit v1.2.3 From 070b4507686570335cb3624ef1ede6f442bd4866 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 26 Jan 2022 17:34:39 +0000 Subject: Add `ODIN_ERROR_POS_STYLE` constant and change `runtime.print_caller_location` based on that constant --- core/runtime/print.odin | 20 +++++++++++++++----- src/build_settings.cpp | 2 ++ src/checker.cpp | 10 ++++++++++ 3 files changed, 27 insertions(+), 5 deletions(-) (limited to 'src/checker.cpp') diff --git a/core/runtime/print.odin b/core/runtime/print.odin index 8a14eba08..8c0b65864 100644 --- a/core/runtime/print.odin +++ b/core/runtime/print.odin @@ -143,11 +143,21 @@ print_int :: proc "contextless" (x: int) { print_i64(i64(x)) } print_caller_location :: proc "contextless" (using loc: Source_Code_Location) { print_string(file_path) - print_byte('(') - print_u64(u64(line)) - print_byte(':') - print_u64(u64(column)) - print_byte(')') + when ODIN_ERROR_POS_STYLE == .Default { + print_byte('(') + print_u64(u64(line)) + print_byte(':') + print_u64(u64(column)) + print_byte(')') + } else when ODIN_ERROR_POS_STYLE == .Unix { + print_byte(':') + print_u64(u64(line)) + print_byte(':') + print_u64(u64(column)) + print_byte(':') + } else { + #panic("unhandled ODIN_ERROR_POS_STYLE") + } } print_typeid :: proc "contextless" (id: typeid) { if id == nil { diff --git a/src/build_settings.cpp b/src/build_settings.cpp index 96339be29..610e4f847 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -168,6 +168,8 @@ enum TimingsExportFormat : i32 { enum ErrorPosStyle { ErrorPosStyle_Default, // path(line:column) msg ErrorPosStyle_Unix, // path:line:column: msg + + ErrorPosStyle_COUNT }; // This stores the information for the specify architecture of this build diff --git a/src/checker.cpp b/src/checker.cpp index b81d9987b..e0c756bb8 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -893,6 +893,16 @@ void init_universal(void) { add_global_enum_constant(fields, "ODIN_ENDIAN", target_endians[bc->metrics.arch]); } + { + GlobalEnumValue values[ErrorPosStyle_COUNT] = { + {"Default", ErrorPosStyle_Default}, + {"Unix", ErrorPosStyle_Unix}, + }; + + auto fields = add_global_enum_type(str_lit("Odin_Error_Pos_Style_Type"), values, gb_count_of(values)); + add_global_enum_constant(fields, "ODIN_ERROR_POS_STYLE", build_context.ODIN_ERROR_POS_STYLE); + } + add_global_bool_constant("ODIN_DEBUG", bc->ODIN_DEBUG); add_global_bool_constant("ODIN_DISABLE_ASSERT", bc->ODIN_DISABLE_ASSERT); -- cgit v1.2.3 From 24e7356825a473cba0a1e9962470be73d60ad248 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 27 Jan 2022 16:08:47 +0000 Subject: Add `#no_type_assert` and `#type_assert` to disable implicit type assertions with `x.(T)` --- src/check_expr.cpp | 8 +++++ src/check_stmt.cpp | 8 +++++ src/checker.cpp | 12 ++++++++ src/llvm_backend_expr.cpp | 72 +++++++++++++++++++++++++------------------- src/llvm_backend_stmt.cpp | 7 +++++ src/llvm_backend_utility.cpp | 41 ++++++++++++++++--------- src/parser.cpp | 36 ++++++++++++++++++++++ src/parser.hpp | 4 +++ 8 files changed, 142 insertions(+), 46 deletions(-) (limited to 'src/checker.cpp') diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 276e9d0bb..fb5a90f5a 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -6883,6 +6883,14 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type out &= ~StateFlag_no_bounds_check; } + if (in & StateFlag_no_type_assert) { + out |= StateFlag_no_type_assert; + out &= ~StateFlag_type_assert; + } else if (in & StateFlag_type_assert) { + out |= StateFlag_type_assert; + out &= ~StateFlag_no_type_assert; + } + c->state_flags = out; } diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp index 94b7561c7..f9e55ab37 100644 --- a/src/check_stmt.cpp +++ b/src/check_stmt.cpp @@ -490,6 +490,14 @@ void check_stmt(CheckerContext *ctx, Ast *node, u32 flags) { out &= ~StateFlag_no_bounds_check; } + if (in & StateFlag_no_type_assert) { + out |= StateFlag_no_type_assert; + out &= ~StateFlag_type_assert; + } else if (in & StateFlag_type_assert) { + out |= StateFlag_type_assert; + out &= ~StateFlag_no_type_assert; + } + ctx->state_flags = out; } diff --git a/src/checker.cpp b/src/checker.cpp index e0c756bb8..038709056 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -4875,6 +4875,9 @@ bool check_proc_info(Checker *c, ProcInfo *pi, UntypedExprInfoMap *untyped, Proc bool bounds_check = (pi->tags & ProcTag_bounds_check) != 0; bool no_bounds_check = (pi->tags & ProcTag_no_bounds_check) != 0; + bool type_assert = (pi->tags & ProcTag_type_assert) != 0; + bool no_type_assert = (pi->tags & ProcTag_no_type_assert) != 0; + if (bounds_check) { ctx.state_flags |= StateFlag_bounds_check; ctx.state_flags &= ~StateFlag_no_bounds_check; @@ -4882,6 +4885,15 @@ bool check_proc_info(Checker *c, ProcInfo *pi, UntypedExprInfoMap *untyped, Proc ctx.state_flags |= StateFlag_no_bounds_check; ctx.state_flags &= ~StateFlag_bounds_check; } + + if (type_assert) { + ctx.state_flags |= StateFlag_type_assert; + ctx.state_flags &= ~StateFlag_no_type_assert; + } else if (no_type_assert) { + ctx.state_flags |= StateFlag_no_type_assert; + ctx.state_flags &= ~StateFlag_type_assert; + } + if (pi->body != nullptr && e != nullptr) { GB_ASSERT((e->flags & EntityFlag_ProcBodyChecked) == 0); } diff --git a/src/llvm_backend_expr.cpp b/src/llvm_backend_expr.cpp index 9b2e26434..ea031ee56 100644 --- a/src/llvm_backend_expr.cpp +++ b/src/llvm_backend_expr.cpp @@ -2768,27 +2768,29 @@ lbValue lb_build_unary_and(lbProcedure *p, Ast *expr) { Type *src_type = type_deref(v.type); Type *dst_type = type; - lbValue src_tag = {}; - lbValue dst_tag = {}; - if (is_type_union_maybe_pointer(src_type)) { - src_tag = lb_emit_comp_against_nil(p, Token_NotEq, v); - dst_tag = lb_const_bool(p->module, t_bool, true); - } else { - src_tag = lb_emit_load(p, lb_emit_union_tag_ptr(p, v)); - dst_tag = lb_const_union_tag(p->module, src_type, dst_type); - } - lbValue ok = lb_emit_comp(p, Token_CmpEq, src_tag, dst_tag); - auto args = array_make(permanent_allocator(), 6); - args[0] = ok; + if ((p->state_flags & StateFlag_no_type_assert) == 0) { + lbValue src_tag = {}; + lbValue dst_tag = {}; + if (is_type_union_maybe_pointer(src_type)) { + src_tag = lb_emit_comp_against_nil(p, Token_NotEq, v); + dst_tag = lb_const_bool(p->module, t_bool, true); + } else { + src_tag = lb_emit_load(p, lb_emit_union_tag_ptr(p, v)); + dst_tag = lb_const_union_tag(p->module, src_type, dst_type); + } + lbValue ok = lb_emit_comp(p, Token_CmpEq, src_tag, dst_tag); + auto args = array_make(permanent_allocator(), 6); + args[0] = ok; - args[1] = lb_find_or_add_entity_string(p->module, get_file_path_string(pos.file_id)); - args[2] = lb_const_int(p->module, t_i32, pos.line); - args[3] = lb_const_int(p->module, t_i32, pos.column); + args[1] = lb_find_or_add_entity_string(p->module, get_file_path_string(pos.file_id)); + args[2] = lb_const_int(p->module, t_i32, pos.line); + args[3] = lb_const_int(p->module, t_i32, pos.column); - args[4] = lb_typeid(p->module, src_type); - args[5] = lb_typeid(p->module, dst_type); - lb_emit_runtime_call(p, "type_assertion_check", args); + args[4] = lb_typeid(p->module, src_type); + args[5] = lb_typeid(p->module, dst_type); + lb_emit_runtime_call(p, "type_assertion_check", args); + } lbValue data_ptr = v; return lb_emit_conv(p, data_ptr, tv.type); @@ -2797,23 +2799,23 @@ lbValue lb_build_unary_and(lbProcedure *p, Ast *expr) { if (is_type_pointer(v.type)) { v = lb_emit_load(p, v); } - lbValue data_ptr = lb_emit_struct_ev(p, v, 0); - lbValue any_id = lb_emit_struct_ev(p, v, 1); - lbValue id = lb_typeid(p->module, type); + if ((p->state_flags & StateFlag_no_type_assert) == 0) { + lbValue any_id = lb_emit_struct_ev(p, v, 1); + lbValue id = lb_typeid(p->module, type); + lbValue ok = lb_emit_comp(p, Token_CmpEq, any_id, id); + auto args = array_make(permanent_allocator(), 6); + args[0] = ok; - lbValue ok = lb_emit_comp(p, Token_CmpEq, any_id, id); - auto args = array_make(permanent_allocator(), 6); - args[0] = ok; - - args[1] = lb_find_or_add_entity_string(p->module, get_file_path_string(pos.file_id)); - args[2] = lb_const_int(p->module, t_i32, pos.line); - args[3] = lb_const_int(p->module, t_i32, pos.column); + args[1] = lb_find_or_add_entity_string(p->module, get_file_path_string(pos.file_id)); + args[2] = lb_const_int(p->module, t_i32, pos.line); + args[3] = lb_const_int(p->module, t_i32, pos.column); - args[4] = any_id; - args[5] = id; - lb_emit_runtime_call(p, "type_assertion_check", args); + args[4] = any_id; + args[5] = id; + lb_emit_runtime_call(p, "type_assertion_check", args); + } return lb_emit_conv(p, data_ptr, tv.type); } else { @@ -2843,6 +2845,14 @@ lbValue lb_build_expr(lbProcedure *p, Ast *expr) { out &= ~StateFlag_bounds_check; } + if (in & StateFlag_type_assert) { + out |= StateFlag_type_assert; + out &= ~StateFlag_no_type_assert; + } else if (in & StateFlag_no_type_assert) { + out |= StateFlag_no_type_assert; + out &= ~StateFlag_type_assert; + } + p->state_flags = out; } diff --git a/src/llvm_backend_stmt.cpp b/src/llvm_backend_stmt.cpp index 3375ceda9..916c0433e 100644 --- a/src/llvm_backend_stmt.cpp +++ b/src/llvm_backend_stmt.cpp @@ -1991,6 +1991,13 @@ void lb_build_stmt(lbProcedure *p, Ast *node) { out |= StateFlag_no_bounds_check; out &= ~StateFlag_bounds_check; } + if (in & StateFlag_no_type_assert) { + out |= StateFlag_no_type_assert; + out &= ~StateFlag_type_assert; + } else if (in & StateFlag_type_assert) { + out |= StateFlag_type_assert; + out &= ~StateFlag_no_type_assert; + } p->state_flags = out; } diff --git a/src/llvm_backend_utility.cpp b/src/llvm_backend_utility.cpp index 5b1b11b44..7e2bd7daa 100644 --- a/src/llvm_backend_utility.cpp +++ b/src/llvm_backend_utility.cpp @@ -626,6 +626,12 @@ lbValue lb_emit_union_cast(lbProcedure *p, lbValue value, Type *type, TokenPos p lbValue value_ = lb_address_from_load_or_generate_local(p, value); + if ((p->state_flags & StateFlag_no_type_assert) != 0 && !is_tuple) { + // just do a bit cast of the data at the front + lbValue ptr = lb_emit_conv(p, value_, alloc_type_pointer(type)); + return lb_emit_load(p, ptr); + } + lbValue tag = {}; lbValue dst_tag = {}; lbValue cond = {}; @@ -666,23 +672,22 @@ lbValue lb_emit_union_cast(lbProcedure *p, lbValue value, Type *type, TokenPos p lb_start_block(p, end_block); if (!is_tuple) { - { - // NOTE(bill): Panic on invalid conversion - Type *dst_type = tuple->Tuple.variables[0]->type; + GB_ASSERT((p->state_flags & StateFlag_no_type_assert) == 0); + // NOTE(bill): Panic on invalid conversion + Type *dst_type = tuple->Tuple.variables[0]->type; - lbValue ok = lb_emit_load(p, lb_emit_struct_ep(p, v.addr, 1)); - auto args = array_make(permanent_allocator(), 7); - args[0] = ok; + lbValue ok = lb_emit_load(p, lb_emit_struct_ep(p, v.addr, 1)); + auto args = array_make(permanent_allocator(), 7); + args[0] = ok; - args[1] = lb_const_string(m, get_file_path_string(pos.file_id)); - args[2] = lb_const_int(m, t_i32, pos.line); - args[3] = lb_const_int(m, t_i32, pos.column); + args[1] = lb_const_string(m, get_file_path_string(pos.file_id)); + args[2] = lb_const_int(m, t_i32, pos.line); + args[3] = lb_const_int(m, t_i32, pos.column); - args[4] = lb_typeid(m, src_type); - args[5] = lb_typeid(m, dst_type); - args[6] = lb_emit_conv(p, value_, t_rawptr); - lb_emit_runtime_call(p, "type_assertion_check2", args); - } + args[4] = lb_typeid(m, src_type); + args[5] = lb_typeid(m, dst_type); + args[6] = lb_emit_conv(p, value_, t_rawptr); + lb_emit_runtime_call(p, "type_assertion_check2", args); return lb_emit_load(p, lb_emit_struct_ep(p, v.addr, 0)); } @@ -706,6 +711,13 @@ lbAddr lb_emit_any_cast_addr(lbProcedure *p, lbValue value, Type *type, TokenPos } Type *dst_type = tuple->Tuple.variables[0]->type; + if ((p->state_flags & StateFlag_no_type_assert) != 0 && !is_tuple) { + // just do a bit cast of the data at the front + lbValue ptr = lb_emit_struct_ev(p, value, 0); + ptr = lb_emit_conv(p, ptr, alloc_type_pointer(type)); + return lb_addr(ptr); + } + lbAddr v = lb_add_local_generated(p, tuple, true); lbValue dst_typeid = lb_typeid(m, dst_type); @@ -731,7 +743,6 @@ lbAddr lb_emit_any_cast_addr(lbProcedure *p, lbValue value, Type *type, TokenPos if (!is_tuple) { // NOTE(bill): Panic on invalid conversion - lbValue ok = lb_emit_load(p, lb_emit_struct_ep(p, v.addr, 1)); auto args = array_make(permanent_allocator(), 7); args[0] = ok; diff --git a/src/parser.cpp b/src/parser.cpp index 108411cd0..9cc9adfc9 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -1843,6 +1843,8 @@ void parse_proc_tags(AstFile *f, u64 *tags) { ELSE_IF_ADD_TAG(require_results) ELSE_IF_ADD_TAG(bounds_check) ELSE_IF_ADD_TAG(no_bounds_check) + ELSE_IF_ADD_TAG(type_assert) + ELSE_IF_ADD_TAG(no_type_assert) else { syntax_error(tag_expr, "Unknown procedure type tag #%.*s", LIT(tag_name)); } @@ -1853,6 +1855,10 @@ void parse_proc_tags(AstFile *f, u64 *tags) { if ((*tags & ProcTag_bounds_check) && (*tags & ProcTag_no_bounds_check)) { syntax_error(f->curr_token, "You cannot apply both #bounds_check and #no_bounds_check to a procedure"); } + + if ((*tags & ProcTag_type_assert) && (*tags & ProcTag_no_type_assert)) { + syntax_error(f->curr_token, "You cannot apply both #type_assert and #no_type_assert to a procedure"); + } } @@ -2000,11 +2006,23 @@ Ast *parse_check_directive_for_statement(Ast *s, Token const &tag_token, u16 sta syntax_error(tag_token, "#bounds_check and #no_bounds_check cannot be applied together"); } break; + case StateFlag_type_assert: + if ((s->state_flags & StateFlag_no_type_assert) != 0) { + syntax_error(tag_token, "#type_assert and #no_type_assert cannot be applied together"); + } + break; + case StateFlag_no_type_assert: + if ((s->state_flags & StateFlag_type_assert) != 0) { + syntax_error(tag_token, "#type_assert and #no_type_assert cannot be applied together"); + } + break; } switch (state_flag) { case StateFlag_bounds_check: case StateFlag_no_bounds_check: + case StateFlag_type_assert: + case StateFlag_no_type_assert: switch (s->kind) { case Ast_BlockStmt: case Ast_IfStmt: @@ -2128,6 +2146,12 @@ Ast *parse_operand(AstFile *f, bool lhs) { } else if (name.string == "no_bounds_check") { Ast *operand = parse_expr(f, lhs); return parse_check_directive_for_statement(operand, name, StateFlag_no_bounds_check); + } else if (name.string == "type_assert") { + Ast *operand = parse_expr(f, lhs); + return parse_check_directive_for_statement(operand, name, StateFlag_type_assert); + } else if (name.string == "no_type_assert") { + Ast *operand = parse_expr(f, lhs); + return parse_check_directive_for_statement(operand, name, StateFlag_no_type_assert); } else if (name.string == "relative") { Ast *tag = ast_basic_directive(f, token, name); tag = parse_call_expr(f, tag); @@ -2224,6 +2248,12 @@ Ast *parse_operand(AstFile *f, bool lhs) { if (tags & ProcTag_bounds_check) { body->state_flags |= StateFlag_bounds_check; } + if (tags & ProcTag_no_type_assert) { + body->state_flags |= StateFlag_no_type_assert; + } + if (tags & ProcTag_type_assert) { + body->state_flags |= StateFlag_type_assert; + } return ast_proc_lit(f, type, body, tags, where_token, where_clauses); } else if (allow_token(f, Token_do)) { @@ -4611,6 +4641,12 @@ Ast *parse_stmt(AstFile *f) { } else if (tag == "no_bounds_check") { s = parse_stmt(f); return parse_check_directive_for_statement(s, name, StateFlag_no_bounds_check); + } else if (tag == "type_assert") { + s = parse_stmt(f); + return parse_check_directive_for_statement(s, name, StateFlag_type_assert); + } else if (tag == "no_type_assert") { + s = parse_stmt(f); + return parse_check_directive_for_statement(s, name, StateFlag_no_type_assert); } else if (tag == "partial") { s = parse_stmt(f); switch (s->kind) { diff --git a/src/parser.hpp b/src/parser.hpp index b005a4465..656f709e8 100644 --- a/src/parser.hpp +++ b/src/parser.hpp @@ -226,6 +226,8 @@ enum ProcInlining { enum ProcTag { ProcTag_bounds_check = 1<<0, ProcTag_no_bounds_check = 1<<1, + ProcTag_type_assert = 1<<2, + ProcTag_no_type_assert = 1<<3, ProcTag_require_results = 1<<4, ProcTag_optional_ok = 1<<5, @@ -258,6 +260,8 @@ ProcCallingConvention default_calling_convention(void) { enum StateFlag : u8 { StateFlag_bounds_check = 1<<0, StateFlag_no_bounds_check = 1<<1, + StateFlag_type_assert = 1<<2, + StateFlag_no_type_assert = 1<<3, StateFlag_BeenHandled = 1<<7, }; -- cgit v1.2.3 From 67ba05cb7cfee60daaf257230ddbc4f1e0a9f8ac Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 31 Jan 2022 19:33:02 +0000 Subject: Correct false positive check in `check_unique_package_names` --- src/checker.cpp | 10 ++++++++-- src/parser.cpp | 5 +++++ src/parser_pos.cpp | 6 ++++++ 3 files changed, 19 insertions(+), 2 deletions(-) (limited to 'src/checker.cpp') diff --git a/src/checker.cpp b/src/checker.cpp index 038709056..d9a1af0d1 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -5307,12 +5307,18 @@ void check_unique_package_names(Checker *c) { string_map_set(&pkgs, key, pkg); continue; } + auto *this = pkg->files[0]->pkg_decl; + auto *other = (*found)->files[0]->pkg_decl; + if (this == other) { + // NOTE(bill): A false positive was found, ignore it + continue; + } - error(pkg->files[0]->pkg_decl, "Duplicate declaration of 'package %.*s'", LIT(name)); + error(this, "Duplicate declaration of 'package %.*s'", LIT(name)); error_line("\tA package name must be unique\n" "\tThere is no relation between a package name and the directory that contains it, so they can be completely different\n" "\tA package name is required for link name prefixing to have a consistent ABI\n"); - error((*found)->files[0]->pkg_decl, "found at previous location"); + error(other, "found at previous location"); } } diff --git a/src/parser.cpp b/src/parser.cpp index 9cc9adfc9..7a858e520 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -183,6 +183,11 @@ Ast *clone_ast(Ast *node) { n->FieldValue.value = clone_ast(n->FieldValue.value); break; + case Ast_EnumFieldValue: + n->EnumFieldValue.name = clone_ast(n->EnumFieldValue.name); + n->EnumFieldValue.value = clone_ast(n->EnumFieldValue.value); + break; + case Ast_TernaryIfExpr: n->TernaryIfExpr.x = clone_ast(n->TernaryIfExpr.x); n->TernaryIfExpr.cond = clone_ast(n->TernaryIfExpr.cond); diff --git a/src/parser_pos.cpp b/src/parser_pos.cpp index 6ef0db215..54c3ec1f1 100644 --- a/src/parser_pos.cpp +++ b/src/parser_pos.cpp @@ -39,6 +39,7 @@ Token ast_token(Ast *node) { case Ast_SliceExpr: return node->SliceExpr.open; case Ast_Ellipsis: return node->Ellipsis.token; case Ast_FieldValue: return node->FieldValue.eq; + case Ast_EnumFieldValue: return ast_token(node->EnumFieldValue.name); case Ast_DerefExpr: return node->DerefExpr.op; case Ast_TernaryIfExpr: return ast_token(node->TernaryIfExpr.x); case Ast_TernaryWhenExpr: return ast_token(node->TernaryWhenExpr.x); @@ -178,6 +179,11 @@ Token ast_end_token(Ast *node) { } return node->Ellipsis.token; case Ast_FieldValue: return ast_end_token(node->FieldValue.value); + case Ast_EnumFieldValue: + if (node->EnumFieldValue.value) { + return ast_end_token(node->EnumFieldValue.value); + } + return ast_end_token(node->EnumFieldValue.name); case Ast_DerefExpr: return node->DerefExpr.op; case Ast_TernaryIfExpr: return ast_end_token(node->TernaryIfExpr.y); case Ast_TernaryWhenExpr: return ast_end_token(node->TernaryWhenExpr.y); -- cgit v1.2.3 From 85706d559d06998895b27710f5e4f4643443b032 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 31 Jan 2022 20:19:46 +0000 Subject: Fix typo --- src/checker.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src/checker.cpp') diff --git a/src/checker.cpp b/src/checker.cpp index d9a1af0d1..d50d4d176 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -5307,18 +5307,18 @@ void check_unique_package_names(Checker *c) { string_map_set(&pkgs, key, pkg); continue; } - auto *this = pkg->files[0]->pkg_decl; - auto *other = (*found)->files[0]->pkg_decl; - if (this == other) { + auto *curr = pkg->files[0]->pkg_decl; + auto *prev = (*found)->files[0]->pkg_decl; + if (curr == prev) { // NOTE(bill): A false positive was found, ignore it continue; } - error(this, "Duplicate declaration of 'package %.*s'", LIT(name)); + error(curr, "Duplicate declaration of 'package %.*s'", LIT(name)); error_line("\tA package name must be unique\n" "\tThere is no relation between a package name and the directory that contains it, so they can be completely different\n" "\tA package name is required for link name prefixing to have a consistent ABI\n"); - error(other, "found at previous location"); + error(prev, "found at previous location"); } } -- cgit v1.2.3 From 78815778ee399b4df1c5f7c44522c792b9dc3e23 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 2 Feb 2022 15:28:49 +0000 Subject: Add `//+private file` to complement `//+private` (`//+private package`) --- src/checker.cpp | 9 ++++++--- src/entity.cpp | 2 +- src/parser.cpp | 12 ++++++++++-- src/parser.hpp | 8 +++++--- src/string.cpp | 12 ++++++++++-- 5 files changed, 32 insertions(+), 11 deletions(-) (limited to 'src/checker.cpp') diff --git a/src/checker.cpp b/src/checker.cpp index d50d4d176..4dcb5120f 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -3467,9 +3467,12 @@ void check_collect_value_decl(CheckerContext *c, Ast *decl) { if (entity_visibility_kind == EntityVisiblity_Public && (c->scope->flags&ScopeFlag_File) && - c->scope->file && - (c->scope->file->flags & AstFile_IsPrivate)) { - entity_visibility_kind = EntityVisiblity_PrivateToPackage; + c->scope->file) { + if (c->scope->file->flags & AstFile_IsPrivatePkg) { + entity_visibility_kind = EntityVisiblity_PrivateToPackage; + } else if (c->scope->file->flags & AstFile_IsPrivateFile) { + entity_visibility_kind = EntityVisiblity_PrivateToFile; + } } if (entity_visibility_kind != EntityVisiblity_Public && !(c->scope->flags&ScopeFlag_File)) { diff --git a/src/entity.cpp b/src/entity.cpp index a0438a9f4..8327a517e 100644 --- a/src/entity.cpp +++ b/src/entity.cpp @@ -245,7 +245,7 @@ bool is_entity_exported(Entity *e, bool allow_builtin = false) { if (e->flags & EntityFlag_NotExported) { return false; } - if (e->file != nullptr && (e->file->flags & AstFile_IsPrivate) != 0) { + if (e->file != nullptr && (e->file->flags & (AstFile_IsPrivatePkg|AstFile_IsPrivateFile)) != 0) { return false; } diff --git a/src/parser.cpp b/src/parser.cpp index 7a858e520..bf8c909c2 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -5535,8 +5535,16 @@ bool parse_file(Parser *p, AstFile *f) { if (!parse_build_tag(tok, lc)) { return false; } - } else if (lc == "+private") { - f->flags |= AstFile_IsPrivate; + } else if (string_starts_with(lc, str_lit("+private"))) { + f->flags |= AstFile_IsPrivatePkg; + String command = string_trim_starts_with(lc, str_lit("+private ")); + if (lc == "+private") { + f->flags |= AstFile_IsPrivatePkg; + } else if (command == "package") { + f->flags |= AstFile_IsPrivatePkg; + } else if (command == "file") { + f->flags |= AstFile_IsPrivateFile; + } } else if (lc == "+lazy") { if (build_context.ignore_lazy) { // Ignore diff --git a/src/parser.hpp b/src/parser.hpp index 656f709e8..0712e83cb 100644 --- a/src/parser.hpp +++ b/src/parser.hpp @@ -78,9 +78,11 @@ struct ImportedFile { }; enum AstFileFlag : u32 { - AstFile_IsPrivate = 1<<0, - AstFile_IsTest = 1<<1, - AstFile_IsLazy = 1<<2, + AstFile_IsPrivatePkg = 1<<0, + AstFile_IsPrivateFile = 1<<1, + + AstFile_IsTest = 1<<3, + AstFile_IsLazy = 1<<4, }; enum AstDelayQueueKind { diff --git a/src/string.cpp b/src/string.cpp index 800378689..eb6058f78 100644 --- a/src/string.cpp +++ b/src/string.cpp @@ -195,8 +195,6 @@ template bool operator > (String const &a, char const (&b)[N]) { retu template bool operator <= (String const &a, char const (&b)[N]) { return str_le(a, make_string(cast(u8 *)b, N-1)); } template bool operator >= (String const &a, char const (&b)[N]) { return str_ge(a, make_string(cast(u8 *)b, N-1)); } - - gb_inline bool string_starts_with(String const &s, String const &prefix) { if (prefix.len > s.len) { return false; @@ -230,6 +228,16 @@ gb_inline bool string_ends_with(String const &s, u8 suffix) { return s[s.len-1] == suffix; } + + +gb_inline String string_trim_starts_with(String const &s, String const &prefix) { + if (string_starts_with(s, prefix)) { + return substring(s, prefix.len, s.len); + } + return s; +} + + gb_inline isize string_extension_position(String const &str) { isize dot_pos = -1; isize i = str.len; -- cgit v1.2.3 From 35c90fe12413335962cad02d77a4894079b00a5d Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 3 Feb 2022 13:34:31 +0000 Subject: Fix type alias declaration evaluation problem (#854 #1439) --- src/check_decl.cpp | 39 +++++++++++++++++- src/check_expr.cpp | 113 ++++++++++++++++++++++++++++++++++++++++++++++------- src/checker.cpp | 3 -- 3 files changed, 137 insertions(+), 18 deletions(-) (limited to 'src/checker.cpp') diff --git a/src/check_decl.cpp b/src/check_decl.cpp index f9bc17ba4..193c28aea 100644 --- a/src/check_decl.cpp +++ b/src/check_decl.cpp @@ -385,7 +385,44 @@ void check_const_decl(CheckerContext *ctx, Entity *e, Ast *type_expr, Ast *init, Operand operand = {}; if (init != nullptr) { - Entity *entity = nullptr; + Entity *entity = check_entity_from_ident_or_selector(ctx, init); + if (entity != nullptr && entity->kind == Entity_TypeName) { + // NOTE(bill, 2022-02-03): This is used to solve the problem caused by type aliases + // being "confused" as constants + // + // A :: B + // C :: proc "c" (^A) + // B :: struct {x: C} + // + // A gets evaluated first, and then checks B. + // B then checks C. + // C then tries to check A which is unresolved but thought to be a constant. + // Therefore within C's check, A errs as "not a type". + // + // This is because a const declaration may or may not be a type and this cannot + // be determined from a syntactical standpoint. + // This check allows the compiler to override the entity to be checked as a type. + // + // There is no problem if B is prefixed with the `#type` helper enforcing at + // both a syntax and semantic level that B must be a type. + // + // A :: #type B + // + // This approach is not fool proof and can fail in case such as: + // + // X :: type_of(x) + // X :: Foo(int).Type + // + // Since even these kind of declarations may cause weird checking cycles. + // For the time being, these are going to be treated as an unfortunate error + // until there is a proper delaying system to try declaration again if they + // have failed. + + e->kind = Entity_TypeName; + check_type_decl(ctx, e, init, named_type); + return; + } + entity = nullptr; if (init->kind == Ast_Ident) { entity = check_ident(ctx, &operand, init, nullptr, e->type, true); } else if (init->kind == Ast_SelectorExpr) { diff --git a/src/check_expr.cpp b/src/check_expr.cpp index fb5a90f5a..88296611b 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -1286,7 +1286,6 @@ bool check_cycle(CheckerContext *c, Entity *curr, bool report) { return false; } - Entity *check_ident(CheckerContext *c, Operand *o, Ast *n, Type *named_type, Type *type_hint, bool allow_import_name) { GB_ASSERT(n->kind == Ast_Ident); o->mode = Addressing_Invalid; @@ -1422,8 +1421,12 @@ Entity *check_ident(CheckerContext *c, Operand *o, Ast *n, Type *named_type, Typ case Entity_TypeName: o->mode = Addressing_Type; if (check_cycle(c, e, true)) { - type = t_invalid; + o->type = t_invalid; + } + if (o->type != nullptr && type->kind == Type_Named && o->type->Named.type_name->TypeName.is_type_alias) { + o->type = base_type(o->type); } + break; case Entity_ImportName: @@ -4064,6 +4067,98 @@ Type *determine_swizzle_array_type(Type *original_type, Type *type_hint, isize n } +bool is_entity_declared_for_selector(Entity *entity, Scope *import_scope, bool *allow_builtin) { + bool is_declared = entity != nullptr; + if (is_declared) { + if (entity->kind == Entity_Builtin) { + // NOTE(bill): Builtin's are in the universal scope which is part of every scopes hierarchy + // This means that we should just ignore the found result through it + *allow_builtin = entity->scope == import_scope || entity->scope != builtin_pkg->scope; + } else if ((entity->scope->flags&ScopeFlag_Global) == ScopeFlag_Global && (import_scope->flags&ScopeFlag_Global) == 0) { + is_declared = false; + } + } + return is_declared; +} + +// NOTE(bill, 2022-02-03): see `check_const_decl` for why it exists reasoning +Entity *check_entity_from_ident_or_selector(CheckerContext *c, Ast *node) { + if (node->kind == Ast_Ident) { + String name = node->Ident.token.string; + return scope_lookup(c->scope, name); + } else if (node->kind == Ast_SelectorExpr) { + ast_node(se, SelectorExpr, node); + if (!c->allow_arrow_right_selector_expr && se->token.kind == Token_ArrowRight) { + return nullptr; + } + + Ast *op_expr = se->expr; + Ast *selector = unparen_expr(se->selector); + if (selector == nullptr) { + return nullptr; + } + if (selector->kind != Ast_Ident) { + return nullptr; + } + + Entity *entity = nullptr; + Entity *expr_entity = nullptr; + bool check_op_expr = true; + + if (op_expr->kind == Ast_Ident) { + String op_name = op_expr->Ident.token.string; + Entity *e = scope_lookup(c->scope, op_name); + add_entity_use(c, op_expr, e); + expr_entity = e; + + if (e != nullptr && e->kind == Entity_ImportName && selector->kind == Ast_Ident) { + // IMPORTANT NOTE(bill): This is very sloppy code but it's also very fragile + // It pretty much needs to be in this order and this way + // If you can clean this up, please do but be really careful + String import_name = op_name; + Scope *import_scope = e->ImportName.scope; + String entity_name = selector->Ident.token.string; + + check_op_expr = false; + entity = scope_lookup_current(import_scope, entity_name); + bool allow_builtin = false; + if (!is_entity_declared_for_selector(entity, import_scope, &allow_builtin)) { + return nullptr; + } + + check_entity_decl(c, entity, nullptr, nullptr); + if (entity->kind == Entity_ProcGroup) { + return entity; + } + GB_ASSERT_MSG(entity->type != nullptr, "%.*s (%.*s)", LIT(entity->token.string), LIT(entity_strings[entity->kind])); + } + } + + Operand operand = {}; + if (check_op_expr) { + check_expr_base(c, &operand, op_expr, nullptr); + if (operand.mode == Addressing_Invalid) { + return nullptr; + } + } + + if (entity == nullptr && selector->kind == Ast_Ident) { + String field_name = selector->Ident.token.string; + if (is_type_dynamic_array(type_deref(operand.type))) { + init_mem_allocator(c->checker); + } + auto sel = lookup_field(operand.type, field_name, operand.mode == Addressing_Type); + entity = sel.entity; + } + + if (entity != nullptr) { + return entity; + } + } + return nullptr; +} + + Entity *check_selector(CheckerContext *c, Operand *operand, Ast *node, Type *type_hint) { ast_node(se, SelectorExpr, node); @@ -4112,18 +4207,8 @@ Entity *check_selector(CheckerContext *c, Operand *operand, Ast *node, Type *typ check_op_expr = false; entity = scope_lookup_current(import_scope, entity_name); - bool is_declared = entity != nullptr; bool allow_builtin = false; - if (is_declared) { - if (entity->kind == Entity_Builtin) { - // NOTE(bill): Builtin's are in the universal scope which is part of every scopes hierarchy - // This means that we should just ignore the found result through it - allow_builtin = entity->scope == import_scope || entity->scope != builtin_pkg->scope; - } else if ((entity->scope->flags&ScopeFlag_Global) == ScopeFlag_Global && (import_scope->flags&ScopeFlag_Global) == 0) { - is_declared = false; - } - } - if (!is_declared) { + if (!is_entity_declared_for_selector(entity, import_scope, &allow_builtin)) { error(op_expr, "'%.*s' is not declared by '%.*s'", LIT(entity_name), LIT(import_name)); operand->mode = Addressing_Invalid; operand->expr = node; @@ -4213,7 +4298,7 @@ Entity *check_selector(CheckerContext *c, Operand *operand, Ast *node, Type *typ } } - if (entity == nullptr && selector->kind == Ast_Ident && is_type_array(type_deref(operand->type))) { + if (entity == nullptr && selector->kind == Ast_Ident && is_type_array(type_deref(operand->type))) { // TODO(bill): Simd_Vector swizzling String field_name = selector->Ident.token.string; diff --git a/src/checker.cpp b/src/checker.cpp index 4dcb5120f..c4423b2bc 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -3563,9 +3563,6 @@ void check_collect_value_decl(CheckerContext *c, Ast *decl) { if (is_ast_type(init)) { e = alloc_entity_type_name(d->scope, token, nullptr); - // if (vd->type != nullptr) { - // error(name, "A type declaration cannot have an type parameter"); - // } } else if (init->kind == Ast_ProcLit) { if (c->scope->flags&ScopeFlag_Type) { error(name, "Procedure declarations are not allowed within a struct"); -- cgit v1.2.3 From 3a81f2ab898d537bba51b9ea81e047652112574e Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 4 Feb 2022 22:40:15 +0000 Subject: Correct the type aliasing problem, caused by aliases (of aliases)+ --- src/check_decl.cpp | 1 + src/check_expr.cpp | 5 ++++- src/checker.cpp | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 70 insertions(+), 2 deletions(-) (limited to 'src/checker.cpp') diff --git a/src/check_decl.cpp b/src/check_decl.cpp index 193c28aea..2454feb33 100644 --- a/src/check_decl.cpp +++ b/src/check_decl.cpp @@ -387,6 +387,7 @@ void check_const_decl(CheckerContext *ctx, Entity *e, Ast *type_expr, Ast *init, if (init != nullptr) { Entity *entity = check_entity_from_ident_or_selector(ctx, init); if (entity != nullptr && entity->kind == Entity_TypeName) { + // @TypeAliasingProblem // NOTE(bill, 2022-02-03): This is used to solve the problem caused by type aliases // being "confused" as constants // diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 88296611b..e1c9bde84 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -4088,7 +4088,7 @@ Entity *check_entity_from_ident_or_selector(CheckerContext *c, Ast *node) { return scope_lookup(c->scope, name); } else if (node->kind == Ast_SelectorExpr) { ast_node(se, SelectorExpr, node); - if (!c->allow_arrow_right_selector_expr && se->token.kind == Token_ArrowRight) { + if (se->token.kind == Token_ArrowRight) { return nullptr; } @@ -4108,6 +4108,9 @@ Entity *check_entity_from_ident_or_selector(CheckerContext *c, Ast *node) { if (op_expr->kind == Ast_Ident) { String op_name = op_expr->Ident.token.string; Entity *e = scope_lookup(c->scope, op_name); + if (e == nullptr) { + return nullptr; + } add_entity_use(c, op_expr, e); expr_entity = e; diff --git a/src/checker.cpp b/src/checker.cpp index c4423b2bc..c90f357dd 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -3665,6 +3665,59 @@ void check_add_foreign_block_decl(CheckerContext *ctx, Ast *decl) { check_collect_entities(&c, block->stmts); } +bool correct_single_type_alias(CheckerContext *c, Entity *e) { + if (e->kind == Entity_Constant) { + DeclInfo *d = e->decl_info; + if (d != nullptr && d->init_expr != nullptr) { + Ast *init = d->init_expr; + Entity *alias_of = check_entity_from_ident_or_selector(c, init); + if (alias_of != nullptr && alias_of->kind == Entity_TypeName) { + e->kind = Entity_TypeName; + return true; + } + } + } + return false; +} + +bool correct_type_alias_in_scope_backwards(CheckerContext *c, Scope *s) { + isize n = s->elements.entries.count; + bool correction = false; + for (isize i = n-1; i >= 0; i--) { + correction |= correct_single_type_alias(c, s->elements.entries[i].value); + } + return correction; +} +bool correct_type_alias_in_scope_forwards(CheckerContext *c, Scope *s) { + isize n = s->elements.entries.count; + bool correction = false; + for (isize i = 0; i < n; i++) { + correction |= correct_single_type_alias(c, s->elements.entries[i].value); + } + return correction; +} + + +void correct_type_aliases_in_scope(CheckerContext *c, Scope *s) { + // NOTE(bill, 2022-02-04): This is used to solve the problem caused by type aliases + // of type aliases being "confused" as constants + // + // A :: C + // B :: A + // C :: struct {b: ^B} + // + // See @TypeAliasingProblem for more information + for (;;) { + bool corrections = false; + corrections |= correct_type_alias_in_scope_backwards(c, s); + corrections |= correct_type_alias_in_scope_forwards(c, s); + if (!corrections) { + return; + } + } +} + + // NOTE(bill): If file_scopes == nullptr, this will act like a local scope void check_collect_entities(CheckerContext *c, Slice const &nodes) { AstFile *curr_file = nullptr; @@ -3736,6 +3789,7 @@ void check_collect_entities(CheckerContext *c, Slice const &nodes) { } } + // correct_type_aliases(c); // NOTE(bill): 'when' stmts need to be handled after the other as the condition may refer to something // declared after this stmt in source @@ -4381,10 +4435,11 @@ bool collect_file_decls(CheckerContext *ctx, Slice const &decls) { for_array(i, decls) { if (collect_file_decl(ctx, decls[i])) { + correct_type_aliases_in_scope(ctx, ctx->scope); return true; } } - + correct_type_aliases_in_scope(ctx, ctx->scope); return false; } @@ -4654,6 +4709,15 @@ void check_import_entities(Checker *c) { } add_untyped_expressions(ctx.info, &untyped); } + + for_array(i, pkg->files) { + AstFile *f = pkg->files[i]; + reset_checker_context(&ctx, f, &untyped); + ctx.collect_delayed_decls = false; + + correct_type_aliases_in_scope(&ctx, pkg->scope); + } + for_array(i, pkg->files) { AstFile *f = pkg->files[i]; reset_checker_context(&ctx, f, &untyped); -- cgit v1.2.3 From d5384c5aa4d823fbd527fb82e9eb5559b4266dfd Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 4 Feb 2022 22:45:13 +0000 Subject: Only check idents in the alias (of alias)+ problem --- src/check_decl.cpp | 2 +- src/check_expr.cpp | 4 ++-- src/checker.cpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src/checker.cpp') diff --git a/src/check_decl.cpp b/src/check_decl.cpp index 2454feb33..63fc777c0 100644 --- a/src/check_decl.cpp +++ b/src/check_decl.cpp @@ -385,7 +385,7 @@ void check_const_decl(CheckerContext *ctx, Entity *e, Ast *type_expr, Ast *init, Operand operand = {}; if (init != nullptr) { - Entity *entity = check_entity_from_ident_or_selector(ctx, init); + Entity *entity = check_entity_from_ident_or_selector(ctx, init, false); if (entity != nullptr && entity->kind == Entity_TypeName) { // @TypeAliasingProblem // NOTE(bill, 2022-02-03): This is used to solve the problem caused by type aliases diff --git a/src/check_expr.cpp b/src/check_expr.cpp index e1c9bde84..d51444b4d 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -4082,11 +4082,11 @@ bool is_entity_declared_for_selector(Entity *entity, Scope *import_scope, bool * } // NOTE(bill, 2022-02-03): see `check_const_decl` for why it exists reasoning -Entity *check_entity_from_ident_or_selector(CheckerContext *c, Ast *node) { +Entity *check_entity_from_ident_or_selector(CheckerContext *c, Ast *node, bool ident_only) { if (node->kind == Ast_Ident) { String name = node->Ident.token.string; return scope_lookup(c->scope, name); - } else if (node->kind == Ast_SelectorExpr) { + } else if (!ident_only) if (node->kind == Ast_SelectorExpr) { ast_node(se, SelectorExpr, node); if (se->token.kind == Token_ArrowRight) { return nullptr; diff --git a/src/checker.cpp b/src/checker.cpp index c90f357dd..188d68502 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -3670,7 +3670,7 @@ bool correct_single_type_alias(CheckerContext *c, Entity *e) { DeclInfo *d = e->decl_info; if (d != nullptr && d->init_expr != nullptr) { Ast *init = d->init_expr; - Entity *alias_of = check_entity_from_ident_or_selector(c, init); + Entity *alias_of = check_entity_from_ident_or_selector(c, init, true); if (alias_of != nullptr && alias_of->kind == Entity_TypeName) { e->kind = Entity_TypeName; return true; -- cgit v1.2.3 From cf246f65ff72db870313627b7db3b83601364385 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sat, 5 Feb 2022 14:31:22 +0000 Subject: Add check for variables which are both shadowing and unused by default --- src/checker.cpp | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) (limited to 'src/checker.cpp') diff --git a/src/checker.cpp b/src/checker.cpp index 188d68502..b62ef7c4c 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -504,6 +504,7 @@ enum VettedEntityKind { VettedEntity_Unused, VettedEntity_Shadowed, + VettedEntity_Shadowed_And_Unused, }; struct VettedEntity { VettedEntityKind kind; @@ -625,12 +626,18 @@ void check_scope_usage(Checker *c, Scope *scope) { MUTEX_GUARD_BLOCK(scope->mutex) for_array(i, scope->elements.entries) { Entity *e = scope->elements.entries[i].value; if (e == nullptr) continue; - VettedEntity ve = {}; - if (vet_unused && check_vet_unused(c, e, &ve)) { - array_add(&vetted_entities, ve); - } - if (vet_shadowing && check_vet_shadowing(c, e, &ve)) { - array_add(&vetted_entities, ve); + VettedEntity ve_unused = {}; + VettedEntity ve_shadowed = {}; + bool is_unused = vet_unused && check_vet_unused(c, e, &ve_unused); + bool is_shadowed = vet_shadowing && check_vet_shadowing(c, e, &ve_shadowed); + if (is_unused && is_shadowed) { + VettedEntity ve_both = ve_shadowed; + ve_both.kind = VettedEntity_Shadowed_And_Unused; + array_add(&vetted_entities, ve_both); + } else if (is_unused) { + array_add(&vetted_entities, ve_unused); + } else if (is_shadowed) { + array_add(&vetted_entities, ve_shadowed); } } @@ -642,16 +649,18 @@ void check_scope_usage(Checker *c, Scope *scope) { Entity *other = ve.other; String name = e->token.string; - if (build_context.vet) { + if (ve.kind == VettedEntity_Shadowed_And_Unused) { + error(e->token, "'%.*s' declared but not used, possibly shadows declaration at line %d", LIT(name), other->token.pos.line); + } else if (build_context.vet) { switch (ve.kind) { case VettedEntity_Unused: error(e->token, "'%.*s' declared but not used", LIT(name)); break; case VettedEntity_Shadowed: if (e->flags&EntityFlag_Using) { - error(e->token, "Declaration of '%.*s' from 'using' shadows declaration at line %lld", LIT(name), cast(long long)other->token.pos.line); + error(e->token, "Declaration of '%.*s' from 'using' shadows declaration at line %d", LIT(name), other->token.pos.line); } else { - error(e->token, "Declaration of '%.*s' shadows declaration at line %lld", LIT(name), cast(long long)other->token.pos.line); + error(e->token, "Declaration of '%.*s' shadows declaration at line %d", LIT(name), other->token.pos.line); } break; default: -- cgit v1.2.3 From 3c2ed3bb69df24ba162e5f2ea8f61ee3f7fd8e2f Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 7 Feb 2022 11:37:13 +0000 Subject: Correct `//+private file` bug --- src/checker.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src/checker.cpp') diff --git a/src/checker.cpp b/src/checker.cpp index b62ef7c4c..7fb4fdb29 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -3477,11 +3477,11 @@ void check_collect_value_decl(CheckerContext *c, Ast *decl) { if (entity_visibility_kind == EntityVisiblity_Public && (c->scope->flags&ScopeFlag_File) && c->scope->file) { - if (c->scope->file->flags & AstFile_IsPrivatePkg) { - entity_visibility_kind = EntityVisiblity_PrivateToPackage; - } else if (c->scope->file->flags & AstFile_IsPrivateFile) { + if (c->scope->file->flags & AstFile_IsPrivateFile) { entity_visibility_kind = EntityVisiblity_PrivateToFile; - } + } else if (c->scope->file->flags & AstFile_IsPrivatePkg) { + entity_visibility_kind = EntityVisiblity_PrivateToPackage; + } } if (entity_visibility_kind != EntityVisiblity_Public && !(c->scope->flags&ScopeFlag_File)) { -- cgit v1.2.3 From 0cc40db565a9c4b99e6fa0844b9ac512558626e4 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 8 Feb 2022 17:04:55 +0000 Subject: Begin work on support objc intrinsics --- src/check_builtin.cpp | 223 +++++++++++++++++++++++++++++++++++++++++- src/check_decl.cpp | 3 + src/checker.cpp | 36 +++++++ src/checker.hpp | 15 ++- src/checker_builtin_procs.hpp | 6 ++ src/entity.cpp | 1 + src/llvm_backend.cpp | 59 ++++++++++- src/llvm_backend.hpp | 6 +- src/llvm_backend_general.cpp | 8 +- src/llvm_backend_proc.cpp | 3 + src/llvm_backend_utility.cpp | 96 ++++++++++++++++++ src/types.cpp | 10 ++ 12 files changed, 459 insertions(+), 7 deletions(-) (limited to 'src/checker.cpp') diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp index 1fb3d6037..8ada77b12 100644 --- a/src/check_builtin.cpp +++ b/src/check_builtin.cpp @@ -143,6 +143,219 @@ void check_or_return_split_types(CheckerContext *c, Operand *x, String const &na } +bool does_require_msgSend_stret(Type *return_type) { + if (return_type == nullptr) { + return false; + } + if (build_context.metrics.arch == TargetArch_i386 || build_context.metrics.arch == TargetArch_amd64) { + i64 struct_limit = type_size_of(t_uintptr) << 1; + return type_size_of(return_type) > struct_limit; + } + if (build_context.metrics.arch == TargetArch_arm64) { + return false; + } + + // if (build_context.metrics.arch == TargetArch_arm32) { + // i64 struct_limit = type_size_of(t_uintptr); + // // NOTE(bill): This is technically wrong + // return is_type_struct(return_type) && !is_type_raw_union(return_type) && type_size_of(return_type) > struct_limit; + // } + GB_PANIC("unsupported architecture"); + return false; +} + +ObjcMsgKind get_objc_proc_kind(Type *return_type) { + if (return_type == nullptr) { + return ObjcMsg_normal; + } + + if (build_context.metrics.arch == TargetArch_i386 || build_context.metrics.arch == TargetArch_amd64) { + if (is_type_float(return_type)) { + return ObjcMsg_fpret; + } + if (build_context.metrics.arch == TargetArch_amd64) { + if (is_type_complex(return_type)) { + // URL: https://github.com/opensource-apple/objc4/blob/cd5e62a5597ea7a31dccef089317abb3a661c154/runtime/message.h#L143-L159 + return ObjcMsg_fpret; + } + } + } + if (build_context.metrics.arch != TargetArch_arm64) { + if (does_require_msgSend_stret(return_type)) { + return ObjcMsg_stret; + } + } + return ObjcMsg_normal; +} + +void add_objc_proc_type(CheckerContext *c, Ast *call, Type *return_type, Slice param_types) { + ObjcMsgKind kind = get_objc_proc_kind(return_type); + + Scope *scope = create_scope(c->info, nullptr); + + // NOTE(bill, 2022-02-08): the backend's ABI handling should handle this correctly, I hope + Type *params = alloc_type_tuple(); + { + auto variables = array_make(permanent_allocator(), 0, param_types.count); + + for_array(i, param_types) { + Type *type = param_types[i]; + Entity *param = alloc_entity_param(scope, blank_token, type, false, true); + array_add(&variables, param); + } + params->Tuple.variables = slice_from_array(variables); + } + + Type *results = alloc_type_tuple(); + if (return_type) { + auto variables = array_make(permanent_allocator(), 1); + results->Tuple.variables = slice_from_array(variables); + Entity *param = alloc_entity_param(scope, blank_token, return_type, false, true); + results->Tuple.variables[0] = param; + } + + + ObjcMsgData data = {}; + data.kind = kind; + data.proc_type = alloc_type_proc(scope, params, param_types.count, results, results->Tuple.variables.count, false, ProcCC_CDecl); + + mutex_lock(&c->info->objc_types_mutex); + map_set(&c->info->objc_msgSend_types, call, data); + mutex_unlock(&c->info->objc_types_mutex); + + add_package_dependency(c, "runtime", "objc_lookUpClass"); + add_package_dependency(c, "runtime", "sel_registerName"); + + add_package_dependency(c, "runtime", "objc_msgSend"); + add_package_dependency(c, "runtime", "objc_msgSend_fpret"); + add_package_dependency(c, "runtime", "objc_msgSend_fp2ret"); + add_package_dependency(c, "runtime", "objc_msgSend_stret"); +} + +bool check_builtin_objc_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 id, Type *type_hint) { + auto const is_constant_string = [](CheckerContext *c, String const &builtin_name, Ast *expr, String *name_) -> bool { + Operand op = {}; + check_expr(c, &op, expr); + if (op.mode == Addressing_Constant && op.value.kind == ExactValue_String) { + if (name_) *name_ = op.value.value_string; + return true; + } + gbString e = expr_to_string(op.expr); + gbString t = type_to_string(op.type); + error(op.expr, "'%.*s' expected a constant string value, got %s of type %s", LIT(builtin_name), e, t); + gb_string_free(t); + gb_string_free(e); + return false; + }; + String builtin_name = builtin_procs[id].name; + + if (build_context.metrics.os != TargetOs_darwin) { + error(call, "'%.*s' only works on darwin", LIT(builtin_name)); + return false; + } + + + ast_node(ce, CallExpr, call); + switch (id) { + default: + GB_PANIC("Implement objective built-in procedure: %.*s", LIT(builtin_name)); + return false; + + case BuiltinProc_objc_send: { + Type *return_type = nullptr; + + Operand rt = {}; + check_expr_or_type(c, &rt, ce->args[0]); + if (rt.mode == Addressing_Type) { + return_type = rt.type; + } else if (is_operand_nil(rt)) { + return_type = nullptr; + } else { + gbString e = expr_to_string(rt.expr); + error(rt.expr, "'%.*s' expected a type or nil to define the return type of the Objective-C call, got %s", LIT(builtin_name), e); + gb_string_free(e); + return false; + } + + operand->type = return_type; + operand->mode = return_type ? Addressing_Value : Addressing_NoValue; + + String class_name = {}; + String sel_name = {}; + + Type *sel_type = t_objc_SEL; + Operand self = {}; + check_expr_or_type(c, &self, ce->args[1]); + if (self.mode == Addressing_Type) { + if (!internal_check_is_assignable_to(self.type, t_objc_object)) { + gbString t = type_to_string(self.type); + error(self.expr, "'%.*s' expected a type or value derived from intrinsics.objc_object, got type %s", LIT(builtin_name), t); + gb_string_free(t); + return false; + } + if (!(self.type->kind == Type_Named && + self.type->Named.type_name != nullptr && + self.type->Named.type_name->TypeName.objc_class_name != "")) { + gbString t = type_to_string(self.type); + error(self.expr, "'%.*s' expected a named type with the attribute @(obj_class=) , got type %s", LIT(builtin_name), t); + gb_string_free(t); + return false; + } + + sel_type = t_objc_Class; + } else if (!is_operand_value(self) || !check_is_assignable_to(c, &self, t_objc_id)) { + gbString e = expr_to_string(self.expr); + gbString t = type_to_string(self.type); + error(self.expr, "'%.*s'3 expected a type or value derived from intrinsics.objc_object, got '%s' of type %s %d", LIT(builtin_name), e, t, self.type->kind); + gb_string_free(t); + gb_string_free(e); + return false; + } else if (!is_type_pointer(self.type)) { + gbString e = expr_to_string(self.expr); + gbString t = type_to_string(self.type); + error(self.expr, "'%.*s' expected a pointer of a value derived from intrinsics.objc_object, got '%s' of type %s", LIT(builtin_name), e, t); + gb_string_free(t); + gb_string_free(e); + return false; + } else { + Type *type = type_deref(self.type); + if (!(type->kind == Type_Named && + type->Named.type_name != nullptr && + type->Named.type_name->TypeName.objc_class_name != "")) { + gbString t = type_to_string(type); + error(self.expr, "'%.*s' expected a named type with the attribute @(obj_class=) , got type %s", LIT(builtin_name), t); + gb_string_free(t); + return false; + } + } + + + if (!is_constant_string(c, builtin_name, ce->args[2], &sel_name)) { + return false; + } + + isize const arg_offset = 1; + auto param_types = slice_make(permanent_allocator(), ce->args.count-arg_offset); + param_types[0] = t_objc_id; + param_types[1] = sel_type; + + for (isize i = 2+arg_offset; i < ce->args.count; i++) { + Operand x = {}; + check_expr(c, &x, ce->args[i]); + param_types[i-arg_offset] = x.type; + } + + add_objc_proc_type(c, call, return_type, param_types); + + return true; + } break; + + case BuiltinProc_objc_create: { + GB_PANIC("TODO: BuiltinProc_objc_create"); + return false; + } break; + } +} bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 id, Type *type_hint) { ast_node(ce, CallExpr, call); @@ -179,6 +392,8 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 case BuiltinProc_len: case BuiltinProc_min: case BuiltinProc_max: + case BuiltinProc_objc_send: + case BuiltinProc_objc_create: // NOTE(bill): The first arg may be a Type, this will be checked case by case break; @@ -202,7 +417,7 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 break; } - String builtin_name = builtin_procs[id].name;; + String builtin_name = builtin_procs[id].name; if (ce->args.count > 0) { @@ -219,6 +434,10 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 GB_PANIC("Implement built-in procedure: %.*s", LIT(builtin_name)); break; + case BuiltinProc_objc_send: + case BuiltinProc_objc_create: + return check_builtin_objc_procedure(c, operand, call, id, type_hint); + case BuiltinProc___entry_point: operand->mode = Addressing_NoValue; operand->type = nullptr; @@ -3815,6 +4034,8 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 operand->type = t_hasher_proc; break; } + + } return true; diff --git a/src/check_decl.cpp b/src/check_decl.cpp index f6dade812..243dbbbc6 100644 --- a/src/check_decl.cpp +++ b/src/check_decl.cpp @@ -338,6 +338,9 @@ void check_type_decl(CheckerContext *ctx, Entity *e, Ast *init_expr, Type *def) if (decl != nullptr) { AttributeContext ac = {}; check_decl_attributes(ctx, decl->attributes, type_decl_attribute, &ac); + if (e->kind == Entity_TypeName && ac.objc_class != "") { + e->TypeName.objc_class_name = ac.objc_class; + } } diff --git a/src/checker.cpp b/src/checker.cpp index 7fb4fdb29..2ab487592 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -841,6 +841,17 @@ void add_global_enum_constant(Slice const &fields, char const *name, i GB_PANIC("Unfound enum value for global constant: %s %lld", name, cast(long long)value); } +Type *add_global_type_name(Scope *scope, String const &type_name, Type *backing_type) { + Entity *e = alloc_entity_type_name(scope, make_token_ident(type_name), nullptr, EntityState_Resolved); + Type *named_type = alloc_type_named(type_name, backing_type, e); + e->type = named_type; + set_base_type(named_type, backing_type); + if (scope_insert(scope, e)) { + compiler_error("double declaration of %.*s", LIT(e->token.string)); + } + return named_type; +} + void init_universal(void) { BuildContext *bc = &build_context; @@ -985,6 +996,17 @@ void init_universal(void) { t_f64_ptr = alloc_type_pointer(t_f64); t_u8_slice = alloc_type_slice(t_u8); t_string_slice = alloc_type_slice(t_string); + + // intrinsics types for objective-c stuff + { + t_objc_object = add_global_type_name(intrinsics_pkg->scope, str_lit("objc_object"), alloc_type_struct()); + t_objc_selector = add_global_type_name(intrinsics_pkg->scope, str_lit("objc_selector"), alloc_type_struct()); + t_objc_class = add_global_type_name(intrinsics_pkg->scope, str_lit("objc_class"), alloc_type_struct()); + + t_objc_id = alloc_type_pointer(t_objc_object); + t_objc_SEL = alloc_type_pointer(t_objc_selector); + t_objc_Class = alloc_type_pointer(t_objc_class); + } } @@ -1041,6 +1063,9 @@ void init_checker_info(CheckerInfo *i) { semaphore_init(&i->collect_semaphore); mpmc_init(&i->intrinsics_entry_point_usage, a, 1<<10); // just waste some memory here, even if it probably never used + + mutex_init(&i->objc_types_mutex); + map_init(&i->objc_msgSend_types, a); } void destroy_checker_info(CheckerInfo *i) { @@ -1073,6 +1098,9 @@ void destroy_checker_info(CheckerInfo *i) { mutex_destroy(&i->type_and_value_mutex); mutex_destroy(&i->identifier_uses_mutex); mutex_destroy(&i->foreign_mutex); + + mutex_destroy(&i->objc_types_mutex); + map_destroy(&i->objc_msgSend_types); } CheckerContext make_checker_context(Checker *c) { @@ -3161,6 +3189,14 @@ DECL_ATTRIBUTE_PROC(type_decl_attribute) { } else if (name == "private") { // NOTE(bill): Handled elsewhere `check_collect_value_decl` return true; + } else if (name == "objc_class") { + ExactValue ev = check_decl_attribute_value(c, value); + if (ev.kind != ExactValue_String || ev.value_string == "") { + error(elem, "Expected a non-empty string value for '%.*s'", LIT(name)); + } else { + ac->objc_class = ev.value_string; + } + return true; } return false; } diff --git a/src/checker.hpp b/src/checker.hpp index 9a8753efd..b812e10a4 100644 --- a/src/checker.hpp +++ b/src/checker.hpp @@ -107,6 +107,7 @@ struct AttributeContext { String thread_local_model; String deprecated_message; String warning_message; + String objc_class; DeferredProcedure deferred_procedure; bool is_export : 1; bool is_static : 1; @@ -267,6 +268,17 @@ struct UntypedExprInfo { typedef PtrMap UntypedExprInfoMap; typedef MPMCQueue ProcBodyQueue; +enum ObjcMsgKind : u32 { + ObjcMsg_normal, + ObjcMsg_fpret, + ObjcMsg_fp2ret, + ObjcMsg_stret, +}; +struct ObjcMsgData { + ObjcMsgKind kind; + Type *proc_type; +}; + // CheckerInfo stores all the symbol information for a type-checked program struct CheckerInfo { Checker *checker; @@ -340,7 +352,8 @@ struct CheckerInfo { MPMCQueue intrinsics_entry_point_usage; - + BlockingMutex objc_types_mutex; + PtrMap objc_msgSend_types; }; struct CheckerContext { diff --git a/src/checker_builtin_procs.hpp b/src/checker_builtin_procs.hpp index d833a055f..1a9d7d7a0 100644 --- a/src/checker_builtin_procs.hpp +++ b/src/checker_builtin_procs.hpp @@ -250,6 +250,9 @@ BuiltinProc__type_end, BuiltinProc___entry_point, + BuiltinProc_objc_send, + BuiltinProc_objc_create, + BuiltinProc_COUNT, }; gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = { @@ -500,4 +503,7 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = { {STR_LIT(""), 0, false, Expr_Stmt, BuiltinProcPkg_intrinsics}, {STR_LIT("__entry_point"), 0, false, Expr_Stmt, BuiltinProcPkg_intrinsics}, + + {STR_LIT("objc_send"), 3, true, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("objc_create"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, }; diff --git a/src/entity.cpp b/src/entity.cpp index 8327a517e..4d5b3b9e1 100644 --- a/src/entity.cpp +++ b/src/entity.cpp @@ -186,6 +186,7 @@ struct Entity { Type * type_parameter_specialization; String ir_mangled_name; bool is_type_alias; + String objc_class_name; } TypeName; struct { u64 tags; diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index 304effb7f..7941c65a3 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -652,7 +652,53 @@ lbProcedure *lb_create_startup_type_info(lbModule *m) { return p; } -lbProcedure *lb_create_startup_runtime(lbModule *main_module, lbProcedure *startup_type_info, Array &global_variables) { // Startup Runtime +lbProcedure *lb_create_objc_names(lbModule *main_module) { + if (build_context.metrics.os != TargetOs_darwin) { + return nullptr; + } + Type *proc_type = alloc_type_proc(nullptr, nullptr, 0, nullptr, 0, false, ProcCC_CDecl); + lbProcedure *p = lb_create_dummy_procedure(main_module, str_lit("__$init_objc_names"), proc_type); + p->is_startup = true; + return p; +} + +void lb_finalize_objc_names(lbProcedure *p) { + if (p == nullptr) { + return; + } + lbModule *m = p->module; + + LLVMPassManagerRef default_function_pass_manager = LLVMCreateFunctionPassManagerForModule(m->mod); + lb_populate_function_pass_manager(m, default_function_pass_manager, false, build_context.optimization_level); + LLVMFinalizeFunctionPassManager(default_function_pass_manager); + + LLVMSetLinkage(p->value, LLVMInternalLinkage); + lb_begin_procedure_body(p); + for_array(i, m->objc_classes.entries) { + auto const &entry = m->objc_classes.entries[i]; + String name = entry.key.string; + auto args = array_make(permanent_allocator(), 1); + args[0] = lb_const_value(m, t_cstring, exact_value_string(name)); + lbValue ptr = lb_emit_runtime_call(p, "objc_lookUpClass", args); + lb_addr_store(p, entry.value, ptr); + } + + for_array(i, m->objc_selectors.entries) { + auto const &entry = m->objc_selectors.entries[i]; + String name = entry.key.string; + auto args = array_make(permanent_allocator(), 1); + args[0] = lb_const_value(m, t_cstring, exact_value_string(name)); + lbValue ptr = lb_emit_runtime_call(p, "sel_registerName", args); + lb_addr_store(p, entry.value, ptr); + } + + lb_end_procedure_body(p); + + lb_run_function_pass_manager(default_function_pass_manager, p); + +} + +lbProcedure *lb_create_startup_runtime(lbModule *main_module, lbProcedure *startup_type_info, lbProcedure *objc_names, Array &global_variables) { // Startup Runtime LLVMPassManagerRef default_function_pass_manager = LLVMCreateFunctionPassManagerForModule(main_module->mod); lb_populate_function_pass_manager(main_module, default_function_pass_manager, false, build_context.optimization_level); LLVMFinalizeFunctionPassManager(default_function_pass_manager); @@ -666,6 +712,10 @@ lbProcedure *lb_create_startup_runtime(lbModule *main_module, lbProcedure *start LLVMBuildCall2(p->builder, LLVMGetElementType(lb_type(main_module, startup_type_info->type)), startup_type_info->value, nullptr, 0, ""); + if (objc_names) { + LLVMBuildCall2(p->builder, LLVMGetElementType(lb_type(main_module, objc_names->type)), objc_names->value, nullptr, 0, ""); + } + for_array(i, global_variables) { auto *var = &global_variables[i]; if (var->is_initialized) { @@ -1570,8 +1620,10 @@ void lb_generate_code(lbGenerator *gen) { TIME_SECTION("LLVM Runtime Type Information Creation"); lbProcedure *startup_type_info = lb_create_startup_type_info(default_module); + lbProcedure *objc_names = lb_create_objc_names(default_module); + TIME_SECTION("LLVM Runtime Startup Creation (Global Variables)"); - lbProcedure *startup_runtime = lb_create_startup_runtime(default_module, startup_type_info, global_variables); + lbProcedure *startup_runtime = lb_create_startup_runtime(default_module, startup_type_info, objc_names, global_variables); gb_unused(startup_runtime); TIME_SECTION("LLVM Global Procedures and Types"); @@ -1650,6 +1702,8 @@ void lb_generate_code(lbGenerator *gen) { } } + lb_finalize_objc_names(objc_names); + if (build_context.ODIN_DEBUG) { TIME_SECTION("LLVM Debug Info Complete Types and Finalize"); for_array(j, gen->modules.entries) { @@ -1662,6 +1716,7 @@ void lb_generate_code(lbGenerator *gen) { } + TIME_SECTION("LLVM Function Pass"); for_array(i, gen->modules.entries) { lbModule *m = gen->modules.entries[i].value; diff --git a/src/llvm_backend.hpp b/src/llvm_backend.hpp index d7093bc63..087cda22a 100644 --- a/src/llvm_backend.hpp +++ b/src/llvm_backend.hpp @@ -144,6 +144,9 @@ struct lbModule { PtrMap debug_values; Array debug_incomplete_types; + + StringMap objc_classes; + StringMap objc_selectors; }; struct lbGenerator { @@ -293,7 +296,6 @@ struct lbProcedure { bool lb_init_generator(lbGenerator *gen, Checker *c); -void lb_generate_module(lbGenerator *gen); String lb_mangle_name(lbModule *m, Entity *e); String lb_get_entity_name(lbModule *m, Entity *e, String name = {}); @@ -366,7 +368,7 @@ lbContextData *lb_push_context_onto_stack(lbProcedure *p, lbAddr ctx); lbContextData *lb_push_context_onto_stack_from_implicit_parameter(lbProcedure *p); -lbAddr lb_add_global_generated(lbModule *m, Type *type, lbValue value={}); +lbAddr lb_add_global_generated(lbModule *m, Type *type, lbValue value={}, Entity **entity_=nullptr); lbAddr lb_add_local(lbProcedure *p, Type *type, Entity *e=nullptr, bool zero_init=true, i32 param_index=0, bool force_no_init=false); void lb_add_foreign_library_path(lbModule *m, Entity *e); diff --git a/src/llvm_backend_general.cpp b/src/llvm_backend_general.cpp index 2fc21b534..1c98aa77f 100644 --- a/src/llvm_backend_general.cpp +++ b/src/llvm_backend_general.cpp @@ -72,6 +72,9 @@ void lb_init_module(lbModule *m, Checker *c) { map_init(&m->debug_values, a); array_init(&m->debug_incomplete_types, a, 0, 1024); + + string_map_init(&m->objc_classes, a); + string_map_init(&m->objc_selectors, a); } bool lb_init_generator(lbGenerator *gen, Checker *c) { @@ -2450,7 +2453,7 @@ lbValue lb_find_procedure_value_from_entity(lbModule *m, Entity *e) { return {}; } -lbAddr lb_add_global_generated(lbModule *m, Type *type, lbValue value) { +lbAddr lb_add_global_generated(lbModule *m, Type *type, lbValue value, Entity **entity_) { GB_ASSERT(type != nullptr); type = default_type(type); @@ -2476,6 +2479,9 @@ lbAddr lb_add_global_generated(lbModule *m, Type *type, lbValue value) { lb_add_entity(m, e, g); lb_add_member(m, name, g); + + if (entity_) *entity_ = e; + return lb_addr(g); } diff --git a/src/llvm_backend_proc.cpp b/src/llvm_backend_proc.cpp index 7a6fac603..6de0aaed7 100644 --- a/src/llvm_backend_proc.cpp +++ b/src/llvm_backend_proc.cpp @@ -2106,6 +2106,9 @@ lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValue const &tv, res.type = t_uintptr; return res; } + + case BuiltinProc_objc_send: + return lb_handle_obj_send(p, expr); } GB_PANIC("Unhandled built-in procedure %.*s", LIT(builtin_procs[id].name)); diff --git a/src/llvm_backend_utility.cpp b/src/llvm_backend_utility.cpp index 7e2bd7daa..d92f711ba 100644 --- a/src/llvm_backend_utility.cpp +++ b/src/llvm_backend_utility.cpp @@ -1819,3 +1819,99 @@ void lb_set_wasm_export_attributes(LLVMValueRef value, String export_name) { LLVMSetVisibility(value, LLVMDefaultVisibility); LLVMAddTargetDependentFunctionAttr(value, "wasm-export-name", alloc_cstring(permanent_allocator(), export_name)); } + + +lbValue lb_lookup_runtime_procedure(lbModule *m, String const &name); + +lbValue lb_handle_obj_id(lbProcedure *p, Ast *expr) { + TypeAndValue const &tav = type_and_value_of_expr(expr); + if (tav.mode == Addressing_Type) { + Type *type = tav.type; + GB_ASSERT_MSG(type->kind == Type_Named, "%s", type_to_string(type)); + Entity *e = type->Named.type_name; + GB_ASSERT(e->kind == Entity_TypeName); + String name = e->TypeName.objc_class_name; + + lbAddr *found = string_map_get(&p->module->objc_classes, name); + if (found) { + return lb_addr_load(p, *found); + } else { + lbModule *default_module = &p->module->gen->default_module; + Entity *e = nullptr; + lbAddr default_addr = lb_add_global_generated(default_module, t_objc_Class, {}, &e); + + lbValue ptr = lb_find_value_from_entity(p->module, e); + lbAddr local_addr = lb_addr(ptr); + + string_map_set(&default_module->objc_classes, name, default_addr); + if (default_module != p->module) { + string_map_set(&p->module->objc_classes, name, local_addr); + } + return lb_addr_load(p, local_addr); + } + } + + return lb_build_expr(p, expr); +} + + +lbValue lb_handle_obj_selector(lbProcedure *p, String const &name) { + lbAddr *found = string_map_get(&p->module->objc_selectors, name); + if (found) { + return lb_addr_load(p, *found); + } else { + lbModule *default_module = &p->module->gen->default_module; + Entity *e = nullptr; + lbAddr default_addr = lb_add_global_generated(default_module, t_objc_SEL, {}, &e); + + lbValue ptr = lb_find_value_from_entity(p->module, e); + lbAddr local_addr = lb_addr(ptr); + + string_map_set(&default_module->objc_selectors, name, default_addr); + if (default_module != p->module) { + string_map_set(&p->module->objc_selectors, name, local_addr); + } + return lb_addr_load(p, local_addr); + } +} + + +lbValue lb_handle_obj_send(lbProcedure *p, Ast *expr) { + ast_node(ce, CallExpr, expr); + + lbModule *m = p->module; + CheckerInfo *info = m->info; + ObjcMsgData data = map_must_get(&info->objc_msgSend_types, expr); + GB_ASSERT(data.proc_type != nullptr); + + GB_ASSERT(ce->args.count >= 3); + auto args = array_make(permanent_allocator(), 0, ce->args.count-1); + + lbValue id = lb_handle_obj_id(p, ce->args[1]); + Ast *sel_expr = ce->args[2]; + GB_ASSERT(sel_expr->tav.value.kind == ExactValue_String); + lbValue sel = lb_handle_obj_selector(p, sel_expr->tav.value.value_string); + + array_add(&args, id); + array_add(&args, sel); + for (isize i = 3; i < ce->args.count; i++) { + lbValue arg = lb_build_expr(p, ce->args[i]); + array_add(&args, arg); + } + + + lbValue the_proc = {}; + switch (data.kind) { + default: + GB_PANIC("unhandled ObjcMsgKind %u", data.kind); + break; + case ObjcMsg_normal: the_proc = lb_lookup_runtime_procedure(m, str_lit("objc_msgSend")); break; + case ObjcMsg_fpret: the_proc = lb_lookup_runtime_procedure(m, str_lit("objc_msgSend_fpret")); break; + case ObjcMsg_fp2ret: the_proc = lb_lookup_runtime_procedure(m, str_lit("objc_msgSend_fp2ret")); break; + case ObjcMsg_stret: the_proc = lb_lookup_runtime_procedure(m, str_lit("objc_msgSend_stret")); break; + } + + the_proc = lb_emit_conv(p, the_proc, data.proc_type); + + return lb_emit_call(p, the_proc, args); +} diff --git a/src/types.cpp b/src/types.cpp index 9ee6ba359..cdb31c6e1 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -685,6 +685,16 @@ gb_global Type *t_map_header = nullptr; gb_global Type *t_equal_proc = nullptr; gb_global Type *t_hasher_proc = nullptr; +gb_global Type *t_objc_object = nullptr; +gb_global Type *t_objc_selector = nullptr; +gb_global Type *t_objc_class = nullptr; + +gb_global Type *t_objc_id = nullptr; +gb_global Type *t_objc_SEL = nullptr; +gb_global Type *t_objc_Class = nullptr; + + + gb_global RecursiveMutex g_type_mutex; struct TypePath; -- cgit v1.2.3 From f8afda3b221f6c2279a393c2c0fb8ab7ea1d59df Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 11 Feb 2022 22:54:51 +0000 Subject: Add more objc attributes --- core/sys/darwin/Foundation/NSArray.odin | 36 ++++-- core/sys/darwin/Foundation/NSAutoreleasePool.odin | 15 ++- core/sys/darwin/Foundation/NSBundle.odin | 56 ++++++-- core/sys/darwin/Foundation/NSData.odin | 12 ++ core/sys/darwin/Foundation/NSDate.odin | 12 ++ core/sys/darwin/Foundation/NSDictionary.odin | 18 +++ core/sys/darwin/Foundation/NSEnumerator.odin | 15 ++- core/sys/darwin/Foundation/NSError.odin | 22 +++- core/sys/darwin/Foundation/NSLock.odin | 24 ++++ core/sys/darwin/Foundation/NSNotification.odin | 15 +++ core/sys/darwin/Foundation/NSNumber.odin | 149 ++++++++++++---------- core/sys/darwin/Foundation/NSObject.odin | 28 ++-- core/sys/darwin/Foundation/NSString.odin | 24 ++++ core/sys/darwin/Foundation/NSURL.odin | 12 ++ src/check_builtin.cpp | 8 +- src/check_decl.cpp | 63 +++++++++ src/check_type.cpp | 2 + src/checker.cpp | 50 +++++++- src/checker.hpp | 6 +- src/entity.cpp | 23 ++++ src/llvm_backend_expr.cpp | 11 +- src/main.cpp | 32 +---- src/string.cpp | 31 +++++ src/types.cpp | 62 +++++++++ 24 files changed, 586 insertions(+), 140 deletions(-) (limited to 'src/checker.cpp') diff --git a/core/sys/darwin/Foundation/NSArray.odin b/core/sys/darwin/Foundation/NSArray.odin index 435e239a2..e17223ff7 100644 --- a/core/sys/darwin/Foundation/NSArray.odin +++ b/core/sys/darwin/Foundation/NSArray.odin @@ -3,26 +3,40 @@ package objc_Foundation import "core:intrinsics" @(objc_class="NSArray") -Array :: struct($T: typeid) where intrinsics.type_is_pointer(T), intrinsics.type_is_subtype_of(T, ^Object) { - using _: Copying(Array(T)), +Array :: struct { + using _: Copying(Array), } -Array_initWithObjects :: proc(self: ^$A/Array($T), objects: [^]^Object, count: UInteger) -> ^A { - return msgSend(^A, "initWithObjects:count:", objects, count) +@(objc_type=Array, objc_class_name="alloc") +Array_alloc :: proc() -> ^Array { + return msgSend(^Array, Array, "alloc") } -Array_initWithCoder :: proc(self: ^$A/Array($T), coder: ^Coder) -> ^A { - return msgSend(^A, "initWithCoder:", coder) +@(objc_type=Array, objc_name="init") +Array_init :: proc(self: ^Array) -> ^Array { + return msgSend(^Array, self, "init") } -Array_objectAtIndex :: proc(self: ^Array($T), index: UInteger) -> ^Object { - return msgSend(^Object, self, "objectAtIndex:", index) +@(objc_type=Array, objc_name="initWithObjects") +Array_initWithObjects :: proc(self: ^Array, objects: [^]^Object, count: UInteger) -> ^Array { + return msgSend(^Array, self, "initWithObjects:count:", objects, count) +} + +@(objc_type=Array, objc_name="initWithCoder") +Array_initWithCoder :: proc(self: ^Array, coder: ^Coder) -> ^Array { + return msgSend(^Array, self, "initWithCoder:", coder) } -Array_object :: proc(self: ^Array($T), index: UInteger) -> T { - return (T)(Array_objectAtIndex(self, index)) +@(objc_type=Array, objc_name="object") +Array_object :: proc(self: ^Array, index: UInteger) -> ^Object { + return msgSend(^Object, self, "objectAtIndex:", index) +} +@(objc_type=Array, objc_name="objectAs") +Array_objectAs :: proc(self: ^Array, index: UInteger, $T: typeid) -> T where intrinsics.type_is_pointer(T), intrinsics.type_is_subtype_of(T, ^Object) { + return (T)(Array_object(self, index)) } -Array_count :: proc(self: ^Array($T)) -> UInteger { +@(objc_type=Array, objc_name="count") +Array_count :: proc(self: ^Array) -> UInteger { return msgSend(UInteger, self, "count") } diff --git a/core/sys/darwin/Foundation/NSAutoreleasePool.odin b/core/sys/darwin/Foundation/NSAutoreleasePool.odin index 47cbc0e9a..17ec88ba1 100644 --- a/core/sys/darwin/Foundation/NSAutoreleasePool.odin +++ b/core/sys/darwin/Foundation/NSAutoreleasePool.odin @@ -3,12 +3,25 @@ package objc_Foundation @(objc_class="NSAutoreleasePool") AutoreleasePool :: struct {using _: Object} +@(objc_type=AutoreleasePool, objc_class_name="alloc") +AutoreleasePool_alloc :: proc() -> ^AutoreleasePool { + return msgSend(^AutoreleasePool, AutoreleasePool, "alloc") +} + +@(objc_type=AutoreleasePool, objc_name="init") +AutoreleasePool_init :: proc(self: ^AutoreleasePool) -> ^AutoreleasePool { + return msgSend(^AutoreleasePool, self, "init") +} + +@(objc_type=AutoreleasePool, objc_name="drain") AutoreleasePool_drain :: proc(self: ^AutoreleasePool) { msgSend(nil, self, "drain") } +@(objc_type=AutoreleasePool, objc_name="addObject") AutoreleasePool_addObject :: proc(self: ^AutoreleasePool, obj: ^Object) { msgSend(nil, self, "addObject:", obj) } +@(objc_type=AutoreleasePool, objc_name="showPools") AutoreleasePool_showPools :: proc(self: ^AutoreleasePool, obj: ^Object) { msgSend(nil, self, "showPools") } @@ -16,5 +29,5 @@ AutoreleasePool_showPools :: proc(self: ^AutoreleasePool, obj: ^Object) { @(deferred_out=AutoreleasePool_drain) scoped_autoreleasepool :: proc() -> ^AutoreleasePool { - return init(alloc(AutoreleasePool)) + return AutoreleasePool.alloc()->init() } \ No newline at end of file diff --git a/core/sys/darwin/Foundation/NSBundle.odin b/core/sys/darwin/Foundation/NSBundle.odin index 375e15b65..a18809b7e 100644 --- a/core/sys/darwin/Foundation/NSBundle.odin +++ b/core/sys/darwin/Foundation/NSBundle.odin @@ -3,98 +3,120 @@ package objc_Foundation @(objc_class="NSBundle") Bundle :: struct { using _: Object } +@(objc_type=Bundle, objc_class_name="mainBundle") Bundle_mainBundle :: proc() -> ^Bundle { return msgSend(^Bundle, Bundle, "mainBundle") } +@(objc_type=Bundle, objc_class_name="bundleWithPath") Bundle_bundleWithPath :: proc(path: ^String) -> ^Bundle { return msgSend(^Bundle, Bundle, "bundleWithPath:", path) } +@(objc_type=Bundle, objc_class_name="bundleWithURL") Bundle_bundleWithURL :: proc(url: ^URL) -> ^Bundle { return msgSend(^Bundle, Bundle, "bundleWithUrl:", url) } -Bundle_bundle :: proc{ - Bundle_bundleWithPath, - Bundle_bundleWithURL, + + +@(objc_type=Bundle, objc_class_name="alloc") +Bundle_alloc :: proc() -> ^Bundle { + return msgSend(^Bundle, Bundle, "alloc") } +@(objc_type=Bundle, objc_name="init") +Bundle_init :: proc(self: ^Bundle) -> ^Bundle { + return msgSend(^Bundle, self, "init") +} +@(objc_type=Bundle, objc_name="initWithPath") Bundle_initWithPath :: proc(self: ^Bundle, path: ^String) -> ^Bundle { return msgSend(^Bundle, self, "initWithPath:", path) } +@(objc_type=Bundle, objc_name="initWithURL") Bundle_initWithURL :: proc(self: ^Bundle, url: ^URL) -> ^Bundle { return msgSend(^Bundle, self, "initWithUrl:", url) } -Bundle_init :: proc{ - Bundle_initWithPath, - Bundle_initWithURL, -} - -Bundle_allBundles :: proc() -> (all: ^Array(^Bundle)) { +@(objc_type=Bundle, objc_name="allBundles") +Bundle_allBundles :: proc() -> (all: ^Array) { return msgSend(type_of(all), Bundle, "allBundles") } -Bundle_allFrameworks :: proc() -> (all: ^Array(^Object)) { +@(objc_type=Bundle, objc_name="allFrameworks") +Bundle_allFrameworks :: proc() -> (all: ^Array) { return msgSend(type_of(all), Bundle, "allFrameworks") } +@(objc_type=Bundle, objc_name="load") Bundle_load :: proc(self: ^Bundle) -> BOOL { return msgSend(BOOL, self, "load") } +@(objc_type=Bundle, objc_name="unload") Bundle_unload :: proc(self: ^Bundle) -> BOOL { return msgSend(BOOL, self, "unload") } +@(objc_type=Bundle, objc_name="isLoaded") Bundle_isLoaded :: proc(self: ^Bundle) -> BOOL { return msgSend(BOOL, self, "isLoaded") } +@(objc_type=Bundle, objc_name="preflightAndReturnError") Bundle_preflightAndReturnError :: proc(self: ^Bundle) -> (ok: BOOL, error: ^Error) { ok = msgSend(BOOL, self, "preflightAndReturnError:", &error) return } +@(objc_type=Bundle, objc_name="loadAndReturnError") Bundle_loadAndReturnError :: proc(self: ^Bundle) -> (ok: BOOL, error: ^Error) { ok = msgSend(BOOL, self, "loadAndReturnError:", &error) return } +@(objc_type=Bundle, objc_name="bundleURL") Bundle_bundleURL :: proc(self: ^Bundle) -> ^URL { return msgSend(^URL, self, "bundleURL") } +@(objc_type=Bundle, objc_name="resourceURL") Bundle_resourceURL :: proc(self: ^Bundle) -> ^URL { return msgSend(^URL, self, "resourceURL") } +@(objc_type=Bundle, objc_name="executableURL") Bundle_executableURL :: proc(self: ^Bundle) -> ^URL { return msgSend(^URL, self, "executableURL") } +@(objc_type=Bundle, objc_name="URLForAuxiliaryExecutable") Bundle_URLForAuxiliaryExecutable :: proc(self: ^Bundle, executableName: ^String) -> ^URL { return msgSend(^URL, self, "URLForAuxiliaryExecutable:", executableName) } +@(objc_type=Bundle, objc_name="privateFrameworksURL") Bundle_privateFrameworksURL :: proc(self: ^Bundle) -> ^URL { return msgSend(^URL, self, "privateFrameworksURL") } +@(objc_type=Bundle, objc_name="sharedFrameworksURL") Bundle_sharedFrameworksURL :: proc(self: ^Bundle) -> ^URL { return msgSend(^URL, self, "sharedFrameworksURL") } +@(objc_type=Bundle, objc_name="sharedSupportURL") Bundle_sharedSupportURL :: proc(self: ^Bundle) -> ^URL { return msgSend(^URL, self, "sharedSupportURL") } +@(objc_type=Bundle, objc_name="builtInPlugInsURL") Bundle_builtInPlugInsURL :: proc(self: ^Bundle) -> ^URL { return msgSend(^URL, self, "builtInPlugInsURL") } +@(objc_type=Bundle, objc_name="appStoreReceiptURL") Bundle_appStoreReceiptURL :: proc(self: ^Bundle) -> ^URL { return msgSend(^URL, self, "appStoreReceiptURL") } @@ -102,60 +124,74 @@ Bundle_appStoreReceiptURL :: proc(self: ^Bundle) -> ^URL { +@(objc_type=Bundle, objc_name="bundlePath") Bundle_bundlePath :: proc(self: ^Bundle) -> ^String { return msgSend(^String, self, "bundlePath") } +@(objc_type=Bundle, objc_name="resourcePath") Bundle_resourcePath :: proc(self: ^Bundle) -> ^String { return msgSend(^String, self, "resourcePath") } +@(objc_type=Bundle, objc_name="executablePath") Bundle_executablePath :: proc(self: ^Bundle) -> ^String { return msgSend(^String, self, "executablePath") } +@(objc_type=Bundle, objc_name="PathForAuxiliaryExecutable") Bundle_PathForAuxiliaryExecutable :: proc(self: ^Bundle, executableName: ^String) -> ^String { return msgSend(^String, self, "PathForAuxiliaryExecutable:", executableName) } +@(objc_type=Bundle, objc_name="privateFrameworksPath") Bundle_privateFrameworksPath :: proc(self: ^Bundle) -> ^String { return msgSend(^String, self, "privateFrameworksPath") } +@(objc_type=Bundle, objc_name="sharedFrameworksPath") Bundle_sharedFrameworksPath :: proc(self: ^Bundle) -> ^String { return msgSend(^String, self, "sharedFrameworksPath") } +@(objc_type=Bundle, objc_name="sharedSupportPath") Bundle_sharedSupportPath :: proc(self: ^Bundle) -> ^String { return msgSend(^String, self, "sharedSupportPath") } +@(objc_type=Bundle, objc_name="builtInPlugInsPath") Bundle_builtInPlugInsPath :: proc(self: ^Bundle) -> ^String { return msgSend(^String, self, "builtInPlugInsPath") } +@(objc_type=Bundle, objc_name="appStoreReceiptPath") Bundle_appStoreReceiptPath :: proc(self: ^Bundle) -> ^String { return msgSend(^String, self, "appStoreReceiptPath") } +@(objc_type=Bundle, objc_name="bundleIdentifier") Bundle_bundleIdentifier :: proc(self: ^Bundle) -> ^String { return msgSend(^String, self, "bundleIdentifier") } +@(objc_type=Bundle, objc_name="infoDictionary") Bundle_infoDictionary :: proc(self: ^Bundle) -> ^Dictionary { return msgSend(^Dictionary, self, "infoDictionary") } +@(objc_type=Bundle, objc_name="localizedInfoDictionary") Bundle_localizedInfoDictionary :: proc(self: ^Bundle) -> ^Dictionary { return msgSend(^Dictionary, self, "localizedInfoDictionary") } +@(objc_type=Bundle, objc_name="objectForInfoDictionaryKey") Bundle_objectForInfoDictionaryKey :: proc(self: ^Bundle, key: ^String) -> ^Object { return msgSend(^Object, self, "objectForInfoDictionaryKey:", key) } +@(objc_type=Bundle, objc_name="localizedStringForKey") Bundle_localizedStringForKey :: proc(self: ^Bundle, key: ^String, value: ^String = nil, tableName: ^String = nil) -> ^String { return msgSend(^String, self, "localizedStringForKey:value:table:", key, value, tableName) } diff --git a/core/sys/darwin/Foundation/NSData.odin b/core/sys/darwin/Foundation/NSData.odin index 93bb3ae0e..e28f6a644 100644 --- a/core/sys/darwin/Foundation/NSData.odin +++ b/core/sys/darwin/Foundation/NSData.odin @@ -3,10 +3,22 @@ package objc_Foundation @(objc_class="NSData") Data :: struct {using _: Copying(Data)} +@(objc_type=Data, objc_class_name="alloc") +Data_alloc :: proc() -> ^Data { + return msgSend(^Data, Data, "alloc") +} + +@(objc_type=Data, objc_name="init") +Data_init :: proc(self: ^Data) -> ^Data { + return msgSend(^Data, self, "init") +} + +@(objc_type=Data, objc_name="mutableBytes") Data_mutableBytes :: proc(self: ^Data) -> rawptr { return msgSend(rawptr, self, "mutableBytes") } +@(objc_type=Data, objc_name="length") Data_length :: proc(self: ^Data) -> UInteger { return msgSend(UInteger, self, "length") } \ No newline at end of file diff --git a/core/sys/darwin/Foundation/NSDate.odin b/core/sys/darwin/Foundation/NSDate.odin index 4b298ee24..85bb14c3e 100644 --- a/core/sys/darwin/Foundation/NSDate.odin +++ b/core/sys/darwin/Foundation/NSDate.odin @@ -3,6 +3,18 @@ package objc_Foundation @(objc_class="NSDate") Date :: struct {using _: Copying(Date)} +@(objc_type=Date, objc_class_name="alloc") +Date_alloc :: proc() -> ^Date { + return msgSend(^Date, Date, "alloc") +} + +@(objc_type=Date, objc_name="init") +Date_init :: proc(self: ^Date) -> ^Date { + return msgSend(^Date, self, "init") +} + + +@(objc_type=Date, objc_name="dateWithTimeIntervalSinceNow") Date_dateWithTimeIntervalSinceNow :: proc(secs: TimeInterval) -> ^Date { return msgSend(^Date, Date, "dateWithTimeIntervalSinceNow:", secs) } \ No newline at end of file diff --git a/core/sys/darwin/Foundation/NSDictionary.odin b/core/sys/darwin/Foundation/NSDictionary.odin index f82b8cffd..3eb378dc7 100644 --- a/core/sys/darwin/Foundation/NSDictionary.odin +++ b/core/sys/darwin/Foundation/NSDictionary.odin @@ -3,31 +3,49 @@ package objc_Foundation @(objc_class="NSDictionary") Dictionary :: struct {using _: Copying(Dictionary)} +@(objc_type=Dictionary, objc_class_name="dictionary") Dictionary_dictionary :: proc() -> ^Dictionary { return msgSend(^Dictionary, Dictionary, "dictionary") } +@(objc_type=Dictionary, objc_class_name="dictionaryWithObject") Dictionary_dictionaryWithObject :: proc(object: ^Object, forKey: ^Object) -> ^Dictionary { return msgSend(^Dictionary, Dictionary, "dictionaryWithObject:forKey:", object, forKey) } +@(objc_type=Dictionary, objc_class_name="dictionaryWithObjects") Dictionary_dictionaryWithObjects :: proc(objects: [^]^Object, forKeys: [^]^Object, count: UInteger) -> ^Dictionary { return msgSend(^Dictionary, Dictionary, "dictionaryWithObjects:forKeys:count", objects, forKeys, count) } +@(objc_type=Dictionary, objc_class_name="alloc") +Dictionary_alloc :: proc() -> ^Dictionary { + return msgSend(^Dictionary, Dictionary, "alloc") +} + +@(objc_type=Dictionary, objc_name="init") +Dictionary_init :: proc(self: ^Dictionary) -> ^Dictionary { + return msgSend(^Dictionary, self, "init") +} + + +@(objc_type=Dictionary, objc_name="initWithObjects") Dictionary_initWithObjects :: proc(self: ^Dictionary, objects: [^]^Object, forKeys: [^]^Object, count: UInteger) -> ^Dictionary { return msgSend(^Dictionary, self, "initWithObjects:forKeys:count", objects, forKeys, count) } +@(objc_type=Dictionary, objc_name="objectForKey") Dictionary_objectForKey :: proc(self: ^Dictionary, key: ^Object) -> ^Object { return msgSend(^Dictionary, self, "objectForKey:", key) } +@(objc_type=Dictionary, objc_name="count") Dictionary_count :: proc(self: ^Dictionary) -> UInteger { return msgSend(UInteger, self, "count") } +@(objc_type=Dictionary, objc_name="keyEnumerator") Dictionary_keyEnumerator :: proc(self: ^Dictionary, $KeyType: typeid) -> (enumerator: ^Enumerator(KeyType)) { return msgSend(type_of(enumerator), self, "keyEnumerator") } diff --git a/core/sys/darwin/Foundation/NSEnumerator.odin b/core/sys/darwin/Foundation/NSEnumerator.odin index b6adf2b98..8a5a32e69 100644 --- a/core/sys/darwin/Foundation/NSEnumerator.odin +++ b/core/sys/darwin/Foundation/NSEnumerator.odin @@ -18,6 +18,19 @@ Enumerator :: struct($T: typeid) where intrinsics.type_is_pointer(T), intrinsics using _: FastEnumeration, } + +@(objc_type=FastEnumeration, objc_class_name="alloc") +FastEnumeration_alloc :: proc() -> ^FastEnumeration { + return msgSend(^FastEnumeration, FastEnumeration, "alloc") +} + +@(objc_type=FastEnumeration, objc_name="init") +FastEnumeration_init :: proc(self: ^FastEnumeration) -> ^FastEnumeration { + return msgSend(^FastEnumeration, self, "init") +} + + +@(objc_type=FastEnumeration, objc_name="countByEnumerating") FastEnumeration_countByEnumerating :: proc(self: ^FastEnumeration, state: ^FastEnumerationState, buffer: [^]^Object, len: UInteger) -> UInteger { return msgSend(UInteger, self, "countByEnumeratingWithState:objects:count:", state, buffer, len) } @@ -26,7 +39,7 @@ Enumerator_nextObject :: proc(self: ^$E/Enumerator($T)) -> T { return msgSend(T, self, "nextObject") } -Enumerator_allObjects :: proc(self: ^$E/Enumerator($T)) -> (all: Array(T)) { +Enumerator_allObjects :: proc(self: ^$E/Enumerator($T)) -> (all: ^Array) { return msgSend(type_of(all), self, "allObjects") } diff --git a/core/sys/darwin/Foundation/NSError.odin b/core/sys/darwin/Foundation/NSError.odin index aebf01035..bff0088e9 100644 --- a/core/sys/darwin/Foundation/NSError.odin +++ b/core/sys/darwin/Foundation/NSError.odin @@ -31,38 +31,58 @@ foreign Foundation { @(objc_class="NSError") Error :: struct { using _: Copying(Error) } + +@(objc_type=Error, objc_class_name="alloc") +Error_alloc :: proc() -> ^Error { + return msgSend(^Error, Error, "alloc") +} + +@(objc_type=Error, objc_name="init") +Error_init :: proc(self: ^Error) -> ^Error { + return msgSend(^Error, self, "init") +} + +@(objc_type=Error, objc_class_name="errorWithDomain") Error_errorWithDomain :: proc(domain: ErrorDomain, code: Integer, userInfo: ^Dictionary) -> ^Error { return msgSend(^Error, Error, "errorWithDomain:code:userInfo:", domain, code, userInfo) } +@(objc_type=Error, objc_name="initWithDomain") Error_initWithDomain :: proc(self: ^Error, domain: ErrorDomain, code: Integer, userInfo: ^Dictionary) -> ^Error { return msgSend(^Error, self, "initWithDomain:code:userInfo:", domain, code, userInfo) } +@(objc_type=Error, objc_name="code") Error_code :: proc(self: ^Error) -> Integer { return msgSend(Integer, self, "code") } +@(objc_type=Error, objc_name="domain") Error_domain :: proc(self: ^Error) -> ErrorDomain { return msgSend(ErrorDomain, self, "domain") } +@(objc_type=Error, objc_name="userInfo") Error_userInfo :: proc(self: ^Error) -> ^Dictionary { return msgSend(^Dictionary, self, "userInfo") } +@(objc_type=Error, objc_name="localizedDescription") Error_localizedDescription :: proc(self: ^Error) -> ^String { return msgSend(^String, self, "localizedDescription") } -Error_localizedRecoveryOptions :: proc(self: ^Error) -> (options: ^Array(^Object)) { +@(objc_type=Error, objc_name="localizedRecoveryOptions") +Error_localizedRecoveryOptions :: proc(self: ^Error) -> (options: ^Array) { return msgSend(type_of(options), self, "localizedRecoveryOptions") } +@(objc_type=Error, objc_name="localizedRecoverySuggestion") Error_localizedRecoverySuggestion :: proc(self: ^Error) -> ^String { return msgSend(^String, self, "localizedRecoverySuggestion") } +@(objc_type=Error, objc_name="localizedFailureReason") Error_localizedFailureReason :: proc(self: ^Error) -> ^String { return msgSend(^String, self, "localizedFailureReason") } \ No newline at end of file diff --git a/core/sys/darwin/Foundation/NSLock.odin b/core/sys/darwin/Foundation/NSLock.odin index 0e76dfc62..3bcc06eab 100644 --- a/core/sys/darwin/Foundation/NSLock.odin +++ b/core/sys/darwin/Foundation/NSLock.odin @@ -12,18 +12,42 @@ Locking_unlock :: proc(self: ^Locking($T)) { @(objc_class="NSCondition") Condition :: struct {using _: Locking(Condition) } + +@(objc_type=Condition, objc_class_name="alloc") +Condition_alloc :: proc() -> ^Condition { + return msgSend(^Condition, Condition, "alloc") +} + +@(objc_type=Condition, objc_name="init") +Condition_init :: proc(self: ^Condition) -> ^Condition { + return msgSend(^Condition, self, "init") +} + +@(objc_type=Condition, objc_name="wait") Condition_wait :: proc(self: ^Condition) { msgSend(nil, self, "wait") } +@(objc_type=Condition, objc_name="waitUntilDate") Condition_waitUntilDate :: proc(self: ^Condition, limit: ^Date) -> BOOL { return msgSend(BOOL, self, "waitUntilDate:", limit) } +@(objc_type=Condition, objc_name="signal") Condition_signal :: proc(self: ^Condition) { msgSend(nil, self, "signal") } +@(objc_type=Condition, objc_name="broadcast") Condition_broadcast :: proc(self: ^Condition) { msgSend(nil, self, "broadcast") +} + +@(objc_type=Condition, objc_name="lock") +Condition_lock :: proc(self: ^Condition) { + msgSend(nil, self, "lock") +} +@(objc_type=Condition, objc_name="unlock") +Condition_unlock :: proc(self: ^Condition) { + msgSend(nil, self, "unlock") } \ No newline at end of file diff --git a/core/sys/darwin/Foundation/NSNotification.odin b/core/sys/darwin/Foundation/NSNotification.odin index fa9160cc8..d8b142e53 100644 --- a/core/sys/darwin/Foundation/NSNotification.odin +++ b/core/sys/darwin/Foundation/NSNotification.odin @@ -3,14 +3,29 @@ package objc_Foundation @(objc_class="NSNotification") Notification :: struct{using _: Object} + +@(objc_type=Notification, objc_class_name="alloc") +Notification_alloc :: proc() -> ^Notification { + return msgSend(^Notification, Notification, "alloc") +} + +@(objc_type=Notification, objc_name="init") +Notification_init :: proc(self: ^Notification) -> ^Notification { + return msgSend(^Notification, self, "init") +} + + +@(objc_type=Notification, objc_name="name") Notification_name :: proc(self: ^Notification) -> ^String { return msgSend(^String, self, "name") } +@(objc_type=Notification, objc_name="object") Notification_object :: proc(self: ^Notification) -> ^Object { return msgSend(^Object, self, "object") } +@(objc_type=Notification, objc_name="userInfo") Notification_userInfo :: proc(self: ^Notification) -> ^Dictionary { return msgSend(^Dictionary, self, "userInfo") } \ No newline at end of file diff --git a/core/sys/darwin/Foundation/NSNumber.odin b/core/sys/darwin/Foundation/NSNumber.odin index 2630e6daa..f77b0866a 100644 --- a/core/sys/darwin/Foundation/NSNumber.odin +++ b/core/sys/darwin/Foundation/NSNumber.odin @@ -8,35 +8,53 @@ import "core:c" @(objc_class="NSValue") Value :: struct{using _: Copying(Value)} +@(objc_type=Value, objc_class_name="alloc") +Value_alloc :: proc() -> ^Value { + return msgSend(^Value, Value, "alloc") +} + +@(objc_type=Value, objc_name="init") +Value_init :: proc(self: ^Value) -> ^Value { + return msgSend(^Value, self, "init") +} + +@(objc_type=Value, objc_class_name="valueWithBytes") Value_valueWithBytes :: proc(value: rawptr, type: cstring) -> ^Value { return msgSend(^Value, Value, "valueWithBytes:objCType:", value, type) } +@(objc_type=Value, objc_class_name="valueWithPointer") Value_valueWithPointer :: proc(pointer: rawptr) -> ^Value { return msgSend(^Value, Value, "valueWithPointer:", pointer) } +@(objc_type=Value, objc_name="initWithBytes") Value_initWithBytes :: proc(self: ^Value, value: rawptr, type: cstring) -> ^Value { return msgSend(^Value, self, "initWithBytes:objCType:", value, type) } -Value_initWithCoder :: proc(coder: ^Coder) -> ^Value { - return msgSend(^Value, Value, "initWithCoder:", coder) +@(objc_type=Value, objc_name="initWithCoder") +Value_initWithCoder :: proc(self: ^Value, coder: ^Coder) -> ^Value { + return msgSend(^Value, self, "initWithCoder:", coder) } +@(objc_type=Value, objc_name="getValue") Value_getValue :: proc(self: ^Value, value: rawptr, size: UInteger) { msgSend(nil, self, "getValue:size:", value, size) } +@(objc_type=Value, objc_name="objCType") Value_objCType :: proc(self: ^Value) -> cstring { return msgSend(cstring, self, "objCType") } +@(objc_type=Value, objc_name="isEqualToValue") Value_isEqualToValue :: proc(self, other: ^Value) -> BOOL { return msgSend(BOOL, self, "isEqualToValue:", other) } +@(objc_type=Value, objc_name="pointerValue") Value_pointerValue :: proc(self: ^Value) -> rawptr { return msgSend(rawptr, self, "pointerValue") } @@ -46,19 +64,29 @@ Value_pointerValue :: proc(self: ^Value) -> rawptr { Number :: struct{using _: Copying(Number), using _: Value} -Number_numberWithI8 :: proc(value: i8) -> ^Number { return msgSend(^Number, Number, "numberWithChar:", value) } -Number_numberWithU8 :: proc(value: u8) -> ^Number { return msgSend(^Number, Number, "numberWithUnsignedChar:", value) } -Number_numberWithI16 :: proc(value: i16) -> ^Number { return msgSend(^Number, Number, "numberWithShort:", value) } -Number_numberWithU16 :: proc(value: u16) -> ^Number { return msgSend(^Number, Number, "numberWithUnsignedShort:", value) } -Number_numberWithI32 :: proc(value: i32) -> ^Number { return msgSend(^Number, Number, "numberWithInt:", value) } -Number_numberWithU32 :: proc(value: u32) -> ^Number { return msgSend(^Number, Number, "numberWithUnsignedInt:", value) } -Number_numberWithInt :: proc(value: int) -> ^Number { return msgSend(^Number, Number, "numberWithLong:", value) } -Number_numberWithUint :: proc(value: uint) -> ^Number { return msgSend(^Number, Number, "numberWithUnsignedLong:", value) } -Number_numberWithU64 :: proc(value: u64) -> ^Number { return msgSend(^Number, Number, "numberWithLongLong:", value) } -Number_numberWithI64 :: proc(value: i64) -> ^Number { return msgSend(^Number, Number, "numberWithUnsignedLongLong:", value) } -Number_numberWithF32 :: proc(value: f32) -> ^Number { return msgSend(^Number, Number, "numberWithFloat:", value) } -Number_numberWithF64 :: proc(value: f64) -> ^Number { return msgSend(^Number, Number, "numberWithDouble:", value) } -Number_numberWithBool :: proc(value: BOOL) -> ^Number { return msgSend(^Number, Number, "numberWithBool:", value) } +@(objc_type=Number, objc_class_name="alloc") +Number_alloc :: proc() -> ^Number { + return msgSend(^Number, Number, "alloc") +} + +@(objc_type=Number, objc_name="init") +Number_init :: proc(self: ^Number) -> ^Number { + return msgSend(^Number, self, "init") +} + +@(objc_type=Number, objc_class_name="numberWithI8") Number_numberWithI8 :: proc(value: i8) -> ^Number { return msgSend(^Number, Number, "numberWithChar:", value) } +@(objc_type=Number, objc_class_name="numberWithU8") Number_numberWithU8 :: proc(value: u8) -> ^Number { return msgSend(^Number, Number, "numberWithUnsignedChar:", value) } +@(objc_type=Number, objc_class_name="numberWithI16") Number_numberWithI16 :: proc(value: i16) -> ^Number { return msgSend(^Number, Number, "numberWithShort:", value) } +@(objc_type=Number, objc_class_name="numberWithU16") Number_numberWithU16 :: proc(value: u16) -> ^Number { return msgSend(^Number, Number, "numberWithUnsignedShort:", value) } +@(objc_type=Number, objc_class_name="numberWithI32") Number_numberWithI32 :: proc(value: i32) -> ^Number { return msgSend(^Number, Number, "numberWithInt:", value) } +@(objc_type=Number, objc_class_name="numberWithU32") Number_numberWithU32 :: proc(value: u32) -> ^Number { return msgSend(^Number, Number, "numberWithUnsignedInt:", value) } +@(objc_type=Number, objc_class_name="numberWithInt") Number_numberWithInt :: proc(value: int) -> ^Number { return msgSend(^Number, Number, "numberWithLong:", value) } +@(objc_type=Number, objc_class_name="numberWithUint") Number_numberWithUint :: proc(value: uint) -> ^Number { return msgSend(^Number, Number, "numberWithUnsignedLong:", value) } +@(objc_type=Number, objc_class_name="numberWithU64") Number_numberWithU64 :: proc(value: u64) -> ^Number { return msgSend(^Number, Number, "numberWithLongLong:", value) } +@(objc_type=Number, objc_class_name="numberWithI64") Number_numberWithI64 :: proc(value: i64) -> ^Number { return msgSend(^Number, Number, "numberWithUnsignedLongLong:", value) } +@(objc_type=Number, objc_class_name="numberWithF32") Number_numberWithF32 :: proc(value: f32) -> ^Number { return msgSend(^Number, Number, "numberWithFloat:", value) } +@(objc_type=Number, objc_class_name="numberWithF64") Number_numberWithF64 :: proc(value: f64) -> ^Number { return msgSend(^Number, Number, "numberWithDouble:", value) } +@(objc_type=Number, objc_class_name="numberWithBool") Number_numberWithBool :: proc(value: BOOL) -> ^Number { return msgSend(^Number, Number, "numberWithBool:", value) } Number_number :: proc{ Number_numberWithI8, @@ -76,62 +104,49 @@ Number_number :: proc{ Number_numberWithBool, } -Number_initWithI8 :: proc(self: ^Number, value: i8) -> ^Number { return msgSend(^Number, self, "initWithChar:", value) } -Number_initWithU8 :: proc(self: ^Number, value: u8) -> ^Number { return msgSend(^Number, self, "initWithUnsignedChar:", value) } -Number_initWithI16 :: proc(self: ^Number, value: i16) -> ^Number { return msgSend(^Number, self, "initWithShort:", value) } -Number_initWithU16 :: proc(self: ^Number, value: u16) -> ^Number { return msgSend(^Number, self, "initWithUnsignedShort:", value) } -Number_initWithI32 :: proc(self: ^Number, value: i32) -> ^Number { return msgSend(^Number, self, "initWithInt:", value) } -Number_initWithU32 :: proc(self: ^Number, value: u32) -> ^Number { return msgSend(^Number, self, "initWithUnsignedInt:", value) } -Number_initWithInt :: proc(self: ^Number, value: int) -> ^Number { return msgSend(^Number, self, "initWithLong:", value) } -Number_initWithUint :: proc(self: ^Number, value: uint) -> ^Number { return msgSend(^Number, self, "initWithUnsignedLong:", value) } -Number_initWithU64 :: proc(self: ^Number, value: u64) -> ^Number { return msgSend(^Number, self, "initWithLongLong:", value) } -Number_initWithI64 :: proc(self: ^Number, value: i64) -> ^Number { return msgSend(^Number, self, "initWithUnsignedLongLong:", value) } -Number_initWithF32 :: proc(self: ^Number, value: f32) -> ^Number { return msgSend(^Number, self, "initWithFloat:", value) } -Number_initWithF64 :: proc(self: ^Number, value: f64) -> ^Number { return msgSend(^Number, self, "initWithDouble:", value) } -Number_initWithBool :: proc(self: ^Number, value: BOOL) -> ^Number { return msgSend(^Number, self, "initWithBool:", value) } - - -Number_init :: proc{ - Number_initWithI8, - Number_initWithU8, - Number_initWithI16, - Number_initWithU16, - Number_initWithI32, - Number_initWithU32, - Number_initWithInt, - Number_initWithUint, - Number_initWithU64, - Number_initWithI64, - Number_initWithF32, - Number_initWithF64, - Number_initWithBool, -} - -Number_i8Value :: proc(self: ^Number) -> i8 { return msgSend(i8, self, "charValue") } -Number_u8Value :: proc(self: ^Number) -> u8 { return msgSend(u8, self, "unsignedCharValue") } -Number_i16Value :: proc(self: ^Number) -> i16 { return msgSend(i16, self, "shortValue") } -Number_u16Value :: proc(self: ^Number) -> u16 { return msgSend(u16, self, "unsignedShortValue") } -Number_i32Value :: proc(self: ^Number) -> i32 { return msgSend(i32, self, "intValue") } -Number_u32Value :: proc(self: ^Number) -> u32 { return msgSend(u32, self, "unsignedIntValue") } -Number_intValue :: proc(self: ^Number) -> int { return msgSend(int, self, "longValue") } -Number_uintValue :: proc(self: ^Number) -> uint { return msgSend(uint, self, "unsignedLongValue") } -Number_u64Value :: proc(self: ^Number) -> u64 { return msgSend(u64, self, "longLongValue") } -Number_i64Value :: proc(self: ^Number) -> i64 { return msgSend(i64, self, "unsignedLongLongValue") } -Number_f32Value :: proc(self: ^Number) -> f32 { return msgSend(f32, self, "floatValue") } -Number_f64Value :: proc(self: ^Number) -> f64 { return msgSend(f64, self, "doubleValue") } -Number_boolValue :: proc(self: ^Number) -> BOOL { return msgSend(BOOL, self, "boolValue") } -Number_integerValue :: proc(self: ^Number) -> Integer { return msgSend(Integer, self, "integerValue") } -Number_uintegerValue :: proc(self: ^Number) -> UInteger { return msgSend(UInteger, self, "unsignedIntegerValue") } -Number_stringValue :: proc(self: ^Number) -> ^String { return msgSend(^String, self, "stringValue") } - -Number_compare :: proc(a, b: ^Number) -> ComparisonResult { - return msgSend(ComparisonResult, a, "compare:", b) +@(objc_type=Number, objc_name="initWithI8") Number_initWithI8 :: proc(self: ^Number, value: i8) -> ^Number { return msgSend(^Number, self, "initWithChar:", value) } +@(objc_type=Number, objc_name="initWithU8") Number_initWithU8 :: proc(self: ^Number, value: u8) -> ^Number { return msgSend(^Number, self, "initWithUnsignedChar:", value) } +@(objc_type=Number, objc_name="initWithI16") Number_initWithI16 :: proc(self: ^Number, value: i16) -> ^Number { return msgSend(^Number, self, "initWithShort:", value) } +@(objc_type=Number, objc_name="initWithU16") Number_initWithU16 :: proc(self: ^Number, value: u16) -> ^Number { return msgSend(^Number, self, "initWithUnsignedShort:", value) } +@(objc_type=Number, objc_name="initWithI32") Number_initWithI32 :: proc(self: ^Number, value: i32) -> ^Number { return msgSend(^Number, self, "initWithInt:", value) } +@(objc_type=Number, objc_name="initWithU32") Number_initWithU32 :: proc(self: ^Number, value: u32) -> ^Number { return msgSend(^Number, self, "initWithUnsignedInt:", value) } +@(objc_type=Number, objc_name="initWithInt") Number_initWithInt :: proc(self: ^Number, value: int) -> ^Number { return msgSend(^Number, self, "initWithLong:", value) } +@(objc_type=Number, objc_name="initWithUint") Number_initWithUint :: proc(self: ^Number, value: uint) -> ^Number { return msgSend(^Number, self, "initWithUnsignedLong:", value) } +@(objc_type=Number, objc_name="initWithU64") Number_initWithU64 :: proc(self: ^Number, value: u64) -> ^Number { return msgSend(^Number, self, "initWithLongLong:", value) } +@(objc_type=Number, objc_name="initWithI64") Number_initWithI64 :: proc(self: ^Number, value: i64) -> ^Number { return msgSend(^Number, self, "initWithUnsignedLongLong:", value) } +@(objc_type=Number, objc_name="initWithF32") Number_initWithF32 :: proc(self: ^Number, value: f32) -> ^Number { return msgSend(^Number, self, "initWithFloat:", value) } +@(objc_type=Number, objc_name="initWithF64") Number_initWithF64 :: proc(self: ^Number, value: f64) -> ^Number { return msgSend(^Number, self, "initWithDouble:", value) } +@(objc_type=Number, objc_name="initWithBool") Number_initWithBool :: proc(self: ^Number, value: BOOL) -> ^Number { return msgSend(^Number, self, "initWithBool:", value) } + + +@(objc_type=Number, objc_name="i8Value") Number_i8Value :: proc(self: ^Number) -> i8 { return msgSend(i8, self, "charValue") } +@(objc_type=Number, objc_name="u8Value") Number_u8Value :: proc(self: ^Number) -> u8 { return msgSend(u8, self, "unsignedCharValue") } +@(objc_type=Number, objc_name="i16Value") Number_i16Value :: proc(self: ^Number) -> i16 { return msgSend(i16, self, "shortValue") } +@(objc_type=Number, objc_name="u16Value") Number_u16Value :: proc(self: ^Number) -> u16 { return msgSend(u16, self, "unsignedShortValue") } +@(objc_type=Number, objc_name="i32Value") Number_i32Value :: proc(self: ^Number) -> i32 { return msgSend(i32, self, "intValue") } +@(objc_type=Number, objc_name="u32Value") Number_u32Value :: proc(self: ^Number) -> u32 { return msgSend(u32, self, "unsignedIntValue") } +@(objc_type=Number, objc_name="intValue") Number_intValue :: proc(self: ^Number) -> int { return msgSend(int, self, "longValue") } +@(objc_type=Number, objc_name="uintValue") Number_uintValue :: proc(self: ^Number) -> uint { return msgSend(uint, self, "unsignedLongValue") } +@(objc_type=Number, objc_name="u64Value") Number_u64Value :: proc(self: ^Number) -> u64 { return msgSend(u64, self, "longLongValue") } +@(objc_type=Number, objc_name="i64Value") Number_i64Value :: proc(self: ^Number) -> i64 { return msgSend(i64, self, "unsignedLongLongValue") } +@(objc_type=Number, objc_name="f32Value") Number_f32Value :: proc(self: ^Number) -> f32 { return msgSend(f32, self, "floatValue") } +@(objc_type=Number, objc_name="f64Value") Number_f64Value :: proc(self: ^Number) -> f64 { return msgSend(f64, self, "doubleValue") } +@(objc_type=Number, objc_name="boolValue") Number_boolValue :: proc(self: ^Number) -> BOOL { return msgSend(BOOL, self, "boolValue") } +@(objc_type=Number, objc_name="integerValue") Number_integerValue :: proc(self: ^Number) -> Integer { return msgSend(Integer, self, "integerValue") } +@(objc_type=Number, objc_name="uintegerValue") Number_uintegerValue :: proc(self: ^Number) -> UInteger { return msgSend(UInteger, self, "unsignedIntegerValue") } +@(objc_type=Number, objc_name="stringValue") Number_stringValue :: proc(self: ^Number) -> ^String { return msgSend(^String, self, "stringValue") } + +@(objc_type=Number, objc_name="compare") +Number_compare :: proc(self, other: ^Number) -> ComparisonResult { + return msgSend(ComparisonResult, self, "compare:", other) } -Number_isEqualToNumber :: proc(a, b: ^Number) -> BOOL { - return msgSend(BOOL, a, "isEqualToNumber:", b) +@(objc_type=Number, objc_name="isEqualToNumber") +Number_isEqualToNumber :: proc(self, other: ^Number) -> BOOL { + return msgSend(BOOL, self, "isEqualToNumber:", other) } +@(objc_type=Number, objc_name="descriptionWithLocale") Number_descriptionWithLocale :: proc(self: ^Number, locale: ^Object) -> ^String { return msgSend(^String, self, "descriptionWithLocale:", locale) } \ No newline at end of file diff --git a/core/sys/darwin/Foundation/NSObject.odin b/core/sys/darwin/Foundation/NSObject.odin index d61f8e947..cd0919edd 100644 --- a/core/sys/darwin/Foundation/NSObject.odin +++ b/core/sys/darwin/Foundation/NSObject.odin @@ -27,37 +27,45 @@ alloc :: proc($T: typeid) -> ^T where intrinsics.type_is_subtype_of(T, Object) { init :: proc(self: ^$T) -> ^T where intrinsics.type_is_subtype_of(T, Object) { return msgSend(^T, self, "init") } -retain :: proc(self: ^$T) -> ^T where intrinsics.type_is_subtype_of(T, Object) { - return msgSend(^T, self, "retain") +copy :: proc(self: ^Copying($T)) -> ^T where intrinsics.type_is_subtype_of(T, Object) { + return msgSend(^T, self, "copy") +} + + +@(objc_type=Object, objc_name="retain") +retain :: proc(self: ^Object) { + _ = msgSend(^Object, self, "retain") } -release :: proc(self: ^$T) where intrinsics.type_is_subtype_of(T, Object) { +@(objc_type=Object, objc_name="release") +release :: proc(self: ^Object) { msgSend(nil, self, "release") } -autorelease :: proc(self: ^$T) where intrinsics.type_is_subtype_of(T, Object) { +@(objc_type=Object, objc_name="autorelease") +autorelease :: proc(self: ^Object) { msgSend(nil, self, "autorelease") } -retainCount :: proc(self: ^$T) -> UInteger where intrinsics.type_is_subtype_of(T, Object) { +@(objc_type=Object, objc_name="retainCount") +retainCount :: proc(self: ^Object) -> UInteger { return msgSend(UInteger, self, "retainCount") } -copy :: proc(self: ^Copying($T)) -> ^T where intrinsics.type_is_subtype_of(T, Object) { - return msgSend(^T, self, "copy") -} - - +@(objc_type=Object, objc_name="hash") hash :: proc(self: ^Object) -> UInteger { return msgSend(UInteger, self, "hash") } +@(objc_type=Object, objc_name="isEqual") isEqual :: proc(self, pObject: ^Object) -> BOOL { return msgSend(BOOL, self, "isEqual:", pObject) } +@(objc_type=Object, objc_name="description") description :: proc(self: ^Object) -> ^String { return msgSend(^String, self, "description") } +@(objc_type=Object, objc_name="debugDescription") debugDescription :: proc(self: ^Object) -> ^String { if msgSendSafeCheck(self, intrinsics.objc_selector_name("debugDescription")) { return msgSend(^String, self, "debugDescription") diff --git a/core/sys/darwin/Foundation/NSString.odin b/core/sys/darwin/Foundation/NSString.odin index 86c8cabea..06dbc27a3 100644 --- a/core/sys/darwin/Foundation/NSString.odin +++ b/core/sys/darwin/Foundation/NSString.odin @@ -59,54 +59,78 @@ MakeConstantString :: proc "c" (#const c: cstring) -> ^String { } +@(objc_type=String, objc_class_name="alloc") +String_alloc :: proc() -> ^String { + return msgSend(^String, String, "alloc") +} + +@(objc_type=String, objc_name="init") +String_init :: proc(self: ^String) -> ^String { + return msgSend(^String, self, "init") +} + + +@(objc_type=String, objc_name="initWithString") String_initWithString :: proc(self: ^String, other: ^String) -> ^String { return msgSend(^String, self, "initWithString:", other) } +@(objc_type=String, objc_name="initWithCString") String_initWithCString :: proc(self: ^String, pString: cstring, encoding: StringEncoding) -> ^String { return msgSend(^String, self, "initWithCstring:encoding:", pString, encoding) } +@(objc_type=String, objc_name="initWithBytesNoCopy") String_initWithBytesNoCopy :: proc(self: ^String, pBytes: rawptr, length: UInteger, encoding: StringEncoding, freeWhenDone: bool) -> ^String { return msgSend(^String, self, "initWithBytesNoCopy:length:encoding:freeWhenDone:", pBytes, length, encoding, freeWhenDone) } +@(objc_type=String, objc_name="initWithOdinString") String_initWithOdinString :: proc(self: ^String, str: string) -> ^String { return String_initWithBytesNoCopy(self, raw_data(str), UInteger(len(str)), .UTF8, false) } +@(objc_type=String, objc_name="characterAtIndex") String_characterAtIndex :: proc(self: ^String, index: UInteger) -> unichar { return msgSend(unichar, self, "characterAtIndex:", index) } +@(objc_type=String, objc_name="length") String_length :: proc(self: ^String) -> UInteger { return msgSend(UInteger, self, "length") } +@(objc_type=String, objc_name="cStringUsingEncoding") String_cStringUsingEncoding :: proc(self: ^String, encoding: StringEncoding) -> cstring { return msgSend(cstring, self, "cStringUsingEncoding:", encoding) } +@(objc_type=String, objc_name="UTF8String") String_UTF8String :: proc(self: ^String) -> cstring { return msgSend(cstring, self, "UTF8String") } +@(objc_type=String, objc_name="OdinString") String_OdinString :: proc(self: ^String) -> string { return string(String_UTF8String(self)) } +@(objc_type=String, objc_name="maximumLengthOfBytesUsingEncoding") String_maximumLengthOfBytesUsingEncoding :: proc(self: ^String, encoding: StringEncoding) -> UInteger { return msgSend(UInteger, self, "maximumLengthOfBytesUsingEncoding:", encoding) } +@(objc_type=String, objc_name="lengthOfBytesUsingEncoding") String_lengthOfBytesUsingEncoding :: proc(self: ^String, encoding: StringEncoding) -> UInteger { return msgSend(UInteger, self, "lengthOfBytesUsingEncoding:", encoding) } +@(objc_type=String, objc_name="isEqualToString") String_isEqualToString :: proc(self, other: ^String) -> BOOL { return msgSend(BOOL, self, "isEqualToString:", other) } +@(objc_type=String, objc_name="rangeOfString") String_rangeOfString :: proc(self, other: ^String, options: StringCompareOptions) -> Range { return msgSend(Range, self, "rangeOfString:options:", other, options) } \ No newline at end of file diff --git a/core/sys/darwin/Foundation/NSURL.odin b/core/sys/darwin/Foundation/NSURL.odin index f4f776130..42edf91c0 100644 --- a/core/sys/darwin/Foundation/NSURL.odin +++ b/core/sys/darwin/Foundation/NSURL.odin @@ -3,6 +3,18 @@ package objc_Foundation @(objc_class="NSURL") URL :: struct{using _: Copying(URL)} + +@(objc_type=URL, objc_class_name="alloc") +URL_alloc :: proc() -> ^URL { + return msgSend(^URL, URL, "alloc") +} + +@(objc_type=URL, objc_name="init") +URL_init :: proc(self: ^URL) -> ^URL { + return msgSend(^URL, self, "init") +} + + URL_initWithString :: proc(self: ^URL, value: ^String) -> ^URL { return msgSend(^URL, self, "initWithString:", value) } diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp index df22d82e2..a9ee5d25f 100644 --- a/src/check_builtin.cpp +++ b/src/check_builtin.cpp @@ -287,15 +287,13 @@ bool check_builtin_objc_procedure(CheckerContext *c, Operand *operand, Ast *call Operand self = {}; check_expr_or_type(c, &self, ce->args[1]); if (self.mode == Addressing_Type) { - if (!internal_check_is_assignable_to(self.type, t_objc_object)) { + if (!is_type_objc_object(self.type)) { gbString t = type_to_string(self.type); error(self.expr, "'%.*s' expected a type or value derived from intrinsics.objc_object, got type %s", LIT(builtin_name), t); gb_string_free(t); return false; } - if (!(self.type->kind == Type_Named && - self.type->Named.type_name != nullptr && - self.type->Named.type_name->TypeName.objc_class_name != "")) { + if (!has_type_got_objc_class_attribute(self.type)) { gbString t = type_to_string(self.type); error(self.expr, "'%.*s' expected a named type with the attribute @(obj_class=) , got type %s", LIT(builtin_name), t); gb_string_free(t); @@ -306,7 +304,7 @@ bool check_builtin_objc_procedure(CheckerContext *c, Operand *operand, Ast *call } else if (!is_operand_value(self) || !check_is_assignable_to(c, &self, t_objc_id)) { gbString e = expr_to_string(self.expr); gbString t = type_to_string(self.type); - error(self.expr, "'%.*s'3 expected a type or value derived from intrinsics.objc_object, got '%s' of type %s %d", LIT(builtin_name), e, t, self.type->kind); + error(self.expr, "'%.*s' expected a type or value derived from intrinsics.objc_object, got '%s' of type %s %d", LIT(builtin_name), e, t, self.type->kind); gb_string_free(t); gb_string_free(e); return false; diff --git a/src/check_decl.cpp b/src/check_decl.cpp index 243dbbbc6..1d30088d6 100644 --- a/src/check_decl.cpp +++ b/src/check_decl.cpp @@ -340,6 +340,10 @@ void check_type_decl(CheckerContext *ctx, Entity *e, Ast *init_expr, Type *def) check_decl_attributes(ctx, decl->attributes, type_decl_attribute, &ac); if (e->kind == Entity_TypeName && ac.objc_class != "") { e->TypeName.objc_class_name = ac.objc_class; + + if (type_size_of(e->type) > 0) { + error(e->token, "@(objc_class) marked type must be of zero size"); + } } } @@ -822,6 +826,65 @@ void check_proc_decl(CheckerContext *ctx, Entity *e, DeclInfo *d) { } e->Procedure.optimization_mode = cast(ProcedureOptimizationMode)ac.optimization_mode; + if (ac.objc_name.len || ac.objc_class_name.len || ac.objc_type) { + if (ac.objc_class_name.len && ac.objc_name.len) { + error(e->token, "@(objc_class_name) and @(objc_name) may not be allowed at the same time"); + } else if (ac.objc_type == nullptr) { + if (ac.objc_name.len) { + error(e->token, "@(objc_name) requires that @(objc_type) to be set"); + } else { + error(e->token, "@(objc_class_name) requires that @(objc_type) to be set"); + } + } else { + Type *t = ac.objc_type; + if (t->kind == Type_Named) { + Entity *tn = t->Named.type_name; + + GB_ASSERT(tn->kind == Entity_TypeName); + + if (tn->scope != e->scope) { + error(e->token, "@(objc_name) and @(objc_class_name) attributes may only be applied to procedures and types within the same scope"); + } else { + mutex_lock(&global_type_name_objc_metadata_mutex); + defer (mutex_unlock(&global_type_name_objc_metadata_mutex)); + + if (!tn->TypeName.objc_metadata) { + tn->TypeName.objc_metadata = create_type_name_obj_c_metadata(); + } + auto *md = tn->TypeName.objc_metadata; + mutex_lock(md->mutex); + defer (mutex_unlock(md->mutex)); + + if (ac.objc_name.len) { + bool ok = true; + for (TypeNameObjCMetadataEntry const &entry : md->value_entries) { + if (entry.name == ac.objc_name) { + error(e->token, "Previous declaration of @(objc_name=\"%.*s\")", LIT(ac.objc_name)); + ok = false; + break; + } + } + if (ok) { + array_add(&md->value_entries, TypeNameObjCMetadataEntry{ac.objc_name, e}); + } + } else { + bool ok = true; + for (TypeNameObjCMetadataEntry const &entry : md->type_entries) { + if (entry.name == ac.objc_class_name) { + error(e->token, "Previous declaration of @(objc_class_name=\"%.*s\")", LIT(ac.objc_class_name)); + ok = false; + break; + } + } + if (ok) { + array_add(&md->type_entries, TypeNameObjCMetadataEntry{ac.objc_class_name, e}); + } + } + } + } + } + } + switch (e->Procedure.optimization_mode) { case ProcedureOptimizationMode_None: diff --git a/src/check_type.cpp b/src/check_type.cpp index e1a0df7e6..32340070e 100644 --- a/src/check_type.cpp +++ b/src/check_type.cpp @@ -325,6 +325,8 @@ void add_polymorphic_record_entity(CheckerContext *ctx, Ast *node, Type *named_t named_type->Named.type_name = e; GB_ASSERT(original_type->kind == Type_Named); e->TypeName.objc_class_name = original_type->Named.type_name->TypeName.objc_class_name; + // TODO(bill): Is this even correct? Or should the metadata be copied? + e->TypeName.objc_metadata = original_type->Named.type_name->TypeName.objc_metadata; mutex_lock(&ctx->info->gen_types_mutex); auto *found_gen_types = map_get(&ctx->info->gen_types, original_type); diff --git a/src/checker.cpp b/src/checker.cpp index 2ab487592..0dd36987e 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -4,7 +4,7 @@ void check_expr(CheckerContext *c, Operand *operand, Ast *expression); void check_expr_or_type(CheckerContext *c, Operand *operand, Ast *expression, Type *type_hint=nullptr); void add_comparison_procedures_for_fields(CheckerContext *c, Type *t); - +Type *check_type(CheckerContext *ctx, Ast *e); bool is_operand_value(Operand o) { switch (o.mode) { @@ -2740,6 +2740,14 @@ ExactValue check_decl_attribute_value(CheckerContext *c, Ast *value) { return ev; } +Type *check_decl_attribute_type(CheckerContext *c, Ast *value) { + if (value != nullptr) { + return check_type(c, value); + } + return nullptr; +} + + #define ATTRIBUTE_USER_TAG_NAME "tag" @@ -3039,6 +3047,46 @@ DECL_ATTRIBUTE_PROC(proc_decl_attribute) { error(elem, "Expected a string for '%.*s'", LIT(name)); } return true; + } else if (name == "objc_name") { + ExactValue ev = check_decl_attribute_value(c, value); + if (ev.kind == ExactValue_String) { + if (string_is_valid_identifier(ev.value_string)) { + ac->objc_name = ev.value_string; + } else { + error(elem, "Invalid identifier for '%.*s', got '%.*s'", LIT(name), LIT(ev.value_string)); + } + } else { + error(elem, "Expected a string value for '%.*s'", LIT(name)); + } + return true; + } else if (name == "objc_class_name") { + ExactValue ev = check_decl_attribute_value(c, value); + if (ev.kind == ExactValue_String) { + if (string_is_valid_identifier(ev.value_string)) { + ac->objc_class_name = ev.value_string; + } else { + error(elem, "Invalid identifier for '%.*s', got '%.*s'", LIT(name), LIT(ev.value_string)); + } + } else { + error(elem, "Expected a string value for '%.*s'", LIT(name)); + } + return true; + } else if (name == "objc_type") { + if (value == nullptr) { + error(elem, "Expected a type for '%.*s'", LIT(name)); + } else { + Type *objc_type = check_type(c, value); + if (objc_type != nullptr) { + if (!has_type_got_objc_class_attribute(objc_type)) { + gbString t = type_to_string(objc_type); + error(value, "'%.*s' expected a named type with the attribute @(obj_class=), got type %s", LIT(name), t); + gb_string_free(t); + } else { + ac->objc_type = objc_type; + } + } + } + return true; } return false; } diff --git a/src/checker.hpp b/src/checker.hpp index b812e10a4..38c8d32f6 100644 --- a/src/checker.hpp +++ b/src/checker.hpp @@ -107,7 +107,6 @@ struct AttributeContext { String thread_local_model; String deprecated_message; String warning_message; - String objc_class; DeferredProcedure deferred_procedure; bool is_export : 1; bool is_static : 1; @@ -119,6 +118,11 @@ struct AttributeContext { bool init : 1; bool set_cold : 1; u32 optimization_mode; // ProcedureOptimizationMode + + String objc_class; + String objc_name; + String objc_class_name; + Type * objc_type; }; AttributeContext make_attribute_context(String link_prefix) { diff --git a/src/entity.cpp b/src/entity.cpp index 4d5b3b9e1..df8ee3faa 100644 --- a/src/entity.cpp +++ b/src/entity.cpp @@ -122,6 +122,28 @@ enum ProcedureOptimizationMode : u32 { ProcedureOptimizationMode_Speed, }; + +BlockingMutex global_type_name_objc_metadata_mutex; + +struct TypeNameObjCMetadataEntry { + String name; + Entity *entity; +}; +struct TypeNameObjCMetadata { + BlockingMutex *mutex; + Array type_entries; + Array value_entries; +}; + +TypeNameObjCMetadata *create_type_name_obj_c_metadata() { + TypeNameObjCMetadata *md = gb_alloc_item(permanent_allocator(), TypeNameObjCMetadata); + md->mutex = gb_alloc_item(permanent_allocator(), BlockingMutex); + mutex_init(md->mutex); + array_init(&md->type_entries, heap_allocator()); + array_init(&md->value_entries, heap_allocator()); + return md; +} + // An Entity is a named "thing" in the language struct Entity { EntityKind kind; @@ -187,6 +209,7 @@ struct Entity { String ir_mangled_name; bool is_type_alias; String objc_class_name; + TypeNameObjCMetadata *objc_metadata; } TypeName; struct { u64 tags; diff --git a/src/llvm_backend_expr.cpp b/src/llvm_backend_expr.cpp index 29a86d116..b2f430cd2 100644 --- a/src/llvm_backend_expr.cpp +++ b/src/llvm_backend_expr.cpp @@ -3320,7 +3320,12 @@ lbAddr lb_build_addr(lbProcedure *p, Ast *expr) { Type *type = base_type(tav.type); if (tav.mode == Addressing_Type) { // Addressing_Type - GB_PANIC("Unreachable"); + Selection sel = lookup_field(tav.type, selector, true); + if (sel.pseudo_field) { + GB_ASSERT(sel.entity->kind == Entity_Procedure); + return lb_addr(lb_find_value_from_entity(p->module, sel.entity)); + } + GB_PANIC("Unreachable %.*s", LIT(selector)); } if (se->swizzle_count > 0) { @@ -3347,6 +3352,10 @@ lbAddr lb_build_addr(lbProcedure *p, Ast *expr) { Selection sel = lookup_field(type, selector, false); GB_ASSERT(sel.entity != nullptr); + if (sel.pseudo_field) { + GB_ASSERT(sel.entity->kind == Entity_Procedure); + return lb_addr(lb_find_value_from_entity(p->module, sel.entity)); + } { lbAddr addr = lb_build_addr(p, se->expr); diff --git a/src/main.cpp b/src/main.cpp index fe56d451f..bd06193bd 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -585,37 +585,6 @@ void usage(String argv0) { print_usage_line(1, "e.g. odin build -help"); } - -bool string_is_valid_identifier(String str) { - if (str.len <= 0) return false; - - isize rune_count = 0; - - isize w = 0; - isize offset = 0; - while (offset < str.len) { - Rune r = 0; - w = utf8_decode(str.text, str.len, &r); - if (r == GB_RUNE_INVALID) { - return false; - } - - if (rune_count == 0) { - if (!rune_is_letter(r)) { - return false; - } - } else { - if (!rune_is_letter(r) && !rune_is_digit(r)) { - return false; - } - } - rune_count += 1; - offset += w; - } - - return true; -} - enum BuildFlagKind { BuildFlag_Invalid, @@ -2447,6 +2416,7 @@ int main(int arg_count, char const **arg_ptr) { virtual_memory_init(); mutex_init(&fullpath_mutex); mutex_init(&hash_exact_value_mutex); + mutex_init(&global_type_name_objc_metadata_mutex); init_string_buffer_memory(); init_string_interner(); diff --git a/src/string.cpp b/src/string.cpp index eb6058f78..bcaf23b9b 100644 --- a/src/string.cpp +++ b/src/string.cpp @@ -781,3 +781,34 @@ i32 unquote_string(gbAllocator a, String *s_, u8 quote=0, bool has_carriage_retu return 2; } + + +bool string_is_valid_identifier(String str) { + if (str.len <= 0) return false; + + isize rune_count = 0; + + isize w = 0; + isize offset = 0; + while (offset < str.len) { + Rune r = 0; + w = utf8_decode(str.text, str.len, &r); + if (r == GB_RUNE_INVALID) { + return false; + } + + if (rune_count == 0) { + if (!rune_is_letter(r)) { + return false; + } + } else { + if (!rune_is_letter(r) && !rune_is_digit(r)) { + return false; + } + } + rune_count += 1; + offset += w; + } + + return true; +} diff --git a/src/types.cpp b/src/types.cpp index 024d644a2..78958146b 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -393,6 +393,7 @@ struct Selection { bool indirect; // Set if there was a pointer deref anywhere down the line u8 swizzle_count; // maximum components = 4 u8 swizzle_indices; // 2 bits per component, representing which swizzle index + bool pseudo_field; }; Selection empty_selection = {0}; @@ -2782,6 +2783,7 @@ Selection lookup_field_from_index(Type *type, i64 index) { } Entity *scope_lookup_current(Scope *s, String const &name); +bool has_type_got_objc_class_attribute(Type *t); Selection lookup_field_with_selection(Type *type_, String field_name, bool is_type, Selection sel, bool allow_blank_ident) { GB_ASSERT(type_ != nullptr); @@ -2794,9 +2796,40 @@ Selection lookup_field_with_selection(Type *type_, String field_name, bool is_ty bool is_ptr = type != type_; sel.indirect = sel.indirect || is_ptr; + Type *original_type = type; + type = base_type(type); if (is_type) { + if (has_type_got_objc_class_attribute(original_type) && original_type->kind == Type_Named) { + Entity *e = original_type->Named.type_name; + GB_ASSERT(e->kind == Entity_TypeName); + if (e->TypeName.objc_metadata) { + auto *md = e->TypeName.objc_metadata; + mutex_lock(md->mutex); + defer (mutex_unlock(md->mutex)); + for (TypeNameObjCMetadataEntry const &entry : md->type_entries) { + GB_ASSERT(entry.entity->kind == Entity_Procedure); + if (entry.name == field_name) { + sel.entity = entry.entity; + sel.pseudo_field = true; + return sel; + } + } + } + if (type->kind == Type_Struct) { + for_array(i, type->Struct.fields) { + Entity *f = type->Struct.fields[i]; + if (f->flags&EntityFlag_Using) { + sel = lookup_field_with_selection(f->type, field_name, is_type, sel, allow_blank_ident); + if (sel.entity) { + return sel; + } + } + } + } + } + if (is_type_enum(type)) { // NOTE(bill): These may not have been added yet, so check in case for_array(i, type->Enum.fields) { @@ -2843,6 +2876,24 @@ Selection lookup_field_with_selection(Type *type_, String field_name, bool is_ty } else if (type->kind == Type_Union) { } else if (type->kind == Type_Struct) { + if (has_type_got_objc_class_attribute(original_type) && original_type->kind == Type_Named) { + Entity *e = original_type->Named.type_name; + GB_ASSERT(e->kind == Entity_TypeName); + if (e->TypeName.objc_metadata) { + auto *md = e->TypeName.objc_metadata; + mutex_lock(md->mutex); + defer (mutex_unlock(md->mutex)); + for (TypeNameObjCMetadataEntry const &entry : md->value_entries) { + GB_ASSERT(entry.entity->kind == Entity_Procedure); + if (entry.name == field_name) { + sel.entity = entry.entity; + sel.pseudo_field = true; + return sel; + } + } + } + } + for_array(i, type->Struct.fields) { Entity *f = type->Struct.fields[i]; if (f->kind != Entity_Variable || (f->flags & EntityFlag_Field) == 0) { @@ -3792,6 +3843,17 @@ bool is_type_subtype_of(Type *src, Type *dst) { } +bool has_type_got_objc_class_attribute(Type *t) { + return t->kind == Type_Named && t->Named.type_name != nullptr && t->Named.type_name->TypeName.objc_class_name != ""; +} + + + +bool is_type_objc_object(Type *t) { + bool internal_check_is_assignable_to(Type *src, Type *dst); + + return internal_check_is_assignable_to(t, t_objc_object); +} Type *get_struct_field_type(Type *t, isize index) { t = base_type(type_deref(t)); -- cgit v1.2.3 From 03aec70287714fb9d66864e6db0d9e6375c18362 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 14 Feb 2022 17:31:55 +0000 Subject: Change objc_class_name to objc_name with objc_is_class_method --- core/sys/darwin/Foundation/NSArray.odin | 2 +- core/sys/darwin/Foundation/NSAutoreleasePool.odin | 2 +- core/sys/darwin/Foundation/NSBundle.odin | 8 +- core/sys/darwin/Foundation/NSData.odin | 2 +- core/sys/darwin/Foundation/NSDate.odin | 2 +- core/sys/darwin/Foundation/NSDictionary.odin | 8 +- core/sys/darwin/Foundation/NSEnumerator.odin | 2 +- core/sys/darwin/Foundation/NSError.odin | 4 +- core/sys/darwin/Foundation/NSLock.odin | 2 +- core/sys/darwin/Foundation/NSNotification.odin | 2 +- core/sys/darwin/Foundation/NSNumber.odin | 34 ++-- core/sys/darwin/Foundation/NSString.odin | 2 +- core/sys/darwin/Foundation/NSURL.odin | 2 +- core/sys/darwin/Metal/MetalClasses.odin | 226 +++++++++++----------- core/sys/darwin/QuartzCore/QuartzCore.odin | 2 +- src/check_decl.cpp | 24 ++- src/checker.cpp | 12 +- src/checker.hpp | 2 +- 18 files changed, 166 insertions(+), 172 deletions(-) (limited to 'src/checker.cpp') diff --git a/core/sys/darwin/Foundation/NSArray.odin b/core/sys/darwin/Foundation/NSArray.odin index e17223ff7..d6021838b 100644 --- a/core/sys/darwin/Foundation/NSArray.odin +++ b/core/sys/darwin/Foundation/NSArray.odin @@ -7,7 +7,7 @@ Array :: struct { using _: Copying(Array), } -@(objc_type=Array, objc_class_name="alloc") +@(objc_type=Array, objc_name="alloc", objc_is_class_method=true) Array_alloc :: proc() -> ^Array { return msgSend(^Array, Array, "alloc") } diff --git a/core/sys/darwin/Foundation/NSAutoreleasePool.odin b/core/sys/darwin/Foundation/NSAutoreleasePool.odin index 17ec88ba1..a388a7146 100644 --- a/core/sys/darwin/Foundation/NSAutoreleasePool.odin +++ b/core/sys/darwin/Foundation/NSAutoreleasePool.odin @@ -3,7 +3,7 @@ package objc_Foundation @(objc_class="NSAutoreleasePool") AutoreleasePool :: struct {using _: Object} -@(objc_type=AutoreleasePool, objc_class_name="alloc") +@(objc_type=AutoreleasePool, objc_name="alloc", objc_is_class_method=true) AutoreleasePool_alloc :: proc() -> ^AutoreleasePool { return msgSend(^AutoreleasePool, AutoreleasePool, "alloc") } diff --git a/core/sys/darwin/Foundation/NSBundle.odin b/core/sys/darwin/Foundation/NSBundle.odin index a18809b7e..4f5a8e928 100644 --- a/core/sys/darwin/Foundation/NSBundle.odin +++ b/core/sys/darwin/Foundation/NSBundle.odin @@ -3,23 +3,23 @@ package objc_Foundation @(objc_class="NSBundle") Bundle :: struct { using _: Object } -@(objc_type=Bundle, objc_class_name="mainBundle") +@(objc_type=Bundle, objc_name="mainBundle", objc_is_class_method=true) Bundle_mainBundle :: proc() -> ^Bundle { return msgSend(^Bundle, Bundle, "mainBundle") } -@(objc_type=Bundle, objc_class_name="bundleWithPath") +@(objc_type=Bundle, objc_name="bundleWithPath", objc_is_class_method=true) Bundle_bundleWithPath :: proc(path: ^String) -> ^Bundle { return msgSend(^Bundle, Bundle, "bundleWithPath:", path) } -@(objc_type=Bundle, objc_class_name="bundleWithURL") +@(objc_type=Bundle, objc_name="bundleWithURL", objc_is_class_method=true) Bundle_bundleWithURL :: proc(url: ^URL) -> ^Bundle { return msgSend(^Bundle, Bundle, "bundleWithUrl:", url) } -@(objc_type=Bundle, objc_class_name="alloc") +@(objc_type=Bundle, objc_name="alloc", objc_is_class_method=true) Bundle_alloc :: proc() -> ^Bundle { return msgSend(^Bundle, Bundle, "alloc") } diff --git a/core/sys/darwin/Foundation/NSData.odin b/core/sys/darwin/Foundation/NSData.odin index e28f6a644..3c6369e86 100644 --- a/core/sys/darwin/Foundation/NSData.odin +++ b/core/sys/darwin/Foundation/NSData.odin @@ -3,7 +3,7 @@ package objc_Foundation @(objc_class="NSData") Data :: struct {using _: Copying(Data)} -@(objc_type=Data, objc_class_name="alloc") +@(objc_type=Data, objc_name="alloc", objc_is_class_method=true) Data_alloc :: proc() -> ^Data { return msgSend(^Data, Data, "alloc") } diff --git a/core/sys/darwin/Foundation/NSDate.odin b/core/sys/darwin/Foundation/NSDate.odin index 85bb14c3e..cd63d313a 100644 --- a/core/sys/darwin/Foundation/NSDate.odin +++ b/core/sys/darwin/Foundation/NSDate.odin @@ -3,7 +3,7 @@ package objc_Foundation @(objc_class="NSDate") Date :: struct {using _: Copying(Date)} -@(objc_type=Date, objc_class_name="alloc") +@(objc_type=Date, objc_name="alloc", objc_is_class_method=true) Date_alloc :: proc() -> ^Date { return msgSend(^Date, Date, "alloc") } diff --git a/core/sys/darwin/Foundation/NSDictionary.odin b/core/sys/darwin/Foundation/NSDictionary.odin index 3eb378dc7..1f009841a 100644 --- a/core/sys/darwin/Foundation/NSDictionary.odin +++ b/core/sys/darwin/Foundation/NSDictionary.odin @@ -3,23 +3,23 @@ package objc_Foundation @(objc_class="NSDictionary") Dictionary :: struct {using _: Copying(Dictionary)} -@(objc_type=Dictionary, objc_class_name="dictionary") +@(objc_type=Dictionary, objc_name="dictionary", objc_is_class_method=true) Dictionary_dictionary :: proc() -> ^Dictionary { return msgSend(^Dictionary, Dictionary, "dictionary") } -@(objc_type=Dictionary, objc_class_name="dictionaryWithObject") +@(objc_type=Dictionary, objc_name="dictionaryWithObject", objc_is_class_method=true) Dictionary_dictionaryWithObject :: proc(object: ^Object, forKey: ^Object) -> ^Dictionary { return msgSend(^Dictionary, Dictionary, "dictionaryWithObject:forKey:", object, forKey) } -@(objc_type=Dictionary, objc_class_name="dictionaryWithObjects") +@(objc_type=Dictionary, objc_name="dictionaryWithObjects", objc_is_class_method=true) Dictionary_dictionaryWithObjects :: proc(objects: [^]^Object, forKeys: [^]^Object, count: UInteger) -> ^Dictionary { return msgSend(^Dictionary, Dictionary, "dictionaryWithObjects:forKeys:count", objects, forKeys, count) } -@(objc_type=Dictionary, objc_class_name="alloc") +@(objc_type=Dictionary, objc_name="alloc", objc_is_class_method=true) Dictionary_alloc :: proc() -> ^Dictionary { return msgSend(^Dictionary, Dictionary, "alloc") } diff --git a/core/sys/darwin/Foundation/NSEnumerator.odin b/core/sys/darwin/Foundation/NSEnumerator.odin index 8a5a32e69..1c7ddeed2 100644 --- a/core/sys/darwin/Foundation/NSEnumerator.odin +++ b/core/sys/darwin/Foundation/NSEnumerator.odin @@ -19,7 +19,7 @@ Enumerator :: struct($T: typeid) where intrinsics.type_is_pointer(T), intrinsics } -@(objc_type=FastEnumeration, objc_class_name="alloc") +@(objc_type=FastEnumeration, objc_name="alloc", objc_is_class_method=true) FastEnumeration_alloc :: proc() -> ^FastEnumeration { return msgSend(^FastEnumeration, FastEnumeration, "alloc") } diff --git a/core/sys/darwin/Foundation/NSError.odin b/core/sys/darwin/Foundation/NSError.odin index bff0088e9..23e6eaba7 100644 --- a/core/sys/darwin/Foundation/NSError.odin +++ b/core/sys/darwin/Foundation/NSError.odin @@ -32,7 +32,7 @@ foreign Foundation { Error :: struct { using _: Copying(Error) } -@(objc_type=Error, objc_class_name="alloc") +@(objc_type=Error, objc_name="alloc", objc_is_class_method=true) Error_alloc :: proc() -> ^Error { return msgSend(^Error, Error, "alloc") } @@ -42,7 +42,7 @@ Error_init :: proc(self: ^Error) -> ^Error { return msgSend(^Error, self, "init") } -@(objc_type=Error, objc_class_name="errorWithDomain") +@(objc_type=Error, objc_name="errorWithDomain", objc_is_class_method=true) Error_errorWithDomain :: proc(domain: ErrorDomain, code: Integer, userInfo: ^Dictionary) -> ^Error { return msgSend(^Error, Error, "errorWithDomain:code:userInfo:", domain, code, userInfo) } diff --git a/core/sys/darwin/Foundation/NSLock.odin b/core/sys/darwin/Foundation/NSLock.odin index 3bcc06eab..c48b5dbad 100644 --- a/core/sys/darwin/Foundation/NSLock.odin +++ b/core/sys/darwin/Foundation/NSLock.odin @@ -13,7 +13,7 @@ Locking_unlock :: proc(self: ^Locking($T)) { Condition :: struct {using _: Locking(Condition) } -@(objc_type=Condition, objc_class_name="alloc") +@(objc_type=Condition, objc_name="alloc", objc_is_class_method=true) Condition_alloc :: proc() -> ^Condition { return msgSend(^Condition, Condition, "alloc") } diff --git a/core/sys/darwin/Foundation/NSNotification.odin b/core/sys/darwin/Foundation/NSNotification.odin index d8b142e53..182d33896 100644 --- a/core/sys/darwin/Foundation/NSNotification.odin +++ b/core/sys/darwin/Foundation/NSNotification.odin @@ -4,7 +4,7 @@ package objc_Foundation Notification :: struct{using _: Object} -@(objc_type=Notification, objc_class_name="alloc") +@(objc_type=Notification, objc_name="alloc", objc_is_class_method=true) Notification_alloc :: proc() -> ^Notification { return msgSend(^Notification, Notification, "alloc") } diff --git a/core/sys/darwin/Foundation/NSNumber.odin b/core/sys/darwin/Foundation/NSNumber.odin index f77b0866a..4f7ef311b 100644 --- a/core/sys/darwin/Foundation/NSNumber.odin +++ b/core/sys/darwin/Foundation/NSNumber.odin @@ -8,7 +8,7 @@ import "core:c" @(objc_class="NSValue") Value :: struct{using _: Copying(Value)} -@(objc_type=Value, objc_class_name="alloc") +@(objc_type=Value, objc_name="alloc", objc_is_class_method=true) Value_alloc :: proc() -> ^Value { return msgSend(^Value, Value, "alloc") } @@ -18,12 +18,12 @@ Value_init :: proc(self: ^Value) -> ^Value { return msgSend(^Value, self, "init") } -@(objc_type=Value, objc_class_name="valueWithBytes") +@(objc_type=Value, objc_name="valueWithBytes", objc_is_class_method=true) Value_valueWithBytes :: proc(value: rawptr, type: cstring) -> ^Value { return msgSend(^Value, Value, "valueWithBytes:objCType:", value, type) } -@(objc_type=Value, objc_class_name="valueWithPointer") +@(objc_type=Value, objc_name="valueWithPointer", objc_is_class_method=true) Value_valueWithPointer :: proc(pointer: rawptr) -> ^Value { return msgSend(^Value, Value, "valueWithPointer:", pointer) } @@ -64,7 +64,7 @@ Value_pointerValue :: proc(self: ^Value) -> rawptr { Number :: struct{using _: Copying(Number), using _: Value} -@(objc_type=Number, objc_class_name="alloc") +@(objc_type=Number, objc_name="alloc", objc_is_class_method=true) Number_alloc :: proc() -> ^Number { return msgSend(^Number, Number, "alloc") } @@ -74,19 +74,19 @@ Number_init :: proc(self: ^Number) -> ^Number { return msgSend(^Number, self, "init") } -@(objc_type=Number, objc_class_name="numberWithI8") Number_numberWithI8 :: proc(value: i8) -> ^Number { return msgSend(^Number, Number, "numberWithChar:", value) } -@(objc_type=Number, objc_class_name="numberWithU8") Number_numberWithU8 :: proc(value: u8) -> ^Number { return msgSend(^Number, Number, "numberWithUnsignedChar:", value) } -@(objc_type=Number, objc_class_name="numberWithI16") Number_numberWithI16 :: proc(value: i16) -> ^Number { return msgSend(^Number, Number, "numberWithShort:", value) } -@(objc_type=Number, objc_class_name="numberWithU16") Number_numberWithU16 :: proc(value: u16) -> ^Number { return msgSend(^Number, Number, "numberWithUnsignedShort:", value) } -@(objc_type=Number, objc_class_name="numberWithI32") Number_numberWithI32 :: proc(value: i32) -> ^Number { return msgSend(^Number, Number, "numberWithInt:", value) } -@(objc_type=Number, objc_class_name="numberWithU32") Number_numberWithU32 :: proc(value: u32) -> ^Number { return msgSend(^Number, Number, "numberWithUnsignedInt:", value) } -@(objc_type=Number, objc_class_name="numberWithInt") Number_numberWithInt :: proc(value: int) -> ^Number { return msgSend(^Number, Number, "numberWithLong:", value) } -@(objc_type=Number, objc_class_name="numberWithUint") Number_numberWithUint :: proc(value: uint) -> ^Number { return msgSend(^Number, Number, "numberWithUnsignedLong:", value) } -@(objc_type=Number, objc_class_name="numberWithU64") Number_numberWithU64 :: proc(value: u64) -> ^Number { return msgSend(^Number, Number, "numberWithLongLong:", value) } -@(objc_type=Number, objc_class_name="numberWithI64") Number_numberWithI64 :: proc(value: i64) -> ^Number { return msgSend(^Number, Number, "numberWithUnsignedLongLong:", value) } -@(objc_type=Number, objc_class_name="numberWithF32") Number_numberWithF32 :: proc(value: f32) -> ^Number { return msgSend(^Number, Number, "numberWithFloat:", value) } -@(objc_type=Number, objc_class_name="numberWithF64") Number_numberWithF64 :: proc(value: f64) -> ^Number { return msgSend(^Number, Number, "numberWithDouble:", value) } -@(objc_type=Number, objc_class_name="numberWithBool") Number_numberWithBool :: proc(value: BOOL) -> ^Number { return msgSend(^Number, Number, "numberWithBool:", value) } +@(objc_type=Number, objc_name="numberWithI8", objc_is_class_method=true) Number_numberWithI8 :: proc(value: i8) -> ^Number { return msgSend(^Number, Number, "numberWithChar:", value) } +@(objc_type=Number, objc_name="numberWithU8", objc_is_class_method=true) Number_numberWithU8 :: proc(value: u8) -> ^Number { return msgSend(^Number, Number, "numberWithUnsignedChar:", value) } +@(objc_type=Number, objc_name="numberWithI16", objc_is_class_method=true) Number_numberWithI16 :: proc(value: i16) -> ^Number { return msgSend(^Number, Number, "numberWithShort:", value) } +@(objc_type=Number, objc_name="numberWithU16", objc_is_class_method=true) Number_numberWithU16 :: proc(value: u16) -> ^Number { return msgSend(^Number, Number, "numberWithUnsignedShort:", value) } +@(objc_type=Number, objc_name="numberWithI32", objc_is_class_method=true) Number_numberWithI32 :: proc(value: i32) -> ^Number { return msgSend(^Number, Number, "numberWithInt:", value) } +@(objc_type=Number, objc_name="numberWithU32", objc_is_class_method=true) Number_numberWithU32 :: proc(value: u32) -> ^Number { return msgSend(^Number, Number, "numberWithUnsignedInt:", value) } +@(objc_type=Number, objc_name="numberWithInt", objc_is_class_method=true) Number_numberWithInt :: proc(value: int) -> ^Number { return msgSend(^Number, Number, "numberWithLong:", value) } +@(objc_type=Number, objc_name="numberWithUint", objc_is_class_method=true) Number_numberWithUint :: proc(value: uint) -> ^Number { return msgSend(^Number, Number, "numberWithUnsignedLong:", value) } +@(objc_type=Number, objc_name="numberWithU64", objc_is_class_method=true) Number_numberWithU64 :: proc(value: u64) -> ^Number { return msgSend(^Number, Number, "numberWithLongLong:", value) } +@(objc_type=Number, objc_name="numberWithI64", objc_is_class_method=true) Number_numberWithI64 :: proc(value: i64) -> ^Number { return msgSend(^Number, Number, "numberWithUnsignedLongLong:", value) } +@(objc_type=Number, objc_name="numberWithF32", objc_is_class_method=true) Number_numberWithF32 :: proc(value: f32) -> ^Number { return msgSend(^Number, Number, "numberWithFloat:", value) } +@(objc_type=Number, objc_name="numberWithF64", objc_is_class_method=true) Number_numberWithF64 :: proc(value: f64) -> ^Number { return msgSend(^Number, Number, "numberWithDouble:", value) } +@(objc_type=Number, objc_name="numberWithBool", objc_is_class_method=true) Number_numberWithBool :: proc(value: BOOL) -> ^Number { return msgSend(^Number, Number, "numberWithBool:", value) } Number_number :: proc{ Number_numberWithI8, diff --git a/core/sys/darwin/Foundation/NSString.odin b/core/sys/darwin/Foundation/NSString.odin index 06dbc27a3..66442383a 100644 --- a/core/sys/darwin/Foundation/NSString.odin +++ b/core/sys/darwin/Foundation/NSString.odin @@ -59,7 +59,7 @@ MakeConstantString :: proc "c" (#const c: cstring) -> ^String { } -@(objc_type=String, objc_class_name="alloc") +@(objc_type=String, objc_name="alloc", objc_is_class_method=true) String_alloc :: proc() -> ^String { return msgSend(^String, String, "alloc") } diff --git a/core/sys/darwin/Foundation/NSURL.odin b/core/sys/darwin/Foundation/NSURL.odin index 42edf91c0..9813b6e59 100644 --- a/core/sys/darwin/Foundation/NSURL.odin +++ b/core/sys/darwin/Foundation/NSURL.odin @@ -4,7 +4,7 @@ package objc_Foundation URL :: struct{using _: Copying(URL)} -@(objc_type=URL, objc_class_name="alloc") +@(objc_type=URL, objc_name="alloc", objc_is_class_method=true) URL_alloc :: proc() -> ^URL { return msgSend(^URL, URL, "alloc") } diff --git a/core/sys/darwin/Metal/MetalClasses.odin b/core/sys/darwin/Metal/MetalClasses.odin index 7472fa37b..2686ce2ae 100644 --- a/core/sys/darwin/Metal/MetalClasses.odin +++ b/core/sys/darwin/Metal/MetalClasses.odin @@ -24,7 +24,7 @@ Methods: @(objc_class="MTLAccelerationStructureBoundingBoxGeometryDescriptor") AccelerationStructureBoundingBoxGeometryDescriptor :: struct { using _: NS.Copying(AccelerationStructureBoundingBoxGeometryDescriptor), using _: AccelerationStructureDescriptor } -@(objc_type=AccelerationStructureBoundingBoxGeometryDescriptor, objc_class_name="alloc") +@(objc_type=AccelerationStructureBoundingBoxGeometryDescriptor, objc_name="alloc", objc_is_class_method=true) AccelerationStructureBoundingBoxGeometryDescriptor_alloc :: #force_inline proc() -> ^AccelerationStructureBoundingBoxGeometryDescriptor { return msgSend(^AccelerationStructureBoundingBoxGeometryDescriptor, AccelerationStructureBoundingBoxGeometryDescriptor, "alloc") } @@ -48,7 +48,7 @@ AccelerationStructureBoundingBoxGeometryDescriptor_boundingBoxCount :: #force_in AccelerationStructureBoundingBoxGeometryDescriptor_boundingBoxStride :: #force_inline proc(self: ^AccelerationStructureBoundingBoxGeometryDescriptor) -> NS.UInteger { return msgSend(NS.UInteger, self, "boundingBoxStride") } -@(objc_type=AccelerationStructureBoundingBoxGeometryDescriptor, objc_class_name="descriptor") +@(objc_type=AccelerationStructureBoundingBoxGeometryDescriptor, objc_name="descriptor", objc_is_class_method=true) AccelerationStructureBoundingBoxGeometryDescriptor_descriptor :: #force_inline proc() -> ^AccelerationStructureBoundingBoxGeometryDescriptor { return msgSend(^AccelerationStructureBoundingBoxGeometryDescriptor, AccelerationStructureBoundingBoxGeometryDescriptor, "descriptor") } @@ -88,31 +88,31 @@ Methods: @(objc_class="MTLMotionKeyframeData") MotionKeyframeData :: struct { using _: NS.Object } -@(objc_type=MotionKeyframeData, objc_class_name="alloc") +@(objc_type=MotionKeyframeData, objc_name="alloc", objc_is_class_method=true) MotionKeyframeData_alloc :: #force_inline proc() -> ^MotionKeyframeData { return msgSend(^MotionKeyframeData, MotionKeyframeData, "alloc") } -@(objc_type=MotionKeyframeData, objc_class_name="data") +@(objc_type=MotionKeyframeData, objc_name="data", objc_is_class_method=true) MotionKeyframeData_data :: #force_inline proc() -> ^MotionKeyframeData { return msgSend(^MotionKeyframeData, MotionKeyframeData, "data") } -@(objc_type=MotionKeyframeData, objc_class_name="init") +@(objc_type=MotionKeyframeData, objc_name="init", objc_is_class_method=true) MotionKeyframeData_init :: #force_inline proc(self: ^MotionKeyframeData) -> ^MotionKeyframeData { return msgSend(^MotionKeyframeData, self, "init") } -@(objc_type=MotionKeyframeData, objc_class_name="buffer") +@(objc_type=MotionKeyframeData, objc_name="buffer", objc_is_class_method=true) MotionKeyframeData_buffer :: #force_inline proc(self: ^MotionKeyframeData) -> ^Buffer { return msgSend(^Buffer, self, "buffer") } -@(objc_type=MotionKeyframeData, objc_class_name="setBuffer") +@(objc_type=MotionKeyframeData, objc_name="setBuffer", objc_is_class_method=true) MotionKeyframeData_setBuffer :: #force_inline proc(self: ^MotionKeyframeData, buffer: ^Buffer) { msgSend(nil, self, "setBuffer:", buffer) } -@(objc_type=MotionKeyframeData, objc_class_name="offset") +@(objc_type=MotionKeyframeData, objc_name="offset", objc_is_class_method=true) MotionKeyframeData_offset :: #force_inline proc(self: ^MotionKeyframeData) -> NS.UInteger { return msgSend(NS.UInteger, self, "offset") } -@(objc_type=MotionKeyframeData, objc_class_name="setOffset") +@(objc_type=MotionKeyframeData, objc_name="setOffset", objc_is_class_method=true) MotionKeyframeData_setOffset :: #force_inline proc(self: ^MotionKeyframeData, offset: NS.UInteger) { msgSend(nil, self, "setOffset:", offset) } @@ -127,7 +127,7 @@ Class: @(objc_class="MTLAccelerationStructureMotionTriangleGeometryDescriptor") AccelerationStructureMotionTriangleGeometryDescriptor :: struct { using _: NS.Copying(AccelerationStructureMotionTriangleGeometryDescriptor), using _: AccelerationStructureGeometryDescriptor } -@(objc_type=AccelerationStructureMotionTriangleGeometryDescriptor, objc_class_name="alloc") +@(objc_type=AccelerationStructureMotionTriangleGeometryDescriptor, objc_name="alloc", objc_is_class_method=true) AccelerationStructureMotionTriangleGeometryDescriptor_alloc :: #force_inline proc() -> ^AccelerationStructureMotionTriangleGeometryDescriptor { return msgSend(^AccelerationStructureMotionTriangleGeometryDescriptor, AccelerationStructureMotionTriangleGeometryDescriptor, "alloc") } @@ -202,7 +202,7 @@ Class: @(objc_class="MTLAccelerationStructureMotionBoundingBoxGeometryDescriptor") AccelerationStructureMotionBoundingBoxGeometryDescriptor :: struct { using _: NS.Copying(AccelerationStructureMotionBoundingBoxGeometryDescriptor), using _: AccelerationStructureGeometryDescriptor } -@(objc_type=AccelerationStructureMotionBoundingBoxGeometryDescriptor, objc_class_name="alloc") +@(objc_type=AccelerationStructureMotionBoundingBoxGeometryDescriptor, objc_name="alloc", objc_is_class_method=true) AccelerationStructureMotionBoundingBoxGeometryDescriptor_alloc :: #force_inline proc() -> ^AccelerationStructureMotionBoundingBoxGeometryDescriptor { return msgSend(^AccelerationStructureMotionBoundingBoxGeometryDescriptor, AccelerationStructureMotionBoundingBoxGeometryDescriptor, "alloc") } @@ -211,7 +211,7 @@ AccelerationStructureMotionBoundingBoxGeometryDescriptor_init :: #force_inline p return msgSend(^AccelerationStructureMotionBoundingBoxGeometryDescriptor, self, "init") } -@(objc_type=AccelerationStructureMotionBoundingBoxGeometryDescriptor, objc_class_name="descriptor") +@(objc_type=AccelerationStructureMotionBoundingBoxGeometryDescriptor, objc_name="descriptor", objc_is_class_method=true) AccelerationStructureMotionBoundingBoxGeometryDescriptor_descriptor :: #force_inline proc() -> ^AccelerationStructureMotionBoundingBoxGeometryDescriptor { return msgSend(^AccelerationStructureMotionBoundingBoxGeometryDescriptor, AccelerationStructureMotionBoundingBoxGeometryDescriptor, "descriptor") } @@ -264,7 +264,7 @@ Methods: @(objc_class="MTLAccelerationStructureDescriptor") AccelerationStructureDescriptor :: struct { using _: NS.Copying(AccelerationStructureDescriptor) } -@(objc_type=AccelerationStructureDescriptor, objc_class_name="alloc") +@(objc_type=AccelerationStructureDescriptor, objc_name="alloc", objc_is_class_method=true) AccelerationStructureDescriptor_alloc :: #force_inline proc() -> ^AccelerationStructureDescriptor { return msgSend(^AccelerationStructureDescriptor, AccelerationStructureDescriptor, "alloc") } @@ -300,7 +300,7 @@ Methods: @(objc_class="MTLAccelerationStructureGeometryDescriptor") AccelerationStructureGeometryDescriptor :: struct { using _: NS.Copying(AccelerationStructureGeometryDescriptor) } -@(objc_type=AccelerationStructureGeometryDescriptor, objc_class_name="alloc") +@(objc_type=AccelerationStructureGeometryDescriptor, objc_name="alloc", objc_is_class_method=true) AccelerationStructureGeometryDescriptor_alloc :: #force_inline proc() -> ^AccelerationStructureGeometryDescriptor { return msgSend(^AccelerationStructureGeometryDescriptor, AccelerationStructureGeometryDescriptor, "alloc") } @@ -361,7 +361,7 @@ Methods: @(objc_class="MTLAccelerationStructureTriangleGeometryDescriptor") AccelerationStructureTriangleGeometryDescriptor :: struct { using _: NS.Copying(AccelerationStructureTriangleGeometryDescriptor), using _: AccelerationStructureDescriptor } -@(objc_type=AccelerationStructureTriangleGeometryDescriptor, objc_class_name="alloc") +@(objc_type=AccelerationStructureTriangleGeometryDescriptor, objc_name="alloc", objc_is_class_method=true) AccelerationStructureTriangleGeometryDescriptor_alloc :: #force_inline proc() -> ^AccelerationStructureTriangleGeometryDescriptor { return msgSend(^AccelerationStructureTriangleGeometryDescriptor, AccelerationStructureTriangleGeometryDescriptor, "alloc") } @@ -369,7 +369,7 @@ AccelerationStructureTriangleGeometryDescriptor_alloc :: #force_inline proc() -> AccelerationStructureTriangleGeometryDescriptor_init :: #force_inline proc(self: ^AccelerationStructureTriangleGeometryDescriptor) -> ^AccelerationStructureTriangleGeometryDescriptor { return msgSend(^AccelerationStructureTriangleGeometryDescriptor, self, "init") } -@(objc_type=AccelerationStructureTriangleGeometryDescriptor, objc_class_name="descriptor") +@(objc_type=AccelerationStructureTriangleGeometryDescriptor, objc_name="descriptor", objc_is_class_method=true) AccelerationStructureTriangleGeometryDescriptor_descriptor :: #force_inline proc() -> ^AccelerationStructureTriangleGeometryDescriptor { return msgSend(^AccelerationStructureTriangleGeometryDescriptor, AccelerationStructureTriangleGeometryDescriptor, "descriptor") } @@ -459,7 +459,7 @@ Methods: @(objc_class="MTLArgument") Argument :: struct { using _: NS.Object } -@(objc_type=Argument, objc_class_name="alloc") +@(objc_type=Argument, objc_name="alloc", objc_is_class_method=true) Argument_alloc :: #force_inline proc() -> ^Argument { return msgSend(^Argument, Argument, "alloc") } @@ -558,7 +558,7 @@ Methods: @(objc_class="MTLArgumentDescriptor") ArgumentDescriptor :: struct { using _: NS.Copying(ArgumentDescriptor) } -@(objc_type=ArgumentDescriptor, objc_class_name="alloc") +@(objc_type=ArgumentDescriptor, objc_name="alloc", objc_is_class_method=true) ArgumentDescriptor_alloc :: #force_inline proc() -> ^ArgumentDescriptor { return msgSend(^ArgumentDescriptor, ArgumentDescriptor, "alloc") } @@ -570,7 +570,7 @@ ArgumentDescriptor_init :: #force_inline proc(self: ^ArgumentDescriptor) -> ^Arg ArgumentDescriptor_access :: #force_inline proc(self: ^ArgumentDescriptor) -> ArgumentAccess { return msgSend(ArgumentAccess, self, "access") } -@(objc_type=ArgumentDescriptor, objc_class_name="argumentDescriptor") +@(objc_type=ArgumentDescriptor, objc_name="argumentDescriptor", objc_is_class_method=true) ArgumentDescriptor_argumentDescriptor :: #force_inline proc() -> ^ArgumentDescriptor { return msgSend(^ArgumentDescriptor, ArgumentDescriptor, "argumentDescriptor") } @@ -640,7 +640,7 @@ Methods: @(objc_class="MTLArrayType") ArrayType :: struct { using _: Type } -@(objc_type=ArrayType, objc_class_name="alloc") +@(objc_type=ArrayType, objc_name="alloc", objc_is_class_method=true) ArrayType_alloc :: #force_inline proc() -> ^ArrayType { return msgSend(^ArrayType, ArrayType, "alloc") } @@ -700,7 +700,7 @@ Methods: @(objc_class="MTLAttribute") Attribute :: struct { using _: NS.Object } -@(objc_type=Attribute, objc_class_name="alloc") +@(objc_type=Attribute, objc_name="alloc", objc_is_class_method=true) Attribute_alloc :: #force_inline proc() -> ^Attribute { return msgSend(^Attribute, Attribute, "alloc") } @@ -752,7 +752,7 @@ Methods: @(objc_class="MTLAttributeDescriptor") AttributeDescriptor :: struct { using _: NS.Copying(AttributeDescriptor) } -@(objc_type=AttributeDescriptor, objc_class_name="alloc") +@(objc_type=AttributeDescriptor, objc_name="alloc", objc_is_class_method=true) AttributeDescriptor_alloc :: #force_inline proc() -> ^AttributeDescriptor { return msgSend(^AttributeDescriptor, AttributeDescriptor, "alloc") } @@ -800,7 +800,7 @@ Methods: @(objc_class="MTLAttributeDescriptorArray") AttributeDescriptorArray :: struct { using _: NS.Object } -@(objc_type=AttributeDescriptorArray, objc_class_name="alloc") +@(objc_type=AttributeDescriptorArray, objc_name="alloc", objc_is_class_method=true) AttributeDescriptorArray_alloc :: #force_inline proc() -> ^AttributeDescriptorArray { return msgSend(^AttributeDescriptorArray, AttributeDescriptorArray, "alloc") } @@ -832,7 +832,7 @@ Methods: @(objc_class="MTLBinaryArchiveDescriptor") BinaryArchiveDescriptor :: struct { using _: NS.Copying(BinaryArchiveDescriptor) } -@(objc_type=BinaryArchiveDescriptor, objc_class_name="alloc") +@(objc_type=BinaryArchiveDescriptor, objc_name="alloc", objc_is_class_method=true) BinaryArchiveDescriptor_alloc :: #force_inline proc() -> ^BinaryArchiveDescriptor { return msgSend(^BinaryArchiveDescriptor, BinaryArchiveDescriptor, "alloc") } @@ -864,7 +864,7 @@ Methods: @(objc_class="MTLBlitPassDescriptor") BlitPassDescriptor :: struct { using _: NS.Copying(BlitPassDescriptor) } -@(objc_type=BlitPassDescriptor, objc_class_name="alloc") +@(objc_type=BlitPassDescriptor, objc_name="alloc", objc_is_class_method=true) BlitPassDescriptor_alloc :: #force_inline proc() -> ^BlitPassDescriptor { return msgSend(^BlitPassDescriptor, BlitPassDescriptor, "alloc") } @@ -872,7 +872,7 @@ BlitPassDescriptor_alloc :: #force_inline proc() -> ^BlitPassDescriptor { BlitPassDescriptor_init :: #force_inline proc(self: ^BlitPassDescriptor) -> ^BlitPassDescriptor { return msgSend(^BlitPassDescriptor, self, "init") } -@(objc_type=BlitPassDescriptor, objc_class_name="blitPassDescriptor") +@(objc_type=BlitPassDescriptor, objc_name="blitPassDescriptor", objc_is_class_method=true) BlitPassDescriptor_blitPassDescriptor :: #force_inline proc() -> ^BlitPassDescriptor { return msgSend(^BlitPassDescriptor, BlitPassDescriptor, "blitPassDescriptor") } @@ -900,7 +900,7 @@ Methods: @(objc_class="MTLBlitPassSampleBufferAttachmentDescriptor") BlitPassSampleBufferAttachmentDescriptor :: struct { using _: NS.Copying(BlitPassSampleBufferAttachmentDescriptor) } -@(objc_type=BlitPassSampleBufferAttachmentDescriptor, objc_class_name="alloc") +@(objc_type=BlitPassSampleBufferAttachmentDescriptor, objc_name="alloc", objc_is_class_method=true) BlitPassSampleBufferAttachmentDescriptor_alloc :: #force_inline proc() -> ^BlitPassSampleBufferAttachmentDescriptor { return msgSend(^BlitPassSampleBufferAttachmentDescriptor, BlitPassSampleBufferAttachmentDescriptor, "alloc") } @@ -948,7 +948,7 @@ Methods: @(objc_class="MTLBlitPassSampleBufferAttachmentDescriptorArray") BlitPassSampleBufferAttachmentDescriptorArray :: struct { using _: NS.Object } -@(objc_type=BlitPassSampleBufferAttachmentDescriptorArray, objc_class_name="alloc") +@(objc_type=BlitPassSampleBufferAttachmentDescriptorArray, objc_name="alloc", objc_is_class_method=true) BlitPassSampleBufferAttachmentDescriptorArray_alloc :: #force_inline proc() -> ^BlitPassSampleBufferAttachmentDescriptorArray { return msgSend(^BlitPassSampleBufferAttachmentDescriptorArray, BlitPassSampleBufferAttachmentDescriptorArray, "alloc") } @@ -984,7 +984,7 @@ Methods: @(objc_class="MTLBufferLayoutDescriptor") BufferLayoutDescriptor :: struct { using _: NS.Copying(BufferLayoutDescriptor) } -@(objc_type=BufferLayoutDescriptor, objc_class_name="alloc") +@(objc_type=BufferLayoutDescriptor, objc_name="alloc", objc_is_class_method=true) BufferLayoutDescriptor_alloc :: #force_inline proc() -> ^BufferLayoutDescriptor { return msgSend(^BufferLayoutDescriptor, BufferLayoutDescriptor, "alloc") } @@ -1032,7 +1032,7 @@ Methods: @(objc_class="MTLBufferLayoutDescriptorArray") BufferLayoutDescriptorArray :: struct { using _: NS.Object } -@(objc_type=BufferLayoutDescriptorArray, objc_class_name="alloc") +@(objc_type=BufferLayoutDescriptorArray, objc_name="alloc", objc_is_class_method=true) BufferLayoutDescriptorArray_alloc :: #force_inline proc() -> ^BufferLayoutDescriptorArray { return msgSend(^BufferLayoutDescriptorArray, BufferLayoutDescriptorArray, "alloc") } @@ -1068,7 +1068,7 @@ Methods: @(objc_class="MTLCaptureDescriptor") CaptureDescriptor :: struct { using _: NS.Copying(CaptureDescriptor) } -@(objc_type=CaptureDescriptor, objc_class_name="alloc") +@(objc_type=CaptureDescriptor, objc_name="alloc", objc_is_class_method=true) CaptureDescriptor_alloc :: #force_inline proc() -> ^CaptureDescriptor { return msgSend(^CaptureDescriptor, CaptureDescriptor, "alloc") } @@ -1126,7 +1126,7 @@ Methods: @(objc_class="MTLCaptureManager") CaptureManager :: struct { using _: NS.Object } -@(objc_type=CaptureManager, objc_class_name="alloc") +@(objc_type=CaptureManager, objc_name="alloc", objc_is_class_method=true) CaptureManager_alloc :: #force_inline proc() -> ^CaptureManager { return msgSend(^CaptureManager, CaptureManager, "alloc") } @@ -1154,7 +1154,7 @@ CaptureManager_newCaptureScopeWithDevice :: #force_inline proc(self: ^CaptureMan CaptureManager_setDefaultCaptureScope :: #force_inline proc(self: ^CaptureManager, defaultCaptureScope: ^CaptureScope) { msgSend(nil, self, "setDefaultCaptureScope:", defaultCaptureScope) } -@(objc_type=CaptureManager, objc_class_name="sharedCaptureManager") +@(objc_type=CaptureManager, objc_name="sharedCaptureManager", objc_is_class_method=true) CaptureManager_sharedCaptureManager :: #force_inline proc() -> ^CaptureManager { return msgSend(^CaptureManager, CaptureManager, "sharedCaptureManager") } @@ -1201,7 +1201,7 @@ Methods: @(objc_class="MTLCommandBufferDescriptor") CommandBufferDescriptor :: struct { using _: NS.Copying(CommandBufferDescriptor) } -@(objc_type=CommandBufferDescriptor, objc_class_name="alloc") +@(objc_type=CommandBufferDescriptor, objc_name="alloc", objc_is_class_method=true) CommandBufferDescriptor_alloc :: #force_inline proc() -> ^CommandBufferDescriptor { return msgSend(^CommandBufferDescriptor, CommandBufferDescriptor, "alloc") } @@ -1253,7 +1253,7 @@ Methods: @(objc_class="MTLCompileOptions") CompileOptions :: struct { using _: NS.Copying(CompileOptions) } -@(objc_type=CompileOptions, objc_class_name="alloc") +@(objc_type=CompileOptions, objc_name="alloc", objc_is_class_method=true) CompileOptions_alloc :: #force_inline proc() -> ^CompileOptions { return msgSend(^CompileOptions, CompileOptions, "alloc") } @@ -1335,7 +1335,7 @@ Methods: @(objc_class="MTLComputePassDescriptor") ComputePassDescriptor :: struct { using _: NS.Copying(ComputePassDescriptor) } -@(objc_type=ComputePassDescriptor, objc_class_name="alloc") +@(objc_type=ComputePassDescriptor, objc_name="alloc", objc_is_class_method=true) ComputePassDescriptor_alloc :: #force_inline proc() -> ^ComputePassDescriptor { return msgSend(^ComputePassDescriptor, ComputePassDescriptor, "alloc") } @@ -1343,7 +1343,7 @@ ComputePassDescriptor_alloc :: #force_inline proc() -> ^ComputePassDescriptor { ComputePassDescriptor_init :: #force_inline proc(self: ^ComputePassDescriptor) -> ^ComputePassDescriptor { return msgSend(^ComputePassDescriptor, self, "init") } -@(objc_type=ComputePassDescriptor, objc_class_name="computePassDescriptor") +@(objc_type=ComputePassDescriptor, objc_name="computePassDescriptor", objc_is_class_method=true) ComputePassDescriptor_computePassDescriptor :: #force_inline proc() -> ^ComputePassDescriptor { return msgSend(^ComputePassDescriptor, ComputePassDescriptor, "computePassDescriptor") } @@ -1379,7 +1379,7 @@ Methods: @(objc_class="MTLComputePassSampleBufferAttachmentDescriptor") ComputePassSampleBufferAttachmentDescriptor :: struct { using _: NS.Copying(ComputePassSampleBufferAttachmentDescriptor) } -@(objc_type=ComputePassSampleBufferAttachmentDescriptor, objc_class_name="alloc") +@(objc_type=ComputePassSampleBufferAttachmentDescriptor, objc_name="alloc", objc_is_class_method=true) ComputePassSampleBufferAttachmentDescriptor_alloc :: #force_inline proc() -> ^ComputePassSampleBufferAttachmentDescriptor { return msgSend(^ComputePassSampleBufferAttachmentDescriptor, ComputePassSampleBufferAttachmentDescriptor, "alloc") } @@ -1427,7 +1427,7 @@ Methods: @(objc_class="MTLComputePassSampleBufferAttachmentDescriptorArray") ComputePassSampleBufferAttachmentDescriptorArray :: struct { using _: NS.Object } -@(objc_type=ComputePassSampleBufferAttachmentDescriptorArray, objc_class_name="alloc") +@(objc_type=ComputePassSampleBufferAttachmentDescriptorArray, objc_name="alloc", objc_is_class_method=true) ComputePassSampleBufferAttachmentDescriptorArray_alloc :: #force_inline proc() -> ^ComputePassSampleBufferAttachmentDescriptorArray { return msgSend(^ComputePassSampleBufferAttachmentDescriptorArray, ComputePassSampleBufferAttachmentDescriptorArray, "alloc") } @@ -1481,7 +1481,7 @@ Methods: @(objc_class="MTLComputePipelineDescriptor") ComputePipelineDescriptor :: struct { using _: NS.Copying(ComputePipelineDescriptor) } -@(objc_type=ComputePipelineDescriptor, objc_class_name="alloc") +@(objc_type=ComputePipelineDescriptor, objc_name="alloc", objc_is_class_method=true) ComputePipelineDescriptor_alloc :: #force_inline proc() -> ^ComputePipelineDescriptor { return msgSend(^ComputePipelineDescriptor, ComputePipelineDescriptor, "alloc") } @@ -1600,7 +1600,7 @@ Methods: @(objc_class="MTLComputePipelineReflection") ComputePipelineReflection :: struct { using _: NS.Object } -@(objc_type=ComputePipelineReflection, objc_class_name="alloc") +@(objc_type=ComputePipelineReflection, objc_name="alloc", objc_is_class_method=true) ComputePipelineReflection_alloc :: #force_inline proc() -> ^ComputePipelineReflection { return msgSend(^ComputePipelineReflection, ComputePipelineReflection, "alloc") } @@ -1634,7 +1634,7 @@ Methods: @(objc_class="MTLCounterSampleBufferDescriptor") CounterSampleBufferDescriptor :: struct { using _: NS.Copying(CounterSampleBufferDescriptor) } -@(objc_type=CounterSampleBufferDescriptor, objc_class_name="alloc") +@(objc_type=CounterSampleBufferDescriptor, objc_name="alloc", objc_is_class_method=true) CounterSampleBufferDescriptor_alloc :: #force_inline proc() -> ^CounterSampleBufferDescriptor { return msgSend(^CounterSampleBufferDescriptor, CounterSampleBufferDescriptor, "alloc") } @@ -1698,7 +1698,7 @@ Methods: @(objc_class="MTLDepthStencilDescriptor") DepthStencilDescriptor :: struct { using _: NS.Copying(DepthStencilDescriptor) } -@(objc_type=DepthStencilDescriptor, objc_class_name="alloc") +@(objc_type=DepthStencilDescriptor, objc_name="alloc", objc_is_class_method=true) DepthStencilDescriptor_alloc :: #force_inline proc() -> ^DepthStencilDescriptor { return msgSend(^DepthStencilDescriptor, DepthStencilDescriptor, "alloc") } @@ -1764,7 +1764,7 @@ Methods: @(objc_class="MTLFunctionConstant") FunctionConstant :: struct { using _: NS.Copying(FunctionConstant) } -@(objc_type=FunctionConstant, objc_class_name="alloc") +@(objc_type=FunctionConstant, objc_name="alloc", objc_is_class_method=true) FunctionConstant_alloc :: #force_inline proc() -> ^FunctionConstant { return msgSend(^FunctionConstant, FunctionConstant, "alloc") } @@ -1806,7 +1806,7 @@ Methods: @(objc_class="MTLFunctionConstantValues") FunctionConstantValues :: struct { using _: NS.Copying(FunctionConstantValues) } -@(objc_type=FunctionConstantValues, objc_class_name="alloc") +@(objc_type=FunctionConstantValues, objc_name="alloc", objc_is_class_method=true) FunctionConstantValues_alloc :: #force_inline proc() -> ^FunctionConstantValues { return msgSend(^FunctionConstantValues, FunctionConstantValues, "alloc") } @@ -1853,7 +1853,7 @@ Methods: @(objc_class="MTLFunctionDescriptor") FunctionDescriptor :: struct { using _: NS.Copying(FunctionDescriptor) } -@(objc_type=FunctionDescriptor, objc_class_name="alloc") +@(objc_type=FunctionDescriptor, objc_name="alloc", objc_is_class_method=true) FunctionDescriptor_alloc :: #force_inline proc() -> ^FunctionDescriptor { return msgSend(^FunctionDescriptor, FunctionDescriptor, "alloc") } @@ -1865,7 +1865,7 @@ FunctionDescriptor_init :: #force_inline proc(self: ^FunctionDescriptor) -> ^Fun FunctionDescriptor_constantValues :: #force_inline proc(self: ^FunctionDescriptor) -> ^FunctionConstantValues { return msgSend(^FunctionConstantValues, self, "constantValues") } -@(objc_type=FunctionDescriptor, objc_class_name="functionDescriptor") +@(objc_type=FunctionDescriptor, objc_name="functionDescriptor", objc_is_class_method=true) FunctionDescriptor_functionDescriptor :: #force_inline proc() -> ^FunctionDescriptor { return msgSend(^FunctionDescriptor, FunctionDescriptor, "functionDescriptor") } @@ -1911,7 +1911,7 @@ Methods: @(objc_class="MTLIntersectionFunctionDescriptor") IntersectionFunctionDescriptor :: struct { using _: NS.Copying(IntersectionFunctionDescriptor) } -@(objc_type=IntersectionFunctionDescriptor, objc_class_name="alloc") +@(objc_type=IntersectionFunctionDescriptor, objc_name="alloc", objc_is_class_method=true) IntersectionFunctionDescriptor_alloc :: #force_inline proc() -> ^IntersectionFunctionDescriptor { return msgSend(^IntersectionFunctionDescriptor, IntersectionFunctionDescriptor, "alloc") } @@ -1945,7 +1945,7 @@ Methods: @(objc_class="MTLHeapDescriptor") HeapDescriptor :: struct { using _: NS.Copying(HeapDescriptor) } -@(objc_type=HeapDescriptor, objc_class_name="alloc") +@(objc_type=HeapDescriptor, objc_name="alloc", objc_is_class_method=true) HeapDescriptor_alloc :: #force_inline proc() -> ^HeapDescriptor { return msgSend(^HeapDescriptor, HeapDescriptor, "alloc") } @@ -2027,7 +2027,7 @@ Methods: @(objc_class="MTLIndirectCommandBufferDescriptor") IndirectCommandBufferDescriptor :: struct { using _: NS.Copying(IndirectCommandBufferDescriptor) } -@(objc_type=IndirectCommandBufferDescriptor, objc_class_name="alloc") +@(objc_type=IndirectCommandBufferDescriptor, objc_name="alloc", objc_is_class_method=true) IndirectCommandBufferDescriptor_alloc :: #force_inline proc() -> ^IndirectCommandBufferDescriptor { return msgSend(^IndirectCommandBufferDescriptor, IndirectCommandBufferDescriptor, "alloc") } @@ -2108,7 +2108,7 @@ Methods: @(objc_class="MTLInstanceAccelerationStructureDescriptor") InstanceAccelerationStructureDescriptor :: struct { using _: NS.Copying(InstanceAccelerationStructureDescriptor), using _: AccelerationStructureDescriptor } -@(objc_type=InstanceAccelerationStructureDescriptor, objc_class_name="alloc") +@(objc_type=InstanceAccelerationStructureDescriptor, objc_name="alloc", objc_is_class_method=true) InstanceAccelerationStructureDescriptor_alloc :: #force_inline proc() -> ^InstanceAccelerationStructureDescriptor { return msgSend(^InstanceAccelerationStructureDescriptor, InstanceAccelerationStructureDescriptor, "alloc") } @@ -2116,7 +2116,7 @@ InstanceAccelerationStructureDescriptor_alloc :: #force_inline proc() -> ^Instan InstanceAccelerationStructureDescriptor_init :: #force_inline proc(self: ^InstanceAccelerationStructureDescriptor) -> ^InstanceAccelerationStructureDescriptor { return msgSend(^InstanceAccelerationStructureDescriptor, self, "init") } -@(objc_type=InstanceAccelerationStructureDescriptor, objc_class_name="descriptor") +@(objc_type=InstanceAccelerationStructureDescriptor, objc_name="descriptor", objc_is_class_method=true) InstanceAccelerationStructureDescriptor_descriptor :: #force_inline proc() -> ^InstanceAccelerationStructureDescriptor { return msgSend(^InstanceAccelerationStructureDescriptor, InstanceAccelerationStructureDescriptor, "descriptor") } @@ -2217,7 +2217,7 @@ Methods: @(objc_class="MTLIntersectionFunctionTableDescriptor") IntersectionFunctionTableDescriptor :: struct { using _: NS.Copying(IntersectionFunctionTableDescriptor) } -@(objc_type=IntersectionFunctionTableDescriptor, objc_class_name="alloc") +@(objc_type=IntersectionFunctionTableDescriptor, objc_name="alloc", objc_is_class_method=true) IntersectionFunctionTableDescriptor_alloc :: #force_inline proc() -> ^IntersectionFunctionTableDescriptor { return msgSend(^IntersectionFunctionTableDescriptor, IntersectionFunctionTableDescriptor, "alloc") } @@ -2229,7 +2229,7 @@ IntersectionFunctionTableDescriptor_init :: #force_inline proc(self: ^Intersecti IntersectionFunctionTableDescriptor_functionCount :: #force_inline proc(self: ^IntersectionFunctionTableDescriptor) -> NS.UInteger { return msgSend(NS.UInteger, self, "functionCount") } -@(objc_type=IntersectionFunctionTableDescriptor, objc_class_name="intersectionFunctionTableDescriptor") +@(objc_type=IntersectionFunctionTableDescriptor, objc_name="intersectionFunctionTableDescriptor", objc_is_class_method=true) IntersectionFunctionTableDescriptor_intersectionFunctionTableDescriptor :: #force_inline proc() -> ^IntersectionFunctionTableDescriptor { return msgSend(^IntersectionFunctionTableDescriptor, IntersectionFunctionTableDescriptor, "intersectionFunctionTableDescriptor") } @@ -2258,7 +2258,7 @@ Methods: @(objc_class="MTLLinkedFunctions") LinkedFunctions :: struct { using _: NS.Copying(LinkedFunctions) } -@(objc_type=LinkedFunctions, objc_class_name="alloc") +@(objc_type=LinkedFunctions, objc_name="alloc", objc_is_class_method=true) LinkedFunctions_alloc :: #force_inline proc() -> ^LinkedFunctions { return msgSend(^LinkedFunctions, LinkedFunctions, "alloc") } @@ -2278,7 +2278,7 @@ LinkedFunctions_functions :: #force_inline proc(self: ^LinkedFunctions) -> ^NS.A LinkedFunctions_groups :: #force_inline proc(self: ^LinkedFunctions) -> ^NS.Dictionary { return msgSend(^NS.Dictionary, self, "groups") } -@(objc_type=LinkedFunctions, objc_class_name="linkedFunctions") +@(objc_type=LinkedFunctions, objc_name="linkedFunctions", objc_is_class_method=true) LinkedFunctions_linkedFunctions :: #force_inline proc() -> ^LinkedFunctions { return msgSend(^LinkedFunctions, LinkedFunctions, "linkedFunctions") } @@ -2310,7 +2310,7 @@ Methods: @(objc_class="MTLPipelineBufferDescriptor") PipelineBufferDescriptor :: struct { using _: NS.Copying(PipelineBufferDescriptor) } -@(objc_type=PipelineBufferDescriptor, objc_class_name="alloc") +@(objc_type=PipelineBufferDescriptor, objc_name="alloc", objc_is_class_method=true) PipelineBufferDescriptor_alloc :: #force_inline proc() -> ^PipelineBufferDescriptor { return msgSend(^PipelineBufferDescriptor, PipelineBufferDescriptor, "alloc") } @@ -2342,7 +2342,7 @@ Methods: @(objc_class="MTLPipelineBufferDescriptorArray") PipelineBufferDescriptorArray :: struct { using _: NS.Object } -@(objc_type=PipelineBufferDescriptorArray, objc_class_name="alloc") +@(objc_type=PipelineBufferDescriptorArray, objc_name="alloc", objc_is_class_method=true) PipelineBufferDescriptorArray_alloc :: #force_inline proc() -> ^PipelineBufferDescriptorArray { return msgSend(^PipelineBufferDescriptorArray, PipelineBufferDescriptorArray, "alloc") } @@ -2379,7 +2379,7 @@ Methods: @(objc_class="MTLPointerType") PointerType :: struct { using _: Type } -@(objc_type=PointerType, objc_class_name="alloc") +@(objc_type=PointerType, objc_name="alloc", objc_is_class_method=true) PointerType_alloc :: #force_inline proc() -> ^PointerType { return msgSend(^PointerType, PointerType, "alloc") } @@ -2432,7 +2432,7 @@ Methods: @(objc_class="MTLPrimitiveAccelerationStructureDescriptor") PrimitiveAccelerationStructureDescriptor :: struct { using _: NS.Copying(PrimitiveAccelerationStructureDescriptor), using _: AccelerationStructureDescriptor } -@(objc_type=PrimitiveAccelerationStructureDescriptor, objc_class_name="alloc") +@(objc_type=PrimitiveAccelerationStructureDescriptor, objc_name="alloc", objc_is_class_method=true) PrimitiveAccelerationStructureDescriptor_alloc :: #force_inline proc() -> ^PrimitiveAccelerationStructureDescriptor { return msgSend(^PrimitiveAccelerationStructureDescriptor, PrimitiveAccelerationStructureDescriptor, "alloc") } @@ -2440,7 +2440,7 @@ PrimitiveAccelerationStructureDescriptor_alloc :: #force_inline proc() -> ^Primi PrimitiveAccelerationStructureDescriptor_init :: #force_inline proc(self: ^PrimitiveAccelerationStructureDescriptor) -> ^PrimitiveAccelerationStructureDescriptor { return msgSend(^PrimitiveAccelerationStructureDescriptor, self, "init") } -@(objc_type=PrimitiveAccelerationStructureDescriptor, objc_class_name="descriptor") +@(objc_type=PrimitiveAccelerationStructureDescriptor, objc_name="descriptor", objc_is_class_method=true) PrimitiveAccelerationStructureDescriptor_descriptor :: #force_inline proc() -> ^PrimitiveAccelerationStructureDescriptor { return msgSend(^PrimitiveAccelerationStructureDescriptor, PrimitiveAccelerationStructureDescriptor, "descriptor") } @@ -2516,7 +2516,7 @@ Methods: @(objc_class="MTLRasterizationRateLayerArray") RasterizationRateLayerArray :: struct { using _: NS.Object } -@(objc_type=RasterizationRateLayerArray, objc_class_name="alloc") +@(objc_type=RasterizationRateLayerArray, objc_name="alloc", objc_is_class_method=true) RasterizationRateLayerArray_alloc :: #force_inline proc() -> ^RasterizationRateLayerArray { return msgSend(^RasterizationRateLayerArray, RasterizationRateLayerArray, "alloc") } @@ -2553,7 +2553,7 @@ Methods: @(objc_class="MTLRasterizationRateLayerDescriptor") RasterizationRateLayerDescriptor :: struct { using _: NS.Copying(RasterizationRateLayerDescriptor) } -@(objc_type=RasterizationRateLayerDescriptor, objc_class_name="alloc") +@(objc_type=RasterizationRateLayerDescriptor, objc_name="alloc", objc_is_class_method=true) RasterizationRateLayerDescriptor_alloc :: #force_inline proc() -> ^RasterizationRateLayerDescriptor { return msgSend(^RasterizationRateLayerDescriptor, RasterizationRateLayerDescriptor, "alloc") } @@ -2614,7 +2614,7 @@ Methods: @(objc_class="MTLRasterizationRateMapDescriptor") RasterizationRateMapDescriptor :: struct { using _: NS.Copying(RasterizationRateMapDescriptor) } -@(objc_type=RasterizationRateMapDescriptor, objc_class_name="alloc") +@(objc_type=RasterizationRateMapDescriptor, objc_name="alloc", objc_is_class_method=true) RasterizationRateMapDescriptor_alloc :: #force_inline proc() -> ^RasterizationRateMapDescriptor { return msgSend(^RasterizationRateMapDescriptor, RasterizationRateMapDescriptor, "alloc") } @@ -2638,15 +2638,15 @@ RasterizationRateMapDescriptor_layerCount :: #force_inline proc(self: ^Rasteriza RasterizationRateMapDescriptor_layers :: #force_inline proc(self: ^RasterizationRateMapDescriptor) -> ^RasterizationRateLayerArray { return msgSend(^RasterizationRateLayerArray, self, "layers") } -@(objc_type=RasterizationRateMapDescriptor, objc_class_name="rasterizationRateMapDescriptorWithScreenSize") +@(objc_type=RasterizationRateMapDescriptor, objc_name="rasterizationRateMapDescriptorWithScreenSize", objc_is_class_method=true) RasterizationRateMapDescriptor_rasterizationRateMapDescriptorWithScreenSize :: #force_inline proc(screenSize: Size) -> ^RasterizationRateMapDescriptor { return msgSend(^RasterizationRateMapDescriptor, RasterizationRateMapDescriptor, "rasterizationRateMapDescriptorWithScreenSize:", screenSize) } -@(objc_type=RasterizationRateMapDescriptor, objc_class_name="rasterizationRateMapDescriptorWithScreenSizeWithLayer") +@(objc_type=RasterizationRateMapDescriptor, objc_name="rasterizationRateMapDescriptorWithScreenSizeWithLayer", objc_is_class_method=true) RasterizationRateMapDescriptor_rasterizationRateMapDescriptorWithScreenSizeWithLayer :: #force_inline proc(screenSize: Size, layer: ^RasterizationRateLayerDescriptor) -> ^RasterizationRateMapDescriptor { return msgSend(^RasterizationRateMapDescriptor, RasterizationRateMapDescriptor, "rasterizationRateMapDescriptorWithScreenSize:layer:", screenSize, layer) } -@(objc_type=RasterizationRateMapDescriptor, objc_class_name="rasterizationRateMapDescriptorWithScreenSizeWithLayers") +@(objc_type=RasterizationRateMapDescriptor, objc_name="rasterizationRateMapDescriptorWithScreenSizeWithLayers", objc_is_class_method=true) RasterizationRateMapDescriptor_rasterizationRateMapDescriptorWithScreenSizeWithLayers :: #force_inline proc(screenSize: Size, layers: []^RasterizationRateLayerDescriptor) -> ^RasterizationRateMapDescriptor { return msgSend(^RasterizationRateMapDescriptor, RasterizationRateMapDescriptor, "rasterizationRateMapDescriptorWithScreenSize:layerCount:layers:", screenSize, NS.UInteger(len(layers)), layers) } @@ -2682,7 +2682,7 @@ Methods: @(objc_class="MTLRasterizationRateSampleArray") RasterizationRateSampleArray :: struct { using _: NS.Object } -@(objc_type=RasterizationRateSampleArray, objc_class_name="alloc") +@(objc_type=RasterizationRateSampleArray, objc_name="alloc", objc_is_class_method=true) RasterizationRateSampleArray_alloc :: #force_inline proc() -> ^RasterizationRateSampleArray { return msgSend(^RasterizationRateSampleArray, RasterizationRateSampleArray, "alloc") } @@ -2734,7 +2734,7 @@ Methods: @(objc_class="MTLRenderPassAttachmentDescriptor") RenderPassAttachmentDescriptor :: struct { using _: NS.Copying(RenderPassAttachmentDescriptor) } -@(objc_type=RenderPassAttachmentDescriptor, objc_class_name="alloc") +@(objc_type=RenderPassAttachmentDescriptor, objc_name="alloc", objc_is_class_method=true) RenderPassAttachmentDescriptor_alloc :: #force_inline proc() -> ^RenderPassAttachmentDescriptor { return msgSend(^RenderPassAttachmentDescriptor, RenderPassAttachmentDescriptor, "alloc") } @@ -2846,7 +2846,7 @@ Methods: @(objc_class="MTLRenderPassColorAttachmentDescriptor") RenderPassColorAttachmentDescriptor :: struct { using _: NS.Copying(RenderPassColorAttachmentDescriptor), using _: RenderPassAttachmentDescriptor } -@(objc_type=RenderPassColorAttachmentDescriptor, objc_class_name="alloc") +@(objc_type=RenderPassColorAttachmentDescriptor, objc_name="alloc", objc_is_class_method=true) RenderPassColorAttachmentDescriptor_alloc :: #force_inline proc() -> ^RenderPassColorAttachmentDescriptor { return msgSend(^RenderPassColorAttachmentDescriptor, RenderPassColorAttachmentDescriptor, "alloc") } @@ -2878,7 +2878,7 @@ Methods: @(objc_class="MTLRenderPassColorAttachmentDescriptorArray") RenderPassColorAttachmentDescriptorArray :: struct { using _: NS.Object } -@(objc_type=RenderPassColorAttachmentDescriptorArray, objc_class_name="alloc") +@(objc_type=RenderPassColorAttachmentDescriptorArray, objc_name="alloc", objc_is_class_method=true) RenderPassColorAttachmentDescriptorArray_alloc :: #force_inline proc() -> ^RenderPassColorAttachmentDescriptorArray { return msgSend(^RenderPassColorAttachmentDescriptorArray, RenderPassColorAttachmentDescriptorArray, "alloc") } @@ -2912,7 +2912,7 @@ Methods: @(objc_class="MTLRenderPassDepthAttachmentDescriptor") RenderPassDepthAttachmentDescriptor :: struct { using _: NS.Copying(RenderPassDepthAttachmentDescriptor), using _: RenderPassAttachmentDescriptor } -@(objc_type=RenderPassDepthAttachmentDescriptor, objc_class_name="alloc") +@(objc_type=RenderPassDepthAttachmentDescriptor, objc_name="alloc", objc_is_class_method=true) RenderPassDepthAttachmentDescriptor_alloc :: #force_inline proc() -> ^RenderPassDepthAttachmentDescriptor { return msgSend(^RenderPassDepthAttachmentDescriptor, RenderPassDepthAttachmentDescriptor, "alloc") } @@ -2979,7 +2979,7 @@ Methods: @(objc_class="MTLRenderPassDescriptor") RenderPassDescriptor :: struct { using _: NS.Copying(RenderPassDescriptor), using _: AccelerationStructureDescriptor } -@(objc_type=RenderPassDescriptor, objc_class_name="alloc") +@(objc_type=RenderPassDescriptor, objc_name="alloc", objc_is_class_method=true) RenderPassDescriptor_alloc :: #force_inline proc() -> ^RenderPassDescriptor { return msgSend(^RenderPassDescriptor, RenderPassDescriptor, "alloc") } @@ -3011,7 +3011,7 @@ RenderPassDescriptor_imageblockSampleLength :: #force_inline proc(self: ^RenderP RenderPassDescriptor_rasterizationRateMap :: #force_inline proc(self: ^RenderPassDescriptor) -> ^RasterizationRateMap { return msgSend(^RasterizationRateMap, self, "rasterizationRateMap") } -@(objc_type=RenderPassDescriptor, objc_class_name="renderPassDescriptor") +@(objc_type=RenderPassDescriptor, objc_name="renderPassDescriptor", objc_is_class_method=true) RenderPassDescriptor_renderPassDescriptor :: #force_inline proc() -> ^RenderPassDescriptor { return msgSend(^RenderPassDescriptor, RenderPassDescriptor, "renderPassDescriptor") } @@ -3127,7 +3127,7 @@ Methods: @(objc_class="MTLRenderPassSampleBufferAttachmentDescriptor") RenderPassSampleBufferAttachmentDescriptor :: struct { using _: NS.Copying(RenderPassSampleBufferAttachmentDescriptor) } -@(objc_type=RenderPassSampleBufferAttachmentDescriptor, objc_class_name="alloc") +@(objc_type=RenderPassSampleBufferAttachmentDescriptor, objc_name="alloc", objc_is_class_method=true) RenderPassSampleBufferAttachmentDescriptor_alloc :: #force_inline proc() -> ^RenderPassSampleBufferAttachmentDescriptor { return msgSend(^RenderPassSampleBufferAttachmentDescriptor, RenderPassSampleBufferAttachmentDescriptor, "alloc") } @@ -3191,7 +3191,7 @@ Methods: @(objc_class="MTLRenderPassSampleBufferAttachmentDescriptorArray") RenderPassSampleBufferAttachmentDescriptorArray :: struct { using _: NS.Object } -@(objc_type=RenderPassSampleBufferAttachmentDescriptorArray, objc_class_name="alloc") +@(objc_type=RenderPassSampleBufferAttachmentDescriptorArray, objc_name="alloc", objc_is_class_method=true) RenderPassSampleBufferAttachmentDescriptorArray_alloc :: #force_inline proc() -> ^RenderPassSampleBufferAttachmentDescriptorArray { return msgSend(^RenderPassSampleBufferAttachmentDescriptorArray, RenderPassSampleBufferAttachmentDescriptorArray, "alloc") } @@ -3225,7 +3225,7 @@ Methods: @(objc_class="MTLRenderPassStencilAttachmentDescriptor") RenderPassStencilAttachmentDescriptor :: struct { using _: NS.Copying(RenderPassStencilAttachmentDescriptor) } -@(objc_type=RenderPassStencilAttachmentDescriptor, objc_class_name="alloc") +@(objc_type=RenderPassStencilAttachmentDescriptor, objc_name="alloc", objc_is_class_method=true) RenderPassStencilAttachmentDescriptor_alloc :: #force_inline proc() -> ^RenderPassStencilAttachmentDescriptor { return msgSend(^RenderPassStencilAttachmentDescriptor, RenderPassStencilAttachmentDescriptor, "alloc") } @@ -3281,7 +3281,7 @@ Methods: @(objc_class="MTLRenderPipelineColorAttachmentDescriptor") RenderPipelineColorAttachmentDescriptor :: struct { using _: NS.Copying(RenderPipelineColorAttachmentDescriptor), using _: RenderPassAttachmentDescriptor } -@(objc_type=RenderPipelineColorAttachmentDescriptor, objc_class_name="alloc") +@(objc_type=RenderPipelineColorAttachmentDescriptor, objc_name="alloc", objc_is_class_method=true) RenderPipelineColorAttachmentDescriptor_alloc :: #force_inline proc() -> ^RenderPipelineColorAttachmentDescriptor { return msgSend(^RenderPipelineColorAttachmentDescriptor, RenderPipelineColorAttachmentDescriptor, "alloc") } @@ -3377,7 +3377,7 @@ Methods: @(objc_class="MTLRenderPipelineColorAttachmentDescriptorArray") RenderPipelineColorAttachmentDescriptorArray :: struct { using _: NS.Object } -@(objc_type=RenderPipelineColorAttachmentDescriptorArray, objc_class_name="alloc") +@(objc_type=RenderPipelineColorAttachmentDescriptorArray, objc_name="alloc", objc_is_class_method=true) RenderPipelineColorAttachmentDescriptorArray_alloc :: #force_inline proc() -> ^RenderPipelineColorAttachmentDescriptorArray { return msgSend(^RenderPipelineColorAttachmentDescriptorArray, RenderPipelineColorAttachmentDescriptorArray, "alloc") } @@ -3455,7 +3455,7 @@ Methods: @(objc_class="MTLRenderPipelineDescriptor") RenderPipelineDescriptor :: struct { using _: NS.Copying(RenderPipelineDescriptor) } -@(objc_type=RenderPipelineDescriptor, objc_class_name="alloc") +@(objc_type=RenderPipelineDescriptor, objc_name="alloc", objc_is_class_method=true) RenderPipelineDescriptor_alloc :: #force_inline proc() -> ^RenderPipelineDescriptor { return msgSend(^RenderPipelineDescriptor, RenderPipelineDescriptor, "alloc") } @@ -3672,7 +3672,7 @@ Methods: @(objc_class="MTLRenderPipelineReflection") RenderPipelineReflection :: struct { using _: NS.Object } -@(objc_type=RenderPipelineReflection, objc_class_name="alloc") +@(objc_type=RenderPipelineReflection, objc_name="alloc", objc_is_class_method=true) RenderPipelineReflection_alloc :: #force_inline proc() -> ^RenderPipelineReflection { return msgSend(^RenderPipelineReflection, RenderPipelineReflection, "alloc") } @@ -3708,7 +3708,7 @@ Methods: @(objc_class="MTLResourceStatePassDescriptor") ResourceStatePassDescriptor :: struct { using _: NS.Copying(ResourceStatePassDescriptor) } -@(objc_type=ResourceStatePassDescriptor, objc_class_name="alloc") +@(objc_type=ResourceStatePassDescriptor, objc_name="alloc", objc_is_class_method=true) ResourceStatePassDescriptor_alloc :: #force_inline proc() -> ^ResourceStatePassDescriptor { return msgSend(^ResourceStatePassDescriptor, ResourceStatePassDescriptor, "alloc") } @@ -3716,7 +3716,7 @@ ResourceStatePassDescriptor_alloc :: #force_inline proc() -> ^ResourceStatePassD ResourceStatePassDescriptor_init :: #force_inline proc(self: ^ResourceStatePassDescriptor) -> ^ResourceStatePassDescriptor { return msgSend(^ResourceStatePassDescriptor, self, "init") } -@(objc_type=ResourceStatePassDescriptor, objc_class_name="resourceStatePassDescriptor") +@(objc_type=ResourceStatePassDescriptor, objc_name="resourceStatePassDescriptor", objc_is_class_method=true) ResourceStatePassDescriptor_resourceStatePassDescriptor :: #force_inline proc() -> ^ResourceStatePassDescriptor { return msgSend(^ResourceStatePassDescriptor, ResourceStatePassDescriptor, "resourceStatePassDescriptor") } @@ -3744,7 +3744,7 @@ Methods: @(objc_class="MTLResourceStatePassSampleBufferAttachmentDescriptor") ResourceStatePassSampleBufferAttachmentDescriptor :: struct { using _: NS.Copying(ResourceStatePassSampleBufferAttachmentDescriptor) } -@(objc_type=ResourceStatePassSampleBufferAttachmentDescriptor, objc_class_name="alloc") +@(objc_type=ResourceStatePassSampleBufferAttachmentDescriptor, objc_name="alloc", objc_is_class_method=true) ResourceStatePassSampleBufferAttachmentDescriptor_alloc :: #force_inline proc() -> ^ResourceStatePassSampleBufferAttachmentDescriptor { return msgSend(^ResourceStatePassSampleBufferAttachmentDescriptor, ResourceStatePassSampleBufferAttachmentDescriptor, "alloc") } @@ -3792,7 +3792,7 @@ Methods: @(objc_class="MTLResourceStatePassSampleBufferAttachmentDescriptorArray") ResourceStatePassSampleBufferAttachmentDescriptorArray :: struct { using _: NS.Object } -@(objc_type=ResourceStatePassSampleBufferAttachmentDescriptorArray, objc_class_name="alloc") +@(objc_type=ResourceStatePassSampleBufferAttachmentDescriptorArray, objc_name="alloc", objc_is_class_method=true) ResourceStatePassSampleBufferAttachmentDescriptorArray_alloc :: #force_inline proc() -> ^ResourceStatePassSampleBufferAttachmentDescriptorArray { return msgSend(^ResourceStatePassSampleBufferAttachmentDescriptorArray, ResourceStatePassSampleBufferAttachmentDescriptorArray, "alloc") } @@ -3852,7 +3852,7 @@ Methods: @(objc_class="MTLSamplerDescriptor") SamplerDescriptor :: struct { using _: NS.Copying(SamplerDescriptor) } -@(objc_type=SamplerDescriptor, objc_class_name="alloc") +@(objc_type=SamplerDescriptor, objc_name="alloc", objc_is_class_method=true) SamplerDescriptor_alloc :: #force_inline proc() -> ^SamplerDescriptor { return msgSend(^SamplerDescriptor, SamplerDescriptor, "alloc") } @@ -3995,7 +3995,7 @@ Methods: @(objc_class="MTLSharedEventHandle") SharedEventHandle :: struct { using _: NS.Object } -@(objc_type=SharedEventHandle, objc_class_name="alloc") +@(objc_type=SharedEventHandle, objc_name="alloc", objc_is_class_method=true) SharedEventHandle_alloc :: #force_inline proc() -> ^SharedEventHandle { return msgSend(^SharedEventHandle, SharedEventHandle, "alloc") } @@ -4023,7 +4023,7 @@ Methods: @(objc_class="MTLSharedEventListener") SharedEventListener :: struct { using _: NS.Object } -@(objc_type=SharedEventListener, objc_class_name="alloc") +@(objc_type=SharedEventListener, objc_name="alloc", objc_is_class_method=true) SharedEventListener_alloc :: #force_inline proc() -> ^SharedEventListener { return msgSend(^SharedEventListener, SharedEventListener, "alloc") } @@ -4055,7 +4055,7 @@ Methods: @(objc_class="MTLSharedTextureHandle") SharedTextureHandle :: struct { using _: NS.Object } -@(objc_type=SharedTextureHandle, objc_class_name="alloc") +@(objc_type=SharedTextureHandle, objc_name="alloc", objc_is_class_method=true) SharedTextureHandle_alloc :: #force_inline proc() -> ^SharedTextureHandle { return msgSend(^SharedTextureHandle, SharedTextureHandle, "alloc") } @@ -4093,7 +4093,7 @@ Methods: @(objc_class="MTLStageInputOutputDescriptor") StageInputOutputDescriptor :: struct { using _: NS.Copying(StageInputOutputDescriptor) } -@(objc_type=StageInputOutputDescriptor, objc_class_name="alloc") +@(objc_type=StageInputOutputDescriptor, objc_name="alloc", objc_is_class_method=true) StageInputOutputDescriptor_alloc :: #force_inline proc() -> ^StageInputOutputDescriptor { return msgSend(^StageInputOutputDescriptor, StageInputOutputDescriptor, "alloc") } @@ -4129,7 +4129,7 @@ StageInputOutputDescriptor_setIndexBufferIndex :: #force_inline proc(self: ^Stag StageInputOutputDescriptor_setIndexType :: #force_inline proc(self: ^StageInputOutputDescriptor, indexType: IndexType) { msgSend(nil, self, "setIndexType:", indexType) } -@(objc_type=StageInputOutputDescriptor, objc_class_name="stageInputOutputDescriptor") +@(objc_type=StageInputOutputDescriptor, objc_name="stageInputOutputDescriptor", objc_is_class_method=true) StageInputOutputDescriptor_stageInputOutputDescriptor :: #force_inline proc() -> ^StageInputOutputDescriptor { return msgSend(^StageInputOutputDescriptor, StageInputOutputDescriptor, "stageInputOutputDescriptor") } @@ -4159,7 +4159,7 @@ Methods: @(objc_class="MTLStencilDescriptor") StencilDescriptor :: struct { using _: NS.Copying(StencilDescriptor) } -@(objc_type=StencilDescriptor, objc_class_name="alloc") +@(objc_type=StencilDescriptor, objc_name="alloc", objc_is_class_method=true) StencilDescriptor_alloc :: #force_inline proc() -> ^StencilDescriptor { return msgSend(^StencilDescriptor, StencilDescriptor, "alloc") } @@ -4237,7 +4237,7 @@ Methods: @(objc_class="MTLStructMember") StructMember :: struct { using _: NS.Object } -@(objc_type=StructMember, objc_class_name="alloc") +@(objc_type=StructMember, objc_name="alloc", objc_is_class_method=true) StructMember_alloc :: #force_inline proc() -> ^StructMember { return msgSend(^StructMember, StructMember, "alloc") } @@ -4293,7 +4293,7 @@ Methods: @(objc_class="MTLStructType") StructType :: struct { using _: Type } -@(objc_type=StructType, objc_class_name="alloc") +@(objc_type=StructType, objc_name="alloc", objc_is_class_method=true) StructType_alloc :: #force_inline proc() -> ^StructType { return msgSend(^StructType, StructType, "alloc") } @@ -4356,7 +4356,7 @@ Methods: @(objc_class="MTLTextureDescriptor") TextureDescriptor :: struct { using _: NS.Copying(TextureDescriptor) } -@(objc_type=TextureDescriptor, objc_class_name="alloc") +@(objc_type=TextureDescriptor, objc_name="alloc", objc_is_class_method=true) TextureDescriptor_alloc :: #force_inline proc() -> ^TextureDescriptor { return msgSend(^TextureDescriptor, TextureDescriptor, "alloc") } @@ -4472,15 +4472,15 @@ TextureDescriptor_storageMode :: #force_inline proc(self: ^TextureDescriptor) -> TextureDescriptor_swizzle :: #force_inline proc(self: ^TextureDescriptor) -> TextureSwizzleChannels { return msgSend(TextureSwizzleChannels, self, "swizzle") } -@(objc_type=TextureDescriptor, objc_class_name="texture2DDescriptor") +@(objc_type=TextureDescriptor, objc_name="texture2DDescriptor", objc_is_class_method=true) TextureDescriptor_texture2DDescriptor :: #force_inline proc(pixelFormat: PixelFormat, width: NS.UInteger, height: NS.UInteger, mipmapped: BOOL) -> ^TextureDescriptor { return msgSend(^TextureDescriptor, TextureDescriptor, "texture2DDescriptorWithPixelFormat:width:height:mipmapped:", pixelFormat, width, height, mipmapped) } -@(objc_type=TextureDescriptor, objc_class_name="textureBufferDescriptor") +@(objc_type=TextureDescriptor, objc_name="textureBufferDescriptor", objc_is_class_method=true) TextureDescriptor_textureBufferDescriptor :: #force_inline proc(pixelFormat: PixelFormat, width: NS.UInteger, resourceOptions: ResourceOptions, usage: TextureUsage) -> ^TextureDescriptor { return msgSend(^TextureDescriptor, TextureDescriptor, "textureBufferDescriptorWithPixelFormat:width:resourceOptions:usage:", pixelFormat, width, resourceOptions, usage) } -@(objc_type=TextureDescriptor, objc_class_name="textureCubeDescriptor") +@(objc_type=TextureDescriptor, objc_name="textureCubeDescriptor", objc_is_class_method=true) TextureDescriptor_textureCubeDescriptor :: #force_inline proc(pixelFormat: PixelFormat, size: NS.UInteger, mipmapped: BOOL) -> ^TextureDescriptor { return msgSend(^TextureDescriptor, TextureDescriptor, "textureCubeDescriptorWithPixelFormat:size:mipmapped:", pixelFormat, size, mipmapped) } @@ -4514,7 +4514,7 @@ Methods: @(objc_class="MTLTextureReferenceType") TextureReferenceType :: struct { using _: Type } -@(objc_type=TextureReferenceType, objc_class_name="alloc") +@(objc_type=TextureReferenceType, objc_name="alloc", objc_is_class_method=true) TextureReferenceType_alloc :: #force_inline proc() -> ^TextureReferenceType { return msgSend(^TextureReferenceType, TextureReferenceType, "alloc") } @@ -4554,7 +4554,7 @@ Methods: @(objc_class="MTLTileRenderPipelineColorAttachmentDescriptor") TileRenderPipelineColorAttachmentDescriptor :: struct { using _: NS.Copying(TileRenderPipelineColorAttachmentDescriptor) } -@(objc_type=TileRenderPipelineColorAttachmentDescriptor, objc_class_name="alloc") +@(objc_type=TileRenderPipelineColorAttachmentDescriptor, objc_name="alloc", objc_is_class_method=true) TileRenderPipelineColorAttachmentDescriptor_alloc :: #force_inline proc() -> ^TileRenderPipelineColorAttachmentDescriptor { return msgSend(^TileRenderPipelineColorAttachmentDescriptor, TileRenderPipelineColorAttachmentDescriptor, "alloc") } @@ -4586,7 +4586,7 @@ Methods: @(objc_class="MTLTileRenderPipelineColorAttachmentDescriptorArray") TileRenderPipelineColorAttachmentDescriptorArray :: struct { using _: NS.Object } -@(objc_type=TileRenderPipelineColorAttachmentDescriptorArray, objc_class_name="alloc") +@(objc_type=TileRenderPipelineColorAttachmentDescriptorArray, objc_name="alloc", objc_is_class_method=true) TileRenderPipelineColorAttachmentDescriptorArray_alloc :: #force_inline proc() -> ^TileRenderPipelineColorAttachmentDescriptorArray { return msgSend(^TileRenderPipelineColorAttachmentDescriptorArray, TileRenderPipelineColorAttachmentDescriptorArray, "alloc") } @@ -4631,7 +4631,7 @@ Methods: @(objc_class="MTLTileRenderPipelineDescriptor") TileRenderPipelineDescriptor :: struct { using _: NS.Copying(TileRenderPipelineDescriptor) } -@(objc_type=TileRenderPipelineDescriptor, objc_class_name="alloc") +@(objc_type=TileRenderPipelineDescriptor, objc_name="alloc", objc_is_class_method=true) TileRenderPipelineDescriptor_alloc :: #force_inline proc() -> ^TileRenderPipelineDescriptor { return msgSend(^TileRenderPipelineDescriptor, TileRenderPipelineDescriptor, "alloc") } @@ -4714,7 +4714,7 @@ Methods: @(objc_class="MTLType") Type :: struct { using _: NS.Object } -@(objc_type=Type, objc_class_name="alloc") +@(objc_type=Type, objc_name="alloc", objc_is_class_method=true) Type_alloc :: #force_inline proc() -> ^Type { return msgSend(^Type, Type, "alloc") } @@ -4746,7 +4746,7 @@ Methods: @(objc_class="MTLVertexAttribute") VertexAttribute :: struct { using _: NS.Object } -@(objc_type=VertexAttribute, objc_class_name="alloc") +@(objc_type=VertexAttribute, objc_name="alloc", objc_is_class_method=true) VertexAttribute_alloc :: #force_inline proc() -> ^VertexAttribute { return msgSend(^VertexAttribute, VertexAttribute, "alloc") } @@ -4798,7 +4798,7 @@ Methods: @(objc_class="MTLVertexAttributeDescriptor") VertexAttributeDescriptor :: struct { using _: NS.Copying(VertexAttributeDescriptor) } -@(objc_type=VertexAttributeDescriptor, objc_class_name="alloc") +@(objc_type=VertexAttributeDescriptor, objc_name="alloc", objc_is_class_method=true) VertexAttributeDescriptor_alloc :: #force_inline proc() -> ^VertexAttributeDescriptor { return msgSend(^VertexAttributeDescriptor, VertexAttributeDescriptor, "alloc") } @@ -4846,7 +4846,7 @@ Methods: @(objc_class="MTLVertexAttributeDescriptorArray") VertexAttributeDescriptorArray :: struct { using _: NS.Object } -@(objc_type=VertexAttributeDescriptorArray, objc_class_name="alloc") +@(objc_type=VertexAttributeDescriptorArray, objc_name="alloc", objc_is_class_method=true) VertexAttributeDescriptorArray_alloc :: #force_inline proc() -> ^VertexAttributeDescriptorArray { return msgSend(^VertexAttributeDescriptorArray, VertexAttributeDescriptorArray, "alloc") } @@ -4882,7 +4882,7 @@ Methods: @(objc_class="MTLVertexBufferLayoutDescriptor") VertexBufferLayoutDescriptor :: struct { using _: NS.Copying(VertexBufferLayoutDescriptor) } -@(objc_type=VertexBufferLayoutDescriptor, objc_class_name="alloc") +@(objc_type=VertexBufferLayoutDescriptor, objc_name="alloc", objc_is_class_method=true) VertexBufferLayoutDescriptor_alloc :: #force_inline proc() -> ^VertexBufferLayoutDescriptor { return msgSend(^VertexBufferLayoutDescriptor, VertexBufferLayoutDescriptor, "alloc") } @@ -4930,7 +4930,7 @@ Methods: @(objc_class="MTLVertexBufferLayoutDescriptorArray") VertexBufferLayoutDescriptorArray :: struct { using _: NS.Object } -@(objc_type=VertexBufferLayoutDescriptorArray, objc_class_name="alloc") +@(objc_type=VertexBufferLayoutDescriptorArray, objc_name="alloc", objc_is_class_method=true) VertexBufferLayoutDescriptorArray_alloc :: #force_inline proc() -> ^VertexBufferLayoutDescriptorArray { return msgSend(^VertexBufferLayoutDescriptorArray, VertexBufferLayoutDescriptorArray, "alloc") } @@ -4964,7 +4964,7 @@ Methods: @(objc_class="MTLVertexDescriptor") VertexDescriptor :: struct { using _: NS.Copying(VertexDescriptor) } -@(objc_type=VertexDescriptor, objc_class_name="alloc") +@(objc_type=VertexDescriptor, objc_name="alloc", objc_is_class_method=true) VertexDescriptor_alloc :: #force_inline proc() -> ^VertexDescriptor { return msgSend(^VertexDescriptor, VertexDescriptor, "alloc") } @@ -4984,7 +4984,7 @@ VertexDescriptor_layouts :: #force_inline proc(self: ^VertexDescriptor) -> ^Vert VertexDescriptor_reset :: #force_inline proc(self: ^VertexDescriptor) { msgSend(nil, self, "reset") } -@(objc_type=VertexDescriptor, objc_class_name="vertexDescriptor") +@(objc_type=VertexDescriptor, objc_name="vertexDescriptor", objc_is_class_method=true) VertexDescriptor_vertexDescriptor :: #force_inline proc() -> ^VertexDescriptor { return msgSend(^VertexDescriptor, VertexDescriptor, "vertexDescriptor") } @@ -5005,7 +5005,7 @@ Methods: @(objc_class="MTLVisibleFunctionTableDescriptor") VisibleFunctionTableDescriptor :: struct { using _: NS.Copying(VisibleFunctionTableDescriptor) } -@(objc_type=VisibleFunctionTableDescriptor, objc_class_name="alloc") +@(objc_type=VisibleFunctionTableDescriptor, objc_name="alloc", objc_is_class_method=true) VisibleFunctionTableDescriptor_alloc :: #force_inline proc() -> ^VisibleFunctionTableDescriptor { return msgSend(^VisibleFunctionTableDescriptor, VisibleFunctionTableDescriptor, "alloc") } @@ -5021,7 +5021,7 @@ VisibleFunctionTableDescriptor_functionCount :: #force_inline proc(self: ^Visibl VisibleFunctionTableDescriptor_setFunctionCount :: #force_inline proc(self: ^VisibleFunctionTableDescriptor, functionCount: NS.UInteger) { msgSend(nil, self, "setFunctionCount:", functionCount) } -@(objc_type=VisibleFunctionTableDescriptor, objc_class_name="visibleFunctionTableDescriptor") +@(objc_type=VisibleFunctionTableDescriptor, objc_name="visibleFunctionTableDescriptor", objc_is_class_method=true) VisibleFunctionTableDescriptor_visibleFunctionTableDescriptor :: #force_inline proc() -> ^VisibleFunctionTableDescriptor { return msgSend(^VisibleFunctionTableDescriptor, VisibleFunctionTableDescriptor, "visibleFunctionTableDescriptor") } @@ -7976,7 +7976,7 @@ Class: @(objc_class="MTLRenderPipelineFunctionsDescriptor") RenderPipelineFunctionsDescriptor :: struct { using _: NS.Copying(RenderPipelineFunctionsDescriptor) } -@(objc_type=RenderPipelineFunctionsDescriptor, objc_class_name="alloc") +@(objc_type=RenderPipelineFunctionsDescriptor, objc_name="alloc", objc_is_class_method=true) RenderPipelineFunctionsDescriptor_alloc :: #force_inline proc() -> ^RenderPipelineFunctionsDescriptor { return msgSend(^RenderPipelineFunctionsDescriptor, RenderPipelineFunctionsDescriptor, "alloc") } diff --git a/core/sys/darwin/QuartzCore/QuartzCore.odin b/core/sys/darwin/QuartzCore/QuartzCore.odin index 0afb8aa37..c35453efc 100644 --- a/core/sys/darwin/QuartzCore/QuartzCore.odin +++ b/core/sys/darwin/QuartzCore/QuartzCore.odin @@ -10,7 +10,7 @@ msgSend :: intrinsics.objc_send @(objc_class="CAMetalLayer") MetalLayer :: struct{ using _: NS.Layer} -@(objc_type=MetalLayer, objc_class_name="layer") +@(objc_type=MetalLayer, objc_name="layer", objc_is_class_method=true) MetalLayer_layer :: proc() -> ^MetalLayer { return msgSend(^MetalLayer, MetalLayer, "layer") } diff --git a/src/check_decl.cpp b/src/check_decl.cpp index 1d30088d6..45d741532 100644 --- a/src/check_decl.cpp +++ b/src/check_decl.cpp @@ -826,15 +826,13 @@ void check_proc_decl(CheckerContext *ctx, Entity *e, DeclInfo *d) { } e->Procedure.optimization_mode = cast(ProcedureOptimizationMode)ac.optimization_mode; - if (ac.objc_name.len || ac.objc_class_name.len || ac.objc_type) { - if (ac.objc_class_name.len && ac.objc_name.len) { - error(e->token, "@(objc_class_name) and @(objc_name) may not be allowed at the same time"); + if (ac.objc_name.len || ac.objc_is_class_method || ac.objc_type) { + if (ac.objc_name.len == 0 && ac.objc_is_class_method) { + error(e->token, "@(objc_name) is required with @(objc_is_class_method)"); } else if (ac.objc_type == nullptr) { - if (ac.objc_name.len) { - error(e->token, "@(objc_name) requires that @(objc_type) to be set"); - } else { - error(e->token, "@(objc_class_name) requires that @(objc_type) to be set"); - } + error(e->token, "@(objc_name) requires that @(objc_type) to be set"); + } else if (ac.objc_name.len == 0 && ac.objc_type) { + error(e->token, "@(objc_name) is required with @(objc_type)"); } else { Type *t = ac.objc_type; if (t->kind == Type_Named) { @@ -843,7 +841,7 @@ void check_proc_decl(CheckerContext *ctx, Entity *e, DeclInfo *d) { GB_ASSERT(tn->kind == Entity_TypeName); if (tn->scope != e->scope) { - error(e->token, "@(objc_name) and @(objc_class_name) attributes may only be applied to procedures and types within the same scope"); + error(e->token, "@(objc_name) attribute may only be applied to procedures and types within the same scope"); } else { mutex_lock(&global_type_name_objc_metadata_mutex); defer (mutex_unlock(&global_type_name_objc_metadata_mutex)); @@ -855,7 +853,7 @@ void check_proc_decl(CheckerContext *ctx, Entity *e, DeclInfo *d) { mutex_lock(md->mutex); defer (mutex_unlock(md->mutex)); - if (ac.objc_name.len) { + if (!ac.objc_is_class_method) { bool ok = true; for (TypeNameObjCMetadataEntry const &entry : md->value_entries) { if (entry.name == ac.objc_name) { @@ -870,14 +868,14 @@ void check_proc_decl(CheckerContext *ctx, Entity *e, DeclInfo *d) { } else { bool ok = true; for (TypeNameObjCMetadataEntry const &entry : md->type_entries) { - if (entry.name == ac.objc_class_name) { - error(e->token, "Previous declaration of @(objc_class_name=\"%.*s\")", LIT(ac.objc_class_name)); + if (entry.name == ac.objc_name) { + error(e->token, "Previous declaration of @(objc_name=\"%.*s\")", LIT(ac.objc_name)); ok = false; break; } } if (ok) { - array_add(&md->type_entries, TypeNameObjCMetadataEntry{ac.objc_class_name, e}); + array_add(&md->type_entries, TypeNameObjCMetadataEntry{ac.objc_name, e}); } } } diff --git a/src/checker.cpp b/src/checker.cpp index 0dd36987e..dac4dd79f 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -3059,16 +3059,12 @@ DECL_ATTRIBUTE_PROC(proc_decl_attribute) { error(elem, "Expected a string value for '%.*s'", LIT(name)); } return true; - } else if (name == "objc_class_name") { + } else if (name == "objc_is_class_method") { ExactValue ev = check_decl_attribute_value(c, value); - if (ev.kind == ExactValue_String) { - if (string_is_valid_identifier(ev.value_string)) { - ac->objc_class_name = ev.value_string; - } else { - error(elem, "Invalid identifier for '%.*s', got '%.*s'", LIT(name), LIT(ev.value_string)); - } + if (ev.kind == ExactValue_Bool) { + ac->objc_is_class_method = ev.value_bool; } else { - error(elem, "Expected a string value for '%.*s'", LIT(name)); + error(elem, "Expected a boolean value for '%.*s'", LIT(name)); } return true; } else if (name == "objc_type") { diff --git a/src/checker.hpp b/src/checker.hpp index 38c8d32f6..552e6aca7 100644 --- a/src/checker.hpp +++ b/src/checker.hpp @@ -121,7 +121,7 @@ struct AttributeContext { String objc_class; String objc_name; - String objc_class_name; + bool objc_is_class_method; Type * objc_type; }; -- cgit v1.2.3 From 5f8137025d0abb946c186dc01271495cf839a871 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 18 Feb 2022 16:12:21 +0000 Subject: Use `try_to_add_package_dependency` --- src/check_builtin.cpp | 14 +++++++------- src/checker.cpp | 15 ++++++++++++++- 2 files changed, 21 insertions(+), 8 deletions(-) (limited to 'src/checker.cpp') diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp index f440aa4d5..eb9d7f293 100644 --- a/src/check_builtin.cpp +++ b/src/check_builtin.cpp @@ -223,10 +223,10 @@ void add_objc_proc_type(CheckerContext *c, Ast *call, Type *return_type, Sliceinfo->objc_msgSend_types, call, data); mutex_unlock(&c->info->objc_types_mutex); - add_package_dependency(c, "runtime", "objc_msgSend"); - add_package_dependency(c, "runtime", "objc_msgSend_fpret"); - add_package_dependency(c, "runtime", "objc_msgSend_fp2ret"); - add_package_dependency(c, "runtime", "objc_msgSend_stret"); + try_to_add_package_dependency(c, "runtime", "objc_msgSend"); + try_to_add_package_dependency(c, "runtime", "objc_msgSend_fpret"); + try_to_add_package_dependency(c, "runtime", "objc_msgSend_fp2ret"); + try_to_add_package_dependency(c, "runtime", "objc_msgSend_stret"); } bool is_constant_string(CheckerContext *c, String const &builtin_name, Ast *expr, String *name_) { @@ -371,9 +371,9 @@ bool check_builtin_objc_procedure(CheckerContext *c, Operand *operand, Ast *call } operand->mode = Addressing_Value; - add_package_dependency(c, "runtime", "objc_lookUpClass"); - add_package_dependency(c, "runtime", "sel_registerName"); - add_package_dependency(c, "runtime", "objc_allocateClassPair"); + try_to_add_package_dependency(c, "runtime", "objc_lookUpClass"); + try_to_add_package_dependency(c, "runtime", "sel_registerName"); + try_to_add_package_dependency(c, "runtime", "objc_allocateClassPair"); return true; } break; } diff --git a/src/checker.cpp b/src/checker.cpp index 81e6f256e..f8aa8d45b 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -733,12 +733,25 @@ void add_package_dependency(CheckerContext *c, char const *package_name, char co String n = make_string_c(name); AstPackage *p = get_core_package(&c->checker->info, make_string_c(package_name)); Entity *e = scope_lookup(p->scope, n); - e->flags |= EntityFlag_Used; GB_ASSERT_MSG(e != nullptr, "%s", name); GB_ASSERT(c->decl != nullptr); + e->flags |= EntityFlag_Used; + add_dependency(c->info, c->decl, e); +} + +void try_to_add_package_dependency(CheckerContext *c, char const *package_name, char const *name) { + String n = make_string_c(name); + AstPackage *p = get_core_package(&c->checker->info, make_string_c(package_name)); + Entity *e = scope_lookup(p->scope, n); + if (e == nullptr) { + return; + } + GB_ASSERT(c->decl != nullptr); + e->flags |= EntityFlag_Used; add_dependency(c->info, c->decl, e); } + void add_declaration_dependency(CheckerContext *c, Entity *e) { if (e == nullptr) { return; -- cgit v1.2.3 From 71df46456a4db2592e8cebbdd4c46dc8b58b5a24 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 18 Feb 2022 21:30:25 +0000 Subject: Minimize memory usage by having an arena per thread rather than an arena per file --- src/array.cpp | 4 +++- src/checker.cpp | 4 ++-- src/common.cpp | 2 +- src/main.cpp | 2 +- src/parser.cpp | 12 ++++++------ src/parser.hpp | 6 ++---- 6 files changed, 15 insertions(+), 15 deletions(-) (limited to 'src/checker.cpp') diff --git a/src/array.cpp b/src/array.cpp index ac3727978..d08bd647f 100644 --- a/src/array.cpp +++ b/src/array.cpp @@ -89,7 +89,9 @@ template void slice_init(Slice *s, gbAllocator const &allocator, isize count) { GB_ASSERT(count >= 0); s->data = gb_alloc_array(allocator, T, count); - GB_ASSERT(s->data != nullptr); + if (count > 0) { + GB_ASSERT(s->data != nullptr); + } s->count = count; } diff --git a/src/checker.cpp b/src/checker.cpp index f8aa8d45b..f440b7c9a 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -225,8 +225,8 @@ bool decl_info_has_init(DeclInfo *d) { Scope *create_scope(CheckerInfo *info, Scope *parent, isize init_elements_capacity=DEFAULT_SCOPE_CAPACITY) { Scope *s = gb_alloc_item(permanent_allocator(), Scope); s->parent = parent; - string_map_init(&s->elements, permanent_allocator(), init_elements_capacity); - ptr_set_init(&s->imported, permanent_allocator(), 0); + string_map_init(&s->elements, heap_allocator(), init_elements_capacity); + ptr_set_init(&s->imported, heap_allocator(), 0); mutex_init(&s->mutex); if (parent != nullptr && parent != builtin_pkg->scope) { diff --git a/src/common.cpp b/src/common.cpp index ab2a46118..d3ee95b76 100644 --- a/src/common.cpp +++ b/src/common.cpp @@ -1021,7 +1021,7 @@ LoadedFileError load_file_32(char const *fullpath, LoadedFile *memory_mapped_fil #endif } - gbFileContents fc = gb_file_read_contents(heap_allocator(), true, fullpath); + gbFileContents fc = gb_file_read_contents(permanent_allocator(), true, fullpath); if (fc.size > I32_MAX) { err = LoadedFile_FileTooLarge; diff --git a/src/main.cpp b/src/main.cpp index 014fbf822..291b56996 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2577,7 +2577,7 @@ int main(int arg_count, char const **arg_ptr) { // NOTE(bill): add 'shared' directory if it is not already set if (!find_library_collection_path(str_lit("shared"), nullptr)) { add_library_collection(str_lit("shared"), - get_fullpath_relative(heap_allocator(), odin_root_dir(), str_lit("shared"))); + get_fullpath_relative(heap_allocator(), odin_root_dir(), str_lit("shared"))); } diff --git a/src/parser.cpp b/src/parser.cpp index 7309d9769..8a7ab2d20 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -57,6 +57,9 @@ isize ast_node_size(AstKind kind) { return align_formula_isize(gb_size_of(AstCommonStuff) + ast_variant_sizes[kind], gb_align_of(void *)); } + +gb_global std::atomic global_total_node_memory_allocated; + // NOTE(bill): And this below is why is I/we need a new language! Discriminated unions are a pain in C/C++ Ast *alloc_ast_node(AstFile *f, AstKind kind) { gbAllocator a = ast_allocator(f); @@ -66,6 +69,9 @@ Ast *alloc_ast_node(AstFile *f, AstKind kind) { Ast *node = cast(Ast *)gb_alloc(a, size); node->kind = kind; node->file_id = f ? f->id : 0; + + global_total_node_memory_allocated += size; + return node; } @@ -4851,12 +4857,6 @@ ParseFileError init_ast_file(AstFile *f, String fullpath, TokenPos *err_pos) { f->prev_token = f->tokens[f->prev_token_index]; f->curr_token = f->tokens[f->curr_token_index]; - isize const page_size = 4*1024; - isize block_size = 2*f->tokens.count*gb_size_of(Ast); - block_size = ((block_size + page_size-1)/page_size) * page_size; - block_size = gb_clamp(block_size, page_size, DEFAULT_MINIMUM_BLOCK_SIZE); - f->arena.minimum_block_size = block_size; - array_init(&f->comments, heap_allocator(), 0, 0); array_init(&f->imports, heap_allocator(), 0, 0); diff --git a/src/parser.hpp b/src/parser.hpp index 83c755553..f6791a291 100644 --- a/src/parser.hpp +++ b/src/parser.hpp @@ -97,8 +97,6 @@ struct AstFile { AstPackage * pkg; Scope * scope; - Arena arena; - Ast * pkg_decl; String fullpath; Tokenizer tokenizer; @@ -801,10 +799,10 @@ gb_inline bool is_ast_when_stmt(Ast *node) { return node->kind == Ast_WhenStmt; } -gb_global gb_thread_local Arena global_ast_arena = {}; +gb_global gb_thread_local Arena global_thread_local_ast_arena = {}; gbAllocator ast_allocator(AstFile *f) { - Arena *arena = f ? &f->arena : &global_ast_arena; + Arena *arena = &global_thread_local_ast_arena; return arena_allocator(arena); } -- cgit v1.2.3 From 0fa487f468b1f63d5ec97ae8bbb0da01717f32cc Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sun, 20 Feb 2022 14:27:44 +0000 Subject: Add `-foreign-error-procedures` --- core/runtime/error_checks.odin | 20 +++++++++++++++++++- src/build_settings.cpp | 2 ++ src/checker.cpp | 1 + src/main.cpp | 12 ++++++++++++ 4 files changed, 34 insertions(+), 1 deletion(-) (limited to 'src/checker.cpp') diff --git a/core/runtime/error_checks.odin b/core/runtime/error_checks.odin index 14d55c64c..ad6902e2d 100644 --- a/core/runtime/error_checks.odin +++ b/core/runtime/error_checks.odin @@ -17,6 +17,24 @@ type_assertion_trap :: proc "contextless" () -> ! { } +when ODIN_FOREIGN_ERROR_PROCEDURES { + foreign { + bounds_check_error :: proc "contextless" (file: string, line, column: i32, index, count: int) --- + slice_handle_error :: proc "contextless" (file: string, line, column: i32, lo, hi: int, len: int) -> ! --- + multi_pointer_slice_handle_error :: proc "contextless" (file: string, line, column: i32, lo, hi: int) -> ! --- + multi_pointer_slice_expr_error :: proc "contextless" (file: string, line, column: i32, lo, hi: int) --- + slice_expr_error_hi :: proc "contextless" (file: string, line, column: i32, hi: int, len: int) --- + slice_expr_error_lo_hi :: proc "contextless" (file: string, line, column: i32, lo, hi: int, len: int) --- + dynamic_array_expr_error :: proc "contextless" (file: string, line, column: i32, low, high, max: int) --- + matrix_bounds_check_error :: proc "contextless" (file: string, line, column: i32, row_index, column_index, row_count, column_count: int) --- + type_assertion_check :: proc "contextless" (ok: bool, file: string, line, column: i32, from, to: typeid) --- + type_assertion_check2 :: proc "contextless" (ok: bool, file: string, line, column: i32, from, to: typeid, from_data: rawptr) --- + make_slice_error_loc :: proc "contextless" (loc := #caller_location, len: int) --- + make_dynamic_array_error_loc :: proc "contextless" (using loc := #caller_location, len, cap: int) --- + make_map_expr_error_loc :: proc "contextless" (loc := #caller_location, cap: int) --- + } +} else { + bounds_check_error :: proc "contextless" (file: string, line, column: i32, index, count: int) { if 0 <= index && index < count { return @@ -231,7 +249,7 @@ make_map_expr_error_loc :: #force_inline proc "contextless" (loc := #caller_loca handle_error(loc, cap) } - +} diff --git a/src/build_settings.cpp b/src/build_settings.cpp index cc76f9e7c..cd9bdb40c 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -200,6 +200,7 @@ struct BuildContext { bool ODIN_DEBUG; // Odin in debug mode bool ODIN_DISABLE_ASSERT; // Whether the default 'assert' et al is disabled in code or not bool ODIN_DEFAULT_TO_NIL_ALLOCATOR; // Whether the default allocator is a "nil" allocator or not (i.e. it does nothing) + bool ODIN_FOREIGN_ERROR_PROCEDURES; ErrorPosStyle ODIN_ERROR_POS_STYLE; @@ -269,6 +270,7 @@ struct BuildContext { bool copy_file_contents; + u32 cmd_doc_flags; Array extra_packages; diff --git a/src/checker.cpp b/src/checker.cpp index f440b7c9a..fe1d362fa 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -976,6 +976,7 @@ void init_universal(void) { add_global_bool_constant("ODIN_USE_SEPARATE_MODULES", bc->use_separate_modules); add_global_bool_constant("ODIN_TEST", bc->command_kind == Command_test); add_global_bool_constant("ODIN_NO_ENTRY_POINT", bc->no_entry_point); + add_global_bool_constant("ODIN_FOREIGN_ERROR_PROCEDURES", bc->ODIN_FOREIGN_ERROR_PROCEDURES); // Builtin Procedures diff --git a/src/main.cpp b/src/main.cpp index 291b56996..5746ef146 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -632,6 +632,7 @@ enum BuildFlagKind { BuildFlag_InsertSemicolon, BuildFlag_StrictStyle, BuildFlag_StrictStyleInitOnly, + BuildFlag_ForeignErrorProcedures, BuildFlag_Compact, BuildFlag_GlobalDefinitions, @@ -785,10 +786,13 @@ bool parse_build_flags(Array args) { add_flag(&build_flags, BuildFlag_InsertSemicolon, str_lit("insert-semicolon"), BuildFlagParam_None, Command__does_check); add_flag(&build_flags, BuildFlag_StrictStyle, str_lit("strict-style"), BuildFlagParam_None, Command__does_check); add_flag(&build_flags, BuildFlag_StrictStyleInitOnly, str_lit("strict-style-init-only"), BuildFlagParam_None, Command__does_check); + add_flag(&build_flags, BuildFlag_ForeignErrorProcedures, str_lit("foreign-error-procedures"), BuildFlagParam_None, Command__does_check); + add_flag(&build_flags, BuildFlag_Compact, str_lit("compact"), BuildFlagParam_None, Command_query); add_flag(&build_flags, BuildFlag_GlobalDefinitions, str_lit("global-definitions"), BuildFlagParam_None, Command_query); add_flag(&build_flags, BuildFlag_GoToDefinitions, str_lit("go-to-definitions"), BuildFlagParam_None, Command_query); + add_flag(&build_flags, BuildFlag_Short, str_lit("short"), BuildFlagParam_None, Command_doc); add_flag(&build_flags, BuildFlag_AllPackages, str_lit("all-packages"), BuildFlagParam_None, Command_doc); add_flag(&build_flags, BuildFlag_DocFormat, str_lit("doc-format"), BuildFlagParam_None, Command_doc); @@ -1356,6 +1360,9 @@ bool parse_build_flags(Array args) { case BuildFlag_DefaultToNilAllocator: build_context.ODIN_DEFAULT_TO_NIL_ALLOCATOR = true; break; + case BuildFlag_ForeignErrorProcedures: + build_context.ODIN_FOREIGN_ERROR_PROCEDURES = true; + break; case BuildFlag_InsertSemicolon: { gb_printf_err("-insert-semicolon flag is not required any more\n"); bad_flags = true; @@ -2084,6 +2091,11 @@ void print_show_help(String const arg0, String const &command) { print_usage_line(1, "-verbose-errors"); print_usage_line(2, "Prints verbose error messages showing the code on that line and the location in that line"); print_usage_line(0, ""); + + print_usage_line(1, "-foreign-error-procedures"); + print_usage_line(2, "States that the error procedues used in the runtime are defined in a separate translation unit"); + print_usage_line(0, ""); + } if (run_or_build) { -- cgit v1.2.3 From 493bc653b5762514dac8c8941d6564ccf5bb8528 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 23 Feb 2022 11:23:27 +0000 Subject: Add `@(no_red_zone)` for procedures --- src/check_decl.cpp | 8 ++++++++ src/checker.cpp | 7 +++++++ src/checker.hpp | 1 + src/entity.cpp | 1 + src/llvm_backend_proc.cpp | 4 ++++ 5 files changed, 21 insertions(+) (limited to 'src/checker.cpp') diff --git a/src/check_decl.cpp b/src/check_decl.cpp index 45d741532..6f8caff98 100644 --- a/src/check_decl.cpp +++ b/src/check_decl.cpp @@ -826,6 +826,14 @@ void check_proc_decl(CheckerContext *ctx, Entity *e, DeclInfo *d) { } e->Procedure.optimization_mode = cast(ProcedureOptimizationMode)ac.optimization_mode; + if (ac.no_red_zone) { + if (!is_arch_wasm()) { + e->Procedure.no_red_zone = true; + } else { + error(e->token, "@(no_red_zone) is not supported on this target architecture"); + } + } + if (ac.objc_name.len || ac.objc_is_class_method || ac.objc_type) { if (ac.objc_name.len == 0 && ac.objc_is_class_method) { error(e->token, "@(objc_name) is required with @(objc_is_class_method)"); diff --git a/src/checker.cpp b/src/checker.cpp index fe1d362fa..89e60c258 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -3128,6 +3128,13 @@ DECL_ATTRIBUTE_PROC(proc_decl_attribute) { } } return true; + } else if (name == "no_red_zone") { + if (value != nullptr) { + error(elem, "Expected no value for '%.*s'", LIT(name)); + } else { + ac->no_red_zone = true; + } + return true; } return false; } diff --git a/src/checker.hpp b/src/checker.hpp index 552e6aca7..548439774 100644 --- a/src/checker.hpp +++ b/src/checker.hpp @@ -117,6 +117,7 @@ struct AttributeContext { bool test : 1; bool init : 1; bool set_cold : 1; + bool no_red_zone : 1; u32 optimization_mode; // ProcedureOptimizationMode String objc_class; diff --git a/src/entity.cpp b/src/entity.cpp index f5720293f..84ddd5c6b 100644 --- a/src/entity.cpp +++ b/src/entity.cpp @@ -226,6 +226,7 @@ struct Entity { bool is_foreign; bool is_export; bool generated_from_polymorphic; + bool no_red_zone; ProcedureOptimizationMode optimization_mode; } Procedure; struct { diff --git a/src/llvm_backend_proc.cpp b/src/llvm_backend_proc.cpp index 7ead77c2c..209f2f67b 100644 --- a/src/llvm_backend_proc.cpp +++ b/src/llvm_backend_proc.cpp @@ -135,6 +135,10 @@ lbProcedure *lb_create_procedure(lbModule *m, Entity *entity, bool ignore_body) lb_add_attribute_to_proc(m, p->value, "naked"); } + if (entity->Procedure.no_red_zone) { + lb_add_attribute_to_proc(m, p->value, "noredzone"); + } + switch (p->inlining) { case ProcInlining_inline: lb_add_attribute_to_proc(m, p->value, "alwaysinline"); -- cgit v1.2.3 From 196bd735d4c30964182fdf1f374f767ccb0912fa Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 23 Feb 2022 11:29:36 +0000 Subject: Replace local `@(no_red_zone)` with global `-disable-red-zone` --- src/build_settings.cpp | 8 ++++++++ src/check_decl.cpp | 8 -------- src/checker.cpp | 7 ------- src/checker.hpp | 1 - src/entity.cpp | 1 - src/llvm_backend_proc.cpp | 2 +- src/main.cpp | 8 ++++++++ 7 files changed, 17 insertions(+), 18 deletions(-) (limited to 'src/checker.cpp') diff --git a/src/build_settings.cpp b/src/build_settings.cpp index 790f7f1bc..62f43fad3 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -278,6 +278,7 @@ struct BuildContext { bool copy_file_contents; RelocMode reloc_mode; + bool disable_red_zone; u32 cmd_doc_flags; @@ -1002,6 +1003,13 @@ void init_build_context(TargetMetrics *cross_target) { bc->threaded_checker = true; #endif + if (bc->disable_red_zone) { + if (!(bc->metrics.os == TargetOs_freestanding && !is_arch_wasm())) { + gb_printf_err("-disable-red-zone is not support for this target"); + gb_exit(1); + } + } + // NOTE(zangent): The linker flags to set the build architecture are different // across OSs. It doesn't make sense to allocate extra data on the heap diff --git a/src/check_decl.cpp b/src/check_decl.cpp index 6f8caff98..45d741532 100644 --- a/src/check_decl.cpp +++ b/src/check_decl.cpp @@ -826,14 +826,6 @@ void check_proc_decl(CheckerContext *ctx, Entity *e, DeclInfo *d) { } e->Procedure.optimization_mode = cast(ProcedureOptimizationMode)ac.optimization_mode; - if (ac.no_red_zone) { - if (!is_arch_wasm()) { - e->Procedure.no_red_zone = true; - } else { - error(e->token, "@(no_red_zone) is not supported on this target architecture"); - } - } - if (ac.objc_name.len || ac.objc_is_class_method || ac.objc_type) { if (ac.objc_name.len == 0 && ac.objc_is_class_method) { error(e->token, "@(objc_name) is required with @(objc_is_class_method)"); diff --git a/src/checker.cpp b/src/checker.cpp index 89e60c258..fe1d362fa 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -3128,13 +3128,6 @@ DECL_ATTRIBUTE_PROC(proc_decl_attribute) { } } return true; - } else if (name == "no_red_zone") { - if (value != nullptr) { - error(elem, "Expected no value for '%.*s'", LIT(name)); - } else { - ac->no_red_zone = true; - } - return true; } return false; } diff --git a/src/checker.hpp b/src/checker.hpp index 548439774..552e6aca7 100644 --- a/src/checker.hpp +++ b/src/checker.hpp @@ -117,7 +117,6 @@ struct AttributeContext { bool test : 1; bool init : 1; bool set_cold : 1; - bool no_red_zone : 1; u32 optimization_mode; // ProcedureOptimizationMode String objc_class; diff --git a/src/entity.cpp b/src/entity.cpp index 84ddd5c6b..f5720293f 100644 --- a/src/entity.cpp +++ b/src/entity.cpp @@ -226,7 +226,6 @@ struct Entity { bool is_foreign; bool is_export; bool generated_from_polymorphic; - bool no_red_zone; ProcedureOptimizationMode optimization_mode; } Procedure; struct { diff --git a/src/llvm_backend_proc.cpp b/src/llvm_backend_proc.cpp index 209f2f67b..053ee2fb2 100644 --- a/src/llvm_backend_proc.cpp +++ b/src/llvm_backend_proc.cpp @@ -135,7 +135,7 @@ lbProcedure *lb_create_procedure(lbModule *m, Entity *entity, bool ignore_body) lb_add_attribute_to_proc(m, p->value, "naked"); } - if (entity->Procedure.no_red_zone) { + if (!entity->Procedure.is_foreign && build_context.disable_red_zone) { lb_add_attribute_to_proc(m, p->value, "noredzone"); } diff --git a/src/main.cpp b/src/main.cpp index cfc7decb1..1e7b78da4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -626,6 +626,7 @@ enum BuildFlagKind { BuildFlag_Microarch, BuildFlag_RelocMode, + BuildFlag_DisableRedZone, BuildFlag_TestName, @@ -782,6 +783,7 @@ bool parse_build_flags(Array args) { add_flag(&build_flags, BuildFlag_Microarch, str_lit("microarch"), BuildFlagParam_String, Command__does_build); add_flag(&build_flags, BuildFlag_RelocMode, str_lit("reloc-mode"), BuildFlagParam_String, Command__does_build); + add_flag(&build_flags, BuildFlag_DisableRedZone, str_lit("disable-red-zone"), BuildFlagParam_None, Command__does_build); add_flag(&build_flags, BuildFlag_TestName, str_lit("test-name"), BuildFlagParam_String, Command_test); @@ -1365,6 +1367,9 @@ bool parse_build_flags(Array args) { break; } + case BuildFlag_DisableRedZone: + build_context.disable_red_zone = true; + break; case BuildFlag_TestName: { GB_ASSERT(value.kind == ExactValue_String); { @@ -2096,6 +2101,9 @@ void print_show_help(String const arg0, String const &command) { print_usage_line(3, "pic"); print_usage_line(3, "dynamic-no-pic"); print_usage_line(0, ""); + + print_usage_line(1, "-disable-red-zone"); + print_usage_line(2, "Disable red zone on a supported freestanding target"); } if (check) { -- cgit v1.2.3 From 5676c9e7ebcec9af526c59ece1faf2e8b15e457c Mon Sep 17 00:00:00 2001 From: Sébastien Marie Date: Fri, 25 Feb 2022 08:49:25 +0000 Subject: initial OpenBSD support --- Makefile | 6 + core/c/libc/errno.odin | 13 + core/c/libc/stdio.odin | 25 ++ core/c/libc/time.odin | 9 +- core/c/libc/wctype.odin | 5 + core/crypto/rand_generic.odin | 2 +- core/crypto/rand_openbsd.odin | 12 + core/dynlib/lib_unix.odin | 2 +- core/os/dir_openbsd.odin | 71 ++++ core/os/os_openbsd.odin | 706 +++++++++++++++++++++++++++++++ core/os/stat_unix.odin | 2 +- core/path/filepath/path_unix.odin | 7 +- core/runtime/entry_unix.odin | 2 +- core/sync/channel_unix.odin | 2 +- core/sync/sync2/futex_openbsd.odin | 78 ++++ core/sync/sync2/primitives_openbsd.odin | 9 + core/sync/sync2/primitives_pthreads.odin | 2 +- core/sync/sync_openbsd.odin | 36 ++ core/sync/sync_unix.odin | 2 +- core/sys/unix/pthread_openbsd.odin | 65 +++ core/sys/unix/pthread_unix.odin | 2 +- core/thread/thread_unix.odin | 2 +- core/time/time_unix.odin | 34 +- src/bug_report.cpp | 14 +- src/build_settings.cpp | 18 + src/check_builtin.cpp | 1 + src/checker.cpp | 1 + src/common.cpp | 2 +- src/gb/gb.h | 46 +- src/threading.cpp | 2 +- 30 files changed, 1151 insertions(+), 27 deletions(-) create mode 100644 core/crypto/rand_openbsd.odin create mode 100644 core/os/dir_openbsd.odin create mode 100644 core/os/os_openbsd.odin create mode 100644 core/sync/sync2/futex_openbsd.odin create mode 100644 core/sync/sync2/primitives_openbsd.odin create mode 100644 core/sync/sync_openbsd.odin create mode 100644 core/sys/unix/pthread_openbsd.odin (limited to 'src/checker.cpp') diff --git a/Makefile b/Makefile index d3d3c6a2d..99c71ccd9 100644 --- a/Makefile +++ b/Makefile @@ -58,6 +58,12 @@ ifeq ($(OS), Linux) CFLAGS:=$(CFLAGS) $(shell $(LLVM_CONFIG) --cxxflags --ldflags) LDFLAGS:=$(LDFLAGS) $(shell $(LLVM_CONFIG) --libs core native --system-libs) endif +ifeq ($(OS), OpenBSD) + LLVM_CONFIG=/usr/local/bin/llvm-config + + CFLAGS:=$(CFLAGS) $(shell $(LLVM_CONFIG) --cxxflags --ldflags) + LDFLAGS:=$(LDFLAGS) -liconv $(shell $(LLVM_CONFIG) --libs core native --system-libs) +endif all: debug demo diff --git a/core/c/libc/errno.odin b/core/c/libc/errno.odin index ecde6af59..53437f42f 100644 --- a/core/c/libc/errno.odin +++ b/core/c/libc/errno.odin @@ -27,6 +27,19 @@ when ODIN_OS == .Linux || ODIN_OS == .FreeBSD { ERANGE :: 34 } +when ODIN_OS == .OpenBSD { + @(private="file") + @(default_calling_convention="c") + foreign libc { + @(link_name="__errno") + _get_errno :: proc() -> ^int --- + } + + EDOM :: 33 + EILSEQ :: 84 + ERANGE :: 34 +} + when ODIN_OS == .Windows { @(private="file") @(default_calling_convention="c") diff --git a/core/c/libc/stdio.odin b/core/c/libc/stdio.odin index 9c4a1a708..fc65b954a 100644 --- a/core/c/libc/stdio.odin +++ b/core/c/libc/stdio.odin @@ -78,6 +78,31 @@ when ODIN_OS == .Linux { } } +when ODIN_OS == .OpenBSD { + fpos_t :: i64 + + _IOFBF :: 0 + _IOLBF :: 1 + _IONBF :: 1 + + BUFSIZ :: 1024 + + EOF :: int(-1) + + FOPEN_MAX :: 20 + FILENAME_MAX :: 1024 + + SEEK_SET :: 0 + SEEK_CUR :: 1 + SEEK_END :: 2 + + foreign libc { + stderr: ^FILE + stdin: ^FILE + stdout: ^FILE + } +} + when ODIN_OS == .Darwin { fpos_t :: distinct i64 diff --git a/core/c/libc/time.odin b/core/c/libc/time.odin index b3539a227..b337e139a 100644 --- a/core/c/libc/time.odin +++ b/core/c/libc/time.odin @@ -45,7 +45,7 @@ when ODIN_OS == .Windows { } } -when ODIN_OS == .Linux || ODIN_OS == .FreeBSD || ODIN_OS == .Darwin { +when ODIN_OS == .Linux || ODIN_OS == .FreeBSD || ODIN_OS == .Darwin || ODIN_OS == .OpenBSD { @(default_calling_convention="c") foreign libc { // 7.27.2 Time manipulation functions @@ -63,7 +63,12 @@ when ODIN_OS == .Linux || ODIN_OS == .FreeBSD || ODIN_OS == .Darwin { strftime :: proc(s: [^]char, maxsize: size_t, format: cstring, timeptr: ^tm) -> size_t --- } - CLOCKS_PER_SEC :: 1000000 + when ODIN_OS == .OpenBSD { + CLOCKS_PER_SEC :: 100 + } else { + CLOCKS_PER_SEC :: 1000000 + } + TIME_UTC :: 1 time_t :: distinct i64 diff --git a/core/c/libc/wctype.odin b/core/c/libc/wctype.odin index 942726ba6..f833af51f 100644 --- a/core/c/libc/wctype.odin +++ b/core/c/libc/wctype.odin @@ -25,6 +25,11 @@ when ODIN_OS == .Darwin { wctype_t :: distinct u32 } +when ODIN_OS == .OpenBSD { + wctrans_t :: distinct rawptr + wctype_t :: distinct rawptr +} + @(default_calling_convention="c") foreign libc { // 7.30.2.1 Wide character classification functions diff --git a/core/crypto/rand_generic.odin b/core/crypto/rand_generic.odin index be6987ee2..10edc1c8a 100644 --- a/core/crypto/rand_generic.odin +++ b/core/crypto/rand_generic.odin @@ -1,6 +1,6 @@ package crypto -when ODIN_OS != .Linux { +when ODIN_OS != .Linux && ODIN_OS != .OpenBSD { _rand_bytes :: proc (dst: []byte) { unimplemented("crypto: rand_bytes not supported on this OS") } diff --git a/core/crypto/rand_openbsd.odin b/core/crypto/rand_openbsd.odin new file mode 100644 index 000000000..bae97e8f0 --- /dev/null +++ b/core/crypto/rand_openbsd.odin @@ -0,0 +1,12 @@ +package crypto + +import "core:c" + +foreign import libc "system:c" +foreign libc { + arc4random_buf :: proc "c" (buf: rawptr, nbytes: c.size_t) --- +} + +_rand_bytes :: proc (dst: []byte) { + arc4random_buf(raw_data(dst), len(dst)) +} diff --git a/core/dynlib/lib_unix.odin b/core/dynlib/lib_unix.odin index bb8affb79..e52ade153 100644 --- a/core/dynlib/lib_unix.odin +++ b/core/dynlib/lib_unix.odin @@ -1,4 +1,4 @@ -// +build linux, darwin, freebsd +// +build linux, darwin, freebsd, openbsd package dynlib import "core:os" diff --git a/core/os/dir_openbsd.odin b/core/os/dir_openbsd.odin new file mode 100644 index 000000000..465fd35ae --- /dev/null +++ b/core/os/dir_openbsd.odin @@ -0,0 +1,71 @@ +package os + +import "core:strings" +import "core:mem" + +read_dir :: proc(fd: Handle, n: int, allocator := context.allocator) -> (fi: []File_Info, err: Errno) { + dirp: Dir + dirp, err = _fdopendir(fd) + if err != ERROR_NONE { + return + } + + defer _closedir(dirp) + + // XXX OpenBSD + dirpath: string + dirpath, err = absolute_path_from_handle(fd) + + if err != ERROR_NONE { + return + } + + defer delete(dirpath) + + n := n + size := n + if n <= 0 { + n = -1 + size = 100 + } + + dfi := make([dynamic]File_Info, 0, size, allocator) + + for { + entry: Dirent + end_of_stream: bool + entry, err, end_of_stream = _readdir(dirp) + if err != ERROR_NONE { + for fi_ in dfi { + file_info_delete(fi_, allocator) + } + delete(dfi) + return + } else if end_of_stream { + break + } + + fi_: File_Info + filename := cast(string)(transmute(cstring)mem.Raw_Cstring{ data = &entry.name[0] }) + + if filename == "." || filename == ".." { + continue + } + + fullpath := strings.join( []string{ dirpath, filename }, "/", context.temp_allocator) + defer delete(fullpath, context.temp_allocator) + + fi_, err = stat(fullpath, allocator) + if err != ERROR_NONE { + for fi__ in dfi { + file_info_delete(fi__, allocator) + } + delete(dfi) + return + } + + append(&dfi, fi_) + } + + return dfi[:], ERROR_NONE +} diff --git a/core/os/os_openbsd.odin b/core/os/os_openbsd.odin new file mode 100644 index 000000000..3862851a1 --- /dev/null +++ b/core/os/os_openbsd.odin @@ -0,0 +1,706 @@ +package os + +foreign import libc "system:c" + +import "core:runtime" +import "core:strings" +import "core:c" + +Handle :: distinct i32 +Pid :: distinct i32 +File_Time :: distinct u64 +Errno :: distinct i32 + +INVALID_HANDLE :: ~Handle(0) + +ERROR_NONE: Errno: 0 + +EPERM: Errno: 1 +ENOENT: Errno: 2 +ESRCH: Errno: 3 +EINTR: Errno: 4 +EIO: Errno: 5 +ENXIO: Errno: 6 +E2BIG: Errno: 7 +ENOEXEC: Errno: 8 +EBADF: Errno: 9 +ECHILD: Errno: 10 +EDEADLK: Errno: 11 +ENOMEM: Errno: 12 +EACCES: Errno: 13 +EFAULT: Errno: 14 +ENOTBLK: Errno: 15 +EBUSY: Errno: 16 +EEXIST: Errno: 17 +EXDEV: Errno: 18 +ENODEV: Errno: 19 +ENOTDIR: Errno: 20 +EISDIR: Errno: 21 +EINVAL: Errno: 22 +ENFILE: Errno: 23 +EMFILE: Errno: 24 +ENOTTY: Errno: 25 +ETXTBSY: Errno: 26 +EFBIG: Errno: 27 +ENOSPC: Errno: 28 +ESPIPE: Errno: 29 +EROFS: Errno: 30 +EMLINK: Errno: 31 +EPIPE: Errno: 32 +EDOM: Errno: 33 +ERANGE: Errno: 34 +EAGAIN: Errno: 35 +EWOULDBLOCK: Errno: EAGAIN +EINPROGRESS: Errno: 36 +EALREADY: Errno: 37 +ENOTSOCK: Errno: 38 +EDESTADDRREQ: Errno: 39 +EMSGSIZE: Errno: 40 +EPROTOTYPE: Errno: 41 +ENOPROTOOPT: Errno: 42 +EPROTONOSUPPORT: Errno: 43 +ESOCKTNOSUPPORT: Errno: 44 +EOPNOTSUPP: Errno: 45 +EPFNOSUPPORT: Errno: 46 +EAFNOSUPPORT: Errno: 47 +EADDRINUSE: Errno: 48 +EADDRNOTAVAIL: Errno: 49 +ENETDOWN: Errno: 50 +ENETUNREACH: Errno: 51 +ENETRESET: Errno: 52 +ECONNABORTED: Errno: 53 +ECONNRESET: Errno: 54 +ENOBUFS: Errno: 55 +EISCONN: Errno: 56 +ENOTCONN: Errno: 57 +ESHUTDOWN: Errno: 58 +ETOOMANYREFS: Errno: 59 +ETIMEDOUT: Errno: 60 +ECONNREFUSED: Errno: 61 +ELOOP: Errno: 62 +ENAMETOOLONG: Errno: 63 +EHOSTDOWN: Errno: 64 +EHOSTUNREACH: Errno: 65 +ENOTEMPTY: Errno: 66 +EPROCLIM: Errno: 67 +EUSERS: Errno: 68 +EDQUOT: Errno: 69 +ESTALE: Errno: 70 +EREMOTE: Errno: 71 +EBADRPC: Errno: 72 +ERPCMISMATCH: Errno: 73 +EPROGUNAVAIL: Errno: 74 +EPROGMISMATCH: Errno: 75 +EPROCUNAVAIL: Errno: 76 +ENOLCK: Errno: 77 +ENOSYS: Errno: 78 +EFTYPE: Errno: 79 +EAUTH: Errno: 80 +ENEEDAUTH: Errno: 81 +EIPSEC: Errno: 82 +ENOATTR: Errno: 83 +EILSEQ: Errno: 84 +ENOMEDIUM: Errno: 85 +EMEDIUMTYPE: Errno: 86 +EOVERFLOW: Errno: 87 +ECANCELED: Errno: 88 +EIDRM: Errno: 89 +ENOMSG: Errno: 90 +ENOTSUP: Errno: 91 +EBADMSG: Errno: 92 +ENOTRECOVERABLE: Errno: 93 +EOWNERDEAD: Errno: 94 +EPROTO: Errno: 95 + +O_RDONLY :: 0x00000 +O_WRONLY :: 0x00001 +O_RDWR :: 0x00002 +O_NONBLOCK :: 0x00004 +O_APPEND :: 0x00008 +O_ASYNC :: 0x00040 +O_SYNC :: 0x00080 +O_CREATE :: 0x00200 +O_TRUNC :: 0x00400 +O_EXCL :: 0x00800 +O_NOCTTY :: 0x08000 +O_CLOEXEC :: 0x10000 + +SEEK_SET :: 0 +SEEK_CUR :: 1 +SEEK_END :: 2 + +RTLD_LAZY :: 0x001 +RTLD_NOW :: 0x002 +RTLD_LOCAL :: 0x000 +RTLD_GLOBAL :: 0x100 +RTLD_TRACE :: 0x200 +RTLD_NODELETE :: 0x400 + +MAX_PATH :: 1024 + +// "Argv" arguments converted to Odin strings +args := _alloc_command_line_arguments() + +pid_t :: i32 +time_t :: i64 +mode_t :: u32 +dev_t :: i32 +ino_t :: u64 +nlink_t :: u32 +uid_t :: u32 +gid_t :: u32 +off_t :: i64 +blkcnt_t :: u64 +blksize_t :: i32 + +Unix_File_Time :: struct { + seconds: time_t, + nanoseconds: c.long, +} + +OS_Stat :: struct { + mode: mode_t, // inode protection mode + device_id: dev_t, // inode's device + serial: ino_t, // inode's number + nlink: nlink_t, // number of hard links + uid: uid_t, // user ID of the file's owner + gid: gid_t, // group ID of the file's group + rdev: dev_t, // device type + + last_access: Unix_File_Time, // time of last access + modified: Unix_File_Time, // time of last data modification + status_change: Unix_File_Time, // time of last file status change + + size: off_t, // file size, in bytes + blocks: blkcnt_t, // blocks allocated for file + block_size: blksize_t, // optimal blocksize for I/O + + flags: u32, // user defined flags for file + gen: u32, // file generation number + birthtime: Unix_File_Time, // time of file creation +} + +MAXNAMLEN :: 255 + +// NOTE(laleksic, 2021-01-21): Comment and rename these to match OS_Stat above +Dirent :: struct { + ino: ino_t, // file number of entry + off: off_t, // offset after this entry + reclen: u16, // length of this record + type: u8, // file type + namlen: u8, // length of string in name + _padding: [4]u8, + name: [MAXNAMLEN + 1]byte, // name +} + +Dir :: distinct rawptr // DIR* + +// File type +S_IFMT :: 0o170000 // Type of file mask +S_IFIFO :: 0o010000 // Named pipe (fifo) +S_IFCHR :: 0o020000 // Character special +S_IFDIR :: 0o040000 // Directory +S_IFBLK :: 0o060000 // Block special +S_IFREG :: 0o100000 // Regular +S_IFLNK :: 0o120000 // Symbolic link +S_IFSOCK :: 0o140000 // Socket +S_ISVTX :: 0o001000 // Save swapped text even after use + +// File mode + // Read, write, execute/search by owner +S_IRWXU :: 0o0700 // RWX mask for owner +S_IRUSR :: 0o0400 // R for owner +S_IWUSR :: 0o0200 // W for owner +S_IXUSR :: 0o0100 // X for owner + + // Read, write, execute/search by group +S_IRWXG :: 0o0070 // RWX mask for group +S_IRGRP :: 0o0040 // R for group +S_IWGRP :: 0o0020 // W for group +S_IXGRP :: 0o0010 // X for group + + // Read, write, execute/search by others +S_IRWXO :: 0o0007 // RWX mask for other +S_IROTH :: 0o0004 // R for other +S_IWOTH :: 0o0002 // W for other +S_IXOTH :: 0o0001 // X for other + +S_ISUID :: 0o4000 // Set user id on execution +S_ISGID :: 0o2000 // Set group id on execution +S_ISTXT :: 0o1000 // Sticky bit + +S_ISLNK :: #force_inline proc(m: u32) -> bool { return (m & S_IFMT) == S_IFLNK } +S_ISREG :: #force_inline proc(m: u32) -> bool { return (m & S_IFMT) == S_IFREG } +S_ISDIR :: #force_inline proc(m: u32) -> bool { return (m & S_IFMT) == S_IFDIR } +S_ISCHR :: #force_inline proc(m: u32) -> bool { return (m & S_IFMT) == S_IFCHR } +S_ISBLK :: #force_inline proc(m: u32) -> bool { return (m & S_IFMT) == S_IFBLK } +S_ISFIFO :: #force_inline proc(m: u32) -> bool { return (m & S_IFMT) == S_IFIFO } +S_ISSOCK :: #force_inline proc(m: u32) -> bool { return (m & S_IFMT) == S_IFSOCK } + +F_OK :: 0x00 // Test for file existance +X_OK :: 0x01 // Test for execute permission +W_OK :: 0x02 // Test for write permission +R_OK :: 0x04 // Test for read permission + +AT_FDCWD :: -100 +AT_EACCESS :: 0x01 +AT_SYMLINK_NOFOLLOW :: 0x02 +AT_SYMLINK_FOLLOW :: 0x04 +AT_REMOVEDIR :: 0x08 + +@(default_calling_convention="c") +foreign libc { + @(link_name="__errno") __errno :: proc() -> ^int --- + + @(link_name="fork") _unix_fork :: proc() -> pid_t --- + @(link_name="getthrid") _unix_getthrid :: proc() -> int --- + + @(link_name="open") _unix_open :: proc(path: cstring, flags: c.int, mode: c.int) -> Handle --- + @(link_name="close") _unix_close :: proc(fd: Handle) -> c.int --- + @(link_name="read") _unix_read :: proc(fd: Handle, buf: rawptr, size: c.size_t) -> c.ssize_t --- + @(link_name="write") _unix_write :: proc(fd: Handle, buf: rawptr, size: c.size_t) -> c.ssize_t --- + @(link_name="lseek") _unix_seek :: proc(fd: Handle, offset: off_t, whence: c.int) -> off_t --- + @(link_name="stat") _unix_stat :: proc(path: cstring, sb: ^OS_Stat) -> c.int --- + @(link_name="fstat") _unix_fstat :: proc(fd: Handle, sb: ^OS_Stat) -> c.int --- + @(link_name="lstat") _unix_lstat :: proc(path: cstring, sb: ^OS_Stat) -> c.int --- + @(link_name="readlink") _unix_readlink :: proc(path: cstring, buf: ^byte, bufsiz: c.size_t) -> c.ssize_t --- + @(link_name="access") _unix_access :: proc(path: cstring, mask: c.int) -> c.int --- + @(link_name="getcwd") _unix_getcwd :: proc(buf: cstring, len: c.size_t) -> cstring --- + @(link_name="chdir") _unix_chdir :: proc(path: cstring) -> c.int --- + @(link_name="rename") _unix_rename :: proc(old, new: cstring) -> c.int --- + @(link_name="unlink") _unix_unlink :: proc(path: cstring) -> c.int --- + @(link_name="rmdir") _unix_rmdir :: proc(path: cstring) -> c.int --- + @(link_name="mkdir") _unix_mkdir :: proc(path: cstring, mode: mode_t) -> c.int --- + + @(link_name="getpagesize") _unix_getpagesize :: proc() -> c.int --- + @(link_name="fdopendir") _unix_fdopendir :: proc(fd: Handle) -> Dir --- + @(link_name="closedir") _unix_closedir :: proc(dirp: Dir) -> c.int --- + @(link_name="rewinddir") _unix_rewinddir :: proc(dirp: Dir) --- + @(link_name="readdir_r") _unix_readdir_r :: proc(dirp: Dir, entry: ^Dirent, result: ^^Dirent) -> c.int --- + + @(link_name="malloc") _unix_malloc :: proc(size: c.size_t) -> rawptr --- + @(link_name="calloc") _unix_calloc :: proc(num, size: c.size_t) -> rawptr --- + @(link_name="free") _unix_free :: proc(ptr: rawptr) --- + @(link_name="realloc") _unix_realloc :: proc(ptr: rawptr, size: c.size_t) -> rawptr --- + + @(link_name="getenv") _unix_getenv :: proc(cstring) -> cstring --- + @(link_name="realpath") _unix_realpath :: proc(path: cstring, resolved_path: rawptr) -> rawptr --- + + @(link_name="exit") _unix_exit :: proc(status: c.int) -> ! --- + + @(link_name="dlopen") _unix_dlopen :: proc(filename: cstring, flags: c.int) -> rawptr --- + @(link_name="dlsym") _unix_dlsym :: proc(handle: rawptr, symbol: cstring) -> rawptr --- + @(link_name="dlclose") _unix_dlclose :: proc(handle: rawptr) -> c.int --- + @(link_name="dlerror") _unix_dlerror :: proc() -> cstring --- +} + +is_path_separator :: proc(r: rune) -> bool { + return r == '/' +} + +get_last_error :: proc() -> int { + return __errno()^ +} + +fork :: proc() -> (Pid, Errno) { + pid := _unix_fork() + if pid == -1 { + return Pid(-1), Errno(get_last_error()) + } + return Pid(pid), ERROR_NONE +} + +open :: proc(path: string, flags: int = O_RDONLY, mode: int = 0) -> (Handle, Errno) { + cstr := strings.clone_to_cstring(path, context.temp_allocator) + handle := _unix_open(cstr, c.int(flags), c.int(mode)) + if handle == -1 { + return INVALID_HANDLE, Errno(get_last_error()) + } + return handle, ERROR_NONE +} + +close :: proc(fd: Handle) -> Errno { + result := _unix_close(fd) + if result == -1 { + return Errno(get_last_error()) + } + return ERROR_NONE +} + +read :: proc(fd: Handle, data: []byte) -> (int, Errno) { + bytes_read := _unix_read(fd, &data[0], c.size_t(len(data))) + if bytes_read == -1 { + return -1, Errno(get_last_error()) + } + return int(bytes_read), ERROR_NONE +} + +write :: proc(fd: Handle, data: []byte) -> (int, Errno) { + if len(data) == 0 { + return 0, ERROR_NONE + } + bytes_written := _unix_write(fd, &data[0], c.size_t(len(data))) + if bytes_written == -1 { + return -1, Errno(get_last_error()) + } + return int(bytes_written), ERROR_NONE +} + +seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Errno) { + res := _unix_seek(fd, offset, c.int(whence)) + if res == -1 { + return -1, Errno(get_last_error()) + } + return res, ERROR_NONE +} + +file_size :: proc(fd: Handle) -> (i64, Errno) { + s, err := _fstat(fd) + if err != ERROR_NONE { + return -1, err + } + return s.size, ERROR_NONE +} + +rename :: proc(old_path, new_path: string) -> Errno { + old_path_cstr := strings.clone_to_cstring(old_path, context.temp_allocator) + new_path_cstr := strings.clone_to_cstring(new_path, context.temp_allocator) + res := _unix_rename(old_path_cstr, new_path_cstr) + if res == -1 { + return Errno(get_last_error()) + } + return ERROR_NONE +} + +remove :: proc(path: string) -> Errno { + path_cstr := strings.clone_to_cstring(path, context.temp_allocator) + res := _unix_unlink(path_cstr) + if res == -1 { + return Errno(get_last_error()) + } + return ERROR_NONE +} + +make_directory :: proc(path: string, mode: mode_t = 0o775) -> Errno { + path_cstr := strings.clone_to_cstring(path, context.temp_allocator) + res := _unix_mkdir(path_cstr, mode) + if res == -1 { + return Errno(get_last_error()) + } + return ERROR_NONE +} + +remove_directory :: proc(path: string) -> Errno { + path_cstr := strings.clone_to_cstring(path, context.temp_allocator) + res := _unix_rmdir(path_cstr) + if res == -1 { + return Errno(get_last_error()) + } + return ERROR_NONE +} + +is_file_handle :: proc(fd: Handle) -> bool { + s, err := _fstat(fd) + if err != ERROR_NONE { + return false + } + return S_ISREG(s.mode) +} + +is_file_path :: proc(path: string, follow_links: bool = true) -> bool { + s: OS_Stat + err: Errno + if follow_links { + s, err = _stat(path) + } else { + s, err = _lstat(path) + } + if err != ERROR_NONE { + return false + } + return S_ISREG(s.mode) +} + +is_dir_handle :: proc(fd: Handle) -> bool { + s, err := _fstat(fd) + if err != ERROR_NONE { + return false + } + return S_ISDIR(s.mode) +} + +is_dir_path :: proc(path: string, follow_links: bool = true) -> bool { + s: OS_Stat + err: Errno + if follow_links { + s, err = _stat(path) + } else { + s, err = _lstat(path) + } + if err != ERROR_NONE { + return false + } + return S_ISDIR(s.mode) +} + +is_file :: proc {is_file_path, is_file_handle} +is_dir :: proc {is_dir_path, is_dir_handle} + +// NOTE(bill): Uses startup to initialize it + +stdin: Handle = 0 +stdout: Handle = 1 +stderr: Handle = 2 + +/* TODO(zangent): Implement these! +last_write_time :: proc(fd: Handle) -> File_Time {} +last_write_time_by_name :: proc(name: string) -> File_Time {} +*/ +last_write_time :: proc(fd: Handle) -> (File_Time, Errno) { + s, err := _fstat(fd) + if err != ERROR_NONE { + return 0, err + } + modified := s.modified.seconds * 1_000_000_000 + s.modified.nanoseconds + return File_Time(modified), ERROR_NONE +} + +last_write_time_by_name :: proc(name: string) -> (File_Time, Errno) { + s, err := _stat(name) + if err != ERROR_NONE { + return 0, err + } + modified := s.modified.seconds * 1_000_000_000 + s.modified.nanoseconds + return File_Time(modified), ERROR_NONE +} + +@private +_stat :: proc(path: string) -> (OS_Stat, Errno) { + cstr := strings.clone_to_cstring(path, context.temp_allocator) + + // deliberately uninitialized + s: OS_Stat = --- + res := _unix_stat(cstr, &s) + if res == -1 { + return s, Errno(get_last_error()) + } + return s, ERROR_NONE +} + +@private +_lstat :: proc(path: string) -> (OS_Stat, Errno) { + cstr := strings.clone_to_cstring(path, context.temp_allocator) + + // deliberately uninitialized + s: OS_Stat = --- + res := _unix_lstat(cstr, &s) + if res == -1 { + return s, Errno(get_last_error()) + } + return s, ERROR_NONE +} + +@private +_fstat :: proc(fd: Handle) -> (OS_Stat, Errno) { + // deliberately uninitialized + s: OS_Stat = --- + res := _unix_fstat(fd, &s) + if res == -1 { + return s, Errno(get_last_error()) + } + return s, ERROR_NONE +} + +@private +_fdopendir :: proc(fd: Handle) -> (Dir, Errno) { + dirp := _unix_fdopendir(fd) + if dirp == cast(Dir)nil { + return nil, Errno(get_last_error()) + } + return dirp, ERROR_NONE +} + +@private +_closedir :: proc(dirp: Dir) -> Errno { + rc := _unix_closedir(dirp) + if rc != 0 { + return Errno(get_last_error()) + } + return ERROR_NONE +} + +@private +_rewinddir :: proc(dirp: Dir) { + _unix_rewinddir(dirp) +} + +@private +_readdir :: proc(dirp: Dir) -> (entry: Dirent, err: Errno, end_of_stream: bool) { + result: ^Dirent + rc := _unix_readdir_r(dirp, &entry, &result) + + if rc != 0 { + err = Errno(get_last_error()) + return + } + err = ERROR_NONE + + if result == nil { + end_of_stream = true + return + } + + return +} + +@private +_readlink :: proc(path: string) -> (string, Errno) { + path_cstr := strings.clone_to_cstring(path, context.temp_allocator) + + bufsz : uint = MAX_PATH + buf := make([]byte, MAX_PATH) + for { + rc := _unix_readlink(path_cstr, &(buf[0]), bufsz) + if rc == -1 { + delete(buf) + return "", Errno(get_last_error()) + } else if rc == int(bufsz) { + bufsz += MAX_PATH + delete(buf) + buf = make([]byte, bufsz) + } else { + return strings.string_from_ptr(&buf[0], rc), ERROR_NONE + } + } + unreachable() +} + +// XXX OpenBSD +absolute_path_from_handle :: proc(fd: Handle) -> (string, Errno) { + return "", Errno(ENOSYS) +} + +absolute_path_from_relative :: proc(rel: string) -> (path: string, err: Errno) { + rel := rel + if rel == "" { + rel = "." + } + + rel_cstr := strings.clone_to_cstring(rel, context.temp_allocator) + + path_ptr := _unix_realpath(rel_cstr, nil) + if path_ptr == nil { + return "", Errno(get_last_error()) + } + defer _unix_free(path_ptr) + + path_cstr := transmute(cstring)path_ptr + path = strings.clone( string(path_cstr) ) + + return path, ERROR_NONE +} + +access :: proc(path: string, mask: int) -> (bool, Errno) { + cstr := strings.clone_to_cstring(path, context.temp_allocator) + res := _unix_access(cstr, c.int(mask)) + if res == -1 { + return false, Errno(get_last_error()) + } + return true, ERROR_NONE +} + +heap_alloc :: proc(size: int) -> rawptr { + assert(size >= 0) + return _unix_calloc(1, c.size_t(size)) +} + +heap_resize :: proc(ptr: rawptr, new_size: int) -> rawptr { + // NOTE: _unix_realloc doesn't guarantee new memory will be zeroed on + // POSIX platforms. Ensure your caller takes this into account. + return _unix_realloc(ptr, c.size_t(new_size)) +} + +heap_free :: proc(ptr: rawptr) { + _unix_free(ptr) +} + +getenv :: proc(name: string) -> (string, bool) { + path_str := strings.clone_to_cstring(name, context.temp_allocator) + cstr := _unix_getenv(path_str) + if cstr == nil { + return "", false + } + return string(cstr), true +} + +get_current_directory :: proc() -> string { + buf := make([dynamic]u8, MAX_PATH) + for { + cwd := _unix_getcwd(cstring(raw_data(buf)), c.size_t(len(buf))) + if cwd != nil { + return string(cwd) + } + if Errno(get_last_error()) != ERANGE { + return "" + } + resize(&buf, len(buf) + MAX_PATH) + } + unreachable() +} + +set_current_directory :: proc(path: string) -> (err: Errno) { + cstr := strings.clone_to_cstring(path, context.temp_allocator) + res := _unix_chdir(cstr) + if res == -1 { + return Errno(get_last_error()) + } + return ERROR_NONE +} + +exit :: proc "contextless" (code: int) -> ! { + _unix_exit(c.int(code)) +} + +current_thread_id :: proc "contextless" () -> int { + return _unix_getthrid() +} + +dlopen :: proc(filename: string, flags: int) -> rawptr { + cstr := strings.clone_to_cstring(filename, context.temp_allocator) + handle := _unix_dlopen(cstr, c.int(flags)) + return handle +} +dlsym :: proc(handle: rawptr, symbol: string) -> rawptr { + assert(handle != nil) + cstr := strings.clone_to_cstring(symbol, context.temp_allocator) + proc_handle := _unix_dlsym(handle, cstr) + return proc_handle +} +dlclose :: proc(handle: rawptr) -> bool { + assert(handle != nil) + return _unix_dlclose(handle) == 0 +} +dlerror :: proc() -> string { + return string(_unix_dlerror()) +} + +get_page_size :: proc() -> int { + // NOTE(tetra): The page size never changes, so why do anything complicated + // if we don't have to. + @static page_size := -1 + if page_size != -1 { + return page_size + } + + page_size = int(_unix_getpagesize()) + return page_size +} + + +_alloc_command_line_arguments :: proc() -> []string { + res := make([]string, len(runtime.args__)) + for arg, i in runtime.args__ { + res[i] = string(arg) + } + return res +} diff --git a/core/os/stat_unix.odin b/core/os/stat_unix.odin index 08c6f53c4..2aa9fc283 100644 --- a/core/os/stat_unix.odin +++ b/core/os/stat_unix.odin @@ -1,4 +1,4 @@ -//+build linux, darwin, freebsd +//+build linux, darwin, freebsd, openbsd package os import "core:time" diff --git a/core/path/filepath/path_unix.odin b/core/path/filepath/path_unix.odin index 3e49c4710..d0eaa3635 100644 --- a/core/path/filepath/path_unix.odin +++ b/core/path/filepath/path_unix.odin @@ -1,4 +1,4 @@ -//+build linux, darwin, freebsd +//+build linux, darwin, freebsd, openbsd package filepath when ODIN_OS == .Darwin { @@ -59,6 +59,11 @@ when ODIN_OS == .Darwin { foreign libc { @(link_name="__error") __error :: proc() -> ^i32 --- } +} else when ODIN_OS == .OpenBSD { + @(private) + foreign libc { + @(link_name="__errno") __error :: proc() -> ^i32 --- + } } else { @(private) foreign libc { diff --git a/core/runtime/entry_unix.odin b/core/runtime/entry_unix.odin index dd1e06625..1a3def200 100644 --- a/core/runtime/entry_unix.odin +++ b/core/runtime/entry_unix.odin @@ -1,5 +1,5 @@ //+private -//+build linux, darwin, freebsd +//+build linux, darwin, freebsd, openbsd package runtime import "core:intrinsics" diff --git a/core/sync/channel_unix.odin b/core/sync/channel_unix.odin index d6bac2d71..47aa46004 100644 --- a/core/sync/channel_unix.odin +++ b/core/sync/channel_unix.odin @@ -1,4 +1,4 @@ -// +build linux, darwin, freebsd +// +build linux, darwin, freebsd, openbsd package sync import "core:time" diff --git a/core/sync/sync2/futex_openbsd.odin b/core/sync/sync2/futex_openbsd.odin new file mode 100644 index 000000000..dbc80747b --- /dev/null +++ b/core/sync/sync2/futex_openbsd.odin @@ -0,0 +1,78 @@ +//+private +//+build openbsd +package sync2 + +import "core:c" +import "core:os" +import "core:time" + +FUTEX_WAIT :: 1 +FUTEX_WAKE :: 2 + +FUTEX_PRIVATE_FLAG :: 128 + +FUTEX_WAIT_PRIVATE :: (FUTEX_WAIT | FUTEX_PRIVATE_FLAG) +FUTEX_WAKE_PRIVATE :: (FUTEX_WAKE | FUTEX_PRIVATE_FLAG) + +foreign import libc "system:c" + +foreign libc { + @(link_name="futex") + _unix_futex :: proc "c" (f: ^Futex, op: c.int, val: u32, timeout: rawptr) -> c.int --- +} + +_futex_wait :: proc(f: ^Futex, expected: u32) -> bool { + res := _unix_futex(f, FUTEX_WAIT_PRIVATE, expected, nil) + + if res != -1 { + return true + } + + if os.Errno(os.get_last_error()) == os.ETIMEDOUT { + return false + } + + panic("futex_wait failure") +} + +_futex_wait_with_timeout :: proc(f: ^Futex, expected: u32, duration: time.Duration) -> bool { + if duration <= 0 { + return false + } + + timespec_t :: struct { + tv_sec: c.long, + tv_nsec: c.long, + } + + res := _unix_futex(f, FUTEX_WAIT_PRIVATE, expected, ×pec_t{ + tv_sec = (c.long)(duration/1e9), + tv_nsec = (c.long)(duration%1e9), + }) + + if res != -1 { + return true + } + + if os.Errno(os.get_last_error()) == os.ETIMEDOUT { + return false + } + + panic("futex_wait_with_timeout failure") +} + +_futex_signal :: proc(f: ^Futex) { + res := _unix_futex(f, FUTEX_WAKE_PRIVATE, 1, nil) + + if res == -1 { + panic("futex_wake_single failure") + } +} + +_futex_broadcast :: proc(f: ^Futex) { + res := _unix_futex(f, FUTEX_WAKE_PRIVATE, u32(max(i32)), nil) + + if res == -1 { + panic("_futex_wake_all failure") + } +} diff --git a/core/sync/sync2/primitives_openbsd.odin b/core/sync/sync2/primitives_openbsd.odin new file mode 100644 index 000000000..ef122b02e --- /dev/null +++ b/core/sync/sync2/primitives_openbsd.odin @@ -0,0 +1,9 @@ +//+build openbsd +//+private +package sync2 + +import "core:os" + +_current_thread_id :: proc "contextless" () -> int { + return os.current_thread_id() +} diff --git a/core/sync/sync2/primitives_pthreads.odin b/core/sync/sync2/primitives_pthreads.odin index 8d2c3986d..28053f9cc 100644 --- a/core/sync/sync2/primitives_pthreads.odin +++ b/core/sync/sync2/primitives_pthreads.odin @@ -1,4 +1,4 @@ -//+build linux, freebsd +//+build linux, freebsd, openbsd //+private package sync2 diff --git a/core/sync/sync_openbsd.odin b/core/sync/sync_openbsd.odin new file mode 100644 index 000000000..926655f5b --- /dev/null +++ b/core/sync/sync_openbsd.odin @@ -0,0 +1,36 @@ +package sync + +import "core:sys/unix" +import "core:os" + +current_thread_id :: proc "contextless" () -> int { + return os.current_thread_id() +} + +// The Darwin docs say it best: +// A semaphore is much like a lock, except that a finite number of threads can hold it simultaneously. +// Semaphores can be thought of as being much like piles of tokens; multiple threads can take these tokens, +// but when there are none left, a thread must wait until another thread returns one. +Semaphore :: struct #align 16 { + handle: unix.sem_t, +} + +semaphore_init :: proc(s: ^Semaphore, initial_count := 0) { + assert(unix.sem_init(&s.handle, 0, u32(initial_count)) == 0) +} + +semaphore_destroy :: proc(s: ^Semaphore) { + assert(unix.sem_destroy(&s.handle) == 0) + s.handle = {} +} + +semaphore_post :: proc(s: ^Semaphore, count := 1) { + // NOTE: SPEED: If there's one syscall to do this, we should use it instead of the loop. + for in 0.. ^sem_t --- + + sem_init :: proc(sem: ^sem_t, pshared: c.int, initial_value: c.uint) -> c.int --- + sem_destroy :: proc(sem: ^sem_t) -> c.int --- + sem_post :: proc(sem: ^sem_t) -> c.int --- + sem_wait :: proc(sem: ^sem_t) -> c.int --- + sem_trywait :: proc(sem: ^sem_t) -> c.int --- + //sem_timedwait :: proc(sem: ^sem_t, timeout: time.TimeSpec) -> c.int --- + + // NOTE: unclear whether pthread_yield is well-supported on Linux systems, + // see https://linux.die.net/man/3/pthread_yield + pthread_yield :: proc() --- +} diff --git a/core/sys/unix/pthread_unix.odin b/core/sys/unix/pthread_unix.odin index ccd8f7844..62e3701ab 100644 --- a/core/sys/unix/pthread_unix.odin +++ b/core/sys/unix/pthread_unix.odin @@ -1,4 +1,4 @@ -//+build linux, darwin, freebsd +//+build linux, darwin, freebsd, openbsd package unix foreign import "system:pthread" diff --git a/core/thread/thread_unix.odin b/core/thread/thread_unix.odin index 6cb91df86..b6679bbc2 100644 --- a/core/thread/thread_unix.odin +++ b/core/thread/thread_unix.odin @@ -1,4 +1,4 @@ -// +build linux, darwin, freebsd +// +build linux, darwin, freebsd, openbsd // +private package thread diff --git a/core/time/time_unix.odin b/core/time/time_unix.odin index 9c5c5cc35..37fc1fd3e 100644 --- a/core/time/time_unix.odin +++ b/core/time/time_unix.odin @@ -1,4 +1,4 @@ -//+build linux, darwin, freebsd +//+build linux, darwin, freebsd, openbsd package time IS_SUPPORTED :: true // NOTE: Times on Darwin are UTC. @@ -22,16 +22,28 @@ TimeSpec :: struct { tv_nsec : i64, /* nanoseconds */ } -CLOCK_REALTIME :: 0 // NOTE(tetra): May jump in time, when user changes the system time. -CLOCK_MONOTONIC :: 1 // NOTE(tetra): May stand still while system is asleep. -CLOCK_PROCESS_CPUTIME_ID :: 2 -CLOCK_THREAD_CPUTIME_ID :: 3 -CLOCK_MONOTONIC_RAW :: 4 // NOTE(tetra): "RAW" means: Not adjusted by NTP. -CLOCK_REALTIME_COARSE :: 5 // NOTE(tetra): "COARSE" clocks are apparently much faster, but not "fine-grained." -CLOCK_MONOTONIC_COARSE :: 6 -CLOCK_BOOTTIME :: 7 // NOTE(tetra): Same as MONOTONIC, except also including time system was asleep. -CLOCK_REALTIME_ALARM :: 8 -CLOCK_BOOTTIME_ALARM :: 9 +when ODIN_OS == .OpenBSD { + CLOCK_REALTIME :: 0 + CLOCK_PROCESS_CPUTIME_ID :: 2 + CLOCK_MONOTONIC :: 3 + CLOCK_THREAD_CPUTIME_ID :: 4 + CLOCK_UPTIME :: 5 + CLOCK_BOOTTIME :: 6 + + // CLOCK_MONOTONIC_RAW doesn't exist, use CLOCK_MONOTONIC + CLOCK_MONOTONIC_RAW :: CLOCK_MONOTONIC +} else { + CLOCK_REALTIME :: 0 // NOTE(tetra): May jump in time, when user changes the system time. + CLOCK_MONOTONIC :: 1 // NOTE(tetra): May stand still while system is asleep. + CLOCK_PROCESS_CPUTIME_ID :: 2 + CLOCK_THREAD_CPUTIME_ID :: 3 + CLOCK_MONOTONIC_RAW :: 4 // NOTE(tetra): "RAW" means: Not adjusted by NTP. + CLOCK_REALTIME_COARSE :: 5 // NOTE(tetra): "COARSE" clocks are apparently much faster, but not "fine-grained." + CLOCK_MONOTONIC_COARSE :: 6 + CLOCK_BOOTTIME :: 7 // NOTE(tetra): Same as MONOTONIC, except also including time system was asleep. + CLOCK_REALTIME_ALARM :: 8 + CLOCK_BOOTTIME_ALARM :: 9 +} // TODO(tetra, 2019-11-05): The original implementation of this package for Darwin used this constants. // I do not know if Darwin programmers are used to the existance of these constants or not, so diff --git a/src/bug_report.cpp b/src/bug_report.cpp index 4dd251f24..7f6b668e8 100644 --- a/src/bug_report.cpp +++ b/src/bug_report.cpp @@ -17,6 +17,10 @@ #include #endif +#if defined(GB_SYSTEM_OPENBSD) + #include +#endif + /* NOTE(Jeroen): This prints the Windows product edition only, to be called from `print_platform_details`. */ @@ -643,6 +647,14 @@ void print_bug_report_help() { } else { gb_printf("macOS: Unknown\n"); } + #elif defined(GB_SYSTEM_OPENBSD) + struct utsname un; + + if (uname(&un) != -1) { + gb_printf("%s %s %s %s\n", un.sysname, un.release, un.version, un.machine); + } else { + gb_printf("OpenBSD: Unknown\n"); + } #else gb_printf("Unknown\n"); @@ -657,4 +669,4 @@ void print_bug_report_help() { And RAM info. */ report_ram_info(); -} \ No newline at end of file +} diff --git a/src/build_settings.cpp b/src/build_settings.cpp index 610e4f847..72a4b35cc 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -16,6 +16,7 @@ enum TargetOsKind { TargetOs_linux, TargetOs_essence, TargetOs_freebsd, + TargetOs_openbsd, TargetOs_wasi, TargetOs_js, @@ -53,6 +54,7 @@ String target_os_names[TargetOs_COUNT] = { str_lit("linux"), str_lit("essence"), str_lit("freebsd"), + str_lit("openbsd"), str_lit("wasi"), str_lit("js"), @@ -354,6 +356,15 @@ gb_global TargetMetrics target_freebsd_amd64 = { str_lit("e-m:w-i64:64-f80:128-n8:16:32:64-S128"), }; +gb_global TargetMetrics target_openbsd_amd64 = { + TargetOs_openbsd, + TargetArch_amd64, + 8, + 16, + str_lit("x86_64-unknown-openbsd-elf"), + str_lit("e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"), +}; + gb_global TargetMetrics target_essence_amd64 = { TargetOs_essence, TargetArch_amd64, @@ -417,6 +428,7 @@ gb_global NamedTargetMetrics named_targets[] = { { str_lit("windows_amd64"), &target_windows_amd64 }, { str_lit("freebsd_386"), &target_freebsd_386 }, { str_lit("freebsd_amd64"), &target_freebsd_amd64 }, + { str_lit("openbsd_amd64"), &target_openbsd_amd64 }, { str_lit("freestanding_wasm32"), &target_freestanding_wasm32 }, { str_lit("wasi_wasm32"), &target_wasi_wasm32 }, { str_lit("js_wasm32"), &target_js_wasm32 }, @@ -723,6 +735,7 @@ String internal_odin_root_dir(void) { #elif defined(GB_SYSTEM_DRAGONFLYBSD) len = readlink("/proc/curproc/file", &path_buf[0], path_buf.count); #else + // XXX OpenBSD len = readlink("/proc/self/exe", &path_buf[0], path_buf.count); #endif if(len == 0) { @@ -922,6 +935,8 @@ void init_build_context(TargetMetrics *cross_target) { #endif #elif defined(GB_SYSTEM_FREEBSD) metrics = &target_freebsd_amd64; + #elif defined(GB_SYSTEM_OPENBSD) + metrics = &target_openbsd_amd64; #elif defined(GB_CPU_ARM) metrics = &target_linux_arm64; #else @@ -980,6 +995,9 @@ void init_build_context(TargetMetrics *cross_target) { case TargetOs_freebsd: bc->link_flags = str_lit("-arch x86-64 "); break; + case TargetOs_openbsd: + bc->link_flags = str_lit("-arch x86-64 "); + break; } } else if (bc->metrics.arch == TargetArch_i386) { switch (bc->metrics.os) { diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp index eb9d7f293..69cc40de8 100644 --- a/src/check_builtin.cpp +++ b/src/check_builtin.cpp @@ -3506,6 +3506,7 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 case TargetOs_linux: case TargetOs_essence: case TargetOs_freebsd: + case TargetOs_openbsd: switch (build_context.metrics.arch) { case TargetArch_i386: case TargetArch_amd64: diff --git a/src/checker.cpp b/src/checker.cpp index f440b7c9a..5a7ece263 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -906,6 +906,7 @@ void init_universal(void) { {"Linux", TargetOs_linux}, {"Essence", TargetOs_essence}, {"FreeBSD", TargetOs_freebsd}, + {"OpenBSD", TargetOs_openbsd}, {"WASI", TargetOs_wasi}, {"JS", TargetOs_js}, {"Freestanding", TargetOs_freestanding}, diff --git a/src/common.cpp b/src/common.cpp index d3ee95b76..aaacda04b 100644 --- a/src/common.cpp +++ b/src/common.cpp @@ -848,7 +848,7 @@ ReadDirectoryError read_directory(String path, Array *fi) { return ReadDirectory_None; } -#elif defined(GB_SYSTEM_LINUX) || defined(GB_SYSTEM_OSX) || defined(GB_SYSTEM_FREEBSD) +#elif defined(GB_SYSTEM_LINUX) || defined(GB_SYSTEM_OSX) || defined(GB_SYSTEM_FREEBSD) || defined(GB_SYSTEM_OPENBSD) #include diff --git a/src/gb/gb.h b/src/gb/gb.h index a9d6378c9..293e5063a 100644 --- a/src/gb/gb.h +++ b/src/gb/gb.h @@ -79,6 +79,10 @@ extern "C" { #ifndef GB_SYSTEM_FREEBSD #define GB_SYSTEM_FREEBSD 1 #endif + #elif defined(__OpenBSD__) + #ifndef GB_SYSTEM_OPENBSD + #define GB_SYSTEM_OPENBSD 1 + #endif #else #error This UNIX operating system is not supported #endif @@ -199,7 +203,7 @@ extern "C" { #endif #include // NOTE(bill): malloc on linux #include - #if !defined(GB_SYSTEM_OSX) && !defined(__FreeBSD__) + #if !defined(GB_SYSTEM_OSX) && !defined(__FreeBSD__) && !defined(__OpenBSD__) #include #endif #include @@ -235,6 +239,15 @@ extern "C" { #define sendfile(out, in, offset, count) sendfile(out, in, offset, count, NULL, NULL, 0) #endif +#if defined(GB_SYSTEM_OPENBSD) + #include + #include + #define lseek64 lseek + + // XXX OpenBSD + #define sendfile(out, in, offset, count) (-1) +#endif + #if defined(GB_SYSTEM_UNIX) #include #endif @@ -783,6 +796,13 @@ typedef struct gbAffinity { isize thread_count; isize threads_per_core; } gbAffinity; +#elif defined(GB_SYSTEM_OPENBSD) +typedef struct gbAffinity { + b32 is_accurate; + isize core_count; + isize thread_count; + isize threads_per_core; +} gbAffinity; #else #error TODO(bill): Unknown system #endif @@ -3678,6 +3698,30 @@ b32 gb_affinity_set(gbAffinity *a, isize core, isize thread_index) { return true; } +isize gb_affinity_thread_count_for_core(gbAffinity *a, isize core) { + GB_ASSERT(0 <= core && core < a->core_count); + return a->threads_per_core; +} + +#elif defined(GB_SYSTEM_OPENBSD) +#include + +void gb_affinity_init(gbAffinity *a) { + a->core_count = sysconf(_SC_NPROCESSORS_ONLN); + a->threads_per_core = 1; + a->is_accurate = a->core_count > 0; + a->core_count = a->is_accurate ? a->core_count : 1; + a->thread_count = a->core_count; +} + +void gb_affinity_destroy(gbAffinity *a) { + gb_unused(a); +} + +b32 gb_affinity_set(gbAffinity *a, isize core, isize thread_index) { + return true; +} + isize gb_affinity_thread_count_for_core(gbAffinity *a, isize core) { GB_ASSERT(0 <= core && core < a->core_count); return a->threads_per_core; diff --git a/src/threading.cpp b/src/threading.cpp index 50d0dfed1..63e3415b2 100644 --- a/src/threading.cpp +++ b/src/threading.cpp @@ -486,7 +486,7 @@ void thread_set_name(Thread *t, char const *name) { #elif defined(GB_SYSTEM_OSX) // TODO(bill): Test if this works pthread_setname_np(name); -#elif defined(GB_SYSTEM_FREEBSD) +#elif defined(GB_SYSTEM_FREEBSD) || defined(GB_SYSTEM_OPENBSD) pthread_set_name_np(t->posix_handle, name); #else // TODO(bill): Test if this works -- cgit v1.2.3 From 278e239973ab1e680bd36f90c069ec798930e54b Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 28 Feb 2022 13:39:27 +0000 Subject: Commit rest of code for `-disallow-rtti` --- src/build_settings.cpp | 3 ++- src/check_builtin.cpp | 18 +++++++++++++----- src/check_decl.cpp | 2 ++ src/check_expr.cpp | 2 ++ src/check_type.cpp | 2 ++ src/checker.cpp | 25 ++++++++++++++++++++++++- src/llvm_backend.cpp | 6 +++++- src/llvm_backend_expr.cpp | 17 ++++++++++++++--- src/llvm_backend_type.cpp | 2 ++ src/llvm_backend_utility.cpp | 30 ++++++++++++++++++++++-------- src/main.cpp | 7 +++++++ 11 files changed, 95 insertions(+), 19 deletions(-) (limited to 'src/checker.cpp') diff --git a/src/build_settings.cpp b/src/build_settings.cpp index d6cdd7006..b2d6c4f43 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -277,6 +277,8 @@ struct BuildContext { bool copy_file_contents; + bool disallow_rtti; + RelocMode reloc_mode; bool disable_red_zone; @@ -946,7 +948,6 @@ void init_build_context(TargetMetrics *cross_target) { } } - bc->copy_file_contents = true; TargetMetrics *metrics = nullptr; diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp index eb9d7f293..5561da01b 100644 --- a/src/check_builtin.cpp +++ b/src/check_builtin.cpp @@ -1241,6 +1241,10 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 if (c->scope->flags&ScopeFlag_Global) { compiler_error("'type_info_of' Cannot be declared within the runtime package due to how the internals of the compiler works"); } + if (build_context.disallow_rtti) { + error(call, "'%.*s' has been disallowed", LIT(builtin_name)); + return false; + } // NOTE(bill): The type information may not be setup yet init_core_type_info(c->checker); @@ -1253,9 +1257,9 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 Type *t = o.type; if (t == nullptr || t == t_invalid || is_type_asm_proc(o.type) || is_type_polymorphic(t)) { if (is_type_polymorphic(t)) { - error(ce->args[0], "Invalid argument for 'type_info_of', unspecialized polymorphic type"); + error(ce->args[0], "Invalid argument for '%.*s', unspecialized polymorphic type", LIT(builtin_name)); } else { - error(ce->args[0], "Invalid argument for 'type_info_of'"); + error(ce->args[0], "Invalid argument for '%.*s'", LIT(builtin_name)); } return false; } @@ -1266,7 +1270,7 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 if (is_operand_value(o) && is_type_typeid(t)) { add_package_dependency(c, "runtime", "__type_info_of"); } else if (o.mode != Addressing_Type) { - error(expr, "Expected a type or typeid for 'type_info_of'"); + error(expr, "Expected a type or typeid for '%.*s'", LIT(builtin_name)); return false; } @@ -1280,6 +1284,10 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 if (c->scope->flags&ScopeFlag_Global) { compiler_error("'typeid_of' Cannot be declared within the runtime package due to how the internals of the compiler works"); } + if (build_context.disallow_rtti) { + error(call, "'%.*s' has been disallowed", LIT(builtin_name)); + return false; + } // NOTE(bill): The type information may not be setup yet init_core_type_info(c->checker); @@ -1291,7 +1299,7 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 } Type *t = o.type; if (t == nullptr || t == t_invalid || is_type_asm_proc(o.type) || is_type_polymorphic(operand->type)) { - error(ce->args[0], "Invalid argument for 'typeid_of'"); + error(ce->args[0], "Invalid argument for '%.*s'", LIT(builtin_name)); return false; } t = default_type(t); @@ -1299,7 +1307,7 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 add_type_info_type(c, t); if (o.mode != Addressing_Type) { - error(expr, "Expected a type for 'typeid_of'"); + error(expr, "Expected a type for '%.*s'", LIT(builtin_name)); return false; } diff --git a/src/check_decl.cpp b/src/check_decl.cpp index 3fdd944f9..b3b1e4474 100644 --- a/src/check_decl.cpp +++ b/src/check_decl.cpp @@ -1205,6 +1205,8 @@ void check_global_variable_decl(CheckerContext *ctx, Entity *&e, Ast *type_expr, Operand o = {}; check_expr_with_type_hint(ctx, &o, init_expr, e->type); check_init_variable(ctx, e, &o, str_lit("variable declaration")); + + check_rtti_type_disallowed(e->token, e->type, "A variable declaration is using a type, %s, which has been disallowed"); } void check_proc_group_decl(CheckerContext *ctx, Entity *&pg_entity, DeclInfo *d) { diff --git a/src/check_expr.cpp b/src/check_expr.cpp index e07dc3d60..f1bcb4cd9 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -9352,6 +9352,8 @@ ExprKind check_expr_base(CheckerContext *c, Operand *o, Ast *node, Type *type_hi if (o->type != nullptr && is_type_untyped(o->type)) { add_untyped(c, node, o->mode, o->type, o->value); } + check_rtti_type_disallowed(node, o->type, "An expression is using a type, %s, which has been disallowed"); + add_type_and_value(c->info, node, o->mode, o->type, o->value); return kind; } diff --git a/src/check_type.cpp b/src/check_type.cpp index c2324ee5a..ff2c3d6a6 100644 --- a/src/check_type.cpp +++ b/src/check_type.cpp @@ -3031,5 +3031,7 @@ Type *check_type_expr(CheckerContext *ctx, Ast *e, Type *named_type) { } set_base_type(named_type, type); + check_rtti_type_disallowed(e, type, "Use of a type, %s, which has been disallowed"); + return type; } diff --git a/src/checker.cpp b/src/checker.cpp index fe1d362fa..e6445d752 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -29,6 +29,23 @@ bool is_operand_undef(Operand o) { return o.mode == Addressing_Value && o.type == t_untyped_undef; } +bool check_rtti_type_disallowed(Token const &token, Type *type, char const *format) { + if (build_context.disallow_rtti && type) { + if (is_type_any(type)) { + gbString t = type_to_string(type); + error(token, format, t); + gb_string_free(t); + return true; + } + } + return false; +} + +bool check_rtti_type_disallowed(Ast *expr, Type *type, char const *format) { + GB_ASSERT(expr != nullptr); + return check_rtti_type_disallowed(ast_token(expr), type, format); +} + void scope_reset(Scope *scope) { if (scope == nullptr) return; @@ -875,7 +892,8 @@ void init_universal(void) { // Types for (isize i = 0; i < gb_count_of(basic_types); i++) { - add_global_type_entity(basic_types[i].Basic.name, &basic_types[i]); + String const &name = basic_types[i].Basic.name; + add_global_type_entity(name, &basic_types[i]); } add_global_type_entity(str_lit("byte"), &basic_types[Basic_u8]); @@ -977,6 +995,7 @@ void init_universal(void) { add_global_bool_constant("ODIN_TEST", bc->command_kind == Command_test); add_global_bool_constant("ODIN_NO_ENTRY_POINT", bc->no_entry_point); add_global_bool_constant("ODIN_FOREIGN_ERROR_PROCEDURES", bc->ODIN_FOREIGN_ERROR_PROCEDURES); + add_global_bool_constant("ODIN_DISALLOW_RTTI", bc->disallow_rtti); // Builtin Procedures @@ -1669,6 +1688,10 @@ void add_implicit_entity(CheckerContext *c, Ast *clause, Entity *e) { void add_type_info_type(CheckerContext *c, Type *t) { void add_type_info_type_internal(CheckerContext *c, Type *t); + if (build_context.disallow_rtti) { + return; + } + mutex_lock(&c->info->type_info_mutex); add_type_info_type_internal(c, t); mutex_unlock(&c->info->type_info_mutex); diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index 6ca256c4b..04c3200f8 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -1285,7 +1285,11 @@ void lb_generate_code(lbGenerator *gen) { // x86-64-v3: (close to Haswell) AVX, AVX2, BMI1, BMI2, F16C, FMA, LZCNT, MOVBE, XSAVE // x86-64-v4: AVX512F, AVX512BW, AVX512CD, AVX512DQ, AVX512VL if (ODIN_LLVM_MINIMUM_VERSION_12) { - llvm_cpu = "x86-64-v2"; + if (build_context.metrics.os == TargetOs_freestanding) { + llvm_cpu = "x86-64"; + } else { + llvm_cpu = "x86-64-v2"; + } } } diff --git a/src/llvm_backend_expr.cpp b/src/llvm_backend_expr.cpp index 844deb43c..18b66572d 100644 --- a/src/llvm_backend_expr.cpp +++ b/src/llvm_backend_expr.cpp @@ -2809,16 +2809,25 @@ lbValue lb_build_unary_and(lbProcedure *p, Ast *expr) { src_tag = lb_emit_load(p, lb_emit_union_tag_ptr(p, v)); dst_tag = lb_const_union_tag(p->module, src_type, dst_type); } + + + isize arg_count = 6; + if (build_context.disallow_rtti) { + arg_count = 4; + } + lbValue ok = lb_emit_comp(p, Token_CmpEq, src_tag, dst_tag); - auto args = array_make(permanent_allocator(), 6); + auto args = array_make(permanent_allocator(), arg_count); args[0] = ok; args[1] = lb_find_or_add_entity_string(p->module, get_file_path_string(pos.file_id)); args[2] = lb_const_int(p->module, t_i32, pos.line); args[3] = lb_const_int(p->module, t_i32, pos.column); - args[4] = lb_typeid(p->module, src_type); - args[5] = lb_typeid(p->module, dst_type); + if (!build_context.disallow_rtti) { + args[4] = lb_typeid(p->module, src_type); + args[5] = lb_typeid(p->module, dst_type); + } lb_emit_runtime_call(p, "type_assertion_check", args); } @@ -2831,6 +2840,8 @@ lbValue lb_build_unary_and(lbProcedure *p, Ast *expr) { } lbValue data_ptr = lb_emit_struct_ev(p, v, 0); if ((p->state_flags & StateFlag_no_type_assert) == 0) { + GB_ASSERT(!build_context.disallow_rtti); + lbValue any_id = lb_emit_struct_ev(p, v, 1); lbValue id = lb_typeid(p->module, type); diff --git a/src/llvm_backend_type.cpp b/src/llvm_backend_type.cpp index 1d6297164..1aac75f9c 100644 --- a/src/llvm_backend_type.cpp +++ b/src/llvm_backend_type.cpp @@ -14,6 +14,8 @@ isize lb_type_info_index(CheckerInfo *info, Type *type, bool err_on_not_found=tr } lbValue lb_typeid(lbModule *m, Type *type) { + GB_ASSERT(!build_context.disallow_rtti); + type = default_type(type); u64 id = cast(u64)lb_type_info_index(m->info, type); diff --git a/src/llvm_backend_utility.cpp b/src/llvm_backend_utility.cpp index 98b7e07f0..fb52a9bd6 100644 --- a/src/llvm_backend_utility.cpp +++ b/src/llvm_backend_utility.cpp @@ -676,17 +676,24 @@ lbValue lb_emit_union_cast(lbProcedure *p, lbValue value, Type *type, TokenPos p // NOTE(bill): Panic on invalid conversion Type *dst_type = tuple->Tuple.variables[0]->type; + isize arg_count = 7; + if (build_context.disallow_rtti) { + arg_count = 4; + } + lbValue ok = lb_emit_load(p, lb_emit_struct_ep(p, v.addr, 1)); - auto args = array_make(permanent_allocator(), 7); + auto args = array_make(permanent_allocator(), arg_count); args[0] = ok; args[1] = lb_const_string(m, get_file_path_string(pos.file_id)); args[2] = lb_const_int(m, t_i32, pos.line); args[3] = lb_const_int(m, t_i32, pos.column); - args[4] = lb_typeid(m, src_type); - args[5] = lb_typeid(m, dst_type); - args[6] = lb_emit_conv(p, value_, t_rawptr); + if (!build_context.disallow_rtti) { + args[4] = lb_typeid(m, src_type); + args[5] = lb_typeid(m, dst_type); + args[6] = lb_emit_conv(p, value_, t_rawptr); + } lb_emit_runtime_call(p, "type_assertion_check2", args); return lb_emit_load(p, lb_emit_struct_ep(p, v.addr, 0)); @@ -744,16 +751,23 @@ lbAddr lb_emit_any_cast_addr(lbProcedure *p, lbValue value, Type *type, TokenPos if (!is_tuple) { // NOTE(bill): Panic on invalid conversion lbValue ok = lb_emit_load(p, lb_emit_struct_ep(p, v.addr, 1)); - auto args = array_make(permanent_allocator(), 7); + + isize arg_count = 7; + if (build_context.disallow_rtti) { + arg_count = 4; + } + auto args = array_make(permanent_allocator(), arg_count); args[0] = ok; args[1] = lb_const_string(m, get_file_path_string(pos.file_id)); args[2] = lb_const_int(m, t_i32, pos.line); args[3] = lb_const_int(m, t_i32, pos.column); - args[4] = any_typeid; - args[5] = dst_typeid; - args[6] = lb_emit_struct_ev(p, value, 0);; + if (!build_context.disallow_rtti) { + args[4] = any_typeid; + args[5] = dst_typeid; + args[6] = lb_emit_struct_ev(p, value, 0); + } lb_emit_runtime_call(p, "type_assertion_check2", args); return lb_addr(lb_emit_struct_ep(p, v.addr, 0)); diff --git a/src/main.cpp b/src/main.cpp index 8f4155d39..d2263f5a7 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -638,6 +638,7 @@ enum BuildFlagKind { BuildFlag_StrictStyle, BuildFlag_StrictStyleInitOnly, BuildFlag_ForeignErrorProcedures, + BuildFlag_DisallowRTTI, BuildFlag_Compact, BuildFlag_GlobalDefinitions, @@ -796,6 +797,9 @@ bool parse_build_flags(Array args) { add_flag(&build_flags, BuildFlag_StrictStyleInitOnly, str_lit("strict-style-init-only"), BuildFlagParam_None, Command__does_check); add_flag(&build_flags, BuildFlag_ForeignErrorProcedures, str_lit("foreign-error-procedures"), BuildFlagParam_None, Command__does_check); + add_flag(&build_flags, BuildFlag_DisallowRTTI, str_lit("disallow-rtti"), BuildFlagParam_None, Command__does_check); + + add_flag(&build_flags, BuildFlag_Compact, str_lit("compact"), BuildFlagParam_None, Command_query); add_flag(&build_flags, BuildFlag_GlobalDefinitions, str_lit("global-definitions"), BuildFlagParam_None, Command_query); add_flag(&build_flags, BuildFlag_GoToDefinitions, str_lit("go-to-definitions"), BuildFlagParam_None, Command_query); @@ -1390,6 +1394,9 @@ bool parse_build_flags(Array args) { case BuildFlag_DisallowDo: build_context.disallow_do = true; break; + case BuildFlag_DisallowRTTI: + build_context.disallow_rtti = true; + break; case BuildFlag_DefaultToNilAllocator: build_context.ODIN_DEFAULT_TO_NIL_ALLOCATOR = true; break; -- cgit v1.2.3 From 4f3b5d8dcb3be98d7b11efd49f3aec758e51bd2a Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 28 Feb 2022 15:29:08 +0000 Subject: Clean up `generate_minimum_dependency_set` code --- src/checker.cpp | 75 +++++++++++++++++++++++++++++++-------------------------- 1 file changed, 41 insertions(+), 34 deletions(-) (limited to 'src/checker.cpp') diff --git a/src/checker.cpp b/src/checker.cpp index e6445d752..660691276 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -2204,21 +2204,25 @@ void generate_minimum_dependency_set(Checker *c, Entity *start) { ptr_set_init(&c->info.minimum_dependency_set, heap_allocator(), min_dep_set_cap); ptr_set_init(&c->info.minimum_dependency_type_info_set, heap_allocator()); - String required_runtime_entities[] = { +#define FORCE_ADD_RUNTIME_ENTITIES(condition, ...) do { \ + if (condition) { \ + String entities[] = {__VA_ARGS__}; \ + for (isize i = 0; i < gb_count_of(entities); i++) { \ + force_add_dependency_entity(c, c->info.runtime_package->scope, entities[i]); \ + } \ + } \ +} while (0) + + // required runtime entities + FORCE_ADD_RUNTIME_ENTITIES(true, // Odin types - str_lit("Type_Info"), str_lit("Source_Code_Location"), str_lit("Context"), str_lit("Allocator"), str_lit("Logger"), - // Global variables - str_lit("args__"), - str_lit("type_table"), - // Odin internal procedures str_lit("__init_context"), - str_lit("__type_info_of"), str_lit("cstring_to_string"), str_lit("_cleanup_runtime"), @@ -2251,35 +2255,36 @@ void generate_minimum_dependency_set(Checker *c, Entity *start) { // WASM Specific str_lit("__ashlti3"), str_lit("__multi3"), - }; - for (isize i = 0; i < gb_count_of(required_runtime_entities); i++) { - force_add_dependency_entity(c, c->info.runtime_package->scope, required_runtime_entities[i]); - } + ); - if (build_context.no_crt) { - String required_no_crt_entities[] = { - // NOTE(bill): Only if these exist - str_lit("_tls_index"), - str_lit("_fltused"), - }; - for (isize i = 0; i < gb_count_of(required_no_crt_entities); i++) { - force_add_dependency_entity(c, c->info.runtime_package->scope, required_no_crt_entities[i]); - } - } + FORCE_ADD_RUNTIME_ENTITIES(!build_context.disallow_rtti, + // Odin types + str_lit("Type_Info"), - if (!build_context.no_bounds_check) { - String bounds_check_entities[] = { - // Bounds checking related procedures - str_lit("bounds_check_error"), - str_lit("matrix_bounds_check_error"), - str_lit("slice_expr_error_hi"), - str_lit("slice_expr_error_lo_hi"), - str_lit("multi_pointer_slice_expr_error"), - }; - for (isize i = 0; i < gb_count_of(bounds_check_entities); i++) { - force_add_dependency_entity(c, c->info.runtime_package->scope, bounds_check_entities[i]); - } - } + // Global variables + str_lit("type_table"), + str_lit("__type_info_of"), + ); + + FORCE_ADD_RUNTIME_ENTITIES(!build_context.no_entry_point, + // Global variables + str_lit("args__"), + ); + + FORCE_ADD_RUNTIME_ENTITIES(build_context.no_crt, + // NOTE(bill): Only if these exist + str_lit("_tls_index"), + str_lit("_fltused"), + ); + + FORCE_ADD_RUNTIME_ENTITIES(!build_context.no_bounds_check, + // Bounds checking related procedures + str_lit("bounds_check_error"), + str_lit("matrix_bounds_check_error"), + str_lit("slice_expr_error_hi"), + str_lit("slice_expr_error_lo_hi"), + str_lit("multi_pointer_slice_expr_error"), + ); for_array(i, c->info.definitions) { Entity *e = c->info.definitions[i]; @@ -2401,6 +2406,8 @@ void generate_minimum_dependency_set(Checker *c, Entity *start) { start->flags |= EntityFlag_Used; add_dependency_to_set(c, start); } + +#undef FORCE_ADD_RUNTIME_ENTITIES } bool is_entity_a_dependency(Entity *e) { -- cgit v1.2.3 From 410b85b5c7f768543e03c9fc6f47f8c2efcd602b Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 28 Feb 2022 15:40:00 +0000 Subject: Disallow `@(thread_local)` on wasm targets --- src/check_decl.cpp | 4 ++++ src/check_stmt.cpp | 5 ++++- src/checker.cpp | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) (limited to 'src/checker.cpp') diff --git a/src/check_decl.cpp b/src/check_decl.cpp index b3b1e4474..12b0e43cb 100644 --- a/src/check_decl.cpp +++ b/src/check_decl.cpp @@ -1130,6 +1130,10 @@ void check_global_variable_decl(CheckerContext *ctx, Entity *&e, Ast *type_expr, } ac.link_name = handle_link_name(ctx, e->token, ac.link_name, ac.link_prefix); + if (is_arch_wasm() && e->Variable.thread_local_model.len != 0) { + error(e->token, "@(thread_local) is not supported for this target platform"); + } + String context_name = str_lit("variable declaration"); if (type_expr != nullptr) { diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp index 7cae1893f..f2c830c1b 100644 --- a/src/check_stmt.cpp +++ b/src/check_stmt.cpp @@ -2152,7 +2152,6 @@ void check_stmt_internal(CheckerContext *ctx, Ast *node, u32 flags) { e->state = EntityState_Resolved; } ac.link_name = handle_link_name(ctx, e->token, ac.link_name, ac.link_prefix); - e->Variable.thread_local_model = ac.thread_local_model; if (ac.link_name.len > 0) { e->Variable.link_name = ac.link_name; @@ -2182,6 +2181,10 @@ void check_stmt_internal(CheckerContext *ctx, Ast *node, u32 flags) { } e->Variable.thread_local_model = ac.thread_local_model; } + + if (is_arch_wasm() && e->Variable.thread_local_model.len != 0) { + error(e->token, "@(thread_local) is not supported for this target platform"); + } if (ac.is_static && ac.thread_local_model != "") { diff --git a/src/checker.cpp b/src/checker.cpp index 660691276..b1abdcb8a 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -2271,7 +2271,7 @@ void generate_minimum_dependency_set(Checker *c, Entity *start) { str_lit("args__"), ); - FORCE_ADD_RUNTIME_ENTITIES(build_context.no_crt, + FORCE_ADD_RUNTIME_ENTITIES((build_context.no_crt && !is_arch_wasm()), // NOTE(bill): Only if these exist str_lit("_tls_index"), str_lit("_fltused"), -- cgit v1.2.3 From a68f0b2d72a3883879da124321868afcdac3b9d6 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 18 Mar 2022 22:18:12 +0000 Subject: Improve procedure group selection based on the minimum number of arguments --- src/check_expr.cpp | 79 +++++++++++++++++++++++++++++++++++++++++++----------- src/check_type.cpp | 14 ---------- src/checker.cpp | 9 +++++++ src/entity.cpp | 10 +++++++ src/types.cpp | 1 - 5 files changed, 82 insertions(+), 31 deletions(-) (limited to 'src/checker.cpp') diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 577f3b07c..b7039fd9a 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -4872,25 +4872,16 @@ bool is_expr_constant_zero(Ast *expr) { return false; } - -CALL_ARGUMENT_CHECKER(check_call_arguments_internal) { - ast_node(ce, CallExpr, call); - GB_ASSERT(is_type_proc(proc_type)); - proc_type = base_type(proc_type); - TypeProc *pt = &proc_type->Proc; - +isize get_procedure_param_count_excluding_defaults(Type *pt, isize *param_count_) { + GB_ASSERT(pt != nullptr); + GB_ASSERT(pt->kind == Type_Proc); isize param_count = 0; isize param_count_excluding_defaults = 0; - bool variadic = pt->variadic; - bool vari_expand = (ce->ellipsis.pos.line != 0); - i64 score = 0; - bool show_error = show_error_mode == CallArgumentMode_ShowErrors; - - + bool variadic = pt->Proc.variadic; TypeTuple *param_tuple = nullptr; - if (pt->params != nullptr) { - param_tuple = &pt->params->Tuple; + if (pt->Proc.params != nullptr) { + param_tuple = &pt->Proc.params->Tuple; param_count = param_tuple->variables.count; if (variadic) { @@ -4930,6 +4921,31 @@ CALL_ARGUMENT_CHECKER(check_call_arguments_internal) { } } + if (param_count_) *param_count_ = param_count; + return param_count_excluding_defaults; +} + + +CALL_ARGUMENT_CHECKER(check_call_arguments_internal) { + ast_node(ce, CallExpr, call); + GB_ASSERT(is_type_proc(proc_type)); + proc_type = base_type(proc_type); + TypeProc *pt = &proc_type->Proc; + + isize param_count = 0; + isize param_count_excluding_defaults = get_procedure_param_count_excluding_defaults(proc_type, ¶m_count); + bool variadic = pt->variadic; + bool vari_expand = (ce->ellipsis.pos.line != 0); + i64 score = 0; + bool show_error = show_error_mode == CallArgumentMode_ShowErrors; + + + TypeTuple *param_tuple = nullptr; + if (pt->params != nullptr) { + param_tuple = &pt->params->Tuple; + } + + CallArgumentError err = CallArgumentError_None; Type *final_proc_type = proc_type; Entity *gen_entity = nullptr; @@ -5602,7 +5618,37 @@ CallArgumentData check_call_arguments(CheckerContext *c, Operand *operand, Type if (operand->mode == Addressing_ProcGroup) { check_entity_decl(c, operand->proc_group, nullptr, nullptr); - Array procs = proc_group_entities(c, *operand); + auto procs = proc_group_entities_cloned(c, *operand); + + if (procs.count > 1) { + isize max_arg_count = args.count; + for_array(i, args) { + // NOTE(bill): The only thing that may have multiple values + // will be a call expression (assuming `or_return` and `()` will be stripped) + Ast *arg = strip_or_return_expr(args[i]); + if (arg && arg->kind == Ast_CallExpr) { + max_arg_count = ISIZE_MAX; + break; + } + } + + for (isize proc_index = 0; proc_index < procs.count; /**/) { + Entity *proc = procs[proc_index]; + Type *pt = base_type(proc->type); + if (!(pt != nullptr && is_type_proc(pt))) { + continue; + } + + isize param_count = 0; + isize param_count_excluding_defaults = get_procedure_param_count_excluding_defaults(pt, ¶m_count); + + if (param_count_excluding_defaults > max_arg_count) { + array_unordered_remove(&procs, proc_index); + } else { + proc_index++; + } + } + } if (procs.count == 1) { Ast *ident = operand->expr; @@ -5632,6 +5678,7 @@ CallArgumentData check_call_arguments(CheckerContext *c, Operand *operand, Type return data; } + Entity **lhs = nullptr; isize lhs_count = -1; diff --git a/src/check_type.cpp b/src/check_type.cpp index ecb2c26ea..3c7f33a46 100644 --- a/src/check_type.cpp +++ b/src/check_type.cpp @@ -1960,20 +1960,6 @@ bool check_procedure_type(CheckerContext *ctx, Type *type, Ast *proc_type_node, if (params) param_count = params ->Tuple.variables.count; if (results) result_count = results->Tuple.variables.count; - if (param_count > 0) { - for_array(i, params->Tuple.variables) { - Entity *param = params->Tuple.variables[i]; - if (param->kind == Entity_Variable) { - ParameterValue pv = param->Variable.param_value; - if (pv.kind == ParameterValue_Constant && - pv.value.kind == ExactValue_Procedure) { - type->Proc.has_proc_default_values = true; - break; - } - } - } - } - if (result_count > 0) { Entity *first = results->Tuple.variables[0]; type->Proc.has_named_results = first->token.string != ""; diff --git a/src/checker.cpp b/src/checker.cpp index ea300afd9..53bba654d 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -2657,6 +2657,15 @@ Array proc_group_entities(CheckerContext *c, Operand o) { return procs; } +Array proc_group_entities_cloned(CheckerContext *c, Operand o) { + auto entities = proc_group_entities(c, o); + if (entities.count == 0) { + return {}; + } + return array_clone(permanent_allocator(), entities); +} + + void init_core_type_info(Checker *c) { diff --git a/src/entity.cpp b/src/entity.cpp index f5720293f..17fa884e1 100644 --- a/src/entity.cpp +++ b/src/entity.cpp @@ -115,6 +115,16 @@ struct ParameterValue { }; }; +bool has_parameter_value(ParameterValue const ¶m_value) { + if (param_value.kind != ParameterValue_Invalid) { + return true; + } + if (param_value.original_ast_expr != nullptr) { + return true; + } + return false; +} + enum EntityConstantFlags : u32 { EntityConstantFlag_ImplicitEnumValue = 1<<0, }; diff --git a/src/types.cpp b/src/types.cpp index 58ccdf5b9..ef770c846 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -186,7 +186,6 @@ struct TypeProc { bool c_vararg; bool is_polymorphic; bool is_poly_specialized; - bool has_proc_default_values; bool has_named_results; bool diverging; // no return bool return_by_pointer; -- cgit v1.2.3 From 203382461b43db30977c17f51929a565c1f3a229 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 31 Mar 2022 00:14:49 +0100 Subject: Replace the atomic intrinsics Matching C11 in style --- src/check_builtin.cpp | 191 +++++++++++++++++++++++++++++------------- src/checker.cpp | 25 +++++- src/checker_builtin_procs.hpp | 175 +++++++++----------------------------- src/llvm_backend_proc.cpp | 170 ++++++++++--------------------------- src/llvm_backend_utility.cpp | 22 +++++ src/types.cpp | 13 +++ 6 files changed, 272 insertions(+), 324 deletions(-) (limited to 'src/checker.cpp') diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp index e480704e3..3fe0f1048 100644 --- a/src/check_builtin.cpp +++ b/src/check_builtin.cpp @@ -379,6 +379,32 @@ bool check_builtin_objc_procedure(CheckerContext *c, Operand *operand, Ast *call } } +bool check_atomic_memory_order_argument(CheckerContext *c, Ast *expr, String const &builtin_name, char const *extra_message = nullptr) { + Operand x = {}; + check_expr_with_type_hint(c, &x, expr, t_atomic_memory_order); + if (x.mode == Addressing_Invalid) { + return false; + } + if (!are_types_identical(x.type, t_atomic_memory_order) || x.mode != Addressing_Constant) { + gbString str = type_to_string(x.type); + if (extra_message) { + error(x.expr, "Expected a constant Atomic_Memory_Order value for the %s of '%.*s', got %s", extra_message, LIT(builtin_name), str); + } else { + error(x.expr, "Expected a constant Atomic_Memory_Order value for '%.*s', got %s", LIT(builtin_name), str); + } + gb_string_free(str); + return false; + } + i64 value = exact_value_to_i64(x.value); + if (value < 0 || value >= OdinAtomicMemoryOrder_COUNT) { + error(x.expr, "Illegal Atomic_Memory_Order value, got %lld", cast(long long)value); + return false; + } + + return true; + +} + bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 id, Type *type_hint) { ast_node(ce, CallExpr, call); if (ce->inlining != ProcInlining_none) { @@ -423,6 +449,11 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 // NOTE(bill): The first arg may be a Type, this will be checked case by case break; + case BuiltinProc_atomic_thread_fence: + case BuiltinProc_atomic_signal_fence: + // NOTE(bill): first type will require a type hint + break; + case BuiltinProc_DIRECTIVE: { ast_node(bd, BasicDirective, ce->proc); String name = bd->name.string; @@ -3198,10 +3229,12 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 break; - case BuiltinProc_atomic_fence: - case BuiltinProc_atomic_fence_acq: - case BuiltinProc_atomic_fence_rel: - case BuiltinProc_atomic_fence_acqrel: + + case BuiltinProc_atomic_thread_fence: + case BuiltinProc_atomic_signal_fence: + if (!check_atomic_memory_order_argument(c, ce->args[0], builtin_name)) { + return false; + } operand->mode = Addressing_NoValue; break; @@ -3210,9 +3243,6 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 case BuiltinProc_unaligned_store: /*fallthrough*/ case BuiltinProc_atomic_store: - case BuiltinProc_atomic_store_rel: - case BuiltinProc_atomic_store_relaxed: - case BuiltinProc_atomic_store_unordered: { Type *elem = nullptr; if (!is_type_normal_pointer(operand->type, &elem)) { @@ -3228,14 +3258,32 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 break; } + case BuiltinProc_atomic_store_explicit: + { + Type *elem = nullptr; + if (!is_type_normal_pointer(operand->type, &elem)) { + error(operand->expr, "Expected a pointer for '%.*s'", LIT(builtin_name)); + return false; + } + Operand x = {}; + check_expr_with_type_hint(c, &x, ce->args[1], elem); + check_assignment(c, &x, elem, builtin_name); + + if (!check_atomic_memory_order_argument(c, ce->args[2], builtin_name)) { + return false; + } + + operand->type = nullptr; + operand->mode = Addressing_NoValue; + break; + } + + case BuiltinProc_volatile_load: /*fallthrough*/ case BuiltinProc_unaligned_load: /*fallthrough*/ case BuiltinProc_atomic_load: - case BuiltinProc_atomic_load_acq: - case BuiltinProc_atomic_load_relaxed: - case BuiltinProc_atomic_load_unordered: { Type *elem = nullptr; if (!is_type_normal_pointer(operand->type, &elem)) { @@ -3247,41 +3295,52 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 break; } + case BuiltinProc_atomic_load_explicit: + { + Type *elem = nullptr; + if (!is_type_normal_pointer(operand->type, &elem)) { + error(operand->expr, "Expected a pointer for '%.*s'", LIT(builtin_name)); + return false; + } + + if (!check_atomic_memory_order_argument(c, ce->args[1], builtin_name)) { + return false; + } + + operand->type = elem; + operand->mode = Addressing_Value; + break; + } + case BuiltinProc_atomic_add: - case BuiltinProc_atomic_add_acq: - case BuiltinProc_atomic_add_rel: - case BuiltinProc_atomic_add_acqrel: - case BuiltinProc_atomic_add_relaxed: case BuiltinProc_atomic_sub: - case BuiltinProc_atomic_sub_acq: - case BuiltinProc_atomic_sub_rel: - case BuiltinProc_atomic_sub_acqrel: - case BuiltinProc_atomic_sub_relaxed: case BuiltinProc_atomic_and: - case BuiltinProc_atomic_and_acq: - case BuiltinProc_atomic_and_rel: - case BuiltinProc_atomic_and_acqrel: - case BuiltinProc_atomic_and_relaxed: case BuiltinProc_atomic_nand: - case BuiltinProc_atomic_nand_acq: - case BuiltinProc_atomic_nand_rel: - case BuiltinProc_atomic_nand_acqrel: - case BuiltinProc_atomic_nand_relaxed: case BuiltinProc_atomic_or: - case BuiltinProc_atomic_or_acq: - case BuiltinProc_atomic_or_rel: - case BuiltinProc_atomic_or_acqrel: - case BuiltinProc_atomic_or_relaxed: case BuiltinProc_atomic_xor: - case BuiltinProc_atomic_xor_acq: - case BuiltinProc_atomic_xor_rel: - case BuiltinProc_atomic_xor_acqrel: - case BuiltinProc_atomic_xor_relaxed: - case BuiltinProc_atomic_xchg: - case BuiltinProc_atomic_xchg_acq: - case BuiltinProc_atomic_xchg_rel: - case BuiltinProc_atomic_xchg_acqrel: - case BuiltinProc_atomic_xchg_relaxed: + case BuiltinProc_atomic_exchange: + { + Type *elem = nullptr; + if (!is_type_normal_pointer(operand->type, &elem)) { + error(operand->expr, "Expected a pointer for '%.*s'", LIT(builtin_name)); + return false; + } + Operand x = {}; + check_expr_with_type_hint(c, &x, ce->args[1], elem); + check_assignment(c, &x, elem, builtin_name); + + operand->type = elem; + operand->mode = Addressing_Value; + break; + } + + case BuiltinProc_atomic_add_explicit: + case BuiltinProc_atomic_sub_explicit: + case BuiltinProc_atomic_and_explicit: + case BuiltinProc_atomic_nand_explicit: + case BuiltinProc_atomic_or_explicit: + case BuiltinProc_atomic_xor_explicit: + case BuiltinProc_atomic_exchange_explicit: { Type *elem = nullptr; if (!is_type_normal_pointer(operand->type, &elem)) { @@ -3292,30 +3351,18 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 check_expr_with_type_hint(c, &x, ce->args[1], elem); check_assignment(c, &x, elem, builtin_name); + + if (!check_atomic_memory_order_argument(c, ce->args[2], builtin_name)) { + return false; + } + operand->type = elem; operand->mode = Addressing_Value; break; } - case BuiltinProc_atomic_cxchg: - case BuiltinProc_atomic_cxchg_acq: - case BuiltinProc_atomic_cxchg_rel: - case BuiltinProc_atomic_cxchg_acqrel: - case BuiltinProc_atomic_cxchg_relaxed: - case BuiltinProc_atomic_cxchg_failrelaxed: - case BuiltinProc_atomic_cxchg_failacq: - case BuiltinProc_atomic_cxchg_acq_failrelaxed: - case BuiltinProc_atomic_cxchg_acqrel_failrelaxed: - - case BuiltinProc_atomic_cxchgweak: - case BuiltinProc_atomic_cxchgweak_acq: - case BuiltinProc_atomic_cxchgweak_rel: - case BuiltinProc_atomic_cxchgweak_acqrel: - case BuiltinProc_atomic_cxchgweak_relaxed: - case BuiltinProc_atomic_cxchgweak_failrelaxed: - case BuiltinProc_atomic_cxchgweak_failacq: - case BuiltinProc_atomic_cxchgweak_acq_failrelaxed: - case BuiltinProc_atomic_cxchgweak_acqrel_failrelaxed: + case BuiltinProc_atomic_compare_exchange_strong: + case BuiltinProc_atomic_compare_exchange_weak: { Type *elem = nullptr; if (!is_type_normal_pointer(operand->type, &elem)) { @@ -3333,7 +3380,33 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 operand->type = elem; break; } - break; + + case BuiltinProc_atomic_compare_exchange_strong_explicit: + case BuiltinProc_atomic_compare_exchange_weak_explicit: + { + Type *elem = nullptr; + if (!is_type_normal_pointer(operand->type, &elem)) { + error(operand->expr, "Expected a pointer for '%.*s'", LIT(builtin_name)); + return false; + } + Operand x = {}; + Operand y = {}; + check_expr_with_type_hint(c, &x, ce->args[1], elem); + check_expr_with_type_hint(c, &y, ce->args[2], elem); + check_assignment(c, &x, elem, builtin_name); + check_assignment(c, &y, elem, builtin_name); + + if (!check_atomic_memory_order_argument(c, ce->args[3], builtin_name, "success ordering")) { + return false; + } + if (!check_atomic_memory_order_argument(c, ce->args[4], builtin_name, "failure ordering")) { + return false; + } + + operand->mode = Addressing_OptionalOk; + operand->type = elem; + break; + } case BuiltinProc_fixed_point_mul: case BuiltinProc_fixed_point_div: diff --git a/src/checker.cpp b/src/checker.cpp index 53bba654d..0c72a8e14 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -829,15 +829,16 @@ struct GlobalEnumValue { i64 value; }; -Slice add_global_enum_type(String const &type_name, GlobalEnumValue *values, isize value_count) { +Slice add_global_enum_type(String const &type_name, GlobalEnumValue *values, isize value_count, Type **enum_type_ = nullptr) { Scope *scope = create_scope(nullptr, builtin_pkg->scope); - Entity *e = alloc_entity_type_name(scope, make_token_ident(type_name), nullptr, EntityState_Resolved); + Entity *entity = alloc_entity_type_name(scope, make_token_ident(type_name), nullptr, EntityState_Resolved); Type *enum_type = alloc_type_enum(); - Type *named_type = alloc_type_named(type_name, enum_type, e); + Type *named_type = alloc_type_named(type_name, enum_type, entity); set_base_type(named_type, enum_type); enum_type->Enum.base_type = t_int; enum_type->Enum.scope = scope; + entity->type = named_type; auto fields = array_make(permanent_allocator(), value_count); for (isize i = 0; i < value_count; i++) { @@ -858,6 +859,9 @@ Slice add_global_enum_type(String const &type_name, GlobalEnumValue *v enum_type->Enum.min_value = &enum_type->Enum.fields[enum_type->Enum.min_value_index]->Constant.value; enum_type->Enum.max_value = &enum_type->Enum.fields[enum_type->Enum.max_value_index]->Constant.value; + + if (enum_type_) *enum_type_ = named_type; + return slice_from_array(fields); } void add_global_enum_constant(Slice const &fields, char const *name, i64 value) { @@ -986,6 +990,21 @@ void init_universal(void) { add_global_enum_constant(fields, "ODIN_ERROR_POS_STYLE", build_context.ODIN_ERROR_POS_STYLE); } + { + GlobalEnumValue values[OdinAtomicMemoryOrder_COUNT] = { + {"relaxed", OdinAtomicMemoryOrder_relaxed}, + {"consume", OdinAtomicMemoryOrder_consume}, + {"acquire", OdinAtomicMemoryOrder_acquire}, + {"release", OdinAtomicMemoryOrder_release}, + {"acq_rel", OdinAtomicMemoryOrder_acq_rel}, + {"seq_cst", OdinAtomicMemoryOrder_seq_cst}, + }; + + add_global_enum_type(str_lit("Atomic_Memory_Order"), values, gb_count_of(values), &t_atomic_memory_order); + GB_ASSERT(t_atomic_memory_order->kind == Type_Named); + scope_insert(intrinsics_pkg->scope, t_atomic_memory_order->Named.type_name); + } + add_global_bool_constant("ODIN_DEBUG", bc->ODIN_DEBUG); add_global_bool_constant("ODIN_DISABLE_ASSERT", bc->ODIN_DISABLE_ASSERT); diff --git a/src/checker_builtin_procs.hpp b/src/checker_builtin_procs.hpp index c647d5a01..c6b0afee0 100644 --- a/src/checker_builtin_procs.hpp +++ b/src/checker_builtin_procs.hpp @@ -86,77 +86,30 @@ enum BuiltinProcId { BuiltinProc_prefetch_write_instruction, BuiltinProc_prefetch_write_data, - BuiltinProc_atomic_fence, - BuiltinProc_atomic_fence_acq, - BuiltinProc_atomic_fence_rel, - BuiltinProc_atomic_fence_acqrel, - + BuiltinProc_atomic_thread_fence, + BuiltinProc_atomic_signal_fence, BuiltinProc_atomic_store, - BuiltinProc_atomic_store_rel, - BuiltinProc_atomic_store_relaxed, - BuiltinProc_atomic_store_unordered, - + BuiltinProc_atomic_store_explicit, BuiltinProc_atomic_load, - BuiltinProc_atomic_load_acq, - BuiltinProc_atomic_load_relaxed, - BuiltinProc_atomic_load_unordered, - + BuiltinProc_atomic_load_explicit, BuiltinProc_atomic_add, - BuiltinProc_atomic_add_acq, - BuiltinProc_atomic_add_rel, - BuiltinProc_atomic_add_acqrel, - BuiltinProc_atomic_add_relaxed, + BuiltinProc_atomic_add_explicit, BuiltinProc_atomic_sub, - BuiltinProc_atomic_sub_acq, - BuiltinProc_atomic_sub_rel, - BuiltinProc_atomic_sub_acqrel, - BuiltinProc_atomic_sub_relaxed, + BuiltinProc_atomic_sub_explicit, BuiltinProc_atomic_and, - BuiltinProc_atomic_and_acq, - BuiltinProc_atomic_and_rel, - BuiltinProc_atomic_and_acqrel, - BuiltinProc_atomic_and_relaxed, + BuiltinProc_atomic_and_explicit, BuiltinProc_atomic_nand, - BuiltinProc_atomic_nand_acq, - BuiltinProc_atomic_nand_rel, - BuiltinProc_atomic_nand_acqrel, - BuiltinProc_atomic_nand_relaxed, + BuiltinProc_atomic_nand_explicit, BuiltinProc_atomic_or, - BuiltinProc_atomic_or_acq, - BuiltinProc_atomic_or_rel, - BuiltinProc_atomic_or_acqrel, - BuiltinProc_atomic_or_relaxed, + BuiltinProc_atomic_or_explicit, BuiltinProc_atomic_xor, - BuiltinProc_atomic_xor_acq, - BuiltinProc_atomic_xor_rel, - BuiltinProc_atomic_xor_acqrel, - BuiltinProc_atomic_xor_relaxed, - - BuiltinProc_atomic_xchg, - BuiltinProc_atomic_xchg_acq, - BuiltinProc_atomic_xchg_rel, - BuiltinProc_atomic_xchg_acqrel, - BuiltinProc_atomic_xchg_relaxed, - - BuiltinProc_atomic_cxchg, - BuiltinProc_atomic_cxchg_acq, - BuiltinProc_atomic_cxchg_rel, - BuiltinProc_atomic_cxchg_acqrel, - BuiltinProc_atomic_cxchg_relaxed, - BuiltinProc_atomic_cxchg_failrelaxed, - BuiltinProc_atomic_cxchg_failacq, - BuiltinProc_atomic_cxchg_acq_failrelaxed, - BuiltinProc_atomic_cxchg_acqrel_failrelaxed, - - BuiltinProc_atomic_cxchgweak, - BuiltinProc_atomic_cxchgweak_acq, - BuiltinProc_atomic_cxchgweak_rel, - BuiltinProc_atomic_cxchgweak_acqrel, - BuiltinProc_atomic_cxchgweak_relaxed, - BuiltinProc_atomic_cxchgweak_failrelaxed, - BuiltinProc_atomic_cxchgweak_failacq, - BuiltinProc_atomic_cxchgweak_acq_failrelaxed, - BuiltinProc_atomic_cxchgweak_acqrel_failrelaxed, + BuiltinProc_atomic_xor_explicit, + BuiltinProc_atomic_exchange, + BuiltinProc_atomic_exchange_explicit, + BuiltinProc_atomic_compare_exchange_strong, + BuiltinProc_atomic_compare_exchange_strong_explicit, + BuiltinProc_atomic_compare_exchange_weak, + BuiltinProc_atomic_compare_exchange_weak_explicit, BuiltinProc_fixed_point_mul, BuiltinProc_fixed_point_div, @@ -352,78 +305,30 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = { {STR_LIT("prefetch_write_instruction"), 2, false, Expr_Stmt, BuiltinProcPkg_intrinsics}, {STR_LIT("prefetch_write_data"), 2, false, Expr_Stmt, BuiltinProcPkg_intrinsics}, - {STR_LIT("atomic_fence"), 0, false, Expr_Stmt, BuiltinProcPkg_intrinsics}, - {STR_LIT("atomic_fence_acq"), 0, false, Expr_Stmt, BuiltinProcPkg_intrinsics}, - {STR_LIT("atomic_fence_rel"), 0, false, Expr_Stmt, BuiltinProcPkg_intrinsics}, - {STR_LIT("atomic_fence_acqrel"), 0, false, Expr_Stmt, BuiltinProcPkg_intrinsics}, - - {STR_LIT("atomic_store"), 2, false, Expr_Stmt, BuiltinProcPkg_intrinsics}, - {STR_LIT("atomic_store_rel"), 2, false, Expr_Stmt, BuiltinProcPkg_intrinsics}, - {STR_LIT("atomic_store_relaxed"), 2, false, Expr_Stmt, BuiltinProcPkg_intrinsics}, - {STR_LIT("atomic_store_unordered"), 2, false, Expr_Stmt, BuiltinProcPkg_intrinsics}, - - {STR_LIT("atomic_load"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, - {STR_LIT("atomic_load_acq"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, - {STR_LIT("atomic_load_relaxed"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, - {STR_LIT("atomic_load_unordered"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, - - {STR_LIT("atomic_add"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, - {STR_LIT("atomic_add_acq"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, - {STR_LIT("atomic_add_rel"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, - {STR_LIT("atomic_add_acqrel"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, - {STR_LIT("atomic_add_relaxed"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, - {STR_LIT("atomic_sub"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, - {STR_LIT("atomic_sub_acq"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, - {STR_LIT("atomic_sub_rel"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, - {STR_LIT("atomic_sub_acqrel"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, - {STR_LIT("atomic_sub_relaxed"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, - {STR_LIT("atomic_and"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, - {STR_LIT("atomic_and_acq"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, - {STR_LIT("atomic_and_rel"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, - {STR_LIT("atomic_and_acqrel"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, - {STR_LIT("atomic_and_relaxed"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, - {STR_LIT("atomic_nand"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, - {STR_LIT("atomic_nand_acq"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, - {STR_LIT("atomic_nand_rel"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, - {STR_LIT("atomic_nand_acqrel"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, - {STR_LIT("atomic_nand_relaxed"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, - {STR_LIT("atomic_or"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, - {STR_LIT("atomic_or_acq"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, - {STR_LIT("atomic_or_rel"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, - {STR_LIT("atomic_or_acqrel"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, - {STR_LIT("atomic_or_relaxed"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, - {STR_LIT("atomic_xor"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, - {STR_LIT("atomic_xor_acq"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, - {STR_LIT("atomic_xor_rel"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, - {STR_LIT("atomic_xor_acqrel"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, - {STR_LIT("atomic_xor_relaxed"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, - - {STR_LIT("atomic_xchg"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, - {STR_LIT("atomic_xchg_acq"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, - {STR_LIT("atomic_xchg_rel"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, - {STR_LIT("atomic_xchg_acqrel"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, - {STR_LIT("atomic_xchg_relaxed"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, - - {STR_LIT("atomic_cxchg"), 3, false, Expr_Expr, BuiltinProcPkg_intrinsics}, - {STR_LIT("atomic_cxchg_acq"), 3, false, Expr_Expr, BuiltinProcPkg_intrinsics}, - {STR_LIT("atomic_cxchg_rel"), 3, false, Expr_Expr, BuiltinProcPkg_intrinsics}, - {STR_LIT("atomic_cxchg_acqrel"), 3, false, Expr_Expr, BuiltinProcPkg_intrinsics}, - {STR_LIT("atomic_cxchg_relaxed"), 3, false, Expr_Expr, BuiltinProcPkg_intrinsics}, - {STR_LIT("atomic_cxchg_failrelaxed"), 3, false, Expr_Expr, BuiltinProcPkg_intrinsics}, - {STR_LIT("atomic_cxchg_failacq"), 3, false, Expr_Expr, BuiltinProcPkg_intrinsics}, - {STR_LIT("atomic_cxchg_acq_failrelaxed"), 3, false, Expr_Expr, BuiltinProcPkg_intrinsics}, - {STR_LIT("atomic_cxchg_acqrel_failrelaxed"), 3, false, Expr_Expr, BuiltinProcPkg_intrinsics}, - - {STR_LIT("atomic_cxchgweak"), 3, false, Expr_Expr, BuiltinProcPkg_intrinsics}, - {STR_LIT("atomic_cxchgweak_acq"), 3, false, Expr_Expr, BuiltinProcPkg_intrinsics}, - {STR_LIT("atomic_cxchgweak_rel"), 3, false, Expr_Expr, BuiltinProcPkg_intrinsics}, - {STR_LIT("atomic_cxchgweak_acqrel"), 3, false, Expr_Expr, BuiltinProcPkg_intrinsics}, - {STR_LIT("atomic_cxchgweak_relaxed"), 3, false, Expr_Expr, BuiltinProcPkg_intrinsics}, - {STR_LIT("atomic_cxchgweak_failrelaxed"), 3, false, Expr_Expr, BuiltinProcPkg_intrinsics}, - {STR_LIT("atomic_cxchgweak_failacq"), 3, false, Expr_Expr, BuiltinProcPkg_intrinsics}, - {STR_LIT("atomic_cxchgweak_acq_failrelaxed"), 3, false, Expr_Expr, BuiltinProcPkg_intrinsics}, - {STR_LIT("atomic_cxchgweak_acqrel_failrelaxed"), 3, false, Expr_Expr, BuiltinProcPkg_intrinsics}, - + {STR_LIT("atomic_thread_fence"), 1, false, Expr_Stmt, BuiltinProcPkg_intrinsics}, + {STR_LIT("atomic_signal_fence"), 1, false, Expr_Stmt, BuiltinProcPkg_intrinsics}, + {STR_LIT("atomic_store"), 2, false, Expr_Stmt, BuiltinProcPkg_intrinsics}, + {STR_LIT("atomic_store_explicit"), 3, false, Expr_Stmt, BuiltinProcPkg_intrinsics}, + {STR_LIT("atomic_load"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("atomic_load_explicit"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("atomic_add"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("atomic_add_explicit"), 3, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("atomic_sub"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("atomic_sub_explicit"), 3, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("atomic_and"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("atomic_and_explicit"), 3, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("atomic_nand"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("atomic_nand_explicit"), 3, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("atomic_or"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("atomic_or_explicit"), 3, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("atomic_xor"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("atomic_xor_explicit"), 3, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("atomic_exchange"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("atomic_exchange_explicit"), 3, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("atomic_compare_exchange_strong"), 3, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("atomic_compare_exchange_strong_explicit"), 5, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("atomic_compare_exchange_weak"), 3, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("atomic_compare_exchange_weak_explicit"), 5, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("fixed_point_mul"), 3, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("fixed_point_div"), 3, false, Expr_Expr, BuiltinProcPkg_intrinsics}, diff --git a/src/llvm_backend_proc.cpp b/src/llvm_backend_proc.cpp index d7f3d6c45..ad82b79e5 100644 --- a/src/llvm_backend_proc.cpp +++ b/src/llvm_backend_proc.cpp @@ -1606,36 +1606,26 @@ lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValue const &tv, } - - case BuiltinProc_atomic_fence: - LLVMBuildFence(p->builder, LLVMAtomicOrderingSequentiallyConsistent, false, ""); - return {}; - case BuiltinProc_atomic_fence_acq: - LLVMBuildFence(p->builder, LLVMAtomicOrderingAcquire, false, ""); - return {}; - case BuiltinProc_atomic_fence_rel: - LLVMBuildFence(p->builder, LLVMAtomicOrderingRelease, false, ""); + // TODO(bill): Which is correct? + case BuiltinProc_atomic_thread_fence: + LLVMBuildFence(p->builder, llvm_atomic_ordering_from_odin(ce->args[0]), false, ""); return {}; - case BuiltinProc_atomic_fence_acqrel: - LLVMBuildFence(p->builder, LLVMAtomicOrderingAcquireRelease, false, ""); + case BuiltinProc_atomic_signal_fence: + LLVMBuildFence(p->builder, llvm_atomic_ordering_from_odin(ce->args[0]), true, ""); return {}; case BuiltinProc_volatile_store: case BuiltinProc_atomic_store: - case BuiltinProc_atomic_store_rel: - case BuiltinProc_atomic_store_relaxed: - case BuiltinProc_atomic_store_unordered: { + case BuiltinProc_atomic_store_explicit: { lbValue dst = lb_build_expr(p, ce->args[0]); lbValue val = lb_build_expr(p, ce->args[1]); val = lb_emit_conv(p, val, type_deref(dst.type)); LLVMValueRef instr = LLVMBuildStore(p->builder, val.value, dst.value); switch (id) { - case BuiltinProc_volatile_store: LLVMSetVolatile(instr, true); break; - case BuiltinProc_atomic_store: LLVMSetOrdering(instr, LLVMAtomicOrderingSequentiallyConsistent); break; - case BuiltinProc_atomic_store_rel: LLVMSetOrdering(instr, LLVMAtomicOrderingRelease); break; - case BuiltinProc_atomic_store_relaxed: LLVMSetOrdering(instr, LLVMAtomicOrderingMonotonic); break; - case BuiltinProc_atomic_store_unordered: LLVMSetOrdering(instr, LLVMAtomicOrderingUnordered); break; + case BuiltinProc_volatile_store: LLVMSetVolatile(instr, true); break; + case BuiltinProc_atomic_store: LLVMSetOrdering(instr, LLVMAtomicOrderingSequentiallyConsistent); break; + case BuiltinProc_atomic_store_explicit: LLVMSetOrdering(instr, llvm_atomic_ordering_from_odin(ce->args[2])); break; } LLVMSetAlignment(instr, cast(unsigned)type_align_of(type_deref(dst.type))); @@ -1645,18 +1635,14 @@ lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValue const &tv, case BuiltinProc_volatile_load: case BuiltinProc_atomic_load: - case BuiltinProc_atomic_load_acq: - case BuiltinProc_atomic_load_relaxed: - case BuiltinProc_atomic_load_unordered: { + case BuiltinProc_atomic_load_explicit: { lbValue dst = lb_build_expr(p, ce->args[0]); LLVMValueRef instr = LLVMBuildLoad(p->builder, dst.value, ""); switch (id) { - case BuiltinProc_volatile_load: LLVMSetVolatile(instr, true); break; - case BuiltinProc_atomic_load: LLVMSetOrdering(instr, LLVMAtomicOrderingSequentiallyConsistent); break; - case BuiltinProc_atomic_load_acq: LLVMSetOrdering(instr, LLVMAtomicOrderingAcquire); break; - case BuiltinProc_atomic_load_relaxed: LLVMSetOrdering(instr, LLVMAtomicOrderingMonotonic); break; - case BuiltinProc_atomic_load_unordered: LLVMSetOrdering(instr, LLVMAtomicOrderingUnordered); break; + case BuiltinProc_volatile_load: LLVMSetVolatile(instr, true); break; + case BuiltinProc_atomic_load: LLVMSetOrdering(instr, LLVMAtomicOrderingSequentiallyConsistent); break; + case BuiltinProc_atomic_load_explicit: LLVMSetOrdering(instr, llvm_atomic_ordering_from_odin(ce->args[1])); break; } LLVMSetAlignment(instr, cast(unsigned)type_align_of(type_deref(dst.type))); @@ -1686,40 +1672,19 @@ lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValue const &tv, } case BuiltinProc_atomic_add: - case BuiltinProc_atomic_add_acq: - case BuiltinProc_atomic_add_rel: - case BuiltinProc_atomic_add_acqrel: - case BuiltinProc_atomic_add_relaxed: case BuiltinProc_atomic_sub: - case BuiltinProc_atomic_sub_acq: - case BuiltinProc_atomic_sub_rel: - case BuiltinProc_atomic_sub_acqrel: - case BuiltinProc_atomic_sub_relaxed: case BuiltinProc_atomic_and: - case BuiltinProc_atomic_and_acq: - case BuiltinProc_atomic_and_rel: - case BuiltinProc_atomic_and_acqrel: - case BuiltinProc_atomic_and_relaxed: case BuiltinProc_atomic_nand: - case BuiltinProc_atomic_nand_acq: - case BuiltinProc_atomic_nand_rel: - case BuiltinProc_atomic_nand_acqrel: - case BuiltinProc_atomic_nand_relaxed: case BuiltinProc_atomic_or: - case BuiltinProc_atomic_or_acq: - case BuiltinProc_atomic_or_rel: - case BuiltinProc_atomic_or_acqrel: - case BuiltinProc_atomic_or_relaxed: case BuiltinProc_atomic_xor: - case BuiltinProc_atomic_xor_acq: - case BuiltinProc_atomic_xor_rel: - case BuiltinProc_atomic_xor_acqrel: - case BuiltinProc_atomic_xor_relaxed: - case BuiltinProc_atomic_xchg: - case BuiltinProc_atomic_xchg_acq: - case BuiltinProc_atomic_xchg_rel: - case BuiltinProc_atomic_xchg_acqrel: - case BuiltinProc_atomic_xchg_relaxed: { + case BuiltinProc_atomic_exchange: + case BuiltinProc_atomic_add_explicit: + case BuiltinProc_atomic_sub_explicit: + case BuiltinProc_atomic_and_explicit: + case BuiltinProc_atomic_nand_explicit: + case BuiltinProc_atomic_or_explicit: + case BuiltinProc_atomic_xor_explicit: + case BuiltinProc_atomic_exchange_explicit: { lbValue dst = lb_build_expr(p, ce->args[0]); lbValue val = lb_build_expr(p, ce->args[1]); val = lb_emit_conv(p, val, type_deref(dst.type)); @@ -1728,41 +1693,20 @@ lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValue const &tv, LLVMAtomicOrdering ordering = {}; switch (id) { - case BuiltinProc_atomic_add: op = LLVMAtomicRMWBinOpAdd; ordering = LLVMAtomicOrderingSequentiallyConsistent; break; - case BuiltinProc_atomic_add_acq: op = LLVMAtomicRMWBinOpAdd; ordering = LLVMAtomicOrderingAcquire; break; - case BuiltinProc_atomic_add_rel: op = LLVMAtomicRMWBinOpAdd; ordering = LLVMAtomicOrderingRelease; break; - case BuiltinProc_atomic_add_acqrel: op = LLVMAtomicRMWBinOpAdd; ordering = LLVMAtomicOrderingAcquireRelease; break; - case BuiltinProc_atomic_add_relaxed: op = LLVMAtomicRMWBinOpAdd; ordering = LLVMAtomicOrderingMonotonic; break; - case BuiltinProc_atomic_sub: op = LLVMAtomicRMWBinOpSub; ordering = LLVMAtomicOrderingSequentiallyConsistent; break; - case BuiltinProc_atomic_sub_acq: op = LLVMAtomicRMWBinOpSub; ordering = LLVMAtomicOrderingAcquire; break; - case BuiltinProc_atomic_sub_rel: op = LLVMAtomicRMWBinOpSub; ordering = LLVMAtomicOrderingRelease; break; - case BuiltinProc_atomic_sub_acqrel: op = LLVMAtomicRMWBinOpSub; ordering = LLVMAtomicOrderingAcquireRelease; break; - case BuiltinProc_atomic_sub_relaxed: op = LLVMAtomicRMWBinOpSub; ordering = LLVMAtomicOrderingMonotonic; break; - case BuiltinProc_atomic_and: op = LLVMAtomicRMWBinOpAnd; ordering = LLVMAtomicOrderingSequentiallyConsistent; break; - case BuiltinProc_atomic_and_acq: op = LLVMAtomicRMWBinOpAnd; ordering = LLVMAtomicOrderingAcquire; break; - case BuiltinProc_atomic_and_rel: op = LLVMAtomicRMWBinOpAnd; ordering = LLVMAtomicOrderingRelease; break; - case BuiltinProc_atomic_and_acqrel: op = LLVMAtomicRMWBinOpAnd; ordering = LLVMAtomicOrderingAcquireRelease; break; - case BuiltinProc_atomic_and_relaxed: op = LLVMAtomicRMWBinOpAnd; ordering = LLVMAtomicOrderingMonotonic; break; - case BuiltinProc_atomic_nand: op = LLVMAtomicRMWBinOpNand; ordering = LLVMAtomicOrderingSequentiallyConsistent; break; - case BuiltinProc_atomic_nand_acq: op = LLVMAtomicRMWBinOpNand; ordering = LLVMAtomicOrderingAcquire; break; - case BuiltinProc_atomic_nand_rel: op = LLVMAtomicRMWBinOpNand; ordering = LLVMAtomicOrderingRelease; break; - case BuiltinProc_atomic_nand_acqrel: op = LLVMAtomicRMWBinOpNand; ordering = LLVMAtomicOrderingAcquireRelease; break; - case BuiltinProc_atomic_nand_relaxed: op = LLVMAtomicRMWBinOpNand; ordering = LLVMAtomicOrderingMonotonic; break; - case BuiltinProc_atomic_or: op = LLVMAtomicRMWBinOpOr; ordering = LLVMAtomicOrderingSequentiallyConsistent; break; - case BuiltinProc_atomic_or_acq: op = LLVMAtomicRMWBinOpOr; ordering = LLVMAtomicOrderingAcquire; break; - case BuiltinProc_atomic_or_rel: op = LLVMAtomicRMWBinOpOr; ordering = LLVMAtomicOrderingRelease; break; - case BuiltinProc_atomic_or_acqrel: op = LLVMAtomicRMWBinOpOr; ordering = LLVMAtomicOrderingAcquireRelease; break; - case BuiltinProc_atomic_or_relaxed: op = LLVMAtomicRMWBinOpOr; ordering = LLVMAtomicOrderingMonotonic; break; - case BuiltinProc_atomic_xor: op = LLVMAtomicRMWBinOpXor; ordering = LLVMAtomicOrderingSequentiallyConsistent; break; - case BuiltinProc_atomic_xor_acq: op = LLVMAtomicRMWBinOpXor; ordering = LLVMAtomicOrderingAcquire; break; - case BuiltinProc_atomic_xor_rel: op = LLVMAtomicRMWBinOpXor; ordering = LLVMAtomicOrderingRelease; break; - case BuiltinProc_atomic_xor_acqrel: op = LLVMAtomicRMWBinOpXor; ordering = LLVMAtomicOrderingAcquireRelease; break; - case BuiltinProc_atomic_xor_relaxed: op = LLVMAtomicRMWBinOpXor; ordering = LLVMAtomicOrderingMonotonic; break; - case BuiltinProc_atomic_xchg: op = LLVMAtomicRMWBinOpXchg; ordering = LLVMAtomicOrderingSequentiallyConsistent; break; - case BuiltinProc_atomic_xchg_acq: op = LLVMAtomicRMWBinOpXchg; ordering = LLVMAtomicOrderingAcquire; break; - case BuiltinProc_atomic_xchg_rel: op = LLVMAtomicRMWBinOpXchg; ordering = LLVMAtomicOrderingRelease; break; - case BuiltinProc_atomic_xchg_acqrel: op = LLVMAtomicRMWBinOpXchg; ordering = LLVMAtomicOrderingAcquireRelease; break; - case BuiltinProc_atomic_xchg_relaxed: op = LLVMAtomicRMWBinOpXchg; ordering = LLVMAtomicOrderingMonotonic; break; + case BuiltinProc_atomic_add: op = LLVMAtomicRMWBinOpAdd; ordering = LLVMAtomicOrderingSequentiallyConsistent; break; + case BuiltinProc_atomic_sub: op = LLVMAtomicRMWBinOpSub; ordering = LLVMAtomicOrderingSequentiallyConsistent; break; + case BuiltinProc_atomic_and: op = LLVMAtomicRMWBinOpAnd; ordering = LLVMAtomicOrderingSequentiallyConsistent; break; + case BuiltinProc_atomic_nand: op = LLVMAtomicRMWBinOpNand; ordering = LLVMAtomicOrderingSequentiallyConsistent; break; + case BuiltinProc_atomic_or: op = LLVMAtomicRMWBinOpOr; ordering = LLVMAtomicOrderingSequentiallyConsistent; break; + case BuiltinProc_atomic_xor: op = LLVMAtomicRMWBinOpXor; ordering = LLVMAtomicOrderingSequentiallyConsistent; break; + case BuiltinProc_atomic_exchange: op = LLVMAtomicRMWBinOpXchg; ordering = LLVMAtomicOrderingSequentiallyConsistent; break; + case BuiltinProc_atomic_add_explicit: op = LLVMAtomicRMWBinOpAdd; ordering = llvm_atomic_ordering_from_odin(ce->args[2]); break; + case BuiltinProc_atomic_sub_explicit: op = LLVMAtomicRMWBinOpSub; ordering = llvm_atomic_ordering_from_odin(ce->args[2]); break; + case BuiltinProc_atomic_and_explicit: op = LLVMAtomicRMWBinOpAnd; ordering = llvm_atomic_ordering_from_odin(ce->args[2]); break; + case BuiltinProc_atomic_nand_explicit: op = LLVMAtomicRMWBinOpNand; ordering = llvm_atomic_ordering_from_odin(ce->args[2]); break; + case BuiltinProc_atomic_or_explicit: op = LLVMAtomicRMWBinOpOr; ordering = llvm_atomic_ordering_from_odin(ce->args[2]); break; + case BuiltinProc_atomic_xor_explicit: op = LLVMAtomicRMWBinOpXor; ordering = llvm_atomic_ordering_from_odin(ce->args[2]); break; + case BuiltinProc_atomic_exchange_explicit: op = LLVMAtomicRMWBinOpXchg; ordering = llvm_atomic_ordering_from_odin(ce->args[2]); break; } lbValue res = {}; @@ -1771,24 +1715,10 @@ lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValue const &tv, return res; } - case BuiltinProc_atomic_cxchg: - case BuiltinProc_atomic_cxchg_acq: - case BuiltinProc_atomic_cxchg_rel: - case BuiltinProc_atomic_cxchg_acqrel: - case BuiltinProc_atomic_cxchg_relaxed: - case BuiltinProc_atomic_cxchg_failrelaxed: - case BuiltinProc_atomic_cxchg_failacq: - case BuiltinProc_atomic_cxchg_acq_failrelaxed: - case BuiltinProc_atomic_cxchg_acqrel_failrelaxed: - case BuiltinProc_atomic_cxchgweak: - case BuiltinProc_atomic_cxchgweak_acq: - case BuiltinProc_atomic_cxchgweak_rel: - case BuiltinProc_atomic_cxchgweak_acqrel: - case BuiltinProc_atomic_cxchgweak_relaxed: - case BuiltinProc_atomic_cxchgweak_failrelaxed: - case BuiltinProc_atomic_cxchgweak_failacq: - case BuiltinProc_atomic_cxchgweak_acq_failrelaxed: - case BuiltinProc_atomic_cxchgweak_acqrel_failrelaxed: { + case BuiltinProc_atomic_compare_exchange_strong: + case BuiltinProc_atomic_compare_exchange_weak: + case BuiltinProc_atomic_compare_exchange_strong_explicit: + case BuiltinProc_atomic_compare_exchange_weak_explicit: { lbValue address = lb_build_expr(p, ce->args[0]); Type *elem = type_deref(address.type); lbValue old_value = lb_build_expr(p, ce->args[1]); @@ -1801,24 +1731,10 @@ lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValue const &tv, LLVMBool weak = false; switch (id) { - case BuiltinProc_atomic_cxchg: success_ordering = LLVMAtomicOrderingSequentiallyConsistent; failure_ordering = LLVMAtomicOrderingSequentiallyConsistent; weak = false; break; - case BuiltinProc_atomic_cxchg_acq: success_ordering = LLVMAtomicOrderingAcquire; failure_ordering = LLVMAtomicOrderingMonotonic; weak = false; break; - case BuiltinProc_atomic_cxchg_rel: success_ordering = LLVMAtomicOrderingRelease; failure_ordering = LLVMAtomicOrderingMonotonic; weak = false; break; - case BuiltinProc_atomic_cxchg_acqrel: success_ordering = LLVMAtomicOrderingAcquireRelease; failure_ordering = LLVMAtomicOrderingMonotonic; weak = false; break; - case BuiltinProc_atomic_cxchg_relaxed: success_ordering = LLVMAtomicOrderingMonotonic; failure_ordering = LLVMAtomicOrderingMonotonic; weak = false; break; - case BuiltinProc_atomic_cxchg_failrelaxed: success_ordering = LLVMAtomicOrderingSequentiallyConsistent; failure_ordering = LLVMAtomicOrderingMonotonic; weak = false; break; - case BuiltinProc_atomic_cxchg_failacq: success_ordering = LLVMAtomicOrderingSequentiallyConsistent; failure_ordering = LLVMAtomicOrderingAcquire; weak = false; break; - case BuiltinProc_atomic_cxchg_acq_failrelaxed: success_ordering = LLVMAtomicOrderingAcquire; failure_ordering = LLVMAtomicOrderingMonotonic; weak = false; break; - case BuiltinProc_atomic_cxchg_acqrel_failrelaxed: success_ordering = LLVMAtomicOrderingAcquireRelease; failure_ordering = LLVMAtomicOrderingMonotonic; weak = false; break; - case BuiltinProc_atomic_cxchgweak: success_ordering = LLVMAtomicOrderingSequentiallyConsistent; failure_ordering = LLVMAtomicOrderingSequentiallyConsistent; weak = false; break; - case BuiltinProc_atomic_cxchgweak_acq: success_ordering = LLVMAtomicOrderingAcquire; failure_ordering = LLVMAtomicOrderingMonotonic; weak = true; break; - case BuiltinProc_atomic_cxchgweak_rel: success_ordering = LLVMAtomicOrderingRelease; failure_ordering = LLVMAtomicOrderingMonotonic; weak = true; break; - case BuiltinProc_atomic_cxchgweak_acqrel: success_ordering = LLVMAtomicOrderingAcquireRelease; failure_ordering = LLVMAtomicOrderingMonotonic; weak = true; break; - case BuiltinProc_atomic_cxchgweak_relaxed: success_ordering = LLVMAtomicOrderingMonotonic; failure_ordering = LLVMAtomicOrderingMonotonic; weak = true; break; - case BuiltinProc_atomic_cxchgweak_failrelaxed: success_ordering = LLVMAtomicOrderingSequentiallyConsistent; failure_ordering = LLVMAtomicOrderingMonotonic; weak = true; break; - case BuiltinProc_atomic_cxchgweak_failacq: success_ordering = LLVMAtomicOrderingSequentiallyConsistent; failure_ordering = LLVMAtomicOrderingAcquire; weak = true; break; - case BuiltinProc_atomic_cxchgweak_acq_failrelaxed: success_ordering = LLVMAtomicOrderingAcquire; failure_ordering = LLVMAtomicOrderingMonotonic; weak = true; break; - case BuiltinProc_atomic_cxchgweak_acqrel_failrelaxed: success_ordering = LLVMAtomicOrderingAcquireRelease; failure_ordering = LLVMAtomicOrderingMonotonic; weak = true; break; + case BuiltinProc_atomic_compare_exchange_strong: success_ordering = LLVMAtomicOrderingSequentiallyConsistent; failure_ordering = LLVMAtomicOrderingSequentiallyConsistent; weak = false; break; + case BuiltinProc_atomic_compare_exchange_weak: success_ordering = LLVMAtomicOrderingSequentiallyConsistent; failure_ordering = LLVMAtomicOrderingSequentiallyConsistent; weak = true; break; + case BuiltinProc_atomic_compare_exchange_strong_explicit: success_ordering = llvm_atomic_ordering_from_odin(ce->args[3]); failure_ordering = llvm_atomic_ordering_from_odin(ce->args[4]); weak = false; break; + case BuiltinProc_atomic_compare_exchange_weak_explicit: success_ordering = llvm_atomic_ordering_from_odin(ce->args[3]); failure_ordering = llvm_atomic_ordering_from_odin(ce->args[4]); weak = true; break; } // TODO(bill): Figure out how to make it weak diff --git a/src/llvm_backend_utility.cpp b/src/llvm_backend_utility.cpp index 399d1632d..037171637 100644 --- a/src/llvm_backend_utility.cpp +++ b/src/llvm_backend_utility.cpp @@ -2005,3 +2005,25 @@ lbValue lb_handle_objc_send(lbProcedure *p, Ast *expr) { } + + +LLVMAtomicOrdering llvm_atomic_ordering_from_odin(ExactValue const &value) { + GB_ASSERT(value.kind == ExactValue_Integer); + i64 v = exact_value_to_i64(value); + switch (v) { + case OdinAtomicMemoryOrder_relaxed: return LLVMAtomicOrderingUnordered; + case OdinAtomicMemoryOrder_consume: return LLVMAtomicOrderingMonotonic; + case OdinAtomicMemoryOrder_acquire: return LLVMAtomicOrderingAcquire; + case OdinAtomicMemoryOrder_release: return LLVMAtomicOrderingRelease; + case OdinAtomicMemoryOrder_acq_rel: return LLVMAtomicOrderingAcquireRelease; + case OdinAtomicMemoryOrder_seq_cst: return LLVMAtomicOrderingSequentiallyConsistent; + } + GB_PANIC("Unknown atomic ordering"); + return LLVMAtomicOrderingSequentiallyConsistent; +} + + +LLVMAtomicOrdering llvm_atomic_ordering_from_odin(Ast *expr) { + ExactValue value = type_and_value_of_expr(expr).value; + return llvm_atomic_ordering_from_odin(value); +} diff --git a/src/types.cpp b/src/types.cpp index b231218a2..25e29820c 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -692,6 +692,19 @@ gb_global Type *t_objc_id = nullptr; gb_global Type *t_objc_SEL = nullptr; gb_global Type *t_objc_Class = nullptr; +enum OdinAtomicMemoryOrder : i32 { + OdinAtomicMemoryOrder_relaxed = 0, + OdinAtomicMemoryOrder_consume = 1, + OdinAtomicMemoryOrder_acquire = 2, + OdinAtomicMemoryOrder_release = 3, + OdinAtomicMemoryOrder_acq_rel = 4, + OdinAtomicMemoryOrder_seq_cst = 5, + OdinAtomicMemoryOrder_COUNT, +}; + +gb_global Type *t_atomic_memory_order = nullptr; + + gb_global RecursiveMutex g_type_mutex; -- cgit v1.2.3 From 9f2d710c357f9d1ca28c169269a9816e1788d1b1 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 31 Mar 2022 12:57:24 +0100 Subject: Change `intrinsics.Atomic_Memory_Order` fields to use `Ada_Case` rather than `snake_case` --- core/c/libc/stdatomic.odin | 150 ++++++++++++++++++------------------- core/intrinsics/intrinsics.odin | 12 +-- core/mem/mem.odin | 2 +- core/sync/atomic.odin | 12 +-- core/sync/extended.odin | 30 ++++---- core/sync/primitives_atomic.odin | 16 ++-- core/sync/primitives_internal.odin | 6 +- src/checker.cpp | 12 +-- src/types.cpp | 12 +-- 9 files changed, 126 insertions(+), 126 deletions(-) (limited to 'src/checker.cpp') diff --git a/core/c/libc/stdatomic.odin b/core/c/libc/stdatomic.odin index 26ea0db5e..9de3c4678 100644 --- a/core/c/libc/stdatomic.odin +++ b/core/c/libc/stdatomic.odin @@ -50,10 +50,10 @@ atomic_thread_fence :: #force_inline proc(order: memory_order) { assert(order != .relaxed) assert(order != .consume) #partial switch order { - case .acquire: intrinsics.atomic_thread_fence(.acquire) - case .release: intrinsics.atomic_thread_fence(.release) - case .acq_rel: intrinsics.atomic_thread_fence(.acq_rel) - case .seq_cst: intrinsics.atomic_thread_fence(.seq_cst) + case .acquire: intrinsics.atomic_thread_fence(.Acquire) + case .release: intrinsics.atomic_thread_fence(.Release) + case .acq_rel: intrinsics.atomic_thread_fence(.Acq_Rel) + case .seq_cst: intrinsics.atomic_thread_fence(.Seq_Cst) } } @@ -61,10 +61,10 @@ atomic_signal_fence :: #force_inline proc(order: memory_order) { assert(order != .relaxed) assert(order != .consume) #partial switch order { - case .acquire: intrinsics.atomic_signal_fence(.acquire) - case .release: intrinsics.atomic_signal_fence(.release) - case .acq_rel: intrinsics.atomic_signal_fence(.acq_rel) - case .seq_cst: intrinsics.atomic_signal_fence(.seq_cst) + case .acquire: intrinsics.atomic_signal_fence(.Acquire) + case .release: intrinsics.atomic_signal_fence(.Release) + case .acq_rel: intrinsics.atomic_signal_fence(.Acq_Rel) + case .seq_cst: intrinsics.atomic_signal_fence(.Seq_Cst) } } @@ -123,9 +123,9 @@ atomic_store_explicit :: #force_inline proc(object: ^$T, desired: T, order: memo assert(order != .acq_rel) #partial switch order { - case .relaxed: intrinsics.atomic_store_explicit(object, desired, .relaxed) - case .release: intrinsics.atomic_store_explicit(object, desired, .release) - case .seq_cst: intrinsics.atomic_store_explicit(object, desired, .seq_cst) + case .relaxed: intrinsics.atomic_store_explicit(object, desired, .Relaxed) + case .release: intrinsics.atomic_store_explicit(object, desired, .Release) + case .seq_cst: intrinsics.atomic_store_explicit(object, desired, .Seq_Cst) } } @@ -138,10 +138,10 @@ atomic_load_explicit :: #force_inline proc(object: ^$T, order: memory_order) { assert(order != .acq_rel) #partial switch order { - case .relaxed: return intrinsics.atomic_load_explicit(object, .relaxed) - case .consume: return intrinsics.atomic_load_explicit(object, .consume) - case .acquire: return intrinsics.atomic_load_explicit(object, .acquire) - case .seq_cst: return intrinsics.atomic_load_explicit(object, .seq_cst) + case .relaxed: return intrinsics.atomic_load_explicit(object, .Relaxed) + case .consume: return intrinsics.atomic_load_explicit(object, .Consume) + case .acquire: return intrinsics.atomic_load_explicit(object, .Acquire) + case .seq_cst: return intrinsics.atomic_load_explicit(object, .Seq_Cst) } } @@ -151,12 +151,12 @@ atomic_exchange :: #force_inline proc(object: ^$T, desired: T) -> T { atomic_exchange_explicit :: #force_inline proc(object: ^$T, desired: T, order: memory_order) -> T { switch order { - case .relaxed: return intrinsics.atomic_exchange_explicit(object, desired, .relaxed) - case .consume: return intrinsics.atomic_exchange_explicit(object, desired, .consume) - case .acquire: return intrinsics.atomic_exchange_explicit(object, desired, .acquire) - case .release: return intrinsics.atomic_exchange_explicit(object, desired, .release) - case .acq_rel: return intrinsics.atomic_exchange_explicit(object, desired, .acq_rel) - case .seq_cst: return intrinsics.atomic_exchange_explicit(object, desired, .seq_cst) + case .relaxed: return intrinsics.atomic_exchange_explicit(object, desired, .Relaxed) + case .consume: return intrinsics.atomic_exchange_explicit(object, desired, .Consume) + case .acquire: return intrinsics.atomic_exchange_explicit(object, desired, .Acquire) + case .release: return intrinsics.atomic_exchange_explicit(object, desired, .Release) + case .acq_rel: return intrinsics.atomic_exchange_explicit(object, desired, .Acq_Rel) + case .seq_cst: return intrinsics.atomic_exchange_explicit(object, desired, .Seq_Cst) } return false } @@ -193,36 +193,36 @@ atomic_compare_exchange_strong_explicit :: #force_inline proc(object, expected: assert(success != .relaxed) #partial switch success { case .seq_cst: - value, ok = intrinsics.atomic_compare_exchange_strong_explicit(object, expected^, desired, .seq_cst, .seq_cst) + value, ok = intrinsics.atomic_compare_exchange_strong_explicit(object, expected^, desired, .Seq_Cst, .Seq_Cst) case .acquire: - value, ok = intrinsics.atomic_compare_exchange_strong_explicit(object, expected^, desired, .acquire, .seq_cst) + value, ok = intrinsics.atomic_compare_exchange_strong_explicit(object, expected^, desired, .Acquire, .Seq_Cst) case .consume: - value, ok = intrinsics.atomic_compare_exchange_strong_explicit(object, expected^, desired, .consume, .seq_cst) + value, ok = intrinsics.atomic_compare_exchange_strong_explicit(object, expected^, desired, .Consume, .Seq_Cst) case .release: - value, ok = intrinsics.atomic_compare_exchange_strong_explicit(object, expected^, desired, .release, .seq_cst) + value, ok = intrinsics.atomic_compare_exchange_strong_explicit(object, expected^, desired, .Release, .Seq_Cst) case .acq_rel: - value, ok = intrinsics.atomic_compare_exchange_strong_explicit(object, expected^, desired, .acq_rel, .seq_cst) + value, ok = intrinsics.atomic_compare_exchange_strong_explicit(object, expected^, desired, .Acq_Rel, .Seq_Cst) } case .relaxed: assert(success != .release) #partial switch success { case .relaxed: - value, ok = intrinsics.atomic_compare_exchange_strong_explicit(object, expected^, desired, .relaxed, .relaxed) + value, ok = intrinsics.atomic_compare_exchange_strong_explicit(object, expected^, desired, .Relaxed, .Relaxed) case .seq_cst: - value, ok = intrinsics.atomic_compare_exchange_strong_explicit(object, expected^, desired, .seq_cst, .relaxed) + value, ok = intrinsics.atomic_compare_exchange_strong_explicit(object, expected^, desired, .Seq_Cst, .Relaxed) case .acquire: - value, ok = intrinsics.atomic_compare_exchange_strong_explicit(object, expected^, desired, .acquire, .relaxed) + value, ok = intrinsics.atomic_compare_exchange_strong_explicit(object, expected^, desired, .Acquire, .Relaxed) case .consume: - value, ok = intrinsics.atomic_compare_exchange_strong_explicit(object, expected^, desired, .consume, .relaxed) + value, ok = intrinsics.atomic_compare_exchange_strong_explicit(object, expected^, desired, .Consume, .Relaxed) case .acq_rel: - value, ok = intrinsics.atomic_compare_exchange_strong_explicit(object, expected^, desired, .acq_rel, .relaxed) + value, ok = intrinsics.atomic_compare_exchange_strong_explicit(object, expected^, desired, .Acq_Rel, .Relaxed) } case .consume: assert(success == .seq_cst) - value, ok = intrinsics.atomic_compare_exchange_strong_explicit(object, expected^, desired, .seq_cst, .consume) + value, ok = intrinsics.atomic_compare_exchange_strong_explicit(object, expected^, desired, .Seq_Cst, .Consume) case .acquire: assert(success == .seq_cst) - value, ok = intrinsics.atomic_compare_exchange_strong_explicit(object, expected^, desired, .seq_cst, .acquire) + value, ok = intrinsics.atomic_compare_exchange_strong_explicit(object, expected^, desired, .Seq_Cst, .Acquire) } if !ok { expected^ = value } @@ -245,36 +245,36 @@ atomic_compare_exchange_weak_explicit :: #force_inline proc(object, expected: ^$ assert(success != .relaxed) #partial switch success { case .seq_cst: - value, ok = intrinsics.atomic_compare_exchange_weak_explicit(object, expected^, desired, .seq_cst, .seq_cst) + value, ok = intrinsics.atomic_compare_exchange_weak_explicit(object, expected^, desired, .Seq_Cst, .Seq_Cst) case .acquire: - value, ok = intrinsics.atomic_compare_exchange_weak_explicit(object, expected^, desired, .acquire, .seq_cst) + value, ok = intrinsics.atomic_compare_exchange_weak_explicit(object, expected^, desired, .Acquire, .Seq_Cst) case .consume: - value, ok = intrinsics.atomic_compare_exchange_weak_explicit(object, expected^, desired, .consume, .seq_cst) + value, ok = intrinsics.atomic_compare_exchange_weak_explicit(object, expected^, desired, .Consume, .Seq_Cst) case .release: - value, ok = intrinsics.atomic_compare_exchange_weak_explicit(object, expected^, desired, .release, .seq_cst) + value, ok = intrinsics.atomic_compare_exchange_weak_explicit(object, expected^, desired, .Release, .Seq_Cst) case .acq_rel: - value, ok = intrinsics.atomic_compare_exchange_weak_explicit(object, expected^, desired, .acq_rel, .seq_cst) + value, ok = intrinsics.atomic_compare_exchange_weak_explicit(object, expected^, desired, .Acq_Rel, .Seq_Cst) } case .relaxed: assert(success != .release) #partial switch success { case .relaxed: - value, ok = intrinsics.atomic_compare_exchange_weak_explicit(object, expected^, desired, .relaxed, .relaxed) + value, ok = intrinsics.atomic_compare_exchange_weak_explicit(object, expected^, desired, .Relaxed, .Relaxed) case .seq_cst: - value, ok = intrinsics.atomic_compare_exchange_weak_explicit(object, expected^, desired, .seq_cst, .relaxed) + value, ok = intrinsics.atomic_compare_exchange_weak_explicit(object, expected^, desired, .Seq_Cst, .Relaxed) case .acquire: - value, ok = intrinsics.atomic_compare_exchange_weak_explicit(object, expected^, desired, .acquire, .relaxed) + value, ok = intrinsics.atomic_compare_exchange_weak_explicit(object, expected^, desired, .Acquire, .Relaxed) case .consume: - value, ok = intrinsics.atomic_compare_exchange_weak_explicit(object, expected^, desired, .consume, .relaxed) + value, ok = intrinsics.atomic_compare_exchange_weak_explicit(object, expected^, desired, .Consume, .Relaxed) case .acq_rel: - value, ok = intrinsics.atomic_compare_exchange_weak_explicit(object, expected^, desired, .acq_rel, .relaxed) + value, ok = intrinsics.atomic_compare_exchange_weak_explicit(object, expected^, desired, .Acq_Rel, .Relaxed) } case .consume: assert(success == .seq_cst) - value, ok = intrinsics.atomic_compare_exchange_weak_explicit(object, expected^, desired, .seq_cst, .consume) + value, ok = intrinsics.atomic_compare_exchange_weak_explicit(object, expected^, desired, .Seq_Cst, .Consume) case .acquire: assert(success == .seq_cst) - value, ok = intrinsics.atomic_compare_exchange_weak_explicit(object, expected^, desired, .seq_cst, .acquire) + value, ok = intrinsics.atomic_compare_exchange_weak_explicit(object, expected^, desired, .Seq_Cst, .Acquire) } if !ok { expected^ = value } @@ -288,13 +288,13 @@ atomic_fetch_add :: #force_inline proc(object: ^$T, operand: T) -> T { atomic_fetch_add_explicit :: #force_inline proc(object: ^$T, operand: T, order: memory_order) -> T { switch order { - case .relaxed: return intrinsics.atomic_add_explicit(object, operand, .relaxed) - case .consume: return intrinsics.atomic_add_explicit(object, operand, .consume) - case .acquire: return intrinsics.atomic_add_explicit(object, operand, .acquire) - case .release: return intrinsics.atomic_add_explicit(object, operand, .release) - case .acq_rel: return intrinsics.atomic_add_explicit(object, operand, .acq_rel) + case .relaxed: return intrinsics.atomic_add_explicit(object, operand, .Relaxed) + case .consume: return intrinsics.atomic_add_explicit(object, operand, .Consume) + case .acquire: return intrinsics.atomic_add_explicit(object, operand, .Acquire) + case .release: return intrinsics.atomic_add_explicit(object, operand, .Release) + case .acq_rel: return intrinsics.atomic_add_explicit(object, operand, .Acq_Rel) case: fallthrough - case .seq_cst: return intrinsics.atomic_add_explicit(object, operand, .seq_cst) + case .seq_cst: return intrinsics.atomic_add_explicit(object, operand, .Seq_Cst) } } @@ -304,13 +304,13 @@ atomic_fetch_sub :: #force_inline proc(object: ^$T, operand: T) -> T { atomic_fetch_sub_explicit :: #force_inline proc(object: ^$T, operand: T, order: memory_order) -> T { switch order { - case .relaxed: return intrinsics.atomic_sub_explicit(object, operand, .relaxed) - case .consume: return intrinsics.atomic_sub_explicit(object, operand, .consume) - case .acquire: return intrinsics.atomic_sub_explicit(object, operand, .acquire) - case .release: return intrinsics.atomic_sub_explicit(object, operand, .release) - case .acq_rel: return intrinsics.atomic_sub_explicit(object, operand, .acq_rel) + case .relaxed: return intrinsics.atomic_sub_explicit(object, operand, .Relaxed) + case .consume: return intrinsics.atomic_sub_explicit(object, operand, .Consume) + case .acquire: return intrinsics.atomic_sub_explicit(object, operand, .Acquire) + case .release: return intrinsics.atomic_sub_explicit(object, operand, .Release) + case .acq_rel: return intrinsics.atomic_sub_explicit(object, operand, .Acq_Rel) case: fallthrough - case .seq_cst: return intrinsics.atomic_sub_explicit(object, operand, .seq_cst) + case .seq_cst: return intrinsics.atomic_sub_explicit(object, operand, .Seq_Cst) } } @@ -320,13 +320,13 @@ atomic_fetch_or :: #force_inline proc(object: ^$T, operand: T) -> T { atomic_fetch_or_explicit :: #force_inline proc(object: ^$T, operand: T, order: memory_order) -> T { switch order { - case .relaxed: return intrinsics.atomic_or_explicit(object, operand, .relaxed) - case .consume: return intrinsics.atomic_or_explicit(object, operand, .consume) - case .acquire: return intrinsics.atomic_or_explicit(object, operand, .acquire) - case .release: return intrinsics.atomic_or_explicit(object, operand, .release) - case .acq_rel: return intrinsics.atomic_or_explicit(object, operand, .acq_rel) + case .relaxed: return intrinsics.atomic_or_explicit(object, operand, .Relaxed) + case .consume: return intrinsics.atomic_or_explicit(object, operand, .Consume) + case .acquire: return intrinsics.atomic_or_explicit(object, operand, .Acquire) + case .release: return intrinsics.atomic_or_explicit(object, operand, .Release) + case .acq_rel: return intrinsics.atomic_or_explicit(object, operand, .Acq_Rel) case: fallthrough - case .seq_cst: return intrinsics.atomic_or_explicit(object, operand, .seq_cst) + case .seq_cst: return intrinsics.atomic_or_explicit(object, operand, .Seq_Cst) } } @@ -336,13 +336,13 @@ atomic_fetch_xor :: #force_inline proc(object: ^$T, operand: T) -> T { atomic_fetch_xor_explicit :: #force_inline proc(object: ^$T, operand: T, order: memory_order) -> T { switch order { - case .relaxed: return intrinsics.atomic_xor_explicit(object, operand, .relaxed) - case .consume: return intrinsics.atomic_xor_explicit(object, operand, .consume) - case .acquire: return intrinsics.atomic_xor_explicit(object, operand, .acquire) - case .release: return intrinsics.atomic_xor_explicit(object, operand, .release) - case .acq_rel: return intrinsics.atomic_xor_explicit(object, operand, .acq_rel) + case .relaxed: return intrinsics.atomic_xor_explicit(object, operand, .Relaxed) + case .consume: return intrinsics.atomic_xor_explicit(object, operand, .Consume) + case .acquire: return intrinsics.atomic_xor_explicit(object, operand, .Acquire) + case .release: return intrinsics.atomic_xor_explicit(object, operand, .Release) + case .acq_rel: return intrinsics.atomic_xor_explicit(object, operand, .Acq_Rel) case: fallthrough - case .seq_cst: return intrinsics.atomic_xor_explicit(object, operand, .seq_cst) + case .seq_cst: return intrinsics.atomic_xor_explicit(object, operand, .Seq_Cst) } } @@ -351,13 +351,13 @@ atomic_fetch_and :: #force_inline proc(object: ^$T, operand: T) -> T { } atomic_fetch_and_explicit :: #force_inline proc(object: ^$T, operand: T, order: memory_order) -> T { switch order { - case .relaxed: return intrinsics.atomic_and_explicit(object, operand, .relaxed) - case .consume: return intrinsics.atomic_and_explicit(object, operand, .consume) - case .acquire: return intrinsics.atomic_and_explicit(object, operand, .acquire) - case .release: return intrinsics.atomic_and_explicit(object, operand, .release) - case .acq_rel: return intrinsics.atomic_and_explicit(object, operand, .acq_rel) + case .relaxed: return intrinsics.atomic_and_explicit(object, operand, .Relaxed) + case .consume: return intrinsics.atomic_and_explicit(object, operand, .Consume) + case .acquire: return intrinsics.atomic_and_explicit(object, operand, .Acquire) + case .release: return intrinsics.atomic_and_explicit(object, operand, .Release) + case .acq_rel: return intrinsics.atomic_and_explicit(object, operand, .Acq_Rel) case: fallthrough - case .seq_cst: return intrinsics.atomic_and_explicit(object, operand, .seq_cst) + case .seq_cst: return intrinsics.atomic_and_explicit(object, operand, .Seq_Cst) } } diff --git a/core/intrinsics/intrinsics.odin b/core/intrinsics/intrinsics.odin index 4c1c166e6..ce8fd96ea 100644 --- a/core/intrinsics/intrinsics.odin +++ b/core/intrinsics/intrinsics.odin @@ -63,12 +63,12 @@ syscall :: proc(id: uintptr, args: ..uintptr) -> uintptr --- // Atomics Atomic_Memory_Order :: enum { - relaxed = 0, // unordered - consume = 1, // monotonic - acquire = 2, - release = 3, - acq_rel = 4, - seq_cst = 5, + Relaxed = 0, // Unordered + Consume = 1, // Monotonic + Acquire = 2, + Release = 3, + Acq_Rel = 4, + Seq_Cst = 5, } atomic_thread_fence :: proc(order: Atomic_Memory_Order) --- diff --git a/core/mem/mem.odin b/core/mem/mem.odin index 1ebe558ef..817c0ea5f 100644 --- a/core/mem/mem.odin +++ b/core/mem/mem.odin @@ -16,7 +16,7 @@ zero_explicit :: proc "contextless" (data: rawptr, len: int) -> rawptr { // equivalent semantics to those provided by the C11 Annex K 3.7.4.1 // memset_s call. intrinsics.mem_zero_volatile(data, len) // Use the volatile mem_zero - intrinsics.atomic_thread_fence(.seq_cst) // Prevent reordering + intrinsics.atomic_thread_fence(.Seq_Cst) // Prevent reordering return data } zero_item :: proc "contextless" (item: $P/^$T) { diff --git a/core/sync/atomic.odin b/core/sync/atomic.odin index d6521daed..f537764c4 100644 --- a/core/sync/atomic.odin +++ b/core/sync/atomic.odin @@ -6,12 +6,12 @@ cpu_relax :: intrinsics.cpu_relax /* Atomic_Memory_Order :: enum { - relaxed = 0, - consume = 1, - acquire = 2, - release = 3, - acq_rel = 4, - seq_cst = 5, + Relaxed = 0, + Consume = 1, + Acquire = 2, + Release = 3, + Acq_Rel = 4, + Seq_Cst = 5, } */ Atomic_Memory_Order :: intrinsics.Atomic_Memory_Order diff --git a/core/sync/extended.odin b/core/sync/extended.odin index c8ae4493f..24f7c096c 100644 --- a/core/sync/extended.odin +++ b/core/sync/extended.odin @@ -146,10 +146,10 @@ Auto_Reset_Event :: struct { } auto_reset_event_signal :: proc(e: ^Auto_Reset_Event) { - old_status := atomic_load_explicit(&e.status, .relaxed) + old_status := atomic_load_explicit(&e.status, .Relaxed) for { new_status := old_status + 1 if old_status < 1 else 1 - if _, ok := atomic_compare_exchange_weak_explicit(&e.status, old_status, new_status, .release, .relaxed); ok { + if _, ok := atomic_compare_exchange_weak_explicit(&e.status, old_status, new_status, .Release, .Relaxed); ok { break } @@ -160,7 +160,7 @@ auto_reset_event_signal :: proc(e: ^Auto_Reset_Event) { } auto_reset_event_wait :: proc(e: ^Auto_Reset_Event) { - old_status := atomic_sub_explicit(&e.status, 1, .acquire) + old_status := atomic_sub_explicit(&e.status, 1, .Acquire) if old_status < 1 { sema_wait(&e.sema) } @@ -174,14 +174,14 @@ Ticket_Mutex :: struct { } ticket_mutex_lock :: #force_inline proc(m: ^Ticket_Mutex) { - ticket := atomic_add_explicit(&m.ticket, 1, .relaxed) - for ticket != atomic_load_explicit(&m.serving, .acquire) { + ticket := atomic_add_explicit(&m.ticket, 1, .Relaxed) + for ticket != atomic_load_explicit(&m.serving, .Acquire) { cpu_relax() } } ticket_mutex_unlock :: #force_inline proc(m: ^Ticket_Mutex) { - atomic_add_explicit(&m.serving, 1, .relaxed) + atomic_add_explicit(&m.serving, 1, .Relaxed) } @(deferred_in=ticket_mutex_unlock) ticket_mutex_guard :: proc(m: ^Ticket_Mutex) -> bool { @@ -196,18 +196,18 @@ Benaphore :: struct { } benaphore_lock :: proc(b: ^Benaphore) { - if atomic_add_explicit(&b.counter, 1, .acquire) > 1 { + if atomic_add_explicit(&b.counter, 1, .Acquire) > 1 { sema_wait(&b.sema) } } benaphore_try_lock :: proc(b: ^Benaphore) -> bool { - v, _ := atomic_compare_exchange_strong_explicit(&b.counter, 1, 0, .acquire, .acquire) + v, _ := atomic_compare_exchange_strong_explicit(&b.counter, 1, 0, .Acquire, .Acquire) return v == 0 } benaphore_unlock :: proc(b: ^Benaphore) { - if atomic_sub_explicit(&b.counter, 1, .release) > 0 { + if atomic_sub_explicit(&b.counter, 1, .Release) > 0 { sema_post(&b.sema) } } @@ -227,7 +227,7 @@ Recursive_Benaphore :: struct { recursive_benaphore_lock :: proc(b: ^Recursive_Benaphore) { tid := current_thread_id() - if atomic_add_explicit(&b.counter, 1, .acquire) > 1 { + if atomic_add_explicit(&b.counter, 1, .Acquire) > 1 { if tid != b.owner { sema_wait(&b.sema) } @@ -240,10 +240,10 @@ recursive_benaphore_lock :: proc(b: ^Recursive_Benaphore) { recursive_benaphore_try_lock :: proc(b: ^Recursive_Benaphore) -> bool { tid := current_thread_id() if b.owner == tid { - atomic_add_explicit(&b.counter, 1, .acquire) + atomic_add_explicit(&b.counter, 1, .Acquire) } - if v, _ := atomic_compare_exchange_strong_explicit(&b.counter, 1, 0, .acquire, .acquire); v != 0 { + if v, _ := atomic_compare_exchange_strong_explicit(&b.counter, 1, 0, .Acquire, .Acquire); v != 0 { return false } // inside the lock @@ -260,7 +260,7 @@ recursive_benaphore_unlock :: proc(b: ^Recursive_Benaphore) { if recursion == 0 { b.owner = 0 } - if atomic_sub_explicit(&b.counter, 1, .release) > 0 { + if atomic_sub_explicit(&b.counter, 1, .Release) > 0 { if recursion == 0 { sema_post(&b.sema) } @@ -293,12 +293,12 @@ once_do :: proc(o: ^Once, fn: proc()) { defer mutex_unlock(&o.m) if !o.done { fn() - atomic_store_explicit(&o.done, true, .release) + atomic_store_explicit(&o.done, true, .Release) } } - if atomic_load_explicit(&o.done, .acquire) == false { + if atomic_load_explicit(&o.done, .Acquire) == false { do_slow(o, fn) } } diff --git a/core/sync/primitives_atomic.odin b/core/sync/primitives_atomic.odin index 401f78b91..11fff4e60 100644 --- a/core/sync/primitives_atomic.odin +++ b/core/sync/primitives_atomic.odin @@ -24,7 +24,7 @@ atomic_mutex_lock :: proc(m: ^Atomic_Mutex) { new_state := curr_state // Make a copy of it spin_lock: for spin in 0.. bool { - _, ok := atomic_compare_exchange_strong_explicit(&m.state, .Unlocked, .Locked, .acquire, .consume) + _, ok := atomic_compare_exchange_strong_explicit(&m.state, .Unlocked, .Locked, .Acquire, .Consume) return ok } @@ -290,7 +290,7 @@ Queue_Item :: struct { @(private="file") queue_item_wait :: proc(item: ^Queue_Item) { - for atomic_load_explicit(&item.futex, .acquire) == 0 { + for atomic_load_explicit(&item.futex, .Acquire) == 0 { futex_wait(&item.futex, 0) cpu_relax() } @@ -298,7 +298,7 @@ queue_item_wait :: proc(item: ^Queue_Item) { @(private="file") queue_item_wait_with_timeout :: proc(item: ^Queue_Item, duration: time.Duration) -> bool { start := time.tick_now() - for atomic_load_explicit(&item.futex, .acquire) == 0 { + for atomic_load_explicit(&item.futex, .Acquire) == 0 { remaining := duration - time.tick_since(start) if remaining < 0 { return false @@ -312,7 +312,7 @@ queue_item_wait_with_timeout :: proc(item: ^Queue_Item, duration: time.Duration) } @(private="file") queue_item_signal :: proc(item: ^Queue_Item) { - atomic_store_explicit(&item.futex, 1, .release) + atomic_store_explicit(&item.futex, 1, .Release) futex_signal(&item.futex) } diff --git a/core/sync/primitives_internal.odin b/core/sync/primitives_internal.odin index c1a38b4ad..4807b41c1 100644 --- a/core/sync/primitives_internal.odin +++ b/core/sync/primitives_internal.odin @@ -10,7 +10,7 @@ when #config(ODIN_SYNC_RECURSIVE_MUTEX_USE_FUTEX, true) { _recursive_mutex_lock :: proc(m: ^Recursive_Mutex) { tid := Futex(current_thread_id()) for { - prev_owner := atomic_compare_exchange_strong_explicit(&m.impl.owner, tid, 0, .acquire, .acquire) + prev_owner := atomic_compare_exchange_strong_explicit(&m.impl.owner, tid, 0, .Acquire, .Acquire) switch prev_owner { case 0, tid: m.impl.recursion += 1 @@ -27,7 +27,7 @@ when #config(ODIN_SYNC_RECURSIVE_MUTEX_USE_FUTEX, true) { if m.impl.recursion != 0 { return } - atomic_exchange_explicit(&m.impl.owner, 0, .release) + atomic_exchange_explicit(&m.impl.owner, 0, .Release) futex_signal(&m.impl.owner) // outside the lock @@ -36,7 +36,7 @@ when #config(ODIN_SYNC_RECURSIVE_MUTEX_USE_FUTEX, true) { _recursive_mutex_try_lock :: proc(m: ^Recursive_Mutex) -> bool { tid := Futex(current_thread_id()) - prev_owner := atomic_compare_exchange_strong_explicit(&m.impl.owner, tid, 0, .acquire, .acquire) + prev_owner := atomic_compare_exchange_strong_explicit(&m.impl.owner, tid, 0, .Acquire, .Acquire) switch prev_owner { case 0, tid: m.impl.recursion += 1 diff --git a/src/checker.cpp b/src/checker.cpp index 0c72a8e14..1bb786ea1 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -992,12 +992,12 @@ void init_universal(void) { { GlobalEnumValue values[OdinAtomicMemoryOrder_COUNT] = { - {"relaxed", OdinAtomicMemoryOrder_relaxed}, - {"consume", OdinAtomicMemoryOrder_consume}, - {"acquire", OdinAtomicMemoryOrder_acquire}, - {"release", OdinAtomicMemoryOrder_release}, - {"acq_rel", OdinAtomicMemoryOrder_acq_rel}, - {"seq_cst", OdinAtomicMemoryOrder_seq_cst}, + {OdinAtomicMemoryOrder_strings[OdinAtomicMemoryOrder_relaxed], OdinAtomicMemoryOrder_relaxed}, + {OdinAtomicMemoryOrder_strings[OdinAtomicMemoryOrder_consume], OdinAtomicMemoryOrder_consume}, + {OdinAtomicMemoryOrder_strings[OdinAtomicMemoryOrder_acquire], OdinAtomicMemoryOrder_acquire}, + {OdinAtomicMemoryOrder_strings[OdinAtomicMemoryOrder_release], OdinAtomicMemoryOrder_release}, + {OdinAtomicMemoryOrder_strings[OdinAtomicMemoryOrder_acq_rel], OdinAtomicMemoryOrder_acq_rel}, + {OdinAtomicMemoryOrder_strings[OdinAtomicMemoryOrder_seq_cst], OdinAtomicMemoryOrder_seq_cst}, }; add_global_enum_type(str_lit("Atomic_Memory_Order"), values, gb_count_of(values), &t_atomic_memory_order); diff --git a/src/types.cpp b/src/types.cpp index 16d07d392..e10dae1ed 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -703,12 +703,12 @@ enum OdinAtomicMemoryOrder : i32 { }; char const *OdinAtomicMemoryOrder_strings[OdinAtomicMemoryOrder_COUNT] = { - "relaxed", - "consume", - "acquire", - "release", - "acq_rel", - "seq_cst", + "Relaxed", + "Consume", + "Acquire", + "Release", + "Acq_Rel", + "Seq_Cst", }; gb_global Type *t_atomic_memory_order = nullptr; -- cgit v1.2.3 From 0e27b27b81f4b51ae4691d4dc84ae130867b3f67 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sun, 1 May 2022 23:28:32 +0100 Subject: Fix building issues with arm32 --- src/build_settings.cpp | 44 +++++++++++++++++++++++++++----------------- src/checker.cpp | 1 + 2 files changed, 28 insertions(+), 17 deletions(-) (limited to 'src/checker.cpp') diff --git a/src/build_settings.cpp b/src/build_settings.cpp index 1619c342b..e596e54e5 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -378,7 +378,7 @@ gb_global TargetMetrics target_linux_arm32 = { TargetArch_arm32, 4, 8, - str_lit("aapcs-linux-gnu"), + str_lit("arm-linux-gnu"), str_lit("e-m:o-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"), }; @@ -1127,6 +1127,15 @@ void init_build_context(TargetMetrics *cross_target) { bc->link_flags = str_lit("-arch x86 "); break; } + } else if (bc->metrics.arch == TargetArch_arm32) { + switch (bc->metrics.os) { + case TargetOs_linux: + bc->link_flags = str_lit("-arch arm "); + break; + default: + gb_printf_err("Compiler Error: Unsupported architecture\n"); + gb_exit(1); + } } else if (bc->metrics.arch == TargetArch_arm64) { switch (bc->metrics.os) { case TargetOs_darwin: @@ -1214,27 +1223,28 @@ bool init_build_paths(String init_filename) { return false; } - GB_ASSERT(find_result.windows_sdk_um_library_path.len > 0); - GB_ASSERT(find_result.windows_sdk_ucrt_library_path.len > 0); + if (find_result.windows_sdk_um_library_path.len > 0) { + GB_ASSERT(find_result.windows_sdk_ucrt_library_path.len > 0); - if (find_result.windows_sdk_root.len > 0) { - bc->build_paths[BuildPath_Win_SDK_Root] = path_from_string(ha, find_result.windows_sdk_root); - } + if (find_result.windows_sdk_root.len > 0) { + bc->build_paths[BuildPath_Win_SDK_Root] = path_from_string(ha, find_result.windows_sdk_root); + } - if (find_result.windows_sdk_um_library_path.len > 0) { - bc->build_paths[BuildPath_Win_SDK_UM_Lib] = path_from_string(ha, find_result.windows_sdk_um_library_path); - } + if (find_result.windows_sdk_um_library_path.len > 0) { + bc->build_paths[BuildPath_Win_SDK_UM_Lib] = path_from_string(ha, find_result.windows_sdk_um_library_path); + } - if (find_result.windows_sdk_ucrt_library_path.len > 0) { - bc->build_paths[BuildPath_Win_SDK_UCRT_Lib] = path_from_string(ha, find_result.windows_sdk_ucrt_library_path); - } + if (find_result.windows_sdk_ucrt_library_path.len > 0) { + bc->build_paths[BuildPath_Win_SDK_UCRT_Lib] = path_from_string(ha, find_result.windows_sdk_ucrt_library_path); + } - if (find_result.vs_exe_path.len > 0) { - bc->build_paths[BuildPath_VS_EXE] = path_from_string(ha, find_result.vs_exe_path); - } + if (find_result.vs_exe_path.len > 0) { + bc->build_paths[BuildPath_VS_EXE] = path_from_string(ha, find_result.vs_exe_path); + } - if (find_result.vs_library_path.len > 0) { - bc->build_paths[BuildPath_VS_LIB] = path_from_string(ha, find_result.vs_library_path); + if (find_result.vs_library_path.len > 0) { + bc->build_paths[BuildPath_VS_LIB] = path_from_string(ha, find_result.vs_library_path); + } } gb_free(ha, find_result.windows_sdk_root.text); diff --git a/src/checker.cpp b/src/checker.cpp index 1bb786ea1..1e33c6e9d 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -944,6 +944,7 @@ void init_universal(void) { {"Unknown", TargetArch_Invalid}, {"amd64", TargetArch_amd64}, {"i386", TargetArch_i386}, + {"arm32", TargetArch_arm32}, {"arm64", TargetArch_arm64}, {"wasm32", TargetArch_wasm32}, {"wasm64", TargetArch_wasm64}, -- cgit v1.2.3 From e4743b15b15ea5f1b2611bbc1718274ebb03bf03 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 4 May 2022 16:40:12 +0100 Subject: Add `@(priority_index=)` for `foreign import` --- src/checker.cpp | 11 +++++++++++ src/checker.hpp | 1 + src/entity.cpp | 1 + src/llvm_backend.cpp | 7 +++++++ 4 files changed, 20 insertions(+) (limited to 'src/checker.cpp') diff --git a/src/checker.cpp b/src/checker.cpp index 1e33c6e9d..fdd75126f 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -4414,6 +4414,14 @@ DECL_ATTRIBUTE_PROC(foreign_import_decl_attribute) { } ac->require_declaration = true; return true; + } else if (name == "priority_index") { + ExactValue ev = check_decl_attribute_value(c, value); + if (ev.kind != ExactValue_Integer) { + error(elem, "Expected an integer value for '%.*s'", LIT(name)); + } else { + ac->foreign_import_priority_index = exact_value_to_i64(ev); + } + return true; } return false; } @@ -4470,6 +4478,9 @@ void check_add_foreign_import_decl(CheckerContext *ctx, Ast *decl) { mpmc_enqueue(&ctx->info->required_foreign_imports_through_force_queue, e); add_entity_use(ctx, nullptr, e); } + if (ac.foreign_import_priority_index != 0) { + e->LibraryName.priority_index = ac.foreign_import_priority_index; + } if (has_asm_extension(fullpath)) { if (build_context.metrics.arch != TargetArch_amd64 || diff --git a/src/checker.hpp b/src/checker.hpp index 552e6aca7..1c9ffd8c7 100644 --- a/src/checker.hpp +++ b/src/checker.hpp @@ -118,6 +118,7 @@ struct AttributeContext { bool init : 1; bool set_cold : 1; u32 optimization_mode; // ProcedureOptimizationMode + i64 foreign_import_priority_index; String objc_class; String objc_name; diff --git a/src/entity.cpp b/src/entity.cpp index 1f87f7af6..904a630fb 100644 --- a/src/entity.cpp +++ b/src/entity.cpp @@ -252,6 +252,7 @@ struct Entity { struct { Slice paths; String name; + i64 priority_index; } LibraryName; i32 Nil; struct { diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index 267431551..7cf588853 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -43,6 +43,13 @@ GB_COMPARE_PROC(foreign_library_cmp) { if (x == y) { return 0; } + GB_ASSERT(x->kind == Entity_LibraryName); + GB_ASSERT(y->kind == Entity_LibraryName); + + cmp = i64_cmp(x->LibraryName.priority_index, y->LibraryName.priority_index); + if (cmp) { + return cmp; + } if (x->pkg != y->pkg) { isize order_x = x->pkg ? x->pkg->order : 0; -- cgit v1.2.3 From b4df272eb5ca8b43a47ad0f70dff19dc98563642 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 11 May 2022 12:15:37 +0100 Subject: Improve -vet shadowing to allow `x := x if cond else y` etc --- src/checker.cpp | 37 ++++++++++++++++++++++++++++--------- 1 file changed, 28 insertions(+), 9 deletions(-) (limited to 'src/checker.cpp') diff --git a/src/checker.cpp b/src/checker.cpp index fdd75126f..d186163e4 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -544,6 +544,28 @@ GB_COMPARE_PROC(vetted_entity_variable_pos_cmp) { return token_pos_cmp(x->token.pos, y->token.pos); } +bool check_vet_shadowing_assignment(Checker *c, Entity *shadowed, Ast *expr) { + Ast *init = unparen_expr(expr); + if (init == nullptr) { + return false; + } + if (init->kind == Ast_Ident) { + // TODO(bill): Which logic is better? Same name or same entity + // bool ignore = init->Ident.token.string == name; + bool ignore = init->Ident.entity == shadowed; + if (ignore) { + return true; + } + } else if (init->kind == Ast_TernaryIfExpr) { + bool x = check_vet_shadowing_assignment(c, shadowed, init->TernaryIfExpr.x); + bool y = check_vet_shadowing_assignment(c, shadowed, init->TernaryIfExpr.y); + if (x || y) { + return true; + } + } + + return false; +} bool check_vet_shadowing(Checker *c, Entity *e, VettedEntity *ve) { @@ -594,17 +616,14 @@ bool check_vet_shadowing(Checker *c, Entity *e, VettedEntity *ve) { } // NOTE(bill): Ignore intentional redeclaration - // x := x; + // x := x // Suggested in issue #637 (2020-05-11) + // Also allow the following + // x := x if cond else y + // x := z if cond else x if ((e->flags & EntityFlag_Using) == 0 && e->kind == Entity_Variable) { - Ast *init = unparen_expr(e->Variable.init_expr); - if (init != nullptr && init->kind == Ast_Ident) { - // TODO(bill): Which logic is better? Same name or same entity - // bool ignore = init->Ident.token.string == name; - bool ignore = init->Ident.entity == shadowed; - if (ignore) { - return false; - } + if (check_vet_shadowing_assignment(c, shadowed, e->Variable.init_expr)) { + return false; } } -- cgit v1.2.3 From 5bc866e420d8eb9e909db71e230d1283c6116d7e Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sat, 14 May 2022 14:44:24 +0100 Subject: Allow for `import _ "foo"` to allow for `@(init)` procedures; Remove `using import` code --- src/checker.cpp | 48 ++++++++++-------------------------------------- src/parser.cpp | 14 ++++---------- src/parser.hpp | 1 - 3 files changed, 14 insertions(+), 49 deletions(-) (limited to 'src/checker.cpp') diff --git a/src/checker.cpp b/src/checker.cpp index d186163e4..da9a97622 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -4356,6 +4356,9 @@ void check_add_import_decl(CheckerContext *ctx, Ast *decl) { } String import_name = path_to_entity_name(id->import_name.string, id->fullpath, false); + if (is_blank_ident(import_name)) { + force_use = true; + } // NOTE(bill, 2019-05-19): If the directory path is not a valid entity name, force the user to assign a custom one // if (import_name.len == 0 || import_name == "_") { @@ -4363,17 +4366,13 @@ void check_add_import_decl(CheckerContext *ctx, Ast *decl) { // } if (import_name.len == 0 || is_blank_ident(import_name)) { - if (id->is_using) { - // TODO(bill): Should this be a warning? - } else { - if (id->import_name.string == "") { - String invalid_name = id->fullpath; - invalid_name = get_invalid_import_name(invalid_name); + if (id->import_name.string == "") { + String invalid_name = id->fullpath; + invalid_name = get_invalid_import_name(invalid_name); - error(id->token, "Import name %.*s, is not a valid identifier. Perhaps you want to reference the package by a different name like this: import \"%.*s\" ", LIT(invalid_name), LIT(invalid_name)); - } else { - error(token, "Import name, %.*s, cannot be use as an import name as it is not a valid identifier", LIT(id->import_name.string)); - } + error(id->token, "Import name %.*s, is not a valid identifier. Perhaps you want to reference the package by a different name like this: import \"%.*s\" ", LIT(invalid_name), LIT(invalid_name)); + } else { + error(token, "Import name, %.*s, cannot be use as an import name as it is not a valid identifier", LIT(id->import_name.string)); } } else { GB_ASSERT(id->import_name.pos.line != 0); @@ -4383,38 +4382,11 @@ void check_add_import_decl(CheckerContext *ctx, Ast *decl) { scope); add_entity(ctx, parent_scope, nullptr, e); - if (force_use || id->is_using) { + if (force_use) { add_entity_use(ctx, nullptr, e); } } - if (id->is_using) { - if (parent_scope->flags & ScopeFlag_Global) { - error(id->import_name, "built-in package imports cannot use using"); - return; - } - - // NOTE(bill): Add imported entities to this file's scope - for_array(elem_index, scope->elements.entries) { - String name = scope->elements.entries[elem_index].key.string; - Entity *e = scope->elements.entries[elem_index].value; - if (e->scope == parent_scope) continue; - - if (is_entity_exported(e, true)) { - Entity *found = scope_lookup_current(parent_scope, name); - if (found != nullptr) { - // NOTE(bill): - // Date: 2019-03-17 - // The order has to be the other way around as `using` adds the entity into the that - // file scope otherwise the error would be the wrong way around - redeclaration_error(name, found, e); - } else { - add_entity_with_name(ctx, parent_scope, e->identifier, e, name); - } - } - } - } - scope->flags |= ScopeFlag_HasBeenImported; } diff --git a/src/parser.cpp b/src/parser.cpp index df7f908a6..1f4093e5f 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -1160,11 +1160,10 @@ Ast *ast_package_decl(AstFile *f, Token token, Token name, CommentGroup *docs, C return result; } -Ast *ast_import_decl(AstFile *f, Token token, bool is_using, Token relpath, Token import_name, +Ast *ast_import_decl(AstFile *f, Token token, Token relpath, Token import_name, CommentGroup *docs, CommentGroup *comment) { Ast *result = alloc_ast_node(f, Ast_ImportDecl); result->ImportDecl.token = token; - result->ImportDecl.is_using = is_using; result->ImportDecl.relpath = relpath; result->ImportDecl.import_name = import_name; result->ImportDecl.docs = docs; @@ -4382,7 +4381,6 @@ Ast *parse_import_decl(AstFile *f, ImportDeclKind kind) { CommentGroup *docs = f->lead_comment; Token token = expect_token(f, Token_import); Token import_name = {}; - bool is_using = kind != ImportDecl_Standard; switch (f->curr_token.kind) { case Token_Ident: @@ -4393,22 +4391,18 @@ Ast *parse_import_decl(AstFile *f, ImportDeclKind kind) { break; } - if (!is_using && is_blank_ident(import_name)) { - syntax_error(import_name, "Illegal import name: '_'"); - } - Token file_path = expect_token_after(f, Token_String, "import"); Ast *s = nullptr; if (f->curr_proc != nullptr) { - syntax_error(import_name, "You cannot use 'import' within a procedure. This must be done at the file scope"); + syntax_error(import_name, "Cannot use 'import' within a procedure. This must be done at the file scope"); s = ast_bad_decl(f, import_name, file_path); } else { - s = ast_import_decl(f, token, is_using, file_path, import_name, docs, f->line_comment); + s = ast_import_decl(f, token, file_path, import_name, docs, f->line_comment); array_add(&f->imports, s); } - if (is_using) { + if (kind != ImportDecl_Standard) { syntax_error(import_name, "'using import' is not allowed, please use the import name explicitly"); } diff --git a/src/parser.hpp b/src/parser.hpp index c7b4fd0d8..698ed7623 100644 --- a/src/parser.hpp +++ b/src/parser.hpp @@ -585,7 +585,6 @@ AST_KIND(_DeclBegin, "", bool) \ Token import_name; \ CommentGroup *docs; \ CommentGroup *comment; \ - bool is_using; \ }) \ AST_KIND(ForeignImportDecl, "foreign import declaration", struct { \ Token token; \ -- cgit v1.2.3 From 23cb96de022f91e1798f73b920f972845081b370 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sun, 15 May 2022 16:37:05 +0100 Subject: Commit `import _` changes --- src/checker.cpp | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) (limited to 'src/checker.cpp') diff --git a/src/checker.cpp b/src/checker.cpp index da9a97622..8afc6eb14 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -4365,15 +4365,12 @@ void check_add_import_decl(CheckerContext *ctx, Ast *decl) { // import_name = scope->pkg->name; // } - if (import_name.len == 0 || is_blank_ident(import_name)) { - if (id->import_name.string == "") { - String invalid_name = id->fullpath; - invalid_name = get_invalid_import_name(invalid_name); + if (import_name.len == 0) { + String invalid_name = id->fullpath; + invalid_name = get_invalid_import_name(invalid_name); - error(id->token, "Import name %.*s, is not a valid identifier. Perhaps you want to reference the package by a different name like this: import \"%.*s\" ", LIT(invalid_name), LIT(invalid_name)); - } else { - error(token, "Import name, %.*s, cannot be use as an import name as it is not a valid identifier", LIT(id->import_name.string)); - } + error(id->token, "Import name %.*s, is not a valid identifier. Perhaps you want to reference the package by a different name like this: import \"%.*s\" ", LIT(invalid_name), LIT(invalid_name)); + error(token, "Import name, %.*s, cannot be use as an import name as it is not a valid identifier", LIT(id->import_name.string)); } else { GB_ASSERT(id->import_name.pos.line != 0); id->import_name.string = import_name; -- cgit v1.2.3 From f3aefbc4434b92fc3fda74c942c953b08dd18a62 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 30 May 2022 14:53:12 +0100 Subject: `@(require_target_feature=)` `@(enable_target_feature=)` require_target_feature - required by the target micro-architecture enable_target_feature - will be enabled for the specified procedure only --- core/simd/x86/fxsr.odin | 4 + core/simd/x86/pclmulqdq.odin | 1 + core/simd/x86/sha.odin | 7 ++ core/simd/x86/sse.odin | 102 ++++++++++++++++++++ core/simd/x86/sse2.odin | 223 +++++++++++++++++++++++++++++++++++++++++++ core/simd/x86/sse3.odin | 11 +++ core/simd/x86/ssse3.odin | 16 ++++ src/build_settings.cpp | 109 ++++++++++++++++++++- src/check_decl.cpp | 12 +++ src/checker.cpp | 16 ++++ src/checker.hpp | 3 + src/entity.cpp | 8 +- src/llvm_backend.cpp | 4 +- src/llvm_backend_proc.cpp | 13 +++ src/main.cpp | 4 +- src/string.cpp | 9 ++ 16 files changed, 533 insertions(+), 9 deletions(-) (limited to 'src/checker.cpp') diff --git a/core/simd/x86/fxsr.odin b/core/simd/x86/fxsr.odin index 847678d29..cd78de7d4 100644 --- a/core/simd/x86/fxsr.odin +++ b/core/simd/x86/fxsr.odin @@ -1,17 +1,21 @@ //+build i386, amd64 package simd_x86 +@(enable_target_feature="fxsr") _fxsave :: #force_inline proc "c" (mem_addr: rawptr) { fxsave(mem_addr) } +@(enable_target_feature="fxsr") _fxrstor :: #force_inline proc "c" (mem_addr: rawptr) { fxrstor(mem_addr) } when ODIN_ARCH == .amd64 { + @(enable_target_feature="fxsr") _fxsave64 :: #force_inline proc "c" (mem_addr: rawptr) { fxsave64(mem_addr) } + @(enable_target_feature="fxsr") _fxrstor64 :: #force_inline proc "c" (mem_addr: rawptr) { fxrstor64(mem_addr) } diff --git a/core/simd/x86/pclmulqdq.odin b/core/simd/x86/pclmulqdq.odin index ba4ecf35f..8a665db03 100644 --- a/core/simd/x86/pclmulqdq.odin +++ b/core/simd/x86/pclmulqdq.odin @@ -1,6 +1,7 @@ //+build i386, amd64 package simd_x86 +@(enable_target_feature="pclmulqdq") _mm_clmulepi64_si128 :: #force_inline proc "c" (a, b: __m128i, $IMM8: u8) -> __m128i { return pclmulqdq(a, b, u8(IMM8)) } diff --git a/core/simd/x86/sha.odin b/core/simd/x86/sha.odin index d907ce6a6..90f1d72ce 100644 --- a/core/simd/x86/sha.odin +++ b/core/simd/x86/sha.odin @@ -1,24 +1,31 @@ //+build i386, amd64 package simd_x86 +@(enable_target_feature="sha") _mm_sha1msg1_epu32 :: #force_inline proc "c" (a, b: __m128i) -> __m128i { return transmute(__m128i)sha1msg1(transmute(i32x4)a, transmute(i32x4)b) } +@(enable_target_feature="sha") _mm_sha1msg2_epu32 :: #force_inline proc "c" (a, b: __m128i) -> __m128i { return transmute(__m128i)sha1msg2(transmute(i32x4)a, transmute(i32x4)b) } +@(enable_target_feature="sha") _mm_sha1nexte_epu32 :: #force_inline proc "c" (a, b: __m128i) -> __m128i { return transmute(__m128i)sha1nexte(transmute(i32x4)a, transmute(i32x4)b) } +@(enable_target_feature="sha") _mm_sha1rnds4_epu32 :: #force_inline proc "c" (a, b: __m128i, $FUNC: u32) -> __m128i where 0 <= FUNC, FUNC <= 3 { return transmute(__m128i)sha1rnds4(transmute(i32x4)a, transmute(i32x4)b, u8(FUNC & 0xff)) } +@(enable_target_feature="sha") _mm_sha256msg1_epu32 :: #force_inline proc "c" (a, b: __m128i) -> __m128i { return transmute(__m128i)sha256msg1(transmute(i32x4)a, transmute(i32x4)b) } +@(enable_target_feature="sha") _mm_sha256msg2_epu32 :: #force_inline proc "c" (a, b: __m128i) -> __m128i { return transmute(__m128i)sha256msg2(transmute(i32x4)a, transmute(i32x4)b) } +@(enable_target_feature="sha") _mm_sha256rnds2_epu32 :: #force_inline proc "c" (a, b, k: __m128i) -> __m128i { return transmute(__m128i)sha256rnds2(transmute(i32x4)a, transmute(i32x4)b, transmute(i32x4)k) } diff --git a/core/simd/x86/sse.odin b/core/simd/x86/sse.odin index a564f243a..6d8939b1b 100644 --- a/core/simd/x86/sse.odin +++ b/core/simd/x86/sse.odin @@ -43,232 +43,299 @@ _MM_FLUSH_ZERO_ON :: 0x8000 _MM_FLUSH_ZERO_OFF :: 0x0000 +@(enable_target_feature="sse") _mm_add_ss :: #force_inline proc "c" (a, b: __m128) -> __m128 { return addss(a, b) } +@(enable_target_feature="sse") _mm_add_ps :: #force_inline proc "c" (a, b: __m128) -> __m128 { return simd.add(a, b) } +@(enable_target_feature="sse") _mm_sub_ss :: #force_inline proc "c" (a, b: __m128) -> __m128 { return subss(a, b) } +@(enable_target_feature="sse") _mm_sub_ps :: #force_inline proc "c" (a, b: __m128) -> __m128 { return simd.sub(a, b) } +@(enable_target_feature="sse") _mm_mul_ss :: #force_inline proc "c" (a, b: __m128) -> __m128 { return mulss(a, b) } +@(enable_target_feature="sse") _mm_mul_ps :: #force_inline proc "c" (a, b: __m128) -> __m128 { return simd.mul(a, b) } +@(enable_target_feature="sse") _mm_div_ss :: #force_inline proc "c" (a, b: __m128) -> __m128 { return divss(a, b) } +@(enable_target_feature="sse") _mm_div_ps :: #force_inline proc "c" (a, b: __m128) -> __m128 { return simd.div(a, b) } +@(enable_target_feature="sse") _mm_sqrt_ss :: #force_inline proc "c" (a, b: __m128) -> __m128 { return sqrtss(a) } +@(enable_target_feature="sse") _mm_sqrt_ps :: #force_inline proc "c" (a: __m128) -> __m128 { return sqrtps(a) } +@(enable_target_feature="sse") _mm_rcp_ss :: #force_inline proc "c" (a: __m128) -> __m128 { return rcpss(a) } +@(enable_target_feature="sse") _mm_rcp_ps :: #force_inline proc "c" (a: __m128) -> __m128 { return rcpps(a) } +@(enable_target_feature="sse") _mm_rsqrt_ss :: #force_inline proc "c" (a: __m128) -> __m128 { return rsqrtss(a) } +@(enable_target_feature="sse") _mm_rsqrt_ps :: #force_inline proc "c" (a: __m128) -> __m128 { return rsqrtps(a) } +@(enable_target_feature="sse") _mm_min_ss :: #force_inline proc "c" (a, b: __m128) -> __m128 { return minss(a, b) } +@(enable_target_feature="sse") _mm_min_ps :: #force_inline proc "c" (a, b: __m128) -> __m128 { return minps(a, b) } +@(enable_target_feature="sse") _mm_max_ss :: #force_inline proc "c" (a, b: __m128) -> __m128 { return maxss(a, b) } +@(enable_target_feature="sse") _mm_max_ps :: #force_inline proc "c" (a, b: __m128) -> __m128 { return maxps(a, b) } +@(enable_target_feature="sse") _mm_and_ps :: #force_inline proc "c" (a, b: __m128) -> __m128 { return transmute(__m128)simd.and(transmute(__m128i)a, transmute(__m128i)b) } +@(enable_target_feature="sse") _mm_andnot_ps :: #force_inline proc "c" (a, b: __m128) -> __m128 { return transmute(__m128)simd.and_not(transmute(__m128i)a, transmute(__m128i)b) } +@(enable_target_feature="sse") _mm_or_ps :: #force_inline proc "c" (a, b: __m128) -> __m128 { return transmute(__m128)simd.or(transmute(__m128i)a, transmute(__m128i)b) } +@(enable_target_feature="sse") _mm_xor_ps :: #force_inline proc "c" (a, b: __m128) -> __m128 { return transmute(__m128)simd.xor(transmute(__m128i)a, transmute(__m128i)b) } +@(enable_target_feature="sse") _mm_cmpeq_ss :: #force_inline proc "c" (a, b: __m128) -> __m128 { return cmpss(a, b, 0) } +@(enable_target_feature="sse") _mm_cmplt_ss :: #force_inline proc "c" (a, b: __m128) -> __m128 { return cmpss(a, b, 1) } +@(enable_target_feature="sse") _mm_cmple_ss :: #force_inline proc "c" (a, b: __m128) -> __m128 { return cmpss(a, b, 2) } +@(enable_target_feature="sse") _mm_cmpgt_ss :: #force_inline proc "c" (a, b: __m128) -> __m128 { return simd.shuffle(a, cmpss(b, a, 1), 4, 1, 2, 3) } +@(enable_target_feature="sse") _mm_cmpge_ss :: #force_inline proc "c" (a, b: __m128) -> __m128 { return simd.shuffle(a, cmpss(b, a, 2), 4, 1, 2, 3) } +@(enable_target_feature="sse") _mm_cmpneq_ss :: #force_inline proc "c" (a, b: __m128) -> __m128 { return cmpss(a, b, 4) } +@(enable_target_feature="sse") _mm_cmpnlt_ss :: #force_inline proc "c" (a, b: __m128) -> __m128 { return cmpss(a, b, 5) } +@(enable_target_feature="sse") _mm_cmpnle_ss :: #force_inline proc "c" (a, b: __m128) -> __m128 { return cmpss(a, b, 6) } +@(enable_target_feature="sse") _mm_cmpngt_ss :: #force_inline proc "c" (a, b: __m128) -> __m128 { return simd.shuffle(a, cmpss(b, a, 5), 4, 1, 2, 3) } +@(enable_target_feature="sse") _mm_cmpnge_ss :: #force_inline proc "c" (a, b: __m128) -> __m128 { return simd.shuffle(a, cmpss(b, a, 6), 4, 1, 2, 3) } +@(enable_target_feature="sse") _mm_cmpord_ss :: #force_inline proc "c" (a, b: __m128) -> __m128 { return cmpss(a, b, 7) } +@(enable_target_feature="sse") _mm_cmpunord_ss :: #force_inline proc "c" (a, b: __m128) -> __m128 { return cmpss(a, b, 3) } +@(enable_target_feature="sse") _mm_cmpeq_ps :: #force_inline proc "c" (a, b: __m128) -> __m128 { return cmpps(a, b, 0) } +@(enable_target_feature="sse") _mm_cmplt_ps :: #force_inline proc "c" (a, b: __m128) -> __m128 { return cmpps(a, b, 1) } +@(enable_target_feature="sse") _mm_cmple_ps :: #force_inline proc "c" (a, b: __m128) -> __m128 { return cmpps(a, b, 2) } +@(enable_target_feature="sse") _mm_cmpgt_ps :: #force_inline proc "c" (a, b: __m128) -> __m128 { return cmpps(b, a, 1) } +@(enable_target_feature="sse") _mm_cmpge_ps :: #force_inline proc "c" (a, b: __m128) -> __m128 { return cmpps(b, a, 2) } +@(enable_target_feature="sse") _mm_cmpneq_ps :: #force_inline proc "c" (a, b: __m128) -> __m128 { return cmpps(a, b, 4) } +@(enable_target_feature="sse") _mm_cmpnlt_ps :: #force_inline proc "c" (a, b: __m128) -> __m128 { return cmpps(a, b, 5) } +@(enable_target_feature="sse") _mm_cmpnle_ps :: #force_inline proc "c" (a, b: __m128) -> __m128 { return cmpps(a, b, 6) } +@(enable_target_feature="sse") _mm_cmpngt_ps :: #force_inline proc "c" (a, b: __m128) -> __m128 { return cmpps(b, a, 5) } +@(enable_target_feature="sse") _mm_cmpnge_ps :: #force_inline proc "c" (a, b: __m128) -> __m128 { return cmpps(b, a, 6) } +@(enable_target_feature="sse") _mm_cmpord_ps :: #force_inline proc "c" (a, b: __m128) -> __m128 { return cmpps(b, a, 7) } +@(enable_target_feature="sse") _mm_cmpunord_ps :: #force_inline proc "c" (a, b: __m128) -> __m128 { return cmpps(b, a, 3) } +@(enable_target_feature="sse") _mm_comieq_ss :: #force_inline proc "c" (a, b: __m128) -> b32 { return comieq_ss(a, b) } +@(enable_target_feature="sse") _mm_comilt_ss :: #force_inline proc "c" (a, b: __m128) -> b32 { return comilt_ss(a, b) } +@(enable_target_feature="sse") _mm_comile_ss :: #force_inline proc "c" (a, b: __m128) -> b32 { return comile_ss(a, b) } +@(enable_target_feature="sse") _mm_comigt_ss :: #force_inline proc "c" (a, b: __m128) -> b32 { return comigt_ss(a, b) } +@(enable_target_feature="sse") _mm_comige_ss :: #force_inline proc "c" (a, b: __m128) -> b32 { return comige_ss(a, b) } +@(enable_target_feature="sse") _mm_comineq_ss :: #force_inline proc "c" (a, b: __m128) -> b32 { return comineq_ss(a, b) } +@(enable_target_feature="sse") _mm_ucomieq_ss :: #force_inline proc "c" (a, b: __m128) -> b32 { return ucomieq_ss(a, b) } +@(enable_target_feature="sse") _mm_ucomilt_ss :: #force_inline proc "c" (a, b: __m128) -> b32 { return ucomilt_ss(a, b) } +@(enable_target_feature="sse") _mm_ucomile_ss :: #force_inline proc "c" (a, b: __m128) -> b32 { return ucomile_ss(a, b) } +@(enable_target_feature="sse") _mm_ucomigt_ss :: #force_inline proc "c" (a, b: __m128) -> b32 { return ucomigt_ss(a, b) } +@(enable_target_feature="sse") _mm_ucomige_ss :: #force_inline proc "c" (a, b: __m128) -> b32 { return ucomige_ss(a, b) } +@(enable_target_feature="sse") _mm_ucomineq_ss :: #force_inline proc "c" (a, b: __m128) -> b32 { return ucomineq_ss(a, b) } +@(enable_target_feature="sse") _mm_cvtss_si32 :: #force_inline proc "c" (a: __m128) -> i32 { return cvtss2si(a) } _mm_cvt_ss2si :: _mm_cvtss_si32 _mm_cvttss_si32 :: _mm_cvtss_si32 +@(enable_target_feature="sse") _mm_cvtss_f32 :: #force_inline proc "c" (a: __m128) -> f32 { return simd.extract(a, 0) } +@(enable_target_feature="sse") _mm_cvtsi32_ss :: #force_inline proc "c" (a: __m128, b: i32) -> __m128 { return cvtsi2ss(a, b) } _mm_cvt_si2ss :: _mm_cvtsi32_ss +@(enable_target_feature="sse") _mm_set_ss :: #force_inline proc "c" (a: f32) -> __m128 { return __m128{a, 0, 0, 0} } +@(enable_target_feature="sse") _mm_set1_ps :: #force_inline proc "c" (a: f32) -> __m128 { return __m128(a) } _mm_set_ps1 :: _mm_set1_ps +@(enable_target_feature="sse") _mm_set_ps :: #force_inline proc "c" (a, b, c, d: f32) -> __m128 { return __m128{d, c, b, a} } +@(enable_target_feature="sse") _mm_setr_ps :: #force_inline proc "c" (a, b, c, d: f32) -> __m128 { return __m128{a, b, c, d} } +@(enable_target_feature="sse") _mm_setzero_ps :: #force_inline proc "c" () -> __m128 { return __m128{0, 0, 0, 0} } +@(enable_target_feature="sse") _mm_shuffle_ps :: #force_inline proc "c" (a, b: __m128, $MASK: u32) -> __m128 { return simd.shuffle( a, b, @@ -279,56 +346,69 @@ _mm_shuffle_ps :: #force_inline proc "c" (a, b: __m128, $MASK: u32) -> __m128 { } +@(enable_target_feature="sse") _mm_unpackhi_ps :: #force_inline proc "c" (a, b: __m128) -> __m128 { return simd.shuffle(a, b, 2, 6, 3, 7) } +@(enable_target_feature="sse") _mm_unpacklo_ps :: #force_inline proc "c" (a, b: __m128) -> __m128 { return simd.shuffle(a, b, 0, 4, 1, 5) } +@(enable_target_feature="sse") _mm_movehl_ps :: #force_inline proc "c" (a, b: __m128) -> __m128 { return simd.shuffle(a, b, 6, 7, 2, 3) } +@(enable_target_feature="sse") _mm_movelh_ps :: #force_inline proc "c" (a, b: __m128) -> __m128 { return simd.shuffle(a, b, 0, 1, 4, 5) } +@(enable_target_feature="sse") _mm_movemask_ps :: #force_inline proc "c" (a: __m128) -> u32 { return movmskps(a) } +@(enable_target_feature="sse") _mm_load_ss :: #force_inline proc "c" (p: ^f32) -> __m128 { return __m128{p^, 0, 0, 0} } +@(enable_target_feature="sse") _mm_load1_ps :: #force_inline proc "c" (p: ^f32) -> __m128 { a := p^ return __m128(a) } _mm_load_ps1 :: _mm_load1_ps +@(enable_target_feature="sse") _mm_load_ps :: #force_inline proc "c" (p: [^]f32) -> __m128 { return (^__m128)(p)^ } +@(enable_target_feature="sse") _mm_loadu_ps :: #force_inline proc "c" (p: [^]f32) -> __m128 { dst := _mm_undefined_ps() intrinsics.mem_copy_non_overlapping(&dst, p, size_of(__m128)) return dst } +@(enable_target_feature="sse") _mm_loadr_ps :: #force_inline proc "c" (p: [^]f32) -> __m128 { return simd.lanes_reverse(_mm_load_ps(p)) } +@(enable_target_feature="sse") _mm_loadu_si64 :: #force_inline proc "c" (mem_addr: rawptr) -> __m128i { a := intrinsics.unaligned_load((^i64)(mem_addr)) return __m128i{a, 0} } +@(enable_target_feature="sse") _mm_store_ss :: #force_inline proc "c" (p: ^f32, a: __m128) { p^ = simd.extract(a, 0) } +@(enable_target_feature="sse") _mm_store1_ps :: #force_inline proc "c" (p: [^]f32, a: __m128) { b := simd.swizzle(a, 0, 0, 0, 0) (^__m128)(p)^ = b @@ -336,71 +416,89 @@ _mm_store1_ps :: #force_inline proc "c" (p: [^]f32, a: __m128) { _mm_store_ps1 :: _mm_store1_ps +@(enable_target_feature="sse") _mm_store_ps :: #force_inline proc "c" (p: [^]f32, a: __m128) { (^__m128)(p)^ = a } +@(enable_target_feature="sse") _mm_storeu_ps :: #force_inline proc "c" (p: [^]f32, a: __m128) { b := a intrinsics.mem_copy_non_overlapping(p, &b, size_of(__m128)) } +@(enable_target_feature="sse") _mm_storer_ps :: #force_inline proc "c" (p: [^]f32, a: __m128) { (^__m128)(p)^ = simd.lanes_reverse(a) } +@(enable_target_feature="sse") _mm_move_ss :: #force_inline proc "c" (a, b: __m128) -> __m128 { return simd.shuffle(a, b, 4, 1, 2, 3) } +@(enable_target_feature="sse") _mm_sfence :: #force_inline proc "c" () { sfence() } +@(enable_target_feature="sse") _mm_getcsr :: #force_inline proc "c" () -> (result: u32) { stmxcsr(&result) return result } +@(enable_target_feature="sse") _mm_setcsr :: #force_inline proc "c" (val: u32) { val := val ldmxcsr(&val) } +@(enable_target_feature="sse") _MM_GET_EXCEPTION_MASK :: #force_inline proc "c" () -> u32 { return _mm_getcsr() & _MM_MASK_MASK } +@(enable_target_feature="sse") _MM_GET_EXCEPTION_STATE :: #force_inline proc "c" () -> u32 { return _mm_getcsr() & _MM_EXCEPT_MASK } +@(enable_target_feature="sse") _MM_GET_FLUSH_ZERO_MODE :: #force_inline proc "c" () -> u32 { return _mm_getcsr() & _MM_FLUSH_ZERO_MASK } +@(enable_target_feature="sse") _MM_GET_ROUNDING_MODE :: #force_inline proc "c" () -> u32 { return _mm_getcsr() & _MM_ROUND_MASK } +@(enable_target_feature="sse") _MM_SET_EXCEPTION_MASK :: #force_inline proc "c" (x: u32) { _mm_setcsr((_mm_getcsr() &~ _MM_MASK_MASK) | x) } +@(enable_target_feature="sse") _MM_SET_EXCEPTION_STATE :: #force_inline proc "c" (x: u32) { _mm_setcsr((_mm_getcsr() &~ _MM_EXCEPT_MASK) | x) } +@(enable_target_feature="sse") _MM_SET_FLUSH_ZERO_MODE :: #force_inline proc "c" (x: u32) { _mm_setcsr((_mm_getcsr() &~ _MM_FLUSH_ZERO_MASK) | x) } +@(enable_target_feature="sse") _MM_SET_ROUNDING_MODE :: #force_inline proc "c" (x: u32) { _mm_setcsr((_mm_getcsr() &~ _MM_ROUND_MASK) | x) } +@(enable_target_feature="sse") _mm_prefetch :: #force_inline proc "c" (p: rawptr, $STRATEGY: u32) { prefetch(p, (STRATEGY>>2)&1, STRATEGY&3, 1) } +@(enable_target_feature="sse") _mm_undefined_ps :: #force_inline proc "c" () -> __m128 { return _mm_set1_ps(0) } +@(enable_target_feature="sse") _MM_TRANSPOSE4_PS :: #force_inline proc "c" (row0, row1, row2, row3: ^__m128) { tmp0 := _mm_unpacklo_ps(row0^, row1^) tmp1 := _mm_unpacklo_ps(row2^, row3^) @@ -413,17 +511,21 @@ _MM_TRANSPOSE4_PS :: #force_inline proc "c" (row0, row1, row2, row3: ^__m128) { row3^ = _mm_movelh_ps(tmp3, tmp1) } +@(enable_target_feature="sse") _mm_stream_ps :: #force_inline proc "c" (addr: [^]f32, a: __m128) { intrinsics.non_temporal_store((^__m128)(addr), a) } when ODIN_ARCH == .amd64 { + @(enable_target_feature="sse") _mm_cvtss_si64 :: #force_inline proc "c"(a: __m128) -> i64 { return cvtss2si64(a) } + @(enable_target_feature="sse") _mm_cvttss_si64 :: #force_inline proc "c"(a: __m128) -> i64 { return cvttss2si64(a) } + @(enable_target_feature="sse") _mm_cvtsi64_ss :: #force_inline proc "c"(a: __m128, b: i64) -> __m128 { return cvtsi642ss(a, b) } diff --git a/core/simd/x86/sse2.odin b/core/simd/x86/sse2.odin index cb2e61f46..d15df8120 100644 --- a/core/simd/x86/sse2.odin +++ b/core/simd/x86/sse2.odin @@ -4,103 +4,135 @@ package simd_x86 import "core:intrinsics" import "core:simd" +@(enable_target_feature="sse2") _mm_pause :: #force_inline proc "c" () { pause() } +@(enable_target_feature="sse2") _mm_clflush :: #force_inline proc "c" (p: rawptr) { clflush(p) } +@(enable_target_feature="sse2") _mm_lfence :: #force_inline proc "c" () { lfence() } +@(enable_target_feature="sse2") _mm_mfence :: #force_inline proc "c" () { mfence() } +@(enable_target_feature="sse2") _mm_add_epi8 :: #force_inline proc "c" (a, b: __m128i) -> __m128i { return transmute(__m128i)simd.add(transmute(i8x16)a, transmute(i8x16)b) } +@(enable_target_feature="sse2") _mm_add_epi16 :: #force_inline proc "c" (a, b: __m128i) -> __m128i { return transmute(__m128i)simd.add(transmute(i16x8)a, transmute(i16x8)b) } +@(enable_target_feature="sse2") _mm_add_epi32 :: #force_inline proc "c" (a, b: __m128i) -> __m128i { return transmute(__m128i)simd.add(transmute(i32x4)a, transmute(i32x4)b) } +@(enable_target_feature="sse2") _mm_add_epi64 :: #force_inline proc "c" (a, b: __m128i) -> __m128i { return transmute(__m128i)simd.add(transmute(i64x2)a, transmute(i64x2)b) } +@(enable_target_feature="sse2") _mm_adds_epi8 :: #force_inline proc "c" (a, b: __m128i) -> __m128i { return transmute(__m128i)simd.add_sat(transmute(i8x16)a, transmute(i8x16)b) } +@(enable_target_feature="sse2") _mm_adds_epi16 :: #force_inline proc "c" (a, b: __m128i) -> __m128i { return transmute(__m128i)simd.add_sat(transmute(i16x8)a, transmute(i16x8)b) } +@(enable_target_feature="sse2") _mm_adds_epu8 :: #force_inline proc "c" (a, b: __m128i) -> __m128i { return transmute(__m128i)simd.add_sat(transmute(u8x16)a, transmute(u8x16)b) } +@(enable_target_feature="sse2") _mm_adds_epu16 :: #force_inline proc "c" (a, b: __m128i) -> __m128i { return transmute(__m128i)simd.add_sat(transmute(u16x8)a, transmute(u16x8)b) } +@(enable_target_feature="sse2") _mm_avg_epu8 :: #force_inline proc "c" (a, b: __m128i) -> __m128i { return transmute(__m128i)pavgb(transmute(u8x16)a, transmute(u8x16)b) } +@(enable_target_feature="sse2") _mm_avg_epu16 :: #force_inline proc "c" (a, b: __m128i) -> __m128i { return transmute(__m128i)pavgw(transmute(u16x8)a, transmute(u16x8)b) } +@(enable_target_feature="sse2") _mm_madd_epi16 :: #force_inline proc "c" (a, b: __m128i) -> __m128i { return transmute(__m128i)pmaddwd(transmute(i16x8)a, transmute(i16x8)b) } +@(enable_target_feature="sse2") _mm_max_epi16 :: #force_inline proc "c" (a, b: __m128i) -> __m128i { return transmute(__m128i)pmaxsw(transmute(i16x8)a, transmute(i16x8)b) } +@(enable_target_feature="sse2") _mm_max_epu8 :: #force_inline proc "c" (a, b: __m128i) -> __m128i { return transmute(__m128i)pmaxub(transmute(u8x16)a, transmute(u8x16)b) } +@(enable_target_feature="sse2") _mm_min_epi16 :: #force_inline proc "c" (a, b: __m128i) -> __m128i { return transmute(__m128i)pminsw(transmute(i16x8)a, transmute(i16x8)b) } +@(enable_target_feature="sse2") _mm_min_epu8 :: #force_inline proc "c" (a, b: __m128i) -> __m128i { return transmute(__m128i)pminub(transmute(u8x16)a, transmute(u8x16)b) } +@(enable_target_feature="sse2") _mm_mulhi_epi16 :: #force_inline proc "c" (a, b: __m128i) -> __m128i { return transmute(__m128i)pmulhw(transmute(i16x8)a, transmute(i16x8)b) } +@(enable_target_feature="sse2") _mm_mulhi_epu16 :: #force_inline proc "c" (a, b: __m128i) -> __m128i { return transmute(__m128i)pmulhuw(transmute(u16x8)a, transmute(u16x8)b) } +@(enable_target_feature="sse2") _mm_mullo_epi16 :: #force_inline proc "c" (a, b: __m128i) -> __m128i { return transmute(__m128i)simd.mul(transmute(i16x8)a, transmute(i16x8)b) } +@(enable_target_feature="sse2") _mm_mul_epu32 :: #force_inline proc "c" (a, b: __m128i) -> __m128i { return transmute(__m128i)pmuludq(transmute(u32x4)a, transmute(u32x4)b) } +@(enable_target_feature="sse2") _mm_sad_epu8 :: #force_inline proc "c" (a, b: __m128i) -> __m128i { return transmute(__m128i)psadbw(transmute(u8x16)a, transmute(u8x16)b) } +@(enable_target_feature="sse2") _mm_sub_epi8 :: #force_inline proc "c" (a, b: __m128i) -> __m128i { return transmute(__m128i)simd.sub(transmute(i8x16)a, transmute(i8x16)b) } +@(enable_target_feature="sse2") _mm_sub_epi16 :: #force_inline proc "c" (a, b: __m128i) -> __m128i { return transmute(__m128i)simd.sub(transmute(i16x8)a, transmute(i16x8)b) } +@(enable_target_feature="sse2") _mm_sub_epi32 :: #force_inline proc "c" (a, b: __m128i) -> __m128i { return transmute(__m128i)simd.sub(transmute(i32x4)a, transmute(i32x4)b) } +@(enable_target_feature="sse2") _mm_sub_epi64 :: #force_inline proc "c" (a, b: __m128i) -> __m128i { return transmute(__m128i)simd.sub(transmute(i64x2)a, transmute(i64x2)b) } +@(enable_target_feature="sse2") _mm_subs_epi8 :: #force_inline proc "c" (a, b: __m128i) -> __m128i { return transmute(__m128i)simd.sub_sat(transmute(i8x16)a, transmute(i8x16)b) } +@(enable_target_feature="sse2") _mm_subs_epi16 :: #force_inline proc "c" (a, b: __m128i) -> __m128i { return transmute(__m128i)simd.sub_sat(transmute(i16x8)a, transmute(i16x8)b) } +@(enable_target_feature="sse2") _mm_subs_epu8 :: #force_inline proc "c" (a, b: __m128i) -> __m128i { return transmute(__m128i)simd.sub_sat(transmute(u8x16)a, transmute(u8x16)b) } +@(enable_target_feature="sse2") _mm_subs_epu16 :: #force_inline proc "c" (a, b: __m128i) -> __m128i { return transmute(__m128i)simd.sub_sat(transmute(u16x8)a, transmute(u16x8)b) } @@ -108,6 +140,7 @@ _mm_subs_epu16 :: #force_inline proc "c" (a, b: __m128i) -> __m128i { @(private) +@(enable_target_feature="sse2") _mm_slli_si128_impl :: #force_inline proc "c" (a: __m128i, $IMM8: u32) -> __m128i { shift :: IMM8 & 0xff @@ -134,6 +167,7 @@ _mm_slli_si128_impl :: #force_inline proc "c" (a: __m128i, $IMM8: u32) -> __m128 } @(private) +@(enable_target_feature="sse2") _mm_srli_si128_impl :: #force_inline proc "c" (a: __m128i, $IMM8: u32) -> __m128i { shift :: IMM8 return transmute(__m128i)simd.shuffle( @@ -159,203 +193,264 @@ _mm_srli_si128_impl :: #force_inline proc "c" (a: __m128i, $IMM8: u32) -> __m128 } +@(enable_target_feature="sse2") _mm_slli_si128 :: #force_inline proc "c" (a: __m128i, $IMM8: u32) -> __m128i { return _mm_slli_si128_impl(a, IMM8) } +@(enable_target_feature="sse2") _mm_bslli_si128 :: #force_inline proc "c" (a: __m128i, $IMM8: u32) -> __m128i { return _mm_slli_si128_impl(a, IMM8) } +@(enable_target_feature="sse2") _mm_bsrli_si128 :: #force_inline proc "c" (a: __m128i, $IMM8: u32) -> __m128i { return _mm_srli_si128_impl(a, IMM8) } +@(enable_target_feature="sse2") _mm_slli_epi16 :: #force_inline proc "c" (a: __m128i, $IMM8: u32) -> __m128i { return transmute(__m128i)pslliw(transmute(i16x8)a, IMM8) } +@(enable_target_feature="sse2") _mm_sll_epi16 :: #force_inline proc "c" (a, count: __m128i) -> __m128i { return transmute(__m128i)psllw(transmute(i16x8)a, transmute(i16x8)count) } +@(enable_target_feature="sse2") _mm_slli_epi32 :: #force_inline proc "c" (a: __m128i, $IMM8: u32) -> __m128i { return transmute(__m128i)psllid(transmute(i32x4)a, IMM8) } +@(enable_target_feature="sse2") _mm_sll_epi32 :: #force_inline proc "c" (a, count: __m128i) -> __m128i { return transmute(__m128i)pslld(transmute(i32x4)a, transmute(i32x4)count) } +@(enable_target_feature="sse2") _mm_slli_epi64 :: #force_inline proc "c" (a: __m128i, $IMM8: u32) -> __m128i { return transmute(__m128i)pslliq(transmute(i64x2)a, IMM8) } +@(enable_target_feature="sse2") _mm_sll_epi64 :: #force_inline proc "c" (a, count: __m128i) -> __m128i { return transmute(__m128i)psllq(transmute(i64x2)a, transmute(i64x2)count) } +@(enable_target_feature="sse2") _mm_srai_epi16 :: #force_inline proc "c" (a: __m128i, $IMM8: u32) -> __m128i { return transmute(__m128i)psraiw(transmute(i16x8)a. IMM8) } +@(enable_target_feature="sse2") _mm_sra_epi16 :: #force_inline proc "c" (a, count: __m128i) -> __m128i { return transmute(__m128i)psraw(transmute(i16x8)a, transmute(i16x8)count) } +@(enable_target_feature="sse2") _mm_srai_epi32 :: #force_inline proc "c" (a: __m128i, $IMM8: u32) -> __m128i { return transmute(__m128i)psraid(transmute(i32x4)a, IMM8) } +@(enable_target_feature="sse2") _mm_sra_epi32 :: #force_inline proc "c" (a, count: __m128i) -> __m128i { return transmute(__m128i)psrad(transmute(i32x4)a, transmute(i32x4)count) } +@(enable_target_feature="sse2") _mm_srli_si128 :: #force_inline proc "c" (a: __m128i, $IMM8: u32) -> __m128i { return _mm_srli_si128_impl(a, IMM8) } +@(enable_target_feature="sse2") _mm_srli_epi16 :: #force_inline proc "c" (a: __m128i, $IMM8: u32) -> __m128i { return transmute(__m128i)psrliw(transmute(i16x8)a. IMM8) } +@(enable_target_feature="sse2") _mm_srl_epi16 :: #force_inline proc "c" (a, count: __m128i) -> __m128i { return transmute(__m128i)psrlw(transmute(i16x8)a, transmute(i16x8)count) } +@(enable_target_feature="sse2") _mm_srli_epi32 :: #force_inline proc "c" (a: __m128i, $IMM8: u32) -> __m128i { return transmute(__m128i)psrlid(transmute(i32x4)a, IMM8) } +@(enable_target_feature="sse2") _mm_srl_epi32 :: #force_inline proc "c" (a, count: __m128i) -> __m128i { return transmute(__m128i)psrld(transmute(i32x4)a, transmute(i32x4)count) } +@(enable_target_feature="sse2") _mm_srli_epi64 :: #force_inline proc "c" (a: __m128i, $IMM8: u32) -> __m128i { return transmute(__m128i)psrliq(transmute(i64x2)a, IMM8) } +@(enable_target_feature="sse2") _mm_srl_epi64 :: #force_inline proc "c" (a, count: __m128i) -> __m128i { return transmute(__m128i)psrlq(transmute(i64x2)a, transmute(i64x2)count) } +@(enable_target_feature="sse2") _mm_and_si128 :: #force_inline proc "c" (a, b: __m128i) -> __m128i { return simd.and(a, b) } +@(enable_target_feature="sse2") _mm_andnot_si128 :: #force_inline proc "c" (a, b: __m128i) -> __m128i { return simd.and_not(b, a) } +@(enable_target_feature="sse2") _mm_or_si128 :: #force_inline proc "c" (a, b: __m128i) -> __m128i { return simd.or(a, b) } +@(enable_target_feature="sse2") _mm_xor_si128 :: #force_inline proc "c" (a, b: __m128i) -> __m128i { return simd.xor(a, b) } +@(enable_target_feature="sse2") _mm_cmpeq_epi8 :: #force_inline proc "c" (a, b: __m128i) -> __m128i { return transmute(__m128i)simd.lanes_eq(transmute(i8x16)a, transmute(i8x16)b) } +@(enable_target_feature="sse2") _mm_cmpeq_epi16 :: #force_inline proc "c" (a, b: __m128i) -> __m128i { return transmute(__m128i)simd.lanes_eq(transmute(i16x8)a, transmute(i16x8)b) } +@(enable_target_feature="sse2") _mm_cmpeq_epi32 :: #force_inline proc "c" (a, b: __m128i) -> __m128i { return transmute(__m128i)simd.lanes_eq(transmute(i32x4)a, transmute(i32x4)b) } +@(enable_target_feature="sse2") _mm_cmpgt_epi8 :: #force_inline proc "c" (a, b: __m128i) -> __m128i { return transmute(__m128i)simd.lanes_gt(transmute(i8x16)a, transmute(i8x16)b) } +@(enable_target_feature="sse2") _mm_cmpgt_epi16 :: #force_inline proc "c" (a, b: __m128i) -> __m128i { return transmute(__m128i)simd.lanes_gt(transmute(i16x8)a, transmute(i16x8)b) } +@(enable_target_feature="sse2") _mm_cmpgt_epi32 :: #force_inline proc "c" (a, b: __m128i) -> __m128i { return transmute(__m128i)simd.lanes_gt(transmute(i32x4)a, transmute(i32x4)b) } +@(enable_target_feature="sse2") _mm_cmplt_epi8 :: #force_inline proc "c" (a, b: __m128i) -> __m128i { return transmute(__m128i)simd.lanes_lt(transmute(i8x16)a, transmute(i8x16)b) } +@(enable_target_feature="sse2") _mm_cmplt_epi16 :: #force_inline proc "c" (a, b: __m128i) -> __m128i { return transmute(__m128i)simd.lanes_lt(transmute(i16x8)a, transmute(i16x8)b) } +@(enable_target_feature="sse2") _mm_cmplt_epi32 :: #force_inline proc "c" (a, b: __m128i) -> __m128i { return transmute(__m128i)simd.lanes_lt(transmute(i32x4)a, transmute(i32x4)b) } +@(enable_target_feature="sse2") _mm_cvtepi32_pd :: #force_inline proc "c" (a: __m128i) -> __m128d { v := transmute(i32x4)a return cast(__m128d)simd.shuffle(v, v, 0, 1) } +@(enable_target_feature="sse2") _mm_cvtsi32_sd :: #force_inline proc "c" (a: __m128d, b: i32) -> __m128d { return simd.replace(a, 0, f64(b)) } +@(enable_target_feature="sse2") _mm_cvtepi32_ps :: #force_inline proc "c" (a: __m128i) -> __m128 { return cvtdq2ps(transmute(i32x4)a) } +@(enable_target_feature="sse2") _mm_cvtps_epi32 :: #force_inline proc "c" (a: __m128) -> __m128i { return transmute(__m128i)cvtps2dq(a) } +@(enable_target_feature="sse2") _mm_cvtsi32_si128 :: #force_inline proc "c" (a: i32) -> __m128i { return transmute(__m128i)i32x4{a, 0, 0, 0} } +@(enable_target_feature="sse2") _mm_cvtsi128_si32 :: #force_inline proc "c" (a: __m128i) -> i32 { return simd.extract(transmute(i32x4)a, 0) } +@(enable_target_feature="sse2") _mm_set_epi64x :: #force_inline proc "c" (e1, e0: i64) -> __m128i { return transmute(__m128i)i64x2{e0, e1} } +@(enable_target_feature="sse2") _mm_set_epi32 :: #force_inline proc "c" (e3, e2, e1, e0: i32) -> __m128i { return transmute(__m128i)i32x4{e0, e1, e2, e3} } +@(enable_target_feature="sse2") _mm_set_epi16 :: #force_inline proc "c" (e7, e6, e5, e4, e3, e2, e1, e0: i16) -> __m128i { return transmute(__m128i)i16x8{e0, e1, e2, e3, e4, e5, e6, e7} } +@(enable_target_feature="sse2") _mm_set_epi8 :: #force_inline proc "c" (e15, e14, e13, e12, e11, e10, e9, e8, e7, e6, e5, e4, e3, e2, e1, e0: i8) -> __m128i { return transmute(__m128i)i8x16{e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15} } +@(enable_target_feature="sse2") _mm_set1_epi64x :: #force_inline proc "c" (a: i64) -> __m128i { return _mm_set_epi64x(a, a) } +@(enable_target_feature="sse2") _mm_set1_epi32 :: #force_inline proc "c" (a: i32) -> __m128i { return _mm_set_epi32(a, a, a, a) } +@(enable_target_feature="sse2") _mm_set1_epi16 :: #force_inline proc "c" (a: i16) -> __m128i { return _mm_set_epi16(a, a, a, a, a, a, a, a) } +@(enable_target_feature="sse2") _mm_set1_epi8 :: #force_inline proc "c" (a: i8) -> __m128i { return _mm_set_epi8(a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a) } +@(enable_target_feature="sse2") _mm_setr_epi32 :: #force_inline proc "c" (e3, e2, e1, e0: i32) -> __m128i { return _mm_set_epi32(e0, e1, e2, e3) } +@(enable_target_feature="sse2") _mm_setr_epi16 :: #force_inline proc "c" (e7, e6, e5, e4, e3, e2, e1, e0: i16) -> __m128i { return _mm_set_epi16(e0, e1, e2, e3, e4, e5, e6, e7) } +@(enable_target_feature="sse2") _mm_setr_epi8 :: #force_inline proc "c" (e15, e14, e13, e12, e11, e10, e9, e8, e7, e6, e5, e4, e3, e2, e1, e0: i8) -> __m128i { return _mm_set_epi8(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15) } +@(enable_target_feature="sse2") _mm_setzero_si128 :: #force_inline proc "c" () -> __m128i { return _mm_set1_epi64x(0) } +@(enable_target_feature="sse2") _mm_loadl_epi64 :: #force_inline proc "c" (mem_addr: ^__m128i) -> __m128i { return _mm_set_epi64x(0, intrinsics.unaligned_load((^i64)(mem_addr))) } +@(enable_target_feature="sse2") _mm_load_si128 :: #force_inline proc "c" (mem_addr: ^__m128i) -> __m128i { return mem_addr^ } +@(enable_target_feature="sse2") _mm_loadu_si128 :: #force_inline proc "c" (mem_addr: ^__m128i) -> __m128i { dst := _mm_undefined_si128() intrinsics.mem_copy_non_overlapping(&dst, mem_addr, size_of(__m128i)) return dst } +@(enable_target_feature="sse2") _mm_maskmoveu_si128 :: #force_inline proc "c" (a, mask: __m128i, mem_addr: rawptr) { maskmovdqu(transmute(i8x16)a, transmute(i8x16)mask, mem_addr) } +@(enable_target_feature="sse2") _mm_store_si128 :: #force_inline proc "c" (mem_addr: ^__m128i, a: __m128i) { mem_addr^ = a } +@(enable_target_feature="sse2") _mm_storeu_si128 :: #force_inline proc "c" (mem_addr: ^__m128i, a: __m128i) { storeudq(mem_addr, a) } +@(enable_target_feature="sse2") _mm_storel_epi64 :: #force_inline proc "c" (mem_addr: ^__m128i, a: __m128i) { a := a intrinsics.mem_copy_non_overlapping(mem_addr, &a, 8) } +@(enable_target_feature="sse2") _mm_stream_si128 :: #force_inline proc "c" (mem_addr: ^__m128i, a: __m128i) { intrinsics.non_temporal_store(mem_addr, a) } +@(enable_target_feature="sse2") _mm_stream_si32 :: #force_inline proc "c" (mem_addr: ^i32, a: i32) { intrinsics.non_temporal_store(mem_addr, a) } +@(enable_target_feature="sse2") _mm_move_epi64 :: #force_inline proc "c" (a: __m128i) -> __m128i { zero := _mm_setzero_si128() return transmute(__m128i)simd.shuffle(transmute(i64x2)a, transmute(i64x2)zero, 0, 2) @@ -364,24 +459,31 @@ _mm_move_epi64 :: #force_inline proc "c" (a: __m128i) -> __m128i { +@(enable_target_feature="sse2") _mm_packs_epi16 :: #force_inline proc "c" (a, b: __m128i) -> __m128i { return transmute(__m128i)packsswb(transmute(i16x8)a, transmute(i16x8)b) } +@(enable_target_feature="sse2") _mm_packs_epi32 :: #force_inline proc "c" (a, b: __m128i) -> __m128i { return transmute(__m128i)packssdw(transmute(i32x4)a, transmute(i32x4)b) } +@(enable_target_feature="sse2") _mm_packus_epi16 :: #force_inline proc "c" (a, b: __m128i) -> __m128i { return transmute(__m128i)packuswb(transmute(i16x8)a, transmute(i16x8)b) } +@(enable_target_feature="sse2") _mm_extract_epi16 :: #force_inline proc "c" (a: __m128i, $IMM8: u32) -> i32 { return i32(simd.extract(transmute(u16x8)a, IMM8)) } +@(enable_target_feature="sse2") _mm_insert_epi16 :: #force_inline proc "c" (a: __m128i, i: i32, $IMM8: u32) -> __m128i { return i32(simd.replace(transmute(u16x8)a, IMM8, i16(i))) } +@(enable_target_feature="sse2") _mm_movemask_epi8 :: #force_inline proc "c" (a: __m128i) -> i32 { return pmovmskb(transmute(i8x16)a) } +@(enable_target_feature="sse2") _mm_shuffle_epi32 :: #force_inline proc "c" (a: __m128i, $IMM8: u32) -> __m128i { v := transmute(i32x4)a return transmute(__m128i)simd.shuffle( @@ -393,6 +495,7 @@ _mm_shuffle_epi32 :: #force_inline proc "c" (a: __m128i, $IMM8: u32) -> __m128i (IMM8 >> 6) & 0b11, ) } +@(enable_target_feature="sse2") _mm_shufflehi_epi16 :: #force_inline proc "c" (a: __m128i, $IMM8: u32) -> __m128i { v := transmute(i16x8)a return transmute(__m128i)simd.shuffle( @@ -408,6 +511,7 @@ _mm_shufflehi_epi16 :: #force_inline proc "c" (a: __m128i, $IMM8: u32) -> __m128 ((IMM8 >> 6) & 0b11) + 4, ) } +@(enable_target_feature="sse2") _mm_shufflelo_epi16 :: #force_inline proc "c" (a: __m128i, $IMM8: u32) -> __m128i { v := transmute(i16x8)a return transmute(__m128i)simd.shuffle( @@ -423,6 +527,7 @@ _mm_shufflelo_epi16 :: #force_inline proc "c" (a: __m128i, $IMM8: u32) -> __m128 7, ) } +@(enable_target_feature="sse2") _mm_unpackhi_epi8 :: #force_inline proc "c" (a, b: __m128i) -> __m128i { return transmute(__m128i)simd.shuffle( transmute(i8x16)a, @@ -430,15 +535,19 @@ _mm_unpackhi_epi8 :: #force_inline proc "c" (a, b: __m128i) -> __m128i { 8, 24, 9, 25, 10, 26, 11, 27, 12, 28, 13, 29, 14, 30, 15, 31, ) } +@(enable_target_feature="sse2") _mm_unpackhi_epi16 :: #force_inline proc "c" (a, b: __m128i) -> __m128i { return transmute(__m128i)simd.shuffle(transmute(i16x8)a, transmute(i16x8)b, 4, 12, 5, 13, 6, 14, 7, 15) } +@(enable_target_feature="sse2") _mm_unpackhi_epi32 :: #force_inline proc "c" (a, b: __m128i) -> __m128i { return transmute(__m128i)simd.shuffle(transmute(i32x4)a, transmute(i32x4)b, 2, 6, 3, 7) } +@(enable_target_feature="sse2") _mm_unpackhi_epi64 :: #force_inline proc "c" (a, b: __m128i) -> __m128i { return transmute(__m128i)simd.shuffle(transmute(i64x2)a, transmute(i64x2)b, 1, 3) } +@(enable_target_feature="sse2") _mm_unpacklo_epi8 :: #force_inline proc "c" (a, b: __m128i) -> __m128i { return transmute(__m128i)simd.shuffle( transmute(i8x16)a, @@ -446,12 +555,15 @@ _mm_unpacklo_epi8 :: #force_inline proc "c" (a, b: __m128i) -> __m128i { 0, 16, 1, 17, 2, 18, 3, 19, 4, 20, 5, 21, 6, 22, 7, 23, ) } +@(enable_target_feature="sse2") _mm_unpacklo_epi16 :: #force_inline proc "c" (a, b: __m128i) -> __m128i { return transmute(__m128i)simd.shuffle(transmute(i16x8)a, transmute(i16x8)b, 0, 8, 1, 9, 2, 10, 3, 11) } +@(enable_target_feature="sse2") _mm_unpacklo_epi32 :: #force_inline proc "c" (a, b: __m128i) -> __m128i { return transmute(__m128i)simd.shuffle(transmute(i32x4)a, transmute(i32x4)b, 0, 4, 1, 5) } +@(enable_target_feature="sse2") _mm_unpacklo_epi64 :: #force_inline proc "c" (a, b: __m128i) -> __m128i { return transmute(__m128i)simd.shuffle(transmute(i64x2)a, transmute(i64x2)b, 0, 2) } @@ -459,57 +571,75 @@ _mm_unpacklo_epi64 :: #force_inline proc "c" (a, b: __m128i) -> __m128i { +@(enable_target_feature="sse2") _mm_add_sd :: #force_inline proc "c" (a, b: __m128d) -> __m128d { return simd.replace(a, 0, _mm_cvtsd_f64(a) + _mm_cvtsd_f64(b)) } +@(enable_target_feature="sse2") _mm_add_pd :: #force_inline proc "c" (a, b: __m128d) -> __m128d { return simd.add(a, b) } +@(enable_target_feature="sse2") _mm_div_sd :: #force_inline proc "c" (a, b: __m128d) -> __m128d { return simd.replace(a, 0, _mm_cvtsd_f64(a) / _mm_cvtsd_f64(b)) } +@(enable_target_feature="sse2") _mm_div_pd :: #force_inline proc "c" (a, b: __m128d) -> __m128d { return simd.div(a, b) } +@(enable_target_feature="sse2") _mm_max_sd :: #force_inline proc "c" (a, b: __m128d) -> __m128d { return maxsd(a, b) } +@(enable_target_feature="sse2") _mm_max_pd :: #force_inline proc "c" (a, b: __m128d) -> __m128d { return maxpd(a, b) } +@(enable_target_feature="sse2") _mm_min_sd :: #force_inline proc "c" (a, b: __m128d) -> __m128d { return minsd(a, b) } +@(enable_target_feature="sse2") _mm_min_pd :: #force_inline proc "c" (a, b: __m128d) -> __m128d { return minpd(a, b) } +@(enable_target_feature="sse2") _mm_mul_sd :: #force_inline proc "c" (a, b: __m128d) -> __m128d { return simd.replace(a, 0, _mm_cvtsd_f64(a) * _mm_cvtsd_f64(b)) } +@(enable_target_feature="sse2") _mm_mul_pd :: #force_inline proc "c" (a, b: __m128d) -> __m128d { return simd.mul(a, b) } +@(enable_target_feature="sse2") _mm_sqrt_sd :: #force_inline proc "c" (a, b: __m128d) -> __m128d { return simd.replace(a, 0, _mm_cvtsd_f64(sqrtsd(b))) } +@(enable_target_feature="sse2") _mm_sqrt_pd :: #force_inline proc "c" (a: __m128d) -> __m128d { return simd.sqrt(a) } +@(enable_target_feature="sse2") _mm_sub_sd :: #force_inline proc "c" (a, b: __m128d) -> __m128d { return simd.replace(a, 0, _mm_cvtsd_f64(a) - _mm_cvtsd_f64(b)) } +@(enable_target_feature="sse2") _mm_sub_pd :: #force_inline proc "c" (a, b: __m128d) -> __m128d { return simd.sub(a, b) } +@(enable_target_feature="sse2") _mm_and_pd :: #force_inline proc "c" (a, b: __m128d) -> __m128d { return transmute(__m128d)_mm_and_si128(transmute(__m128i)a, transmute(__m128i)b) } +@(enable_target_feature="sse2") _mm_andnot_pd :: #force_inline proc "c" (a, b: __m128d) -> __m128d { return transmute(__m128d)_mm_andnot_si128(transmute(__m128i)a, transmute(__m128i)b) } +@(enable_target_feature="sse2") _mm_or_pd :: #force_inline proc "c" (a, b: __m128d) -> __m128d { return transmute(__m128d)_mm_or_si128(transmute(__m128i)a, transmute(__m128i)b) } +@(enable_target_feature="sse2") _mm_xor_pd :: #force_inline proc "c" (a, b: __m128d) -> __m128d { return transmute(__m128d)_mm_xor_si128(transmute(__m128i)a, transmute(__m128i)b) } @@ -517,111 +647,147 @@ _mm_xor_pd :: #force_inline proc "c" (a, b: __m128d) -> __m128d { +@(enable_target_feature="sse2") _mm_cmpeq_sd :: #force_inline proc "c" (a, b: __m128d) -> __m128d { return cmpsd(a, b, 0) } +@(enable_target_feature="sse2") _mm_cmplt_sd :: #force_inline proc "c" (a, b: __m128d) -> __m128d { return cmpsd(a, b, 1) } +@(enable_target_feature="sse2") _mm_cmple_sd :: #force_inline proc "c" (a, b: __m128d) -> __m128d { return cmpsd(a, b, 2) } +@(enable_target_feature="sse2") _mm_cmpgt_sd :: #force_inline proc "c" (a, b: __m128d) -> __m128d { return simd.replace(_mm_cmplt_sd(b, a), 1, simd.extract(a, 1)) } +@(enable_target_feature="sse2") _mm_cmpge_sd :: #force_inline proc "c" (a, b: __m128d) -> __m128d { return simd.replace(_mm_cmple_sd(b, a), 1, simd.extract(a, 1)) } +@(enable_target_feature="sse2") _mm_cmpord_sd :: #force_inline proc "c" (a, b: __m128d) -> __m128d { return cmpsd(a, b, 7) } +@(enable_target_feature="sse2") _mm_cmpunord_sd :: #force_inline proc "c" (a, b: __m128d) -> __m128d { return cmpsd(a, b, 3) } +@(enable_target_feature="sse2") _mm_cmpneq_sd :: #force_inline proc "c" (a, b: __m128d) -> __m128d { return cmpsd(a, b, 4) } +@(enable_target_feature="sse2") _mm_cmpnlt_sd :: #force_inline proc "c" (a, b: __m128d) -> __m128d { return cmpsd(a, b, 5) } +@(enable_target_feature="sse2") _mm_cmpnle_sd :: #force_inline proc "c" (a, b: __m128d) -> __m128d { return cmpsd(a, b, 6) } +@(enable_target_feature="sse2") _mm_cmpngt_sd :: #force_inline proc "c" (a, b: __m128d) -> __m128d { return simd.replace(_mm_cmpnlt_sd(b, a), 1, simd.extract(a, 1)) } +@(enable_target_feature="sse2") _mm_cmpnge_sd :: #force_inline proc "c" (a, b: __m128d) -> __m128d { return simd.replace(_mm_cmpnle_sd(b, a), 1, simd.extract(a, 1)) } +@(enable_target_feature="sse2") _mm_cmpeq_pd :: #force_inline proc "c" (a, b: __m128d) -> __m128d { return cmppd(a, b, 0) } +@(enable_target_feature="sse2") _mm_cmplt_pd :: #force_inline proc "c" (a, b: __m128d) -> __m128d { return cmppd(a, b, 1) } +@(enable_target_feature="sse2") _mm_cmple_pd :: #force_inline proc "c" (a, b: __m128d) -> __m128d { return cmppd(a, b, 2) } +@(enable_target_feature="sse2") _mm_cmpgt_pd :: #force_inline proc "c" (a, b: __m128d) -> __m128d { return _mm_cmplt_pd(b, a) } +@(enable_target_feature="sse2") _mm_cmpge_pd :: #force_inline proc "c" (a, b: __m128d) -> __m128d { return _mm_cmple_pd(b, a) } +@(enable_target_feature="sse2") _mm_cmpord_pd :: #force_inline proc "c" (a, b: __m128d) -> __m128d { return cmppd(a, b, 7) } +@(enable_target_feature="sse2") _mm_cmpunord_pd :: #force_inline proc "c" (a, b: __m128d) -> __m128d { return cmppd(a, b, 3) } +@(enable_target_feature="sse2") _mm_cmpneq_pd :: #force_inline proc "c" (a, b: __m128d) -> __m128d { return cmppd(a, b, 4) } +@(enable_target_feature="sse2") _mm_cmpnlt_pd :: #force_inline proc "c" (a, b: __m128d) -> __m128d { return cmppd(a, b, 5) } +@(enable_target_feature="sse2") _mm_cmpnle_pd :: #force_inline proc "c" (a, b: __m128d) -> __m128d { return cmppd(a, b, 6) } +@(enable_target_feature="sse2") _mm_cmpngt_pd :: #force_inline proc "c" (a, b: __m128d) -> __m128d { return _mm_cmpnlt_pd(b, a) } +@(enable_target_feature="sse2") _mm_cmpnge_pd :: #force_inline proc "c" (a, b: __m128d) -> __m128d { return _mm_cmpnle_pd(b, a) } +@(enable_target_feature="sse2") _mm_comieq_sd :: #force_inline proc "c" (a, b: __m128d) -> i32 { return comieqsd(a, b) } +@(enable_target_feature="sse2") _mm_comilt_sd :: #force_inline proc "c" (a, b: __m128d) -> i32 { return comiltsd(a, b) } +@(enable_target_feature="sse2") _mm_comile_sd :: #force_inline proc "c" (a, b: __m128d) -> i32 { return comilesd(a, b) } +@(enable_target_feature="sse2") _mm_comigt_sd :: #force_inline proc "c" (a, b: __m128d) -> i32 { return comigtsd(a, b) } +@(enable_target_feature="sse2") _mm_comige_sd :: #force_inline proc "c" (a, b: __m128d) -> i32 { return comigesd(a, b) } +@(enable_target_feature="sse2") _mm_comineq_sd :: #force_inline proc "c" (a, b: __m128d) -> i32 { return comineqsd(a, b) } +@(enable_target_feature="sse2") _mm_ucomieq_sd :: #force_inline proc "c" (a, b: __m128d) -> i32 { return ucomieqsd(a, b) } +@(enable_target_feature="sse2") _mm_ucomilt_sd :: #force_inline proc "c" (a, b: __m128d) -> i32 { return ucomiltsd(a, b) } +@(enable_target_feature="sse2") _mm_ucomile_sd :: #force_inline proc "c" (a, b: __m128d) -> i32 { return ucomilesd(a, b) } +@(enable_target_feature="sse2") _mm_ucomigt_sd :: #force_inline proc "c" (a, b: __m128d) -> i32 { return ucomigtsd(a, b) } +@(enable_target_feature="sse2") _mm_ucomige_sd :: #force_inline proc "c" (a, b: __m128d) -> i32 { return ucomigesd(a, b) } +@(enable_target_feature="sse2") _mm_ucomineq_sd :: #force_inline proc "c" (a, b: __m128d) -> i32 { return ucomineqsd(a, b) } @@ -630,115 +796,151 @@ _mm_ucomineq_sd :: #force_inline proc "c" (a, b: __m128d) -> i32 { +@(enable_target_feature="sse2") _mm_cvtpd_ps :: #force_inline proc "c" (a: __m128d) -> __m128 { return cvtpd2ps(a) } +@(enable_target_feature="sse2") _mm_cvtps_pd :: #force_inline proc "c" (a: __m128) -> __m128d { return cvtps2pd(a) } +@(enable_target_feature="sse2") _mm_cvtpd_epi32 :: #force_inline proc "c" (a: __m128d) -> __m128i { return transmute(__m128i)cvtpd2dq(a) } +@(enable_target_feature="sse2") _mm_cvtsd_si32 :: #force_inline proc "c" (a: __m128d) -> i32 { return cvtsd2si(a) } +@(enable_target_feature="sse2") _mm_cvtsd_ss :: #force_inline proc "c" (a, b: __m128d) -> __m128 { return cvtsd2ss(a, b) } +@(enable_target_feature="sse2") _mm_cvtsd_f64 :: #force_inline proc "c" (a: __m128d) -> f64 { return simd.extract(a, 0) } +@(enable_target_feature="sse2") _mm_cvtss_sd :: #force_inline proc "c" (a, b: __m128) -> __m128d { return cvtss2sd(a, b) } +@(enable_target_feature="sse2") _mm_cvttpd_epi32 :: #force_inline proc "c" (a: __m128d) -> __m128i { return transmute(__m128i)cvttpd2dq(a) } +@(enable_target_feature="sse2") _mm_cvttsd_si32 :: #force_inline proc "c" (a: __m128d) -> i32 { return cvttsd2si(a) } +@(enable_target_feature="sse2") _mm_cvttps_epi32 :: #force_inline proc "c" (a: __m128) -> __m128i { return transmute(__m128i)cvttps2dq(a) } +@(enable_target_feature="sse2") _mm_set_sd :: #force_inline proc "c" (a: f64) -> __m128d { return _mm_set_pd(0.0, a) } +@(enable_target_feature="sse2") _mm_set1_pd :: #force_inline proc "c" (a: f64) -> __m128d { return _mm_set_pd(a, a) } +@(enable_target_feature="sse2") _mm_set_pd1 :: #force_inline proc "c" (a: f64) -> __m128d { return _mm_set_pd(a, a) } +@(enable_target_feature="sse2") _mm_set_pd :: #force_inline proc "c" (a: f64, b: f64) -> __m128d { return __m128d{b, a} } +@(enable_target_feature="sse2") _mm_setr_pd :: #force_inline proc "c" (a: f64, b: f64) -> __m128d { return _mm_set_pd(b, a) } +@(enable_target_feature="sse2") _mm_setzero_pd :: #force_inline proc "c" () -> __m128d { return _mm_set_pd(0.0, 0.0) } +@(enable_target_feature="sse2") _mm_movemask_pd :: #force_inline proc "c" (a: __m128d) -> i32 { return movmskpd(a) } +@(enable_target_feature="sse2") _mm_load_pd :: #force_inline proc "c" (mem_addr: ^f64) -> __m128d { return (^__m128d)(mem_addr)^ } +@(enable_target_feature="sse2") _mm_load_sd :: #force_inline proc "c" (mem_addr: ^f64) -> __m128d { return _mm_setr_pd(mem_addr^, 0.) } +@(enable_target_feature="sse2") _mm_loadh_pd :: #force_inline proc "c" (a: __m128d, mem_addr: ^f64) -> __m128d { return _mm_setr_pd(simd.extract(a, 0), mem_addr^) } +@(enable_target_feature="sse2") _mm_loadl_pd :: #force_inline proc "c" (a: __m128d, mem_addr: ^f64) -> __m128d { return _mm_setr_pd(mem_addr^, simd.extract(a, 1)) } +@(enable_target_feature="sse2") _mm_stream_pd :: #force_inline proc "c" (mem_addr: ^f64, a: __m128d) { intrinsics.non_temporal_store((^__m128d)(mem_addr), a) } +@(enable_target_feature="sse2") _mm_store_sd :: #force_inline proc "c" (mem_addr: ^f64, a: __m128d) { mem_addr^ = simd.extract(a, 0) } +@(enable_target_feature="sse2") _mm_store_pd :: #force_inline proc "c" (mem_addr: ^f64, a: __m128d) { (^__m128d)(mem_addr)^ = a } +@(enable_target_feature="sse2") _mm_storeu_pd :: #force_inline proc "c" (mem_addr: ^f64, a: __m128d) { storeupd(mem_addr, a) } +@(enable_target_feature="sse2") _mm_store1_pd :: #force_inline proc "c" (mem_addr: ^f64, a: __m128d) { (^__m128d)(mem_addr)^ = simd.shuffle(a, a, 0, 0) } +@(enable_target_feature="sse2") _mm_store_pd1 :: #force_inline proc "c" (mem_addr: ^f64, a: __m128d) { (^__m128d)(mem_addr)^ = simd.shuffle(a, a, 0, 0) } +@(enable_target_feature="sse2") _mm_storer_pd :: #force_inline proc "c" (mem_addr: ^f64, a: __m128d) { (^__m128d)(mem_addr)^ = simd.shuffle(a, a, 1, 0) } +@(enable_target_feature="sse2") _mm_storeh_pd :: #force_inline proc "c" (mem_addr: ^f64, a: __m128d) { mem_addr^ = simd.extract(a, 1) } +@(enable_target_feature="sse2") _mm_storel_pd :: #force_inline proc "c" (mem_addr: ^f64, a: __m128d) { mem_addr^ = simd.extract(a, 0) } +@(enable_target_feature="sse2") _mm_load1_pd :: #force_inline proc "c" (mem_addr: ^f64) -> __m128d { d := mem_addr^ return _mm_setr_pd(d, d) } +@(enable_target_feature="sse2") _mm_load_pd1 :: #force_inline proc "c" (mem_addr: ^f64) -> __m128d { return _mm_load1_pd(mem_addr) } +@(enable_target_feature="sse2") _mm_loadr_pd :: #force_inline proc "c" (mem_addr: ^f64) -> __m128d { a := _mm_load_pd(mem_addr) return simd.shuffle(a, a, 1, 0) } +@(enable_target_feature="sse2") _mm_loadu_pd :: #force_inline proc "c" (mem_addr: ^f64) -> __m128d { dst := _mm_undefined_pd() intrinsics.mem_copy_non_overlapping(&dst, mem_addr, size_of(__m128d)) return dst } +@(enable_target_feature="sse2") _mm_shuffle_pd :: #force_inline proc "c" (a, b: __m128d, $MASK: u32) -> __m128d { return simd.shuffle(a, b, MASK&0b1, ((MASK>>1)&0b1) + 2) } +@(enable_target_feature="sse2") _mm_move_sd :: #force_inline proc "c" (a, b: __m128d) -> __m128d { return _mm_setr_pd(simd.extract(b, 0), simd.extract(a, 1)) } @@ -746,71 +948,92 @@ _mm_move_sd :: #force_inline proc "c" (a, b: __m128d) -> __m128d { +@(enable_target_feature="sse2") _mm_castpd_ps :: #force_inline proc "c" (a: __m128d) -> __m128 { return transmute(__m128)a } +@(enable_target_feature="sse2") _mm_castpd_si128 :: #force_inline proc "c" (a: __m128d) -> __m128i { return transmute(__m128i)a } +@(enable_target_feature="sse2") _mm_castps_pd :: #force_inline proc "c" (a: __m128) -> __m128d { return transmute(__m128d)a } +@(enable_target_feature="sse2") _mm_castps_si128 :: #force_inline proc "c" (a: __m128) -> __m128i { return transmute(__m128i)a } +@(enable_target_feature="sse2") _mm_castsi128_pd :: #force_inline proc "c" (a: __m128i) -> __m128d { return transmute(__m128d)a } +@(enable_target_feature="sse2") _mm_castsi128_ps :: #force_inline proc "c" (a: __m128i) -> __m128 { return transmute(__m128)a } +@(enable_target_feature="sse2") _mm_undefined_pd :: #force_inline proc "c" () -> __m128d { return __m128d{0, 0} } +@(enable_target_feature="sse2") _mm_undefined_si128 :: #force_inline proc "c" () -> __m128i { return __m128i{0, 0} } +@(enable_target_feature="sse2") _mm_unpackhi_pd :: #force_inline proc "c" (a, b: __m128d) -> __m128d { return simd.shuffle(a, b, 1, 3) } +@(enable_target_feature="sse2") _mm_unpacklo_pd :: #force_inline proc "c" (a, b: __m128d) -> __m128d { return simd.shuffle(a, b, 0, 2) } when ODIN_ARCH == .amd64 { + @(enable_target_feature="sse2") _mm_cvtsd_si64 :: #force_inline proc "c" (a: __m128d) -> i64 { return cvtsd2si64(a) } + @(enable_target_feature="sse2") _mm_cvtsd_si64x :: #force_inline proc "c" (a: __m128d) -> i64 { return _mm_cvtsd_si64(a) } + @(enable_target_feature="sse2") _mm_cvttsd_si64 :: #force_inline proc "c" (a: __m128d) -> i64 { return cvttsd2si64(a) } + @(enable_target_feature="sse2") _mm_cvttsd_si64x :: #force_inline proc "c" (a: __m128d) -> i64 { return _mm_cvttsd_si64(a) } + @(enable_target_feature="sse2") _mm_stream_si64 :: #force_inline proc "c" (mem_addr: ^i64, a: i64) { intrinsics.non_temporal_store(mem_addr, a) } + @(enable_target_feature="sse2") _mm_cvtsi64_si128 :: #force_inline proc "c" (a: i64) -> __m128i { return _mm_set_epi64x(0, a) } + @(enable_target_feature="sse2") _mm_cvtsi64x_si128 :: #force_inline proc "c" (a: i64) -> __m128i { return _mm_cvtsi64_si128(a) } + @(enable_target_feature="sse2") _mm_cvtsi128_si64 :: #force_inline proc "c" (a: __m128i) -> i64 { return simd.extract(transmute(i64x2)a, 0) } + @(enable_target_feature="sse2") _mm_cvtsi128_si64x :: #force_inline proc "c" (a: __m128i) -> i64 { return _mm_cvtsi128_si64(a) } + @(enable_target_feature="sse2") _mm_cvtsi64_sd :: #force_inline proc "c" (a: __m128d, b: i64) -> __m128d { return simd.replace(a, 0, f64(b)) } + @(enable_target_feature="sse2") _mm_cvtsi64x_sd :: #force_inline proc "c" (a: __m128d, b: i64) -> __m128d { return _mm_cvtsi64_sd(a, b) } diff --git a/core/simd/x86/sse3.odin b/core/simd/x86/sse3.odin index 9766a43e6..370bfa952 100644 --- a/core/simd/x86/sse3.odin +++ b/core/simd/x86/sse3.odin @@ -4,36 +4,47 @@ package simd_x86 import "core:intrinsics" import "core:simd" +@(enable_target_feature="sse3") _mm_addsub_ps :: #force_inline proc "c" (a, b: __m128) -> __m128 { return addsubps(a, b) } +@(enable_target_feature="sse3") _mm_addsub_pd :: #force_inline proc "c" (a: __m128d, b: __m128d) -> __m128d { return addsubpd(a, b) } +@(enable_target_feature="sse3") _mm_hadd_pd :: #force_inline proc "c" (a: __m128d, b: __m128d) -> __m128d { return haddpd(a, b) } +@(enable_target_feature="sse3") _mm_hadd_ps :: #force_inline proc "c" (a, b: __m128) -> __m128 { return haddps(a, b) } +@(enable_target_feature="sse3") _mm_hsub_pd :: #force_inline proc "c" (a: __m128d, b: __m128d) -> __m128d { return hsubpd(a, b) } +@(enable_target_feature="sse3") _mm_hsub_ps :: #force_inline proc "c" (a, b: __m128) -> __m128 { return hsubps(a, b) } +@(enable_target_feature="sse3") _mm_lddqu_si128 :: #force_inline proc "c" (mem_addr: ^__m128i) -> __m128i { return transmute(__m128i)lddqu(mem_addr) } +@(enable_target_feature="sse3") _mm_movedup_pd :: #force_inline proc "c" (a: __m128d) -> __m128d { return simd.shuffle(a, a, 0, 0) } +@(enable_target_feature="sse3") _mm_loaddup_pd :: #force_inline proc "c" (mem_addr: [^]f64) -> __m128d { return _mm_load1_pd(mem_addr) } +@(enable_target_feature="sse3") _mm_movehdup_ps :: #force_inline proc "c" (a: __m128) -> __m128 { return simd.shuffle(a, a, 1, 1, 3, 3) } +@(enable_target_feature="sse3") _mm_moveldup_ps :: #force_inline proc "c" (a: __m128) -> __m128 { return simd.shuffle(a, a, 0, 0, 2, 2) } diff --git a/core/simd/x86/ssse3.odin b/core/simd/x86/ssse3.odin index 6c6f28008..8c677aed4 100644 --- a/core/simd/x86/ssse3.odin +++ b/core/simd/x86/ssse3.odin @@ -5,18 +5,23 @@ import "core:intrinsics" import "core:simd" _ :: simd +@(enable_target_feature="ssse3") _mm_abs_epi8 :: #force_inline proc "c" (a: __m128i) -> __m128i { return transmute(__m128i)pabsb128(transmute(i8x16)a) } +@(enable_target_feature="ssse3") _mm_abs_epi16 :: #force_inline proc "c" (a: __m128i) -> __m128i { return transmute(__m128i)pabsw128(transmute(i16x8)a) } +@(enable_target_feature="ssse3") _mm_abs_epi32 :: #force_inline proc "c" (a: __m128i) -> __m128i { return transmute(__m128i)pabsd128(transmute(i32x4)a) } +@(enable_target_feature="ssse3") _mm_shuffle_epi8 :: #force_inline proc "c" (a, b: __m128i) -> __m128i { return transmute(__m128i)pshufb128(transmute(u8x16)a, transmute(u8x16)b) } +@(enable_target_feature="ssse3") _mm_alignr_epi8 :: #force_inline proc "c" (a, b: __m128i, $IMM8: u32) -> __m128i { shift :: IMM8 @@ -53,36 +58,47 @@ _mm_alignr_epi8 :: #force_inline proc "c" (a, b: __m128i, $IMM8: u32) -> __m128i } +@(enable_target_feature="ssse3") _mm_hadd_epi16 :: #force_inline proc "c" (a, b: __m128i) -> __m128i { return transmute(__m128i)phaddw128(transmute(i16x8)a, transmute(i16x8)b) } +@(enable_target_feature="ssse3") _mm_hadds_epi16 :: #force_inline proc "c" (a, b: __m128i) -> __m128i { return transmute(__m128i)phaddsw128(transmute(i16x8)a, transmute(i16x8)b) } +@(enable_target_feature="ssse3") _mm_hadd_epi32 :: #force_inline proc "c" (a, b: __m128i) -> __m128i { return transmute(__m128i)phaddd128(transmute(i32x4)a, transmute(i32x4)b) } +@(enable_target_feature="ssse3") _mm_hsub_epi16 :: #force_inline proc "c" (a, b: __m128i) -> __m128i { return transmute(__m128i)phsubw128(transmute(i16x8)a, transmute(i16x8)b) } +@(enable_target_feature="ssse3") _mm_hsubs_epi16 :: #force_inline proc "c" (a, b: __m128i) -> __m128i { return transmute(__m128i)phsubsw128(transmute(i16x8)a, transmute(i16x8)b) } +@(enable_target_feature="ssse3") _mm_hsub_epi32 :: #force_inline proc "c" (a, b: __m128i) -> __m128i { return transmute(__m128i)phsubd128(transmute(i32x4)a, transmute(i32x4)b) } +@(enable_target_feature="ssse3") _mm_maddubs_epi16 :: #force_inline proc "c" (a, b: __m128i) -> __m128i { return transmute(__m128i)pmaddubsw128(transmute(u8x16)a, transmute(i8x16)b) } +@(enable_target_feature="ssse3") _mm_mulhrs_epi16 :: #force_inline proc "c" (a, b: __m128i) -> __m128i { return transmute(__m128i)pmulhrsw128(transmute(i16x8)a, transmute(i16x8)b) } +@(enable_target_feature="ssse3") _mm_sign_epi8 :: #force_inline proc "c" (a, b: __m128i) -> __m128i { return transmute(__m128i)psignb128(transmute(i8x16)a, transmute(i8x16)b) } +@(enable_target_feature="ssse3") _mm_sign_epi16 :: #force_inline proc "c" (a, b: __m128i) -> __m128i { return transmute(__m128i)psignw128(transmute(i16x8)a, transmute(i16x8)b) } +@(enable_target_feature="ssse3") _mm_sign_epi32 :: #force_inline proc "c" (a, b: __m128i) -> __m128i { return transmute(__m128i)psignd128(transmute(i32x4)a, transmute(i32x4)b) } diff --git a/src/build_settings.cpp b/src/build_settings.cpp index 27e09a0db..65470749f 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -256,7 +256,6 @@ struct BuildContext { String extra_linker_flags; String extra_assembler_flags; String microarch; - String target_features; BuildModeKind build_mode; bool generate_docs; i32 optimization_level; @@ -320,6 +319,10 @@ struct BuildContext { PtrMap defined_values; + BlockingMutex target_features_mutex; + StringSet target_features_set; + String target_features_string; + }; gb_global BuildContext build_context = {0}; @@ -1197,6 +1200,100 @@ void init_build_context(TargetMetrics *cross_target) { #include "microsoft_craziness.h" #endif + +Array split_by_comma(String const &list) { + isize n = 1; + for (isize i = 0; i < list.len; i++) { + if (list.text[i] == ',') { + n++; + } + } + auto res = array_make(heap_allocator(), n); + + String s = list; + for (isize i = 0; i < n; i++) { + isize m = string_index_byte(s, ','); + if (m < 0) { + res[i] = s; + break; + } + res[i] = substring(s, 0, m); + s = substring(s, m+1, s.len); + } + return res; +} + +bool check_target_feature_is_valid(TokenPos pos, String const &feature) { + // TODO(bill): check_target_feature_is_valid + return true; +} + +bool check_target_feature_is_enabled(TokenPos pos, String const &target_feature_list) { + BuildContext *bc = &build_context; + mutex_lock(&bc->target_features_mutex); + defer (mutex_unlock(&bc->target_features_mutex)); + + auto items = split_by_comma(target_feature_list); + array_free(&items); + for_array(i, items) { + String const &item = items.data[i]; + if (!check_target_feature_is_valid(pos, item)) { + error(pos, "Target feature '%.*s' is not valid", LIT(item)); + return false; + } + if (!string_set_exists(&bc->target_features_set, item)) { + error(pos, "Target feature '%.*s' is not enabled", LIT(item)); + return false; + } + } + + return true; +} + +void enable_target_feature(TokenPos pos, String const &target_feature_list) { + BuildContext *bc = &build_context; + mutex_lock(&bc->target_features_mutex); + defer (mutex_unlock(&bc->target_features_mutex)); + + auto items = split_by_comma(target_feature_list); + array_free(&items); + for_array(i, items) { + String const &item = items.data[i]; + if (!check_target_feature_is_valid(pos, item)) { + error(pos, "Target feature '%.*s' is not valid", LIT(item)); + } + } +} + + +char const *target_features_set_to_cstring(gbAllocator allocator, bool with_quotes) { + isize len = 0; + for_array(i, build_context.target_features_set.entries) { + if (i != 0) { + len += 1; + } + String feature = build_context.target_features_set.entries[i].value; + len += feature.len; + if (with_quotes) len += 2; + } + char *features = gb_alloc_array(allocator, char, len+1); + len = 0; + for_array(i, build_context.target_features_set.entries) { + if (i != 0) { + features[len++] = ','; + } + + if (with_quotes) features[len++] = '"'; + String feature = build_context.target_features_set.entries[i].value; + gb_memmove(features, feature.text, feature.len); + len += feature.len; + if (with_quotes) features[len++] = '"'; + } + features[len++] = 0; + + return features; +} + // NOTE(Jeroen): Set/create the output and other paths and report an error as appropriate. // We've previously called `parse_build_flags`, so `out_filepath` should be set. bool init_build_paths(String init_filename) { @@ -1206,6 +1303,9 @@ bool init_build_paths(String init_filename) { // NOTE(Jeroen): We're pre-allocating BuildPathCOUNT slots so that certain paths are always at the same enumerated index. array_init(&bc->build_paths, permanent_allocator(), BuildPathCOUNT); + string_set_init(&bc->target_features_set, heap_allocator(), 1024); + mutex_init(&bc->target_features_mutex); + // [BuildPathMainPackage] Turn given init path into a `Path`, which includes normalizing it into a full path. bc->build_paths[BuildPath_Main_Package] = path_from_string(ha, init_filename); @@ -1382,5 +1482,10 @@ bool init_build_paths(String init_filename) { return false; } + if (bc->target_features_string.len != 0) { + enable_target_feature({}, bc->target_features_string); + } + return true; -} \ No newline at end of file +} + diff --git a/src/check_decl.cpp b/src/check_decl.cpp index 62a1e2555..d4818892b 100644 --- a/src/check_decl.cpp +++ b/src/check_decl.cpp @@ -899,6 +899,18 @@ void check_proc_decl(CheckerContext *ctx, Entity *e, DeclInfo *d) { } } + if (ac.require_target_feature.len != 0 && ac.enable_target_feature.len != 0) { + error(e->token, "Attributes @(require_target_feature=...) and @(enable_target_feature=...) cannot be used together"); + } else if (ac.require_target_feature.len != 0) { + if (check_target_feature_is_enabled(e->token.pos, ac.require_target_feature)) { + e->Procedure.target_feature = ac.require_target_feature; + } else { + e->Procedure.target_feature_disabled = true; + } + } else if (ac.enable_target_feature.len != 0) { + enable_target_feature(e->token.pos, ac.enable_target_feature); + e->Procedure.target_feature = ac.enable_target_feature; + } switch (e->Procedure.optimization_mode) { case ProcedureOptimizationMode_None: diff --git a/src/checker.cpp b/src/checker.cpp index 8afc6eb14..874839ece 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -3207,6 +3207,22 @@ DECL_ATTRIBUTE_PROC(proc_decl_attribute) { } } return true; + } else if (name == "require_target_feature") { + ExactValue ev = check_decl_attribute_value(c, value); + if (ev.kind == ExactValue_String) { + ac->require_target_feature = ev.value_string; + } else { + error(elem, "Expected a string value for '%.*s'", LIT(name)); + } + return true; + } else if (name == "enable_target_feature") { + ExactValue ev = check_decl_attribute_value(c, value); + if (ev.kind == ExactValue_String) { + ac->enable_target_feature = ev.value_string; + } else { + error(elem, "Expected a string value for '%.*s'", LIT(name)); + } + return true; } return false; } diff --git a/src/checker.hpp b/src/checker.hpp index 1c9ffd8c7..8fc9e54c8 100644 --- a/src/checker.hpp +++ b/src/checker.hpp @@ -124,6 +124,9 @@ struct AttributeContext { String objc_name; bool objc_is_class_method; Type * objc_type; + + String require_target_feature; // required by the target micro-architecture + String enable_target_feature; // will be enabled for the procedure only }; AttributeContext make_attribute_context(String link_prefix) { diff --git a/src/entity.cpp b/src/entity.cpp index 904a630fb..76e6912b9 100644 --- a/src/entity.cpp +++ b/src/entity.cpp @@ -233,10 +233,12 @@ struct Entity { String link_name; String link_prefix; DeferredProcedure deferred_procedure; - bool is_foreign; - bool is_export; - bool generated_from_polymorphic; ProcedureOptimizationMode optimization_mode; + bool is_foreign : 1; + bool is_export : 1; + bool generated_from_polymorphic : 1; + bool target_feature_disabled : 1; + String target_feature; } Procedure; struct { Array entities; diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index 7cf588853..cf7389ec1 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -1332,8 +1332,8 @@ void lb_generate_code(lbGenerator *gen) { } } - if (build_context.target_features.len != 0) { - llvm_features = alloc_cstring(permanent_allocator(), build_context.target_features); + if (build_context.target_features_set.entries.count != 0) { + llvm_features = target_features_set_to_cstring(permanent_allocator(), false); } // GB_ASSERT_MSG(LLVMTargetHasAsmBackend(target)); diff --git a/src/llvm_backend_proc.cpp b/src/llvm_backend_proc.cpp index 1e3591bf1..296a7fa6b 100644 --- a/src/llvm_backend_proc.cpp +++ b/src/llvm_backend_proc.cpp @@ -169,6 +169,19 @@ lbProcedure *lb_create_procedure(lbModule *m, Entity *entity, bool ignore_body) } } + if (!entity->Procedure.target_feature_disabled && + entity->Procedure.target_feature.len != 0) { + auto features = split_by_comma(entity->Procedure.target_feature); + for_array(i, features) { + String feature = features[i]; + LLVMAttributeRef ref = LLVMCreateStringAttribute( + m->ctx, + cast(char const *)feature.text, cast(unsigned)feature.len, + "", 0); + LLVMAddAttributeAtIndex(p->value, LLVMAttributeIndex_FunctionIndex, ref); + } + } + if (entity->flags & EntityFlag_Cold) { lb_add_attribute_to_proc(m, p->value, "cold"); } diff --git a/src/main.cpp b/src/main.cpp index 13c8bd74d..ee71b91df 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1376,8 +1376,8 @@ bool parse_build_flags(Array args) { } case BuildFlag_TargetFeatures: { GB_ASSERT(value.kind == ExactValue_String); - build_context.target_features = value.value_string; - string_to_lower(&build_context.target_features); + build_context.target_features_string = value.value_string; + string_to_lower(&build_context.target_features_string); break; } case BuildFlag_RelocMode: { diff --git a/src/string.cpp b/src/string.cpp index 616761265..44eccd2d2 100644 --- a/src/string.cpp +++ b/src/string.cpp @@ -157,6 +157,15 @@ int string_compare(String const &x, String const &y) { return 0; } +isize string_index_byte(String const &s, u8 x) { + for (isize i = 0; i < s.len; i++) { + if (s.text[i] == x) { + return i; + } + } + return -1; +} + GB_COMPARE_PROC(string_cmp_proc) { String x = *(String *)a; String y = *(String *)b; -- cgit v1.2.3