diff --git a/core/mem/alloc.odin b/core/mem/alloc.odin index 93d120c67..57e82a5f8 100644 --- a/core/mem/alloc.odin +++ b/core/mem/alloc.odin @@ -56,7 +56,7 @@ Allocator :: struct { DEFAULT_ALIGNMENT :: 2*align_of(rawptr) DEFAULT_PAGE_SIZE :: - 64 * 1024 when ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64 else + 64 * 1024 when ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64p32 else 16 * 1024 when ODIN_OS == .Darwin && ODIN_ARCH == .arm64 else 4 * 1024 diff --git a/core/runtime/core.odin b/core/runtime/core.odin index 9939bfc5c..058ca6161 100644 --- a/core/runtime/core.odin +++ b/core/runtime/core.odin @@ -425,7 +425,7 @@ Raw_Map :: struct { // Map_Hash directly, though for consistency sake it's written as if it were // an array of Map_Cell(Map_Hash). data: uintptr, // 8-bytes on 64-bits, 4-bytes on 32-bits - len: int, // 8-bytes on 64-bits, 4-bytes on 32-bits + len: uintptr, // 8-bytes on 64-bits, 4-bytes on 32-bits allocator: Allocator, // 16-bytes on 64-bits, 8-bytes on 32-bits } @@ -471,7 +471,7 @@ Odin_OS_Type :: type_of(ODIN_OS) arm32, arm64, wasm32, - wasm64, + wasm64p32, } */ Odin_Arch_Type :: type_of(ODIN_ARCH) diff --git a/core/runtime/dynamic_map_internal.odin b/core/runtime/dynamic_map_internal.odin index 78fdb23f8..05c03028f 100644 --- a/core/runtime/dynamic_map_internal.odin +++ b/core/runtime/dynamic_map_internal.odin @@ -184,7 +184,7 @@ map_cell_index_static :: #force_inline proc "contextless" (cells: [^]Map_Cell($T // len() for map @(require_results) map_len :: #force_inline proc "contextless" (m: Raw_Map) -> int { - return m.len + return int(m.len) } // cap() for map @@ -207,8 +207,8 @@ map_load_factor :: #force_inline proc "contextless" (log2_capacity: uintptr) -> } @(require_results) -map_resize_threshold :: #force_inline proc "contextless" (m: Raw_Map) -> int { - return int(map_load_factor(map_log2_cap(m))) +map_resize_threshold :: #force_inline proc "contextless" (m: Raw_Map) -> uintptr { + return map_load_factor(map_log2_cap(m)) } // The data stores the log2 capacity in the lower six bits. This is primarily diff --git a/core/runtime/entry_wasm.odin b/core/runtime/entry_wasm.odin index 125abc756..235d5611b 100644 --- a/core/runtime/entry_wasm.odin +++ b/core/runtime/entry_wasm.odin @@ -1,5 +1,5 @@ //+private -//+build wasm32, wasm64 +//+build wasm32, wasm64p32 package runtime import "core:intrinsics" diff --git a/core/runtime/internal.odin b/core/runtime/internal.odin index 16f8ed755..71ad9386a 100644 --- a/core/runtime/internal.odin +++ b/core/runtime/internal.odin @@ -3,7 +3,7 @@ package runtime import "core:intrinsics" @(private="file") -IS_WASM :: ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64 +IS_WASM :: ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64p32 @(private) RUNTIME_LINKAGE :: "strong" when ( diff --git a/core/runtime/procs.odin b/core/runtime/procs.odin index 510abcbb9..3a433c3bf 100644 --- a/core/runtime/procs.odin +++ b/core/runtime/procs.odin @@ -25,7 +25,7 @@ when ODIN_NO_CRT && ODIN_OS == .Windows { RtlMoveMemory(dst, src, len) return dst } -} else when ODIN_NO_CRT || (ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64) { +} else when ODIN_NO_CRT || (ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64p32) { @(link_name="memset", linkage="strong", require) memset :: proc "c" (ptr: rawptr, val: i32, len: int) -> rawptr { if ptr != nil && len != 0 { diff --git a/core/runtime/procs_js_wasm32.odin b/core/runtime/procs_js.odin similarity index 93% rename from core/runtime/procs_js_wasm32.odin rename to core/runtime/procs_js.odin index b8acebc87..d3e12410c 100644 --- a/core/runtime/procs_js_wasm32.odin +++ b/core/runtime/procs_js.odin @@ -1,4 +1,4 @@ -//+build js wasm32 +//+build js package runtime init_default_context_for_js: Context diff --git a/core/runtime/procs_wasm32.odin b/core/runtime/procs_wasm.odin similarity index 96% rename from core/runtime/procs_wasm32.odin rename to core/runtime/procs_wasm.odin index 3981cead0..26dcfef77 100644 --- a/core/runtime/procs_wasm32.odin +++ b/core/runtime/procs_wasm.odin @@ -1,4 +1,4 @@ -//+build wasm32 +//+build wasm32, wasm64p32 package runtime @(private="file") diff --git a/core/sync/futex_wasm.odin b/core/sync/futex_wasm.odin index 621f4edaa..248542836 100644 --- a/core/sync/futex_wasm.odin +++ b/core/sync/futex_wasm.odin @@ -1,5 +1,5 @@ //+private -//+build wasm32, wasm64 +//+build wasm32, wasm64p32 package sync import "core:intrinsics" diff --git a/core/sync/primitives_wasm.odin b/core/sync/primitives_wasm.odin index ac36404d9..f8d9ab657 100644 --- a/core/sync/primitives_wasm.odin +++ b/core/sync/primitives_wasm.odin @@ -1,5 +1,5 @@ //+private -//+build wasm32, wasm64 +//+build wasm32, wasm64p32 package sync _current_thread_id :: proc "contextless" () -> int { diff --git a/src/build_settings.cpp b/src/build_settings.cpp index 8fe559309..92e0df38b 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -35,14 +35,12 @@ enum TargetArchKind : u16 { TargetArch_arm32, TargetArch_arm64, TargetArch_wasm32, - TargetArch_wasm64, + TargetArch_wasm64p32, TargetArch_COUNT, }; enum TargetEndianKind : u8 { - TargetEndian_Invalid, - TargetEndian_Little, TargetEndian_Big, @@ -81,11 +79,10 @@ gb_global String target_arch_names[TargetArch_COUNT] = { str_lit("arm32"), str_lit("arm64"), str_lit("wasm32"), - str_lit("wasm64"), + str_lit("wasm64p32"), }; gb_global String target_endian_names[TargetEndian_COUNT] = { - str_lit(""), str_lit("little"), str_lit("big"), }; @@ -97,7 +94,8 @@ gb_global String target_abi_names[TargetABI_COUNT] = { }; gb_global TargetEndianKind target_endians[TargetArch_COUNT] = { - TargetEndian_Invalid, + TargetEndian_Little, + TargetEndian_Little, TargetEndian_Little, TargetEndian_Little, TargetEndian_Little, @@ -116,7 +114,8 @@ gb_global String const ODIN_VERSION = str_lit(ODIN_VERSION_RAW); struct TargetMetrics { TargetOsKind os; TargetArchKind arch; - isize word_size; + isize ptr_size; + isize int_size; isize max_align; isize max_simd_align; String target_triplet; @@ -237,9 +236,10 @@ struct BuildContext { TargetEndianKind endian_kind; // In bytes - i64 word_size; // Size of a pointer, must be >= 4 - i64 max_align; // max alignment, must be >= 1 (and typically >= word_size) - i64 max_simd_align; // max alignment, must be >= 1 (and typically >= word_size) + i64 ptr_size; // Size of a pointer, must be >= 4 + i64 int_size; // Size of a int/uint, must be >= 4 + i64 max_align; // max alignment, must be >= 1 (and typically >= ptr_size) + i64 max_simd_align; // max alignment, must be >= 1 (and typically >= ptr_size) CommandKind command_kind; String command; @@ -361,13 +361,13 @@ gb_internal isize MAX_ERROR_COLLECTOR_COUNT(void) { gb_global TargetMetrics target_windows_i386 = { TargetOs_windows, TargetArch_i386, - 4, 4, 8, + 4, 4, 4, 8, str_lit("i386-pc-windows-msvc"), }; gb_global TargetMetrics target_windows_amd64 = { TargetOs_windows, TargetArch_amd64, - 8, 8, 16, + 8, 8, 8, 16, str_lit("x86_64-pc-windows-msvc"), str_lit("e-m:w-i64:64-f80:128-n8:16:32:64-S128"), }; @@ -375,21 +375,21 @@ gb_global TargetMetrics target_windows_amd64 = { gb_global TargetMetrics target_linux_i386 = { TargetOs_linux, TargetArch_i386, - 4, 4, 8, + 4, 4, 4, 8, str_lit("i386-pc-linux-gnu"), }; gb_global TargetMetrics target_linux_amd64 = { TargetOs_linux, TargetArch_amd64, - 8, 8, 16, + 8, 8, 8, 16, str_lit("x86_64-pc-linux-gnu"), str_lit("e-m:w-i64:64-f80:128-n8:16:32:64-S128"), }; gb_global TargetMetrics target_linux_arm64 = { TargetOs_linux, TargetArch_arm64, - 8, 8, 16, + 8, 8, 8, 16, str_lit("aarch64-linux-elf"), str_lit("e-m:o-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"), }; @@ -397,7 +397,7 @@ gb_global TargetMetrics target_linux_arm64 = { gb_global TargetMetrics target_linux_arm32 = { TargetOs_linux, TargetArch_arm32, - 4, 4, 8, + 4, 4, 4, 8, str_lit("arm-linux-gnu"), str_lit("e-m:o-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"), }; @@ -405,7 +405,7 @@ gb_global TargetMetrics target_linux_arm32 = { gb_global TargetMetrics target_darwin_amd64 = { TargetOs_darwin, TargetArch_amd64, - 8, 8, 16, + 8, 8, 8, 16, str_lit("x86_64-apple-darwin"), str_lit("e-m:o-i64:64-f80:128-n8:16:32:64-S128"), }; @@ -413,7 +413,7 @@ gb_global TargetMetrics target_darwin_amd64 = { gb_global TargetMetrics target_darwin_arm64 = { TargetOs_darwin, TargetArch_arm64, - 8, 8, 16, + 8, 8, 8, 16, str_lit("arm64-apple-macosx11.0.0"), str_lit("e-m:o-i64:64-i128:128-n32:64-S128"), }; @@ -421,14 +421,14 @@ gb_global TargetMetrics target_darwin_arm64 = { gb_global TargetMetrics target_freebsd_i386 = { TargetOs_freebsd, TargetArch_i386, - 4, 4, 8, + 4, 4, 4, 8, str_lit("i386-unknown-freebsd-elf"), }; gb_global TargetMetrics target_freebsd_amd64 = { TargetOs_freebsd, TargetArch_amd64, - 8, 8, 16, + 8, 8, 8, 16, str_lit("x86_64-unknown-freebsd-elf"), str_lit("e-m:w-i64:64-f80:128-n8:16:32:64-S128"), }; @@ -436,7 +436,7 @@ gb_global TargetMetrics target_freebsd_amd64 = { gb_global TargetMetrics target_openbsd_amd64 = { TargetOs_openbsd, TargetArch_amd64, - 8, 8, 16, + 8, 8, 8, 16, str_lit("x86_64-unknown-openbsd-elf"), str_lit("e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"), }; @@ -444,7 +444,7 @@ gb_global TargetMetrics target_openbsd_amd64 = { gb_global TargetMetrics target_essence_amd64 = { TargetOs_essence, TargetArch_amd64, - 8, 8, 16, + 8, 8, 8, 16, str_lit("x86_64-pc-none-elf"), }; @@ -452,7 +452,7 @@ gb_global TargetMetrics target_essence_amd64 = { gb_global TargetMetrics target_freestanding_wasm32 = { TargetOs_freestanding, TargetArch_wasm32, - 4, 8, 16, + 4, 4, 8, 16, str_lit("wasm32-freestanding-js"), str_lit("e-m:e-p:32:32-i64:64-n32:64-S128"), }; @@ -460,7 +460,7 @@ gb_global TargetMetrics target_freestanding_wasm32 = { gb_global TargetMetrics target_js_wasm32 = { TargetOs_js, TargetArch_wasm32, - 4, 8, 16, + 4, 4, 8, 16, str_lit("wasm32-js-js"), str_lit("e-m:e-p:32:32-i64:64-n32:64-S128"), }; @@ -468,24 +468,42 @@ gb_global TargetMetrics target_js_wasm32 = { gb_global TargetMetrics target_wasi_wasm32 = { TargetOs_wasi, TargetArch_wasm32, - 4, 8, 16, + 4, 4, 8, 16, str_lit("wasm32-wasi-js"), str_lit("e-m:e-p:32:32-i64:64-n32:64-S128"), }; -gb_global TargetMetrics target_js_wasm64 = { - TargetOs_js, - TargetArch_wasm64, - 8, 8, 16, - str_lit("wasm64-js-js"), - str_lit(""), +gb_global TargetMetrics target_freestanding_wasm64p32 = { + TargetOs_freestanding, + TargetArch_wasm64p32, + 4, 8, 8, 16, + str_lit("wasm32-freestanding-js"), + str_lit("e-m:e-p:32:32-i64:64-n32:64-S128"), }; +gb_global TargetMetrics target_js_wasm64p32 = { + TargetOs_js, + TargetArch_wasm64p32, + 4, 8, 8, 16, + str_lit("wasm32-js-js"), + str_lit("e-m:e-p:32:32-i64:64-n32:64-S128"), +}; + +gb_global TargetMetrics target_wasi_wasm64p32 = { + TargetOs_wasi, + TargetArch_wasm32, + 4, 8, 8, 16, + str_lit("wasm32-wasi-js"), + str_lit("e-m:e-p:32:32-i64:64-n32:64-S128"), +}; + + + gb_global TargetMetrics target_freestanding_amd64_sysv = { TargetOs_freestanding, TargetArch_amd64, - 8, 8, 16, + 8, 8, 8, 16, str_lit("x86_64-pc-none-gnu"), str_lit("e-m:w-i64:64-f80:128-n8:16:32:64-S128"), TargetABI_SysV, @@ -501,20 +519,29 @@ struct NamedTargetMetrics { gb_global NamedTargetMetrics named_targets[] = { { str_lit("darwin_amd64"), &target_darwin_amd64 }, { str_lit("darwin_arm64"), &target_darwin_arm64 }, + { str_lit("essence_amd64"), &target_essence_amd64 }, + { str_lit("linux_i386"), &target_linux_i386 }, { str_lit("linux_amd64"), &target_linux_amd64 }, { str_lit("linux_arm64"), &target_linux_arm64 }, { str_lit("linux_arm32"), &target_linux_arm32 }, + { str_lit("windows_i386"), &target_windows_i386 }, { str_lit("windows_amd64"), &target_windows_amd64 }, + { str_lit("freebsd_i386"), &target_freebsd_i386 }, { str_lit("freebsd_amd64"), &target_freebsd_amd64 }, + { str_lit("openbsd_amd64"), &target_openbsd_amd64 }, + { str_lit("freestanding_wasm32"), &target_freestanding_wasm32 }, { str_lit("wasi_wasm32"), &target_wasi_wasm32 }, { str_lit("js_wasm32"), &target_js_wasm32 }, - // { str_lit("js_wasm64"), &target_js_wasm64 }, + + { str_lit("freestanding_wasm64p32"), &target_freestanding_wasm64p32 }, + { str_lit("js_wasm64p32"), &target_js_wasm64p32 }, + { str_lit("wasi_wasm64p32"), &target_wasi_wasm64p32 }, { str_lit("freestanding_amd64_sysv"), &target_freestanding_amd64_sysv }, }; @@ -623,7 +650,7 @@ gb_internal bool find_library_collection_path(String name, String *path) { gb_internal bool is_arch_wasm(void) { switch (build_context.metrics.arch) { case TargetArch_wasm32: - case TargetArch_wasm64: + case TargetArch_wasm64p32: return true; } return false; @@ -641,7 +668,7 @@ gb_internal bool is_arch_x86(void) { gb_internal bool allow_check_foreign_filepath(void) { switch (build_context.metrics.arch) { case TargetArch_wasm32: - case TargetArch_wasm64: + case TargetArch_wasm64p32: return false; } return true; @@ -1164,16 +1191,24 @@ gb_internal void init_build_context(TargetMetrics *cross_target) { GB_ASSERT(metrics->os != TargetOs_Invalid); GB_ASSERT(metrics->arch != TargetArch_Invalid); - GB_ASSERT(metrics->word_size > 1); + GB_ASSERT(metrics->ptr_size > 1); + GB_ASSERT(metrics->int_size > 1); GB_ASSERT(metrics->max_align > 1); GB_ASSERT(metrics->max_simd_align > 1); + GB_ASSERT(metrics->int_size >= metrics->ptr_size); + if (metrics->int_size > metrics->ptr_size) { + GB_ASSERT(metrics->int_size == 2*metrics->ptr_size); + } + + bc->metrics = *metrics; bc->ODIN_OS = target_os_names[metrics->os]; bc->ODIN_ARCH = target_arch_names[metrics->arch]; bc->endian_kind = target_endians[metrics->arch]; - bc->word_size = metrics->word_size; + bc->ptr_size = metrics->ptr_size; + bc->int_size = metrics->int_size; bc->max_align = metrics->max_align; bc->max_simd_align = metrics->max_simd_align; bc->link_flags = str_lit(" "); @@ -1257,9 +1292,9 @@ gb_internal void init_build_context(TargetMetrics *cross_target) { // link_flags = gb_string_appendc(link_flags, "--export-all "); // link_flags = gb_string_appendc(link_flags, "--export-table "); link_flags = gb_string_appendc(link_flags, "--allow-undefined "); - if (bc->metrics.arch == TargetArch_wasm64) { - link_flags = gb_string_appendc(link_flags, "-mwasm64 "); - } + // if (bc->metrics.arch == TargetArch_wasm64) { + // link_flags = gb_string_appendc(link_flags, "-mwasm64 "); + // } if (bc->no_entry_point) { link_flags = gb_string_appendc(link_flags, "--no-entry "); } diff --git a/src/checker.cpp b/src/checker.cpp index a9893bca4..6b5046f3d 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -971,13 +971,13 @@ gb_internal void init_universal(void) { { GlobalEnumValue values[TargetArch_COUNT] = { - {"Unknown", TargetArch_Invalid}, - {"amd64", TargetArch_amd64}, - {"i386", TargetArch_i386}, - {"arm32", TargetArch_arm32}, - {"arm64", TargetArch_arm64}, - {"wasm32", TargetArch_wasm32}, - {"wasm64", TargetArch_wasm64}, + {"Unknown", TargetArch_Invalid}, + {"amd64", TargetArch_amd64}, + {"i386", TargetArch_i386}, + {"arm32", TargetArch_arm32}, + {"arm64", TargetArch_arm64}, + {"wasm32", TargetArch_wasm32}, + {"wasm64p32", TargetArch_wasm64p32}, }; auto fields = add_global_enum_type(str_lit("Odin_Arch_Type"), values, gb_count_of(values)); @@ -1000,8 +1000,6 @@ gb_internal void init_universal(void) { { GlobalEnumValue values[TargetEndian_COUNT] = { - {"Unknown", TargetEndian_Invalid}, - {"Little", TargetEndian_Little}, {"Big", TargetEndian_Big}, }; diff --git a/src/llvm_abi.cpp b/src/llvm_abi.cpp index 550e2a582..b0045d869 100644 --- a/src/llvm_abi.cpp +++ b/src/llvm_abi.cpp @@ -218,7 +218,7 @@ gb_internal i64 lb_sizeof(LLVMTypeRef type) { case LLVMDoubleTypeKind: return 8; case LLVMPointerTypeKind: - return build_context.word_size; + return build_context.ptr_size; case LLVMStructTypeKind: { unsigned field_count = LLVMCountStructElementTypes(type); @@ -275,7 +275,7 @@ gb_internal i64 lb_alignof(LLVMTypeRef type) { case LLVMIntegerTypeKind: { unsigned w = LLVMGetIntTypeWidth(type); - return gb_clamp((w + 7)/8, 1, build_context.word_size); + return gb_clamp((w + 7)/8, 1, build_context.ptr_size); } case LLVMHalfTypeKind: return 2; @@ -284,7 +284,7 @@ gb_internal i64 lb_alignof(LLVMTypeRef type) { case LLVMDoubleTypeKind: return 8; case LLVMPointerTypeKind: - return build_context.word_size; + return build_context.ptr_size; case LLVMStructTypeKind: { if (LLVMIsPackedStruct(type)) { @@ -326,7 +326,7 @@ gb_internal i64 lb_alignof(LLVMTypeRef type) { } -#define LB_ABI_INFO(name) lbFunctionType *name(LLVMContextRef c, LLVMTypeRef *arg_types, unsigned arg_count, LLVMTypeRef return_type, bool return_is_defined, bool return_is_tuple, ProcCallingConvention calling_convention) +#define LB_ABI_INFO(name) lbFunctionType *name(LLVMContextRef c, LLVMTypeRef *arg_types, unsigned arg_count, LLVMTypeRef return_type, bool return_is_defined, bool return_is_tuple, ProcCallingConvention calling_convention, Type *original_type) typedef LB_ABI_INFO(lbAbiInfoType); #define LB_ABI_COMPUTE_RETURN_TYPE(name) lbArgType name(lbFunctionType *ft, LLVMContextRef c, LLVMTypeRef return_type, bool return_is_defined, bool return_is_tuple) @@ -388,7 +388,7 @@ namespace lbAbi386 { } if (build_context.metrics.os == TargetOs_windows && - build_context.word_size == 8 && + build_context.ptr_size == 8 && lb_is_type_kind(type, LLVMIntegerTypeKind) && type == LLVMIntTypeInContext(c, 128)) { // NOTE(bill): Because Windows AMD64 is weird @@ -1217,7 +1217,7 @@ namespace lbAbiWasm { The approach taken optimizes for passing things in multiple registers/arguments if possible rather than by pointer. */ - gb_internal Array compute_arg_types(LLVMContextRef c, LLVMTypeRef *arg_types, unsigned arg_count, ProcCallingConvention calling_convention); + gb_internal Array compute_arg_types(LLVMContextRef c, LLVMTypeRef *arg_types, unsigned arg_count, ProcCallingConvention calling_convention, Type *original_type); gb_internal LB_ABI_COMPUTE_RETURN_TYPE(compute_return_type); enum {MAX_DIRECT_STRUCT_SIZE = 32}; @@ -1225,7 +1225,7 @@ namespace lbAbiWasm { gb_internal LB_ABI_INFO(abi_info) { lbFunctionType *ft = gb_alloc_item(permanent_allocator(), lbFunctionType); ft->ctx = c; - ft->args = compute_arg_types(c, arg_types, arg_count, calling_convention); + ft->args = compute_arg_types(c, arg_types, arg_count, calling_convention, original_type); ft->ret = compute_return_type(ft, c, return_type, return_is_defined, return_is_tuple); ft->calling_convention = calling_convention; return ft; @@ -1315,15 +1315,42 @@ namespace lbAbiWasm { return lb_arg_type_indirect(type, nullptr); } + gb_internal lbArgType pseudo_slice(LLVMContextRef c, LLVMTypeRef type, ProcCallingConvention calling_convention) { + if (build_context.metrics.ptr_size < build_context.metrics.int_size && + type_can_be_direct(type, calling_convention)) { + LLVMTypeRef types[2] = { + LLVMStructGetTypeAtIndex(type, 0), + // ignore padding + LLVMStructGetTypeAtIndex(type, 2) + }; + LLVMTypeRef new_type = LLVMStructTypeInContext(c, types, gb_count_of(types), false); + return lb_arg_type_direct(type, new_type, nullptr, nullptr); + } else { + return is_struct(c, type, calling_convention); + } + } - gb_internal Array compute_arg_types(LLVMContextRef c, LLVMTypeRef *arg_types, unsigned arg_count, ProcCallingConvention calling_convention) { + gb_internal Array compute_arg_types(LLVMContextRef c, LLVMTypeRef *arg_types, unsigned arg_count, ProcCallingConvention calling_convention, + Type *original_type) { auto args = array_make(lb_function_type_args_allocator(), arg_count); - for (unsigned i = 0; i < arg_count; i++) { + GB_ASSERT(original_type->kind == Type_Proc); + GB_ASSERT(cast(isize)arg_count <= original_type->Proc.param_count); + auto const ¶ms = original_type->Proc.params->Tuple.variables; + + for (unsigned i = 0, j = 0; i < arg_count; i++, j++) { + while (params[j]->kind != Entity_Variable) { + j++; + } + Type *ptype = params[j]->type; LLVMTypeRef t = arg_types[i]; LLVMTypeKind kind = LLVMGetTypeKind(t); if (kind == LLVMStructTypeKind || kind == LLVMArrayTypeKind) { - args[i] = is_struct(c, t, calling_convention); + if (is_type_slice(ptype) || is_type_string(ptype)) { + args[i] = pseudo_slice(c, t, calling_convention); + } else { + args[i] = is_struct(c, t, calling_convention); + } } else { args[i] = non_struct(c, t, false); } @@ -1460,32 +1487,33 @@ gb_internal LB_ABI_INFO(lb_get_abi_info_internal) { } case ProcCC_Win64: GB_ASSERT(build_context.metrics.arch == TargetArch_amd64); - return lbAbiAmd64Win64::abi_info(c, arg_types, arg_count, return_type, return_is_defined, return_is_tuple, calling_convention); + return lbAbiAmd64Win64::abi_info(c, arg_types, arg_count, return_type, return_is_defined, return_is_tuple, calling_convention, original_type); case ProcCC_SysV: GB_ASSERT(build_context.metrics.arch == TargetArch_amd64); - return lbAbiAmd64SysV::abi_info(c, arg_types, arg_count, return_type, return_is_defined, return_is_tuple, calling_convention); + return lbAbiAmd64SysV::abi_info(c, arg_types, arg_count, return_type, return_is_defined, return_is_tuple, calling_convention, original_type); } switch (build_context.metrics.arch) { case TargetArch_amd64: if (build_context.metrics.os == TargetOs_windows) { - return lbAbiAmd64Win64::abi_info(c, arg_types, arg_count, return_type, return_is_defined, return_is_tuple, calling_convention); + return lbAbiAmd64Win64::abi_info(c, arg_types, arg_count, return_type, return_is_defined, return_is_tuple, calling_convention, original_type); } else if (build_context.metrics.abi == TargetABI_Win64) { - return lbAbiAmd64Win64::abi_info(c, arg_types, arg_count, return_type, return_is_defined, return_is_tuple, calling_convention); + return lbAbiAmd64Win64::abi_info(c, arg_types, arg_count, return_type, return_is_defined, return_is_tuple, calling_convention, original_type); } else if (build_context.metrics.abi == TargetABI_SysV) { - return lbAbiAmd64SysV::abi_info(c, arg_types, arg_count, return_type, return_is_defined, return_is_tuple, calling_convention); + return lbAbiAmd64SysV::abi_info(c, arg_types, arg_count, return_type, return_is_defined, return_is_tuple, calling_convention, original_type); } else { - return lbAbiAmd64SysV::abi_info(c, arg_types, arg_count, return_type, return_is_defined, return_is_tuple, calling_convention); + return lbAbiAmd64SysV::abi_info(c, arg_types, arg_count, return_type, return_is_defined, return_is_tuple, calling_convention, original_type); } case TargetArch_i386: - return lbAbi386::abi_info(c, arg_types, arg_count, return_type, return_is_defined, return_is_tuple, calling_convention); + return lbAbi386::abi_info(c, arg_types, arg_count, return_type, return_is_defined, return_is_tuple, calling_convention, original_type); case TargetArch_arm32: - return lbAbiArm32::abi_info(c, arg_types, arg_count, return_type, return_is_defined, return_is_tuple, calling_convention); + return lbAbiArm32::abi_info(c, arg_types, arg_count, return_type, return_is_defined, return_is_tuple, calling_convention, original_type); case TargetArch_arm64: - return lbAbiArm64::abi_info(c, arg_types, arg_count, return_type, return_is_defined, return_is_tuple, calling_convention); + return lbAbiArm64::abi_info(c, arg_types, arg_count, return_type, return_is_defined, return_is_tuple, calling_convention, original_type); case TargetArch_wasm32: - case TargetArch_wasm64: - return lbAbiWasm::abi_info(c, arg_types, arg_count, return_type, return_is_defined, return_is_tuple, calling_convention); + return lbAbiWasm::abi_info(c, arg_types, arg_count, return_type, return_is_defined, return_is_tuple, calling_convention, original_type); + case TargetArch_wasm64p32: + return lbAbiWasm::abi_info(c, arg_types, arg_count, return_type, return_is_defined, return_is_tuple, calling_convention, original_type); } GB_PANIC("Unsupported ABI"); @@ -1499,7 +1527,8 @@ gb_internal LB_ABI_INFO(lb_get_abi_info) { arg_types, arg_count, return_type, return_is_defined, ALLOW_SPLIT_MULTI_RETURNS && return_is_tuple && is_calling_convention_odin(calling_convention), - calling_convention); + calling_convention, + base_type(original_type)); // NOTE(bill): this is handled here rather than when developing the type in `lb_type_internal_for_procedures_raw` diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index ab9292fbe..34a401c33 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -1987,7 +1987,7 @@ gb_internal bool lb_generate_code(lbGenerator *gen) { LLVMInitializeAArch64Disassembler(); break; case TargetArch_wasm32: - case TargetArch_wasm64: + case TargetArch_wasm64p32: LLVMInitializeWebAssemblyTargetInfo(); LLVMInitializeWebAssemblyTarget(); LLVMInitializeWebAssemblyTargetMC(); diff --git a/src/llvm_backend.hpp b/src/llvm_backend.hpp index 1ddd4fed7..4c4d9703d 100644 --- a/src/llvm_backend.hpp +++ b/src/llvm_backend.hpp @@ -539,7 +539,7 @@ gb_internal void lb_mem_copy_non_overlapping(lbProcedure *p, lbValue dst, lbValu gb_internal LLVMValueRef lb_mem_zero_ptr_internal(lbProcedure *p, LLVMValueRef ptr, LLVMValueRef len, unsigned alignment, bool is_volatile); gb_internal gb_inline i64 lb_max_zero_init_size(void) { - return cast(i64)(4*build_context.word_size); + return cast(i64)(4*build_context.int_size); } gb_internal LLVMTypeRef OdinLLVMGetArrayElementType(LLVMTypeRef type); diff --git a/src/llvm_backend_const.cpp b/src/llvm_backend_const.cpp index 8149b1eda..c9d2f5b26 100644 --- a/src/llvm_backend_const.cpp +++ b/src/llvm_backend_const.cpp @@ -131,6 +131,25 @@ gb_internal lbValue lb_const_ptr_cast(lbModule *m, lbValue value, Type *t) { return res; } + +gb_internal LLVMValueRef llvm_const_string_internal(lbModule *m, Type *t, LLVMValueRef data, LLVMValueRef len) { + if (build_context.metrics.ptr_size < build_context.metrics.int_size) { + LLVMValueRef values[3] = { + data, + LLVMConstNull(lb_type(m, t_i32)), + len, + }; + return llvm_const_named_struct_internal(lb_type(m, t), values, 3); + } else { + LLVMValueRef values[2] = { + data, + len, + }; + return llvm_const_named_struct_internal(lb_type(m, t), values, 2); + } +} + + gb_internal LLVMValueRef llvm_const_named_struct(lbModule *m, Type *t, LLVMValueRef *values, isize value_count_) { LLVMTypeRef struct_type = lb_type(m, t); GB_ASSERT(LLVMGetTypeKind(struct_type) == LLVMStructTypeKind); @@ -180,17 +199,33 @@ gb_internal LLVMValueRef llvm_const_array(LLVMTypeRef elem_type, LLVMValueRef *v return LLVMConstArray(elem_type, values, value_count); } +gb_internal LLVMValueRef llvm_const_slice_internal(lbModule *m, LLVMValueRef data, LLVMValueRef len) { + if (build_context.metrics.ptr_size < build_context.metrics.int_size) { + GB_ASSERT(build_context.metrics.ptr_size == 4); + GB_ASSERT(build_context.metrics.int_size == 8); + LLVMValueRef vals[3] = { + data, + LLVMConstNull(lb_type(m, t_u32)), + len, + }; + return LLVMConstStructInContext(m->ctx, vals, gb_count_of(vals), false); + } else { + LLVMValueRef vals[2] = { + data, + len, + }; + return LLVMConstStructInContext(m->ctx, vals, gb_count_of(vals), false); + } +} gb_internal LLVMValueRef llvm_const_slice(lbModule *m, lbValue data, lbValue len) { GB_ASSERT(is_type_pointer(data.type) || is_type_multi_pointer(data.type)); GB_ASSERT(are_types_identical(len.type, t_int)); - LLVMValueRef vals[2] = { - data.value, - len.value, - }; - return LLVMConstStructInContext(m->ctx, vals, gb_count_of(vals), false); + + return llvm_const_slice_internal(m, data.value, len.value); } + gb_internal lbValue lb_const_nil(lbModule *m, Type *type) { LLVMValueRef v = LLVMConstNull(lb_type(m, type)); return lbValue{v, type}; @@ -643,10 +678,9 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, bo ptr = LLVMConstNull(lb_type(m, t_u8_ptr)); } LLVMValueRef str_len = LLVMConstInt(lb_type(m, t_int), value.value_string.len, true); - LLVMValueRef values[2] = {ptr, str_len}; GB_ASSERT(is_type_string(original_type)); - res.value = llvm_const_named_struct(m, original_type, values, 2); + res.value = llvm_const_string_internal(m, original_type, ptr, str_len); } return res; diff --git a/src/llvm_backend_debug.cpp b/src/llvm_backend_debug.cpp index bec719a4a..b9c6c606e 100644 --- a/src/llvm_backend_debug.cpp +++ b/src/llvm_backend_debug.cpp @@ -52,8 +52,8 @@ gb_internal LLVMMetadataRef lb_debug_type_internal_proc(lbModule *m, Type *type) GB_ASSERT(type != t_invalid); - /* unsigned const word_size = cast(unsigned)build_context.word_size; - unsigned const word_bits = cast(unsigned)(8*build_context.word_size); */ + /* unsigned const ptr_size = cast(unsigned)build_context.ptr_size; + unsigned const ptr_bits = cast(unsigned)(8*build_context.ptr_size); */ GB_ASSERT(type->kind == Type_Proc); unsigned parameter_count = 1; @@ -131,8 +131,9 @@ gb_internal LLVMMetadataRef lb_debug_type_internal(lbModule *m, Type *type) { GB_ASSERT(type != t_invalid); - /* unsigned const word_size = cast(unsigned)build_context.word_size; */ - unsigned const word_bits = cast(unsigned)(8*build_context.word_size); + /* unsigned const ptr_size = cast(unsigned)build_context.ptr_size; */ + unsigned const int_bits = cast(unsigned)(8*build_context.int_size); + unsigned const ptr_bits = cast(unsigned)(8*build_context.ptr_size); switch (type->kind) { case Type_Basic: @@ -162,12 +163,12 @@ gb_internal LLVMMetadataRef lb_debug_type_internal(lbModule *m, Type *type) { case Basic_f32: return lb_debug_type_basic_type(m, str_lit("f32"), 32, LLVMDWARFTypeEncoding_Float); case Basic_f64: return lb_debug_type_basic_type(m, str_lit("f64"), 64, LLVMDWARFTypeEncoding_Float); - case Basic_int: return lb_debug_type_basic_type(m, str_lit("int"), word_bits, LLVMDWARFTypeEncoding_Signed); - case Basic_uint: return lb_debug_type_basic_type(m, str_lit("uint"), word_bits, LLVMDWARFTypeEncoding_Unsigned); - case Basic_uintptr: return lb_debug_type_basic_type(m, str_lit("uintptr"), word_bits, LLVMDWARFTypeEncoding_Unsigned); + case Basic_int: return lb_debug_type_basic_type(m, str_lit("int"), int_bits, LLVMDWARFTypeEncoding_Signed); + case Basic_uint: return lb_debug_type_basic_type(m, str_lit("uint"), int_bits, LLVMDWARFTypeEncoding_Unsigned); + case Basic_uintptr: return lb_debug_type_basic_type(m, str_lit("uintptr"), ptr_bits, LLVMDWARFTypeEncoding_Unsigned); case Basic_typeid: - return lb_debug_type_basic_type(m, str_lit("typeid"), word_bits, LLVMDWARFTypeEncoding_Unsigned); + return lb_debug_type_basic_type(m, str_lit("typeid"), ptr_bits, LLVMDWARFTypeEncoding_Unsigned); // Endian Specific Types case Basic_i16le: return lb_debug_type_basic_type(m, str_lit("i16le"), 16, LLVMDWARFTypeEncoding_Signed, LLVMDIFlagLittleEndian); @@ -251,26 +252,26 @@ gb_internal LLVMMetadataRef lb_debug_type_internal(lbModule *m, Type *type) { case Basic_rawptr: { LLVMMetadataRef void_type = lb_debug_type_basic_type(m, str_lit("void"), 8, LLVMDWARFTypeEncoding_Unsigned); - return LLVMDIBuilderCreatePointerType(m->debug_builder, void_type, word_bits, word_bits, LLVMDWARFTypeEncoding_Address, "rawptr", 6); + return LLVMDIBuilderCreatePointerType(m->debug_builder, void_type, ptr_bits, ptr_bits, LLVMDWARFTypeEncoding_Address, "rawptr", 6); } case Basic_string: { LLVMMetadataRef elements[2] = {}; elements[0] = lb_debug_struct_field(m, str_lit("data"), t_u8_ptr, 0); - elements[1] = lb_debug_struct_field(m, str_lit("len"), t_int, word_bits); - return lb_debug_basic_struct(m, str_lit("string"), 2*word_bits, word_bits, elements, gb_count_of(elements)); + elements[1] = lb_debug_struct_field(m, str_lit("len"), t_int, int_bits); + return lb_debug_basic_struct(m, str_lit("string"), 2*int_bits, int_bits, elements, gb_count_of(elements)); } case Basic_cstring: { LLVMMetadataRef char_type = lb_debug_type_basic_type(m, str_lit("char"), 8, LLVMDWARFTypeEncoding_Unsigned); - return LLVMDIBuilderCreatePointerType(m->debug_builder, char_type, word_bits, word_bits, 0, "cstring", 7); + return LLVMDIBuilderCreatePointerType(m->debug_builder, char_type, ptr_bits, ptr_bits, 0, "cstring", 7); } case Basic_any: { LLVMMetadataRef elements[2] = {}; elements[0] = lb_debug_struct_field(m, str_lit("data"), t_rawptr, 0); - elements[1] = lb_debug_struct_field(m, str_lit("id"), t_typeid, word_bits); - return lb_debug_basic_struct(m, str_lit("any"), 2*word_bits, word_bits, elements, gb_count_of(elements)); + elements[1] = lb_debug_struct_field(m, str_lit("id"), t_typeid, ptr_bits); + return lb_debug_basic_struct(m, str_lit("any"), 2*ptr_bits, ptr_bits, elements, gb_count_of(elements)); } // Untyped types @@ -292,11 +293,11 @@ gb_internal LLVMMetadataRef lb_debug_type_internal(lbModule *m, Type *type) { GB_PANIC("Type_Named should be handled in lb_debug_type separately"); case Type_SoaPointer: - return LLVMDIBuilderCreatePointerType(m->debug_builder, lb_debug_type(m, type->SoaPointer.elem), word_bits, word_bits, 0, nullptr, 0); + return LLVMDIBuilderCreatePointerType(m->debug_builder, lb_debug_type(m, type->SoaPointer.elem), int_bits, int_bits, 0, nullptr, 0); case Type_Pointer: - return LLVMDIBuilderCreatePointerType(m->debug_builder, lb_debug_type(m, type->Pointer.elem), word_bits, word_bits, 0, nullptr, 0); + return LLVMDIBuilderCreatePointerType(m->debug_builder, lb_debug_type(m, type->Pointer.elem), ptr_bits, ptr_bits, 0, nullptr, 0); case Type_MultiPointer: - return LLVMDIBuilderCreatePointerType(m->debug_builder, lb_debug_type(m, type->MultiPointer.elem), word_bits, word_bits, 0, nullptr, 0); + return LLVMDIBuilderCreatePointerType(m->debug_builder, lb_debug_type(m, type->MultiPointer.elem), ptr_bits, ptr_bits, 0, nullptr, 0); case Type_Array: { LLVMMetadataRef subscripts[1] = {}; @@ -416,7 +417,7 @@ gb_internal LLVMMetadataRef lb_debug_type_internal(lbModule *m, Type *type) { case Type_Proc: { LLVMMetadataRef proc_underlying_type = lb_debug_type_internal_proc(m, type); - LLVMMetadataRef pointer_type = LLVMDIBuilderCreatePointerType(m->debug_builder, proc_underlying_type, word_bits, word_bits, 0, nullptr, 0); + LLVMMetadataRef pointer_type = LLVMDIBuilderCreatePointerType(m->debug_builder, proc_underlying_type, ptr_bits, ptr_bits, 0, nullptr, 0); gbString name = type_to_string(type, temporary_allocator()); return LLVMDIBuilderCreateTypedef(m->debug_builder, pointer_type, name, gb_string_length(name), nullptr, 0, nullptr, cast(u32)(8*type_align_of(type))); } @@ -447,10 +448,11 @@ gb_internal LLVMMetadataRef lb_debug_type_internal(lbModule *m, Type *type) { unsigned element_count = 0; LLVMMetadataRef elements[2] = {}; Type *base_integer = type->RelativeSlice.base_integer; + unsigned base_bits = cast(unsigned)(8*type_size_of(base_integer)); elements[0] = lb_debug_struct_field(m, str_lit("data_offset"), base_integer, 0); - elements[1] = lb_debug_struct_field(m, str_lit("len"), base_integer, 8*type_size_of(base_integer)); + elements[1] = lb_debug_struct_field(m, str_lit("len"), base_integer, base_bits); gbString name = type_to_string(type, temporary_allocator()); - return LLVMDIBuilderCreateStructType(m->debug_builder, nullptr, name, gb_string_length(name), nullptr, 0, 2*word_bits, word_bits, LLVMDIFlagZero, nullptr, elements, element_count, 0, nullptr, "", 0); + return LLVMDIBuilderCreateStructType(m->debug_builder, nullptr, name, gb_string_length(name), nullptr, 0, 2*base_bits, base_bits, LLVMDIFlagZero, nullptr, elements, element_count, 0, nullptr, "", 0); } case Type_Matrix: { @@ -616,8 +618,7 @@ gb_internal LLVMMetadataRef lb_debug_type(lbModule *m, Type *type) { } gb_internal void lb_debug_complete_types(lbModule *m) { - /* unsigned const word_size = cast(unsigned)build_context.word_size; */ - unsigned const word_bits = cast(unsigned)(8*build_context.word_size); + unsigned const int_bits = cast(unsigned)(8*build_context.int_size); for_array(debug_incomplete_type_index, m->debug_incomplete_types) { TEMPORARY_ALLOCATOR_GUARD(); @@ -691,27 +692,27 @@ gb_internal void lb_debug_complete_types(lbModule *m) { element_count = 2; elements = gb_alloc_array(temporary_allocator(), LLVMMetadataRef, element_count); #if defined(GB_SYSTEM_WINDOWS) - elements[0] = lb_debug_struct_field(m, str_lit("data"), alloc_type_pointer(bt->Slice.elem), 0*word_bits); + elements[0] = lb_debug_struct_field(m, str_lit("data"), alloc_type_pointer(bt->Slice.elem), 0*int_bits); #else // FIX HACK TODO(bill): For some reason this causes a crash in *nix systems due to the reference counting // of the debug type information - elements[0] = lb_debug_struct_field(m, str_lit("data"), t_rawptr, 0*word_bits); + elements[0] = lb_debug_struct_field(m, str_lit("data"), t_rawptr, 0*int_bits); #endif - elements[1] = lb_debug_struct_field(m, str_lit("len"), t_int, 1*word_bits); + elements[1] = lb_debug_struct_field(m, str_lit("len"), t_int, 1*int_bits); break; case Type_DynamicArray: element_count = 4; elements = gb_alloc_array(temporary_allocator(), LLVMMetadataRef, element_count); #if defined(GB_SYSTEM_WINDOWS) - elements[0] = lb_debug_struct_field(m, str_lit("data"), alloc_type_pointer(bt->DynamicArray.elem), 0*word_bits); + elements[0] = lb_debug_struct_field(m, str_lit("data"), alloc_type_pointer(bt->DynamicArray.elem), 0*int_bits); #else // FIX HACK TODO(bill): For some reason this causes a crash in *nix systems due to the reference counting // of the debug type information - elements[0] = lb_debug_struct_field(m, str_lit("data"), t_rawptr, 0*word_bits); + elements[0] = lb_debug_struct_field(m, str_lit("data"), t_rawptr, 0*int_bits); #endif - elements[1] = lb_debug_struct_field(m, str_lit("len"), t_int, 1*word_bits); - elements[2] = lb_debug_struct_field(m, str_lit("cap"), t_int, 2*word_bits); - elements[3] = lb_debug_struct_field(m, str_lit("allocator"), t_allocator, 3*word_bits); + elements[1] = lb_debug_struct_field(m, str_lit("len"), t_int, 1*int_bits); + elements[2] = lb_debug_struct_field(m, str_lit("cap"), t_int, 2*int_bits); + elements[3] = lb_debug_struct_field(m, str_lit("allocator"), t_allocator, 3*int_bits); break; case Type_Map: @@ -737,7 +738,7 @@ gb_internal 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; + isize field_size_bits = 8*type_size_of(bt) - element_offset*int_bits; switch (bt->Struct.soa_kind) { case StructSoa_Slice: @@ -756,7 +757,7 @@ gb_internal 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), - field_size_bits + 0*word_bits, + field_size_bits + 0*int_bits, LLVMDIFlagZero, lb_debug_type(m, t_int) ); elements[1] = LLVMDIBuilderCreateMemberType( @@ -764,7 +765,7 @@ gb_internal 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), - field_size_bits + 1*word_bits, + field_size_bits + 1*int_bits, LLVMDIFlagZero, lb_debug_type(m, t_int) ); elements[2] = LLVMDIBuilderCreateMemberType( @@ -772,7 +773,7 @@ gb_internal void lb_debug_complete_types(lbModule *m) { ".allocator", 10, file, 0, 8*cast(u64)type_size_of(t_int), 8*cast(u32)type_align_of(t_int), - field_size_bits + 2*word_bits, + field_size_bits + 2*int_bits, LLVMDIFlagZero, lb_debug_type(m, t_allocator) ); break; diff --git a/src/llvm_backend_expr.cpp b/src/llvm_backend_expr.cpp index 143e38a8d..f95e351ce 100644 --- a/src/llvm_backend_expr.cpp +++ b/src/llvm_backend_expr.cpp @@ -518,7 +518,7 @@ gb_internal bool lb_is_matrix_simdable(Type *t) { return true; case TargetArch_i386: case TargetArch_wasm32: - case TargetArch_wasm64: + case TargetArch_wasm64p32: return false; } } @@ -4230,11 +4230,12 @@ gb_internal lbAddr lb_build_addr_compound_lit(lbProcedure *p, Ast *expr) { lbValue count = {}; count.type = t_int; + unsigned len_index = lb_convert_struct_index(p->module, type, 1); if (lb_is_const(slice)) { - unsigned indices[1] = {1}; + unsigned indices[1] = {len_index}; count.value = LLVMConstExtractValue(slice.value, indices, gb_count_of(indices)); } else { - count.value = LLVMBuildExtractValue(p->builder, slice.value, 1, ""); + count.value = LLVMBuildExtractValue(p->builder, slice.value, len_index, ""); } lb_fill_slice(p, v, data, count); } diff --git a/src/llvm_backend_general.cpp b/src/llvm_backend_general.cpp index 628c1e5fa..e5f3e3081 100644 --- a/src/llvm_backend_general.cpp +++ b/src/llvm_backend_general.cpp @@ -1,4 +1,5 @@ gb_internal void lb_add_debug_local_variable(lbProcedure *p, LLVMValueRef ptr, Type *type, Token const &token); +gb_internal LLVMValueRef llvm_const_string_internal(lbModule *m, Type *t, LLVMValueRef data, LLVMValueRef len); gb_global Entity *lb_global_type_info_data_entity = {}; gb_global lbAddr lb_global_type_info_member_types = {}; @@ -1579,7 +1580,7 @@ gb_internal LLVMTypeRef lb_type_internal_for_procedures_raw(lbModule *m, Type *t } } GB_ASSERT(param_index == param_count); - lbFunctionType *ft = lb_get_abi_info(m->ctx, params, param_count, ret, ret != nullptr, return_is_tuple, type->Proc.calling_convention); + lbFunctionType *ft = lb_get_abi_info(m->ctx, params, param_count, ret, ret != nullptr, return_is_tuple, type->Proc.calling_convention, type); { for_array(j, ft->args) { auto arg = ft->args[j]; @@ -1626,6 +1627,8 @@ gb_internal LLVMTypeRef lb_type_internal(lbModule *m, Type *type) { GB_ASSERT(type != t_invalid); + bool bigger_int = build_context.ptr_size != build_context.int_size; + switch (type->kind) { case Type_Basic: switch (type->Basic.kind) { @@ -1760,10 +1763,10 @@ gb_internal LLVMTypeRef lb_type_internal(lbModule *m, Type *type) { return type; } - case Basic_int: return LLVMIntTypeInContext(ctx, 8*cast(unsigned)build_context.word_size); - case Basic_uint: return LLVMIntTypeInContext(ctx, 8*cast(unsigned)build_context.word_size); + case Basic_int: return LLVMIntTypeInContext(ctx, 8*cast(unsigned)build_context.int_size); + case Basic_uint: return LLVMIntTypeInContext(ctx, 8*cast(unsigned)build_context.int_size); - case Basic_uintptr: return LLVMIntTypeInContext(ctx, 8*cast(unsigned)build_context.word_size); + case Basic_uintptr: return LLVMIntTypeInContext(ctx, 8*cast(unsigned)build_context.ptr_size); case Basic_rawptr: return LLVMPointerType(LLVMInt8TypeInContext(ctx), 0); case Basic_string: @@ -1774,11 +1777,23 @@ gb_internal LLVMTypeRef lb_type_internal(lbModule *m, Type *type) { return type; } type = LLVMStructCreateNamed(ctx, name); - LLVMTypeRef fields[2] = { - LLVMPointerType(lb_type(m, t_u8), 0), - lb_type(m, t_int), - }; - LLVMStructSetBody(type, fields, 2, false); + + if (build_context.metrics.ptr_size < build_context.metrics.int_size) { + GB_ASSERT(build_context.metrics.ptr_size == 4); + GB_ASSERT(build_context.metrics.int_size == 8); + LLVMTypeRef fields[3] = { + LLVMPointerType(lb_type(m, t_u8), 0), + lb_type(m, t_i32), + lb_type(m, t_int), + }; + LLVMStructSetBody(type, fields, 3, false); + } else { + LLVMTypeRef fields[2] = { + LLVMPointerType(lb_type(m, t_u8), 0), + lb_type(m, t_int), + }; + LLVMStructSetBody(type, fields, 2, false); + } return type; } case Basic_cstring: return LLVMPointerType(LLVMInt8TypeInContext(ctx), 0); @@ -1798,7 +1813,7 @@ gb_internal LLVMTypeRef lb_type_internal(lbModule *m, Type *type) { return type; } - case Basic_typeid: return LLVMIntTypeInContext(m->ctx, 8*cast(unsigned)build_context.word_size); + case Basic_typeid: return LLVMIntTypeInContext(m->ctx, 8*cast(unsigned)build_context.ptr_size); // Endian Specific Types case Basic_i16le: return LLVMInt16TypeInContext(ctx); @@ -1922,23 +1937,43 @@ gb_internal LLVMTypeRef lb_type_internal(lbModule *m, Type *type) { case Type_Slice: { - LLVMTypeRef fields[2] = { - LLVMPointerType(lb_type(m, type->Slice.elem), 0), // data - lb_type(m, t_int), // len - }; - return LLVMStructTypeInContext(ctx, fields, 2, false); + if (bigger_int) { + LLVMTypeRef fields[3] = { + LLVMPointerType(lb_type(m, type->Slice.elem), 0), // data + lb_type_padding_filler(m, build_context.ptr_size, build_context.ptr_size), // padding + lb_type(m, t_int), // len + }; + return LLVMStructTypeInContext(ctx, fields, gb_count_of(fields), false); + } else { + LLVMTypeRef fields[2] = { + LLVMPointerType(lb_type(m, type->Slice.elem), 0), // data + lb_type(m, t_int), // len + }; + return LLVMStructTypeInContext(ctx, fields, gb_count_of(fields), false); + } } break; case Type_DynamicArray: { - LLVMTypeRef fields[4] = { - LLVMPointerType(lb_type(m, type->DynamicArray.elem), 0), // data - lb_type(m, t_int), // len - lb_type(m, t_int), // cap - lb_type(m, t_allocator), // allocator - }; - return LLVMStructTypeInContext(ctx, fields, 4, false); + if (bigger_int) { + LLVMTypeRef fields[5] = { + LLVMPointerType(lb_type(m, type->DynamicArray.elem), 0), // data + lb_type_padding_filler(m, build_context.ptr_size, build_context.ptr_size), // padding + lb_type(m, t_int), // len + lb_type(m, t_int), // cap + lb_type(m, t_allocator), // allocator + }; + return LLVMStructTypeInContext(ctx, fields, gb_count_of(fields), false); + } else { + LLVMTypeRef fields[4] = { + LLVMPointerType(lb_type(m, type->DynamicArray.elem), 0), // data + lb_type(m, t_int), // len + lb_type(m, t_int), // cap + lb_type(m, t_allocator), // allocator + }; + return LLVMStructTypeInContext(ctx, fields, gb_count_of(fields), false); + } } break; @@ -2145,9 +2180,17 @@ gb_internal LLVMTypeRef lb_type_internal(lbModule *m, Type *type) { case Type_SoaPointer: { unsigned field_count = 2; + if (bigger_int) { + field_count = 3; + } LLVMTypeRef *fields = gb_alloc_array(permanent_allocator(), LLVMTypeRef, field_count); fields[0] = LLVMPointerType(lb_type(m, type->Pointer.elem), 0); - fields[1] = LLVMIntTypeInContext(ctx, 8*cast(unsigned)build_context.word_size); + if (bigger_int) { + fields[1] = lb_type_padding_filler(m, build_context.ptr_size, build_context.ptr_size); + fields[2] = LLVMIntTypeInContext(ctx, 8*cast(unsigned)build_context.int_size); + } else { + fields[1] = LLVMIntTypeInContext(ctx, 8*cast(unsigned)build_context.int_size); + } return LLVMStructTypeInContext(ctx, fields, field_count, false); } @@ -2503,10 +2546,9 @@ gb_internal lbValue lb_find_or_add_entity_string(lbModule *m, String const &str) ptr = LLVMConstNull(lb_type(m, t_u8_ptr)); } LLVMValueRef str_len = LLVMConstInt(lb_type(m, t_int), str.len, true); - LLVMValueRef values[2] = {ptr, str_len}; lbValue res = {}; - res.value = llvm_const_named_struct(m, t_string, values, 2); + res.value = llvm_const_string_internal(m, t_string, ptr, str_len); res.type = t_string; return res; } diff --git a/src/llvm_backend_proc.cpp b/src/llvm_backend_proc.cpp index b8353a466..f7298a4a6 100644 --- a/src/llvm_backend_proc.cpp +++ b/src/llvm_backend_proc.cpp @@ -14,7 +14,7 @@ gb_internal void lb_mem_copy_overlapping(lbProcedure *p, lbValue dst, lbValue sr char const *name = "llvm.memmove"; if (LLVMIsConstant(len.value)) { i64 const_len = cast(i64)LLVMConstIntGetSExtValue(len.value); - if (const_len <= 4*build_context.word_size) { + if (const_len <= 4*build_context.int_size) { name = "llvm.memmove.inline"; } } @@ -43,7 +43,7 @@ gb_internal void lb_mem_copy_non_overlapping(lbProcedure *p, lbValue dst, lbValu char const *name = "llvm.memcpy"; if (LLVMIsConstant(len.value)) { i64 const_len = cast(i64)LLVMConstIntGetSExtValue(len.value); - if (const_len <= 4*build_context.word_size) { + if (const_len <= 4*build_context.int_size) { name = "llvm.memcpy.inline"; } } @@ -2890,7 +2890,7 @@ gb_internal lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValu { char const *name = "llvm.wasm.memory.grow"; LLVMTypeRef types[1] = { - lb_type(p->module, t_uintptr), + lb_type(p->module, t_i32), }; LLVMValueRef args[2] = {}; @@ -2898,24 +2898,24 @@ gb_internal lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValu args[1] = lb_emit_conv(p, lb_build_expr(p, ce->args[1]), t_uintptr).value; lbValue res = {}; - res.type = tv.type; + res.type = t_i32; res.value = lb_call_intrinsic(p, name, args, gb_count_of(args), types, gb_count_of(types)); - return res; + return lb_emit_conv(p, res, tv.type); } case BuiltinProc_wasm_memory_size: { char const *name = "llvm.wasm.memory.size"; LLVMTypeRef types[1] = { - lb_type(p->module, t_uintptr), + lb_type(p->module, t_i32), }; LLVMValueRef args[1] = {}; args[0] = lb_emit_conv(p, lb_build_expr(p, ce->args[0]), t_uintptr).value; lbValue res = {}; - res.type = tv.type; + res.type = t_i32; res.value = lb_call_intrinsic(p, name, args, gb_count_of(args), types, gb_count_of(types)); - return res; + return lb_emit_conv(p, res, tv.type); } case BuiltinProc_wasm_memory_atomic_wait32: diff --git a/src/llvm_backend_stmt.cpp b/src/llvm_backend_stmt.cpp index b305cc796..275d1f728 100644 --- a/src/llvm_backend_stmt.cpp +++ b/src/llvm_backend_stmt.cpp @@ -1812,7 +1812,7 @@ gb_internal void lb_build_return_stmt_internal(lbProcedure *p, lbValue res) { if (res.value != nullptr) { LLVMValueRef res_val = res.value; i64 sz = type_size_of(res.type); - if (LLVMIsALoadInst(res_val) && sz > build_context.word_size) { + if (LLVMIsALoadInst(res_val) && sz > build_context.int_size) { lbValue ptr = lb_address_from_load_or_generate_local(p, res); lb_mem_copy_non_overlapping(p, p->return_ptr.addr, ptr, lb_const_int(p->module, t_int, sz)); } else { @@ -2471,6 +2471,7 @@ gb_internal void lb_build_stmt(lbProcedure *p, Ast *node) { } GB_ASSERT(lval_index == lvals.count); + for_array(i, vd->names) { Ast *name = vd->names[i]; if (!is_blank_ident(name) && !lvals_preused[i]) { diff --git a/src/llvm_backend_type.cpp b/src/llvm_backend_type.cpp index 3af10112f..1e26fd6bd 100644 --- a/src/llvm_backend_type.cpp +++ b/src/llvm_backend_type.cpp @@ -68,21 +68,21 @@ gb_internal lbValue lb_typeid(lbModule *m, Type *type) { } u64 data = 0; - if (build_context.word_size == 4) { + if (build_context.ptr_size == 4) { GB_ASSERT(id <= (1u<<24u)); data |= (id &~ (1u<<24)) << 0u; // index data |= (kind &~ (1u<<5)) << 24u; // kind - data |= (named &~ (1u<<1)) << 29u; // kind - data |= (special &~ (1u<<1)) << 30u; // kind - data |= (reserved &~ (1u<<1)) << 31u; // kind + data |= (named &~ (1u<<1)) << 29u; // named + data |= (special &~ (1u<<1)) << 30u; // special + data |= (reserved &~ (1u<<1)) << 31u; // reserved } else { - GB_ASSERT(build_context.word_size == 8); + GB_ASSERT(build_context.ptr_size == 8); GB_ASSERT(id <= (1ull<<56u)); data |= (id &~ (1ull<<56)) << 0ul; // index data |= (kind &~ (1ull<<5)) << 56ull; // kind - data |= (named &~ (1ull<<1)) << 61ull; // kind - data |= (special &~ (1ull<<1)) << 62ull; // kind - data |= (reserved &~ (1ull<<1)) << 63ull; // kind + data |= (named &~ (1ull<<1)) << 61ull; // named + data |= (special &~ (1ull<<1)) << 62ull; // special + data |= (reserved &~ (1ull<<1)) << 63ull; // reserved } lbValue res = {}; @@ -157,11 +157,11 @@ gb_internal void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup global_type_info_data_entity_count = type->Array.count; LLVMValueRef indices[2] = {llvm_zero(m), llvm_zero(m)}; - LLVMValueRef values[2] = { - LLVMConstInBoundsGEP2(lb_type(m, lb_global_type_info_data_entity->type), lb_global_type_info_data_ptr(m).value, indices, gb_count_of(indices)), - LLVMConstInt(lb_type(m, t_int), type->Array.count, true), - }; - LLVMValueRef slice = llvm_const_named_struct_internal(lb_type(m, type_deref(global_type_table.type)), values, gb_count_of(values)); + LLVMValueRef data = LLVMConstInBoundsGEP2(lb_type(m, lb_global_type_info_data_entity->type), lb_global_type_info_data_ptr(m).value, indices, gb_count_of(indices)); + LLVMValueRef len = LLVMConstInt(lb_type(m, t_int), type->Array.count, true); + Type *t = type_deref(global_type_table.type); + GB_ASSERT(is_type_slice(t)); + LLVMValueRef slice = llvm_const_slice_internal(m, data, len); LLVMSetInitializer(global_type_table.value, slice); } diff --git a/src/llvm_backend_utility.cpp b/src/llvm_backend_utility.cpp index ddae2243b..0c26382ed 100644 --- a/src/llvm_backend_utility.cpp +++ b/src/llvm_backend_utility.cpp @@ -929,7 +929,38 @@ gb_internal lbStructFieldRemapping lb_get_struct_remapping(lbModule *m, Type *t) gb_internal i32 lb_convert_struct_index(lbModule *m, Type *t, i32 index) { if (t->kind == Type_Struct) { auto field_remapping = lb_get_struct_remapping(m, t); - index = field_remapping[index]; + return field_remapping[index]; + } else if (build_context.ptr_size != build_context.int_size) { + switch (t->kind) { + case Type_Basic: + if (t->Basic.kind != Basic_string) { + break; + } + /*fallthrough*/ + case Type_Slice: + GB_ASSERT(build_context.ptr_size*2 == build_context.int_size); + switch (index) { + case 0: return 0; // data + case 1: return 2; // len + } + break; + case Type_DynamicArray: + GB_ASSERT(build_context.ptr_size*2 == build_context.int_size); + switch (index) { + case 0: return 0; // data + case 1: return 2; // len + case 2: return 3; // cap + case 3: return 4; // allocator + } + break; + case Type_SoaPointer: + GB_ASSERT(build_context.ptr_size*2 == build_context.int_size); + switch (index) { + case 0: return 0; // data + case 1: return 2; // offset + } + break; + } } return index; } @@ -1563,7 +1594,7 @@ gb_internal lbValue lb_map_data_uintptr(lbProcedure *p, lbValue value) { GB_ASSERT(is_type_map(value.type) || are_types_identical(value.type, t_raw_map)); lbValue data = lb_emit_struct_ev(p, value, 0); u64 mask_value = 0; - if (build_context.word_size == 4) { + if (build_context.ptr_size == 4) { mask_value = 0xfffffffful & ~(MAP_CACHE_LINE_SIZE-1); } else { mask_value = 0xffffffffffffffffull & ~(MAP_CACHE_LINE_SIZE-1); @@ -1659,7 +1690,7 @@ gb_internal lbValue lb_emit_mul_add(lbProcedure *p, lbValue a, lbValue b, lbValu break; case TargetArch_i386: case TargetArch_wasm32: - case TargetArch_wasm64: + case TargetArch_wasm64p32: is_possible = false; break; } diff --git a/src/types.cpp b/src/types.cpp index 35fbb719b..3cc077f84 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -3417,13 +3417,16 @@ gb_internal i64 type_size_of(Type *t) { if (t->kind == Type_Basic) { GB_ASSERT_MSG(is_type_typed(t), "%s", type_to_string(t)); switch (t->Basic.kind) { - case Basic_string: size = 2*build_context.word_size; break; - case Basic_cstring: size = build_context.word_size; break; - case Basic_any: size = 2*build_context.word_size; break; - case Basic_typeid: size = build_context.word_size; break; + case Basic_string: size = 2*build_context.int_size; break; + case Basic_cstring: size = build_context.ptr_size; break; + case Basic_any: size = 2*build_context.ptr_size; break; + case Basic_typeid: size = build_context.ptr_size; break; - case Basic_int: case Basic_uint: case Basic_uintptr: case Basic_rawptr: - size = build_context.word_size; + case Basic_int: case Basic_uint: + size = build_context.int_size; + break; + case Basic_uintptr: case Basic_rawptr: + size = build_context.ptr_size; break; default: size = t->Basic.size; @@ -3477,13 +3480,15 @@ gb_internal i64 type_align_of_internal(Type *t, TypePath *path) { case Type_Basic: { GB_ASSERT(is_type_typed(t)); switch (t->Basic.kind) { - case Basic_string: return build_context.word_size; - case Basic_cstring: return build_context.word_size; - case Basic_any: return build_context.word_size; - case Basic_typeid: return build_context.word_size; + case Basic_string: return build_context.int_size; + case Basic_cstring: return build_context.ptr_size; + case Basic_any: return build_context.ptr_size; + case Basic_typeid: return build_context.ptr_size; - case Basic_int: case Basic_uint: case Basic_uintptr: case Basic_rawptr: - return build_context.word_size; + case Basic_int: case Basic_uint: + return build_context.int_size; + case Basic_uintptr: case Basic_rawptr: + return build_context.ptr_size; case Basic_complex32: case Basic_complex64: case Basic_complex128: return type_size_of_internal(t, path) / 2; @@ -3516,10 +3521,10 @@ gb_internal i64 type_align_of_internal(Type *t, TypePath *path) { case Type_DynamicArray: // data, count, capacity, allocator - return build_context.word_size; + return build_context.int_size; case Type_Slice: - return build_context.word_size; + return build_context.int_size; case Type_Tuple: { @@ -3534,7 +3539,7 @@ gb_internal i64 type_align_of_internal(Type *t, TypePath *path) { } break; case Type_Map: - return build_context.word_size; + return build_context.ptr_size; case Type_Enum: return type_align_of_internal(t->Enum.base_type, path); @@ -3614,10 +3619,10 @@ gb_internal i64 type_align_of_internal(Type *t, TypePath *path) { return type_align_of_internal(t->RelativeSlice.base_integer, path); case Type_SoaPointer: - return build_context.word_size; + return build_context.int_size; } - // NOTE(bill): Things that are bigger than build_context.word_size, are actually comprised of smaller types + // NOTE(bill): Things that are bigger than build_context.ptr_size, are actually comprised of smaller types // TODO(bill): Is this correct for 128-bit types (integers)? return gb_clamp(next_pow2(type_size_of_internal(t, path)), 1, build_context.max_align); } @@ -3699,24 +3704,26 @@ gb_internal i64 type_size_of_internal(Type *t, TypePath *path) { return size; } switch (kind) { - case Basic_string: return 2*build_context.word_size; - case Basic_cstring: return build_context.word_size; - case Basic_any: return 2*build_context.word_size; - case Basic_typeid: return build_context.word_size; + case Basic_string: return 2*build_context.int_size; + case Basic_cstring: return build_context.ptr_size; + case Basic_any: return 2*build_context.ptr_size; + case Basic_typeid: return build_context.ptr_size; - case Basic_int: case Basic_uint: case Basic_uintptr: case Basic_rawptr: - return build_context.word_size; + case Basic_int: case Basic_uint: + return build_context.int_size; + case Basic_uintptr: case Basic_rawptr: + return build_context.ptr_size; } } break; case Type_Pointer: - return build_context.word_size; + return build_context.ptr_size; case Type_MultiPointer: - return build_context.word_size; + return build_context.ptr_size; case Type_SoaPointer: - return build_context.word_size*2; + return build_context.int_size*2; case Type_Array: { i64 count, align, size, alignment; @@ -3749,11 +3756,11 @@ gb_internal i64 type_size_of_internal(Type *t, TypePath *path) { } break; case Type_Slice: // ptr + len - return 2 * build_context.word_size; + return 2 * build_context.int_size; case Type_DynamicArray: // data + len + cap + allocator(procedure+data) - return (3 + 2)*build_context.word_size; + return 3*build_context.int_size + 2*build_context.ptr_size; case Type_Map: /* @@ -3763,7 +3770,7 @@ gb_internal i64 type_size_of_internal(Type *t, TypePath *path) { allocator: runtime.Allocator, // 2 words } */ - return (1 + 1 + 2)*build_context.word_size; + return (1 + 1 + 2)*build_context.ptr_size; case Type_Tuple: { i64 count, align, size; @@ -3889,7 +3896,7 @@ gb_internal i64 type_size_of_internal(Type *t, TypePath *path) { } // Catch all - return build_context.word_size; + return build_context.ptr_size; } gb_internal i64 type_offset_of(Type *t, i32 index) { @@ -3909,32 +3916,32 @@ gb_internal i64 type_offset_of(Type *t, i32 index) { } else if (t->kind == Type_Basic) { if (t->Basic.kind == Basic_string) { switch (index) { - case 0: return 0; // data - case 1: return build_context.word_size; // len + case 0: return 0; // data + case 1: return build_context.int_size; // len } } else if (t->Basic.kind == Basic_any) { switch (index) { - case 0: return 0; // type_info - case 1: return build_context.word_size; // data + case 0: return 0; // type_info + case 1: return build_context.ptr_size; // data } } } else if (t->kind == Type_Slice) { switch (index) { - case 0: return 0; // data - case 1: return 1*build_context.word_size; // len - case 2: return 2*build_context.word_size; // cap + case 0: return 0; // data + case 1: return 1*build_context.int_size; // len + case 2: return 2*build_context.int_size; // cap } } else if (t->kind == Type_DynamicArray) { switch (index) { - case 0: return 0; // data - case 1: return 1*build_context.word_size; // len - case 2: return 2*build_context.word_size; // cap - case 3: return 3*build_context.word_size; // allocator + case 0: return 0; // data + case 1: return 1*build_context.int_size; // len + case 2: return 2*build_context.int_size; // cap + case 3: return 3*build_context.int_size; // allocator } } else if (t->kind == Type_Union) { /* i64 s = */ type_size_of(t); switch (index) { - case -1: return align_formula(t->Union.variant_block_size, build_context.word_size); // __type_info + case -1: return align_formula(t->Union.variant_block_size, build_context.ptr_size); // __type_info } } return 0; diff --git a/vendor/wasm/js/dom.odin b/vendor/wasm/js/dom.odin index d650dd70a..2662c4201 100644 --- a/vendor/wasm/js/dom.odin +++ b/vendor/wasm/js/dom.odin @@ -1,4 +1,4 @@ -//+build js wasm32, js wasm64 +//+build js wasm32, js wasm64p32 package wasm_js_interface foreign import dom_lib "odin_dom" diff --git a/vendor/wasm/js/events.odin b/vendor/wasm/js/events.odin index 136c0610d..f14d7054e 100644 --- a/vendor/wasm/js/events.odin +++ b/vendor/wasm/js/events.odin @@ -1,4 +1,4 @@ -//+build js wasm32, js wasm64 +//+build js wasm32, js wasm64p32 package wasm_js_interface foreign import dom_lib "odin_dom" diff --git a/vendor/wasm/js/general.odin b/vendor/wasm/js/general.odin index 0f6a9589c..513c60a6f 100644 --- a/vendor/wasm/js/general.odin +++ b/vendor/wasm/js/general.odin @@ -1,4 +1,4 @@ -//+build js wasm32, js wasm64 +//+build js wasm32, js wasm64p32 package wasm_js_interface foreign import "odin_env" diff --git a/vendor/wasm/js/memory_js.odin b/vendor/wasm/js/memory_js.odin index efbf89445..cdeb58128 100644 --- a/vendor/wasm/js/memory_js.odin +++ b/vendor/wasm/js/memory_js.odin @@ -1,4 +1,4 @@ -//+build js wasm32, js wasm64 +//+build js wasm32, js wasm64p32 package wasm_js_interface import "core:mem"