From df23cf47c69877e69b75d109e4da58e782070ac8 Mon Sep 17 00:00:00 2001 From: CiD- Date: Wed, 16 Feb 2022 22:08:39 -0500 Subject: [PATCH 01/56] fix odin test --- src/llvm_backend.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index 52c46cadc..c777819c3 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -1694,6 +1694,11 @@ void lb_generate_code(lbGenerator *gen) { } } + if (build_context.command_kind == Command_test && !already_has_entry_point) { + TIME_SECTION("LLVM main"); + lb_create_main_procedure(default_module, startup_runtime); + } + for_array(j, gen->modules.entries) { lbModule *m = gen->modules.entries[j].value; for_array(i, m->missing_procedures_to_check) { From bea2f3644325454e7fe0e12313528359d0782843 Mon Sep 17 00:00:00 2001 From: CiD- Date: Thu, 17 Feb 2022 10:48:30 -0500 Subject: [PATCH 02/56] improve entry point check logic --- src/llvm_backend.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index c777819c3..07b8e97b2 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -1468,9 +1468,8 @@ void lb_generate_code(lbGenerator *gen) { if ((e->scope->flags&ScopeFlag_Init) && name == "main") { GB_ASSERT(e == info->entry_point); } - if (e->Procedure.is_export || - (e->Procedure.link_name.len > 0) || - ((e->scope->flags&ScopeFlag_File) && e->Procedure.link_name.len > 0)) { + if (build_context.command_kind == Command_test && + (e->Procedure.is_export || e->Procedure.link_name.len > 0)) { String link_name = e->Procedure.link_name; if (e->pkg->kind == Package_Runtime) { if (link_name == "main" || From 1bec9e5331bad9aaecee8ba80bf2cbeb97bb3ef0 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sun, 20 Feb 2022 14:19:52 +0000 Subject: [PATCH 03/56] Add `freestanding_amd64_gnu` --- src/build_settings.cpp | 36 ++++++++++++++++++++++++++++++++---- src/llvm_abi.cpp | 4 +++- src/llvm_backend.cpp | 13 +++++++++++++ 3 files changed, 48 insertions(+), 5 deletions(-) diff --git a/src/build_settings.cpp b/src/build_settings.cpp index 610e4f847..cc76f9e7c 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -8,7 +8,7 @@ // #define DEFAULT_TO_THREADED_CHECKER // #endif -enum TargetOsKind { +enum TargetOsKind : u16 { TargetOs_Invalid, TargetOs_windows, @@ -25,7 +25,7 @@ enum TargetOsKind { TargetOs_COUNT, }; -enum TargetArchKind { +enum TargetArchKind : u16 { TargetArch_Invalid, TargetArch_amd64, @@ -37,7 +37,7 @@ enum TargetArchKind { TargetArch_COUNT, }; -enum TargetEndianKind { +enum TargetEndianKind : u8 { TargetEndian_Invalid, TargetEndian_Little, @@ -46,6 +46,16 @@ enum TargetEndianKind { TargetEndian_COUNT, }; +enum TargetABIKind : u16 { + TargetABI_Default, + + TargetABI_MSVC, + TargetABI_GNU, + + TargetABI_COUNT, +}; + + String target_os_names[TargetOs_COUNT] = { str_lit(""), str_lit("windows"), @@ -75,6 +85,12 @@ String target_endian_names[TargetEndian_COUNT] = { str_lit("big"), }; +String target_abi_names[TargetABI_COUNT] = { + str_lit(""), + str_lit("win64"), + str_lit("sysv"), +}; + TargetEndianKind target_endians[TargetArch_COUNT] = { TargetEndian_Invalid, TargetEndian_Little, @@ -98,6 +114,7 @@ struct TargetMetrics { isize max_align; String target_triplet; String target_data_layout; + TargetABIKind abi; }; @@ -399,6 +416,16 @@ gb_global TargetMetrics target_wasi_wasm32 = { // str_lit(""), // }; +gb_global TargetMetrics target_freestanding_amd64_gnu = { + TargetOs_freestanding, + TargetArch_amd64, + 8, + 16, + str_lit("x86_64-pc-none-gnu"), + str_lit("e-m:w-i64:64-f80:128-n8:16:32:64-S128"), + TargetABI_GNU, +}; + struct NamedTargetMetrics { @@ -420,7 +447,8 @@ gb_global NamedTargetMetrics named_targets[] = { { str_lit("freestanding_wasm32"), &target_freestanding_wasm32 }, { str_lit("wasi_wasm32"), &target_wasi_wasm32 }, { str_lit("js_wasm32"), &target_js_wasm32 }, - // { str_lit("freestanding_wasm64"), &target_freestanding_wasm64 }, + + { str_lit("freestanding_amd64_gnu"), &target_freestanding_amd64_gnu }, }; NamedTargetMetrics *selected_target_metrics; diff --git a/src/llvm_abi.cpp b/src/llvm_abi.cpp index 0244b73d6..770e54ac8 100644 --- a/src/llvm_abi.cpp +++ b/src/llvm_abi.cpp @@ -1194,8 +1194,10 @@ LB_ABI_INFO(lb_get_abi_info) { switch (build_context.metrics.arch) { case TargetArch_amd64: - if (build_context.metrics.os == TargetOs_windows) { + if (build_context.metrics.os == TargetOs_windows || build_context.metrics.abi == TargetABI_MSVC) { return lbAbiAmd64Win64::abi_info(c, arg_types, arg_count, return_type, return_is_defined, calling_convention); + } else if (build_context.metrics.abi == TargetABI_GNU) { + return lbAbiAmd64SysV::abi_info(c, arg_types, arg_count, return_type, return_is_defined, calling_convention); } else { return lbAbiAmd64SysV::abi_info(c, arg_types, arg_count, return_type, return_is_defined, calling_convention); } diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index 52c46cadc..934daee28 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -996,6 +996,19 @@ String lb_filepath_obj_for_module(lbModule *m) { case TargetOs_essence: ext = STR_LIT(".o"); break; + + case TargetOs_freestanding: + switch (build_context.metrics.abi) { + default: + case TargetABI_Default: + case TargetABI_GNU: + ext = STR_LIT(".o"); + break; + case TargetABI_MSVC: + ext = STR_LIT(".obj"); + break; + } + break; } } } From 0fa487f468b1f63d5ec97ae8bbb0da01717f32cc Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sun, 20 Feb 2022 14:27:44 +0000 Subject: [PATCH 04/56] 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(-) 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) { From 3e5c60f74672651044d70303e8b0a8e56ca765f2 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sun, 20 Feb 2022 14:48:12 +0000 Subject: [PATCH 05/56] Add `-reloc-mode:` --- src/build_settings.cpp | 9 +++++++++ src/llvm_backend.cpp | 14 ++++++++++++++ src/main.cpp | 26 ++++++++++++++++++++++++++ 3 files changed, 49 insertions(+) diff --git a/src/build_settings.cpp b/src/build_settings.cpp index cd9bdb40c..d56a343df 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -189,6 +189,13 @@ enum ErrorPosStyle { ErrorPosStyle_COUNT }; +enum RelocMode { + RelocMode_Default, + RelocMode_Static, + RelocMode_PIC, + RelocMode_DynamicNoPIC, +}; + // This stores the information for the specify architecture of this build struct BuildContext { // Constants @@ -270,6 +277,8 @@ struct BuildContext { bool copy_file_contents; + RelocMode reloc_mode; + u32 cmd_doc_flags; Array extra_packages; diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index 934daee28..692b96c51 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -1308,6 +1308,20 @@ void lb_generate_code(lbGenerator *gen) { reloc_mode = LLVMRelocPIC; } + switch (build_context.reloc_mode) { + case RelocMode_Default: + break; + case RelocMode_Static: + reloc_mode = LLVMRelocStatic; + break; + case RelocMode_PIC: + reloc_mode = LLVMRelocPIC; + break; + case RelocMode_DynamicNoPIC: + reloc_mode = LLVMRelocDynamicNoPic; + break; + } + for_array(i, gen->modules.entries) { target_machines[i] = LLVMCreateTargetMachine( target, target_triple, llvm_cpu, diff --git a/src/main.cpp b/src/main.cpp index 5746ef146..087f2b442 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -625,6 +625,8 @@ enum BuildFlagKind { BuildFlag_ExtraAssemblerFlags, BuildFlag_Microarch, + BuildFlag_RelocMode, + BuildFlag_TestName, BuildFlag_DisallowDo, @@ -779,6 +781,8 @@ bool parse_build_flags(Array args) { add_flag(&build_flags, BuildFlag_ExtraAssemblerFlags, str_lit("extra-assembler-flags"), BuildFlagParam_String, Command__does_build); 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_TestName, str_lit("test-name"), BuildFlagParam_String, Command_test); add_flag(&build_flags, BuildFlag_DisallowDo, str_lit("disallow-do"), BuildFlagParam_None, Command__does_check); @@ -1339,6 +1343,28 @@ bool parse_build_flags(Array args) { string_to_lower(&build_context.microarch); break; } + case BuildFlag_RelocMode: { + GB_ASSERT(value.kind == ExactValue_String); + String v = value.value_string; + if (v == "default") { + build_context.reloc_mode = RelocMode_Default; + } else if (v == "static") { + build_context.reloc_mode = RelocMode_Static; + } else if (v == "pic") { + build_context.reloc_mode = RelocMode_PIC; + } else if (v == "dynamic-no-pic") { + build_context.reloc_mode = RelocMode_DynamicNoPIC; + } else { + gb_printf_err("-reloc-mode flag expected one of the following\n"); + gb_printf_err("\tdefault\n"); + gb_printf_err("\tstatic\n"); + gb_printf_err("\tpic\n"); + gb_printf_err("\tdynamic-no-pic\n"); + bad_flags = true; + } + + break; + } case BuildFlag_TestName: { GB_ASSERT(value.kind == ExactValue_String); { From 3d209798c9aff4a0ebd135536234022620c9e650 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 23 Feb 2022 11:19:51 +0000 Subject: [PATCH 06/56] Add help docs for `-reloc-mode:` --- src/build_settings.cpp | 2 +- src/llvm_backend.cpp | 2 ++ src/main.cpp | 9 +++++++++ 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/build_settings.cpp b/src/build_settings.cpp index d56a343df..790f7f1bc 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -189,7 +189,7 @@ enum ErrorPosStyle { ErrorPosStyle_COUNT }; -enum RelocMode { +enum RelocMode : u8 { RelocMode_Default, RelocMode_Static, RelocMode_PIC, diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index 692b96c51..ec22c7443 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -1261,6 +1261,8 @@ void lb_generate_code(lbGenerator *gen) { LLVMCodeModel code_mode = LLVMCodeModelDefault; if (is_arch_wasm()) { code_mode = LLVMCodeModelJITDefault; + } else if (build_context.metrics.os == TargetOs_freestanding) { + code_mode = LLVMCodeModelKernel; } char const *host_cpu_name = LLVMGetHostCPUName(); diff --git a/src/main.cpp b/src/main.cpp index 087f2b442..cfc7decb1 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2087,6 +2087,15 @@ void print_show_help(String const arg0, String const &command) { print_usage_line(3, "-microarch:sandybridge"); print_usage_line(3, "-microarch:native"); print_usage_line(0, ""); + + print_usage_line(1, "-reloc-mode:"); + print_usage_line(2, "Specifies the reloc mode"); + print_usage_line(2, "Options:"); + print_usage_line(3, "default"); + print_usage_line(3, "static"); + print_usage_line(3, "pic"); + print_usage_line(3, "dynamic-no-pic"); + print_usage_line(0, ""); } if (check) { From 493bc653b5762514dac8c8941d6564ccf5bb8528 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 23 Feb 2022 11:23:27 +0000 Subject: [PATCH 07/56] 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(+) 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"); From 196bd735d4c30964182fdf1f374f767ccb0912fa Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 23 Feb 2022 11:29:36 +0000 Subject: [PATCH 08/56] 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(-) 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) { From 4a04a32e0ab4ad91a7b62c0a94e57312002b85d5 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 23 Feb 2022 11:33:28 +0000 Subject: [PATCH 09/56] Change target name to `freestanding_amd64_sysv` --- src/build_settings.cpp | 10 +++++----- src/llvm_abi.cpp | 4 ++-- src/llvm_backend.cpp | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/build_settings.cpp b/src/build_settings.cpp index 62f43fad3..d6cdd7006 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -49,8 +49,8 @@ enum TargetEndianKind : u8 { enum TargetABIKind : u16 { TargetABI_Default, - TargetABI_MSVC, - TargetABI_GNU, + TargetABI_Win64, + TargetABI_SysV, TargetABI_COUNT, }; @@ -428,14 +428,14 @@ gb_global TargetMetrics target_wasi_wasm32 = { // str_lit(""), // }; -gb_global TargetMetrics target_freestanding_amd64_gnu = { +gb_global TargetMetrics target_freestanding_amd64_sysv = { TargetOs_freestanding, TargetArch_amd64, 8, 16, str_lit("x86_64-pc-none-gnu"), str_lit("e-m:w-i64:64-f80:128-n8:16:32:64-S128"), - TargetABI_GNU, + TargetABI_SysV, }; @@ -460,7 +460,7 @@ gb_global NamedTargetMetrics named_targets[] = { { str_lit("wasi_wasm32"), &target_wasi_wasm32 }, { str_lit("js_wasm32"), &target_js_wasm32 }, - { str_lit("freestanding_amd64_gnu"), &target_freestanding_amd64_gnu }, + { str_lit("freestanding_amd64_sysv"), &target_freestanding_amd64_sysv }, }; NamedTargetMetrics *selected_target_metrics; diff --git a/src/llvm_abi.cpp b/src/llvm_abi.cpp index 770e54ac8..07d2dd6e3 100644 --- a/src/llvm_abi.cpp +++ b/src/llvm_abi.cpp @@ -1194,9 +1194,9 @@ LB_ABI_INFO(lb_get_abi_info) { switch (build_context.metrics.arch) { case TargetArch_amd64: - if (build_context.metrics.os == TargetOs_windows || build_context.metrics.abi == TargetABI_MSVC) { + if (build_context.metrics.os == TargetOs_windows || build_context.metrics.abi == TargetABI_Win64) { return lbAbiAmd64Win64::abi_info(c, arg_types, arg_count, return_type, return_is_defined, calling_convention); - } else if (build_context.metrics.abi == TargetABI_GNU) { + } else if (build_context.metrics.abi == TargetABI_SysV) { return lbAbiAmd64SysV::abi_info(c, arg_types, arg_count, return_type, return_is_defined, calling_convention); } else { return lbAbiAmd64SysV::abi_info(c, arg_types, arg_count, return_type, return_is_defined, calling_convention); diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index ec22c7443..6ca256c4b 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -1001,10 +1001,10 @@ String lb_filepath_obj_for_module(lbModule *m) { switch (build_context.metrics.abi) { default: case TargetABI_Default: - case TargetABI_GNU: + case TargetABI_SysV: ext = STR_LIT(".o"); break; - case TargetABI_MSVC: + case TargetABI_Win64: ext = STR_LIT(".obj"); break; } From 32988b03632912bbdb788e3dc319592a1dab9bfe Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 25 Feb 2022 12:01:53 +0000 Subject: [PATCH 10/56] Correct internals for `os.read` on windows (read_console) for `os.stdin` (Fix #1556) --- core/os/file_windows.odin | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/core/os/file_windows.odin b/core/os/file_windows.odin index 8a0f2ed64..5368f51cf 100644 --- a/core/os/file_windows.odin +++ b/core/os/file_windows.odin @@ -108,7 +108,8 @@ read_console :: proc(handle: win32.HANDLE, b: []byte) -> (n: int, err: Errno) { buf8: [4*BUF_SIZE]u8 for n < len(b) && err == 0 { - max_read := u32(min(BUF_SIZE, len(b)/4)) + min_read := max(min(len(b), 4), len(b)/4) + max_read := u32(min(BUF_SIZE, min_read)) single_read_length: u32 ok := win32.ReadConsoleW(handle, &buf16[0], max_read, &single_read_length, nil) @@ -129,7 +130,7 @@ read_console :: proc(handle: win32.HANDLE, b: []byte) -> (n: int, err: Errno) { b[n] = x n += 1 } - if ctrl_z || single_read_length < len(buf16) { + if ctrl_z || single_read_length < max_read { break } } From ab9d1f99fdb776352352d882f49aefc80d0e9d58 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 28 Feb 2022 12:36:21 +0000 Subject: [PATCH 11/56] Change `#c_vararg` checking to only disallow odin calling conventions --- src/check_type.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/check_type.cpp b/src/check_type.cpp index 64fb67723..c2324ee5a 100644 --- a/src/check_type.cpp +++ b/src/check_type.cpp @@ -2031,10 +2031,14 @@ bool check_procedure_type(CheckerContext *ctx, Type *type, Ast *proc_type_node, if (param_count > 0) { Entity *end = params->Tuple.variables[param_count-1]; if (end->flags&EntityFlag_CVarArg) { - if (cc == ProcCC_StdCall || cc == ProcCC_CDecl) { + switch (cc) { + default: type->Proc.c_vararg = true; - } else { + break; + case ProcCC_Odin: + case ProcCC_Contextless: error(end->token, "Calling convention does not support #c_vararg"); + break; } } } From 37bba4c0a6b98f38a3160c9508bc55a6cb8ea7f1 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 28 Feb 2022 12:45:19 +0000 Subject: [PATCH 12/56] Reorganize error check procedures --- core/runtime/error_checks.odin | 339 ++++++++++++++++----------------- 1 file changed, 168 insertions(+), 171 deletions(-) diff --git a/core/runtime/error_checks.odin b/core/runtime/error_checks.odin index ad6902e2d..e4dd96d32 100644 --- a/core/runtime/error_checks.odin +++ b/core/runtime/error_checks.odin @@ -17,6 +17,23 @@ type_assertion_trap :: proc "contextless" () -> ! { } +bounds_check_error_loc :: #force_inline proc "contextless" (using loc := #caller_location, index, count: int) { + bounds_check_error(file_path, line, column, index, count) +} + +slice_expr_error_hi_loc :: #force_inline proc "contextless" (using loc := #caller_location, hi: int, len: int) { + slice_expr_error_hi(file_path, line, column, hi, len) +} + +slice_expr_error_lo_hi_loc :: #force_inline proc "contextless" (using loc := #caller_location, lo, hi: int, len: int) { + slice_expr_error_lo_hi(file_path, line, column, lo, hi, len) +} + +dynamic_array_expr_error_loc :: #force_inline proc "contextless" (using loc := #caller_location, low, high, max: int) { + dynamic_array_expr_error(file_path, line, column, low, high, max) +} + + when ODIN_FOREIGN_ERROR_PROCEDURES { foreign { bounds_check_error :: proc "contextless" (file: string, line, column: i32, index, count: int) --- @@ -29,182 +46,182 @@ when ODIN_FOREIGN_ERROR_PROCEDURES { 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 + bounds_check_error :: proc "contextless" (file: string, line, column: i32, index, count: int) { + if 0 <= index && index < count { + return + } + handle_error :: proc "contextless" (file: string, line, column: i32, index, count: int) { + print_caller_location(Source_Code_Location{file, line, column, ""}) + print_string(" Index ") + print_i64(i64(index)) + print_string(" is out of range 0..<") + print_i64(i64(count)) + print_byte('\n') + bounds_trap() + } + handle_error(file, line, column, index, count) } - handle_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) -> ! { print_caller_location(Source_Code_Location{file, line, column, ""}) - print_string(" Index ") - print_i64(i64(index)) - print_string(" is out of range 0..<") - print_i64(i64(count)) - print_byte('\n') - bounds_trap() - } - handle_error(file, line, column, index, count) -} - -slice_handle_error :: proc "contextless" (file: string, line, column: i32, lo, hi: int, len: int) -> ! { - print_caller_location(Source_Code_Location{file, line, column, ""}) - print_string(" Invalid slice indices ") - print_i64(i64(lo)) - print_string(":") - print_i64(i64(hi)) - print_string(" is out of range 0..<") - print_i64(i64(len)) - print_byte('\n') - bounds_trap() -} - -multi_pointer_slice_handle_error :: proc "contextless" (file: string, line, column: i32, lo, hi: int) -> ! { - print_caller_location(Source_Code_Location{file, line, column, ""}) - print_string(" Invalid slice indices ") - print_i64(i64(lo)) - print_string(":") - print_i64(i64(hi)) - print_byte('\n') - bounds_trap() -} - - -multi_pointer_slice_expr_error :: proc "contextless" (file: string, line, column: i32, lo, hi: int) { - if lo <= hi { - return - } - multi_pointer_slice_handle_error(file, line, column, lo, hi) -} - -slice_expr_error_hi :: proc "contextless" (file: string, line, column: i32, hi: int, len: int) { - if 0 <= hi && hi <= len { - return - } - slice_handle_error(file, line, column, 0, hi, len) -} - -slice_expr_error_lo_hi :: proc "contextless" (file: string, line, column: i32, lo, hi: int, len: int) { - if 0 <= lo && lo <= len && lo <= hi && hi <= len { - return - } - slice_handle_error(file, line, column, lo, hi, len) -} - -dynamic_array_expr_error :: proc "contextless" (file: string, line, column: i32, low, high, max: int) { - if 0 <= low && low <= high && high <= max { - return - } - handle_error :: proc "contextless" (file: string, line, column: i32, low, high, max: int) { - print_caller_location(Source_Code_Location{file, line, column, ""}) - print_string(" Invalid dynamic array indices ") - print_i64(i64(low)) + print_string(" Invalid slice indices ") + print_i64(i64(lo)) print_string(":") - print_i64(i64(high)) + print_i64(i64(hi)) print_string(" is out of range 0..<") - print_i64(i64(max)) + print_i64(i64(len)) print_byte('\n') bounds_trap() } - handle_error(file, line, column, low, high, max) -} - -matrix_bounds_check_error :: proc "contextless" (file: string, line, column: i32, row_index, column_index, row_count, column_count: int) { - if 0 <= row_index && row_index < row_count && - 0 <= column_index && column_index < column_count { - return - } - handle_error :: proc "contextless" (file: string, line, column: i32, row_index, column_index, row_count, column_count: int) { + multi_pointer_slice_handle_error :: proc "contextless" (file: string, line, column: i32, lo, hi: int) -> ! { print_caller_location(Source_Code_Location{file, line, column, ""}) - print_string(" Matrix indices [") - print_i64(i64(row_index)) - print_string(", ") - print_i64(i64(column_index)) - print_string(" is out of range [0..<") - print_i64(i64(row_count)) - print_string(", 0..<") - print_i64(i64(column_count)) - print_string("]") + print_string(" Invalid slice indices ") + print_i64(i64(lo)) + print_string(":") + print_i64(i64(hi)) print_byte('\n') bounds_trap() } - handle_error(file, line, column, row_index, column_index, row_count, column_count) -} -type_assertion_check :: proc "contextless" (ok: bool, file: string, line, column: i32, from, to: typeid) { - if ok { - return - } - handle_error :: proc "contextless" (file: string, line, column: i32, from, to: typeid) { - print_caller_location(Source_Code_Location{file, line, column, ""}) - print_string(" Invalid type assertion from ") - print_typeid(from) - print_string(" to ") - print_typeid(to) - print_byte('\n') - type_assertion_trap() - } - handle_error(file, line, column, from, to) -} - -type_assertion_check2 :: proc "contextless" (ok: bool, file: string, line, column: i32, from, to: typeid, from_data: rawptr) { - if ok { - return + multi_pointer_slice_expr_error :: proc "contextless" (file: string, line, column: i32, lo, hi: int) { + if lo <= hi { + return + } + multi_pointer_slice_handle_error(file, line, column, lo, hi) } - variant_type :: proc "contextless" (id: typeid, data: rawptr) -> typeid { - if id == nil || data == nil { + slice_expr_error_hi :: proc "contextless" (file: string, line, column: i32, hi: int, len: int) { + if 0 <= hi && hi <= len { + return + } + slice_handle_error(file, line, column, 0, hi, len) + } + + slice_expr_error_lo_hi :: proc "contextless" (file: string, line, column: i32, lo, hi: int, len: int) { + if 0 <= lo && lo <= len && lo <= hi && hi <= len { + return + } + slice_handle_error(file, line, column, lo, hi, len) + } + + dynamic_array_expr_error :: proc "contextless" (file: string, line, column: i32, low, high, max: int) { + if 0 <= low && low <= high && high <= max { + return + } + handle_error :: proc "contextless" (file: string, line, column: i32, low, high, max: int) { + print_caller_location(Source_Code_Location{file, line, column, ""}) + print_string(" Invalid dynamic array indices ") + print_i64(i64(low)) + print_string(":") + print_i64(i64(high)) + print_string(" is out of range 0..<") + print_i64(i64(max)) + print_byte('\n') + bounds_trap() + } + handle_error(file, line, column, low, high, max) + } + + + matrix_bounds_check_error :: proc "contextless" (file: string, line, column: i32, row_index, column_index, row_count, column_count: int) { + if 0 <= row_index && row_index < row_count && + 0 <= column_index && column_index < column_count { + return + } + handle_error :: proc "contextless" (file: string, line, column: i32, row_index, column_index, row_count, column_count: int) { + print_caller_location(Source_Code_Location{file, line, column, ""}) + print_string(" Matrix indices [") + print_i64(i64(row_index)) + print_string(", ") + print_i64(i64(column_index)) + print_string(" is out of range [0..<") + print_i64(i64(row_count)) + print_string(", 0..<") + print_i64(i64(column_count)) + print_string("]") + print_byte('\n') + bounds_trap() + } + handle_error(file, line, column, row_index, column_index, row_count, column_count) + } + + + type_assertion_check :: proc "contextless" (ok: bool, file: string, line, column: i32, from, to: typeid) { + if ok { + return + } + handle_error :: proc "contextless" (file: string, line, column: i32, from, to: typeid) { + print_caller_location(Source_Code_Location{file, line, column, ""}) + print_string(" Invalid type assertion from ") + print_typeid(from) + print_string(" to ") + print_typeid(to) + print_byte('\n') + type_assertion_trap() + } + handle_error(file, line, column, from, to) + } + + type_assertion_check2 :: proc "contextless" (ok: bool, file: string, line, column: i32, from, to: typeid, from_data: rawptr) { + if ok { + return + } + + variant_type :: proc "contextless" (id: typeid, data: rawptr) -> typeid { + if id == nil || data == nil { + return id + } + ti := type_info_base(type_info_of(id)) + #partial switch v in ti.variant { + case Type_Info_Any: + return (^any)(data).id + case Type_Info_Union: + tag_ptr := uintptr(data) + v.tag_offset + idx := 0 + switch v.tag_type.size { + case 1: idx = int((^u8)(tag_ptr)^) - 1 + case 2: idx = int((^u16)(tag_ptr)^) - 1 + case 4: idx = int((^u32)(tag_ptr)^) - 1 + case 8: idx = int((^u64)(tag_ptr)^) - 1 + case 16: idx = int((^u128)(tag_ptr)^) - 1 + } + if idx < 0 { + return nil + } else if idx < len(v.variants) { + return v.variants[idx].id + } + } return id } - ti := type_info_base(type_info_of(id)) - #partial switch v in ti.variant { - case Type_Info_Any: - return (^any)(data).id - case Type_Info_Union: - tag_ptr := uintptr(data) + v.tag_offset - idx := 0 - switch v.tag_type.size { - case 1: idx = int((^u8)(tag_ptr)^) - 1 - case 2: idx = int((^u16)(tag_ptr)^) - 1 - case 4: idx = int((^u32)(tag_ptr)^) - 1 - case 8: idx = int((^u64)(tag_ptr)^) - 1 - case 16: idx = int((^u128)(tag_ptr)^) - 1 - } - if idx < 0 { - return nil - } else if idx < len(v.variants) { - return v.variants[idx].id + + handle_error :: proc "contextless" (file: string, line, column: i32, from, to: typeid, from_data: rawptr) { + + actual := variant_type(from, from_data) + + print_caller_location(Source_Code_Location{file, line, column, ""}) + print_string(" Invalid type assertion from ") + print_typeid(from) + print_string(" to ") + print_typeid(to) + if actual != from { + print_string(", actual type: ") + print_typeid(actual) } + print_byte('\n') + type_assertion_trap() } - return id + handle_error(file, line, column, from, to, from_data) } - - handle_error :: proc "contextless" (file: string, line, column: i32, from, to: typeid, from_data: rawptr) { - - actual := variant_type(from, from_data) - - print_caller_location(Source_Code_Location{file, line, column, ""}) - print_string(" Invalid type assertion from ") - print_typeid(from) - print_string(" to ") - print_typeid(to) - if actual != from { - print_string(", actual type: ") - print_typeid(actual) - } - print_byte('\n') - type_assertion_trap() - } - handle_error(file, line, column, from, to, from_data) } +// `make` related procedures below + + make_slice_error_loc :: #force_inline proc "contextless" (loc := #caller_location, len: int) { if 0 <= len { return @@ -219,7 +236,7 @@ make_slice_error_loc :: #force_inline proc "contextless" (loc := #caller_locatio handle_error(loc, len) } -make_dynamic_array_error_loc :: #force_inline proc "contextless" (using loc := #caller_location, len, cap: int) { +make_dynamic_array_error_loc :: #force_inline proc "contextless" (loc := #caller_location, len, cap: int) { if 0 <= len && len <= cap { return } @@ -248,23 +265,3 @@ make_map_expr_error_loc :: #force_inline proc "contextless" (loc := #caller_loca } handle_error(loc, cap) } - -} - - - -bounds_check_error_loc :: #force_inline proc "contextless" (using loc := #caller_location, index, count: int) { - bounds_check_error(file_path, line, column, index, count) -} - -slice_expr_error_hi_loc :: #force_inline proc "contextless" (using loc := #caller_location, hi: int, len: int) { - slice_expr_error_hi(file_path, line, column, hi, len) -} - -slice_expr_error_lo_hi_loc :: #force_inline proc "contextless" (using loc := #caller_location, lo, hi: int, len: int) { - slice_expr_error_lo_hi(file_path, line, column, lo, hi, len) -} - -dynamic_array_expr_error_loc :: #force_inline proc "contextless" (using loc := #caller_location, low, high, max: int) { - dynamic_array_expr_error(file_path, line, column, low, high, max) -} From 01162e08b55406578a2972d74c472de8a14f12b8 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 28 Feb 2022 13:35:29 +0000 Subject: [PATCH 13/56] Add `-disallow-rtti` --- core/runtime/core.odin | 20 +-- core/runtime/error_checks.odin | 277 ++++++++++++++++++--------------- core/runtime/print.odin | 16 +- 3 files changed, 172 insertions(+), 141 deletions(-) diff --git a/core/runtime/core.odin b/core/runtime/core.odin index 8d315a238..83a5418ed 100644 --- a/core/runtime/core.odin +++ b/core/runtime/core.odin @@ -508,16 +508,18 @@ __type_info_of :: proc "contextless" (id: typeid) -> ^Type_Info #no_bounds_check return &type_table[n] } -typeid_base :: proc "contextless" (id: typeid) -> typeid { - ti := type_info_of(id) - ti = type_info_base(ti) - return ti.id +when !ODIN_DISALLOW_RTTI { + typeid_base :: proc "contextless" (id: typeid) -> typeid { + ti := type_info_of(id) + ti = type_info_base(ti) + return ti.id + } + typeid_core :: proc "contextless" (id: typeid) -> typeid { + ti := type_info_core(type_info_of(id)) + return ti.id + } + typeid_base_without_enum :: typeid_core } -typeid_core :: proc "contextless" (id: typeid) -> typeid { - ti := type_info_core(type_info_of(id)) - return ti.id -} -typeid_base_without_enum :: typeid_core diff --git a/core/runtime/error_checks.odin b/core/runtime/error_checks.odin index e4dd96d32..0d0b39072 100644 --- a/core/runtime/error_checks.odin +++ b/core/runtime/error_checks.odin @@ -17,143 +17,143 @@ type_assertion_trap :: proc "contextless" () -> ! { } -bounds_check_error_loc :: #force_inline proc "contextless" (using loc := #caller_location, index, count: int) { - bounds_check_error(file_path, line, column, index, count) +bounds_check_error :: proc "contextless" (file: string, line, column: i32, index, count: int) { + if 0 <= index && index < count { + return + } + @(cold) + handle_error :: proc "contextless" (file: string, line, column: i32, index, count: int) { + print_caller_location(Source_Code_Location{file, line, column, ""}) + print_string(" Index ") + print_i64(i64(index)) + print_string(" is out of range 0..<") + print_i64(i64(count)) + print_byte('\n') + bounds_trap() + } + handle_error(file, line, column, index, count) } -slice_expr_error_hi_loc :: #force_inline proc "contextless" (using loc := #caller_location, hi: int, len: int) { - slice_expr_error_hi(file_path, line, column, hi, len) +slice_handle_error :: proc "contextless" (file: string, line, column: i32, lo, hi: int, len: int) -> ! { + print_caller_location(Source_Code_Location{file, line, column, ""}) + print_string(" Invalid slice indices ") + print_i64(i64(lo)) + print_string(":") + print_i64(i64(hi)) + print_string(" is out of range 0..<") + print_i64(i64(len)) + print_byte('\n') + bounds_trap() } -slice_expr_error_lo_hi_loc :: #force_inline proc "contextless" (using loc := #caller_location, lo, hi: int, len: int) { - slice_expr_error_lo_hi(file_path, line, column, lo, hi, len) -} - -dynamic_array_expr_error_loc :: #force_inline proc "contextless" (using loc := #caller_location, low, high, max: int) { - dynamic_array_expr_error(file_path, line, column, low, high, max) +multi_pointer_slice_handle_error :: proc "contextless" (file: string, line, column: i32, lo, hi: int) -> ! { + print_caller_location(Source_Code_Location{file, line, column, ""}) + print_string(" Invalid slice indices ") + print_i64(i64(lo)) + print_string(":") + print_i64(i64(hi)) + print_byte('\n') + bounds_trap() } -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) --- +multi_pointer_slice_expr_error :: proc "contextless" (file: string, line, column: i32, lo, hi: int) { + if lo <= hi { + return + } + multi_pointer_slice_handle_error(file, line, column, lo, hi) +} + +slice_expr_error_hi :: proc "contextless" (file: string, line, column: i32, hi: int, len: int) { + if 0 <= hi && hi <= len { + return + } + slice_handle_error(file, line, column, 0, hi, len) +} + +slice_expr_error_lo_hi :: proc "contextless" (file: string, line, column: i32, lo, hi: int, len: int) { + if 0 <= lo && lo <= len && lo <= hi && hi <= len { + return + } + slice_handle_error(file, line, column, lo, hi, len) +} + +dynamic_array_expr_error :: proc "contextless" (file: string, line, column: i32, low, high, max: int) { + if 0 <= low && low <= high && high <= max { + return + } + @(cold) + handle_error :: proc "contextless" (file: string, line, column: i32, low, high, max: int) { + print_caller_location(Source_Code_Location{file, line, column, ""}) + print_string(" Invalid dynamic array indices ") + print_i64(i64(low)) + print_string(":") + print_i64(i64(high)) + print_string(" is out of range 0..<") + print_i64(i64(max)) + print_byte('\n') + bounds_trap() + } + handle_error(file, line, column, low, high, max) +} + + +matrix_bounds_check_error :: proc "contextless" (file: string, line, column: i32, row_index, column_index, row_count, column_count: int) { + if 0 <= row_index && row_index < row_count && + 0 <= column_index && column_index < column_count { + return + } + @(cold) + handle_error :: proc "contextless" (file: string, line, column: i32, row_index, column_index, row_count, column_count: int) { + print_caller_location(Source_Code_Location{file, line, column, ""}) + print_string(" Matrix indices [") + print_i64(i64(row_index)) + print_string(", ") + print_i64(i64(column_index)) + print_string(" is out of range [0..<") + print_i64(i64(row_count)) + print_string(", 0..<") + print_i64(i64(column_count)) + print_string("]") + print_byte('\n') + bounds_trap() + } + handle_error(file, line, column, row_index, column_index, row_count, column_count) +} + + +when ODIN_DISALLOW_RTTI { + type_assertion_check :: proc "contextless" (ok: bool, file: string, line, column: i32) { + if ok { + return + } + @(cold) + handle_error :: proc "contextless" (file: string, line, column: i32) { + print_caller_location(Source_Code_Location{file, line, column, ""}) + print_string(" Invalid type assertion\n") + type_assertion_trap() + } + handle_error(file, line, column) + } + + type_assertion_check2 :: proc "contextless" (ok: bool, file: string, line, column: i32) { + if ok { + return + } + @(cold) + handle_error :: proc "contextless" (file: string, line, column: i32) { + print_caller_location(Source_Code_Location{file, line, column, ""}) + print_string(" Invalid type assertion\n") + type_assertion_trap() + } + handle_error(file, line, column) } } else { - bounds_check_error :: proc "contextless" (file: string, line, column: i32, index, count: int) { - if 0 <= index && index < count { - return - } - handle_error :: proc "contextless" (file: string, line, column: i32, index, count: int) { - print_caller_location(Source_Code_Location{file, line, column, ""}) - print_string(" Index ") - print_i64(i64(index)) - print_string(" is out of range 0..<") - print_i64(i64(count)) - print_byte('\n') - bounds_trap() - } - handle_error(file, line, column, index, count) - } - - slice_handle_error :: proc "contextless" (file: string, line, column: i32, lo, hi: int, len: int) -> ! { - print_caller_location(Source_Code_Location{file, line, column, ""}) - print_string(" Invalid slice indices ") - print_i64(i64(lo)) - print_string(":") - print_i64(i64(hi)) - print_string(" is out of range 0..<") - print_i64(i64(len)) - print_byte('\n') - bounds_trap() - } - - multi_pointer_slice_handle_error :: proc "contextless" (file: string, line, column: i32, lo, hi: int) -> ! { - print_caller_location(Source_Code_Location{file, line, column, ""}) - print_string(" Invalid slice indices ") - print_i64(i64(lo)) - print_string(":") - print_i64(i64(hi)) - print_byte('\n') - bounds_trap() - } - - - multi_pointer_slice_expr_error :: proc "contextless" (file: string, line, column: i32, lo, hi: int) { - if lo <= hi { - return - } - multi_pointer_slice_handle_error(file, line, column, lo, hi) - } - - slice_expr_error_hi :: proc "contextless" (file: string, line, column: i32, hi: int, len: int) { - if 0 <= hi && hi <= len { - return - } - slice_handle_error(file, line, column, 0, hi, len) - } - - slice_expr_error_lo_hi :: proc "contextless" (file: string, line, column: i32, lo, hi: int, len: int) { - if 0 <= lo && lo <= len && lo <= hi && hi <= len { - return - } - slice_handle_error(file, line, column, lo, hi, len) - } - - dynamic_array_expr_error :: proc "contextless" (file: string, line, column: i32, low, high, max: int) { - if 0 <= low && low <= high && high <= max { - return - } - handle_error :: proc "contextless" (file: string, line, column: i32, low, high, max: int) { - print_caller_location(Source_Code_Location{file, line, column, ""}) - print_string(" Invalid dynamic array indices ") - print_i64(i64(low)) - print_string(":") - print_i64(i64(high)) - print_string(" is out of range 0..<") - print_i64(i64(max)) - print_byte('\n') - bounds_trap() - } - handle_error(file, line, column, low, high, max) - } - - - matrix_bounds_check_error :: proc "contextless" (file: string, line, column: i32, row_index, column_index, row_count, column_count: int) { - if 0 <= row_index && row_index < row_count && - 0 <= column_index && column_index < column_count { - return - } - handle_error :: proc "contextless" (file: string, line, column: i32, row_index, column_index, row_count, column_count: int) { - print_caller_location(Source_Code_Location{file, line, column, ""}) - print_string(" Matrix indices [") - print_i64(i64(row_index)) - print_string(", ") - print_i64(i64(column_index)) - print_string(" is out of range [0..<") - print_i64(i64(row_count)) - print_string(", 0..<") - print_i64(i64(column_count)) - print_string("]") - print_byte('\n') - bounds_trap() - } - handle_error(file, line, column, row_index, column_index, row_count, column_count) - } - - type_assertion_check :: proc "contextless" (ok: bool, file: string, line, column: i32, from, to: typeid) { if ok { return } + @(cold) handle_error :: proc "contextless" (file: string, line, column: i32, from, to: typeid) { print_caller_location(Source_Code_Location{file, line, column, ""}) print_string(" Invalid type assertion from ") @@ -198,6 +198,7 @@ when ODIN_FOREIGN_ERROR_PROCEDURES { return id } + @(cold) handle_error :: proc "contextless" (file: string, line, column: i32, from, to: typeid, from_data: rawptr) { actual := variant_type(from, from_data) @@ -219,13 +220,11 @@ when ODIN_FOREIGN_ERROR_PROCEDURES { } -// `make` related procedures below - - make_slice_error_loc :: #force_inline proc "contextless" (loc := #caller_location, len: int) { if 0 <= len { return } + @(cold) handle_error :: proc "contextless" (loc: Source_Code_Location, len: int) { print_caller_location(loc) print_string(" Invalid slice length for make: ") @@ -236,10 +235,11 @@ make_slice_error_loc :: #force_inline proc "contextless" (loc := #caller_locatio handle_error(loc, len) } -make_dynamic_array_error_loc :: #force_inline proc "contextless" (loc := #caller_location, len, cap: int) { +make_dynamic_array_error_loc :: #force_inline proc "contextless" (using loc := #caller_location, len, cap: int) { if 0 <= len && len <= cap { return } + @(cold) handle_error :: proc "contextless" (loc: Source_Code_Location, len, cap: int) { print_caller_location(loc) print_string(" Invalid dynamic array parameters for make: ") @@ -256,6 +256,7 @@ make_map_expr_error_loc :: #force_inline proc "contextless" (loc := #caller_loca if 0 <= cap { return } + @(cold) handle_error :: proc "contextless" (loc: Source_Code_Location, cap: int) { print_caller_location(loc) print_string(" Invalid map capacity for make: ") @@ -265,3 +266,23 @@ make_map_expr_error_loc :: #force_inline proc "contextless" (loc := #caller_loca } handle_error(loc, cap) } + + + + + +bounds_check_error_loc :: #force_inline proc "contextless" (using loc := #caller_location, index, count: int) { + bounds_check_error(file_path, line, column, index, count) +} + +slice_expr_error_hi_loc :: #force_inline proc "contextless" (using loc := #caller_location, hi: int, len: int) { + slice_expr_error_hi(file_path, line, column, hi, len) +} + +slice_expr_error_lo_hi_loc :: #force_inline proc "contextless" (using loc := #caller_location, lo, hi: int, len: int) { + slice_expr_error_lo_hi(file_path, line, column, lo, hi, len) +} + +dynamic_array_expr_error_loc :: #force_inline proc "contextless" (using loc := #caller_location, low, high, max: int) { + dynamic_array_expr_error(file_path, line, column, low, high, max) +} diff --git a/core/runtime/print.odin b/core/runtime/print.odin index 06740bc75..89c196fc2 100644 --- a/core/runtime/print.odin +++ b/core/runtime/print.odin @@ -160,11 +160,19 @@ print_caller_location :: proc "contextless" (using loc: Source_Code_Location) { } } print_typeid :: proc "contextless" (id: typeid) { - if id == nil { - print_string("nil") + when ODIN_DISALLOW_RTTI { + if id == nil { + print_string("nil") + } else { + print_string("") + } } else { - ti := type_info_of(id) - print_type(ti) + if id == nil { + print_string("nil") + } else { + ti := type_info_of(id) + print_type(ti) + } } } print_type :: proc "contextless" (ti: ^Type_Info) { From fda803b46ae7d9bf3eba33e2ae701c452e72477d Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 28 Feb 2022 13:39:27 +0000 Subject: [PATCH 14/56] Commit rest of code for `-disable-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(-) 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; From 278e239973ab1e680bd36f90c069ec798930e54b Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 28 Feb 2022 13:39:27 +0000 Subject: [PATCH 15/56] 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(-) 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; From 882116e35819937206e14dbf02d1c9ad42037d93 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 28 Feb 2022 14:00:44 +0000 Subject: [PATCH 16/56] Only allow `-disallow-rtti` on freestanding targets --- src/build_settings.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/build_settings.cpp b/src/build_settings.cpp index b2d6c4f43..7beee8664 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -1077,6 +1077,11 @@ void init_build_context(TargetMetrics *cross_target) { bc->optimization_level = gb_clamp(bc->optimization_level, 0, 3); + if (bc->disallow_rtti && bc->metrics.os != TargetOs_freestanding) { + gb_printf_err("-disallow-rtti is only allowed on freestanding targets\n"); + gb_exit(1); + } + #undef LINK_FLAG_X64 #undef LINK_FLAG_386 } From 2d89faa17cf88b76e183e35f4d50722271c76d20 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 28 Feb 2022 14:35:38 +0000 Subject: [PATCH 17/56] Add extra checks for -disallow-rtti --- src/llvm_backend.cpp | 9 +++++++-- src/llvm_backend_type.cpp | 8 ++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index 04c3200f8..40c06c23a 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -624,6 +624,9 @@ struct lbGlobalVariable { }; lbProcedure *lb_create_startup_type_info(lbModule *m) { + if (build_context.disallow_rtti) { + return nullptr; + } 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); @@ -711,7 +714,9 @@ lbProcedure *lb_create_startup_runtime(lbModule *main_module, lbProcedure *start lb_begin_procedure_body(p); - LLVMBuildCall2(p->builder, LLVMGetElementType(lb_type(main_module, startup_type_info->type)), startup_type_info->value, nullptr, 0, ""); + if (startup_type_info) { + 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, ""); @@ -1394,7 +1399,7 @@ void lb_generate_code(lbGenerator *gen) { TIME_SECTION("LLVM Global Variables"); - { + if (!build_context.disallow_rtti) { lbModule *m = default_module; { // Add type info data diff --git a/src/llvm_backend_type.cpp b/src/llvm_backend_type.cpp index 1aac75f9c..e245a8b40 100644 --- a/src/llvm_backend_type.cpp +++ b/src/llvm_backend_type.cpp @@ -90,6 +90,8 @@ lbValue lb_typeid(lbModule *m, Type *type) { } lbValue lb_type_info(lbModule *m, Type *type) { + GB_ASSERT(!build_context.disallow_rtti); + type = default_type(type); isize index = lb_type_info_index(m->info, type); @@ -108,6 +110,8 @@ lbValue lb_type_info(lbModule *m, Type *type) { } lbValue lb_get_type_info_ptr(lbModule *m, Type *type) { + GB_ASSERT(!build_context.disallow_rtti); + i32 index = cast(i32)lb_type_info_index(m->info, type); GB_ASSERT(index >= 0); // gb_printf_err("%d %s\n", index, type_to_string(type)); @@ -157,6 +161,10 @@ lbValue lb_type_info_member_tags_offset(lbProcedure *p, isize count) { void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup type_info data + if (build_context.disallow_rtti) { + return; + } + lbModule *m = p->module; CheckerInfo *info = m->info; From 09e4fff5b18a314876c5f5d79f01cdd90aed7362 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 28 Feb 2022 15:08:50 +0000 Subject: [PATCH 18/56] `-target-features:` This just passes a string directly to the LLVM features string --- src/build_settings.cpp | 1 + src/llvm_backend.cpp | 4 ++++ src/main.cpp | 10 +++++++++- src/string.cpp | 8 -------- 4 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/build_settings.cpp b/src/build_settings.cpp index 7beee8664..e94fade4e 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -232,6 +232,7 @@ struct BuildContext { String extra_linker_flags; String extra_assembler_flags; String microarch; + String target_features; BuildModeKind build_mode; bool generate_docs; i32 optimization_level; diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index 40c06c23a..ed3ae7dfc 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -1298,6 +1298,10 @@ void lb_generate_code(lbGenerator *gen) { } } + if (build_context.target_features.len != 0) { + llvm_features = alloc_cstring(permanent_allocator(), build_context.target_features); + } + // GB_ASSERT_MSG(LLVMTargetHasAsmBackend(target)); LLVMCodeGenOptLevel code_gen_level = LLVMCodeGenLevelNone; diff --git a/src/main.cpp b/src/main.cpp index d2263f5a7..5a77e09d8 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -626,6 +626,7 @@ enum BuildFlagKind { BuildFlag_ExtraLinkerFlags, BuildFlag_ExtraAssemblerFlags, BuildFlag_Microarch, + BuildFlag_TargetFeatures, BuildFlag_RelocMode, BuildFlag_DisableRedZone, @@ -783,7 +784,8 @@ bool parse_build_flags(Array args) { add_flag(&build_flags, BuildFlag_IgnoreUnknownAttributes, str_lit("ignore-unknown-attributes"), BuildFlagParam_None, Command__does_check); add_flag(&build_flags, BuildFlag_ExtraLinkerFlags, str_lit("extra-linker-flags"), BuildFlagParam_String, Command__does_build); add_flag(&build_flags, BuildFlag_ExtraAssemblerFlags, str_lit("extra-assembler-flags"), BuildFlagParam_String, Command__does_build); - add_flag(&build_flags, BuildFlag_Microarch, str_lit("microarch"), BuildFlagParam_String, Command__does_build); + add_flag(&build_flags, BuildFlag_Microarch, str_lit("microarch"), BuildFlagParam_String, Command__does_build); + add_flag(&build_flags, BuildFlag_TargetFeatures, str_lit("target-features"), 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); @@ -1351,6 +1353,12 @@ bool parse_build_flags(Array args) { string_to_lower(&build_context.microarch); break; } + case BuildFlag_TargetFeatures: { + GB_ASSERT(value.kind == ExactValue_String); + build_context.target_features = value.value_string; + string_to_lower(&build_context.target_features); + break; + } case BuildFlag_RelocMode: { GB_ASSERT(value.kind == ExactValue_String); String v = value.value_string; diff --git a/src/string.cpp b/src/string.cpp index bcaf23b9b..d3dbc6904 100644 --- a/src/string.cpp +++ b/src/string.cpp @@ -10,10 +10,6 @@ struct String { u8 * text; isize len; - // u8 &operator[](isize i) { - // GB_ASSERT_MSG(0 <= i && i < len, "[%td]", i); - // return text[i]; - // } u8 const &operator[](isize i) const { GB_ASSERT_MSG(0 <= i && i < len, "[%td]", i); return text[i]; @@ -33,10 +29,6 @@ struct String { struct String16 { wchar_t *text; isize len; - wchar_t &operator[](isize i) { - GB_ASSERT_MSG(0 <= i && i < len, "[%td]", i); - return text[i]; - } wchar_t const &operator[](isize i) const { GB_ASSERT_MSG(0 <= i && i < len, "[%td]", i); return text[i]; From 15d783e920abd0cabb918eed4a982efe577bfe54 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 28 Feb 2022 15:13:41 +0000 Subject: [PATCH 19/56] Enforce `-no-entry-point` on freestanding targets --- src/build_settings.cpp | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/build_settings.cpp b/src/build_settings.cpp index e94fade4e..c94f914dc 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -1006,12 +1006,20 @@ void init_build_context(TargetMetrics *cross_target) { #endif if (bc->disable_red_zone) { - if (!(bc->metrics.os == TargetOs_freestanding && !is_arch_wasm())) { + if (!!is_arch_wasm() && bc->metrics.os == TargetOs_freestanding) { gb_printf_err("-disable-red-zone is not support for this target"); gb_exit(1); } } + if (bc->metrics.os == TargetOs_freestanding) { + bc->no_entry_point = true; + } else { + if (bc->disallow_rtti) { + gb_printf_err("-disallow-rtti is only allowed on freestanding targets\n"); + 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 @@ -1063,14 +1071,14 @@ void init_build_context(TargetMetrics *cross_target) { if (bc->metrics.arch == TargetArch_wasm64) { link_flags = gb_string_appendc(link_flags, "-mwas64 "); } - if (bc->metrics.os == TargetOs_freestanding) { + if (bc->no_entry_point) { link_flags = gb_string_appendc(link_flags, "--no-entry "); } bc->link_flags = make_string_c(link_flags); // Disallow on wasm - build_context.use_separate_modules = false; + bc->use_separate_modules = false; } else { gb_printf_err("Compiler Error: Unsupported architecture\n"); gb_exit(1); @@ -1078,10 +1086,7 @@ void init_build_context(TargetMetrics *cross_target) { bc->optimization_level = gb_clamp(bc->optimization_level, 0, 3); - if (bc->disallow_rtti && bc->metrics.os != TargetOs_freestanding) { - gb_printf_err("-disallow-rtti is only allowed on freestanding targets\n"); - gb_exit(1); - } + #undef LINK_FLAG_X64 #undef LINK_FLAG_386 From 4f3b5d8dcb3be98d7b11efd49f3aec758e51bd2a Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 28 Feb 2022 15:29:08 +0000 Subject: [PATCH 20/56] Clean up `generate_minimum_dependency_set` code --- src/checker.cpp | 75 +++++++++++++++++++++++++++---------------------- 1 file changed, 41 insertions(+), 34 deletions(-) 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) { From fc4eb4152cd9e95ee1e020d60f89a2e245e8febe Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 28 Feb 2022 15:35:10 +0000 Subject: [PATCH 21/56] Correct calling convention for `_startup_runtime` --- core/runtime/core.odin | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/runtime/core.odin b/core/runtime/core.odin index 83a5418ed..3f6b03107 100644 --- a/core/runtime/core.odin +++ b/core/runtime/core.odin @@ -451,7 +451,7 @@ Odin_Endian_Type :: type_of(ODIN_ENDIAN) // This is probably only useful for freestanding targets foreign { @(link_name="__$startup_runtime") - _startup_runtime :: proc() --- + _startup_runtime :: proc "odin" () --- } @(link_name="__$cleanup_runtime") From 0ae012ba08c1981952dc508ab2b6244331926ba1 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 28 Feb 2022 15:37:15 +0000 Subject: [PATCH 22/56] Correct comment --- src/check_type.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/check_type.cpp b/src/check_type.cpp index ff2c3d6a6..ecb2c26ea 100644 --- a/src/check_type.cpp +++ b/src/check_type.cpp @@ -2174,7 +2174,7 @@ void init_map_entry_type(Type *type) { /* struct { - hash: runtime.Map_Hash, + hash: uintptr, next: int, key: Key, value: Value, From 410b85b5c7f768543e03c9fc6f47f8c2efcd602b Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 28 Feb 2022 15:40:00 +0000 Subject: [PATCH 23/56] 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(-) 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"), From b94a7a87fabba83ecb7774f6a2d8a23c0075955a Mon Sep 17 00:00:00 2001 From: gitlost Date: Tue, 8 Mar 2022 18:06:25 +0000 Subject: [PATCH 24/56] Fix issue #1574 "fract in linalg/glm is broken" by fixing trunc_f16/32/64 in "math.odin" (~ typos on expressions) Fix classify_f16 Inf test (would fail for subnormal 0h0001) by changing multiplier 0.5 -> 0.25 Add some useful consts to "math.odin" (INF_F16 etc) Add comment to "demo.odin" mentioning that -0.0 must be used to specify negative zero --- core/math/math.odin | 31 +- examples/demo/demo.odin | 1 + tests/common/common.odin | 41 +++ tests/core/Makefile | 11 +- .../linalg/glsl/test_linalg_glsl_math.odin | 85 +++++ tests/core/math/test_core_math.odin | 310 ++++++++++++++++++ 6 files changed, 472 insertions(+), 7 deletions(-) create mode 100644 tests/common/common.odin create mode 100644 tests/core/math/linalg/glsl/test_linalg_glsl_math.odin create mode 100644 tests/core/math/test_core_math.odin diff --git a/core/math/math.odin b/core/math/math.odin index b81598da9..afbda051d 100644 --- a/core/math/math.odin +++ b/core/math/math.odin @@ -396,7 +396,7 @@ trunc_f16 :: proc "contextless" (x: f16) -> f16 { e := (x >> shift) & mask - bias if e < shift { - x &= ~(1 << (shift-e)) - 1 + x &~= 1 << (shift-e) - 1 } return transmute(f16)x } @@ -428,7 +428,7 @@ trunc_f32 :: proc "contextless" (x: f32) -> f32 { e := (x >> shift) & mask - bias if e < shift { - x &= ~(1 << (shift-e)) - 1 + x &~= 1 << (shift-e) - 1 } return transmute(f32)x } @@ -460,7 +460,7 @@ trunc_f64 :: proc "contextless" (x: f64) -> f64 { e := (x >> shift) & mask - bias if e < shift { - x &= ~(1 << (shift-e)) - 1 + x &~= 1 << (shift-e) - 1 } return transmute(f64)x } @@ -473,6 +473,7 @@ trunc_f64 :: proc "contextless" (x: f64) -> f64 { } trunc_f64le :: proc "contextless" (x: f64le) -> f64le { return #force_inline f64le(trunc_f64(f64(x))) } trunc_f64be :: proc "contextless" (x: f64be) -> f64be { return #force_inline f64be(trunc_f64(f64(x))) } +// Removes the fractional part of the value, i.e. rounds towards zero. trunc :: proc{ trunc_f16, trunc_f16le, trunc_f16be, trunc_f32, trunc_f32le, trunc_f32be, @@ -958,7 +959,7 @@ classify_f16 :: proc "contextless" (x: f16) -> Float_Class { return .Neg_Zero } return .Zero - case x*0.5 == x: + case x*0.25 == x: if x < 0 { return .Neg_Inf } @@ -1027,6 +1028,8 @@ classify_f64 :: proc "contextless" (x: f64) -> Float_Class { } classify_f64le :: proc "contextless" (x: f64le) -> Float_Class { return #force_inline classify_f64(f64(x)) } classify_f64be :: proc "contextless" (x: f64be) -> Float_Class { return #force_inline classify_f64(f64(x)) } +// Returns the `Float_Class` of the value, i.e. whether normal, subnormal, zero, negative zero, NaN, infinity or +// negative infinity. classify :: proc{ classify_f16, classify_f16le, classify_f16be, classify_f32, classify_f32le, classify_f32be, @@ -1715,4 +1718,22 @@ F32_BIAS :: 0x7f F64_MASK :: 0x7ff F64_SHIFT :: 64 - 12 -F64_BIAS :: 0x3ff \ No newline at end of file +F64_BIAS :: 0x3ff + +INF_F16 :f16: 0h7C00 +NEG_INF_F16 :f16: 0hFC00 + +SNAN_F16 :f16: 0h7C01 +QNAN_F16 :f16: 0h7E01 + +INF_F32 :f32: 0h7F80_0000 +NEG_INF_F32 :f32: 0hFF80_0000 + +SNAN_F32 :f32: 0hFF80_0001 +QNAN_F32 :f32: 0hFFC0_0001 + +INF_F64 :f64: 0h7FF0_0000_0000_0000 +NEG_INF_F64 :f64: 0hFFF0_0000_0000_0000 + +SNAN_F64 :f64: 0h7FF0_0000_0000_0001 +QNAN_F64 :f64: 0h7FF8_0000_0000_0001 \ No newline at end of file diff --git a/examples/demo/demo.odin b/examples/demo/demo.odin index 044860ff7..4d4490446 100644 --- a/examples/demo/demo.odin +++ b/examples/demo/demo.odin @@ -94,6 +94,7 @@ the_basics :: proc() { z: f64 // `z` is typed of type `f64` (64-bit floating point number) z = 1 // `1` is an untyped integer literal which can be implicitly converted to `f64` // No need for any suffixes or decimal places like in other languages + // (with the exception of negative zero, which must be given as `-0.0`) // CONSTANTS JUST WORK!!! diff --git a/tests/common/common.odin b/tests/common/common.odin new file mode 100644 index 000000000..2f5272b03 --- /dev/null +++ b/tests/common/common.odin @@ -0,0 +1,41 @@ +// Boilerplate for tests +package common + +import "core:testing" +import "core:fmt" +import "core:os" + +TEST_count := 0 +TEST_fail := 0 + +when ODIN_TEST { + expect :: testing.expect + log :: testing.log +} else { + expect :: proc(t: ^testing.T, condition: bool, message: string, loc := #caller_location) { + TEST_count += 1 + if !condition { + TEST_fail += 1 + fmt.printf("[%v] FAIL %s\n", loc, message) + return + } + fmt.printf("[%v] PASS\n", loc) + } + log :: proc(t: ^testing.T, v: any, loc := #caller_location) { + fmt.printf("[%v]", loc) + fmt.printf(" log: %v\n", v) + } +} + +report :: proc(t: ^testing.T) { + if TEST_fail > 0 { + if TEST_fail > 1 { + fmt.printf("%v/%v tests successful, %v tests failed.\n", TEST_count - TEST_fail, TEST_count, TEST_fail) + } else { + fmt.printf("%v/%v tests successful, %v test failed.\n", TEST_count - TEST_fail, TEST_count, TEST_fail) + } + os.exit(1) + } else { + fmt.printf("%v/%v tests successful.\n", TEST_count, TEST_count) + } +} diff --git a/tests/core/Makefile b/tests/core/Makefile index 1c2cee6bd..c003e4bc8 100644 --- a/tests/core/Makefile +++ b/tests/core/Makefile @@ -1,7 +1,8 @@ ODIN=../../odin PYTHON=$(shell which python3) -all: download_test_assets image_test compress_test strings_test hash_test crypto_test noise_test +all: download_test_assets image_test compress_test strings_test hash_test crypto_test noise_test \ + math_test linalg_glsl_math_test download_test_assets: $(PYTHON) download_assets.py @@ -22,4 +23,10 @@ crypto_test: $(ODIN) run crypto -out=crypto_hash -o:speed -no-bounds-check noise_test: - $(ODIN) run math/noise -out=test_noise \ No newline at end of file + $(ODIN) run math/noise -out=test_noise + +math_test: + $(ODIN) run math/test_core_math.odin -collection:tests=.. + +linalg_glsl_math_test: + $(ODIN) run math/linalg/glsl/test_linalg_glsl_math.odin -collection:tests=.. \ No newline at end of file diff --git a/tests/core/math/linalg/glsl/test_linalg_glsl_math.odin b/tests/core/math/linalg/glsl/test_linalg_glsl_math.odin new file mode 100644 index 000000000..e0b4f5145 --- /dev/null +++ b/tests/core/math/linalg/glsl/test_linalg_glsl_math.odin @@ -0,0 +1,85 @@ +// Tests "linalg_glsl_math.odin" in "core:math/linalg/glsl". +// Must be run with `-collection:tests=` flag, e.g. +// ./odin run tests/core/math/linalg/glsl/test_linalg_glsl_math.odin -collection:tests=./tests +package test_core_math_linalg_glsl_math + +import glsl "core:math/linalg/glsl" + +import "core:fmt" +import "core:math" +import "core:testing" +import tc "tests:common" + +main :: proc() { + + t := testing.T{} + + test_fract_f32(&t) + test_fract_f64(&t) + + tc.report(&t) +} + +@test +test_fract_f32 :: proc(t: ^testing.T) { + + using math + + r: f32 + + Datum :: struct { + i: int, + v: f32, + e: f32, + } + @static data := []Datum{ + { 0, 10.5, 0.5 }, // Issue #1574 fract in linalg/glm is broken + { 1, -10.5, -0.5 }, + { 2, F32_MIN, F32_MIN }, // 0x1p-126 + { 3, -F32_MIN, -F32_MIN }, + { 4, 0.0, 0.0 }, + { 5, -0.0, -0.0 }, + { 6, 1, 0.0 }, + { 7, -1, -0.0 }, + { 8, 0h3F80_0001, 0h3400_0000 }, // 0x1.000002p+0, 0x1p-23 + { 9, -0h3F80_0001, -0h3400_0000 }, + } + + for d, i in data { + assert(i == d.i) + r = glsl.fract(d.v) + tc.expect(t, r == d.e, fmt.tprintf("i:%d %s(%v (%h)) -> %v (%h) != %v", i, #procedure, d.v, d.v, r, r, d.e)) + } +} + +@test +test_fract_f64 :: proc(t: ^testing.T) { + + using math + + r: f64 + + Datum :: struct { + i: int, + v: f64, + e: f64, + } + @static data := []Datum{ + { 0, 10.5, 0.5 }, // Issue #1574 fract in linalg/glm is broken + { 1, -10.5, -0.5 }, + { 2, F64_MIN, F64_MIN }, // 0x1p-1022 + { 3, -F64_MIN, -F64_MIN }, + { 4, 0.0, 0.0 }, + { 5, -0.0, -0.0 }, + { 6, 1, 0.0 }, + { 7, -1, -0.0 }, + { 8, 0h3FF0_0000_0000_0001, 0h3CB0_0000_0000_0000 }, // 0x1.0000000000001p+0, 0x1p-52 + { 9, -0h3FF0_0000_0000_0001, -0h3CB0_0000_0000_0000 }, + } + + for d, i in data { + assert(i == d.i) + r = glsl.fract(d.v) + tc.expect(t, r == d.e, fmt.tprintf("i:%d %s(%v (%h)) -> %v (%h) != %v", i, #procedure, d.v, d.v, r, r, d.e)) + } +} diff --git a/tests/core/math/test_core_math.odin b/tests/core/math/test_core_math.odin new file mode 100644 index 000000000..57da27002 --- /dev/null +++ b/tests/core/math/test_core_math.odin @@ -0,0 +1,310 @@ +// Tests "math.odin" in "core:math". +// Must be run with `-collection:tests=` flag, e.g. +// ./odin run tests/core/math/test_core_math.odin -collection:tests=./tests +package test_core_math + +import "core:fmt" +import "core:math" +import "core:testing" +import tc "tests:common" + +main :: proc() { + t := testing.T{} + + test_classify_f16(&t) + test_classify_f32(&t) + test_classify_f64(&t) + + test_trunc_f16(&t) + test_trunc_f32(&t) + test_trunc_f64(&t) + + tc.report(&t) +} + +@test +test_classify_f16 :: proc(t: ^testing.T) { + + using math + using Float_Class + + r: Float_Class + + Datum :: struct { + i: int, + v: f16, + e: math.Float_Class, + } + @static data := []Datum{ + { 0, 1.2, Normal }, + { 1, 0h0001, Subnormal }, + { 2, 0.0, Zero }, + { 3, -0.0, Neg_Zero }, + { 4, SNAN_F16, NaN }, + { 5, QNAN_F16, NaN }, + { 6, INF_F16, Inf }, + { 7, NEG_INF_F16, Neg_Inf }, + } + + for d, i in data { + assert(i == d.i) + r = classify_f16(d.v) + tc.expect(t, r == d.e, fmt.tprintf("i:%d %s(%h) -> %v != %v", i, #procedure, d.v, r, d.e)) + } + + /* Check all subnormals (exponent 0, 10-bit significand non-zero) */ + for i :u16 = 1; i < 0x400; i += 1 { + v :f16 = transmute(f16)i + r = classify_f16(v) + e :Float_Class: Subnormal + tc.expect(t, r == e, fmt.tprintf("i:%d %s(%h) -> %v != %v", i, #procedure, v, r, e)) + } +} + +@test +test_classify_f32 :: proc(t: ^testing.T) { + + using math + using Float_Class + + r: Float_Class + + Datum :: struct { + i: int, + v: f32, + e: math.Float_Class, + } + @static data := []Datum{ + { 0, 1.2, Normal }, + { 1, 0h0000_0001, Subnormal }, + { 2, 0.0, Zero }, + { 3, -0.0, Neg_Zero }, + { 4, SNAN_F32, NaN }, + { 5, QNAN_F32, NaN }, + { 6, INF_F32, Inf }, + { 7, NEG_INF_F32, Neg_Inf }, + } + + for d, i in data { + assert(i == d.i) + r = classify_f32(d.v) + tc.expect(t, r == d.e, fmt.tprintf("i:%d %s(%h) -> %v != %v", i, #procedure, d.v, r, d.e)) + } +} + +@test +test_classify_f64 :: proc(t: ^testing.T) { + + using math + using Float_Class + + r: Float_Class + + Datum :: struct { + i: int, + v: f64, + e: math.Float_Class, + } + @static data := []Datum{ + { 0, 1.2, Normal }, + { 1, 0h0000_0000_0000_0001, Subnormal }, + { 2, 0.0, Zero }, + { 3, -0.0, Neg_Zero }, + { 4, SNAN_F64, NaN }, + { 5, QNAN_F64, NaN }, + { 6, INF_F64, Inf }, + { 7, NEG_INF_F64, Neg_Inf }, + } + + for d, i in data { + assert(i == d.i) + r = classify_f64(d.v) + tc.expect(t, r == d.e, fmt.tprintf("i:%d %s(%h) -> %v != %v", i, #procedure, d.v, r, d.e)) + } +} + +@test +test_trunc_f16 :: proc(t: ^testing.T) { + + using math + + r, v: f16 + + Datum :: struct { + i: int, + v: f16, + e: f16, + } + @static data := []Datum{ + { 0, 10.5, 10 }, // Issue #1574 fract in linalg/glm is broken + { 1, -10.5, -10 }, + + { 2, F16_MAX, F16_MAX }, + { 3, -F16_MAX, -F16_MAX }, + { 4, F16_MIN, 0.0 }, + { 5, -F16_MIN, -0.0 }, + { 6, 0.0, 0.0 }, + { 7, -0.0, -0.0 }, + { 8, 1, 1 }, + { 9, -1, -1 }, + { 10, INF_F16, INF_F16 }, + { 11, NEG_INF_F16, NEG_INF_F16 }, + + /* From https://en.wikipedia.org/wiki/Half-precision_floating-point_format */ + { 12, 0h3C01, 1 }, // 0x1.004p+0 (smallest > 1) + { 13, -0h3C01, -1 }, + { 14, 0h3BFF, 0.0 }, // 0x1.ffcp-1 (largest < 1) + { 15, -0h3BFF, -0.0 }, + { 16, 0h0001, 0.0 }, // 0x0.004p-14 (smallest subnormal) + { 17, -0h0001, -0.0 }, + { 18, 0h03FF, 0.0 }, // 0x0.ffcp-14 (largest subnormal) + { 19, -0h03FF, -0.0 }, + + { 20, 0hC809, -8 }, // -0x1.024p+3 + { 21, 0h4458, 4 }, // 0x1.16p+2 + } + + for d, i in data { + assert(i == d.i) + r = trunc_f16(d.v) + tc.expect(t, r == d.e, fmt.tprintf("i:%d %s(%h) -> %h != %h", i, #procedure, d.v, r, d.e)) + } + + v = SNAN_F16 + r = trunc_f16(v) + tc.expect(t, is_nan_f16(r), fmt.tprintf("%s(%f) -> %f != NaN", #procedure, v, r)) + + v = QNAN_F16 + r = trunc_f16(v) + tc.expect(t, is_nan_f16(r), fmt.tprintf("%s(%f) -> %f != NaN", #procedure, v, r)) +} + +@test +test_trunc_f32 :: proc(t: ^testing.T) { + + using math + + r, v: f32 + + Datum :: struct { + i: int, + v: f32, + e: f32, + } + @static data := []Datum{ + { 0, 10.5, 10 }, // Issue #1574 fract in linalg/glm is broken + { 1, -10.5, -10 }, + + { 2, F32_MAX, F32_MAX }, + { 3, -F32_MAX, -F32_MAX }, + { 4, F32_MIN, 0.0 }, + { 5, -F32_MIN, -0.0 }, + { 6, 0.0, 0.0 }, + { 7, -0.0, -0.0 }, + { 8, 1, 1 }, + { 9, -1, -1 }, + { 10, INF_F32, INF_F32 }, + { 11, NEG_INF_F32, NEG_INF_F32 }, + + /* From https://en.wikipedia.org/wiki/Single-precision_floating-point_format */ + { 12, 0h3F80_0001, 1 }, // 0x1.000002p+0 (smallest > 1) + { 13, -0h3F80_0001, -1 }, + { 14, 0h3F7F_FFFF, 0.0 }, // 0x1.fffffep-1 (largest < 1) + { 15, -0h3F7F_FFFF, -0.0 }, + { 16, 0h0000_0001, 0.0 }, // 0x0.000002p-126 (smallest subnormal) + { 17, -0h0000_0001, -0.0 }, + { 18, 0h007F_FFFF, 0.0 }, // 0x0.fffffep-126 (largest subnormal) + { 19, -0h007F_FFFF, -0.0 }, + + /* From libc-test src/math/sanity/truncf.h */ + { 20, 0hC101_11D0, -8 }, // -0x1.0223ap+3 + { 21, 0h408B_0C34, 4 }, // 0x1.161868p+2 + { 22, 0hC106_1A5A, -8 }, // -0x1.0c34b4p+3 + { 23, 0hC0D1_0378, -6 }, // -0x1.a206fp+2 + { 24, 0h4114_45DE, 9 }, // 0x1.288bbcp+3 + { 25, 0h3F29_77E8, 0.0 }, // 0x1.52efdp-1 + { 26, 0hBED0_2E64, -0.0 }, // -0x1.a05cc8p-2 + { 27, 0h3F0F_CF7D, 0.0 }, // 0x1.1f9efap-1 + { 28, 0h3F46_2ED8, 0.0 }, // 0x1.8c5dbp-1 + { 29, 0hBF2D_C375, -0.0 }, // -0x1.5b86eap-1 + } + + for d, i in data { + assert(i == d.i) + r = trunc_f32(d.v) + tc.expect(t, r == d.e, fmt.tprintf("i:%d %s(%h) -> %h != %h", i, #procedure, d.v, r, d.e)) + } + + v = SNAN_F32 + r = trunc_f32(v) + tc.expect(t, is_nan_f32(r), fmt.tprintf("%s(%f) -> %f != NaN", #procedure, v, r)) + + v = QNAN_F32 + r = trunc_f32(v) + tc.expect(t, is_nan_f32(r), fmt.tprintf("%s(%f) -> %f != NaN", #procedure, v, r)) +} + +@test +test_trunc_f64 :: proc(t: ^testing.T) { + + using math + + r, v: f64 + + Datum :: struct { + i: int, + v: f64, + e: f64, + } + data := []Datum{ + { 0, 10.5, 10 }, // Issue #1574 fract in linalg/glm is broken + { 1, -10.5, -10 }, + + { 2, F64_MAX, F64_MAX }, + { 3, -F64_MAX, -F64_MAX }, + { 4, F64_MIN, 0.0 }, + { 5, -F64_MIN, -0.0 }, + { 6, 0.0, 0.0 }, + { 7, -0.0, -0.0 }, + { 8, 1, 1 }, + { 9, -1, -1 }, + { 10, INF_F64, INF_F64 }, + { 11, NEG_INF_F64, NEG_INF_F64 }, + + /* From https://en.wikipedia.org/wiki/Double-precision_floating-point_format */ + { 12, 0h3FF0_0000_0000_0001, 1 }, // 0x1.0000000000001p+0 (smallest > 1) + { 13, -0h3FF0_0000_0000_0001, -1 }, + { 14, 0h3FEF_FFFF_FFFF_FFFF, 0.0 }, // 0x1.fffffffffffffp-1 (largest < 1) + { 15, -0h3FEF_FFFF_FFFF_FFFF, -0.0 }, + { 16, 0h0000_0000_0000_0001, 0.0 }, // 0x0.0000000000001p-1022 (smallest subnormal) + { 17, -0h0000_0000_0000_0001, -0.0 }, + { 18, 0h000F_FFFF_FFFF_FFFF, 0.0 }, // 0x0.fffffffffffffp-1022 (largest subnormal) + { 19, -0h000F_FFFF_FFFF_FFFF, -0.0 }, + + /* From libc-test src/math/sanity/trunc.h */ + { 20, 0hC020_2239_F3C6_A8F1, -8 }, // -0x1.02239f3c6a8f1p+3 + { 21, 0h4011_6186_8E18_BC67, 4 }, // 0x1.161868e18bc67p+2 + { 22, 0hC020_C34B_3E01_E6E7, -8 }, // -0x1.0c34b3e01e6e7p+3 + { 23, 0hC01A_206F_0A19_DCC4, -6 }, // -0x1.a206f0a19dcc4p+2 + { 24, 0h4022_88BB_B0D6_A1E6, 9 }, // 0x1.288bbb0d6a1e6p+3 + { 25, 0h3FE5_2EFD_0CD8_0497, 0.0 }, // 0x1.52efd0cd80497p-1 + { 26, 0hBFDA_05CC_7544_81D1, -0.0 }, // -0x1.a05cc754481d1p-2 + { 27, 0h3FE1_F9EF_9347_45CB, 0.0 }, // 0x1.1f9ef934745cbp-1 + { 28, 0h3FE8_C5DB_097F_7442, 0.0 }, // 0x1.8c5db097f7442p-1 + { 29, 0hBFE5_B86E_A811_8A0E, -0.0 }, // -0x1.5b86ea8118a0ep-1 + } + + for d, i in data { + assert(i == d.i) + r = trunc_f64(d.v) + tc.expect(t, r == d.e, fmt.tprintf("i:%d %s(%h) -> %h != %h", i, #procedure, d.v, r, d.e)) + } + + v = SNAN_F64 + r = trunc_f64(v) + tc.expect(t, is_nan_f64(r), fmt.tprintf("%s(%f) -> %f != NaN", #procedure, v, r)) + + v = QNAN_F64 + r = trunc_f64(v) + tc.expect(t, is_nan_f64(r), fmt.tprintf("%s(%f) -> %f != NaN", #procedure, v, r)) +} From 0278ac85a04309c8777663afe733e984a44bbcc8 Mon Sep 17 00:00:00 2001 From: Al Hoang <3811822-hoanga@users.noreply.gitlab.com> Date: Tue, 8 Mar 2022 23:48:25 -0600 Subject: [PATCH 25/56] update to build for FreeBSD --- Makefile | 6 ++++++ core/os/os_freebsd.odin | 4 ++-- core/os/stat_unix.odin | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index ceff3c207..b8bf26a88 100644 --- a/Makefile +++ b/Makefile @@ -62,6 +62,12 @@ ifeq ($(OS), OpenBSD) CFLAGS:=$(CFLAGS) $(shell $(LLVM_CONFIG) --cxxflags --ldflags) LDFLAGS:=$(LDFLAGS) $(shell $(LLVM_CONFIG) --libs core native --system-libs) endif +ifeq ($(OS), FreeBSD) + LLVM_CONFIG=/usr/local/bin/llvm-config11 + + CFLAGS:=$(CFLAGS) $(shell $(LLVM_CONFIG) --cxxflags --ldflags) + LDFLAGS:=$(LDFLAGS) $(shell $(LLVM_CONFIG) --libs core native --system-libs) +endif all: debug demo diff --git a/core/os/os_freebsd.odin b/core/os/os_freebsd.odin index e31eb31bb..4f31b1492 100644 --- a/core/os/os_freebsd.odin +++ b/core/os/os_freebsd.odin @@ -232,10 +232,10 @@ foreign libc { @(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="lseek64") _unix_seek :: proc(fd: Handle, offset: i64, whence: c.int) -> i64 --- + @(link_name="lseek") _unix_seek :: proc(fd: Handle, offset: i64, whence: c.int) -> i64 --- @(link_name="gettid") _unix_gettid :: proc() -> u64 --- @(link_name="getpagesize") _unix_getpagesize :: proc() -> c.int --- - @(link_name="stat64") _unix_stat :: proc(path: cstring, stat: ^OS_Stat) -> c.int --- + @(link_name="stat") _unix_stat :: proc(path: cstring, stat: ^OS_Stat) -> c.int --- @(link_name="fstat") _unix_fstat :: proc(fd: Handle, stat: ^OS_Stat) -> c.int --- @(link_name="access") _unix_access :: proc(path: cstring, mask: c.int) -> c.int --- diff --git a/core/os/stat_unix.odin b/core/os/stat_unix.odin index 2aa9fc283..c82466b08 100644 --- a/core/os/stat_unix.odin +++ b/core/os/stat_unix.odin @@ -1,4 +1,4 @@ -//+build linux, darwin, freebsd, openbsd +//+build linux, darwin, openbsd package os import "core:time" From 5eebdebec89aa4a6041cf1eb4b72a74bbd669db4 Mon Sep 17 00:00:00 2001 From: Colin Davidson Date: Wed, 9 Mar 2022 05:09:39 -0800 Subject: [PATCH 26/56] Make llvm-config build more general for linux --- Makefile | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/Makefile b/Makefile index ceff3c207..e77acea93 100644 --- a/Makefile +++ b/Makefile @@ -30,25 +30,29 @@ ifeq ($(OS), Darwin) ifeq ($(shell $(LLVM_CONFIG) --version | grep -E $(LLVM_VERSION_PATTERN)),) ifeq ($(ARCH), arm64) $(error "Requirement: llvm-config must be base version 13 for arm64") - else + else $(error "Requirement: llvm-config must be base version greater than 11 for amd64/x86") - endif - endif + endif + endif LDFLAGS:=$(LDFLAGS) -liconv -ldl CFLAGS:=$(CFLAGS) $(shell $(LLVM_CONFIG) --cxxflags --ldflags) LDFLAGS:=$(LDFLAGS) -lLLVM-C endif ifeq ($(OS), Linux) - LLVM_CONFIG=llvm-config-11 - ifneq ($(shell which llvm-config-11 2>/dev/null),) - LLVM_CONFIG=llvm-config-11 - else ifneq ($(shell which llvm-config-11-64 2>/dev/null),) - LLVM_CONFIG=llvm-config-11-64 - else - ifeq ($(shell $(LLVM_CONFIG) --version | grep '^11\.'),) - $(error "Requirement: llvm-config must be version 11") - endif + LLVM_CONFIG=llvm-config + + LLVM_VERSIONS = "13.%.%" "12.0.1" "11.1.0" + + LLVM_VERSION_PATTERN_SEPERATOR = )|( + LLVM_VERSION_PATTERNS_ESCAPED_DOT = $(subst .,\.,$(LLVM_VERSIONS)) + LLVM_VERSION_PATTERNS_REPLACE_PERCENT = $(subst %,.*,$(LLVM_VERSION_PATTERNS_ESCAPED_DOT)) + LLVM_VERSION_PATTERN_REMOVE_ELEMENTS = $(subst " ",$(LLVM_VERSION_PATTERN_SEPERATOR),$(LLVM_VERSION_PATTERNS_REPLACE_PERCENT)) + LLMV_VERSION_PATTERN_REMOVE_SINGLE_STR = $(subst ",,$(LLVM_VERSION_PATTERN_REMOVE_ELEMENTS)) + LLVM_VERSION_PATTERN = "^(($(LLMV_VERSION_PATTERN_REMOVE_SINGLE_STR)))" + + ifeq ($(shell $(LLVM_CONFIG) --version | grep -E $(LLVM_VERSION_PATTERN)),) + $(error "Requirement: llvm-config must be base version greater than 11") endif LDFLAGS:=$(LDFLAGS) -ldl From 3092fb2ff3ab776290eefb8df27def79cc1fbe77 Mon Sep 17 00:00:00 2001 From: Colin Davidson Date: Wed, 9 Mar 2022 06:01:40 -0800 Subject: [PATCH 27/56] Add initial cut of build script --- build_odin.sh | 118 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100755 build_odin.sh diff --git a/build_odin.sh b/build_odin.sh new file mode 100755 index 000000000..5b3767a1a --- /dev/null +++ b/build_odin.sh @@ -0,0 +1,118 @@ +#!/bin/bash +set -eu + +GIT_SHA=$(git rev-parse --short HEAD) +DISABLED_WARNINGS="-Wno-switch -Wno-macro-redefined -Wno-unused-value" +LDFLAGS="-pthread -lm -lstdc++" +CFLAGS="-std=c++14 -DGIT_SHA=\"$GIT_SHA\"" +CFLAGS="$CFLAGS -DODIN_VERSION_RAW=\"dev-$(date +"%Y-%m")\"" +CC=clang +OS=$(uname) + +panic() { + printf "%s\n" "$1" + exit 1 +} + +config_darwin() { + ARCH=$(uname -m) + LLVM_CONFIG=llvm-config + + # allow for arm only llvm's with version 13 + if [ ARCH == arm64 ]; then + LLVM_VERSIONS="13.%.%" + else + # allow for x86 / amd64 all llvm versions begining from 11 + LLVM_VERSIONS="13.%.%" "12.0.1" "11.1.0" + fi + + if [ $($LLVM_CONFIG --version | grep -E $(LLVM_VERSION_PATTERN)) == 0 ]; then + if [ ARCH == arm64 ]; then + panic "Requirement: llvm-config must be base version 13 for arm64" + else + panic "Requirement: llvm-config must be base version greater than 11 for amd64/x86" + fi + fi + + LDFLAGS="$LDFLAGS -liconv -ldl" + CFLAGS="$CFLAGS $($LLVM_CONFIG --cxxflags --ldflags)" + LDFLAGS="$LDFLAGS -lLLVM-C" +} + +config_openbsd() { + LLVM_CONFIG=/usr/local/bin/llvm-config + + LDFLAGS="$LDFLAGS -liconv" + CFLAGS="$CFLAGS $($LLVM_CONFIG --cxxflags --ldflags)" + LDFLAGS="$LDFLAGS $($LLVM_CONFIG --libs core native --system-libs)" +} + +config_linux() { + LLVM_CONFIG=llvm-config + + LDFLAGS="$LDFLAGS -ldl" + CFLAGS="$CFLAGS $($LLVM_CONFIG --cxxflags --ldflags)" + LDFLAGS="$LDFLAGS $($LLVM_CONFIG --libs core native --system-libs)" +} + +build_odin() { + set -x + $CC src/main.cpp src/libtommath.cpp $DISABLED_WARNINGS $CFLAGS $EXTRAFLAGS $LDFLAGS -o odin + set +x +} + +run_demo() { + ./odin run examples/demo/demo.odin +} + +case $OS in +Linux) + config_linux + ;; +Darwin) + config_darwin + ;; +OpenBSD) + config_openbsd + ;; +esac + +if [[ $# -eq 0 ]]; then + EXTRAFLAGS="-g" + + build_odin + run_demo + + exit 0 +fi + +if [[ $# -eq 1 ]]; then + case $1 in + report) + EXTRAFLAGS="-g" + build_odin + ./odin report + exit 0 + ;; + debug) + EXTRAFLAGS="-g" + ;; + release) + EXTRAFLAGS="-O3" + ;; + release_native) + EXTRAFLAGS="-O3 -march=native" + ;; + nightly) + EXTRAFLAGS="-DNIGHTLY -O3" + ;; + *) + panic "Unsupported build option!" + ;; + esac + + build_odin + run_demo + + exit 0 +fi From d1477bcfa74fbc04813ceff4e603c1c982fd4d33 Mon Sep 17 00:00:00 2001 From: Colin Davidson Date: Wed, 9 Mar 2022 06:07:19 -0800 Subject: [PATCH 28/56] Fix wonky copied space issues --- build_odin.sh | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/build_odin.sh b/build_odin.sh index 5b3767a1a..e836cb0ac 100755 --- a/build_odin.sh +++ b/build_odin.sh @@ -16,43 +16,43 @@ panic() { config_darwin() { ARCH=$(uname -m) - LLVM_CONFIG=llvm-config + LLVM_CONFIG=llvm-config - # allow for arm only llvm's with version 13 + # allow for arm only llvm's with version 13 if [ ARCH == arm64 ]; then - LLVM_VERSIONS="13.%.%" + LLVM_VERSIONS="13.%.%" else - # allow for x86 / amd64 all llvm versions begining from 11 - LLVM_VERSIONS="13.%.%" "12.0.1" "11.1.0" + # allow for x86 / amd64 all llvm versions begining from 11 + LLVM_VERSIONS="13.%.%" "12.0.1" "11.1.0" fi if [ $($LLVM_CONFIG --version | grep -E $(LLVM_VERSION_PATTERN)) == 0 ]; then if [ ARCH == arm64 ]; then - panic "Requirement: llvm-config must be base version 13 for arm64" + panic "Requirement: llvm-config must be base version 13 for arm64" else panic "Requirement: llvm-config must be base version greater than 11 for amd64/x86" fi - fi + fi - LDFLAGS="$LDFLAGS -liconv -ldl" - CFLAGS="$CFLAGS $($LLVM_CONFIG --cxxflags --ldflags)" - LDFLAGS="$LDFLAGS -lLLVM-C" + LDFLAGS="$LDFLAGS -liconv -ldl" + CFLAGS="$CFLAGS $($LLVM_CONFIG --cxxflags --ldflags)" + LDFLAGS="$LDFLAGS -lLLVM-C" } config_openbsd() { - LLVM_CONFIG=/usr/local/bin/llvm-config + LLVM_CONFIG=/usr/local/bin/llvm-config - LDFLAGS="$LDFLAGS -liconv" - CFLAGS="$CFLAGS $($LLVM_CONFIG --cxxflags --ldflags)" - LDFLAGS="$LDFLAGS $($LLVM_CONFIG --libs core native --system-libs)" + LDFLAGS="$LDFLAGS -liconv" + CFLAGS="$CFLAGS $($LLVM_CONFIG --cxxflags --ldflags)" + LDFLAGS="$LDFLAGS $($LLVM_CONFIG --libs core native --system-libs)" } config_linux() { - LLVM_CONFIG=llvm-config + LLVM_CONFIG=llvm-config - LDFLAGS="$LDFLAGS -ldl" - CFLAGS="$CFLAGS $($LLVM_CONFIG --cxxflags --ldflags)" - LDFLAGS="$LDFLAGS $($LLVM_CONFIG --libs core native --system-libs)" + LDFLAGS="$LDFLAGS -ldl" + CFLAGS="$CFLAGS $($LLVM_CONFIG --cxxflags --ldflags)" + LDFLAGS="$LDFLAGS $($LLVM_CONFIG --libs core native --system-libs)" } build_odin() { From 005d52cab7db883269e325ca8c0bb9e56a6e542e Mon Sep 17 00:00:00 2001 From: Colin Davidson Date: Wed, 9 Mar 2022 06:08:48 -0800 Subject: [PATCH 29/56] more spacing issues --- build_odin.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build_odin.sh b/build_odin.sh index e836cb0ac..634e4aa7f 100755 --- a/build_odin.sh +++ b/build_odin.sh @@ -26,7 +26,7 @@ config_darwin() { LLVM_VERSIONS="13.%.%" "12.0.1" "11.1.0" fi - if [ $($LLVM_CONFIG --version | grep -E $(LLVM_VERSION_PATTERN)) == 0 ]; then + if [ $($LLVM_CONFIG --version | grep -E $(LLVM_VERSION_PATTERN)) == 0 ]; then if [ ARCH == arm64 ]; then panic "Requirement: llvm-config must be base version 13 for arm64" else From f5cc8bd7bf0071d46fb39091a23fe19def22c02b Mon Sep 17 00:00:00 2001 From: Colin Davidson Date: Wed, 9 Mar 2022 06:14:30 -0800 Subject: [PATCH 30/56] only build odin for report when necessary --- build_odin.sh | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/build_odin.sh b/build_odin.sh index 634e4aa7f..77d69a6e5 100755 --- a/build_odin.sh +++ b/build_odin.sh @@ -89,8 +89,11 @@ fi if [[ $# -eq 1 ]]; then case $1 in report) - EXTRAFLAGS="-g" - build_odin + if [[ ! -f "./odin" ]]; then + EXTRAFLAGS="-g" + build_odin + fi + ./odin report exit 0 ;; From db169a4334862a8e49b7492452e4da51aeee814a Mon Sep 17 00:00:00 2001 From: Colin Davidson Date: Wed, 9 Mar 2022 06:26:25 -0800 Subject: [PATCH 31/56] Cleanup build mode selection --- build_odin.sh | 43 ++++++++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/build_odin.sh b/build_odin.sh index 77d69a6e5..dac89acf7 100755 --- a/build_odin.sh +++ b/build_odin.sh @@ -56,6 +56,23 @@ config_linux() { } build_odin() { + case $1 in + debug) + EXTRAFLAGS="-g" + ;; + release) + EXTRAFLAGS="-O3" + ;; + release-native) + EXTRAFLAGS="-O3 -march=native" + ;; + nightly) + EXTRAFLAGS="-DNIGHTLY -O3" + ;; + *) + panic "Build mode unsupported!" + esac + set -x $CC src/main.cpp src/libtommath.cpp $DISABLED_WARNINGS $CFLAGS $EXTRAFLAGS $LDFLAGS -o odin set +x @@ -75,14 +92,13 @@ Darwin) OpenBSD) config_openbsd ;; +*) + panic "Platform unsupported!" esac if [[ $# -eq 0 ]]; then - EXTRAFLAGS="-g" - - build_odin + build_odin debug run_demo - exit 0 fi @@ -90,32 +106,17 @@ if [[ $# -eq 1 ]]; then case $1 in report) if [[ ! -f "./odin" ]]; then - EXTRAFLAGS="-g" - build_odin + build_odin debug fi ./odin report exit 0 ;; - debug) - EXTRAFLAGS="-g" - ;; - release) - EXTRAFLAGS="-O3" - ;; - release_native) - EXTRAFLAGS="-O3 -march=native" - ;; - nightly) - EXTRAFLAGS="-DNIGHTLY -O3" - ;; *) - panic "Unsupported build option!" + build_odin $1 ;; esac - build_odin run_demo - exit 0 fi From d5b0632e4f7aa289c2876d6248508bff6e68a7b5 Mon Sep 17 00:00:00 2001 From: Colin Davidson Date: Wed, 9 Mar 2022 06:27:52 -0800 Subject: [PATCH 32/56] add handling for too many args --- build_odin.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/build_odin.sh b/build_odin.sh index dac89acf7..8cd0849a7 100755 --- a/build_odin.sh +++ b/build_odin.sh @@ -119,4 +119,6 @@ if [[ $# -eq 1 ]]; then run_demo exit 0 +else + panic "Too many arguments!" fi From 9aea990184b35dadbd786b70730111735fb4fc0a Mon Sep 17 00:00:00 2001 From: Colin Davidson Date: Wed, 9 Mar 2022 06:49:52 -0800 Subject: [PATCH 33/56] clean up osx semver handling in build --- build_odin.sh | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/build_odin.sh b/build_odin.sh index 8cd0849a7..80c35dc44 100755 --- a/build_odin.sh +++ b/build_odin.sh @@ -14,19 +14,21 @@ panic() { exit 1 } +function version { echo "$@" | awk -F. '{ printf("%d%03d%03d%03d\n", $1,$2,$3,$4); }'; } + config_darwin() { ARCH=$(uname -m) LLVM_CONFIG=llvm-config # allow for arm only llvm's with version 13 if [ ARCH == arm64 ]; then - LLVM_VERSIONS="13.%.%" + MIN_LLVM_VERSION=("13.0.0") else # allow for x86 / amd64 all llvm versions begining from 11 - LLVM_VERSIONS="13.%.%" "12.0.1" "11.1.0" + MIN_LLVM_VERSION=("11.1.0") fi - if [ $($LLVM_CONFIG --version | grep -E $(LLVM_VERSION_PATTERN)) == 0 ]; then + if [ $(version $($LLVM_CONFIG --version)) -lt $(version $MIN_LLVM_VERSION) ]; then if [ ARCH == arm64 ]; then panic "Requirement: llvm-config must be base version 13 for arm64" else From 34a9f55f3771c05695f3e4c886b7c067d7aec5e2 Mon Sep 17 00:00:00 2001 From: Colin Davidson Date: Wed, 9 Mar 2022 06:52:22 -0800 Subject: [PATCH 34/56] Update ci to use build script --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 412587b3c..cbe3fc08c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -9,7 +9,7 @@ jobs: - name: Download LLVM, botan run: sudo apt-get install llvm-11 clang-11 llvm libbotan-2-dev botan - name: build odin - run: make release + run: ./build_odin.sh release - name: Odin version run: ./odin version timeout-minutes: 1 @@ -55,7 +55,7 @@ jobs: TMP_PATH=$(xcrun --show-sdk-path)/user/include echo "CPATH=$TMP_PATH" >> $GITHUB_ENV - name: build odin - run: make release + run: ./build_odin.sh release - name: Odin version run: ./odin version timeout-minutes: 1 From c543ecd64c0681a7dc92fd3edef670380a24756e Mon Sep 17 00:00:00 2001 From: Colin Davidson Date: Wed, 9 Mar 2022 06:57:59 -0800 Subject: [PATCH 35/56] Try to find llvm-config-11 on goofy misconfigured CI box --- build_odin.sh | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/build_odin.sh b/build_odin.sh index 80c35dc44..911e8a2d5 100755 --- a/build_odin.sh +++ b/build_odin.sh @@ -52,6 +52,15 @@ config_openbsd() { config_linux() { LLVM_CONFIG=llvm-config + MIN_LLVM_VERSION=("11.1.0") + if [ $(version $($LLVM_CONFIG --version)) -lt $(version $MIN_LLVM_VERSION) ]; then + + LLVM_CONFIG=llvm-config-11 + if [ $(version $($LLVM_CONFIG --version)) -lt $(version $MIN_LLVM_VERSION) ]; then + panic "Requirement: llvm-config must be base version greater than 11" + fi + fi + LDFLAGS="$LDFLAGS -ldl" CFLAGS="$CFLAGS $($LLVM_CONFIG --cxxflags --ldflags)" LDFLAGS="$LDFLAGS $($LLVM_CONFIG --libs core native --system-libs)" From 7adaa4dc2b3784997ad38e499133bdfe4651c02c Mon Sep 17 00:00:00 2001 From: Colin Davidson Date: Wed, 9 Mar 2022 07:15:08 -0800 Subject: [PATCH 36/56] refix make, adjust build for CI weirdness --- Makefile | 22 +++++++++------------- build_odin.sh | 16 ++++++++++------ 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/Makefile b/Makefile index e77acea93..8de6ff06b 100644 --- a/Makefile +++ b/Makefile @@ -40,19 +40,15 @@ ifeq ($(OS), Darwin) LDFLAGS:=$(LDFLAGS) -lLLVM-C endif ifeq ($(OS), Linux) - LLVM_CONFIG=llvm-config - - LLVM_VERSIONS = "13.%.%" "12.0.1" "11.1.0" - - LLVM_VERSION_PATTERN_SEPERATOR = )|( - LLVM_VERSION_PATTERNS_ESCAPED_DOT = $(subst .,\.,$(LLVM_VERSIONS)) - LLVM_VERSION_PATTERNS_REPLACE_PERCENT = $(subst %,.*,$(LLVM_VERSION_PATTERNS_ESCAPED_DOT)) - LLVM_VERSION_PATTERN_REMOVE_ELEMENTS = $(subst " ",$(LLVM_VERSION_PATTERN_SEPERATOR),$(LLVM_VERSION_PATTERNS_REPLACE_PERCENT)) - LLMV_VERSION_PATTERN_REMOVE_SINGLE_STR = $(subst ",,$(LLVM_VERSION_PATTERN_REMOVE_ELEMENTS)) - LLVM_VERSION_PATTERN = "^(($(LLMV_VERSION_PATTERN_REMOVE_SINGLE_STR)))" - - ifeq ($(shell $(LLVM_CONFIG) --version | grep -E $(LLVM_VERSION_PATTERN)),) - $(error "Requirement: llvm-config must be base version greater than 11") + LLVM_CONFIG=llvm-config-11 + ifneq ($(shell which llvm-config-11 2>/dev/null),) + LLVM_CONFIG=llvm-config-11 + else ifneq ($(shell which llvm-config-11-64 2>/dev/null),) + LLVM_CONFIG=llvm-config-11-64 + else + ifeq ($(shell $(LLVM_CONFIG) --version | grep '^11\.'),) + $(error "Requirement: llvm-config must be version 11") + endif endif LDFLAGS:=$(LDFLAGS) -ldl diff --git a/build_odin.sh b/build_odin.sh index 911e8a2d5..c707f4e67 100755 --- a/build_odin.sh +++ b/build_odin.sh @@ -50,15 +50,19 @@ config_openbsd() { } config_linux() { - LLVM_CONFIG=llvm-config + if which llvm-config > /dev/null 2>&1; then + LLVM_CONFIG=llvm-config + elif which llvm-config-11 > /dev/null 2>&1; then + LLVM_CONFIG=llvm-config-11 + elif which llvm-config-11-64 > /dev/null 2>&1; then + LLVM_CONFIG=llvm-config-11-64 + else + panic "Unable to find LLVM-config" + fi MIN_LLVM_VERSION=("11.1.0") if [ $(version $($LLVM_CONFIG --version)) -lt $(version $MIN_LLVM_VERSION) ]; then - - LLVM_CONFIG=llvm-config-11 - if [ $(version $($LLVM_CONFIG --version)) -lt $(version $MIN_LLVM_VERSION) ]; then - panic "Requirement: llvm-config must be base version greater than 11" - fi + panic "Requirement: llvm-config must be base version greater than 11" fi LDFLAGS="$LDFLAGS -ldl" From 3bd1ac4c82a0e6944f3218ad38c4f5f5995d703e Mon Sep 17 00:00:00 2001 From: Colin Davidson Date: Wed, 9 Mar 2022 07:18:41 -0800 Subject: [PATCH 37/56] test adjusting apt arg order --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cbe3fc08c..d5179e51b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,7 +7,7 @@ jobs: steps: - uses: actions/checkout@v1 - name: Download LLVM, botan - run: sudo apt-get install llvm-11 clang-11 llvm libbotan-2-dev botan + run: sudo apt-get install llvm llvm-11 clang-11 libbotan-2-dev botan - name: build odin run: ./build_odin.sh release - name: Odin version From 1306c53fb1829b3454c795bf923c8c7f6f3c4483 Mon Sep 17 00:00:00 2001 From: Colin Davidson Date: Wed, 9 Mar 2022 07:21:19 -0800 Subject: [PATCH 38/56] more build tweaks? --- build_odin.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/build_odin.sh b/build_odin.sh index c707f4e67..dc6434e19 100755 --- a/build_odin.sh +++ b/build_odin.sh @@ -62,6 +62,7 @@ config_linux() { MIN_LLVM_VERSION=("11.1.0") if [ $(version $($LLVM_CONFIG --version)) -lt $(version $MIN_LLVM_VERSION) ]; then + echo "Tried to use " $(which $LLVM_CONFIG) "version" $($LLVM_CONFIG --version) panic "Requirement: llvm-config must be base version greater than 11" fi From 7f8a9587e0d375486e3b45f9627463b8ec9421a1 Mon Sep 17 00:00:00 2001 From: Colin Davidson Date: Wed, 9 Mar 2022 07:22:48 -0800 Subject: [PATCH 39/56] more build tweaks? --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d5179e51b..a7aa1b265 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,7 +7,7 @@ jobs: steps: - uses: actions/checkout@v1 - name: Download LLVM, botan - run: sudo apt-get install llvm llvm-11 clang-11 libbotan-2-dev botan + run: sudo apt-get install llvm-11 clang-11 libbotan-2-dev botan - name: build odin run: ./build_odin.sh release - name: Odin version From a2250a5d4918498f6c68423c7dcd02c1910ceaec Mon Sep 17 00:00:00 2001 From: Colin Davidson Date: Wed, 9 Mar 2022 07:24:49 -0800 Subject: [PATCH 40/56] lower minimum llvm version --- build_odin.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build_odin.sh b/build_odin.sh index dc6434e19..11d098952 100755 --- a/build_odin.sh +++ b/build_odin.sh @@ -60,7 +60,7 @@ config_linux() { panic "Unable to find LLVM-config" fi - MIN_LLVM_VERSION=("11.1.0") + MIN_LLVM_VERSION=("11.0.0") if [ $(version $($LLVM_CONFIG --version)) -lt $(version $MIN_LLVM_VERSION) ]; then echo "Tried to use " $(which $LLVM_CONFIG) "version" $($LLVM_CONFIG --version) panic "Requirement: llvm-config must be base version greater than 11" From 2652c2d7a573cc44379d7843472b9f379246d31b Mon Sep 17 00:00:00 2001 From: Colin Davidson Date: Wed, 9 Mar 2022 07:42:38 -0800 Subject: [PATCH 41/56] normalize version parser --- build_odin.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build_odin.sh b/build_odin.sh index 11d098952..a323782a1 100755 --- a/build_odin.sh +++ b/build_odin.sh @@ -14,7 +14,7 @@ panic() { exit 1 } -function version { echo "$@" | awk -F. '{ printf("%d%03d%03d%03d\n", $1,$2,$3,$4); }'; } +version() { echo "$@" | awk -F. '{ printf("%d%03d%03d%03d\n", $1,$2,$3,$4); }'; } config_darwin() { ARCH=$(uname -m) From c6dc5170042057da9bd4708f81017a3a994b2293 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 11 Mar 2022 08:52:16 +0000 Subject: [PATCH 42/56] Correct: murmur32 --- core/hash/hash.odin | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/hash/hash.odin b/core/hash/hash.odin index 5044d567a..f2152f1b6 100644 --- a/core/hash/hash.odin +++ b/core/hash/hash.odin @@ -151,7 +151,7 @@ murmur32 :: proc(data: []byte, seed := u32(0)) -> u32 { k1 ~= u32(tail[2]) << 16 fallthrough case 2: - k1 ~= u32(tail[2]) << 8 + k1 ~= u32(tail[1]) << 8 fallthrough case 1: k1 ~= u32(tail[0]) From 7a7b87181dda2f5b3ac3f3286861f033fdd60aa9 Mon Sep 17 00:00:00 2001 From: Jeroen van Rijn Date: Fri, 11 Mar 2022 11:09:58 +0100 Subject: [PATCH 43/56] [examples] Add `core:encoding/varint` to `examples/all`. --- examples/all/all_main.odin | 2 ++ 1 file changed, 2 insertions(+) diff --git a/examples/all/all_main.odin b/examples/all/all_main.odin index e694060d2..7d2082250 100644 --- a/examples/all/all_main.odin +++ b/examples/all/all_main.odin @@ -54,6 +54,7 @@ import base64 "core:encoding/base64" import csv "core:encoding/csv" import hxa "core:encoding/hxa" import json "core:encoding/json" +import varint "core:encoding/varint" import fmt "core:fmt" import hash "core:hash" @@ -153,6 +154,7 @@ _ :: base64 _ :: csv _ :: hxa _ :: json +_ :: varint _ :: fmt _ :: hash _ :: image From 8982ae34e38d5937b7cb74d95c30cb6a2bac8146 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Marie?= Date: Sat, 12 Mar 2022 09:19:52 +0000 Subject: [PATCH 44/56] fix linux_arm64 - SYS_fork doesn't exist, uses SYS_clone - properly cast AT_FDCWD to uintptr --- core/os/os_linux.odin | 26 +++++++++++++++----------- core/sys/unix/syscalls_linux.odin | 2 ++ 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/core/os/os_linux.odin b/core/os/os_linux.odin index 9716e2925..ed73341c0 100644 --- a/core/os/os_linux.odin +++ b/core/os/os_linux.odin @@ -269,7 +269,7 @@ X_OK :: 1 // Test for execute permission W_OK :: 2 // Test for write permission R_OK :: 4 // Test for read permission -AT_FDCWD :: -100 +AT_FDCWD :: ~uintptr(99) /* -100 */ AT_REMOVEDIR :: uintptr(0x200) AT_SYMLINK_NOFOLLOW :: uintptr(0x100) @@ -278,7 +278,11 @@ _unix_personality :: proc(persona: u64) -> int { } _unix_fork :: proc() -> Pid { - res := int(intrinsics.syscall(unix.SYS_fork)) + when ODIN_ARCH != .arm64 { + res := int(intrinsics.syscall(unix.SYS_fork)) + } else { + res := int(intrinsics.syscall(unix.SYS_clone, unix.SIGCHLD)) + } return -1 if res < 0 else Pid(res) } @@ -286,7 +290,7 @@ _unix_open :: proc(path: cstring, flags: int, mode: int = 0o000) -> Handle { when ODIN_ARCH != .arm64 { res := int(intrinsics.syscall(unix.SYS_open, uintptr(rawptr(path)), uintptr(flags), uintptr(mode))) } else { // NOTE: arm64 does not have open - res := int(intrinsics.syscall(unix.SYS_openat, uintptr(AT_FDCWD), uintptr(rawptr(path), uintptr(flags), uintptr(mode)))) + res := int(intrinsics.syscall(unix.SYS_openat, AT_FDCWD, uintptr(rawptr(path)), uintptr(flags), uintptr(mode))) } return -1 if res < 0 else Handle(res) } @@ -321,7 +325,7 @@ _unix_stat :: proc(path: cstring, stat: ^OS_Stat) -> int { } else when ODIN_ARCH != .arm64 { return int(intrinsics.syscall(unix.SYS_stat64, uintptr(rawptr(path)), uintptr(stat))) } else { // NOTE: arm64 does not have stat - return int(intrinsics.syscall(unix.SYS_fstatat, uintptr(AT_FDCWD), uintptr(rawptr(path)), uintptr(stat), 0)) + return int(intrinsics.syscall(unix.SYS_fstatat, AT_FDCWD, uintptr(rawptr(path)), uintptr(stat), 0)) } } @@ -339,7 +343,7 @@ _unix_lstat :: proc(path: cstring, stat: ^OS_Stat) -> int { } else when ODIN_ARCH != .arm64 { return int(intrinsics.syscall(unix.SYS_lstat64, uintptr(rawptr(path)), uintptr(stat))) } else { // NOTE: arm64 does not have any lstat - return int(intrinsics.syscall(unix.SYS_fstatat, uintptr(AT_FDCWD), uintptr(rawptr(path)), uintptr(stat), AT_SYMLINK_NOFOLLOW)) + return int(intrinsics.syscall(unix.SYS_fstatat, AT_FDCWD, uintptr(rawptr(path)), uintptr(stat), AT_SYMLINK_NOFOLLOW)) } } @@ -347,7 +351,7 @@ _unix_readlink :: proc(path: cstring, buf: rawptr, bufsiz: uint) -> int { when ODIN_ARCH != .arm64 { return int(intrinsics.syscall(unix.SYS_readlink, uintptr(rawptr(path)), uintptr(buf), uintptr(bufsiz))) } else { // NOTE: arm64 does not have readlink - return int(intrinsics.syscall(unix.SYS_readlinkat, uintptr(AT_FDCWD), uintptr(rawptr(path)), uintptr(buf), uintptr(bufsiz))) + return int(intrinsics.syscall(unix.SYS_readlinkat, AT_FDCWD, uintptr(rawptr(path)), uintptr(buf), uintptr(bufsiz))) } } @@ -355,7 +359,7 @@ _unix_access :: proc(path: cstring, mask: int) -> int { when ODIN_ARCH != .arm64 { return int(intrinsics.syscall(unix.SYS_access, uintptr(rawptr(path)), uintptr(mask))) } else { // NOTE: arm64 does not have access - return int(intrinsics.syscall(unix.SYS_faccessat, uintptr(AT_FDCWD), uintptr(rawptr(path)), uintptr(mask))) + return int(intrinsics.syscall(unix.SYS_faccessat, AT_FDCWD, uintptr(rawptr(path)), uintptr(mask))) } } @@ -371,7 +375,7 @@ _unix_rename :: proc(old, new: cstring) -> int { when ODIN_ARCH != .arm64 { return int(intrinsics.syscall(unix.SYS_rename, uintptr(rawptr(old)), uintptr(rawptr(new)))) } else { // NOTE: arm64 does not have rename - return int(intrinsics.syscall(unix.SYS_renameat, uintptr(AT_FDCWD), uintptr(rawptr(old)), uintptr(rawptr(new)))) + return int(intrinsics.syscall(unix.SYS_renameat, AT_FDCWD, uintptr(rawptr(old)), uintptr(rawptr(new)))) } } @@ -379,7 +383,7 @@ _unix_unlink :: proc(path: cstring) -> int { when ODIN_ARCH != .arm64 { return int(intrinsics.syscall(unix.SYS_unlink, uintptr(rawptr(path)))) } else { // NOTE: arm64 does not have unlink - return int(intrinsics.syscall(unix.SYS_unlinkat, uintptr(AT_FDCWD), uintptr(rawptr(path), 0))) + return int(intrinsics.syscall(unix.SYS_unlinkat, AT_FDCWD, uintptr(rawptr(path)), 0)) } } @@ -387,7 +391,7 @@ _unix_rmdir :: proc(path: cstring) -> int { when ODIN_ARCH != .arm64 { return int(intrinsics.syscall(unix.SYS_rmdir, uintptr(rawptr(path)))) } else { // NOTE: arm64 does not have rmdir - return int(intrinsics.syscall(unix.SYS_unlinkat, uintptr(AT_FDCWD), uintptr(rawptr(path)), AT_REMOVEDIR)) + return int(intrinsics.syscall(unix.SYS_unlinkat, AT_FDCWD, uintptr(rawptr(path)), AT_REMOVEDIR)) } } @@ -395,7 +399,7 @@ _unix_mkdir :: proc(path: cstring, mode: u32) -> int { when ODIN_ARCH != .arm64 { return int(intrinsics.syscall(unix.SYS_mkdir, uintptr(rawptr(path)), uintptr(mode))) } else { // NOTE: arm64 does not have mkdir - return int(intrinsics.syscall(unix.SYS_mkdirat, uintptr(AT_FDCWD), uintptr(rawptr(path)), uintptr(mode))) + return int(intrinsics.syscall(unix.SYS_mkdirat, AT_FDCWD, uintptr(rawptr(path)), uintptr(mode))) } } diff --git a/core/sys/unix/syscalls_linux.odin b/core/sys/unix/syscalls_linux.odin index 0082c7261..3d06d42d4 100644 --- a/core/sys/unix/syscalls_linux.odin +++ b/core/sys/unix/syscalls_linux.odin @@ -675,6 +675,8 @@ when ODIN_ARCH == .amd64 { SYS_landlock_create_ruleset : uintptr : 444 SYS_landlock_add_rule : uintptr : 445 SYS_landlock_restrict_self : uintptr : 446 + + SIGCHLD :: 17 } else when ODIN_ARCH == .i386 { SYS_restart_syscall : uintptr : 0 SYS_exit : uintptr : 1 From 15f9795ab051b0ed711be51c0e1cbb4f7fbaae52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Marie?= Date: Sat, 12 Mar 2022 09:21:46 +0000 Subject: [PATCH 45/56] enable linux_arm64 check in CI --- .github/workflows/ci.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 412587b3c..a42716dd0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -87,6 +87,9 @@ jobs: - name: Odin check examples/all for Darwin arm64 run: ./odin check examples/all -vet -strict-style -target:darwin_arm64 timeout-minutes: 10 + - name: Odin check examples/all for Linux arm64 + run: ./odin check examples/all -vet -strict-style -target:linux_arm64 + timeout-minutes: 10 build_windows: runs-on: windows-2019 steps: From f7c8b40ea2c133d91827ed788adfb23b24fa1838 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Marie?= Date: Sat, 12 Mar 2022 09:40:55 +0000 Subject: [PATCH 46/56] use distinct type for fpos_t on OpenBSD --- core/c/libc/stdio.odin | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/c/libc/stdio.odin b/core/c/libc/stdio.odin index fc65b954a..c0d9f9d14 100644 --- a/core/c/libc/stdio.odin +++ b/core/c/libc/stdio.odin @@ -79,7 +79,7 @@ when ODIN_OS == .Linux { } when ODIN_OS == .OpenBSD { - fpos_t :: i64 + fpos_t :: distinct i64 _IOFBF :: 0 _IOLBF :: 1 From c12c7d53701e1ba9d110a9c4bd61fc2cb19a8fd1 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sat, 12 Mar 2022 10:47:52 +0000 Subject: [PATCH 47/56] Remove tag --- core/sync/sync2/primitives.odin | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/sync/sync2/primitives.odin b/core/sync/sync2/primitives.odin index 046ecbc35..6d056d439 100644 --- a/core/sync/sync2/primitives.odin +++ b/core/sync/sync2/primitives.odin @@ -11,7 +11,7 @@ current_thread_id :: proc "contextless" () -> int { // // A Mutex must not be copied after first use Mutex :: struct { - impl: _Mutex `This is a tag`, + impl: _Mutex, } // mutex_lock locks m From f907516cbd0078b69996929d02742d0c1a48c226 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sat, 12 Mar 2022 10:48:31 +0000 Subject: [PATCH 48/56] #Fix 1615 Replace `llvm.readcyclecounter` with `cntvct_el0` on arm64 --- src/llvm_backend_proc.cpp | 21 +++++++++++++++------ src/llvm_backend_utility.cpp | 2 +- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/src/llvm_backend_proc.cpp b/src/llvm_backend_proc.cpp index eb6c89b85..1698c211b 100644 --- a/src/llvm_backend_proc.cpp +++ b/src/llvm_backend_proc.cpp @@ -1402,14 +1402,23 @@ lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValue const &tv, case BuiltinProc_read_cycle_counter: { - char const *name = "llvm.readcyclecounter"; - unsigned id = LLVMLookupIntrinsicID(name, gb_strlen(name)); - GB_ASSERT_MSG(id != 0, "Unable to find %s", name); - LLVMValueRef ip = LLVMGetIntrinsicDeclaration(p->module->mod, id, nullptr, 0); - lbValue res = {}; - res.value = LLVMBuildCall(p->builder, ip, nullptr, 0, ""); res.type = tv.type; + + if (build_context.metrics.arch == TargetArch_arm64) { + LLVMTypeRef func_type = LLVMFunctionType(LLVMInt64TypeInContext(p->module->ctx), nullptr, 0, false); + bool has_side_effects = false; + LLVMValueRef the_asm = llvm_get_inline_asm(func_type, str_lit("mrs x9, cntvct_el0"), str_lit("=r"), has_side_effects); + GB_ASSERT(the_asm != nullptr); + res.value = LLVMBuildCall2(p->builder, func_type, the_asm, nullptr, 0, ""); + } else { + char const *name = "llvm.readcyclecounter"; + unsigned id = LLVMLookupIntrinsicID(name, gb_strlen(name)); + GB_ASSERT_MSG(id != 0, "Unable to find %s", name); + LLVMValueRef ip = LLVMGetIntrinsicDeclaration(p->module->mod, id, nullptr, 0); + + res.value = LLVMBuildCall(p->builder, ip, nullptr, 0, ""); + } return res; } diff --git a/src/llvm_backend_utility.cpp b/src/llvm_backend_utility.cpp index 431cfea9b..15075380a 100644 --- a/src/llvm_backend_utility.cpp +++ b/src/llvm_backend_utility.cpp @@ -1779,7 +1779,7 @@ LLVMValueRef llvm_get_inline_asm(LLVMTypeRef func_type, String const &str, Strin return LLVMGetInlineAsm(func_type, cast(char *)str.text, cast(size_t)str.len, cast(char *)clobbers.text, cast(size_t)clobbers.len, - /*HasSideEffects*/true, /*IsAlignStack*/false, + has_side_effects, is_align_stack, dialect #if LLVM_VERSION_MAJOR >= 13 , /*CanThrow*/false From ca67cf032c5a8e0c0fe711fe668cf4d77b080a62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Marie?= Date: Sun, 13 Mar 2022 11:42:42 +0000 Subject: [PATCH 49/56] freebsd_amd64 support --- core/c/libc/stdio.odin | 25 ++ core/c/libc/wctype.odin | 14 +- core/os/dir_freebsd.odin | 70 ++++++ core/os/os_freebsd.odin | 311 +++++++++++++++++++++--- core/os/stat_unix.odin | 4 +- core/sync/sync2/futex_freebsd.odin | 75 ++++++ core/sync/sync2/primitives_freebsd.odin | 9 + core/sync/sync_freebsd.odin | 14 +- core/sys/unix/pthread_freebsd.odin | 90 +++---- 9 files changed, 515 insertions(+), 97 deletions(-) create mode 100644 core/os/dir_freebsd.odin create mode 100644 core/sync/sync2/futex_freebsd.odin create mode 100644 core/sync/sync2/primitives_freebsd.odin diff --git a/core/c/libc/stdio.odin b/core/c/libc/stdio.odin index fc65b954a..004b923e8 100644 --- a/core/c/libc/stdio.odin +++ b/core/c/libc/stdio.odin @@ -103,6 +103,31 @@ when ODIN_OS == .OpenBSD { } } +when ODIN_OS == .FreeBSD { + fpos_t :: distinct 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/wctype.odin b/core/c/libc/wctype.odin index f833af51f..43aee9dc6 100644 --- a/core/c/libc/wctype.odin +++ b/core/c/libc/wctype.odin @@ -13,21 +13,23 @@ when ODIN_OS == .Windows { when ODIN_OS == .Windows { wctrans_t :: distinct wchar_t wctype_t :: distinct ushort -} -when ODIN_OS == .Linux { +} else when ODIN_OS == .Linux { wctrans_t :: distinct intptr_t wctype_t :: distinct ulong -} -when ODIN_OS == .Darwin { +} else when ODIN_OS == .Darwin { wctrans_t :: distinct int wctype_t :: distinct u32 -} -when ODIN_OS == .OpenBSD { +} else when ODIN_OS == .OpenBSD { wctrans_t :: distinct rawptr wctype_t :: distinct rawptr + +} else when ODIN_OS == .FreeBSD { + wctrans_t :: distinct int + wctype_t :: distinct ulong + } @(default_calling_convention="c") diff --git a/core/os/dir_freebsd.odin b/core/os/dir_freebsd.odin new file mode 100644 index 000000000..74c410a51 --- /dev/null +++ b/core/os/dir_freebsd.odin @@ -0,0 +1,70 @@ +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) + + 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_freebsd.odin b/core/os/os_freebsd.odin index 9d09a790a..4a95028c1 100644 --- a/core/os/os_freebsd.odin +++ b/core/os/os_freebsd.odin @@ -10,7 +10,6 @@ import "core:c" Handle :: distinct i32 File_Time :: distinct u64 Errno :: distinct i32 -Syscall :: distinct i32 INVALID_HANDLE :: ~Handle(0) @@ -142,40 +141,74 @@ RTLD_TRACE :: 0x200 RTLD_NODELETE :: 0x01000 RTLD_NOLOAD :: 0x02000 +MAX_PATH :: 1024 + args := _alloc_command_line_arguments() Unix_File_Time :: struct { - seconds: i64, + seconds: time_t, nanoseconds: c.long, } +dev_t :: u64 +ino_t :: u64 +nlink_t :: u64 +off_t :: i64 +mode_t :: u16 pid_t :: u32 +uid_t :: u32 +gid_t :: u32 +blkcnt_t :: i64 +blksize_t :: i32 +fflags_t :: u32 + +when ODIN_ARCH == .amd64 /* LP64 */ { + time_t :: i64 +} else { + time_t :: i32 +} + OS_Stat :: struct { - device_id: u64, - serial: u64, - nlink: u64, - mode: u32, + device_id: dev_t, + serial: ino_t, + nlink: nlink_t, + mode: mode_t, _padding0: i16, - uid: u32, - gid: u32, + uid: uid_t, + gid: gid_t, _padding1: i32, - rdev: u64, + rdev: dev_t, last_access: Unix_File_Time, modified: Unix_File_Time, status_change: Unix_File_Time, birthtime: Unix_File_Time, - size: i64, - blocks: i64, - block_size: i32, + size: off_t, + blocks: blkcnt_t, + block_size: blksize_t, - flags: u32, + flags: fflags_t, gen: u64, - lspare: i64, + lspare: [10]u64, } + +// since FreeBSD v12 +Dirent :: struct { + ino: ino_t, + off: off_t, + reclen: u16, + type: u8, + _pad0: u8, + namlen: u16, + _pad1: u16, + name: [256]byte, +} + +Dir :: distinct rawptr // DIR* + // File type S_IFMT :: 0o170000 // Type of file mask S_IFIFO :: 0o010000 // Named pipe (fifo) @@ -211,13 +244,13 @@ S_ISGID :: 0o2000 // Set group id on execution S_ISVTX :: 0o1000 // Directory restrcted delete -S_ISLNK :: #force_inline proc(m: u32) -> bool do return (m & S_IFMT) == S_IFLNK -S_ISREG :: #force_inline proc(m: u32) -> bool do return (m & S_IFMT) == S_IFREG -S_ISDIR :: #force_inline proc(m: u32) -> bool do return (m & S_IFMT) == S_IFDIR -S_ISCHR :: #force_inline proc(m: u32) -> bool do return (m & S_IFMT) == S_IFCHR -S_ISBLK :: #force_inline proc(m: u32) -> bool do return (m & S_IFMT) == S_IFBLK -S_ISFIFO :: #force_inline proc(m: u32) -> bool do return (m & S_IFMT) == S_IFIFO -S_ISSOCK :: #force_inline proc(m: u32) -> bool do return (m & S_IFMT) == S_IFSOCK +S_ISLNK :: #force_inline proc(m: mode_t) -> bool do return (m & S_IFMT) == S_IFLNK +S_ISREG :: #force_inline proc(m: mode_t) -> bool do return (m & S_IFMT) == S_IFREG +S_ISDIR :: #force_inline proc(m: mode_t) -> bool do return (m & S_IFMT) == S_IFDIR +S_ISCHR :: #force_inline proc(m: mode_t) -> bool do return (m & S_IFMT) == S_IFCHR +S_ISBLK :: #force_inline proc(m: mode_t) -> bool do return (m & S_IFMT) == S_IFBLK +S_ISFIFO :: #force_inline proc(m: mode_t) -> bool do return (m & S_IFMT) == S_IFIFO +S_ISSOCK :: #force_inline proc(m: mode_t) -> bool do return (m & S_IFMT) == S_IFSOCK F_OK :: 0 // Test for file existance X_OK :: 1 // Test for execute permission @@ -225,27 +258,38 @@ W_OK :: 2 // Test for write permission R_OK :: 4 // Test for read permission foreign libc { - @(link_name="__error") __errno_location :: proc() -> ^int --- - @(link_name="syscall") syscall :: proc(number: Syscall, #c_vararg args: ..any) -> int --- + @(link_name="__error") __errno_location :: 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: i64, whence: c.int) -> i64 --- - @(link_name="gettid") _unix_gettid :: proc() -> u64 --- + @(link_name="lseek") _unix_seek :: proc(fd: Handle, offset: i64, whence: c.int) -> i64 --- @(link_name="getpagesize") _unix_getpagesize :: proc() -> c.int --- - @(link_name="stat") _unix_stat :: proc(path: cstring, stat: ^OS_Stat) -> c.int --- + @(link_name="stat") _unix_stat :: proc(path: cstring, stat: ^OS_Stat) -> c.int --- + @(link_name="lstat") _unix_lstat :: proc(path: cstring, sb: ^OS_Stat) -> c.int --- @(link_name="fstat") _unix_fstat :: proc(fd: Handle, stat: ^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(buf: 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="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="getcwd") _unix_getcwd :: proc(buf: cstring, len: c.size_t) -> cstring --- - @(link_name="chdir") _unix_chdir :: proc(buf: cstring) -> c.int --- + @(link_name="realpath") _unix_realpath :: proc(path: cstring, resolved_path: rawptr) -> rawptr --- @(link_name="exit") _unix_exit :: proc(status: c.int) -> ! --- } @@ -318,12 +362,102 @@ file_size :: proc(fd: Handle) -> (i64, Errno) { return s.size, ERROR_NONE } -stdin: Handle = 0 +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) + s, err := _fstat(fd) if err != ERROR_NONE { return 0, err } @@ -332,7 +466,7 @@ last_write_time :: proc(fd: Handle) -> (File_Time, Errno) { } last_write_time_by_name :: proc(name: string) -> (File_Time, Errno) { - s, err := stat(name) + s, err := _stat(name) if err != ERROR_NONE { return 0, err } @@ -340,18 +474,33 @@ last_write_time_by_name :: proc(name: string) -> (File_Time, Errno) { return File_Time(modified), ERROR_NONE } -stat :: proc(path: string) -> (OS_Stat, Errno) { +@private +_stat :: proc(path: string) -> (OS_Stat, Errno) { cstr := strings.clone_to_cstring(path, context.temp_allocator) - s: OS_Stat - result := _unix_stat(cstr, &s) + s: OS_Stat = --- + result := _unix_lstat(cstr, &s) if result == -1 { return s, Errno(get_last_error()) } return s, ERROR_NONE } -fstat :: proc(fd: Handle) -> (OS_Stat, Errno) { - s: OS_Stat +@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) { + s: OS_Stat = --- result := _unix_fstat(fd, &s) if result == -1 { return s, Errno(get_last_error()) @@ -359,6 +508,95 @@ fstat :: proc(fd: Handle) -> (OS_Stat, Errno) { 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 FreeBSD +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) result := _unix_access(cstr, c.int(mask)) @@ -464,4 +702,3 @@ _alloc_command_line_arguments :: proc() -> []string { } return res } - diff --git a/core/os/stat_unix.odin b/core/os/stat_unix.odin index c82466b08..395d2e73e 100644 --- a/core/os/stat_unix.odin +++ b/core/os/stat_unix.odin @@ -1,4 +1,4 @@ -//+build linux, darwin, openbsd +//+build linux, darwin, freebsd, openbsd package os import "core:time" @@ -61,7 +61,7 @@ _make_time_from_unix_file_time :: proc(uft: Unix_File_Time) -> time.Time { _fill_file_info_from_stat :: proc(fi: ^File_Info, s: OS_Stat) { fi.size = s.size fi.mode = cast(File_Mode)s.mode - fi.is_dir = S_ISDIR(u32(s.mode)) + fi.is_dir = S_ISDIR(s.mode) // NOTE(laleksic, 2021-01-21): Not really creation time, but closest we can get (maybe better to leave it 0?) fi.creation_time = _make_time_from_unix_file_time(s.status_change) diff --git a/core/sync/sync2/futex_freebsd.odin b/core/sync/sync2/futex_freebsd.odin new file mode 100644 index 000000000..2cbdb4aaa --- /dev/null +++ b/core/sync/sync2/futex_freebsd.odin @@ -0,0 +1,75 @@ +//+private +//+build freebsd +package sync2 + +import "core:c" +import "core:os" +import "core:time" + +UMTX_OP_WAIT :: 2 +UMTX_OP_WAKE :: 3 + +foreign import libc "system:c" + +foreign libc { + _umtx_op :: proc "c" (obj: rawptr, op: c.int, val: c.ulong, uaddr: rawptr, uaddr2: rawptr) -> c.int --- +} + +_futex_wait :: proc(f: ^Futex, expected: u32) -> bool { + timeout := os.Unix_File_Time{ + seconds = 5, + nanoseconds = 0, + } + + for { + res := _umtx_op(f, UMTX_OP_WAIT, c.ulong(expected), nil, &timeout) + + if res != -1 { + return true + } + + if os.Errno(os.get_last_error()) == os.ETIMEDOUT { + continue + } + + panic("_futex_wait failure") + } + unreachable() +} + +_futex_wait_with_timeout :: proc(f: ^Futex, expected: u32, duration: time.Duration) -> bool { + if duration <= 0 { + return false + } + + res := _umtx_op(f, UMTX_OP_WAIT, c.ulong(expected), nil, &os.Unix_File_Time{ + seconds = (os.time_t)(duration/1e9), + nanoseconds = (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 := _umtx_op(f, UMTX_OP_WAKE, 1, nil, nil) + + if res == -1 { + panic("_futex_signal failure") + } +} + +_futex_broadcast :: proc(f: ^Futex) { + res := _umtx_op(f, UMTX_OP_WAKE, c.ulong(max(i32)), nil, nil) + + if res == -1 { + panic("_futex_broadcast failure") + } +} diff --git a/core/sync/sync2/primitives_freebsd.odin b/core/sync/sync2/primitives_freebsd.odin new file mode 100644 index 000000000..2a25a18a4 --- /dev/null +++ b/core/sync/sync2/primitives_freebsd.odin @@ -0,0 +1,9 @@ +//+build freebsd +//+private +package sync2 + +import "core:os" + +_current_thread_id :: proc "contextless" () -> int { + return os.current_thread_id() +} diff --git a/core/sync/sync_freebsd.odin b/core/sync/sync_freebsd.odin index 240308b7d..20e6bfceb 100644 --- a/core/sync/sync_freebsd.odin +++ b/core/sync/sync_freebsd.odin @@ -5,8 +5,8 @@ import "core:intrinsics" current_thread_id :: proc "contextless" () -> int { - SYS_GETTID :: 186; - return int(intrinsics.syscall(SYS_GETTID)); + SYS_GETTID :: 186 + return int(intrinsics.syscall(SYS_GETTID)) } @@ -19,22 +19,22 @@ Semaphore :: struct #align 16 { } semaphore_init :: proc(s: ^Semaphore, initial_count := 0) { - assert(unix.sem_init(&s.handle, 0, u32(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 = {}; + 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_open :: proc(name: cstring, flags: c.int) -> ^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 ---; + 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() ---; + pthread_yield :: proc() --- } From ed4c9335db7ba30679797eda7afe6c61a313ecc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Marie?= Date: Sun, 13 Mar 2022 11:43:36 +0000 Subject: [PATCH 50/56] enable freebsd_amd64 inside CI --- .github/workflows/ci.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 412587b3c..ecb01e8a5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -41,6 +41,9 @@ jobs: - name: Odin check examples/all for Linux i386 run: ./odin check examples/all -vet -strict-style -target:linux_i386 timeout-minutes: 10 + - name: Odin check examples/all for FreeBSD amd64 + run: ./odin check examples/all -vet -strict-style -target:freebsd_amd64 + timeout-minutes: 10 - name: Odin check examples/all for OpenBSD amd64 run: ./odin check examples/all -vet -strict-style -target:openbsd_amd64 timeout-minutes: 10 From 036900da51fb256bb9dbbc82172880440601b6f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Marie?= Date: Sun, 13 Mar 2022 12:41:03 +0000 Subject: [PATCH 51/56] fix mode_t on darwin - fix mkdir() prototype (mode_t is u16) - remove explicit cast --- core/os/os_darwin.odin | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/core/os/os_darwin.odin b/core/os/os_darwin.odin index ace622582..ae5336849 100644 --- a/core/os/os_darwin.odin +++ b/core/os/os_darwin.odin @@ -260,13 +260,13 @@ S_ISUID :: 0o4000 // Set user id on execution S_ISGID :: 0o2000 // Set group id on execution S_ISVTX :: 0o1000 // Directory restrcted delete -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 } +S_ISLNK :: #force_inline proc(m: u16) -> bool { return (m & S_IFMT) == S_IFLNK } +S_ISREG :: #force_inline proc(m: u16) -> bool { return (m & S_IFMT) == S_IFREG } +S_ISDIR :: #force_inline proc(m: u16) -> bool { return (m & S_IFMT) == S_IFDIR } +S_ISCHR :: #force_inline proc(m: u16) -> bool { return (m & S_IFMT) == S_IFCHR } +S_ISBLK :: #force_inline proc(m: u16) -> bool { return (m & S_IFMT) == S_IFBLK } +S_ISFIFO :: #force_inline proc(m: u16) -> bool { return (m & S_IFMT) == S_IFIFO } +S_ISSOCK :: #force_inline proc(m: u16) -> bool { return (m & S_IFMT) == S_IFSOCK } R_OK :: 4 // Test for read permission W_OK :: 2 // Test for write permission @@ -313,7 +313,7 @@ foreign libc { @(link_name="getenv") _unix_getenv :: proc(cstring) -> cstring --- @(link_name="getcwd") _unix_getcwd :: proc(buf: cstring, len: c.size_t) -> cstring --- @(link_name="chdir") _unix_chdir :: proc(buf: cstring) -> c.int --- - @(link_name="mkdir") _unix_mkdir :: proc(buf: cstring, mode: u32) -> c.int --- + @(link_name="mkdir") _unix_mkdir :: proc(buf: cstring, mode: u16) -> c.int --- @(link_name="realpath") _unix_realpath :: proc(path: cstring, resolved_path: rawptr) -> rawptr --- @(link_name="strerror") _darwin_string_error :: proc(num : c.int) -> cstring --- @@ -433,7 +433,7 @@ is_file_handle :: proc(fd: Handle) -> bool { if err != ERROR_NONE { return false } - return S_ISREG(cast(u32)s.mode) + return S_ISREG(s.mode) } is_file_path :: proc(path: string, follow_links: bool = true) -> bool { @@ -447,7 +447,7 @@ is_file_path :: proc(path: string, follow_links: bool = true) -> bool { if err != ERROR_NONE { return false } - return S_ISREG(cast(u32)s.mode) + return S_ISREG(s.mode) } @@ -456,7 +456,7 @@ is_dir_handle :: proc(fd: Handle) -> bool { if err != ERROR_NONE { return false } - return S_ISDIR(cast(u32)s.mode) + return S_ISDIR(s.mode) } is_dir_path :: proc(path: string, follow_links: bool = true) -> bool { @@ -470,7 +470,7 @@ is_dir_path :: proc(path: string, follow_links: bool = true) -> bool { if err != ERROR_NONE { return false } - return S_ISDIR(cast(u32)s.mode) + return S_ISDIR(s.mode) } is_file :: proc {is_file_path, is_file_handle} @@ -670,7 +670,7 @@ set_current_directory :: proc(path: string) -> (err: Errno) { return ERROR_NONE } -make_directory :: proc(path: string, mode: u32 = 0o775) -> Errno { +make_directory :: proc(path: string, mode: u16 = 0o775) -> Errno { path_cstr := strings.clone_to_cstring(path, context.temp_allocator) res := _unix_mkdir(path_cstr, mode) if res == -1 { From ef3f448861303dcfe3c0bb7164d47ad694a03c0e Mon Sep 17 00:00:00 2001 From: Jeroen van Rijn Date: Mon, 14 Mar 2022 13:06:50 +0100 Subject: [PATCH 52/56] Remove accidentally committed test binary. --- tests/core/crypto_hash | Bin 626328 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100755 tests/core/crypto_hash diff --git a/tests/core/crypto_hash b/tests/core/crypto_hash deleted file mode 100755 index 32f8217be6856cf6dcbfef1a3cd3a128eb3386e5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 626328 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

4sXI3yv_?U4zQR*J*Y#sn1T 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

Y4eLEBY*o3 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

LXIOS(Um^YXBIwpbr!=j#TMvbnesmq) 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 E0a8N0TL1t6 From ffe6d81ecd3169d2cadd112fa878872ed5acd8bf Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 14 Mar 2022 12:24:10 +0000 Subject: [PATCH 53/56] Remove comments --- examples/demo/demo.odin | 4 ---- 1 file changed, 4 deletions(-) diff --git a/examples/demo/demo.odin b/examples/demo/demo.odin index 4d4490446..8c2321dae 100644 --- a/examples/demo/demo.odin +++ b/examples/demo/demo.odin @@ -1715,7 +1715,6 @@ deprecated_attribute :: proc() { } range_statements_with_multiple_return_values :: proc() { - // IMPORTANT NOTE(bill, 2019-11-02): This feature is subject to be changed/removed fmt.println("\n#range statements with multiple return values") My_Iterator :: struct { index: int, @@ -2005,7 +2004,6 @@ relative_data_types :: proc() { or_else_operator :: proc() { fmt.println("\n#'or_else'") - // IMPORTANT NOTE: 'or_else' is an experimental feature and subject to change/removal { m: map[string]int i: int @@ -2036,8 +2034,6 @@ or_else_operator :: proc() { or_return_operator :: proc() { fmt.println("\n#'or_return'") - // IMPORTANT NOTE: 'or_return' is an experimental feature and subject to change/removal - // // The concept of 'or_return' will work by popping off the end value in a multiple // valued expression and checking whether it was not 'nil' or 'false', and if so, // set the end return value to value if possible. If the procedure only has one From 286549693eb2e7b216effba01d9aa192eab78d12 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 14 Mar 2022 12:28:28 +0000 Subject: [PATCH 54/56] Fix `#1609` --- src/check_decl.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/check_decl.cpp b/src/check_decl.cpp index 12b0e43cb..d4a320f03 100644 --- a/src/check_decl.cpp +++ b/src/check_decl.cpp @@ -440,6 +440,12 @@ void check_const_decl(CheckerContext *ctx, Entity *e, Ast *type_expr, Ast *init, if (type_expr) { e->type = check_type(ctx, type_expr); + if (are_types_identical(e->type, t_typeid)) { + e->type = nullptr; + e->kind = Entity_TypeName; + check_type_decl(ctx, e, init, named_type); + return; + } } Operand operand = {}; From 6ea9ba16e72df9ae45d6ff77664d4af9a7197852 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 14 Mar 2022 12:38:56 +0000 Subject: [PATCH 55/56] Fix #1610 --- src/parser.cpp | 50 +++++++++++++++++++++----------------------------- 1 file changed, 21 insertions(+), 29 deletions(-) diff --git a/src/parser.cpp b/src/parser.cpp index 94a585f35..a435d1317 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -1577,7 +1577,7 @@ void assign_removal_flag_to_semicolon(AstFile *f) { } } -void expect_semicolon(AstFile *f, Ast *s) { +void expect_semicolon(AstFile *f) { Token prev_token = {}; if (allow_token(f, Token_Semicolon)) { @@ -1602,17 +1602,17 @@ void expect_semicolon(AstFile *f, Ast *s) { if (f->curr_token.kind == Token_EOF) { return; } - - if (s != nullptr) { - return; - } switch (f->curr_token.kind) { case Token_EOF: return; } - String p = token_to_string(f->curr_token); - syntax_error(prev_token, "Expected ';', got %.*s", LIT(p)); - fix_advance_to_next_stmt(f); + + if (f->curr_token.pos.line == f->prev_token.pos.line) { + String p = token_to_string(f->curr_token); + prev_token.pos = token_pos_end(prev_token); + syntax_error(prev_token, "Expected ';', got %.*s", LIT(p)); + fix_advance_to_next_stmt(f); + } } @@ -3181,7 +3181,7 @@ Ast *parse_foreign_block(AstFile *f, Token token) { Ast *body = ast_block_stmt(f, decls, open, close); Ast *decl = ast_foreign_block_decl(f, token, foreign_library, body, docs); - expect_semicolon(f, decl); + expect_semicolon(f); return decl; } @@ -3227,15 +3227,11 @@ Ast *parse_value_decl(AstFile *f, Array names, CommentGroup *docs) { } if (f->expr_level >= 0) { - Ast *end = nullptr; - if (!is_mutable && values.count > 0) { - end = values[values.count-1]; - } if (f->curr_token.kind == Token_CloseBrace && f->curr_token.pos.line == f->prev_token.pos.line) { } else { - expect_semicolon(f, end); + expect_semicolon(f); } } @@ -4143,11 +4139,7 @@ Ast *parse_return_stmt(AstFile *f) { advance_token(f); } - Ast *end = nullptr; - if (results.count > 0) { - end = results[results.count-1]; - } - expect_semicolon(f, end); + expect_semicolon(f); return ast_return_stmt(f, token, results); } @@ -4398,7 +4390,7 @@ Ast *parse_import_decl(AstFile *f, ImportDeclKind kind) { syntax_error(import_name, "'using import' is not allowed, please use the import name explicitly"); } - expect_semicolon(f, s); + expect_semicolon(f); return s; } @@ -4456,7 +4448,7 @@ Ast *parse_foreign_decl(AstFile *f) { } else { s = ast_foreign_import_decl(f, token, filepaths, lib_name, docs, f->line_comment); } - expect_semicolon(f, s); + expect_semicolon(f); return s; } } @@ -4595,7 +4587,7 @@ Ast *parse_stmt(AstFile *f) { case Token_Not: case Token_And: s = parse_simple_stmt(f, StmtAllowFlag_Label); - expect_semicolon(f, s); + expect_semicolon(f); return s; @@ -4623,7 +4615,7 @@ Ast *parse_stmt(AstFile *f) { label = parse_ident(f); } s = ast_branch_stmt(f, token, label); - expect_semicolon(f, s); + expect_semicolon(f); return s; } @@ -4638,12 +4630,12 @@ Ast *parse_stmt(AstFile *f) { Array list = parse_lhs_expr_list(f); if (list.count == 0) { syntax_error(token, "Illegal use of 'using' statement"); - expect_semicolon(f, nullptr); + expect_semicolon(f); return ast_bad_stmt(f, token, f->curr_token); } if (f->curr_token.kind != Token_Colon) { - expect_semicolon(f, list[list.count-1]); + expect_semicolon(f); return ast_using_stmt(f, token, list); } expect_token_after(f, Token_Colon, "identifier list"); @@ -4700,13 +4692,13 @@ Ast *parse_stmt(AstFile *f) { } else if (tag == "assert" || tag == "panic") { Ast *t = ast_basic_directive(f, hash_token, name); Ast *stmt = ast_expr_stmt(f, parse_call_expr(f, t)); - expect_semicolon(f, stmt); + expect_semicolon(f); return stmt; } else if (name.string == "force_inline" || name.string == "force_no_inline") { Ast *expr = parse_force_inlining_operand(f, name); Ast *stmt = ast_expr_stmt(f, expr); - expect_semicolon(f, stmt); + expect_semicolon(f); return stmt; } else if (tag == "unroll") { return parse_unrolled_for_loop(f, name); @@ -4728,7 +4720,7 @@ Ast *parse_stmt(AstFile *f) { case Token_Semicolon: s = ast_empty_stmt(f, token); - expect_semicolon(f, nullptr); + expect_semicolon(f); return s; } @@ -5586,7 +5578,7 @@ bool parse_file(Parser *p, AstFile *f) { } Ast *pd = ast_package_decl(f, f->package_token, package_name, docs, f->line_comment); - expect_semicolon(f, pd); + expect_semicolon(f); f->pkg_decl = pd; if (f->error_count == 0) { From 1d147ba99339afbef47bf689a0e0d7591a33c633 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 14 Mar 2022 12:44:35 +0000 Subject: [PATCH 56/56] Fix typo --- vendor/directx/d3d12/d3d12_constants.odin | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/vendor/directx/d3d12/d3d12_constants.odin b/vendor/directx/d3d12/d3d12_constants.odin index 3f83dca6b..a30296cc1 100644 --- a/vendor/directx/d3d12/d3d12_constants.odin +++ b/vendor/directx/d3d12/d3d12_constants.odin @@ -292,7 +292,8 @@ MAX_DEPTH :: 1.0 MAX_LIVE_STATIC_SAMPLERS :: 2032 MAX_MAXANISOTROPY :: 16 MAX_MULTISAMPLE_SAMPLE_COUNT :: 32 -MAX_POSITION_VALUE :: 3.402823466e+34D3D12_MAX_ROOT_COST :: 64 +MAX_POSITION_VALUE :: 3.402823466e+34 +MAX_ROOT_COST :: 64 MAX_SHADER_VISIBLE_DESCRIPTOR_HEAP_SIZE_TIER_1 :: 1000000 MAX_SHADER_VISIBLE_DESCRIPTOR_HEAP_SIZE_TIER_2 :: 1000000 MAX_SHADER_VISIBLE_SAMPLER_HEAP_SIZE :: 2048