aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgingerBill <gingerBill@users.noreply.github.com>2021-08-28 12:51:22 +0100
committerGitHub <noreply@github.com>2021-08-28 12:51:22 +0100
commit713cd728ba59e3a56db145b0fdb4821df744f349 (patch)
tree651f14e138d77e8456da8ce0eacbbf75fd22db97
parent586641d77fd5585f64f08007f854926099ede375 (diff)
parentf9bea5b791514393b3450a7af1dc8192cd34d493 (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.odin6
-rw-r--r--core/c/libc/ctype.odin6
-rw-r--r--core/c/libc/errno.odin6
-rw-r--r--core/c/libc/math.odin6
-rw-r--r--core/c/libc/setjmp.odin52
-rw-r--r--core/c/libc/signal.odin6
-rw-r--r--core/c/libc/stdio.odin6
-rw-r--r--core/c/libc/stdlib.odin8
-rw-r--r--core/c/libc/string.odin6
-rw-r--r--core/c/libc/tests/general.odin50
-rw-r--r--core/c/libc/threads.odin10
-rw-r--r--core/c/libc/time.odin6
-rw-r--r--core/c/libc/uchar.odin6
-rw-r--r--core/c/libc/wchar.odin6
-rw-r--r--core/c/libc/wctype.odin6
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;