diff --git a/core/runtime/core.odin b/core/runtime/core.odin index 9ad5d3d8a..7ba98ae30 100644 --- a/core/runtime/core.odin +++ b/core/runtime/core.odin @@ -237,7 +237,22 @@ global_scratch_allocator_data: mem.Scratch_Allocator; +Raw_Slice :: struct { + data: rawptr, + len: int, +} +Raw_Dynamic_Array :: struct { + data: rawptr, + len: int, + cap: int, + allocator: mem.Allocator, +} + +Raw_Map :: struct { + hashes: []int, + entries: Raw_Dynamic_Array, +} INITIAL_MAP_CAP :: 16; @@ -261,7 +276,7 @@ Map_Entry_Header :: struct { } Map_Header :: struct { - m: ^mem.Raw_Map, + m: ^Raw_Map, is_key_string: bool, entry_size: int, @@ -394,7 +409,7 @@ default_assertion_failure_proc :: proc(prefix, message: string, loc: Source_Code @builtin copy :: proc "contextless" (dst, src: $T/[]$E) -> int { n := max(0, min(len(dst), len(src))); - if n > 0 do mem.copy(&dst[0], &src[0], n*size_of(E)); + if n > 0 do mem_copy(&dst[0], &src[0], n*size_of(E)); return n; } @@ -405,7 +420,7 @@ pop :: proc "contextless" (array: ^$T/[dynamic]$E) -> E { if array == nil do return E{}; assert(len(array) > 0); res := array[len(array)-1]; - (^mem.Raw_Dynamic_Array)(array).len -= 1; + (^Raw_Dynamic_Array)(array).len -= 1; return res; } @@ -469,14 +484,11 @@ make :: proc{ mem.make_map, }; - - - @builtin clear_map :: inline proc "contextless" (m: ^$T/map[$K]$V) { if m == nil do return; - raw_map := (^mem.Raw_Map)(m); - entries := (^mem.Raw_Dynamic_Array)(&raw_map.entries); + raw_map := (^Raw_Map)(m); + entries := (^Raw_Dynamic_Array)(&raw_map.entries); entries.len = 0; for _, i in raw_map.hashes { raw_map.hashes[i] = -1; @@ -507,11 +519,11 @@ append_elem :: proc(array: ^$T/[dynamic]$E, arg: E, loc := #caller_location) { } arg_len = min(cap(array)-len(array), arg_len); if arg_len > 0 { - a := (^mem.Raw_Dynamic_Array)(array); + a := (^Raw_Dynamic_Array)(array); data := (^E)(a.data); assert(data != nil); val := arg; - mem.copy(mem.ptr_offset(data, a.len), &val, size_of(E)); + mem_copy(mem.ptr_offset(data, a.len), &val, size_of(E)); a.len += arg_len; } } @@ -529,10 +541,10 @@ append_elems :: proc(array: ^$T/[dynamic]$E, args: ..E, loc := #caller_location) } arg_len = min(cap(array)-len(array), arg_len); if arg_len > 0 { - a := (^mem.Raw_Dynamic_Array)(array); + a := (^Raw_Dynamic_Array)(array); data := (^E)(a.data); assert(data != nil); - mem.copy(mem.ptr_offset(data, a.len), &args[0], size_of(E) * arg_len); + mem_copy(mem.ptr_offset(data, a.len), &args[0], size_of(E) * arg_len); a.len += arg_len; } } @@ -549,13 +561,13 @@ append_string :: proc(array: ^$T/[dynamic]$E/u8, args: ..string, loc := #caller_ @builtin clear_dynamic_array :: inline proc "contextless" (array: ^$T/[dynamic]$E) { - if array != nil do (^mem.Raw_Dynamic_Array)(array).len = 0; + if array != nil do (^Raw_Dynamic_Array)(array).len = 0; } @builtin reserve_dynamic_array :: proc(array: ^$T/[dynamic]$E, capacity: int, loc := #caller_location) -> bool { if array == nil do return false; - a := (^mem.Raw_Dynamic_Array)(array); + a := (^Raw_Dynamic_Array)(array); if capacity <= a.cap do return true; @@ -582,7 +594,7 @@ reserve_dynamic_array :: proc(array: ^$T/[dynamic]$E, capacity: int, loc := #cal @builtin resize_dynamic_array :: proc(array: ^$T/[dynamic]$E, length: int, loc := #caller_location) -> bool { if array == nil do return false; - a := (^mem.Raw_Dynamic_Array)(array); + a := (^Raw_Dynamic_Array)(array); if length <= a.cap { a.len = max(length, 0); @@ -722,7 +734,7 @@ unreachable :: proc(message := "", loc := #caller_location) -> ! { __dynamic_array_make :: proc(array_: rawptr, elem_size, elem_align: int, len, cap: int, loc := #caller_location) { - array := (^mem.Raw_Dynamic_Array)(array_); + array := (^Raw_Dynamic_Array)(array_); array.allocator = context.allocator; assert(array.allocator.procedure != nil); @@ -733,7 +745,7 @@ __dynamic_array_make :: proc(array_: rawptr, elem_size, elem_align: int, len, ca } __dynamic_array_reserve :: proc(array_: rawptr, elem_size, elem_align: int, cap: int, loc := #caller_location) -> bool { - array := (^mem.Raw_Dynamic_Array)(array_); + array := (^Raw_Dynamic_Array)(array_); if cap <= array.cap do return true; @@ -755,7 +767,7 @@ __dynamic_array_reserve :: proc(array_: rawptr, elem_size, elem_align: int, cap: } __dynamic_array_resize :: proc(array_: rawptr, elem_size, elem_align: int, len: int, loc := #caller_location) -> bool { - array := (^mem.Raw_Dynamic_Array)(array_); + array := (^Raw_Dynamic_Array)(array_); ok := __dynamic_array_reserve(array_, elem_size, elem_align, len, loc); if ok do array.len = len; @@ -765,7 +777,7 @@ __dynamic_array_resize :: proc(array_: rawptr, elem_size, elem_align: int, len: __dynamic_array_append :: proc(array_: rawptr, elem_size, elem_align: int, items: rawptr, item_count: int, loc := #caller_location) -> int { - array := (^mem.Raw_Dynamic_Array)(array_); + array := (^Raw_Dynamic_Array)(array_); if items == nil do return 0; if item_count <= 0 do return 0; @@ -782,13 +794,13 @@ __dynamic_array_append :: proc(array_: rawptr, elem_size, elem_align: int, assert(array.data != nil); data := uintptr(array.data) + uintptr(elem_size*array.len); - mem.copy(rawptr(data), items, elem_size * item_count); + mem_copy(rawptr(data), items, elem_size * item_count); array.len += item_count; return array.len; } __dynamic_array_append_nothing :: proc(array_: rawptr, elem_size, elem_align: int, loc := #caller_location) -> int { - array := (^mem.Raw_Dynamic_Array)(array_); + array := (^Raw_Dynamic_Array)(array_); ok := true; if array.cap <= array.len+1 { @@ -811,7 +823,7 @@ __dynamic_array_append_nothing :: proc(array_: rawptr, elem_size, elem_align: in // Map __get_map_header :: proc "contextless" (m: ^$T/map[$K]$V) -> Map_Header { - header := Map_Header{m = (^mem.Raw_Map)(m)}; + header := Map_Header{m = (^Raw_Map)(m)}; Entry :: struct { key: Map_Key, next: int, @@ -885,7 +897,7 @@ source_code_location_hash :: proc(s: Source_Code_Location) -> u64 { __slice_resize :: proc(array_: ^$T/[]$E, new_count: int, allocator: mem.Allocator, loc := #caller_location) -> bool { - array := (^mem.Raw_Slice)(array_); + array := (^Raw_Slice)(array_); if new_count < array.len do return true; @@ -911,7 +923,7 @@ __dynamic_map_reserve :: proc(using header: Map_Header, cap: int, loc := #caller } __dynamic_map_rehash :: proc(using header: Map_Header, new_count: int, loc := #caller_location) #no_bounds_check { new_header: Map_Header = header; - nm := mem.Raw_Map{}; + nm := Raw_Map{}; nm.entries.allocator = m.entries.allocator; new_header.m = &nm; @@ -943,7 +955,7 @@ __dynamic_map_rehash :: proc(using header: Map_Header, new_count: int, loc := #c e := __dynamic_map_get_entry(new_header, j); e.next = fr.entry_index; ndata := uintptr(e); - mem.copy(rawptr(ndata+value_offset), rawptr(data+value_offset), value_size); + mem_copy(rawptr(ndata+value_offset), rawptr(data+value_offset), value_size); if __dynamic_map_full(new_header) do __dynamic_map_grow(new_header, loc); } @@ -986,7 +998,7 @@ __dynamic_map_set :: proc(h: Map_Header, key: Map_Key, value: rawptr, loc := #ca e := __dynamic_map_get_entry(h, index); e.key = key; val := (^byte)(uintptr(e) + h.value_offset); - mem.copy(val, value, h.value_size); + mem_copy(val, value, h.value_size); } if __dynamic_map_full(h) { @@ -1065,7 +1077,7 @@ __dynamic_map_erase :: proc(using h: Map_Header, fr: Map_Find_Result) #no_bounds } else { old := __dynamic_map_get_entry(h, fr.entry_index); end := __dynamic_map_get_entry(h, m.entries.len-1); - mem.copy(old, end, entry_size); + mem_copy(old, end, entry_size); if last := __dynamic_map_find(h, old.key); last.entry_prev >= 0 { last_entry := __dynamic_map_get_entry(h, last.entry_prev); diff --git a/core/runtime/internal.odin b/core/runtime/internal.odin index a5099944b..630942805 100644 --- a/core/runtime/internal.odin +++ b/core/runtime/internal.odin @@ -1,9 +1,22 @@ package runtime -import "core:mem" import "core:os" -import "core:unicode/utf8" +mem_copy :: proc "contextless" (dst, src: rawptr, len: int) -> rawptr { + if src == nil do return dst; + // NOTE(bill): This _must_ be implemented like C's memmove + foreign _ { + when size_of(rawptr) == 8 { + @(link_name="llvm.memmove.p0i8.p0i8.i64") + llvm_memmove :: proc(dst, src: rawptr, len: int, align: i32, is_volatile: bool) ---; + } else { + @(link_name="llvm.memmove.p0i8.p0i8.i32") + llvm_memmove :: proc(dst, src: rawptr, len: int, align: i32, is_volatile: bool) ---; + } + } + llvm_memmove(dst, src, len, 1, false); + return dst; +} print_u64 :: proc(fd: os.Handle, x: u64) { digits := "0123456789"; @@ -336,17 +349,22 @@ string_ge :: inline proc "contextless" (a, b: string) -> bool { return string_cm cstring_len :: proc "contextless" (s: cstring) -> int { n := 0; - for p := (^byte)(s); p != nil && p^ != 0; p = mem.ptr_offset(p, 1) { - n += 1; + p := uintptr((^byte)(s)); + for p != 0 && (^byte)(p)^ != 0 { + p += 1; } return n; } cstring_to_string :: proc "contextless" (s: cstring) -> string { + Raw_String :: struct { + data: ^byte, + len: int, + }; if s == nil do return ""; ptr := (^byte)(s); n := cstring_len(s); - return transmute(string)mem.Raw_String{ptr, n}; + return transmute(string)Raw_String{ptr, n}; } @@ -435,8 +453,84 @@ type_assertion_check :: proc "contextless" (ok: bool, file: string, line, column handle_error(file, line, column, from, to); } + string_decode_rune :: inline proc "contextless" (s: string) -> (rune, int) { - return utf8.decode_rune_in_string(s); + // NOTE(bill): Duplicated here to remove dependency on package unicode/utf8 + + @static accept_sizes := [256]u8{ + 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, // 0x00-0x0f + 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, // 0x10-0x1f + 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, // 0x20-0x2f + 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, // 0x30-0x3f + 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, // 0x40-0x4f + 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, // 0x50-0x5f + 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, // 0x60-0x6f + 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, // 0x70-0x7f + + 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, // 0x80-0x8f + 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, // 0x90-0x9f + 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, // 0xa0-0xaf + 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, // 0xb0-0xbf + 0xf1, 0xf1, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, // 0xc0-0xcf + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, // 0xd0-0xdf + 0x13, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x23, 0x03, 0x03, // 0xe0-0xef + 0x34, 0x04, 0x04, 0x04, 0x44, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, // 0xf0-0xff + }; + Accept_Range :: struct {lo, hi: u8}; + + @static accept_ranges := [5]Accept_Range{ + {0x80, 0xbf}, + {0xa0, 0xbf}, + {0x80, 0x9f}, + {0x90, 0xbf}, + {0x80, 0x8f}, + }; + + MASKX :: 0b0011_1111; + MASK2 :: 0b0001_1111; + MASK3 :: 0b0000_1111; + MASK4 :: 0b0000_0111; + + LOCB :: 0b1000_0000; + HICB :: 0b1011_1111; + + + RUNE_ERROR :: '\ufffd'; + + n := len(s); + if n < 1 { + return RUNE_ERROR, 0; + } + s0 := s[0]; + x := accept_sizes[s0]; + if x >= 0xF0 { + mask := rune(x) << 31 >> 31; // NOTE(bill): Create 0x0000 or 0xffff. + return rune(s[0])&~mask | RUNE_ERROR&mask, 1; + } + sz := x & 7; + accept := accept_ranges[x>>4]; + if n < int(sz) { + return RUNE_ERROR, 1; + } + b1 := s[1]; + if b1 < accept.lo || accept.hi < b1 { + return RUNE_ERROR, 1; + } + if sz == 2 { + return rune(s0&MASK2)<<6 | rune(b1&MASKX), 2; + } + b2 := s[2]; + if b2 < LOCB || HICB < b2 { + return RUNE_ERROR, 1; + } + if sz == 3 { + return rune(s0&MASK3)<<12 | rune(b1&MASKX)<<6 | rune(b2&MASKX), 3; + } + b3 := s[3]; + if b3 < LOCB || HICB < b3 { + return RUNE_ERROR, 1; + } + return rune(s0&MASK4)<<18 | rune(b1&MASKX)<<12 | rune(b2&MASKX)<<6 | rune(b3&MASKX), 4; } bounds_check_error_loc :: inline proc "contextless" (using loc := #caller_location, index, count: int) { diff --git a/src/checker.cpp b/src/checker.cpp index 8ce9d8ec2..e7b347f1a 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -1628,6 +1628,7 @@ void generate_minimum_dependency_set(Checker *c, Entity *start) { str_lit("mul_quaternion256"), str_lit("quo_quaternion128"), str_lit("quo_quaternion256"), + str_lit("cstring_to_string"), str_lit("umodti3"), str_lit("udivti3"),