aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLaytan Laats <laytanlaats@hotmail.com>2023-11-12 02:02:30 +0100
committerLaytan Laats <laytanlaats@hotmail.com>2023-11-15 18:06:27 +0100
commit6b9202dfbf25a022287583197e57dbcd9159ea63 (patch)
tree085f5f9607304b39281a330396e6451465117174
parent70c1f9d0e19a4b97c03308de8f2b9c0c28ba4cf1 (diff)
-no-crt and assembly compilation on darwin
-rw-r--r--core/runtime/entry_unix.odin11
-rw-r--r--core/runtime/entry_unix_no_crt_darwin_arm64.asm20
-rw-r--r--core/runtime/os_specific_any.odin2
-rw-r--r--core/runtime/os_specific_darwin.odin12
-rw-r--r--src/checker.cpp2
-rw-r--r--src/linker.cpp42
6 files changed, 68 insertions, 21 deletions
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)) {