Browse Source

Merge pull request #2470 from odin-lang/separate-int-word-sizes

Separate int size from word/pointer size
gingerBill 2 năm trước cách đây
mục cha
commit
907ef82d4b

+ 1 - 1
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
 

+ 2 - 2
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)

+ 3 - 3
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

+ 1 - 1
core/runtime/entry_wasm.odin

@@ -1,5 +1,5 @@
 //+private
-//+build wasm32, wasm64
+//+build wasm32, wasm64p32
 package runtime
 
 import "core:intrinsics"

+ 1 - 1
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 (

+ 1 - 1
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 {

+ 1 - 1
core/runtime/procs_js_wasm32.odin → core/runtime/procs_js.odin

@@ -1,4 +1,4 @@
-//+build js wasm32
+//+build js
 package runtime
 
 init_default_context_for_js: Context

+ 1 - 1
core/runtime/procs_wasm32.odin → core/runtime/procs_wasm.odin

@@ -1,4 +1,4 @@
-//+build wasm32
+//+build wasm32, wasm64p32
 package runtime
 
 @(private="file")

+ 1 - 1
core/sync/futex_wasm.odin

@@ -1,5 +1,5 @@
 //+private
-//+build wasm32, wasm64
+//+build wasm32, wasm64p32
 package sync
 
 import "core:intrinsics"

+ 1 - 1
core/sync/primitives_wasm.odin

@@ -1,5 +1,5 @@
 //+private
-//+build wasm32, wasm64
+//+build wasm32, wasm64p32
 package sync
 
 _current_thread_id :: proc "contextless" () -> int {

+ 74 - 39
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 = {
+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_wasm64,
-	8, 8, 16,
-	str_lit("wasm64-js-js"),
-	str_lit(""),
+	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 ");
 		}

+ 7 - 9
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},
 		};

+ 51 - 22
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<lbArgType> compute_arg_types(LLVMContextRef c, LLVMTypeRef *arg_types, unsigned arg_count, ProcCallingConvention calling_convention);
+	gb_internal Array<lbArgType> 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<lbArgType> compute_arg_types(LLVMContextRef c, LLVMTypeRef *arg_types, unsigned arg_count, ProcCallingConvention calling_convention) {
+	gb_internal Array<lbArgType> compute_arg_types(LLVMContextRef c, LLVMTypeRef *arg_types, unsigned arg_count, ProcCallingConvention calling_convention,
+	                                               Type *original_type) {
 		auto args = array_make<lbArgType>(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 &params = 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`

+ 1 - 1
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();

+ 1 - 1
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);

+ 41 - 7
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;

+ 35 - 34
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;

+ 4 - 3
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);
 			}

+ 67 - 25
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;
 }

+ 8 - 8
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:

+ 2 - 1
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]) {

+ 13 - 13
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);
 	}

+ 34 - 3
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;
 		}

+ 49 - 42
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;

+ 1 - 1
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"

+ 1 - 1
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"

+ 1 - 1
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"

+ 1 - 1
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"