Parcourir la source

Begin work on supporting wasm32 architecture

gingerBill il y a 5 ans
Parent
commit
098699103d
5 fichiers modifiés avec 146 ajouts et 9 suppressions
  1. 68 0
      core/os/os_js_wasm32.odin
  2. 14 0
      core/runtime/procs_wasm32.odin
  3. 22 3
      src/build_settings.cpp
  4. 27 3
      src/llvm_backend.cpp
  5. 15 3
      src/main.cpp

+ 68 - 0
core/os/os_js_wasm32.odin

@@ -0,0 +1,68 @@
+package os
+
+OS :: "js";
+
+
+Handle :: distinct i32;
+Errno :: distinct i32;
+
+ERROR_NONE :: Errno(0);
+
+O_RDONLY   :: 0x00000;
+O_WRONLY   :: 0x00001;
+O_RDWR     :: 0x00002;
+O_CREATE   :: 0x00040;
+O_EXCL     :: 0x00080;
+O_NOCTTY   :: 0x00100;
+O_TRUNC    :: 0x00200;
+O_NONBLOCK :: 0x00800;
+O_APPEND   :: 0x00400;
+O_SYNC     :: 0x01000;
+O_ASYNC    :: 0x02000;
+O_CLOEXEC  :: 0x80000;
+
+stdout: Handle;
+stderr: Handle;
+stdin: Handle;
+
+
+write :: proc(fd: Handle, data: []byte) -> (int, Errno) {
+	return 0, 0;
+}
+read :: proc(fd: Handle, data: []byte) -> (int, Errno) {
+	return 0, 0;
+}
+open :: proc(path: string, mode: int = O_RDONLY, perm: int = 0) -> (Handle, Errno) {
+	return 0, 0;
+}
+close :: proc(fd: Handle) -> Errno {
+	return 0;
+}
+
+
+current_thread_id :: proc "contextless" () -> int {
+	return 0;
+}
+
+
+file_size :: proc(fd: Handle) -> (i64, Errno) {
+	return 0, 0;
+}
+
+
+
+heap_alloc :: proc(size: int) -> rawptr {
+	return nil;
+}
+heap_resize :: proc(ptr: rawptr, new_size: int) -> rawptr {
+	if new_size == 0 {
+		heap_free(ptr);
+		return nil;
+	}
+	if ptr == nil do return heap_alloc(new_size);
+
+	return nil;
+}
+heap_free :: proc(ptr: rawptr) {
+	if ptr == nil do return;
+}

+ 14 - 0
core/runtime/procs_wasm32.odin

@@ -0,0 +1,14 @@
+package runtime
+
+@(link_name="memset")
+memset :: proc "c" (ptr: rawptr, val: i32, len: int) -> rawptr {
+	b := byte(val);
+
+	p_start := uintptr(ptr);
+	p_end := p_start + uintptr(max(len, 0));
+	for p := p_start; p < p_end; p += 1 {
+		(^byte)(p)^ = b;
+	}
+
+	return ptr;
+}

+ 22 - 3
src/build_settings.cpp

@@ -5,6 +5,7 @@ enum TargetOsKind {
 	TargetOs_darwin,
 	TargetOs_linux,
 	TargetOs_essence,
+	TargetOs_js,
 
 	TargetOs_COUNT,
 };
@@ -14,6 +15,7 @@ enum TargetArchKind {
 
 	TargetArch_amd64,
 	TargetArch_386,
+	TargetArch_wasm32,
 
 	TargetArch_COUNT,
 };
@@ -33,12 +35,14 @@ String target_os_names[TargetOs_COUNT] = {
 	str_lit("darwin"),
 	str_lit("linux"),
 	str_lit("essence"),
+	str_lit("js"),
 };
 
 String target_arch_names[TargetArch_COUNT] = {
 	str_lit(""),
 	str_lit("amd64"),
 	str_lit("386"),
+	str_lit("wasm32"),
 };
 
 String target_endian_names[TargetEndian_COUNT] = {
@@ -51,11 +55,12 @@ TargetEndianKind target_endians[TargetArch_COUNT] = {
 	TargetEndian_Invalid,
 	TargetEndian_Little,
 	TargetEndian_Little,
+	TargetEndian_Little,
 };
 
 
 
-String const ODIN_VERSION = str_lit("0.12.0");
+String const ODIN_VERSION = str_lit("0.13.0");
 
 
 
@@ -204,6 +209,16 @@ gb_global TargetMetrics target_essence_amd64 = {
 	str_lit("x86_64-pc-none-elf"),
 };
 
+gb_global TargetMetrics target_js_wasm32 = {
+	TargetOs_js,
+	TargetArch_wasm32,
+	4,
+	8,
+	str_lit("wasm32-freestanding-js"),
+	str_lit(""),
+};
+
+
 struct NamedTargetMetrics {
 	String name;
 	TargetMetrics *metrics;
@@ -216,6 +231,8 @@ gb_global NamedTargetMetrics named_targets[] = {
 	{ str_lit("linux_amd64"),   &target_linux_amd64 },
 	{ str_lit("windows_386"),   &target_windows_386 },
 	{ str_lit("windows_amd64"), &target_windows_amd64 },
+	{ str_lit("js_wasm32"),     &target_js_wasm32 },
+	{ str_lit("wasm32"),        &target_js_wasm32 },
 };
 
 NamedTargetMetrics *selected_target_metrics;
@@ -601,7 +618,7 @@ void init_build_context(TargetMetrics *cross_target) {
 		#if defined(GB_SYSTEM_WINDOWS)
 			metrics = target_windows_386;
 		#elif defined(GB_SYSTEM_OSX)
-			#error "Unsupported architecture"
+			#error "Build Error: Unsupported architecture"
 		#else
 			metrics = target_linux_386;
 		#endif
@@ -666,8 +683,10 @@ void init_build_context(TargetMetrics *cross_target) {
 			bc->link_flags = str_lit("-arch x86 ");
 			break;
 		}
+	} else if (bc->metrics.arch == TargetArch_wasm32) {
+
 	} else {
-		gb_printf_err("Unsupported architecture\n");;
+		gb_printf_err("Compiler Error: Unsupported architecture\n");;
 		gb_exit(1);
 	}
 

+ 27 - 3
src/llvm_backend.cpp

@@ -2030,6 +2030,11 @@ lbProcedure *lb_create_procedure(lbModule *m, Entity *entity) {
 	lb_add_member(m, p->name, proc_value);
 	lb_add_procedure_value(m, p);
 
+	if (p->is_export) {
+		LLVMSetLinkage(p->value, LLVMDLLExportLinkage);
+		LLVMSetDLLStorageClass(p->value, LLVMDLLExportStorageClass);
+		LLVMSetVisibility(p->value, LLVMDefaultVisibility);
+	}
 
 	// NOTE(bill): offset==0 is the return value
 	isize offset = 1;
@@ -11135,7 +11140,7 @@ void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup type_info da
 
 			{
 				GB_ASSERT(t->Enum.base_type != nullptr);
-				GB_ASSERT(type_size_of(t_type_info_enum_value) == 16);
+				// GB_ASSERT_MSG(type_size_of(t_type_info_enum_value) == 16, "%lld == 16", cast(long long)type_size_of(t_type_info_enum_value));
 
 
 				LLVMValueRef vals[3] = {};
@@ -11542,7 +11547,12 @@ void lb_generate_code(lbGenerator *gen) {
 
 	TIME_SECTION("LLVM Create Target Machine");
 
-	LLVMTargetMachineRef target_machine = LLVMCreateTargetMachine(target, target_triple, "generic", "", LLVMCodeGenLevelNone, LLVMRelocDefault, LLVMCodeModelDefault);
+	LLVMCodeModel code_mode = LLVMCodeModelDefault;
+	if (build_context.metrics.arch == TargetArch_wasm32) {
+		code_mode = LLVMCodeModelJITDefault;
+	}
+
+	LLVMTargetMachineRef target_machine = LLVMCreateTargetMachine(target, target_triple, "generic", "", LLVMCodeGenLevelNone, LLVMRelocDefault, code_mode);
 	defer (LLVMDisposeTargetMachine(target_machine));
 
 	LLVMSetModuleDataLayout(mod, LLVMCreateTargetDataLayout(target_machine));
@@ -11749,6 +11759,7 @@ void lb_generate_code(lbGenerator *gen) {
 		}
 		if (is_export) {
 			LLVMSetLinkage(g.value, LLVMDLLExportLinkage);
+			LLVMSetDLLStorageClass(g.value, LLVMDLLExportStorageClass);
 		}
 
 		GlobalVariable var = {};
@@ -12135,7 +12146,20 @@ void lb_generate_code(lbGenerator *gen) {
 	String filepath_ll  = concatenate_strings(heap_allocator(), gen->output_base, STR_LIT(".ll"));
 	defer (gb_free(heap_allocator(), filepath_ll.text));
 
-	String filepath_obj = concatenate_strings(heap_allocator(), gen->output_base, STR_LIT(".obj"));
+	String filepath_obj = {};
+	switch (build_context.metrics.os) {
+	case TargetOs_windows:
+		filepath_obj = concatenate_strings(heap_allocator(), gen->output_base, STR_LIT(".obj"));
+		break;
+	case TargetOs_darwin:
+	case TargetOs_linux:
+	case TargetOs_essence:
+		filepath_obj = concatenate_strings(heap_allocator(), gen->output_base, STR_LIT(".o"));
+		break;
+	case TargetOs_js:
+		filepath_obj = concatenate_strings(heap_allocator(), gen->output_base, STR_LIT(".wasm"));
+		break;
+	}
 
 
 	if (build_context.keep_temp_files) {

+ 15 - 3
src/main.cpp

@@ -1415,6 +1415,8 @@ void print_show_help(String const arg0, String const &command) {
 		print_usage_line(3, "-build-mode:exe       Build as an executable");
 		print_usage_line(3, "-build-mode:dll       Build as a dynamically linked library");
 		print_usage_line(3, "-build-mode:shared    Build as a dynamically linked library");
+		print_usage_line(3, "-build-mode:obj       Build as an object file");
+		print_usage_line(3, "-build-mode:object    Build as an object file");
 		print_usage_line(0, "");
 	}
 
@@ -1514,6 +1516,7 @@ int main(int arg_count, char const **arg_ptr) {
 	global_big_int_init();
 	arena_init(&global_ast_arena, heap_allocator());
 
+
 	array_init(&library_collections, heap_allocator());
 	// NOTE(bill): 'core' cannot be (re)defined by the user
 	add_library_collection(str_lit("core"), get_fullpath_relative(heap_allocator(), odin_root_dir(), str_lit("core")));
@@ -1617,10 +1620,20 @@ int main(int arg_count, char const **arg_ptr) {
 
 
 	init_build_context(selected_target_metrics ? selected_target_metrics->metrics : nullptr);
-	if (build_context.word_size == 4) {
-		print_usage_line(0, "%.*s 32-bit is not yet supported", LIT(args[0]));
+	if (build_context.word_size == 4 && build_context.metrics.os != TargetOs_js) {
+		print_usage_line(0, "%.*s 32-bit is not yet supported for this platform", LIT(args[0]));
 		return 1;
 	}
+	if (build_context.metrics.os == TargetOs_js) {
+		if (!build_context.use_llvm_api) {
+			print_usage_line(0, "%.*s - js platform only supported with the -llvm-api backend", LIT(args[0]));
+			return 1;
+		}
+		if (build_context.build_mode != BuildMode_Object) {
+			print_usage_line(0, "%.*s - js platform only supports -build-mode:object", LIT(args[0]));
+			return 1;
+		}
+	}
 
 	init_universal();
 	// TODO(bill): prevent compiling without a linker
@@ -1677,7 +1690,6 @@ int main(int arg_count, char const **arg_ptr) {
 
 	if (build_context.use_llvm_api) {
 #if defined(LLVM_BACKEND_SUPPORT)
-
 		timings_start_section(timings, str_lit("LLVM API Code Gen"));
 		lbGenerator gen = {};
 		if (!lb_init_generator(&gen, &checker)) {