diff options
| author | gingerBill <gingerBill@users.noreply.github.com> | 2021-08-28 12:51:22 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-08-28 12:51:22 +0100 |
| commit | 713cd728ba59e3a56db145b0fdb4821df744f349 (patch) | |
| tree | 651f14e138d77e8456da8ce0eacbbf75fd22db97 | |
| parent | 586641d77fd5585f64f08007f854926099ede375 (diff) | |
| parent | f9bea5b791514393b3450a7af1dc8192cd34d493 (diff) | |
Merge pull request #1107 from odin-lang/mv/libc-errors
Fix libc errors in Windows and add some tests.
| -rw-r--r-- | core/c/libc/complex.odin | 6 | ||||
| -rw-r--r-- | core/c/libc/ctype.odin | 6 | ||||
| -rw-r--r-- | core/c/libc/errno.odin | 6 | ||||
| -rw-r--r-- | core/c/libc/math.odin | 6 | ||||
| -rw-r--r-- | core/c/libc/setjmp.odin | 52 | ||||
| -rw-r--r-- | core/c/libc/signal.odin | 6 | ||||
| -rw-r--r-- | core/c/libc/stdio.odin | 6 | ||||
| -rw-r--r-- | core/c/libc/stdlib.odin | 8 | ||||
| -rw-r--r-- | core/c/libc/string.odin | 6 | ||||
| -rw-r--r-- | core/c/libc/tests/general.odin | 50 | ||||
| -rw-r--r-- | core/c/libc/threads.odin | 10 | ||||
| -rw-r--r-- | core/c/libc/time.odin | 6 | ||||
| -rw-r--r-- | core/c/libc/uchar.odin | 6 | ||||
| -rw-r--r-- | core/c/libc/wchar.odin | 6 | ||||
| -rw-r--r-- | core/c/libc/wctype.odin | 6 |
15 files changed, 161 insertions, 25 deletions
diff --git a/core/c/libc/complex.odin b/core/c/libc/complex.odin index c11e51586..4e199ac69 100644 --- a/core/c/libc/complex.odin +++ b/core/c/libc/complex.odin @@ -2,7 +2,11 @@ package libc // 7.3 Complex arithmetic -foreign import libc "system:c" +when ODIN_OS == "windows" { + foreign import libc "system:libucrt.lib" +} else { + foreign import libc "system:c" +} @(default_calling_convention="c") foreign libc { diff --git a/core/c/libc/ctype.odin b/core/c/libc/ctype.odin index 2f9a023a6..0aefc00c3 100644 --- a/core/c/libc/ctype.odin +++ b/core/c/libc/ctype.odin @@ -1,6 +1,10 @@ package libc -foreign import libc "system:c" +when ODIN_OS == "windows" { + foreign import libc "system:libucrt.lib" +} else { + foreign import libc "system:c" +} // 7.4 Character handling diff --git a/core/c/libc/errno.odin b/core/c/libc/errno.odin index 78f6763eb..6d5a6ff0c 100644 --- a/core/c/libc/errno.odin +++ b/core/c/libc/errno.odin @@ -2,7 +2,11 @@ package libc // 7.5 Errors -foreign import libc "system:c" +when ODIN_OS == "windows" { + foreign import libc "system:libucrt.lib" +} else { + foreign import libc "system:c" +} // C11 standard only requires the definition of: // EDOM, diff --git a/core/c/libc/math.odin b/core/c/libc/math.odin index b3c285950..ae9e3c709 100644 --- a/core/c/libc/math.odin +++ b/core/c/libc/math.odin @@ -4,7 +4,11 @@ package libc import "core:intrinsics" -foreign import libc "system:c" +when ODIN_OS == "windows" { + foreign import libc "system:libucrt.lib" +} else { + foreign import libc "system:c" +} // To support C's tgmath behavior we use Odin's explicit procedure overloading, // but we cannot use the same names as exported by libc so use @(link_name) diff --git a/core/c/libc/setjmp.odin b/core/c/libc/setjmp.odin index 57a31301c..c5b07b893 100644 --- a/core/c/libc/setjmp.odin +++ b/core/c/libc/setjmp.odin @@ -2,18 +2,52 @@ package libc // 7.13 Nonlocal jumps -foreign import libc "system:c" +when ODIN_OS == "windows" { + foreign import libc "system:libucrt.lib" +} else { + foreign import libc "system:c" +} + +when ODIN_OS == "windows" { + @(default_calling_convention="c") + foreign libc { + // 7.13.1 Save calling environment + // + // NOTE(dweiler): C11 requires setjmp be a macro, which means it won't + // necessarily export a symbol named setjmp but rather _setjmp in the case + // of musl, glibc, BSD libc, and msvcrt. + // + /// NOTE(dweiler): UCRT has two implementations of longjmp. One that performs + // stack unwinding and one that doesn't. The choice of which to use depends on a + // flag which is set inside the jmp_buf structure given to setjmp. The default + // behavior is to unwind the stack. Within Odin, we cannot use the stack + // unwinding version as the unwinding information isn't present. To opt-in to + // the regular non-unwinding version we need a way to set this flag. Since the + // location of the flag within the struct is not defined or part of the ABI and + // can change between versions of UCRT, we must rely on setjmp to set it. It + // turns out that setjmp receives this flag in the RDX register on Win64, this + // just so happens to coincide with the second argument of a function in the + // Win64 ABI. By giving our setjmp a second argument with the value of zero, + // the RDX register will contain zero and correctly set the flag to disable + // stack unwinding. + @(link_name="_setjmp") + setjmp :: proc(env: ^jmp_buf, hack: rawptr = nil) -> int ---; + } +} else { + @(default_calling_convention="c") + foreign libc { + // 7.13.1 Save calling environment + // + // NOTE(dweiler): C11 requires setjmp be a macro, which means it won't + // necessarily export a symbol named setjmp but rather _setjmp in the case + // of musl, glibc, BSD libc, and msvcrt. + @(link_name="_setjmp") + setjmp :: proc(env: ^jmp_buf) -> int ---; + } +} @(default_calling_convention="c") foreign libc { - // 7.13.1 Save calling environment - // - // NOTE(dweiler): C11 requires setjmp be a macro, which means it won't - // necessarily export a symbol named setjmp but rather _setjmp in the case - // of musl, glibc, BSD libc, and msvcrt. - @(link_name="_setjmp") - setjmp :: proc(env: ^jmp_buf) -> int ---; - // 7.13.2 Restore calling environment longjmp :: proc(env: ^jmp_buf, val: int) -> ! ---; } diff --git a/core/c/libc/signal.odin b/core/c/libc/signal.odin index 04a2d373f..22bcaec0b 100644 --- a/core/c/libc/signal.odin +++ b/core/c/libc/signal.odin @@ -2,7 +2,11 @@ package libc // 7.14 Signal handling -foreign import libc "system:c" +when ODIN_OS == "windows" { + foreign import libc "system:libucrt.lib" +} else { + foreign import libc "system:c" +} sig_atomic_t :: distinct atomic_int; diff --git a/core/c/libc/stdio.odin b/core/c/libc/stdio.odin index 40e32ea07..0f7cb44a7 100644 --- a/core/c/libc/stdio.odin +++ b/core/c/libc/stdio.odin @@ -1,6 +1,10 @@ package libc -foreign import libc "system:c" +when ODIN_OS == "windows" { + foreign import libc "system:libucrt.lib" +} else { + foreign import libc "system:c" +} // 7.21 Input/output diff --git a/core/c/libc/stdlib.odin b/core/c/libc/stdlib.odin index ce9dc9c4e..ba4602e84 100644 --- a/core/c/libc/stdlib.odin +++ b/core/c/libc/stdlib.odin @@ -2,7 +2,11 @@ package libc // 7.22 General utilities -foreign import libc "system:c" +when ODIN_OS == "windows" { + foreign import libc "system:libucrt.lib" +} else { + foreign import libc "system:c" +} when ODIN_OS == "windows" { RAND_MAX :: 0x7fff; @@ -14,7 +18,7 @@ when ODIN_OS == "windows" { } MB_CUR_MAX :: #force_inline proc() -> size_t { - return ___mb_cur_max_func(); + return size_t(___mb_cur_max_func()); } } diff --git a/core/c/libc/string.odin b/core/c/libc/string.odin index 9665a8491..d39b4ecb2 100644 --- a/core/c/libc/string.odin +++ b/core/c/libc/string.odin @@ -3,7 +3,11 @@ package libc // 7.24 String handling -foreign import libc "system:c" +when ODIN_OS == "windows" { + foreign import libc "system:libucrt.lib" +} else { + foreign import libc "system:c" +} foreign libc { // 7.24.2 Copying functions diff --git a/core/c/libc/tests/general.odin b/core/c/libc/tests/general.odin new file mode 100644 index 000000000..1c311a8f3 --- /dev/null +++ b/core/c/libc/tests/general.odin @@ -0,0 +1,50 @@ +package libc_tests + +import "core:c/libc" + +test_stdio :: proc() { + c: libc.char = 'C'; + libc.puts("Hello from puts"); + libc.printf("Hello from printf in %c\n", c); +} +test_thread :: proc() { + thread_proc :: proc "c" (rawptr) -> libc.int { + libc.printf("Hello from thread"); + return 42; + } + thread: libc.thrd_t; + libc.thrd_create(&thread, thread_proc, nil); + result: libc.int; + libc.thrd_join(thread, &result); + libc.printf(" %d\n", result); +} + +jmp: libc.jmp_buf; +test_sjlj :: proc() { + if libc.setjmp(&jmp) != 0 { + libc.printf("Hello from longjmp\n"); + return; + } + libc.printf("Hello from setjmp\n"); + libc.longjmp(&jmp, 1); +} +test_signal :: proc() { + handler :: proc "c" (sig: libc.int) { + libc.printf("Hello from signal handler\n"); + } + libc.signal(libc.SIGABRT, handler); + libc.raise(libc.SIGABRT); +} +test_atexit :: proc() { + handler :: proc "c" () { + libc.printf("Hello from atexit\n"); + } + libc.atexit(handler); +} +main :: proc() { + test_stdio(); + test_thread(); + test_sjlj(); + test_signal(); + test_atexit(); +}
\ No newline at end of file diff --git a/core/c/libc/threads.odin b/core/c/libc/threads.odin index 93d4f4efe..cf21bc614 100644 --- a/core/c/libc/threads.odin +++ b/core/c/libc/threads.odin @@ -6,7 +6,10 @@ thrd_start_t :: proc "c" (rawptr) -> int; tss_dtor_t :: proc "c" (rawptr); when ODIN_OS == "windows" { - foreign import libc "system:c" + foreign import libc { + "system:libucrt.lib", + "system:msvcprt.lib" + } thrd_success :: 0; // _Thrd_success thrd_nomem :: 1; // _Thrd_nomem @@ -24,6 +27,7 @@ when ODIN_OS == "windows" { thrd_t :: struct { _: rawptr, _: uint, } // _Thrd_t tss_t :: distinct int; // _Tss_imp_t cnd_t :: distinct rawptr; // _Cnd_imp_t + mtx_t :: distinct rawptr; // _Mtx_imp_t // MSVCRT does not expose the C11 symbol names as what they are in C11 // because they held off implementing <threads.h> and C11 support for so @@ -52,9 +56,9 @@ when ODIN_OS == "windows" { @(link_name="_Mtx_unlock") mtx_unlock :: proc(mtx: ^mtx_t) -> int ---; // 7.26.5 Thread functions - @(link_name="_Thrd_create") thrd_create :: proc(thr: ^thr_t, func: thrd_start_t, arg: rawptr) -> int ---; + @(link_name="_Thrd_create") thrd_create :: proc(thr: ^thrd_t, func: thrd_start_t, arg: rawptr) -> int ---; @(link_name="_Thrd_current") thrd_current :: proc() -> thrd_t ---; - @(link_name="_Thrd_detach") thrd_detach :: proc(thr: thr_t) -> int ---; + @(link_name="_Thrd_detach") thrd_detach :: proc(thr: thrd_t) -> int ---; @(link_name="_Thrd_equal") thrd_equal :: proc(lhs, rhs: thrd_t) -> int ---; @(link_name="_Thrd_exit") thrd_exit :: proc(res: int) -> ! ---; @(link_name="_Thrd_join") thrd_join :: proc(thr: thrd_t, res: ^int) -> int ---; diff --git a/core/c/libc/time.odin b/core/c/libc/time.odin index 42dd739e2..93574ae38 100644 --- a/core/c/libc/time.odin +++ b/core/c/libc/time.odin @@ -2,7 +2,11 @@ package libc // 7.27 Date and time -foreign import libc "system:c" +when ODIN_OS == "windows" { + foreign import libc "system:libucrt.lib" +} else { + foreign import libc "system:c" +} // We enforce 64-bit time_t and timespec as there is no reason to use 32-bit as // we approach the 2038 problem. Windows has defaulted to this since VC8 (2005). diff --git a/core/c/libc/uchar.odin b/core/c/libc/uchar.odin index 60b71d786..e9adbe13d 100644 --- a/core/c/libc/uchar.odin +++ b/core/c/libc/uchar.odin @@ -2,7 +2,11 @@ package libc // 7.28 Unicode utilities -foreign import libc "system:c" +when ODIN_OS == "windows" { + foreign import libc "system:libucrt.lib" +} else { + foreign import libc "system:c" +} @(default_calling_convention="c") foreign libc { diff --git a/core/c/libc/wchar.odin b/core/c/libc/wchar.odin index d66fa91b7..9851c8053 100644 --- a/core/c/libc/wchar.odin +++ b/core/c/libc/wchar.odin @@ -2,7 +2,11 @@ package libc // 7.29 Extended multibyte and wide character utilities -foreign import libc "system:c" +when ODIN_OS == "windows" { + foreign import libc "system:libucrt.lib" +} else { + foreign import libc "system:c" +} @(default_calling_convention="c") foreign libc { diff --git a/core/c/libc/wctype.odin b/core/c/libc/wctype.odin index fed258acd..8b887d309 100644 --- a/core/c/libc/wctype.odin +++ b/core/c/libc/wctype.odin @@ -2,7 +2,11 @@ package libc // 7.30 Wide character classification and mapping utilities -foreign import libc "system:c" +when ODIN_OS == "windows" { + foreign import libc "system:libucrt.lib" +} else { + foreign import libc "system:c" +} when ODIN_OS == "windows" { wctrans_t :: distinct wchar_t; |