diff --git a/core/container/small_array/small_array.odin b/core/container/small_array/small_array.odin index 4dd16f30c..b8210d1b0 100644 --- a/core/container/small_array/small_array.odin +++ b/core/container/small_array/small_array.odin @@ -8,40 +8,40 @@ Small_Array :: struct($N: int, $T: typeid) where N >= 0 { } -len :: proc(a: $A/Small_Array) -> int { +len :: proc "contextless" (a: $A/Small_Array) -> int { return a.len } -cap :: proc(a: $A/Small_Array) -> int { +cap :: proc "contextless" (a: $A/Small_Array) -> int { return builtin.len(a.data) } -space :: proc(a: $A/Small_Array) -> int { +space :: proc "contextless" (a: $A/Small_Array) -> int { return builtin.len(a.data) - a.len } -slice :: proc(a: ^$A/Small_Array($N, $T)) -> []T { +slice :: proc "contextless" (a: ^$A/Small_Array($N, $T)) -> []T { return a.data[:a.len] } -get :: proc(a: $A/Small_Array($N, $T), index: int) -> T { +get :: proc "contextless" (a: $A/Small_Array($N, $T), index: int) -> T { return a.data[index] } -get_ptr :: proc(a: ^$A/Small_Array($N, $T), index: int) -> ^T { +get_ptr :: proc "contextless" (a: ^$A/Small_Array($N, $T), index: int) -> ^T { return &a.data[index] } -set :: proc(a: ^$A/Small_Array($N, $T), index: int, item: T) { +set :: proc "contextless" (a: ^$A/Small_Array($N, $T), index: int, item: T) { a.data[index] = item } -resize :: proc(a: ^$A/Small_Array, length: int) { +resize :: proc "contextless" (a: ^$A/Small_Array, length: int) { a.len = min(length, builtin.len(a.data)) } -push_back :: proc(a: ^$A/Small_Array($N, $T), item: T) -> bool { +push_back :: proc "contextless" (a: ^$A/Small_Array($N, $T), item: T) -> bool { if a.len < cap(a^) { a.data[a.len] = item a.len += 1 @@ -50,7 +50,7 @@ push_back :: proc(a: ^$A/Small_Array($N, $T), item: T) -> bool { return false } -push_front :: proc(a: ^$A/Small_Array($N, $T), item: T) -> bool { +push_front :: proc "contextless" (a: ^$A/Small_Array($N, $T), item: T) -> bool { if a.len < cap(a^) { a.len += 1 data := slice(a) @@ -61,14 +61,14 @@ push_front :: proc(a: ^$A/Small_Array($N, $T), item: T) -> bool { return false } -pop_back :: proc(a: ^$A/Small_Array($N, $T), loc := #caller_location) -> T { +pop_back :: proc "odin" (a: ^$A/Small_Array($N, $T), loc := #caller_location) -> T { assert(condition=(N > 0 && a.len > 0), loc=loc) item := a.data[a.len-1] a.len -= 1 return item } -pop_front :: proc(a: ^$A/Small_Array($N, $T), loc := #caller_location) -> T { +pop_front :: proc "odin" (a: ^$A/Small_Array($N, $T), loc := #caller_location) -> T { assert(condition=(N > 0 && a.len > 0), loc=loc) item := a.data[0] s := slice(a) @@ -77,7 +77,7 @@ pop_front :: proc(a: ^$A/Small_Array($N, $T), loc := #caller_location) -> T { return item } -pop_back_safe :: proc(a: ^$A/Small_Array($N, $T)) -> (item: T, ok: bool) { +pop_back_safe :: proc "contextless" (a: ^$A/Small_Array($N, $T)) -> (item: T, ok: bool) { if N > 0 && a.len > 0 { item = a.data[a.len-1] a.len -= 1 @@ -86,7 +86,7 @@ pop_back_safe :: proc(a: ^$A/Small_Array($N, $T)) -> (item: T, ok: bool) { return } -pop_front_safe :: proc(a: ^$A/Small_Array($N, $T)) -> (item: T, ok: bool) { +pop_front_safe :: proc "contextless" (a: ^$A/Small_Array($N, $T)) -> (item: T, ok: bool) { if N > 0 && a.len > 0 { item = a.data[0] s := slice(a) @@ -97,16 +97,16 @@ pop_front_safe :: proc(a: ^$A/Small_Array($N, $T)) -> (item: T, ok: bool) { return } -consume :: proc(a: ^$A/Small_Array($N, $T), count: int, loc := #caller_location) { +consume :: proc "odin" (a: ^$A/Small_Array($N, $T), count: int, loc := #caller_location) { assert(condition=a.len >= count, loc=loc) a.len -= count } -clear :: proc(a: ^$A/Small_Array($N, $T)) { +clear :: proc "contextless" (a: ^$A/Small_Array($N, $T)) { resize(a, 0) } -push_back_elems :: proc(a: ^$A/Small_Array($N, $T), items: ..T) { +push_back_elems :: proc "contextless" (a: ^$A/Small_Array($N, $T), items: ..T) { n := copy(a.data[a.len:], items[:]) a.len += n } diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp index 890f7a39b..031ef1218 100644 --- a/src/check_builtin.cpp +++ b/src/check_builtin.cpp @@ -4182,6 +4182,13 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 return false; } + Type *elem = type_deref(ptr0.type); + if (type_size_of(elem) == 0) { + gbString str = type_to_string(ptr0.type); + error(ptr0.expr, "Expected a pointer to a non-zero sized element for '%.*s', got %s", LIT(builtin_name), str); + gb_string_free(str); + return false + } } break; diff --git a/src/llvm_backend_proc.cpp b/src/llvm_backend_proc.cpp index 4b0323855..eaff6edc0 100644 --- a/src/llvm_backend_proc.cpp +++ b/src/llvm_backend_proc.cpp @@ -2125,17 +2125,17 @@ lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValue const &tv, } case BuiltinProc_ptr_sub: { - lbValue ptr0 = lb_build_expr(p, ce->args[0]); - lbValue ptr1 = lb_build_expr(p, ce->args[1]); + Type *elem0 = type_deref(type_of_expr(ce->args[0])); + Type *elem1 = type_deref(type_of_expr(ce->args[1])); + GB_ASSERT(are_types_identical(elem0, elem1)); + Type *elem = elem0; - LLVMTypeRef type_int = lb_type(p->module, t_int); - LLVMValueRef diff = LLVMBuildPtrDiff2(p->builder, lb_type(p->module, ptr0.type), ptr0.value, ptr1.value, ""); - diff = LLVMBuildIntCast2(p->builder, diff, type_int, /*signed*/true, ""); + lbValue ptr0 = lb_emit_conv(p, lb_build_expr(p, ce->args[0]), t_uintptr); + lbValue ptr1 = lb_emit_conv(p, lb_build_expr(p, ce->args[1]), t_uintptr); - lbValue res = {}; - res.type = t_int; - res.value = diff; - return res; + lbValue diff = lb_emit_arith(p, Token_Sub, ptr0, ptr1, t_uintptr); + diff = lb_emit_conv(p, diff, t_int); + return lb_emit_arith(p, Token_Quo, diff, lb_const_int(p->module, t_int, type_size_of(elem)), t_int); } diff --git a/src/types.cpp b/src/types.cpp index 47007491d..b7bfe1b0f 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -1260,6 +1260,9 @@ bool is_type_typed(Type *t) { } bool is_type_untyped(Type *t) { t = base_type(t); + if (t == nullptr) { + return false; + } if (t->kind == Type_Basic) { return (t->Basic.flags & BasicFlag_Untyped) != 0; }