mirror of
https://github.com/odin-lang/Odin.git
synced 2026-01-20 11:30:34 +00:00
Merge branch 'master' into fix-2694
This commit is contained in:
@@ -2420,7 +2420,7 @@ buddy_allocator_proc :: proc(
|
||||
// on the old size to work.
|
||||
//
|
||||
// The overhead of this allocator is an extra max(alignment, size_of(Header)) bytes allocated for each allocation, these bytes are
|
||||
// used to store the size and original pointer.
|
||||
// used to store the size and alignment.
|
||||
Compat_Allocator :: struct {
|
||||
parent: Allocator,
|
||||
}
|
||||
@@ -2440,51 +2440,87 @@ compat_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
|
||||
size, alignment: int,
|
||||
old_memory: rawptr, old_size: int,
|
||||
location := #caller_location) -> (data: []byte, err: Allocator_Error) {
|
||||
size, old_size := size, old_size
|
||||
|
||||
Header :: struct {
|
||||
size: int,
|
||||
ptr: rawptr,
|
||||
size: int,
|
||||
alignment: int,
|
||||
}
|
||||
|
||||
@(no_sanitize_address)
|
||||
get_unpoisoned_header :: #force_inline proc(ptr: rawptr) -> Header {
|
||||
header := ([^]Header)(ptr)[-1]
|
||||
a := max(header.alignment, size_of(Header))
|
||||
sanitizer.address_unpoison(rawptr(uintptr(ptr)-uintptr(a)), a)
|
||||
return header
|
||||
}
|
||||
|
||||
rra := (^Compat_Allocator)(allocator_data)
|
||||
switch mode {
|
||||
case .Alloc, .Alloc_Non_Zeroed:
|
||||
a := max(alignment, size_of(Header))
|
||||
size += a
|
||||
assert(size >= 0, "overflow")
|
||||
a := max(alignment, size_of(Header))
|
||||
req_size := size + a
|
||||
assert(req_size >= 0, "overflow")
|
||||
|
||||
allocation := rra.parent.procedure(rra.parent.data, mode, size, alignment, old_memory, old_size, location) or_return
|
||||
allocation := rra.parent.procedure(rra.parent.data, mode, req_size, alignment, old_memory, old_size, location) or_return
|
||||
#no_bounds_check data = allocation[a:]
|
||||
|
||||
([^]Header)(raw_data(data))[-1] = {
|
||||
size = size,
|
||||
ptr = raw_data(allocation),
|
||||
size = size,
|
||||
alignment = alignment,
|
||||
}
|
||||
|
||||
sanitizer.address_poison(raw_data(allocation), a)
|
||||
return
|
||||
|
||||
case .Free:
|
||||
header := ([^]Header)(old_memory)[-1]
|
||||
return rra.parent.procedure(rra.parent.data, mode, size, alignment, header.ptr, header.size, location)
|
||||
header := get_unpoisoned_header(old_memory)
|
||||
a := max(header.alignment, size_of(Header))
|
||||
orig_ptr := rawptr(uintptr(old_memory)-uintptr(a))
|
||||
orig_size := header.size + a
|
||||
|
||||
return rra.parent.procedure(rra.parent.data, mode, orig_size, header.alignment, orig_ptr, orig_size, location)
|
||||
|
||||
case .Resize, .Resize_Non_Zeroed:
|
||||
header := ([^]Header)(old_memory)[-1]
|
||||
header := get_unpoisoned_header(old_memory)
|
||||
orig_a := max(header.alignment, size_of(Header))
|
||||
orig_ptr := rawptr(uintptr(old_memory)-uintptr(orig_a))
|
||||
orig_size := header.size + orig_a
|
||||
|
||||
a := max(alignment, size_of(header))
|
||||
size += a
|
||||
new_alignment := max(header.alignment, alignment)
|
||||
|
||||
a := max(new_alignment, size_of(header))
|
||||
req_size := size + a
|
||||
assert(size >= 0, "overflow")
|
||||
|
||||
allocation := rra.parent.procedure(rra.parent.data, mode, size, alignment, header.ptr, header.size, location) or_return
|
||||
allocation := rra.parent.procedure(rra.parent.data, mode, req_size, new_alignment, orig_ptr, orig_size, location) or_return
|
||||
#no_bounds_check data = allocation[a:]
|
||||
|
||||
([^]Header)(raw_data(data))[-1] = {
|
||||
size = size,
|
||||
ptr = raw_data(allocation),
|
||||
size = size,
|
||||
alignment = new_alignment,
|
||||
}
|
||||
|
||||
sanitizer.address_poison(raw_data(allocation), a)
|
||||
return
|
||||
|
||||
case .Free_All:
|
||||
return rra.parent.procedure(rra.parent.data, mode, size, alignment, old_memory, old_size, location)
|
||||
|
||||
case .Query_Info:
|
||||
info := (^Allocator_Query_Info)(old_memory)
|
||||
if info != nil && info.pointer != nil {
|
||||
header := get_unpoisoned_header(info.pointer)
|
||||
info.size = header.size
|
||||
info.alignment = header.alignment
|
||||
}
|
||||
return
|
||||
|
||||
case .Free_All, .Query_Info, .Query_Features:
|
||||
return rra.parent.procedure(rra.parent.data, mode, size, alignment, old_memory, old_size, location)
|
||||
case .Query_Features:
|
||||
data, err = rra.parent.procedure(rra.parent.data, mode, size, alignment, old_memory, old_size, location)
|
||||
if err != nil {
|
||||
set := (^Allocator_Mode_Set)(old_memory)
|
||||
set^ += {.Query_Info}
|
||||
}
|
||||
return
|
||||
|
||||
case: unreachable()
|
||||
}
|
||||
|
||||
@@ -49,8 +49,8 @@ init_dns_configuration :: proc() {
|
||||
/*
|
||||
Resolve %ENVIRONMENT% placeholders in their paths.
|
||||
*/
|
||||
dns_configuration.resolv_conf, _ = replace_environment_path(dns_configuration.resolv_conf)
|
||||
dns_configuration.hosts_file, _ = replace_environment_path(dns_configuration.hosts_file)
|
||||
dns_configuration.resolv_conf = os.replace_environment_placeholders(dns_configuration.resolv_conf)
|
||||
dns_configuration.hosts_file = os.replace_environment_placeholders(dns_configuration.hosts_file)
|
||||
}
|
||||
|
||||
@(fini, private)
|
||||
@@ -63,28 +63,6 @@ destroy_dns_configuration :: proc() {
|
||||
|
||||
dns_configuration := DEFAULT_DNS_CONFIGURATION
|
||||
|
||||
// Always allocates for consistency.
|
||||
replace_environment_path :: proc(path: string, allocator := context.allocator) -> (res: string, ok: bool) {
|
||||
// Nothing to replace. Return a clone of the original.
|
||||
if strings.count(path, "%") != 2 {
|
||||
return strings.clone(path, allocator), true
|
||||
}
|
||||
|
||||
left := strings.index(path, "%") + 1
|
||||
assert(left > 0 && left <= len(path)) // should be covered by there being two %
|
||||
|
||||
right := strings.index(path[left:], "%") + 1
|
||||
assert(right > 0 && right <= len(path)) // should be covered by there being two %
|
||||
|
||||
env_key := path[left: right]
|
||||
env_val := os.get_env(env_key, allocator)
|
||||
defer delete(env_val)
|
||||
|
||||
res, _ = strings.replace(path, path[left - 1: right + 1], env_val, 1, allocator)
|
||||
return res, true
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Resolves a hostname to exactly one IP4 and IP6 endpoint.
|
||||
It's then up to you which one you use.
|
||||
|
||||
@@ -4,6 +4,7 @@ import "base:intrinsics"
|
||||
import "base:runtime"
|
||||
import "core:io"
|
||||
import "core:strconv"
|
||||
import "core:strings"
|
||||
import "core:unicode/utf8"
|
||||
|
||||
|
||||
@@ -210,3 +211,55 @@ heap_free :: runtime.heap_free
|
||||
processor_core_count :: proc() -> int {
|
||||
return _processor_core_count()
|
||||
}
|
||||
|
||||
// Always allocates for consistency.
|
||||
replace_environment_placeholders :: proc(path: string, allocator := context.allocator) -> (res: string) {
|
||||
path := path
|
||||
|
||||
sb: strings.Builder
|
||||
strings.builder_init_none(&sb, allocator)
|
||||
for len(path) > 0 {
|
||||
switch path[0] {
|
||||
case '%': // Windows
|
||||
when ODIN_OS == .Windows {
|
||||
for r, i in path[1:] {
|
||||
if r == '%' {
|
||||
env_key := path[1:i+1]
|
||||
env_val := get_env(env_key, context.temp_allocator)
|
||||
strings.write_string(&sb, env_val)
|
||||
path = path[i+1:] // % is part of key, so skip 1 character extra
|
||||
}
|
||||
}
|
||||
} else {
|
||||
strings.write_rune(&sb, rune(path[0]))
|
||||
}
|
||||
|
||||
case '$': // Posix
|
||||
when ODIN_OS != .Windows {
|
||||
env_key := ""
|
||||
dollar_loop: for r, i in path[1:] {
|
||||
switch r {
|
||||
case 'A'..='Z', 'a'..='z', '0'..='9', '_': // Part of key ident
|
||||
case:
|
||||
env_key = path[1:i+1]
|
||||
break dollar_loop
|
||||
}
|
||||
}
|
||||
if len(env_key) > 0 {
|
||||
env_val := get_env(env_key, context.temp_allocator)
|
||||
strings.write_string(&sb, env_val)
|
||||
path = path[len(env_key):]
|
||||
}
|
||||
|
||||
} else {
|
||||
strings.write_rune(&sb, rune(path[0]))
|
||||
}
|
||||
|
||||
case:
|
||||
strings.write_rune(&sb, rune(path[0]))
|
||||
}
|
||||
|
||||
path = path[1:]
|
||||
}
|
||||
return strings.to_string(sb)
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package os2
|
||||
|
||||
import "base:runtime"
|
||||
import "core:strings"
|
||||
|
||||
// get_env retrieves the value of the environment variable named by the key
|
||||
// It returns the value, which will be empty if the variable is not present
|
||||
@@ -45,4 +46,55 @@ environ :: proc(allocator: runtime.Allocator) -> ([]string, Error) {
|
||||
return _environ(allocator)
|
||||
}
|
||||
|
||||
// Always allocates for consistency.
|
||||
replace_environment_placeholders :: proc(path: string, allocator: runtime.Allocator) -> (res: string) {
|
||||
path := path
|
||||
|
||||
sb: strings.Builder
|
||||
strings.builder_init_none(&sb, allocator)
|
||||
|
||||
for len(path) > 0 {
|
||||
switch path[0] {
|
||||
case '%': // Windows
|
||||
when ODIN_OS == .Windows {
|
||||
for r, i in path[1:] {
|
||||
if r == '%' {
|
||||
env_key := path[1:i+1]
|
||||
env_val := get_env(env_key, context.temp_allocator)
|
||||
strings.write_string(&sb, env_val)
|
||||
path = path[i+1:] // % is part of key, so skip 1 character extra
|
||||
}
|
||||
}
|
||||
} else {
|
||||
strings.write_rune(&sb, rune(path[0]))
|
||||
}
|
||||
|
||||
case '$': // Posix
|
||||
when ODIN_OS != .Windows {
|
||||
env_key := ""
|
||||
dollar_loop: for r, i in path[1:] {
|
||||
switch r {
|
||||
case 'A'..='Z', 'a'..='z', '0'..='9', '_': // Part of key ident
|
||||
case:
|
||||
env_key = path[1:i+1]
|
||||
break dollar_loop
|
||||
}
|
||||
}
|
||||
if len(env_key) > 0 {
|
||||
env_val := get_env(env_key, context.temp_allocator)
|
||||
strings.write_string(&sb, env_val)
|
||||
path = path[len(env_key):]
|
||||
}
|
||||
|
||||
} else {
|
||||
strings.write_rune(&sb, rune(path[0]))
|
||||
}
|
||||
|
||||
case:
|
||||
strings.write_rune(&sb, rune(path[0]))
|
||||
}
|
||||
|
||||
path = path[1:]
|
||||
}
|
||||
return strings.to_string(sb)
|
||||
}
|
||||
@@ -4,7 +4,6 @@ package os2
|
||||
import "base:runtime"
|
||||
import "core:encoding/ini"
|
||||
import "core:strings"
|
||||
import "core:sys/posix"
|
||||
|
||||
_user_cache_dir :: proc(allocator: runtime.Allocator) -> (dir: string, err: Error) {
|
||||
#partial switch ODIN_OS {
|
||||
@@ -169,14 +168,7 @@ _xdg_user_dirs_lookup :: proc(xdg_key: string, allocator: runtime.Allocator) ->
|
||||
|
||||
for k, v in ini.iterate(&it) {
|
||||
if k == xdg_key {
|
||||
we: posix.wordexp_t
|
||||
defer posix.wordfree(&we)
|
||||
|
||||
if _err := posix.wordexp(strings.clone_to_cstring(v, temp_allocator), &we, nil); _err != nil || we.we_wordc != 1 {
|
||||
return "", .Wordexp_Failed
|
||||
}
|
||||
|
||||
return strings.clone_from_cstring(we.we_wordv[0], allocator)
|
||||
return replace_environment_placeholders(v, allocator), nil
|
||||
}
|
||||
}
|
||||
return
|
||||
|
||||
@@ -252,4 +252,9 @@ current_thread_id :: proc "contextless" () -> int {
|
||||
|
||||
lookup_env :: proc(key: string, allocator := context.allocator) -> (value: string, found: bool) {
|
||||
return "", false
|
||||
}
|
||||
|
||||
get_env :: proc(key: string, allocator := context.allocator) -> string {
|
||||
value, _ := lookup_env(key, allocator)
|
||||
return value
|
||||
}
|
||||
@@ -239,3 +239,12 @@ exit :: proc "contextless" (code: int) -> ! {
|
||||
runtime._cleanup_runtime_contextless()
|
||||
wasi.proc_exit(wasi.exitcode_t(code))
|
||||
}
|
||||
|
||||
lookup_env :: proc(key: string, allocator := context.allocator) -> (value: string, found: bool) {
|
||||
return "", false
|
||||
}
|
||||
|
||||
get_env :: proc(key: string, allocator := context.allocator) -> string {
|
||||
value, _ := lookup_env(key, allocator)
|
||||
return value
|
||||
}
|
||||
@@ -34,6 +34,7 @@ init_platform :: proc() {
|
||||
} else {
|
||||
os_version.platform = .MacOS
|
||||
switch version.majorVersion {
|
||||
case 26: ws(&b, "macOS Tahoe")
|
||||
case 15: ws(&b, "macOS Sequoia")
|
||||
case 14: ws(&b, "macOS Sonoma")
|
||||
case 13: ws(&b, "macOS Ventura")
|
||||
|
||||
@@ -540,6 +540,7 @@ gb_internal void report_os_info() {
|
||||
}
|
||||
|
||||
switch (major) {
|
||||
case 26: gb_printf("macOS Tahoe"); break;
|
||||
case 15: gb_printf("macOS Sequoia"); break;
|
||||
case 14: gb_printf("macOS Sonoma"); break;
|
||||
case 13: gb_printf("macOS Ventura"); break;
|
||||
|
||||
@@ -1203,6 +1203,7 @@ gb_internal Type *type_deref(Type *t, bool allow_multi_pointer) {
|
||||
}
|
||||
|
||||
gb_internal bool is_type_named(Type *t) {
|
||||
if (t == nullptr) { return false; }
|
||||
if (t->kind == Type_Basic) {
|
||||
return true;
|
||||
}
|
||||
@@ -1212,6 +1213,7 @@ gb_internal bool is_type_named(Type *t) {
|
||||
gb_internal bool is_type_boolean(Type *t) {
|
||||
// t = core_type(t);
|
||||
t = base_type(t);
|
||||
if (t == nullptr) { return false; }
|
||||
if (t->kind == Type_Basic) {
|
||||
return (t->Basic.flags & BasicFlag_Boolean) != 0;
|
||||
}
|
||||
@@ -1220,6 +1222,7 @@ gb_internal bool is_type_boolean(Type *t) {
|
||||
gb_internal bool is_type_integer(Type *t) {
|
||||
// t = core_type(t);
|
||||
t = base_type(t);
|
||||
if (t == nullptr) { return false; }
|
||||
if (t->kind == Type_Basic) {
|
||||
return (t->Basic.flags & BasicFlag_Integer) != 0;
|
||||
}
|
||||
@@ -1241,15 +1244,15 @@ gb_internal bool is_type_integer_like(Type *t) {
|
||||
|
||||
gb_internal bool is_type_unsigned(Type *t) {
|
||||
t = base_type(t);
|
||||
// t = core_type(t);
|
||||
if (t == nullptr) { return false; }
|
||||
if (t->kind == Type_Basic) {
|
||||
return (t->Basic.flags & BasicFlag_Unsigned) != 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
gb_internal bool is_type_integer_128bit(Type *t) {
|
||||
// t = core_type(t);
|
||||
t = base_type(t);
|
||||
if (t == nullptr) { return false; }
|
||||
if (t->kind == Type_Basic) {
|
||||
return (t->Basic.flags & BasicFlag_Integer) != 0 && t->Basic.size == 16;
|
||||
}
|
||||
@@ -1258,6 +1261,7 @@ gb_internal bool is_type_integer_128bit(Type *t) {
|
||||
gb_internal bool is_type_rune(Type *t) {
|
||||
// t = core_type(t);
|
||||
t = base_type(t);
|
||||
if (t == nullptr) { return false; }
|
||||
if (t->kind == Type_Basic) {
|
||||
return (t->Basic.flags & BasicFlag_Rune) != 0;
|
||||
}
|
||||
@@ -1266,6 +1270,7 @@ gb_internal bool is_type_rune(Type *t) {
|
||||
gb_internal bool is_type_numeric(Type *t) {
|
||||
// t = core_type(t);
|
||||
t = base_type(t);
|
||||
if (t == nullptr) { return false; }
|
||||
if (t->kind == Type_Basic) {
|
||||
return (t->Basic.flags & BasicFlag_Numeric) != 0;
|
||||
} else if (t->kind == Type_Enum) {
|
||||
@@ -1279,6 +1284,7 @@ gb_internal bool is_type_numeric(Type *t) {
|
||||
}
|
||||
gb_internal bool is_type_string(Type *t) {
|
||||
t = base_type(t);
|
||||
if (t == nullptr) { return false; }
|
||||
if (t->kind == Type_Basic) {
|
||||
return (t->Basic.flags & BasicFlag_String) != 0;
|
||||
}
|
||||
@@ -1286,6 +1292,7 @@ gb_internal bool is_type_string(Type *t) {
|
||||
}
|
||||
gb_internal bool is_type_cstring(Type *t) {
|
||||
t = base_type(t);
|
||||
if (t == nullptr) { return false; }
|
||||
if (t->kind == Type_Basic) {
|
||||
return t->Basic.kind == Basic_cstring;
|
||||
}
|
||||
@@ -1293,9 +1300,7 @@ gb_internal bool is_type_cstring(Type *t) {
|
||||
}
|
||||
gb_internal bool is_type_typed(Type *t) {
|
||||
t = base_type(t);
|
||||
if (t == nullptr) {
|
||||
return false;
|
||||
}
|
||||
if (t == nullptr) { return false; }
|
||||
if (t->kind == Type_Basic) {
|
||||
return (t->Basic.flags & BasicFlag_Untyped) == 0;
|
||||
}
|
||||
@@ -1303,9 +1308,7 @@ gb_internal bool is_type_typed(Type *t) {
|
||||
}
|
||||
gb_internal bool is_type_untyped(Type *t) {
|
||||
t = base_type(t);
|
||||
if (t == nullptr) {
|
||||
return false;
|
||||
}
|
||||
if (t == nullptr) { return false; }
|
||||
if (t->kind == Type_Basic) {
|
||||
return (t->Basic.flags & BasicFlag_Untyped) != 0;
|
||||
}
|
||||
@@ -1313,6 +1316,7 @@ gb_internal bool is_type_untyped(Type *t) {
|
||||
}
|
||||
gb_internal bool is_type_ordered(Type *t) {
|
||||
t = core_type(t);
|
||||
if (t == nullptr) { return false; }
|
||||
switch (t->kind) {
|
||||
case Type_Basic:
|
||||
return (t->Basic.flags & BasicFlag_Ordered) != 0;
|
||||
@@ -1325,6 +1329,7 @@ gb_internal bool is_type_ordered(Type *t) {
|
||||
}
|
||||
gb_internal bool is_type_ordered_numeric(Type *t) {
|
||||
t = core_type(t);
|
||||
if (t == nullptr) { return false; }
|
||||
switch (t->kind) {
|
||||
case Type_Basic:
|
||||
return (t->Basic.flags & BasicFlag_OrderedNumeric) != 0;
|
||||
@@ -1333,6 +1338,7 @@ gb_internal bool is_type_ordered_numeric(Type *t) {
|
||||
}
|
||||
gb_internal bool is_type_constant_type(Type *t) {
|
||||
t = core_type(t);
|
||||
if (t == nullptr) { return false; }
|
||||
if (t->kind == Type_Basic) {
|
||||
return (t->Basic.flags & BasicFlag_ConstantType) != 0;
|
||||
}
|
||||
@@ -1346,6 +1352,7 @@ gb_internal bool is_type_constant_type(Type *t) {
|
||||
}
|
||||
gb_internal bool is_type_float(Type *t) {
|
||||
t = core_type(t);
|
||||
if (t == nullptr) { return false; }
|
||||
if (t->kind == Type_Basic) {
|
||||
return (t->Basic.flags & BasicFlag_Float) != 0;
|
||||
}
|
||||
@@ -1353,6 +1360,7 @@ gb_internal bool is_type_float(Type *t) {
|
||||
}
|
||||
gb_internal bool is_type_complex(Type *t) {
|
||||
t = core_type(t);
|
||||
if (t == nullptr) { return false; }
|
||||
if (t->kind == Type_Basic) {
|
||||
return (t->Basic.flags & BasicFlag_Complex) != 0;
|
||||
}
|
||||
@@ -1360,6 +1368,7 @@ gb_internal bool is_type_complex(Type *t) {
|
||||
}
|
||||
gb_internal bool is_type_quaternion(Type *t) {
|
||||
t = core_type(t);
|
||||
if (t == nullptr) { return false; }
|
||||
if (t->kind == Type_Basic) {
|
||||
return (t->Basic.flags & BasicFlag_Quaternion) != 0;
|
||||
}
|
||||
@@ -1367,6 +1376,7 @@ gb_internal bool is_type_quaternion(Type *t) {
|
||||
}
|
||||
gb_internal bool is_type_complex_or_quaternion(Type *t) {
|
||||
t = core_type(t);
|
||||
if (t == nullptr) { return false; }
|
||||
if (t->kind == Type_Basic) {
|
||||
return (t->Basic.flags & (BasicFlag_Complex|BasicFlag_Quaternion)) != 0;
|
||||
}
|
||||
@@ -1374,6 +1384,7 @@ gb_internal bool is_type_complex_or_quaternion(Type *t) {
|
||||
}
|
||||
gb_internal bool is_type_pointer(Type *t) {
|
||||
t = base_type(t);
|
||||
if (t == nullptr) { return false; }
|
||||
if (t->kind == Type_Basic) {
|
||||
return (t->Basic.flags & BasicFlag_Pointer) != 0;
|
||||
}
|
||||
@@ -1381,10 +1392,12 @@ gb_internal bool is_type_pointer(Type *t) {
|
||||
}
|
||||
gb_internal bool is_type_soa_pointer(Type *t) {
|
||||
t = base_type(t);
|
||||
if (t == nullptr) { return false; }
|
||||
return t->kind == Type_SoaPointer;
|
||||
}
|
||||
gb_internal bool is_type_multi_pointer(Type *t) {
|
||||
t = base_type(t);
|
||||
if (t == nullptr) { return false; }
|
||||
return t->kind == Type_MultiPointer;
|
||||
}
|
||||
gb_internal bool is_type_internally_pointer_like(Type *t) {
|
||||
@@ -1393,6 +1406,7 @@ gb_internal bool is_type_internally_pointer_like(Type *t) {
|
||||
|
||||
gb_internal bool is_type_tuple(Type *t) {
|
||||
t = base_type(t);
|
||||
if (t == nullptr) { return false; }
|
||||
return t->kind == Type_Tuple;
|
||||
}
|
||||
gb_internal bool is_type_uintptr(Type *t) {
|
||||
@@ -1415,14 +1429,17 @@ gb_internal bool is_type_u8(Type *t) {
|
||||
}
|
||||
gb_internal bool is_type_array(Type *t) {
|
||||
t = base_type(t);
|
||||
if (t == nullptr) { return false; }
|
||||
return t->kind == Type_Array;
|
||||
}
|
||||
gb_internal bool is_type_enumerated_array(Type *t) {
|
||||
t = base_type(t);
|
||||
if (t == nullptr) { return false; }
|
||||
return t->kind == Type_EnumeratedArray;
|
||||
}
|
||||
gb_internal bool is_type_matrix(Type *t) {
|
||||
t = base_type(t);
|
||||
if (t == nullptr) { return false; }
|
||||
return t->kind == Type_Matrix;
|
||||
}
|
||||
|
||||
@@ -1566,22 +1583,27 @@ gb_internal bool is_type_valid_for_matrix_elems(Type *t) {
|
||||
|
||||
gb_internal bool is_type_dynamic_array(Type *t) {
|
||||
t = base_type(t);
|
||||
if (t == nullptr) { return false; }
|
||||
return t->kind == Type_DynamicArray;
|
||||
}
|
||||
gb_internal bool is_type_slice(Type *t) {
|
||||
t = base_type(t);
|
||||
if (t == nullptr) { return false; }
|
||||
return t->kind == Type_Slice;
|
||||
}
|
||||
gb_internal bool is_type_proc(Type *t) {
|
||||
t = base_type(t);
|
||||
if (t == nullptr) { return false; }
|
||||
return t->kind == Type_Proc;
|
||||
}
|
||||
gb_internal bool is_type_asm_proc(Type *t) {
|
||||
t = base_type(t);
|
||||
if (t == nullptr) { return false; }
|
||||
return t->kind == Type_Proc && t->Proc.calling_convention == ProcCC_InlineAsm;
|
||||
}
|
||||
gb_internal bool is_type_simd_vector(Type *t) {
|
||||
t = base_type(t);
|
||||
if (t == nullptr) { return false; }
|
||||
return t->kind == Type_SimdVector;
|
||||
}
|
||||
|
||||
@@ -1621,11 +1643,13 @@ gb_internal Type *base_any_array_type(Type *t) {
|
||||
|
||||
gb_internal bool is_type_generic(Type *t) {
|
||||
t = base_type(t);
|
||||
if (t == nullptr) { return false; }
|
||||
return t->kind == Type_Generic;
|
||||
}
|
||||
|
||||
gb_internal bool is_type_u8_slice(Type *t) {
|
||||
t = base_type(t);
|
||||
if (t == nullptr) { return false; }
|
||||
if (t->kind == Type_Slice) {
|
||||
return is_type_u8(t->Slice.elem);
|
||||
}
|
||||
@@ -1633,6 +1657,7 @@ gb_internal bool is_type_u8_slice(Type *t) {
|
||||
}
|
||||
gb_internal bool is_type_u8_array(Type *t) {
|
||||
t = base_type(t);
|
||||
if (t == nullptr) { return false; }
|
||||
if (t->kind == Type_Array) {
|
||||
return is_type_u8(t->Array.elem);
|
||||
}
|
||||
@@ -1640,6 +1665,7 @@ gb_internal bool is_type_u8_array(Type *t) {
|
||||
}
|
||||
gb_internal bool is_type_u8_ptr(Type *t) {
|
||||
t = base_type(t);
|
||||
if (t == nullptr) { return false; }
|
||||
if (t->kind == Type_Pointer) {
|
||||
return is_type_u8(t->Slice.elem);
|
||||
}
|
||||
@@ -1647,6 +1673,7 @@ gb_internal bool is_type_u8_ptr(Type *t) {
|
||||
}
|
||||
gb_internal bool is_type_u8_multi_ptr(Type *t) {
|
||||
t = base_type(t);
|
||||
if (t == nullptr) { return false; }
|
||||
if (t->kind == Type_MultiPointer) {
|
||||
return is_type_u8(t->Slice.elem);
|
||||
}
|
||||
@@ -1654,6 +1681,7 @@ gb_internal bool is_type_u8_multi_ptr(Type *t) {
|
||||
}
|
||||
gb_internal bool is_type_rune_array(Type *t) {
|
||||
t = base_type(t);
|
||||
if (t == nullptr) { return false; }
|
||||
if (t->kind == Type_Array) {
|
||||
return is_type_rune(t->Array.elem);
|
||||
}
|
||||
@@ -1979,7 +2007,13 @@ gb_internal bool is_type_untyped_uninit(Type *t) {
|
||||
}
|
||||
|
||||
gb_internal bool is_type_empty_union(Type *t) {
|
||||
if (t == nullptr) {
|
||||
return false;
|
||||
}
|
||||
t = base_type(t);
|
||||
if (t == nullptr) {
|
||||
return false;
|
||||
}
|
||||
return t->kind == Type_Union && t->Union.variants.count == 0;
|
||||
}
|
||||
|
||||
@@ -2668,7 +2702,7 @@ gb_internal bool are_types_identical(Type *x, Type *y) {
|
||||
y = y->Named.base;
|
||||
}
|
||||
}
|
||||
if (x->kind != y->kind) {
|
||||
if (x == nullptr || y == nullptr || x->kind != y->kind) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user