| author | |
| committer | |
| log | 0707be8de88823ff943c3fbd7d0035f88d32dd87 |
| tree | 97e21a5c78e3aa7272e929a3fb3621aeb67dcb3b |
| parent | 2182d28cb0917b8d869d13802a5955ee35b4537a |
| signature |
13 files changed, 172 insertions(+), 88 deletions(-)
lib/std/mem.zig+2-2| ... | ... | @@ -560,7 +560,7 @@ pub fn span(ptr: var) Span(@TypeOf(ptr)) { |
| 560 | 560 | |
| 561 | 561 | test "span" { |
| 562 | 562 | var array: [5]u16 = [_]u16{ 1, 2, 3, 4, 5 }; |
| 563 | const ptr = array[0..2 :3].ptr; | |
| 563 | const ptr = @as([*:3]u16, array[0..2 :3]); | |
| 564 | 564 | testing.expect(eql(u16, span(ptr), &[_]u16{ 1, 2 })); |
| 565 | 565 | testing.expect(eql(u16, span(&array), &[_]u16{ 1, 2, 3, 4, 5 })); |
| 566 | 566 | } |
| ... | ... | @@ -602,7 +602,7 @@ test "len" { |
| 602 | 602 | testing.expect(len(&array) == 5); |
| 603 | 603 | testing.expect(len(array[0..3]) == 3); |
| 604 | 604 | array[2] = 0; |
| 605 | const ptr = array[0..2 :0].ptr; | |
| 605 | const ptr = @as([*:0]u16, array[0..2 :0]); | |
| 606 | 606 | testing.expect(len(ptr) == 2); |
| 607 | 607 | } |
| 608 | 608 | { |
src-self-hosted/stage2.zig+1-1| ... | ... | @@ -128,7 +128,7 @@ export fn stage2_translate_c( |
| 128 | 128 | args_end: [*]?[*]const u8, |
| 129 | 129 | resources_path: [*:0]const u8, |
| 130 | 130 | ) Error { |
| 131 | var errors = @as([*]translate_c.ClangErrMsg, undefined)[0..0]; | |
| 131 | var errors: []translate_c.ClangErrMsg = &[0]translate_c.ClangErrMsg{}; | |
| 132 | 132 | out_ast.* = translate_c.translate(std.heap.c_allocator, args_begin, args_end, &errors, resources_path) catch |err| switch (err) { |
| 133 | 133 | error.SemanticAnalyzeFail => { |
| 134 | 134 | out_errors_ptr.* = errors.ptr; |
src/all_types.hpp+5| ... | ... | @@ -231,6 +231,7 @@ enum ConstPtrSpecial { |
| 231 | 231 | // The pointer is a reference to a single object. |
| 232 | 232 | ConstPtrSpecialRef, |
| 233 | 233 | // The pointer points to an element in an underlying array. |
| 234 | // Not to be confused with ConstPtrSpecialSubArray. | |
| 234 | 235 | ConstPtrSpecialBaseArray, |
| 235 | 236 | // The pointer points to a field in an underlying struct. |
| 236 | 237 | ConstPtrSpecialBaseStruct, |
| ... | ... | @@ -257,6 +258,10 @@ enum ConstPtrSpecial { |
| 257 | 258 | // types to be the same, so all optionals of pointer types use x_ptr |
| 258 | 259 | // instead of x_optional. |
| 259 | 260 | ConstPtrSpecialNull, |
| 261 | // The pointer points to a sub-array (not an individual element). | |
| 262 | // Not to be confused with ConstPtrSpecialBaseArray. However, it uses the same | |
| 263 | // union payload struct (base_array). | |
| 264 | ConstPtrSpecialSubArray, | |
| 260 | 265 | }; |
| 261 | 266 | |
| 262 | 267 | enum ConstPtrMut { |
src/analyze.cpp+7| ... | ... | @@ -5280,6 +5280,11 @@ static uint32_t hash_const_val_ptr(ZigValue *const_val) { |
| 5280 | 5280 | hash_val += hash_ptr(const_val->data.x_ptr.data.base_array.array_val); |
| 5281 | 5281 | hash_val += hash_size(const_val->data.x_ptr.data.base_array.elem_index); |
| 5282 | 5282 | return hash_val; |
| 5283 | case ConstPtrSpecialSubArray: | |
| 5284 | hash_val += (uint32_t)2643358777; | |
| 5285 | hash_val += hash_ptr(const_val->data.x_ptr.data.base_array.array_val); | |
| 5286 | hash_val += hash_size(const_val->data.x_ptr.data.base_array.elem_index); | |
| 5287 | return hash_val; | |
| 5283 | 5288 | case ConstPtrSpecialBaseStruct: |
| 5284 | 5289 | hash_val += (uint32_t)3518317043; |
| 5285 | 5290 | hash_val += hash_ptr(const_val->data.x_ptr.data.base_struct.struct_val); |
| ... | ... | @@ -6746,6 +6751,7 @@ bool const_values_equal_ptr(ZigValue *a, ZigValue *b) { |
| 6746 | 6751 | return false; |
| 6747 | 6752 | return true; |
| 6748 | 6753 | case ConstPtrSpecialBaseArray: |
| 6754 | case ConstPtrSpecialSubArray: | |
| 6749 | 6755 | if (a->data.x_ptr.data.base_array.array_val != b->data.x_ptr.data.base_array.array_val) { |
| 6750 | 6756 | return false; |
| 6751 | 6757 | } |
| ... | ... | @@ -7003,6 +7009,7 @@ static void render_const_val_ptr(CodeGen *g, Buf *buf, ZigValue *const_val, ZigT |
| 7003 | 7009 | render_const_value(g, buf, const_ptr_pointee(nullptr, g, const_val, nullptr)); |
| 7004 | 7010 | return; |
| 7005 | 7011 | case ConstPtrSpecialBaseArray: |
| 7012 | case ConstPtrSpecialSubArray: | |
| 7006 | 7013 | buf_appendf(buf, "*"); |
| 7007 | 7014 | // TODO we need a source node for const_ptr_pointee because it can generate compile errors |
| 7008 | 7015 | render_const_value(g, buf, const_ptr_pointee(nullptr, g, const_val, nullptr)); |
src/codegen.cpp+14-17| ... | ... | @@ -5418,8 +5418,6 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutableGen *executable, IrI |
| 5418 | 5418 | ZigType *array_type = array_ptr_type->data.pointer.child_type; |
| 5419 | 5419 | LLVMValueRef array_ptr = get_handle_value(g, array_ptr_ptr, array_type, array_ptr_type); |
| 5420 | 5420 | |
| 5421 | LLVMValueRef tmp_struct_ptr = ir_llvm_value(g, instruction->result_loc); | |
| 5422 | ||
| 5423 | 5421 | bool want_runtime_safety = instruction->safety_check_on && ir_want_runtime_safety(g, &instruction->base); |
| 5424 | 5422 | |
| 5425 | 5423 | ZigType *result_type = instruction->base.value->type; |
| ... | ... | @@ -5472,6 +5470,8 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutableGen *executable, IrI |
| 5472 | 5470 | } |
| 5473 | 5471 | } |
| 5474 | 5472 | if (!type_has_bits(g, array_type)) { |
| 5473 | LLVMValueRef tmp_struct_ptr = ir_llvm_value(g, instruction->result_loc); | |
| 5474 | ||
| 5475 | 5475 | LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, slice_len_index, ""); |
| 5476 | 5476 | |
| 5477 | 5477 | // TODO if runtime safety is on, store 0xaaaaaaa in ptr field |
| ... | ... | @@ -5486,20 +5486,20 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutableGen *executable, IrI |
| 5486 | 5486 | }; |
| 5487 | 5487 | LLVMValueRef slice_start_ptr = LLVMBuildInBoundsGEP(g->builder, array_ptr, indices, 2, ""); |
| 5488 | 5488 | if (result_type->id == ZigTypeIdPointer) { |
| 5489 | ir_assert(instruction->result_loc == nullptr, &instruction->base); | |
| 5489 | 5490 | LLVMTypeRef result_ptr_type = get_llvm_type(g, result_type); |
| 5490 | LLVMValueRef bitcasted = LLVMBuildBitCast(g->builder, slice_start_ptr, result_ptr_type, ""); | |
| 5491 | gen_store_untyped(g, bitcasted, tmp_struct_ptr, 0, false); | |
| 5492 | return slice_start_ptr; | |
| 5491 | return LLVMBuildBitCast(g->builder, slice_start_ptr, result_ptr_type, ""); | |
| 5493 | 5492 | } else { |
| 5493 | LLVMValueRef tmp_struct_ptr = ir_llvm_value(g, instruction->result_loc); | |
| 5494 | 5494 | LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, slice_ptr_index, ""); |
| 5495 | 5495 | gen_store_untyped(g, slice_start_ptr, ptr_field_ptr, 0, false); |
| 5496 | 5496 | |
| 5497 | 5497 | LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, slice_len_index, ""); |
| 5498 | 5498 | LLVMValueRef len_value = LLVMBuildNSWSub(g->builder, end_val, start_val, ""); |
| 5499 | 5499 | gen_store_untyped(g, len_value, len_field_ptr, 0, false); |
| 5500 | } | |
| 5501 | 5500 | |
| 5502 | return tmp_struct_ptr; | |
| 5501 | return tmp_struct_ptr; | |
| 5502 | } | |
| 5503 | 5503 | } else if (array_type->id == ZigTypeIdPointer) { |
| 5504 | 5504 | assert(array_type->data.pointer.ptr_len != PtrLenSingle); |
| 5505 | 5505 | LLVMValueRef start_val = ir_llvm_value(g, instruction->start); |
| ... | ... | @@ -5515,12 +5515,12 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutableGen *executable, IrI |
| 5515 | 5515 | |
| 5516 | 5516 | LLVMValueRef slice_start_ptr = LLVMBuildInBoundsGEP(g->builder, array_ptr, &start_val, 1, ""); |
| 5517 | 5517 | if (result_type->id == ZigTypeIdPointer) { |
| 5518 | ir_assert(instruction->result_loc == nullptr, &instruction->base); | |
| 5518 | 5519 | LLVMTypeRef result_ptr_type = get_llvm_type(g, result_type); |
| 5519 | LLVMValueRef bitcasted = LLVMBuildBitCast(g->builder, slice_start_ptr, result_ptr_type, ""); | |
| 5520 | gen_store_untyped(g, bitcasted, tmp_struct_ptr, 0, false); | |
| 5521 | return bitcasted; | |
| 5520 | return LLVMBuildBitCast(g->builder, slice_start_ptr, result_ptr_type, ""); | |
| 5522 | 5521 | } |
| 5523 | 5522 | |
| 5523 | LLVMValueRef tmp_struct_ptr = ir_llvm_value(g, instruction->result_loc); | |
| 5524 | 5524 | if (type_has_bits(g, array_type)) { |
| 5525 | 5525 | size_t gen_ptr_index = result_type->data.structure.fields[slice_ptr_index]->gen_index; |
| 5526 | 5526 | LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, gen_ptr_index, ""); |
| ... | ... | @@ -5537,9 +5537,6 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutableGen *executable, IrI |
| 5537 | 5537 | assert(array_type->data.structure.special == StructSpecialSlice); |
| 5538 | 5538 | assert(LLVMGetTypeKind(LLVMTypeOf(array_ptr)) == LLVMPointerTypeKind); |
| 5539 | 5539 | assert(LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(array_ptr))) == LLVMStructTypeKind); |
| 5540 | if (result_type->id != ZigTypeIdPointer) { | |
| 5541 | assert(LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(tmp_struct_ptr))) == LLVMStructTypeKind); | |
| 5542 | } | |
| 5543 | 5540 | |
| 5544 | 5541 | size_t ptr_index = array_type->data.structure.fields[slice_ptr_index]->gen_index; |
| 5545 | 5542 | assert(ptr_index != SIZE_MAX); |
| ... | ... | @@ -5578,11 +5575,11 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutableGen *executable, IrI |
| 5578 | 5575 | |
| 5579 | 5576 | LLVMValueRef slice_start_ptr = LLVMBuildInBoundsGEP(g->builder, src_ptr, &start_val, 1, ""); |
| 5580 | 5577 | if (result_type->id == ZigTypeIdPointer) { |
| 5578 | ir_assert(instruction->result_loc == nullptr, &instruction->base); | |
| 5581 | 5579 | LLVMTypeRef result_ptr_type = get_llvm_type(g, result_type); |
| 5582 | LLVMValueRef bitcasted = LLVMBuildBitCast(g->builder, slice_start_ptr, result_ptr_type, ""); | |
| 5583 | gen_store_untyped(g, bitcasted, tmp_struct_ptr, 0, false); | |
| 5584 | return bitcasted; | |
| 5580 | return LLVMBuildBitCast(g->builder, slice_start_ptr, result_ptr_type, ""); | |
| 5585 | 5581 | } else { |
| 5582 | LLVMValueRef tmp_struct_ptr = ir_llvm_value(g, instruction->result_loc); | |
| 5586 | 5583 | LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, (unsigned)ptr_index, ""); |
| 5587 | 5584 | gen_store_untyped(g, slice_start_ptr, ptr_field_ptr, 0, false); |
| 5588 | 5585 | |
| ... | ... | @@ -6676,7 +6673,6 @@ static LLVMValueRef gen_const_ptr_array_recursive(CodeGen *g, ZigValue *array_co |
| 6676 | 6673 | }; |
| 6677 | 6674 | return LLVMConstInBoundsGEP(base_ptr, indices, 2); |
| 6678 | 6675 | } else { |
| 6679 | assert(parent->id == ConstParentIdScalar); | |
| 6680 | 6676 | return base_ptr; |
| 6681 | 6677 | } |
| 6682 | 6678 | } |
| ... | ... | @@ -6904,6 +6900,7 @@ static LLVMValueRef gen_const_val_ptr(CodeGen *g, ZigValue *const_val, const cha |
| 6904 | 6900 | return const_val->llvm_value; |
| 6905 | 6901 | } |
| 6906 | 6902 | case ConstPtrSpecialBaseArray: |
| 6903 | case ConstPtrSpecialSubArray: | |
| 6907 | 6904 | { |
| 6908 | 6905 | ZigValue *array_const_val = const_val->data.x_ptr.data.base_array.array_val; |
| 6909 | 6906 | assert(array_const_val->type->id == ZigTypeIdArray); |
src/ir.cpp+110-45| ... | ... | @@ -784,14 +784,32 @@ static ZigValue *const_ptr_pointee_unchecked_no_isf(CodeGen *g, ZigValue *const_ |
| 784 | 784 | break; |
| 785 | 785 | case ConstPtrSpecialBaseArray: { |
| 786 | 786 | ZigValue *array_val = const_val->data.x_ptr.data.base_array.array_val; |
| 787 | if (const_val->data.x_ptr.data.base_array.elem_index == array_val->type->data.array.len) { | |
| 787 | size_t elem_index = const_val->data.x_ptr.data.base_array.elem_index; | |
| 788 | if (elem_index == array_val->type->data.array.len) { | |
| 788 | 789 | result = array_val->type->data.array.sentinel; |
| 789 | 790 | } else { |
| 790 | 791 | expand_undef_array(g, array_val); |
| 791 | result = &array_val->data.x_array.data.s_none.elements[const_val->data.x_ptr.data.base_array.elem_index]; | |
| 792 | result = &array_val->data.x_array.data.s_none.elements[elem_index]; | |
| 792 | 793 | } |
| 793 | 794 | break; |
| 794 | 795 | } |
| 796 | case ConstPtrSpecialSubArray: { | |
| 797 | ZigValue *array_val = const_val->data.x_ptr.data.base_array.array_val; | |
| 798 | size_t elem_index = const_val->data.x_ptr.data.base_array.elem_index; | |
| 799 | ||
| 800 | // TODO handle sentinel terminated arrays | |
| 801 | expand_undef_array(g, array_val); | |
| 802 | result = g->pass1_arena->create<ZigValue>(); | |
| 803 | result->special = array_val->special; | |
| 804 | result->type = get_array_type(g, array_val->type->data.array.child_type, | |
| 805 | array_val->type->data.array.len - elem_index, nullptr); | |
| 806 | result->data.x_array.special = ConstArraySpecialNone; | |
| 807 | result->data.x_array.data.s_none.elements = &array_val->data.x_array.data.s_none.elements[elem_index]; | |
| 808 | result->parent.id = ConstParentIdArray; | |
| 809 | result->parent.data.p_array.array_val = array_val; | |
| 810 | result->parent.data.p_array.elem_index = elem_index; | |
| 811 | break; | |
| 812 | } | |
| 795 | 813 | case ConstPtrSpecialBaseStruct: { |
| 796 | 814 | ZigValue *struct_val = const_val->data.x_ptr.data.base_struct.struct_val; |
| 797 | 815 | expand_undef_struct(g, struct_val); |
| ... | ... | @@ -3727,8 +3745,8 @@ static IrInstGen *ir_build_slice_gen(IrAnalyze *ira, IrInst *source_instruction, |
| 3727 | 3745 | |
| 3728 | 3746 | ir_ref_inst_gen(ptr, ira->new_irb.current_basic_block); |
| 3729 | 3747 | ir_ref_inst_gen(start, ira->new_irb.current_basic_block); |
| 3730 | if (end) ir_ref_inst_gen(end, ira->new_irb.current_basic_block); | |
| 3731 | ir_ref_inst_gen(result_loc, ira->new_irb.current_basic_block); | |
| 3748 | if (end != nullptr) ir_ref_inst_gen(end, ira->new_irb.current_basic_block); | |
| 3749 | if (result_loc != nullptr) ir_ref_inst_gen(result_loc, ira->new_irb.current_basic_block); | |
| 3732 | 3750 | |
| 3733 | 3751 | return &instruction->base; |
| 3734 | 3752 | } |
| ... | ... | @@ -12672,40 +12690,63 @@ static IrInstGen *ir_resolve_ptr_of_array_to_slice(IrAnalyze *ira, IrInst* sourc |
| 12672 | 12690 | Error err; |
| 12673 | 12691 | |
| 12674 | 12692 | assert(array_ptr->value->type->id == ZigTypeIdPointer); |
| 12693 | assert(array_ptr->value->type->data.pointer.child_type->id == ZigTypeIdArray); | |
| 12675 | 12694 | |
| 12676 | if ((err = type_resolve(ira->codegen, array_ptr->value->type, ResolveStatusAlignmentKnown))) { | |
| 12677 | return ira->codegen->invalid_inst_gen; | |
| 12678 | } | |
| 12695 | ZigType *array_type = array_ptr->value->type->data.pointer.child_type; | |
| 12696 | const size_t array_len = array_type->data.array.len; | |
| 12679 | 12697 | |
| 12680 | assert(array_ptr->value->type->data.pointer.child_type->id == ZigTypeIdArray); | |
| 12698 | // A zero-sized array can be casted regardless of the destination alignment, or | |
| 12699 | // whether the pointer is undefined, and the result is always comptime known. | |
| 12700 | if (array_len == 0) { | |
| 12701 | ZigValue *undef_array = ira->codegen->pass1_arena->create<ZigValue>(); | |
| 12702 | undef_array->special = ConstValSpecialUndef; | |
| 12703 | undef_array->type = array_type; | |
| 12681 | 12704 | |
| 12682 | const size_t array_len = array_ptr->value->type->data.pointer.child_type->data.array.len; | |
| 12705 | IrInstGen *result = ir_const(ira, source_instr, wanted_type); | |
| 12706 | init_const_slice(ira->codegen, result->value, undef_array, 0, 0, false); | |
| 12707 | result->value->data.x_struct.fields[slice_ptr_index]->data.x_ptr.mut = ConstPtrMutComptimeConst; | |
| 12708 | result->value->type = wanted_type; | |
| 12709 | return result; | |
| 12710 | } | |
| 12683 | 12711 | |
| 12684 | // A zero-sized array can always be casted irregardless of the destination | |
| 12685 | // alignment | |
| 12686 | if (array_len != 0) { | |
| 12687 | wanted_type = adjust_slice_align(ira->codegen, wanted_type, | |
| 12688 | get_ptr_align(ira->codegen, array_ptr->value->type)); | |
| 12712 | if ((err = type_resolve(ira->codegen, array_ptr->value->type, ResolveStatusAlignmentKnown))) { | |
| 12713 | return ira->codegen->invalid_inst_gen; | |
| 12689 | 12714 | } |
| 12690 | 12715 | |
| 12716 | wanted_type = adjust_slice_align(ira->codegen, wanted_type, | |
| 12717 | get_ptr_align(ira->codegen, array_ptr->value->type)); | |
| 12718 | ||
| 12691 | 12719 | if (instr_is_comptime(array_ptr)) { |
| 12692 | 12720 | ZigValue *array_ptr_val = ir_resolve_const(ira, array_ptr, UndefBad); |
| 12693 | 12721 | if (array_ptr_val == nullptr) |
| 12694 | 12722 | return ira->codegen->invalid_inst_gen; |
| 12695 | ZigValue *pointee = const_ptr_pointee(ira, ira->codegen, array_ptr_val, source_instr->source_node); | |
| 12696 | if (pointee == nullptr) | |
| 12697 | return ira->codegen->invalid_inst_gen; | |
| 12698 | if (pointee->special != ConstValSpecialRuntime) { | |
| 12699 | assert(array_ptr_val->type->id == ZigTypeIdPointer); | |
| 12700 | ZigType *array_type = array_ptr_val->type->data.pointer.child_type; | |
| 12701 | assert(is_slice(wanted_type)); | |
| 12702 | bool is_const = wanted_type->data.structure.fields[slice_ptr_index]->type_entry->data.pointer.is_const; | |
| 12723 | ir_assert(is_slice(wanted_type), source_instr); | |
| 12724 | bool wanted_const = wanted_type->data.structure.fields[slice_ptr_index]->type_entry->data.pointer.is_const; | |
| 12725 | // Optimization to avoid creating unnecessary ZigValue in const_ptr_pointee | |
| 12726 | if (array_ptr_val->data.x_ptr.special == ConstPtrSpecialSubArray) { | |
| 12727 | ZigValue *array_val = array_ptr_val->data.x_ptr.data.base_array.array_val; | |
| 12728 | if (array_val->special != ConstValSpecialRuntime) { | |
| 12729 | IrInstGen *result = ir_const(ira, source_instr, wanted_type); | |
| 12730 | init_const_slice(ira->codegen, result->value, array_val, | |
| 12731 | array_ptr_val->data.x_ptr.data.base_array.elem_index, | |
| 12732 | array_type->data.array.len, wanted_const); | |
| 12733 | result->value->data.x_struct.fields[slice_ptr_index]->data.x_ptr.mut = array_ptr_val->data.x_ptr.mut; | |
| 12734 | result->value->type = wanted_type; | |
| 12735 | return result; | |
| 12736 | } | |
| 12737 | } else { | |
| 12738 | ZigValue *pointee = const_ptr_pointee(ira, ira->codegen, array_ptr_val, source_instr->source_node); | |
| 12739 | if (pointee == nullptr) | |
| 12740 | return ira->codegen->invalid_inst_gen; | |
| 12741 | if (pointee->special != ConstValSpecialRuntime) { | |
| 12742 | assert(array_ptr_val->type->id == ZigTypeIdPointer); | |
| 12703 | 12743 | |
| 12704 | IrInstGen *result = ir_const(ira, source_instr, wanted_type); | |
| 12705 | init_const_slice(ira->codegen, result->value, pointee, 0, array_type->data.array.len, is_const); | |
| 12706 | result->value->data.x_struct.fields[slice_ptr_index]->data.x_ptr.mut = array_ptr_val->data.x_ptr.mut; | |
| 12707 | result->value->type = wanted_type; | |
| 12708 | return result; | |
| 12744 | IrInstGen *result = ir_const(ira, source_instr, wanted_type); | |
| 12745 | init_const_slice(ira->codegen, result->value, pointee, 0, array_type->data.array.len, wanted_const); | |
| 12746 | result->value->data.x_struct.fields[slice_ptr_index]->data.x_ptr.mut = array_ptr_val->data.x_ptr.mut; | |
| 12747 | result->value->type = wanted_type; | |
| 12748 | return result; | |
| 12749 | } | |
| 12709 | 12750 | } |
| 12710 | 12751 | } |
| 12711 | 12752 | |
| ... | ... | @@ -19931,6 +19972,7 @@ static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source |
| 19931 | 19972 | dst_size, buf_ptr(&pointee->type->name), src_size)); |
| 19932 | 19973 | return ErrorSemanticAnalyzeFail; |
| 19933 | 19974 | } |
| 19975 | case ConstPtrSpecialSubArray: | |
| 19934 | 19976 | case ConstPtrSpecialBaseArray: { |
| 19935 | 19977 | ZigValue *array_val = ptr_val->data.x_ptr.data.base_array.array_val; |
| 19936 | 19978 | assert(array_val->type->id == ZigTypeIdArray); |
| ... | ... | @@ -20814,6 +20856,7 @@ static IrInstGen *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstSrcElemP |
| 20814 | 20856 | } |
| 20815 | 20857 | break; |
| 20816 | 20858 | case ConstPtrSpecialBaseArray: |
| 20859 | case ConstPtrSpecialSubArray: | |
| 20817 | 20860 | { |
| 20818 | 20861 | size_t offset = array_ptr_val->data.x_ptr.data.base_array.elem_index; |
| 20819 | 20862 | new_index = offset + index; |
| ... | ... | @@ -20884,6 +20927,7 @@ static IrInstGen *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstSrcElemP |
| 20884 | 20927 | out_val->data.x_ptr.special = ConstPtrSpecialRef; |
| 20885 | 20928 | out_val->data.x_ptr.data.ref.pointee = ptr_field->data.x_ptr.data.ref.pointee; |
| 20886 | 20929 | break; |
| 20930 | case ConstPtrSpecialSubArray: | |
| 20887 | 20931 | case ConstPtrSpecialBaseArray: |
| 20888 | 20932 | { |
| 20889 | 20933 | size_t offset = ptr_field->data.x_ptr.data.base_array.elem_index; |
| ... | ... | @@ -25894,6 +25938,7 @@ static IrInstGen *ir_analyze_instruction_memset(IrAnalyze *ira, IrInstSrcMemset |
| 25894 | 25938 | start = 0; |
| 25895 | 25939 | bound_end = 1; |
| 25896 | 25940 | break; |
| 25941 | case ConstPtrSpecialSubArray: | |
| 25897 | 25942 | case ConstPtrSpecialBaseArray: |
| 25898 | 25943 | { |
| 25899 | 25944 | ZigValue *array_val = dest_ptr_val->data.x_ptr.data.base_array.array_val; |
| ... | ... | @@ -26027,6 +26072,7 @@ static IrInstGen *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstSrcMemcpy |
| 26027 | 26072 | dest_start = 0; |
| 26028 | 26073 | dest_end = 1; |
| 26029 | 26074 | break; |
| 26075 | case ConstPtrSpecialSubArray: | |
| 26030 | 26076 | case ConstPtrSpecialBaseArray: |
| 26031 | 26077 | { |
| 26032 | 26078 | ZigValue *array_val = dest_ptr_val->data.x_ptr.data.base_array.array_val; |
| ... | ... | @@ -26070,6 +26116,7 @@ static IrInstGen *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstSrcMemcpy |
| 26070 | 26116 | src_start = 0; |
| 26071 | 26117 | src_end = 1; |
| 26072 | 26118 | break; |
| 26119 | case ConstPtrSpecialSubArray: | |
| 26073 | 26120 | case ConstPtrSpecialBaseArray: |
| 26074 | 26121 | { |
| 26075 | 26122 | ZigValue *array_val = src_ptr_val->data.x_ptr.data.base_array.array_val; |
| ... | ... | @@ -26219,7 +26266,8 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i |
| 26219 | 26266 | ZigType *return_type; |
| 26220 | 26267 | |
| 26221 | 26268 | if (value_is_comptime(casted_start->value) && |
| 26222 | ((end != nullptr && value_is_comptime(end->value)) || array_type->id == ZigTypeIdArray )) | |
| 26269 | ((end != nullptr && value_is_comptime(end->value)) || | |
| 26270 | (end == nullptr && array_type->id == ZigTypeIdArray))) | |
| 26223 | 26271 | { |
| 26224 | 26272 | ZigValue *start_val = ir_resolve_const(ira, casted_start, UndefBad); |
| 26225 | 26273 | if (!start_val) |
| ... | ... | @@ -26244,13 +26292,16 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i |
| 26244 | 26292 | return ira->codegen->invalid_inst_gen; |
| 26245 | 26293 | } |
| 26246 | 26294 | |
| 26295 | // TODO in the case of non-zero start index, the byte alignment should be smarter here. | |
| 26296 | // we should be able to use the same logic as indexing. | |
| 26297 | uint32_t ptr_byte_alignment = ((end_scalar - start_scalar != 0) && start_scalar == 0) ? | |
| 26298 | non_sentinel_slice_ptr_type->data.pointer.explicit_alignment : 0; | |
| 26247 | 26299 | ZigType *return_array_type = get_array_type(ira->codegen, elem_type, end_scalar - start_scalar, |
| 26248 | 26300 | array_sentinel); |
| 26249 | 26301 | return_type = get_pointer_to_type_extra(ira->codegen, return_array_type, |
| 26250 | 26302 | non_sentinel_slice_ptr_type->data.pointer.is_const, |
| 26251 | 26303 | non_sentinel_slice_ptr_type->data.pointer.is_volatile, |
| 26252 | PtrLenSingle, | |
| 26253 | 0, 0, 0, false); | |
| 26304 | PtrLenSingle, ptr_byte_alignment, 0, 0, false); | |
| 26254 | 26305 | } else if (sentinel_val != nullptr) { |
| 26255 | 26306 | ZigType *slice_ptr_type = adjust_ptr_sentinel(ira->codegen, non_sentinel_slice_ptr_type, sentinel_val); |
| 26256 | 26307 | return_type = get_slice_type(ira->codegen, slice_ptr_type); |
| ... | ... | @@ -26283,6 +26334,10 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i |
| 26283 | 26334 | abs_offset = 0; |
| 26284 | 26335 | rel_end = SIZE_MAX; |
| 26285 | 26336 | ptr_is_undef = true; |
| 26337 | } else if (parent_ptr->data.x_ptr.special == ConstPtrSpecialHardCodedAddr) { | |
| 26338 | array_val = nullptr; | |
| 26339 | abs_offset = 0; | |
| 26340 | rel_end = SIZE_MAX; | |
| 26286 | 26341 | } else { |
| 26287 | 26342 | array_val = const_ptr_pointee(ira, ira->codegen, parent_ptr, instruction->base.base.source_node); |
| 26288 | 26343 | if (array_val == nullptr) |
| ... | ... | @@ -26325,6 +26380,7 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i |
| 26325 | 26380 | rel_end = 1; |
| 26326 | 26381 | } |
| 26327 | 26382 | break; |
| 26383 | case ConstPtrSpecialSubArray: | |
| 26328 | 26384 | case ConstPtrSpecialBaseArray: |
| 26329 | 26385 | array_val = parent_ptr->data.x_ptr.data.base_array.array_val; |
| 26330 | 26386 | abs_offset = parent_ptr->data.x_ptr.data.base_array.elem_index; |
| ... | ... | @@ -26375,6 +26431,7 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i |
| 26375 | 26431 | abs_offset = SIZE_MAX; |
| 26376 | 26432 | rel_end = 1; |
| 26377 | 26433 | break; |
| 26434 | case ConstPtrSpecialSubArray: | |
| 26378 | 26435 | case ConstPtrSpecialBaseArray: |
| 26379 | 26436 | array_val = parent_ptr->data.x_ptr.data.base_array.array_val; |
| 26380 | 26437 | abs_offset = parent_ptr->data.x_ptr.data.base_array.elem_index; |
| ... | ... | @@ -26454,6 +26511,9 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i |
| 26454 | 26511 | if (array_val) { |
| 26455 | 26512 | size_t index = abs_offset + start_scalar; |
| 26456 | 26513 | init_const_ptr_array(ira->codegen, ptr_val, array_val, index, return_type_is_const, PtrLenUnknown); |
| 26514 | if (return_type->id == ZigTypeIdPointer) { | |
| 26515 | ptr_val->data.x_ptr.special = ConstPtrSpecialSubArray; | |
| 26516 | } | |
| 26457 | 26517 | if (array_type->id == ZigTypeIdArray) { |
| 26458 | 26518 | ptr_val->data.x_ptr.mut = ptr_ptr->value->data.x_ptr.mut; |
| 26459 | 26519 | } else if (is_slice(array_type)) { |
| ... | ... | @@ -26463,7 +26523,7 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i |
| 26463 | 26523 | } |
| 26464 | 26524 | } else if (ptr_is_undef) { |
| 26465 | 26525 | ptr_val->type = get_pointer_to_type(ira->codegen, parent_ptr->type->data.pointer.child_type, |
| 26466 | return_type_is_const); | |
| 26526 | return_type_is_const); | |
| 26467 | 26527 | ptr_val->special = ConstValSpecialUndef; |
| 26468 | 26528 | } else switch (parent_ptr->data.x_ptr.special) { |
| 26469 | 26529 | case ConstPtrSpecialInvalid: |
| ... | ... | @@ -26473,6 +26533,7 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i |
| 26473 | 26533 | init_const_ptr_ref(ira->codegen, ptr_val, parent_ptr->data.x_ptr.data.ref.pointee, |
| 26474 | 26534 | return_type_is_const); |
| 26475 | 26535 | break; |
| 26536 | case ConstPtrSpecialSubArray: | |
| 26476 | 26537 | case ConstPtrSpecialBaseArray: |
| 26477 | 26538 | zig_unreachable(); |
| 26478 | 26539 | case ConstPtrSpecialBaseStruct: |
| ... | ... | @@ -26500,20 +26561,6 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i |
| 26500 | 26561 | return result; |
| 26501 | 26562 | } |
| 26502 | 26563 | |
| 26503 | IrInstGen *result_loc = ir_resolve_result(ira, &instruction->base.base, instruction->result_loc, | |
| 26504 | return_type, nullptr, true, true); | |
| 26505 | if (result_loc != nullptr) { | |
| 26506 | if (type_is_invalid(result_loc->value->type) || result_loc->value->type->id == ZigTypeIdUnreachable) { | |
| 26507 | return result_loc; | |
| 26508 | } | |
| 26509 | IrInstGen *dummy_value = ir_const(ira, &instruction->base.base, return_type); | |
| 26510 | dummy_value->value->special = ConstValSpecialRuntime; | |
| 26511 | IrInstGen *dummy_result = ir_implicit_cast2(ira, &instruction->base.base, | |
| 26512 | dummy_value, result_loc->value->type->data.pointer.child_type); | |
| 26513 | if (type_is_invalid(dummy_result->value->type)) | |
| 26514 | return ira->codegen->invalid_inst_gen; | |
| 26515 | } | |
| 26516 | ||
| 26517 | 26564 | if (generate_non_null_assert) { |
| 26518 | 26565 | IrInstGen *ptr_val = ir_get_deref(ira, &instruction->base.base, ptr_ptr, nullptr); |
| 26519 | 26566 | |
| ... | ... | @@ -26523,6 +26570,24 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i |
| 26523 | 26570 | ir_build_assert_non_null(ira, &instruction->base.base, ptr_val); |
| 26524 | 26571 | } |
| 26525 | 26572 | |
| 26573 | IrInstGen *result_loc = nullptr; | |
| 26574 | ||
| 26575 | if (return_type->id != ZigTypeIdPointer) { | |
| 26576 | result_loc = ir_resolve_result(ira, &instruction->base.base, instruction->result_loc, | |
| 26577 | return_type, nullptr, true, true); | |
| 26578 | if (result_loc != nullptr) { | |
| 26579 | if (type_is_invalid(result_loc->value->type) || result_loc->value->type->id == ZigTypeIdUnreachable) { | |
| 26580 | return result_loc; | |
| 26581 | } | |
| 26582 | IrInstGen *dummy_value = ir_const(ira, &instruction->base.base, return_type); | |
| 26583 | dummy_value->value->special = ConstValSpecialRuntime; | |
| 26584 | IrInstGen *dummy_result = ir_implicit_cast2(ira, &instruction->base.base, | |
| 26585 | dummy_value, result_loc->value->type->data.pointer.child_type); | |
| 26586 | if (type_is_invalid(dummy_result->value->type)) | |
| 26587 | return ira->codegen->invalid_inst_gen; | |
| 26588 | } | |
| 26589 | } | |
| 26590 | ||
| 26526 | 26591 | return ir_build_slice_gen(ira, &instruction->base.base, return_type, ptr_ptr, |
| 26527 | 26592 | casted_start, end, instruction->safety_check_on, result_loc); |
| 26528 | 26593 | } |
test/stage1/behavior/align.zig+11-10| ... | ... | @@ -171,18 +171,19 @@ test "runtime known array index has best alignment possible" { |
| 171 | 171 | |
| 172 | 172 | // because pointer is align 2 and u32 align % 2 == 0 we can assume align 2 |
| 173 | 173 | var smaller align(2) = [_]u32{ 1, 2, 3, 4 }; |
| 174 | comptime expect(@TypeOf(smaller[0..]) == []align(2) u32); | |
| 175 | comptime expect(@TypeOf(smaller[0..].ptr) == [*]align(2) u32); | |
| 176 | testIndex(smaller[0..].ptr, 0, *align(2) u32); | |
| 177 | testIndex(smaller[0..].ptr, 1, *align(2) u32); | |
| 178 | testIndex(smaller[0..].ptr, 2, *align(2) u32); | |
| 179 | testIndex(smaller[0..].ptr, 3, *align(2) u32); | |
| 174 | var runtime_zero: usize = 0; | |
| 175 | comptime expect(@TypeOf(smaller[runtime_zero..]) == []align(2) u32); | |
| 176 | comptime expect(@TypeOf(smaller[runtime_zero..].ptr) == [*]align(2) u32); | |
| 177 | testIndex(smaller[runtime_zero..].ptr, 0, *align(2) u32); | |
| 178 | testIndex(smaller[runtime_zero..].ptr, 1, *align(2) u32); | |
| 179 | testIndex(smaller[runtime_zero..].ptr, 2, *align(2) u32); | |
| 180 | testIndex(smaller[runtime_zero..].ptr, 3, *align(2) u32); | |
| 180 | 181 | |
| 181 | 182 | // has to use ABI alignment because index known at runtime only |
| 182 | testIndex2(array[0..].ptr, 0, *u8); | |
| 183 | testIndex2(array[0..].ptr, 1, *u8); | |
| 184 | testIndex2(array[0..].ptr, 2, *u8); | |
| 185 | testIndex2(array[0..].ptr, 3, *u8); | |
| 183 | testIndex2(array[runtime_zero..].ptr, 0, *u8); | |
| 184 | testIndex2(array[runtime_zero..].ptr, 1, *u8); | |
| 185 | testIndex2(array[runtime_zero..].ptr, 2, *u8); | |
| 186 | testIndex2(array[runtime_zero..].ptr, 3, *u8); | |
| 186 | 187 | } |
| 187 | 188 | fn testIndex(smaller: [*]align(2) u32, index: usize, comptime T: type) void { |
| 188 | 189 | comptime expect(@TypeOf(&smaller[index]) == T); |
test/stage1/behavior/cast.zig+2-1| ... | ... | @@ -435,7 +435,8 @@ fn incrementVoidPtrValue(value: ?*c_void) void { |
| 435 | 435 | |
| 436 | 436 | test "implicit cast from [*]T to ?*c_void" { |
| 437 | 437 | var a = [_]u8{ 3, 2, 1 }; |
| 438 | incrementVoidPtrArray(a[0..].ptr, 3); | |
| 438 | var runtime_zero: usize = 0; | |
| 439 | incrementVoidPtrArray(a[runtime_zero..].ptr, 3); | |
| 439 | 440 | expect(std.mem.eql(u8, &a, &[_]u8{ 4, 3, 2 })); |
| 440 | 441 | } |
| 441 | 442 |
test/stage1/behavior/eval.zig+1-1| ... | ... | @@ -524,7 +524,7 @@ test "comptime slice of slice preserves comptime var" { |
| 524 | 524 | test "comptime slice of pointer preserves comptime var" { |
| 525 | 525 | comptime { |
| 526 | 526 | var buff: [10]u8 = undefined; |
| 527 | var a = buff[0..].ptr; | |
| 527 | var a = @ptrCast([*]u8, &buff); | |
| 528 | 528 | a[0..1][0] = 1; |
| 529 | 529 | expect(buff[0..][0..][0] == 1); |
| 530 | 530 | } |
test/stage1/behavior/misc.zig+9-5| ... | ... | @@ -102,8 +102,8 @@ test "memcpy and memset intrinsics" { |
| 102 | 102 | var foo: [20]u8 = undefined; |
| 103 | 103 | var bar: [20]u8 = undefined; |
| 104 | 104 | |
| 105 | @memset(foo[0..].ptr, 'A', foo.len); | |
| 106 | @memcpy(bar[0..].ptr, foo[0..].ptr, bar.len); | |
| 105 | @memset(&foo, 'A', foo.len); | |
| 106 | @memcpy(&bar, &foo, bar.len); | |
| 107 | 107 | |
| 108 | 108 | if (bar[11] != 'A') unreachable; |
| 109 | 109 | } |
| ... | ... | @@ -565,12 +565,16 @@ test "volatile load and store" { |
| 565 | 565 | expect(ptr.* == 1235); |
| 566 | 566 | } |
| 567 | 567 | |
| 568 | test "slice string literal has type []const u8" { | |
| 568 | test "slice string literal has correct type" { | |
| 569 | 569 | comptime { |
| 570 | expect(@TypeOf("aoeu"[0..]) == []const u8); | |
| 570 | expect(@TypeOf("aoeu"[0..]) == *const [4:0]u8); | |
| 571 | 571 | const array = [_]i32{ 1, 2, 3, 4 }; |
| 572 | expect(@TypeOf(array[0..]) == []const i32); | |
| 572 | expect(@TypeOf(array[0..]) == *const [4]i32); | |
| 573 | 573 | } |
| 574 | var runtime_zero: usize = 0; | |
| 575 | expect(@TypeOf("aoeu"[runtime_zero..]) == [:0]const u8); | |
| 576 | const array = [_]i32{ 1, 2, 3, 4 }; | |
| 577 | expect(@TypeOf(array[runtime_zero..]) == []const u8); | |
| 574 | 578 | } |
| 575 | 579 | |
| 576 | 580 | test "pointer child field" { |
test/stage1/behavior/ptrcast.zig+1-1| ... | ... | @@ -13,7 +13,7 @@ fn testReinterpretBytesAsInteger() void { |
| 13 | 13 | builtin.Endian.Little => 0xab785634, |
| 14 | 14 | builtin.Endian.Big => 0x345678ab, |
| 15 | 15 | }; |
| 16 | expect(@ptrCast(*align(1) const u32, bytes[1..5].ptr).* == expected); | |
| 16 | expect(@ptrCast(*align(1) const u32, bytes[1..5]).* == expected); | |
| 17 | 17 | } |
| 18 | 18 | |
| 19 | 19 | test "reinterpret bytes of an array into an extern struct" { |
test/stage1/behavior/slice.zig+7-3| ... | ... | @@ -7,7 +7,7 @@ const mem = std.mem; |
| 7 | 7 | const x = @intToPtr([*]i32, 0x1000)[0..0x500]; |
| 8 | 8 | const y = x[0x100..]; |
| 9 | 9 | test "compile time slice of pointer to hard coded address" { |
| 10 | expect(@ptrToInt(x.ptr) == 0x1000); | |
| 10 | expect(@ptrToInt(x) == 0x1000); | |
| 11 | 11 | expect(x.len == 0x500); |
| 12 | 12 | |
| 13 | 13 | expect(@ptrToInt(y.ptr) == 0x1100); |
| ... | ... | @@ -47,7 +47,9 @@ test "C pointer slice access" { |
| 47 | 47 | var buf: [10]u32 = [1]u32{42} ** 10; |
| 48 | 48 | const c_ptr = @ptrCast([*c]const u32, &buf); |
| 49 | 49 | |
| 50 | comptime expectEqual([]const u32, @TypeOf(c_ptr[0..1])); | |
| 50 | var runtime_zero: usize = 0; | |
| 51 | comptime expectEqual([]const u32, @TypeOf(c_ptr[runtime_zero..1])); | |
| 52 | comptime expectEqual(*const [1]u32, @TypeOf(c_ptr[0..1])); | |
| 51 | 53 | |
| 52 | 54 | for (c_ptr[0..5]) |*cl| { |
| 53 | 55 | expectEqual(@as(u32, 42), cl.*); |
| ... | ... | @@ -107,7 +109,9 @@ test "obtaining a null terminated slice" { |
| 107 | 109 | const ptr2 = buf[0..runtime_len :0]; |
| 108 | 110 | // ptr2 is a null-terminated slice |
| 109 | 111 | comptime expect(@TypeOf(ptr2) == [:0]u8); |
| 110 | comptime expect(@TypeOf(ptr2[0..2]) == []u8); | |
| 112 | comptime expect(@TypeOf(ptr2[0..2]) == *[2]u8); | |
| 113 | var runtime_zero: usize = 0; | |
| 114 | comptime expect(@TypeOf(ptr2[runtime_zero..2]) == []u8); | |
| 111 | 115 | } |
| 112 | 116 | |
| 113 | 117 | test "empty array to slice" { |
test/stage1/behavior/struct.zig+2-2| ... | ... | @@ -409,8 +409,8 @@ const Bitfields = packed struct { |
| 409 | 409 | test "native bit field understands endianness" { |
| 410 | 410 | var all: u64 = 0x7765443322221111; |
| 411 | 411 | var bytes: [8]u8 = undefined; |
| 412 | @memcpy(bytes[0..].ptr, @ptrCast([*]u8, &all), 8); | |
| 413 | var bitfields = @ptrCast(*Bitfields, bytes[0..].ptr).*; | |
| 412 | @memcpy(&bytes, @ptrCast([*]u8, &all), 8); | |
| 413 | var bitfields = @ptrCast(*Bitfields, &bytes).*; | |
| 414 | 414 | |
| 415 | 415 | expect(bitfields.f1 == 0x1111); |
| 416 | 416 | expect(bitfields.f2 == 0x2222); |