Forráskód Böngészése

Merge branch 'master' of https://github.com/odin-lang/Odin

gingerBill 1 éve
szülő
commit
a667878d23

+ 2 - 1
.github/workflows/ci.yml

@@ -10,7 +10,7 @@ jobs:
     steps:
     - uses: actions/checkout@v4
     - name: Build, Check, and Test
-      timeout-minutes: 25
+      timeout-minutes: 15
       uses: vmactions/netbsd-vm@v1
       with:
         release: "10.0"
@@ -31,6 +31,7 @@ jobs:
           ./odin version
           ./odin report
           ./odin check examples/all -vet -strict-style -target:netbsd_amd64
+          ./odin check examples/all -vet -strict-style -target:netbsd_arm64
           (cd tests/core; gmake all_bsd)
           (cd tests/internal; gmake all_bsd)
           (cd tests/issues; ./run.sh)

+ 6 - 2
core/os/os_netbsd.odin

@@ -5,7 +5,6 @@ foreign import libc "system:c"
 
 import "base:runtime"
 import "core:strings"
-import "core:sys/unix"
 import "core:c"
 
 Handle :: distinct i32
@@ -328,6 +327,11 @@ foreign dl {
 	@(link_name="dlerror")          _unix_dlerror       :: proc() -> cstring ---
 }
 
+@(private)
+foreign libc {
+	_lwp_self :: proc() -> i32 ---
+}
+
 // NOTE(phix): Perhaps share the following functions with FreeBSD if they turn out to be the same in the end.
 
 is_path_separator :: proc(r: rune) -> bool {
@@ -721,7 +725,7 @@ exit :: proc "contextless" (code: int) -> ! {
 }
 
 current_thread_id :: proc "contextless" () -> int {
-	return cast(int) unix.pthread_self()
+	return int(_lwp_self())
 }
 
 dlopen :: proc(filename: string, flags: int) -> rawptr {

+ 9 - 6
core/strconv/strconv.odin

@@ -882,13 +882,16 @@ parse_f64_prefix :: proc(str: string) -> (value: f64, nr: int, ok: bool) {
 				s = s[1:]
 				fallthrough
 			case 'i', 'I':
-				n = common_prefix_len_ignore_case(s, "infinity")
-				if 3 < n && n < 8 { // "inf" or "infinity"
-					n = 3
-				}
-				if n == 3 || n == 8 {
+				m := common_prefix_len_ignore_case(s, "infinity")
+				if 3 <= m && m < 9 { // "inf" to "infinity"
 					f = 0h7ff00000_00000000 if sign == 1 else 0hfff00000_00000000
-					n = nsign + 3
+					if m == 8 {
+						// We only count the entire prefix if it is precisely "infinity".
+						n = nsign + m
+					} else {
+						// The string was either only "inf" or incomplete.
+						n = nsign + 3
+					}
 					ok = true
 					return
 				}

+ 6 - 2
core/sync/primitives_netbsd.odin

@@ -1,8 +1,12 @@
 //+private
 package sync
 
-import "core:sys/unix"
+foreign import libc "system:c"
+
+foreign libc {
+	_lwp_self :: proc "c" () -> i32 ---
+}
 
 _current_thread_id :: proc "contextless" () -> int {
-	return cast(int) unix.pthread_self()
+	return int(_lwp_self())
 }

+ 15 - 2
src/build_settings.cpp

@@ -1039,6 +1039,13 @@ gb_global TargetMetrics target_netbsd_amd64 = {
 	str_lit("x86_64-unknown-netbsd-elf"),
 };
 
+gb_global TargetMetrics target_netbsd_arm64 = {
+	TargetOs_netbsd,
+	TargetArch_arm64,
+	8, 8, 16, 16,
+	str_lit("aarch64-unknown-netbsd-elf"),
+};
+
 gb_global TargetMetrics target_haiku_amd64 = {
 	TargetOs_haiku,
 	TargetArch_amd64,
@@ -1154,8 +1161,10 @@ gb_global NamedTargetMetrics named_targets[] = {
 	{ str_lit("freebsd_amd64"),       &target_freebsd_amd64  },
 	{ str_lit("freebsd_arm64"),       &target_freebsd_arm64  },
 
-	{ str_lit("openbsd_amd64"),       &target_openbsd_amd64  },
 	{ str_lit("netbsd_amd64"),        &target_netbsd_amd64   },
+	{ str_lit("netbsd_arm64"),        &target_netbsd_arm64   },
+
+	{ str_lit("openbsd_amd64"),       &target_openbsd_amd64  },
 	{ str_lit("haiku_amd64"),         &target_haiku_amd64    },
 
 	{ str_lit("freestanding_wasm32"), &target_freestanding_wasm32 },
@@ -1916,7 +1925,11 @@ gb_internal void init_build_context(TargetMetrics *cross_target, Subtarget subta
 		#elif defined(GB_SYSTEM_OPENBSD)
 			metrics = &target_openbsd_amd64;
 		#elif defined(GB_SYSTEM_NETBSD)
-			metrics = &target_netbsd_amd64;
+			#if defined(GB_CPU_ARM)
+				metrics = &target_netbsd_arm64;
+			#else
+				metrics = &target_netbsd_amd64;
+			#endif
 		#elif defined(GB_SYSTEM_HAIKU)
 			metrics = &target_haiku_amd64;
 		#elif defined(GB_CPU_ARM)

+ 3 - 0
src/gb/gb.h

@@ -256,6 +256,7 @@ extern "C" {
 
 #if defined(GB_SYSTEM_NETBSD)
 	#include <stdio.h>
+	#include <lwp.h>
 	#define lseek64 lseek
 #endif
 
@@ -3027,6 +3028,8 @@ gb_inline u32 gb_thread_current_id(void) {
 	thread_id = find_thread(NULL);
 #elif defined(GB_SYSTEM_FREEBSD)
 	thread_id = pthread_getthreadid_np();
+#elif defined(GB_SYSTEM_NETBSD)
+	thread_id = (u32)_lwp_self();
 #else
 	#error Unsupported architecture for gb_thread_current_id()
 #endif

+ 2 - 0
src/threading.cpp

@@ -494,6 +494,8 @@ gb_internal u32 thread_current_id(void) {
 	thread_id = find_thread(NULL);
 #elif defined(GB_SYSTEM_FREEBSD)
 	thread_id = pthread_getthreadid_np();
+#elif defined(GB_SYSTEM_NETBSD)
+	thread_id = (u32)_lwp_self();
 #else
 	#error Unsupported architecture for thread_current_id()
 #endif

+ 4 - 0
tests/core/Makefile

@@ -25,6 +25,7 @@ all_bsd: download_test_assets \
          reflect_test \
          runtime_test \
          slice_test \
+         strconv_test \
          strings_test \
          thread_test \
          time_test
@@ -98,6 +99,9 @@ runtime_test:
 slice_test:
 	$(ODIN) test slice $(COMMON) -out:test_core_slice
 
+strconv_test:
+	$(ODIN) test strconv $(COMMON) -out:test_core_strconv
+
 strings_test:
 	$(ODIN) test strings $(COMMON) -out:test_core_strings
 

+ 5 - 0
tests/core/build.bat

@@ -103,6 +103,11 @@ echo Running core:slice tests
 echo ---
 %PATH_TO_ODIN% test slice %COMMON% -out:test_core_slice.exe || exit /b
 
+echo ---
+echo Running core:strconv tests
+echo ---
+%PATH_TO_ODIN% test strconv %COMMON% -out:test_core_strconv.exe || exit /b
+
 echo ---
 echo Running core:strings tests
 echo ---

+ 145 - 0
tests/core/strconv/test_core_strconv.odin

@@ -0,0 +1,145 @@
+package test_core_strconv
+
+import "core:math"
+import "core:strconv"
+import "core:testing"
+
+@(test)
+test_float :: proc(t: ^testing.T) {
+	n: int
+	f: f64
+	ok: bool
+
+	f, ok = strconv.parse_f64("1.2", &n)
+	testing.expect_value(t, f, 1.2)
+	testing.expect_value(t, n, 3)
+	testing.expect_value(t, ok, true)
+
+	f, ok = strconv.parse_f64("1.2a", &n)
+	testing.expect_value(t, f, 1.2)
+	testing.expect_value(t, n, 3)
+	testing.expect_value(t, ok, false)
+
+	f, ok = strconv.parse_f64("+", &n)
+	testing.expect_value(t, f, 0)
+	testing.expect_value(t, n, 0)
+	testing.expect_value(t, ok, false)
+
+	f, ok = strconv.parse_f64("-", &n)
+	testing.expect_value(t, f, 0)
+	testing.expect_value(t, n, 0)
+	testing.expect_value(t, ok, false)
+
+}
+
+@(test)
+test_nan :: proc(t: ^testing.T) {
+	n: int
+	f: f64
+	ok: bool
+
+	f, ok = strconv.parse_f64("nan", &n)
+	testing.expect_value(t, math.classify(f), math.Float_Class.NaN)
+	testing.expect_value(t, n, 3)
+	testing.expect_value(t, ok, true)
+
+	f, ok = strconv.parse_f64("nAN", &n)
+	testing.expect_value(t, math.classify(f), math.Float_Class.NaN)
+	testing.expect_value(t, n, 3)
+	testing.expect_value(t, ok, true)
+
+	f, ok = strconv.parse_f64("Nani", &n)
+	testing.expect_value(t, math.classify(f), math.Float_Class.NaN)
+	testing.expect_value(t, n, 3)
+	testing.expect_value(t, ok, false)
+}
+
+@(test)
+test_infinity :: proc(t: ^testing.T) {
+	pos_inf := math.inf_f64(+1)
+	neg_inf := math.inf_f64(-1)
+
+	n: int
+	s := "infinity"
+
+	for i in 0 ..< len(s) + 1 {
+		ss := s[:i]
+		f, ok := strconv.parse_f64(ss, &n)
+		if i >= 3 { // "inf" .. "infinity"
+			expected_n := 8 if i == 8 else 3
+			expected_ok := i == 3 || i == 8
+			testing.expect_value(t, f, pos_inf)
+			testing.expect_value(t, n, expected_n)
+			testing.expect_value(t, ok, expected_ok)
+			testing.expect_value(t, math.classify(f), math.Float_Class.Inf)
+		} else { // invalid substring
+			testing.expect_value(t, f, 0)
+			testing.expect_value(t, n, 0)
+			testing.expect_value(t, ok, false)
+			testing.expect_value(t, math.classify(f), math.Float_Class.Zero)
+		}
+	}
+	
+	s = "+infinity"
+	for i in 0 ..< len(s) + 1 {
+		ss := s[:i]
+		f, ok := strconv.parse_f64(ss, &n)
+		if i >= 4 { // "+inf" .. "+infinity"
+			expected_n := 9 if i == 9 else 4
+			expected_ok := i == 4 || i == 9
+			testing.expect_value(t, f, pos_inf)
+			testing.expect_value(t, n, expected_n)
+			testing.expect_value(t, ok, expected_ok)
+			testing.expect_value(t, math.classify(f), math.Float_Class.Inf)
+		} else { // invalid substring
+			testing.expect_value(t, f, 0)
+			testing.expect_value(t, n, 0)
+			testing.expect_value(t, ok, false)
+			testing.expect_value(t, math.classify(f), math.Float_Class.Zero)
+		}
+	}
+
+	s = "-infinity"
+	for i in 0 ..< len(s) + 1 {
+		ss := s[:i]
+		f, ok := strconv.parse_f64(ss, &n)
+		if i >= 4 { // "-inf" .. "infinity"
+			expected_n := 9 if i == 9 else 4
+			expected_ok := i == 4 || i == 9
+			testing.expect_value(t, f, neg_inf)
+			testing.expect_value(t, n, expected_n)
+			testing.expect_value(t, ok, expected_ok)
+			testing.expect_value(t, math.classify(f), math.Float_Class.Neg_Inf)
+		} else { // invalid substring
+			testing.expect_value(t, f, 0)
+			testing.expect_value(t, n, 0)
+			testing.expect_value(t, ok, false)
+			testing.expect_value(t, math.classify(f), math.Float_Class.Zero)
+		}
+	}
+
+	// Make sure odd casing works.
+	batch := [?]string {"INFiniTY", "iNfInItY", "InFiNiTy"}
+	for ss in batch {
+		f, ok := strconv.parse_f64(ss, &n)
+		testing.expect_value(t, f, pos_inf)
+		testing.expect_value(t, n, 8)
+		testing.expect_value(t, ok, true)
+		testing.expect_value(t, math.classify(f), math.Float_Class.Inf)
+	}
+
+	// Explicitly check how trailing characters are handled.
+	s = "infinityyyy"
+	f, ok := strconv.parse_f64(s, &n)
+	testing.expect_value(t, f, pos_inf)
+	testing.expect_value(t, n, 8)
+	testing.expect_value(t, ok, false)
+	testing.expect_value(t, math.classify(f), math.Float_Class.Inf)
+
+	s = "inflippity"
+	f, ok = strconv.parse_f64(s, &n)
+	testing.expect_value(t, f, pos_inf)
+	testing.expect_value(t, n, 3)
+	testing.expect_value(t, ok, false)
+	testing.expect_value(t, math.classify(f), math.Float_Class.Inf)
+}

+ 0 - 62
tests/issues/test_issue_2087.odin

@@ -1,62 +0,0 @@
-// Tests issue #2087 https://github.com/odin-lang/Odin/issues/2087
-package test_issues
-
-import "core:math"
-import "core:strconv"
-import "core:testing"
-
-@(test)
-test_parse_float :: proc(t: ^testing.T) {
-	{
-		f, ok := strconv.parse_f64("1.2")
-		testing.expect(t, ok && f == 1.2, "expected f64(1.2), fully consumed")
-		f, ok = strconv.parse_f64("1.2a")
-		testing.expect(t, !ok && f == 1.2, "expected f64(1.2), partially consumed")
-		f, ok = strconv.parse_f64("+")
-		testing.expect(t, !ok && f == 0.0, "expected f64(0.0), with ok=false")
-		f, ok = strconv.parse_f64("-")
-		testing.expect(t, !ok && f == 0.0, "expected f64(0.0), with ok=false")
-
-
-		f, ok = strconv.parse_f64("inf")
-		testing.expect(t, ok && math.classify(f) == math.Float_Class.Inf, "expected f64(+inf), fully consumed")
-		f, ok = strconv.parse_f64("+inf")
-		testing.expect(t, ok && math.classify(f) == math.Float_Class.Inf, "expected f64(+inf), fully consumed")
-		f, ok = strconv.parse_f64("-inf")
-		testing.expect(t, ok && math.classify(f) == math.Float_Class.Neg_Inf, "expected f64(-inf), fully consumed")
-		f, ok = strconv.parse_f64("inFinity")
-		testing.expect(t, !ok && math.classify(f) == math.Float_Class.Inf, "expected f64(+inf), partially consumed")
-		f, ok = strconv.parse_f64("+InFinity")
-		testing.expect(t, !ok && math.classify(f) == math.Float_Class.Inf, "expected f64(+inf), partially consumed")
-		f, ok = strconv.parse_f64("-InfiniTy")
-		testing.expect(t, !ok && math.classify(f) == math.Float_Class.Neg_Inf, "expected f64(-inf), partially consumed")
-		f, ok = strconv.parse_f64("nan")
-		testing.expect(t, ok && math.classify(f) == math.Float_Class.NaN, "expected f64(nan), fully consumed")
-		f, ok = strconv.parse_f64("nAN")
-		testing.expect(t, ok && math.classify(f) == math.Float_Class.NaN, "expected f64(nan), fully consumed")
-	}
-	{
-		f, ok := strconv.parse_f32("1.2")
-		testing.expect(t, ok && f == 1.2, "expected f32(1.2), fully consumed")
-
-		f, ok = strconv.parse_f32("1.2a")
-		testing.expect(t, !ok && f == 1.2, "expected f32(1.2), partially consumed")
-
-		f, ok = strconv.parse_f32("inf")
-		testing.expect(t, ok && math.classify(f) == math.Float_Class.Inf, "expected f32(+inf), fully consumed")
-		f, ok = strconv.parse_f32("+inf")
-		testing.expect(t, ok && math.classify(f) == math.Float_Class.Inf, "expected f32(+inf), fully consumed")
-		f, ok = strconv.parse_f32("-inf")
-		testing.expect(t, ok && math.classify(f) == math.Float_Class.Neg_Inf, "expected f32(-inf), fully consumed")
-		f, ok = strconv.parse_f32("inFinity")
-		testing.expect(t, !ok && math.classify(f) == math.Float_Class.Inf, "expected f32(+inf), partially consumed")
-		f, ok = strconv.parse_f32("+InFinity")
-		testing.expect(t, !ok && math.classify(f) == math.Float_Class.Inf, "expected f32(+inf), partially consumed")
-		f, ok = strconv.parse_f32("-InfiniTy")
-		testing.expect(t, !ok && math.classify(f) == math.Float_Class.Neg_Inf, "expected f32(-inf), partially consumed")
-		f, ok = strconv.parse_f32("nan")
-		testing.expect(t, ok && math.classify(f) == math.Float_Class.NaN, "expected f32(nan), fully consumed")
-		f, ok = strconv.parse_f32("nAN")
-		testing.expect(t, ok && math.classify(f) == math.Float_Class.NaN, "expected f32(nan), fully consumed")
-	}
-}