From 6b9202dfbf25a022287583197e57dbcd9159ea63 Mon Sep 17 00:00:00 2001 From: Laytan Laats Date: Sun, 12 Nov 2023 02:02:30 +0100 Subject: [PATCH] -no-crt and assembly compilation on darwin --- core/runtime/entry_unix.odin | 11 ++--- .../entry_unix_no_crt_darwin_arm64.asm | 20 +++++++++ core/runtime/os_specific_any.odin | 2 +- core/runtime/os_specific_darwin.odin | 12 ++++++ src/checker.cpp | 2 +- src/linker.cpp | 42 ++++++++++++------- 6 files changed, 68 insertions(+), 21 deletions(-) create mode 100644 core/runtime/entry_unix_no_crt_darwin_arm64.asm create mode 100644 core/runtime/os_specific_darwin.odin diff --git a/core/runtime/entry_unix.odin b/core/runtime/entry_unix.odin index 0c718445a..78e545c22 100644 --- a/core/runtime/entry_unix.odin +++ b/core/runtime/entry_unix.odin @@ -26,8 +26,13 @@ when ODIN_BUILD_MODE == .Dynamic { // to retrieve argc and argv from the stack when ODIN_ARCH == .amd64 { @require foreign import entry "entry_unix_no_crt_amd64.asm" + SYS_exit :: 60 } else when ODIN_ARCH == .i386 { @require foreign import entry "entry_unix_no_crt_i386.asm" + SYS_exit :: 1 + } else when ODIN_OS == .Darwin && ODIN_ARCH == .arm64 { + @require foreign import entry "entry_unix_no_crt_darwin_arm64.asm" + SYS_exit :: 1 } @(link_name="_start_odin", linkage="strong", require) _start_odin :: proc "c" (argc: i32, argv: [^]cstring) -> ! { @@ -36,11 +41,7 @@ when ODIN_BUILD_MODE == .Dynamic { #force_no_inline _startup_runtime() intrinsics.__entry_point() #force_no_inline _cleanup_runtime() - when ODIN_ARCH == .amd64 { - intrinsics.syscall(/*SYS_exit = */60) - } else when ODIN_ARCH == .i386 { - intrinsics.syscall(/*SYS_exit = */1) - } + intrinsics.syscall(SYS_exit, 0) unreachable() } } else { diff --git a/core/runtime/entry_unix_no_crt_darwin_arm64.asm b/core/runtime/entry_unix_no_crt_darwin_arm64.asm new file mode 100644 index 000000000..0f71fbdf8 --- /dev/null +++ b/core/runtime/entry_unix_no_crt_darwin_arm64.asm @@ -0,0 +1,20 @@ + .section __TEXT,__text + + ; NOTE(laytan): this should ideally be the -minimum-os-version flag but there is no nice way of preprocessing assembly in Odin. + ; 10 seems to be the lowest it goes and I don't see it mess with any targeted os version so this seems fine. + .build_version macos, 10, 0 + + .extern __start_odin + + .global _main + .align 2 +_main: + mov x5, sp ; use x5 as the stack pointer + + str x0, [x5] ; get argc into x0 (kernel passes 32-bit int argc as 64-bits on stack to keep alignment) + str x1, [x5, #8] ; get argv into x1 + + and sp, x5, #~15 ; force 16-byte alignment of the stack + + bl __start_odin ; call into Odin entry point + ret ; should never get here diff --git a/core/runtime/os_specific_any.odin b/core/runtime/os_specific_any.odin index afa106138..5fffceeeb 100644 --- a/core/runtime/os_specific_any.odin +++ b/core/runtime/os_specific_any.odin @@ -1,4 +1,4 @@ -//+build !freestanding !wasi !windows !js +//+build !freestanding !wasi !windows !js !darwin package runtime import "core:os" diff --git a/core/runtime/os_specific_darwin.odin b/core/runtime/os_specific_darwin.odin new file mode 100644 index 000000000..33136c92f --- /dev/null +++ b/core/runtime/os_specific_darwin.odin @@ -0,0 +1,12 @@ +//+build darwin +package runtime + +import "core:intrinsics" + +_os_write :: proc "contextless" (data: []byte) -> (int, _OS_Errno) { + ret := intrinsics.syscall(4, 1, uintptr(raw_data(data)), uintptr(len(data))) + if ret < 0 { + return 0, _OS_Errno(-ret) + } + return int(ret), 0 +} diff --git a/src/checker.cpp b/src/checker.cpp index 29f22bd9c..0366cf05d 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -4733,7 +4733,7 @@ gb_internal void check_add_foreign_import_decl(CheckerContext *ctx, Ast *decl) { } if (has_asm_extension(fullpath)) { - if (build_context.metrics.arch != TargetArch_amd64) { + if (build_context.metrics.arch != TargetArch_amd64 && build_context.metrics.os != TargetOs_darwin) { error(decl, "Assembly files are not yet supported on this platform: %.*s_%.*s", LIT(target_os_names[build_context.metrics.os]), LIT(target_arch_names[build_context.metrics.arch])); } diff --git a/src/linker.cpp b/src/linker.cpp index eb3687ae2..c3ede0f55 100644 --- a/src/linker.cpp +++ b/src/linker.cpp @@ -337,20 +337,34 @@ gb_internal i32 linker_stage(LinkerData *gen) { obj_format = str_lit("elf32"); } #endif // GB_ARCH_*_BIT - // Note(bumbread): I'm assuming nasm is installed on the host machine. - // Shipping binaries on unix-likes gets into the weird territorry of - // "which version of glibc" is it linked with. - result = system_exec_command_line_app("nasm", - "nasm \"%.*s\" " - "-f \"%.*s\" " - "-o \"%.*s\" " - "%.*s " - "", - LIT(asm_file), - LIT(obj_format), - LIT(obj_file), - LIT(build_context.extra_assembler_flags) - ); + + if (is_osx) { + // `as` comes with MacOS. + result = system_exec_command_line_app("as", + "as \"%.*s\" " + "-o \"%.*s\" " + "%.*s " + "", + LIT(asm_file), + LIT(obj_file), + LIT(build_context.extra_assembler_flags) + ); + } else { + // Note(bumbread): I'm assuming nasm is installed on the host machine. + // Shipping binaries on unix-likes gets into the weird territorry of + // "which version of glibc" is it linked with. + result = system_exec_command_line_app("nasm", + "nasm \"%.*s\" " + "-f \"%.*s\" " + "-o \"%.*s\" " + "%.*s " + "", + LIT(asm_file), + LIT(obj_format), + LIT(obj_file), + LIT(build_context.extra_assembler_flags) + ); + } array_add(&gen->output_object_paths, obj_file); } else { if (string_set_update(&libs, lib)) {