Skip to content

Commit 087211f

Browse files
committed
v2: lots of ssa and arm64 fixes for self hosting
1 parent 8ccb813 commit 087211f

28 files changed

Lines changed: 1032 additions & 183 deletions

‎cmd/v2/v2.v‎

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,6 @@ fn main() {
2323
eprintln('At least 1 .v file expected')
2424
exit(1)
2525
}
26-
$if debug {
27-
eprintln('v files: ${files}')
28-
}
2926

3027
mut b := builder.new_builder(prefs)
3128
b.build(files)

‎vlib/builtin/cfns_wrapper.c.v‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ pub fn vmemcpy(dest voidptr, const_src voidptr, n isize) voidptr {
2929
print_backtrace()
3030
}
3131
}
32-
if n == 0 {
32+
if n == 0 || u64(dest) <= 0xFFFF || u64(const_src) <= 0xFFFF {
3333
return dest
3434
}
3535
unsafe {
@@ -47,7 +47,7 @@ pub fn vmemmove(dest voidptr, const_src voidptr, n isize) voidptr {
4747
$if trace_vmemmove ? {
4848
C.fprintf(C.stderr, c'vmemmove dest: %p src: %p n: %6ld\n', dest, const_src, n)
4949
}
50-
if n == 0 {
50+
if n == 0 || u64(dest) <= 0xFFFF || u64(const_src) <= 0xFFFF {
5151
return dest
5252
}
5353
unsafe {
@@ -72,7 +72,7 @@ pub fn vmemcmp(const_s1 voidptr, const_s2 voidptr, n isize) int {
7272
$if trace_vmemcmp ? {
7373
C.fprintf(C.stderr, c'vmemcmp s1: %p s2: %p n: %6ld\n', const_s1, const_s2, n)
7474
}
75-
if n == 0 {
75+
if n == 0 || u64(const_s1) <= 0xFFFF || u64(const_s2) <= 0xFFFF {
7676
return 0
7777
}
7878
unsafe {
@@ -94,7 +94,7 @@ pub fn vmemset(s voidptr, c int, n isize) voidptr {
9494
print_backtrace()
9595
}
9696
}
97-
if n == 0 {
97+
if n == 0 || u64(s) <= 0xFFFF {
9898
return s
9999
}
100100
unsafe {

‎vlib/builtin/map.v‎

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -382,6 +382,10 @@ fn (mut m map) meta_greater(_index u32, _metas u32, kvi u32) {
382382
}
383383
index += 2
384384
meta += probe_inc
385+
// Grow metas if probing is approaching the buffer boundary
386+
if index + 2 >= m.even_index + 2 + m.extra_metas {
387+
m.ensure_extra_metas_grow()
388+
}
385389
}
386390
unsafe {
387391
m.metas[index] = meta
@@ -391,6 +395,19 @@ fn (mut m map) meta_greater(_index u32, _metas u32, kvi u32) {
391395
m.ensure_extra_metas(probe_count)
392396
}
393397

398+
fn (mut m map) ensure_extra_metas_grow() {
399+
size_of_u32 := sizeof(u32)
400+
old_mem_size := (m.even_index + 2 + m.extra_metas)
401+
m.extra_metas += extra_metas_inc
402+
mem_size := (m.even_index + 2 + m.extra_metas)
403+
unsafe {
404+
x := realloc_data(&u8(m.metas), int(size_of_u32 * old_mem_size), int(size_of_u32 * mem_size))
405+
m.metas = &u32(x)
406+
// Use explicit byte arithmetic: cast to &u8 to avoid pointer scaling issues
407+
vmemset(&u8(m.metas) + (mem_size - extra_metas_inc) * size_of_u32, 0, int(sizeof(u32) * extra_metas_inc))
408+
}
409+
}
410+
394411
@[inline]
395412
fn (mut m map) ensure_extra_metas(probe_count u32) {
396413
if (probe_count << 1) == m.extra_metas {
@@ -401,7 +418,8 @@ fn (mut m map) ensure_extra_metas(probe_count u32) {
401418
unsafe {
402419
x := realloc_data(&u8(m.metas), int(size_of_u32 * old_mem_size), int(size_of_u32 * mem_size))
403420
m.metas = &u32(x)
404-
vmemset(m.metas + mem_size - extra_metas_inc, 0, int(sizeof(u32) * extra_metas_inc))
421+
// Use explicit byte arithmetic: cast to &u8 to avoid pointer scaling issues
422+
vmemset(&u8(m.metas) + (mem_size - extra_metas_inc) * size_of_u32, 0, int(sizeof(u32) * extra_metas_inc))
405423
}
406424
// Should almost never happen
407425
if probe_count == 252 {
@@ -414,8 +432,9 @@ fn (mut m map) ensure_extra_metas(probe_count u32) {
414432
// not equivalent to the key of any other element already in the container.
415433
// If the key already exists, its value is changed to the value of the new element.
416434
fn (mut m map) set(key voidptr, value voidptr) {
417-
load_factor := f32(u32(m.len) << 1) / f32(m.even_index)
418-
if load_factor > max_load_factor {
435+
// Integer-based load factor check: equivalent to (2*len)/even_index > 0.8
436+
// which simplifies to 5*len > 2*even_index (avoids float ops broken in ARM64 backend)
437+
if u32(5) * u32(m.len) > u32(2) * m.even_index {
419438
m.expand()
420439
}
421440
mut index, mut meta := m.key_to_index(key)
@@ -505,8 +524,8 @@ fn (mut m map) cached_rehash(old_cap u32) {
505524
old_index := (i - old_probe_count) & (m.even_index >> 1)
506525
mut index := (old_index | (old_meta << m.shift)) & m.even_index
507526
mut meta := (old_meta & hash_mask) | probe_inc
508-
index, meta = m.meta_less(index, meta)
509527
kv_index := unsafe { old_metas[i + 1] }
528+
index, meta = m.meta_less(index, meta)
510529
m.meta_greater(index, meta, kv_index)
511530
}
512531
unsafe { free(old_metas) }

‎vlib/builtin/printing.c.v‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ module builtin
33
// eprintln prints a message with a line end, to stderr. Both stderr and stdout are flushed.
44
@[if !noeprintln ?]
55
pub fn eprintln(s string) {
6-
if s.str == 0 {
6+
if s.str == 0 || u64(s.str) <= 0xFFFF {
77
eprintln('eprintln(NIL)')
88
return
99
}
@@ -32,7 +32,7 @@ pub fn eprintln(s string) {
3232
// eprint prints a message to stderr. Both stderr and stdout are flushed.
3333
@[if !noeprintln ?]
3434
pub fn eprint(s string) {
35-
if s.str == 0 {
35+
if s.str == 0 || u64(s.str) <= 0xFFFF {
3636
eprint('eprint(NIL)')
3737
return
3838
}
@@ -129,7 +129,7 @@ pub fn print(s string) {
129129
// println prints a message with a line end, to stdout. Note that unlike `eprintln`, stdout is not automatically flushed.
130130
@[if !noprintln ?; manualfree]
131131
pub fn println(s string) {
132-
if s.str == 0 {
132+
if s.str == 0 || u64(s.str) <= 0xFFFF {
133133
println('println(NIL)')
134134
return
135135
}

‎vlib/builtin/string.v‎

Lines changed: 29 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -339,7 +339,7 @@ fn (a string) option_clone_static() ?string {
339339

340340
// clone returns a copy of the V string `a`.
341341
pub fn (a string) clone() string {
342-
if a.len <= 0 {
342+
if a.len <= 0 || u64(a.str) <= 0xFFFF {
343343
return ''
344344
}
345345
mut b := string{
@@ -783,8 +783,9 @@ pub fn (s string) parse_int(_base int, _bit_size int) !i64 {
783783
@[direct_array_access]
784784
fn (s string) == (a string) bool {
785785
if s.str == 0 {
786-
// should never happen
787-
panic('string.eq(): nil string')
786+
// Nil string: equal only to another nil/empty string.
787+
// This can happen with zero-initialized struct fields in the native backend.
788+
return a.str == 0 || a.len == 0
788789
}
789790
if s.len != a.len {
790791
return false
@@ -832,16 +833,20 @@ fn (s string) < (a string) bool {
832833

833834
@[direct_array_access]
834835
fn (s string) + (a string) string {
835-
new_len := a.len + s.len
836+
slen := if s.len > 0 && u64(s.str) > 0xFFFF { s.len } else { 0 }
837+
alen := if a.len > 0 && u64(a.str) > 0xFFFF { a.len } else { 0 }
838+
new_len := alen + slen
836839
mut res := string{
837840
str: unsafe { malloc_noscan(new_len + 1) }
838841
len: new_len
839842
}
840843
unsafe {
841-
vmemcpy(res.str, s.str, s.len)
842-
vmemcpy(res.str + s.len, a.str, a.len)
843-
}
844-
unsafe {
844+
if slen > 0 {
845+
vmemcpy(res.str, s.str, slen)
846+
}
847+
if alen > 0 {
848+
vmemcpy(res.str + slen, a.str, alen)
849+
}
845850
res.str[new_len] = 0 // V strings are not null terminated, but just in case
846851
}
847852
return res
@@ -850,17 +855,24 @@ fn (s string) + (a string) string {
850855
// for `s + s2 + s3`, an optimization (faster than string_plus(string_plus(s1, s2), s3))
851856
@[direct_array_access]
852857
fn (s string) plus_two(a string, b string) string {
853-
new_len := a.len + b.len + s.len
858+
slen := if s.len > 0 && u64(s.str) > 0xFFFF { s.len } else { 0 }
859+
alen := if a.len > 0 && u64(a.str) > 0xFFFF { a.len } else { 0 }
860+
blen := if b.len > 0 && u64(b.str) > 0xFFFF { b.len } else { 0 }
861+
new_len := alen + blen + slen
854862
mut res := string{
855863
str: unsafe { malloc_noscan(new_len + 1) }
856864
len: new_len
857865
}
858866
unsafe {
859-
vmemcpy(res.str, s.str, s.len)
860-
vmemcpy(res.str + s.len, a.str, a.len)
861-
vmemcpy(res.str + s.len + a.len, b.str, b.len)
862-
}
863-
unsafe {
867+
if slen > 0 {
868+
vmemcpy(res.str, s.str, slen)
869+
}
870+
if alen > 0 {
871+
vmemcpy(res.str + slen, a.str, alen)
872+
}
873+
if blen > 0 {
874+
vmemcpy(res.str + slen + alen, b.str, blen)
875+
}
864876
res.str[new_len] = 0 // V strings are not null terminated, but just in case
865877
}
866878
return res
@@ -1269,7 +1281,7 @@ pub fn (s string) substr_ni(_start int, _end int) string {
12691281
// It will return `-1` if the input string can't be found.
12701282
@[direct_array_access]
12711283
pub fn (s string) index_(p string) int {
1272-
if p.len > s.len || p.len == 0 {
1284+
if p.len > s.len || p.len == 0 || u64(s.str) <= 0xFFFF || u64(p.str) <= 0xFFFF {
12731285
return -1
12741286
}
12751287
if p.len > 2 {
@@ -1572,7 +1584,7 @@ pub fn (s string) contains_any_substr(substrs []string) bool {
15721584
// starts_with returns `true` if the string starts with `p`.
15731585
@[direct_array_access]
15741586
pub fn (s string) starts_with(p string) bool {
1575-
if p.len > s.len {
1587+
if p.len > s.len || u64(s.str) <= 0xFFFF || u64(p.str) <= 0xFFFF {
15761588
return false
15771589
} else if unsafe { vmemcmp(s.str, p.str, p.len) == 0 } {
15781590
return true
@@ -1583,7 +1595,7 @@ pub fn (s string) starts_with(p string) bool {
15831595
// ends_with returns `true` if the string ends with `p`.
15841596
@[direct_array_access]
15851597
pub fn (s string) ends_with(p string) bool {
1586-
if p.len > s.len {
1598+
if p.len > s.len || u64(s.str) <= 0xFFFF || u64(p.str) <= 0xFFFF {
15871599
return false
15881600
} else if unsafe { vmemcmp(s.str + s.len - p.len, p.str, p.len) == 0 } {
15891601
return true

‎vlib/v2/builder/parse.v‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ fn (mut b Builder) parse_files(files []string) []ast.File {
2525
ast_files << parsed_core_files
2626
} else {
2727
for module_path in core_cached_module_paths {
28-
module_files := get_v_files_from_dir(b.pref.get_vlib_module_path(module_path),
29-
b.pref.user_defines)
28+
vlib_path := b.pref.get_vlib_module_path(module_path)
29+
module_files := get_v_files_from_dir(vlib_path, b.pref.user_defines)
3030
parsed_module_files := parser_reused.parse_files(module_files, mut b.file_set)
3131
ast_files << parsed_module_files
3232
}

0 commit comments

Comments
 (0)