diff --git a/examples/demo/demo.odin b/examples/demo/demo.odin index 4f425b698..e6882fbcc 100644 --- a/examples/demo/demo.odin +++ b/examples/demo/demo.odin @@ -1938,10 +1938,29 @@ dummy_procedure :: proc() { explicit_context_definition :: proc "c" () { // Try commenting the following statement out below - context = runtime.default_context(); + context = runtime.default_context(); + + fmt.println("\n#explicit context definition"); dummy_procedure(); } +relative_data_types :: proc() { + fmt.println("\n#relative data types"); + + x: int = 123; + ptr: #relative(i16) ^int; + ptr = &x; + fmt.println(ptr^); + + arr := [3]int{1, 2, 3}; + s := arr[:]; + rel_slice: #relative(i16) []int; + rel_slice = s; + fmt.println(rel_slice); + fmt.println(rel_slice[:]); + fmt.println(rel_slice[1]); +} + main :: proc() { when true { the_basics(); @@ -1973,5 +1992,6 @@ main :: proc() { constant_literal_expressions(); union_maybe(); explicit_context_definition(); + relative_data_types(); } } diff --git a/src/check_expr.cpp b/src/check_expr.cpp index ab4755bd3..06c7e7f36 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -7563,6 +7563,17 @@ bool check_set_index_data(Operand *o, Type *t, bool indirection, i64 *max_count, } return true; + case Type_RelativeSlice: + { + Type *slice_type = base_type(t->RelativeSlice.slice_type); + GB_ASSERT(slice_type->kind == Type_Slice); + o->type = slice_type->Slice.elem; + if (o->mode != Addressing_Constant) { + o->mode = Addressing_Variable; + } + } + return true; + case Type_DynamicArray: o->type = t->DynamicArray.elem; if (o->mode != Addressing_Constant) { @@ -9250,6 +9261,8 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type // Okay } else if (is_type_string(t)) { // Okay + } else if (is_type_relative_slice(t)) { + // Okay } else { valid = false; } @@ -9392,6 +9405,19 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type } } break; + + case Type_RelativeSlice: + valid = true; + o->type = t->RelativeSlice.slice_type; + if (o->mode != Addressing_Variable) { + gbString str = expr_to_string(node); + error(node, "Cannot relative slice '%s', value is not addressable", str); + gb_string_free(str); + o->mode = Addressing_Invalid; + o->expr = node; + return kind; + } + break; } if (!valid) { diff --git a/src/ir.cpp b/src/ir.cpp index ee4c03fc5..b45f6bf85 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -494,6 +494,7 @@ enum irAddrKind { irAddr_Context, irAddr_SoaVariable, irAddr_RelativePointer, + irAddr_RelativeSlice, }; struct irAddr { @@ -525,6 +526,9 @@ irAddr ir_addr(irValue *addr) { if (addr != nullptr && is_type_relative_pointer(type_deref(ir_type(addr)))) { GB_ASSERT(is_type_pointer(ir_type(addr))); v.kind = irAddr_RelativePointer; + } else if (addr != nullptr && is_type_relative_slice(type_deref(ir_type(addr)))) { + GB_ASSERT(is_type_pointer(ir_type(addr))); + v.kind = irAddr_RelativeSlice; } return v; } @@ -912,7 +916,9 @@ irValue *ir_emit_bitcast(irProcedure *proc, irValue *data, Type *type); irValue *ir_emit_byte_swap(irProcedure *proc, irValue *value, Type *t); irValue *ir_find_or_add_entity_string(irModule *m, String str); irValue *ir_find_or_add_entity_string_byte_slice(irModule *m, String str); - +irValue *ir_slice_elem(irProcedure *proc, irValue *slice); +irValue *ir_slice_len(irProcedure *proc, irValue *slice); +void ir_fill_slice(irProcedure *proc, irValue *slice_ptr, irValue *data, irValue *len); irValue *ir_alloc_value(irValueKind kind) { @@ -3655,6 +3661,34 @@ void ir_addr_store(irProcedure *proc, irAddr const &addr, irValue *value) { ir_emit_store(proc, offset_ptr, offset); return; + } else if (addr.kind == irAddr_RelativeSlice) { + Type *rel_ptr = base_type(ir_addr_type(addr)); + GB_ASSERT(rel_ptr->kind == Type_RelativeSlice); + + value = ir_emit_conv(proc, value, rel_ptr->RelativeSlice.slice_type); + + GB_ASSERT(is_type_pointer(ir_type(addr.addr))); + irValue *ptr = ir_emit_conv(proc, ir_emit_struct_ep(proc, addr.addr, 0), t_uintptr); + irValue *val_ptr = ir_emit_conv(proc, ir_slice_elem(proc, value), t_uintptr); + irValue *offset = ir_emit_arith(proc, Token_Sub, val_ptr, ptr, t_uintptr); + + if (!is_type_unsigned(rel_ptr->RelativePointer.base_integer)) { + offset = ir_emit_conv(proc, offset, t_i64); + } + offset = ir_emit_conv(proc, offset, rel_ptr->RelativePointer.base_integer); + + + irValue *offset_ptr = ir_emit_conv(proc, addr.addr, alloc_type_pointer(rel_ptr->RelativePointer.base_integer)); + ir_emit_store(proc, offset_ptr, offset); + + irValue *len = ir_slice_len(proc, value); + len = ir_emit_conv(proc, len, rel_ptr->RelativePointer.base_integer); + + irValue *len_ptr = ir_emit_struct_ep(proc, addr.addr, 1); + ir_emit_store(proc, len_ptr, len); + + return; + } else if (addr.kind == irAddr_Map) { ir_insert_dynamic_map_key_and_value(proc, addr.addr, addr.map_type, addr.map_key, value); return; @@ -3823,6 +3857,42 @@ irValue *ir_addr_load(irProcedure *proc, irAddr const &addr) { return ir_emit_load(proc, final_ptr); + } else if (addr.kind == irAddr_RelativeSlice) { + Type *rel_ptr = base_type(ir_addr_type(addr)); + GB_ASSERT(rel_ptr->kind == Type_RelativeSlice); + + irValue *offset_ptr = ir_emit_struct_ep(proc, addr.addr, 0); + irValue *ptr = ir_emit_conv(proc, offset_ptr, t_uintptr); + irValue *offset = ir_emit_load(proc, offset_ptr); + + + if (!is_type_unsigned(rel_ptr->RelativeSlice.base_integer)) { + offset = ir_emit_conv(proc, offset, t_i64); + } + offset = ir_emit_conv(proc, offset, t_uintptr); + irValue *absolute_ptr = ir_emit_arith(proc, Token_Add, ptr, offset, t_uintptr); + + Type *slice_type = base_type(rel_ptr->RelativeSlice.slice_type); + GB_ASSERT(rel_ptr->RelativeSlice.slice_type->kind == Type_Slice); + Type *slice_elem = slice_type->Slice.elem; + Type *slice_elem_ptr = alloc_type_pointer(slice_elem); + + absolute_ptr = ir_emit_conv(proc, absolute_ptr, slice_elem_ptr); + + irValue *cond = ir_emit_comp(proc, Token_CmpEq, offset, ir_value_nil(rel_ptr->RelativeSlice.base_integer)); + + // NOTE(bill): nil check + irValue *nil_ptr = ir_value_nil(slice_elem_ptr); + irValue *data = ir_emit_select(proc, cond, nil_ptr, absolute_ptr); + + irValue *len = ir_emit_load(proc, ir_emit_struct_ep(proc, addr.addr, 1)); + len = ir_emit_conv(proc, len, t_int); + + irValue *slice = ir_add_local_generated(proc, slice_type, false); + ir_fill_slice(proc, slice, data, len); + return ir_emit_load(proc, slice); + + } else if (addr.kind == irAddr_Map) { Type *map_type = base_type(addr.map_type); irValue *v = ir_add_local_generated(proc, map_type->Map.lookup_result_type, true); @@ -4872,6 +4942,11 @@ irValue *ir_emit_struct_ep(irProcedure *proc, irValue *s, i32 index) { } } else if (is_type_array(t)) { return ir_emit_array_epi(proc, s, index); + } else if (is_type_relative_slice(t)) { + switch (index) { + case 0: result_type = alloc_type_pointer(t->RelativeSlice.base_integer); break; + case 1: result_type = alloc_type_pointer(t->RelativeSlice.base_integer); break; + } } else { GB_PANIC("TODO(bill): struct_gep type: %s, %d", type_to_string(ir_type(s)), index); } @@ -8245,18 +8320,12 @@ irAddr ir_build_addr(irProcedure *proc, Ast *expr) { return ir_addr_map(map_val, key, t, result_type); } - irValue *using_addr = nullptr; - switch (t->kind) { case Type_Array: { irValue *array = nullptr; - if (using_addr != nullptr) { - array = using_addr; - } else { - array = ir_build_addr_ptr(proc, ie->expr); - if (deref) { - array = ir_emit_load(proc, array); - } + array = ir_build_addr_ptr(proc, ie->expr); + if (deref) { + array = ir_emit_load(proc, array); } irValue *index = ir_emit_conv(proc, ir_build_expr(proc, ie->index), t_int); irValue *elem = ir_emit_array_ep(proc, array, index); @@ -8271,15 +8340,10 @@ irAddr ir_build_addr(irProcedure *proc, Ast *expr) { case Type_EnumeratedArray: { irValue *array = nullptr; - if (using_addr != nullptr) { - array = using_addr; - } else { - array = ir_build_addr_ptr(proc, ie->expr); - if (deref) { - array = ir_emit_load(proc, array); - } + array = ir_build_addr_ptr(proc, ie->expr); + if (deref) { + array = ir_emit_load(proc, array); } - Type *index_type = t->EnumeratedArray.index; auto index_tv = type_and_value_of_expr(ie->index); @@ -8308,14 +8372,26 @@ irAddr ir_build_addr(irProcedure *proc, Ast *expr) { case Type_Slice: { irValue *slice = nullptr; - if (using_addr != nullptr) { - slice = ir_emit_load(proc, using_addr); - } else { - slice = ir_build_expr(proc, ie->expr); - if (deref) { - slice = ir_emit_load(proc, slice); - } + slice = ir_build_expr(proc, ie->expr); + if (deref) { + slice = ir_emit_load(proc, slice); } + + irValue *elem = ir_slice_elem(proc, slice); + irValue *index = ir_emit_conv(proc, ir_build_expr(proc, ie->index), t_int); + irValue *len = ir_slice_len(proc, slice); + ir_emit_bounds_check(proc, ast_token(ie->index), index, len); + irValue *v = ir_emit_ptr_offset(proc, elem, index); + return ir_addr(v); + } + + case Type_RelativeSlice: { + irAddr addr = ir_build_addr(proc, ie->expr); + if (deref) { + addr = ir_addr(ir_addr_load(proc, addr)); + } + irValue *slice = ir_addr_load(proc, addr); + irValue *elem = ir_slice_elem(proc, slice); irValue *index = ir_emit_conv(proc, ir_build_expr(proc, ie->index), t_int); irValue *len = ir_slice_len(proc, slice); @@ -8326,14 +8402,11 @@ irAddr ir_build_addr(irProcedure *proc, Ast *expr) { case Type_DynamicArray: { irValue *dynamic_array = nullptr; - if (using_addr != nullptr) { - dynamic_array = ir_emit_load(proc, using_addr); - } else { - dynamic_array = ir_build_expr(proc, ie->expr); - if (deref) { - dynamic_array = ir_emit_load(proc, dynamic_array); - } + dynamic_array = ir_build_expr(proc, ie->expr); + if (deref) { + dynamic_array = ir_emit_load(proc, dynamic_array); } + irValue *elem = ir_dynamic_array_elem(proc, dynamic_array); irValue *len = ir_dynamic_array_len(proc, dynamic_array); irValue *index = ir_emit_conv(proc, ir_build_expr(proc, ie->index), t_int); @@ -8349,14 +8422,11 @@ irAddr ir_build_addr(irProcedure *proc, Ast *expr) { irValue *len; irValue *index; - if (using_addr != nullptr) { - str = ir_emit_load(proc, using_addr); - } else { - str = ir_build_expr(proc, ie->expr); - if (deref) { - str = ir_emit_load(proc, str); - } + str = ir_build_expr(proc, ie->expr); + if (deref) { + str = ir_emit_load(proc, str); } + elem = ir_string_elem(proc, str); len = ir_string_len(proc, str); @@ -8379,14 +8449,14 @@ irAddr ir_build_addr(irProcedure *proc, Ast *expr) { bool no_indices = se->low == nullptr && se->high == nullptr; - irValue *addr = ir_build_addr_ptr(proc, se->expr); - irValue *base = ir_emit_load(proc, addr); + irAddr addr = ir_build_addr(proc, se->expr); + irValue *base = ir_addr_load(proc, addr); Type *type = base_type(ir_type(base)); if (is_type_pointer(type)) { type = base_type(type_deref(type)); - addr = base; - base = ir_emit_load(proc, base); + addr = ir_addr(base); + base = ir_addr_load(proc, addr); } // TODO(bill): Cleanup like mad! @@ -8442,7 +8512,7 @@ irAddr ir_build_addr(irProcedure *proc, Ast *expr) { ir_emit_slice_bounds_check(proc, se->open, low, high, len, se->low != nullptr); } } - irValue *elem = ir_emit_ptr_offset(proc, ir_array_elem(proc, addr), low); + irValue *elem = ir_emit_ptr_offset(proc, ir_array_elem(proc, ir_addr_get_ptr(proc, addr)), low); irValue *new_len = ir_emit_arith(proc, Token_Sub, high, low, t_int); irValue *slice = ir_add_local_generated(proc, slice_type, false); @@ -8470,7 +8540,7 @@ irAddr ir_build_addr(irProcedure *proc, Ast *expr) { case Type_Struct: if (is_type_soa_struct(type)) { - irValue *len = ir_soa_struct_len(proc, addr); + irValue *len = ir_soa_struct_len(proc, ir_addr_get_ptr(proc, addr)); if (high == nullptr) high = len; if (!no_indices) { @@ -8482,7 +8552,7 @@ irAddr ir_build_addr(irProcedure *proc, Ast *expr) { i32 field_count = cast(i32)type->Struct.fields.count; for (i32 i = 0; i < field_count; i++) { irValue *field_dst = ir_emit_struct_ep(proc, dst, i); - irValue *field_src = ir_emit_struct_ep(proc, addr, i); + irValue *field_src = ir_emit_struct_ep(proc, ir_addr_get_ptr(proc, addr), i); field_src = ir_emit_array_ep(proc, field_src, low); ir_emit_store(proc, field_dst, field_src); } diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index 392cfc7b9..545851bd0 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -59,6 +59,9 @@ lbAddr lb_addr(lbValue addr) { if (addr.type != nullptr && is_type_relative_pointer(type_deref(addr.type))) { GB_ASSERT(is_type_pointer(addr.type)); v.kind = lbAddr_RelativePointer; + } else if (addr.type != nullptr && is_type_relative_slice(type_deref(addr.type))) { + GB_ASSERT(is_type_pointer(addr.type)); + v.kind = lbAddr_RelativeSlice; } return v; } @@ -186,6 +189,36 @@ void lb_addr_store(lbProcedure *p, lbAddr const &addr, lbValue value) { LLVMBuildStore(p->builder, offset.value, offset_ptr.value); return; + } else if (addr.kind == lbAddr_RelativeSlice) { + Type *rel_ptr = base_type(lb_addr_type(addr)); + GB_ASSERT(rel_ptr->kind == Type_RelativeSlice); + + value = lb_emit_conv(p, value, rel_ptr->RelativeSlice.slice_type); + + GB_ASSERT(is_type_pointer(addr.addr.type)); + lbValue ptr = lb_emit_conv(p, lb_emit_struct_ep(p, addr.addr, 0), t_uintptr); + lbValue val_ptr = lb_emit_conv(p, lb_slice_elem(p, value), t_uintptr); + lbValue offset = {}; + offset.value = LLVMBuildSub(p->builder, val_ptr.value, ptr.value, ""); + offset.type = t_uintptr; + + if (!is_type_unsigned(rel_ptr->RelativePointer.base_integer)) { + offset = lb_emit_conv(p, offset, t_i64); + } + offset = lb_emit_conv(p, offset, rel_ptr->RelativePointer.base_integer); + + + lbValue offset_ptr = lb_emit_conv(p, addr.addr, alloc_type_pointer(rel_ptr->RelativePointer.base_integer)); + LLVMBuildStore(p->builder, offset.value, offset_ptr.value); + + lbValue len = lb_slice_len(p, value); + len = lb_emit_conv(p, len, rel_ptr->RelativePointer.base_integer); + + lbValue len_ptr = lb_emit_struct_ep(p, addr.addr, 1); + LLVMBuildStore(p->builder, len.value, len_ptr.value); + + return; + } else if (addr.kind == lbAddr_AtomOp_index_set) { lbValue ptr = addr.addr; lbValue index = addr.index_set.index; @@ -394,6 +427,44 @@ lbValue lb_addr_load(lbProcedure *p, lbAddr const &addr) { return lb_emit_load(p, final_ptr); + } else if (addr.kind == lbAddr_RelativeSlice) { + Type *rel_ptr = base_type(lb_addr_type(addr)); + GB_ASSERT(rel_ptr->kind == Type_RelativeSlice); + + lbValue offset_ptr = lb_emit_struct_ep(p, addr.addr, 0); + lbValue ptr = lb_emit_conv(p, offset_ptr, t_uintptr); + lbValue offset = lb_emit_load(p, offset_ptr); + + + if (!is_type_unsigned(rel_ptr->RelativeSlice.base_integer)) { + offset = lb_emit_conv(p, offset, t_i64); + } + offset = lb_emit_conv(p, offset, t_uintptr); + lbValue absolute_ptr = lb_emit_arith(p, Token_Add, ptr, offset, t_uintptr); + + Type *slice_type = base_type(rel_ptr->RelativeSlice.slice_type); + GB_ASSERT(rel_ptr->RelativeSlice.slice_type->kind == Type_Slice); + Type *slice_elem = slice_type->Slice.elem; + Type *slice_elem_ptr = alloc_type_pointer(slice_elem); + + absolute_ptr = lb_emit_conv(p, absolute_ptr, slice_elem_ptr); + + lbValue cond = lb_emit_comp(p, Token_CmpEq, offset, lb_const_nil(p->module, rel_ptr->RelativeSlice.base_integer)); + + // NOTE(bill): nil check + lbValue nil_ptr = lb_const_nil(p->module, slice_elem_ptr); + lbValue data = {}; + data.type = absolute_ptr.type; + data.value = LLVMBuildSelect(p->builder, cond.value, nil_ptr.value, absolute_ptr.value, ""); + + lbValue len = lb_emit_load(p, lb_emit_struct_ep(p, addr.addr, 1)); + len = lb_emit_conv(p, len, t_int); + + lbAddr slice = lb_add_local_generated(p, slice_type, false); + lb_fill_slice(p, slice, data, len); + return lb_addr_load(p, slice); + + } else if (addr.kind == lbAddr_Map) { Type *map_type = base_type(addr.map.type); lbAddr v = lb_add_local_generated(p, map_type->Map.lookup_result_type, true); @@ -6282,6 +6353,11 @@ lbValue lb_emit_struct_ep(lbProcedure *p, lbValue s, i32 index) { } } else if (is_type_array(t)) { return lb_emit_array_epi(p, s, index); + } else if (is_type_relative_slice(t)) { + switch (index) { + case 0: result_type = t->RelativeSlice.base_integer; break; + case 1: result_type = t->RelativeSlice.base_integer; break; + } } else { GB_PANIC("TODO(bill): struct_gep type: %s, %d", type_to_string(s.type), index); } @@ -9476,18 +9552,12 @@ lbAddr lb_build_addr(lbProcedure *p, Ast *expr) { return lb_addr_map(map_val, key, t, result_type); } - lbValue using_addr = {}; - switch (t->kind) { case Type_Array: { lbValue array = {}; - if (using_addr.value != nullptr) { - array = using_addr; - } else { - array = lb_build_addr_ptr(p, ie->expr); - if (deref) { - array = lb_emit_load(p, array); - } + array = lb_build_addr_ptr(p, ie->expr); + if (deref) { + array = lb_emit_load(p, array); } lbValue index = lb_build_expr(p, ie->index); index = lb_emit_conv(p, index, t_int); @@ -9503,13 +9573,9 @@ lbAddr lb_build_addr(lbProcedure *p, Ast *expr) { case Type_EnumeratedArray: { lbValue array = {}; - if (using_addr.value != nullptr) { - array = using_addr; - } else { - array = lb_build_addr_ptr(p, ie->expr); - if (deref) { - array = lb_emit_load(p, array); - } + array = lb_build_addr_ptr(p, ie->expr); + if (deref) { + array = lb_emit_load(p, array); } Type *index_type = t->EnumeratedArray.index; @@ -9540,13 +9606,9 @@ lbAddr lb_build_addr(lbProcedure *p, Ast *expr) { case Type_Slice: { lbValue slice = {}; - if (using_addr.value != nullptr) { - slice = lb_emit_load(p, using_addr); - } else { - slice = lb_build_expr(p, ie->expr); - if (deref) { - slice = lb_emit_load(p, slice); - } + slice = lb_build_expr(p, ie->expr); + if (deref) { + slice = lb_emit_load(p, slice); } lbValue elem = lb_slice_elem(p, slice); lbValue index = lb_emit_conv(p, lb_build_expr(p, ie->index), t_int); @@ -9556,15 +9618,28 @@ lbAddr lb_build_addr(lbProcedure *p, Ast *expr) { return lb_addr(v); } + case Type_RelativeSlice: { + lbAddr slice_addr = {}; + if (deref) { + slice_addr = lb_addr(lb_build_expr(p, ie->expr)); + } else { + slice_addr = lb_build_addr(p, ie->expr); + } + lbValue slice = lb_addr_load(p, slice_addr); + + lbValue elem = lb_slice_elem(p, slice); + lbValue index = lb_emit_conv(p, lb_build_expr(p, ie->index), t_int); + lbValue len = lb_slice_len(p, slice); + // ir_emit_bounds_check(p, ast_token(ie->index), index, len); + lbValue v = lb_emit_ptr_offset(p, elem, index); + return lb_addr(v); + } + case Type_DynamicArray: { lbValue dynamic_array = {}; - if (using_addr.value != nullptr) { - dynamic_array = lb_emit_load(p, using_addr); - } else { - dynamic_array = lb_build_expr(p, ie->expr); - if (deref) { - dynamic_array = lb_emit_load(p, dynamic_array); - } + dynamic_array = lb_build_expr(p, ie->expr); + if (deref) { + dynamic_array = lb_emit_load(p, dynamic_array); } lbValue elem = lb_dynamic_array_elem(p, dynamic_array); lbValue len = lb_dynamic_array_len(p, dynamic_array); @@ -9581,13 +9656,9 @@ lbAddr lb_build_addr(lbProcedure *p, Ast *expr) { lbValue len; lbValue index; - if (using_addr.value != nullptr) { - str = lb_emit_load(p, using_addr); - } else { - str = lb_build_expr(p, ie->expr); - if (deref) { - str = lb_emit_load(p, str); - } + str = lb_build_expr(p, ie->expr); + if (deref) { + str = lb_emit_load(p, str); } elem = lb_string_elem(p, str); len = lb_string_len(p, str); @@ -9640,14 +9711,14 @@ lbAddr lb_build_addr(lbProcedure *p, Ast *expr) { } - lbValue addr = lb_build_addr_ptr(p, se->expr); - lbValue base = lb_emit_load(p, addr); + lbAddr addr = lb_build_addr(p, se->expr); + lbValue base = lb_addr_load(p, addr); Type *type = base_type(base.type); if (is_type_pointer(type)) { type = base_type(type_deref(type)); - addr = base; - base = lb_emit_load(p, base); + addr = lb_addr(base); + base = lb_addr_load(p, addr); } switch (type->kind) { @@ -9668,6 +9739,10 @@ lbAddr lb_build_addr(lbProcedure *p, Ast *expr) { return slice; } + case Type_RelativeSlice: + GB_PANIC("TODO(bill): Type_RelativeSlice should be handled above already on the lb_addr_load"); + break; + case Type_DynamicArray: { Type *elem_type = type->DynamicArray.elem; Type *slice_type = alloc_type_slice(elem_type); @@ -9702,7 +9777,7 @@ lbAddr lb_build_addr(lbProcedure *p, Ast *expr) { lb_emit_slice_bounds_check(p, se->open, low, high, len, se->low != nullptr); } } - lbValue elem = lb_emit_ptr_offset(p, lb_array_elem(p, addr), low); + lbValue elem = lb_emit_ptr_offset(p, lb_array_elem(p, lb_addr_get_ptr(p, addr)), low); lbValue new_len = lb_emit_arith(p, Token_Sub, high, low, t_int); lbAddr slice = lb_add_local_generated(p, slice_type, false); @@ -9730,7 +9805,7 @@ lbAddr lb_build_addr(lbProcedure *p, Ast *expr) { case Type_Struct: if (is_type_soa_struct(type)) { - lbValue len = lb_soa_struct_len(p, addr); + lbValue len = lb_soa_struct_len(p, lb_addr_get_ptr(p, addr)); if (high.value == nullptr) high = len; if (!no_indices) { @@ -9743,7 +9818,7 @@ lbAddr lb_build_addr(lbProcedure *p, Ast *expr) { i32 field_count = cast(i32)type->Struct.fields.count; for (i32 i = 0; i < field_count; i++) { lbValue field_dst = lb_emit_struct_ep(p, dst.addr, i); - lbValue field_src = lb_emit_struct_ep(p, addr, i); + lbValue field_src = lb_emit_struct_ep(p, lb_addr_get_ptr(p, addr), i); field_src = lb_emit_array_ep(p, field_src, low); lb_emit_store(p, field_dst, field_src); } diff --git a/src/llvm_backend.hpp b/src/llvm_backend.hpp index 0b1c331ea..e69e630a9 100644 --- a/src/llvm_backend.hpp +++ b/src/llvm_backend.hpp @@ -29,6 +29,7 @@ enum lbAddrKind { lbAddr_SoaVariable, lbAddr_RelativePointer, + lbAddr_RelativeSlice, lbAddr_AtomOp_index_set, }; @@ -320,9 +321,9 @@ lbValue lb_map_entries_ptr(lbProcedure *p, lbValue value); lbValue lb_map_len(lbProcedure *p, lbValue value); lbValue lb_map_cap(lbProcedure *p, lbValue value); lbValue lb_soa_struct_len(lbProcedure *p, lbValue value); - void lb_emit_increment(lbProcedure *p, lbValue addr); +void lb_fill_slice(lbProcedure *p, lbAddr const &slice, lbValue base_elem, lbValue len); lbValue lb_type_info(lbModule *m, Type *type); diff --git a/src/types.cpp b/src/types.cpp index 9a109741f..274ad2ced 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -1572,6 +1572,8 @@ bool is_type_indexable(Type *t) { return true; case Type_EnumeratedArray: return true; + case Type_RelativeSlice: + return true; } return false; } @@ -1587,6 +1589,8 @@ bool is_type_sliceable(Type *t) { return true; case Type_EnumeratedArray: return false; + case Type_RelativeSlice: + return true; } return false; }