From 3a167e3a75449f4c36c05c17bc3eaf359d4ee2e1 Mon Sep 17 00:00:00 2001 From: Jeroen van Rijn Date: Mon, 1 Nov 2021 14:46:59 +0100 Subject: [PATCH 1/9] Add Windows 10 Home Core detection. --- src/bug_report.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/bug_report.cpp b/src/bug_report.cpp index d6b5be551..85dfea1ec 100644 --- a/src/bug_report.cpp +++ b/src/bug_report.cpp @@ -39,6 +39,10 @@ void report_windows_product_type(DWORD ProductType) { gb_printf("Enterprise"); break; + case PRODUCT_CORE: + gb_printf("Home Basic"); + break; + case PRODUCT_HOME_BASIC_N: gb_printf("Home Basic N"); break; From 0b4cbcf4095cd2f95341a4e32167e2f0f314cd9a Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 1 Nov 2021 16:39:02 +0000 Subject: [PATCH 2/9] Correct debug info for `matrix` type --- src/llvm_backend_debug.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/llvm_backend_debug.cpp b/src/llvm_backend_debug.cpp index 1d14de32e..0d4ee9fe3 100644 --- a/src/llvm_backend_debug.cpp +++ b/src/llvm_backend_debug.cpp @@ -547,6 +547,7 @@ LLVMMetadataRef lb_debug_type(lbModule *m, Type *type) { case Type_SimdVector: case Type_RelativePointer: case Type_RelativeSlice: + case Type_Matrix: { LLVMMetadataRef debug_bt = lb_debug_type(m, bt); LLVMMetadataRef final_decl = LLVMDIBuilderCreateTypedef(m->debug_builder, debug_bt, name_text, name_len, file, line, scope, align_in_bits); From 96ba8f35d496149d4486181b89f4b072759281d4 Mon Sep 17 00:00:00 2001 From: Jeroen van Rijn Date: Mon, 1 Nov 2021 17:44:05 +0100 Subject: [PATCH 3/9] CI: Run demo with debug info. --- .github/workflows/ci.yml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 608538e90..6c9603db5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -22,6 +22,9 @@ jobs: - name: Odin run run: ./odin run examples/demo/demo.odin timeout-minutes: 10 + - name: Odin run -debug + run: ./odin run examples/demo/demo.odin -debug + timeout-minutes: 10 - name: Core library tests run: | cd tests/core @@ -51,6 +54,9 @@ jobs: - name: Odin run run: ./odin run examples/demo/demo.odin timeout-minutes: 10 + - name: Odin run -debug + run: ./odin run examples/demo/demo.odin -debug + timeout-minutes: 10 build_windows: runs-on: windows-latest steps: @@ -78,6 +84,12 @@ jobs: call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat odin run examples/demo/demo.odin timeout-minutes: 10 + - name: Odin run -debug + shell: cmd + run: | + call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat + odin run examples/demo/demo.odin -debug + timeout-minutes: 10 - name: Core library tests shell: cmd run: | From 2a0311797cd04305c37faa6f9dafcb0f053a0976 Mon Sep 17 00:00:00 2001 From: Jeroen van Rijn Date: Mon, 1 Nov 2021 17:57:35 +0100 Subject: [PATCH 4/9] Don't run demo's `soa_struct` when under -debug. --- examples/demo/demo.odin | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/examples/demo/demo.odin b/examples/demo/demo.odin index c287e4054..6a7653b10 100644 --- a/examples/demo/demo.odin +++ b/examples/demo/demo.odin @@ -2439,7 +2439,16 @@ main :: proc() { deprecated_attribute() range_statements_with_multiple_return_values() threading_example() - soa_struct_layout() + + when !ODIN_DEBUG { + /* + This test causes the following error when compiled with -`debug`: + `Kernel32.lib(KERNEL32.dll) : fatal error LNK1103: debugging information corrupt; recompile module` + Only compile when not running under debug for now to not hold up CI for other commits. + */ + soa_struct_layout() + } + constant_literal_expressions() union_maybe() explicit_context_definition() From b01e0fbbc209110cf49b980149edb73ece475af3 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 1 Nov 2021 23:00:42 +0000 Subject: [PATCH 5/9] Correct typo in soa data type debug information generation --- examples/demo/demo.odin | 4 ++-- src/llvm_backend_debug.cpp | 13 ++++++++----- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/examples/demo/demo.odin b/examples/demo/demo.odin index 6a7653b10..c1f5c90ed 100644 --- a/examples/demo/demo.odin +++ b/examples/demo/demo.odin @@ -2440,14 +2440,14 @@ main :: proc() { range_statements_with_multiple_return_values() threading_example() - when !ODIN_DEBUG { + // when !ODIN_DEBUG { /* This test causes the following error when compiled with -`debug`: `Kernel32.lib(KERNEL32.dll) : fatal error LNK1103: debugging information corrupt; recompile module` Only compile when not running under debug for now to not hold up CI for other commits. */ soa_struct_layout() - } + // } constant_literal_expressions() union_maybe() diff --git a/src/llvm_backend_debug.cpp b/src/llvm_backend_debug.cpp index 0d4ee9fe3..4a73c03f2 100644 --- a/src/llvm_backend_debug.cpp +++ b/src/llvm_backend_debug.cpp @@ -684,6 +684,9 @@ void lb_debug_complete_types(lbModule *m) { } element_count = cast(unsigned)(bt->Struct.fields.count + element_offset); elements = gb_alloc_array(temporary_allocator(), LLVMMetadataRef, element_count); + + isize field_size_bits = 8*type_size_of(bt) - element_offset*word_bits; + switch (bt->Struct.soa_kind) { case StructSoa_Slice: elements[0] = LLVMDIBuilderCreateMemberType( @@ -691,7 +694,7 @@ void lb_debug_complete_types(lbModule *m) { ".len", 4, file, 0, 8*cast(u64)type_size_of(t_int), 8*cast(u32)type_align_of(t_int), - 8*type_size_of(bt)-word_bits, + field_size_bits, LLVMDIFlagZero, lb_debug_type(m, t_int) ); break; @@ -701,7 +704,7 @@ void lb_debug_complete_types(lbModule *m) { ".len", 4, file, 0, 8*cast(u64)type_size_of(t_int), 8*cast(u32)type_align_of(t_int), - 8*type_size_of(bt)-word_bits + 0*word_bits, + field_size_bits + 0*word_bits, LLVMDIFlagZero, lb_debug_type(m, t_int) ); elements[1] = LLVMDIBuilderCreateMemberType( @@ -709,15 +712,15 @@ void lb_debug_complete_types(lbModule *m) { ".cap", 4, file, 0, 8*cast(u64)type_size_of(t_int), 8*cast(u32)type_align_of(t_int), - 8*type_size_of(bt)-word_bits + 1*word_bits, + field_size_bits + 1*word_bits, LLVMDIFlagZero, lb_debug_type(m, t_int) ); elements[2] = LLVMDIBuilderCreateMemberType( m->debug_builder, record_scope, - ".allocator", 12, + ".allocator", 10, file, 0, 8*cast(u64)type_size_of(t_int), 8*cast(u32)type_align_of(t_int), - 8*type_size_of(bt)-word_bits + 2*word_bits, + field_size_bits + 2*word_bits, LLVMDIFlagZero, lb_debug_type(m, t_allocator) ); break; From e2e9b5d3b06acb6040f8d89c6f25f73450e03179 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 1 Nov 2021 23:04:00 +0000 Subject: [PATCH 6/9] Remove comments --- examples/demo/demo.odin | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/examples/demo/demo.odin b/examples/demo/demo.odin index c1f5c90ed..c287e4054 100644 --- a/examples/demo/demo.odin +++ b/examples/demo/demo.odin @@ -2439,16 +2439,7 @@ main :: proc() { deprecated_attribute() range_statements_with_multiple_return_values() threading_example() - - // when !ODIN_DEBUG { - /* - This test causes the following error when compiled with -`debug`: - `Kernel32.lib(KERNEL32.dll) : fatal error LNK1103: debugging information corrupt; recompile module` - Only compile when not running under debug for now to not hold up CI for other commits. - */ - soa_struct_layout() - // } - + soa_struct_layout() constant_literal_expressions() union_maybe() explicit_context_definition() From a4b68b93f2db127fde34c935e0764deaeb06a518 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 1 Nov 2021 23:18:39 +0000 Subject: [PATCH 7/9] Modify ABI for the wasm32 --- src/llvm_abi.cpp | 59 +++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 51 insertions(+), 8 deletions(-) diff --git a/src/llvm_abi.cpp b/src/llvm_abi.cpp index 9c7ced91e..e18dc344b 100644 --- a/src/llvm_abi.cpp +++ b/src/llvm_abi.cpp @@ -1069,6 +1069,54 @@ namespace lbAbiWasm32 { } return lb_arg_type_direct(type, nullptr, nullptr, attr); } + + bool is_struct_valid_elem_type(LLVMTypeRef type) { + switch (LLVMGetTypeKind(type)) { + case LLVMHalfTypeKind: + case LLVMFloatTypeKind: + case LLVMDoubleTypeKind: + case LLVMPointerTypeKind: + return true; + case LLVMIntegerTypeKind: + return lb_sizeof(type) <= 8; + } + return false; + } + + lbArgType is_struct(LLVMContextRef c, LLVMTypeRef type) { + LLVMTypeKind kind = LLVMGetTypeKind(type); + GB_ASSERT(kind == LLVMArrayTypeKind || kind == LLVMStructTypeKind); + + i64 sz = lb_sizeof(type); + if (sz == 0) { + return lb_arg_type_ignore(type); + } + if (sz <= 16) { + if (kind == LLVMArrayTypeKind) { + LLVMTypeRef elem = LLVMGetElementType(type); + if (is_struct_valid_elem_type(elem)) { + return lb_arg_type_direct(type); + } + } else if (kind == LLVMStructTypeKind) { + bool can_be_direct = true; + unsigned count = LLVMCountStructElementTypes(type); + for (unsigned i = 0; i < count; i++) { + LLVMTypeRef elem = LLVMStructGetTypeAtIndex(type, i); + if (!is_struct_valid_elem_type(elem)) { + can_be_direct = false; + break; + } + + } + if (can_be_direct) { + return lb_arg_type_direct(type); + } + } + } + + return lb_arg_type_indirect(type, nullptr); + } + Array compute_arg_types(LLVMContextRef c, LLVMTypeRef *arg_types, unsigned arg_count) { auto args = array_make(heap_allocator(), arg_count); @@ -1076,13 +1124,8 @@ namespace lbAbiWasm32 { for (unsigned i = 0; i < arg_count; i++) { LLVMTypeRef t = arg_types[i]; LLVMTypeKind kind = LLVMGetTypeKind(t); - i64 sz = lb_sizeof(t); if (kind == LLVMStructTypeKind || kind == LLVMArrayTypeKind) { - if (sz == 0) { - args[i] = lb_arg_type_ignore(t); - } else { - args[i] = lb_arg_type_indirect(t, nullptr); - } + args[i] = is_struct(c, t); } else { args[i] = non_struct(c, t, false); } @@ -1096,8 +1139,8 @@ namespace lbAbiWasm32 { } else if (lb_is_type_kind(return_type, LLVMStructTypeKind) || lb_is_type_kind(return_type, LLVMArrayTypeKind)) { i64 sz = lb_sizeof(return_type); switch (sz) { - case 1: return lb_arg_type_direct(return_type, LLVMIntTypeInContext(c, 32), nullptr, nullptr); - case 2: return lb_arg_type_direct(return_type, LLVMIntTypeInContext(c, 32), nullptr, nullptr); + case 1: return lb_arg_type_direct(return_type, LLVMIntTypeInContext(c, 8), nullptr, nullptr); + case 2: return lb_arg_type_direct(return_type, LLVMIntTypeInContext(c, 16), nullptr, nullptr); case 4: return lb_arg_type_direct(return_type, LLVMIntTypeInContext(c, 32), nullptr, nullptr); case 8: return lb_arg_type_direct(return_type, LLVMIntTypeInContext(c, 64), nullptr, nullptr); } From 46a394815c6cc6cec75b8d4731045a88024e629c Mon Sep 17 00:00:00 2001 From: Jeroen van Rijn Date: Tue, 2 Nov 2021 02:20:43 +0100 Subject: [PATCH 8/9] `odin report` add Windows 10 Education Edition. --- src/bug_report.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/bug_report.cpp b/src/bug_report.cpp index 85dfea1ec..5249cc3a4 100644 --- a/src/bug_report.cpp +++ b/src/bug_report.cpp @@ -47,6 +47,14 @@ void report_windows_product_type(DWORD ProductType) { gb_printf("Home Basic N"); break; + case PRODUCT_EDUCATION: + gb_printf("Education"); + break; + + case PRODUCT_EDUCATION_N: + gb_printf("Education N"); + break; + case PRODUCT_BUSINESS: gb_printf("Business"); break; From c5cd97dd8968f5f6ad4f130a68008beacda78b64 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 2 Nov 2021 12:54:23 +0000 Subject: [PATCH 9/9] Improve `wasm-import` semantics to allow procedures from different import paths --- src/build_settings.cpp | 2 ++ src/check_decl.cpp | 29 +++++++++++++++++++++++++---- src/llvm_backend.cpp | 12 ++++-------- src/llvm_backend_proc.cpp | 20 ++------------------ src/llvm_backend_utility.cpp | 33 +++++++++++++++++++++++++++++++++ 5 files changed, 66 insertions(+), 30 deletions(-) diff --git a/src/build_settings.cpp b/src/build_settings.cpp index b758f439c..63752ce68 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -516,6 +516,8 @@ bool allow_check_foreign_filepath(void) { String const WIN32_SEPARATOR_STRING = {cast(u8 *)"\\", 1}; String const NIX_SEPARATOR_STRING = {cast(u8 *)"/", 1}; +String const WASM_MODULE_NAME_SEPARATOR = str_lit(".."); + String internal_odin_root_dir(void); String odin_root_dir(void) { if (global_module_path_set) { diff --git a/src/check_decl.cpp b/src/check_decl.cpp index c2d23e70c..127bb67fd 100644 --- a/src/check_decl.cpp +++ b/src/check_decl.cpp @@ -594,7 +594,7 @@ bool are_signatures_similar_enough(Type *a_, Type *b_) { return true; } -void init_entity_foreign_library(CheckerContext *ctx, Entity *e) { +Entity *init_entity_foreign_library(CheckerContext *ctx, Entity *e) { Ast *ident = nullptr; Entity **foreign_library = nullptr; @@ -608,7 +608,7 @@ void init_entity_foreign_library(CheckerContext *ctx, Entity *e) { foreign_library = &e->Variable.foreign_library; break; default: - return; + return nullptr; } if (ident == nullptr) { @@ -631,8 +631,10 @@ void init_entity_foreign_library(CheckerContext *ctx, Entity *e) { *foreign_library = found; found->flags |= EntityFlag_Used; add_entity_use(ctx, ident, found); + return found; } } + return nullptr; } String handle_link_name(CheckerContext *ctx, Token token, String link_name, String link_prefix) { @@ -836,11 +838,27 @@ void check_proc_decl(CheckerContext *ctx, Entity *e, DeclInfo *d) { if (e->Procedure.link_name.len > 0) { name = e->Procedure.link_name; } + Entity *foreign_library = init_entity_foreign_library(ctx, e); + + if (is_arch_wasm()) { + String module_name = str_lit("env"); + if (foreign_library != nullptr) { + GB_ASSERT (foreign_library->kind == Entity_LibraryName); + if (foreign_library->LibraryName.paths.count != 1) { + error(foreign_library->token, "'foreign import' for '%.*s' architecture may only have one path, got %td", + LIT(target_arch_names[build_context.metrics.arch]), foreign_library->LibraryName.paths.count); + } + + if (foreign_library->LibraryName.paths.count >= 1) { + module_name = foreign_library->LibraryName.paths[0]; + } + } + name = concatenate3_strings(permanent_allocator(), module_name, WASM_MODULE_NAME_SEPARATOR, name); + } + e->Procedure.is_foreign = true; e->Procedure.link_name = name; - init_entity_foreign_library(ctx, e); - mutex_lock(&ctx->info->foreign_mutex); auto *fp = &ctx->info->foreigns; @@ -962,6 +980,9 @@ void check_global_variable_decl(CheckerContext *ctx, Entity *&e, Ast *type_expr, error(e->token, "A foreign variable declaration cannot have a default value"); } init_entity_foreign_library(ctx, e); + if (is_arch_wasm()) { + error(e->token, "A foreign variable declaration are not allowed for the '%.*s' architecture", LIT(target_arch_names[build_context.metrics.arch])); + } } if (ac.link_name.len > 0) { e->Variable.link_name = ac.link_name; diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index 1d382aa6d..730b9c1ba 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -895,15 +895,9 @@ lbProcedure *lb_create_main_procedure(lbModule *m, lbProcedure *startup_runtime) lb_end_procedure_body(p); + LLVMSetLinkage(p->value, LLVMExternalLinkage); if (is_arch_wasm()) { - LLVMSetLinkage(p->value, LLVMDLLExportLinkage); - LLVMSetDLLStorageClass(p->value, LLVMDLLExportStorageClass); - LLVMSetVisibility(p->value, LLVMDefaultVisibility); - - char const *export_name = alloc_cstring(permanent_allocator(), p->name); - LLVMAddTargetDependentFunctionAttr(p->value, "wasm-export-name", export_name); - } else { - LLVMSetLinkage(p->value, LLVMExternalLinkage); + lb_set_wasm_export_attributes(p->value, p->name); } @@ -1489,6 +1483,8 @@ void lb_generate_code(lbGenerator *gen) { LLVMSetLinkage(g.value, LLVMExternalLinkage); LLVMSetExternallyInitialized(g.value, true); lb_add_foreign_library_path(m, e->Variable.foreign_library); + + lb_set_wasm_import_attributes(g.value, e, name); } else { LLVMSetInitializer(g.value, LLVMConstNull(lb_type(m, e->type))); } diff --git a/src/llvm_backend_proc.cpp b/src/llvm_backend_proc.cpp index e1edfcac7..ed9aa4b8b 100644 --- a/src/llvm_backend_proc.cpp +++ b/src/llvm_backend_proc.cpp @@ -57,7 +57,6 @@ void lb_mem_copy_non_overlapping(lbProcedure *p, lbValue dst, lbValue src, lbVal LLVMBuildCall(p->builder, ip, args, gb_count_of(args), ""); } - lbProcedure *lb_create_procedure(lbModule *m, Entity *entity, bool ignore_body) { GB_ASSERT(entity != nullptr); GB_ASSERT(entity->kind == Entity_Procedure); @@ -183,10 +182,7 @@ lbProcedure *lb_create_procedure(lbModule *m, Entity *entity, bool ignore_body) LLVMSetDLLStorageClass(p->value, LLVMDLLExportStorageClass); LLVMSetVisibility(p->value, LLVMDefaultVisibility); - if (is_arch_wasm()) { - char const *export_name = alloc_cstring(permanent_allocator(), p->name); - LLVMAddTargetDependentFunctionAttr(p->value, "wasm-export-name", export_name); - } + lb_set_wasm_export_attributes(p->value, p->name); } else if (!p->is_foreign) { if (!USE_SEPARATE_MODULES) { LLVMSetLinkage(p->value, LLVMInternalLinkage); @@ -209,19 +205,7 @@ lbProcedure *lb_create_procedure(lbModule *m, Entity *entity, bool ignore_body) } if (p->is_foreign) { - if (is_arch_wasm()) { - char const *import_name = alloc_cstring(permanent_allocator(), p->name); - char const *module_name = "env"; - if (entity->Procedure.foreign_library != nullptr) { - Entity *foreign_library = entity->Procedure.foreign_library; - GB_ASSERT(foreign_library->kind == Entity_LibraryName); - if (foreign_library->LibraryName.paths.count > 0) { - module_name = alloc_cstring(permanent_allocator(), foreign_library->LibraryName.paths[0]); - } - } - LLVMAddTargetDependentFunctionAttr(p->value, "wasm-import-name", import_name); - LLVMAddTargetDependentFunctionAttr(p->value, "wasm-import-module", module_name); - } + lb_set_wasm_import_attributes(p->value, entity, p->name); } diff --git a/src/llvm_backend_utility.cpp b/src/llvm_backend_utility.cpp index 709106bc4..1359d93c2 100644 --- a/src/llvm_backend_utility.cpp +++ b/src/llvm_backend_utility.cpp @@ -1770,3 +1770,36 @@ LLVMValueRef llvm_get_inline_asm(LLVMTypeRef func_type, String const &str, Strin #endif ); } + + +void lb_set_wasm_import_attributes(LLVMValueRef value, Entity *entity, String import_name) { + if (!is_arch_wasm()) { + return; + } + String module_name = str_lit("env"); + if (entity->Procedure.foreign_library != nullptr) { + Entity *foreign_library = entity->Procedure.foreign_library; + GB_ASSERT(foreign_library->kind == Entity_LibraryName); + GB_ASSERT(foreign_library->LibraryName.paths.count == 1); + + module_name = foreign_library->LibraryName.paths[0]; + + if (string_starts_with(import_name, module_name)) { + import_name = substring(import_name, module_name.len+WASM_MODULE_NAME_SEPARATOR.len, import_name.len); + } + + } + LLVMAddTargetDependentFunctionAttr(value, "wasm-import-module", alloc_cstring(permanent_allocator(), module_name)); + LLVMAddTargetDependentFunctionAttr(value, "wasm-import-name", alloc_cstring(permanent_allocator(), import_name)); +} + + +void lb_set_wasm_export_attributes(LLVMValueRef value, String export_name) { + if (!is_arch_wasm()) { + return; + } + LLVMSetLinkage(value, LLVMDLLExportLinkage); + LLVMSetDLLStorageClass(value, LLVMDLLExportStorageClass); + LLVMSetVisibility(value, LLVMDefaultVisibility); + LLVMAddTargetDependentFunctionAttr(value, "wasm-export-name", alloc_cstring(permanent_allocator(), export_name)); +}