| 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,7 +560,7 @@ pub fn span(ptr: var) Span(@TypeOf(ptr)) { |
| 560 | 560 | ||
| 561 | test "span" { | 561 | test "span" { |
| 562 | var array: [5]u16 = [_]u16{ 1, 2, 3, 4, 5 }; | 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 | testing.expect(eql(u16, span(ptr), &[_]u16{ 1, 2 })); | 564 | testing.expect(eql(u16, span(ptr), &[_]u16{ 1, 2 })); |
| 565 | testing.expect(eql(u16, span(&array), &[_]u16{ 1, 2, 3, 4, 5 })); | 565 | testing.expect(eql(u16, span(&array), &[_]u16{ 1, 2, 3, 4, 5 })); |
| 566 | } | 566 | } |
| ... | @@ -602,7 +602,7 @@ test "len" { | ... | @@ -602,7 +602,7 @@ test "len" { |
| 602 | testing.expect(len(&array) == 5); | 602 | testing.expect(len(&array) == 5); |
| 603 | testing.expect(len(array[0..3]) == 3); | 603 | testing.expect(len(array[0..3]) == 3); |
| 604 | array[2] = 0; | 604 | array[2] = 0; |
| 605 | const ptr = array[0..2 :0].ptr; | 605 | const ptr = @as([*:0]u16, array[0..2 :0]); |
| 606 | testing.expect(len(ptr) == 2); | 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,7 +128,7 @@ export fn stage2_translate_c( |
| 128 | args_end: [*]?[*]const u8, | 128 | args_end: [*]?[*]const u8, |
| 129 | resources_path: [*:0]const u8, | 129 | resources_path: [*:0]const u8, |
| 130 | ) Error { | 130 | ) Error { |
| 131 | var errors = @as([*]translate_c.ClangErrMsg, undefined)[0..0]; | 131 | var errors: []translate_c.ClangErrMsg = &[0]translate_c.ClangErrMsg{}; |
| 132 | out_ast.* = translate_c.translate(std.heap.c_allocator, args_begin, args_end, &errors, resources_path) catch |err| switch (err) { | 132 | out_ast.* = translate_c.translate(std.heap.c_allocator, args_begin, args_end, &errors, resources_path) catch |err| switch (err) { |
| 133 | error.SemanticAnalyzeFail => { | 133 | error.SemanticAnalyzeFail => { |
| 134 | out_errors_ptr.* = errors.ptr; | 134 | out_errors_ptr.* = errors.ptr; |
src/all_types.hpp+5| ... | @@ -231,6 +231,7 @@ enum ConstPtrSpecial { | ... | @@ -231,6 +231,7 @@ enum ConstPtrSpecial { |
| 231 | // The pointer is a reference to a single object. | 231 | // The pointer is a reference to a single object. |
| 232 | ConstPtrSpecialRef, | 232 | ConstPtrSpecialRef, |
| 233 | // The pointer points to an element in an underlying array. | 233 | // The pointer points to an element in an underlying array. |
| 234 | // Not to be confused with ConstPtrSpecialSubArray. | ||
| 234 | ConstPtrSpecialBaseArray, | 235 | ConstPtrSpecialBaseArray, |
| 235 | // The pointer points to a field in an underlying struct. | 236 | // The pointer points to a field in an underlying struct. |
| 236 | ConstPtrSpecialBaseStruct, | 237 | ConstPtrSpecialBaseStruct, |
| ... | @@ -257,6 +258,10 @@ enum ConstPtrSpecial { | ... | @@ -257,6 +258,10 @@ enum ConstPtrSpecial { |
| 257 | // types to be the same, so all optionals of pointer types use x_ptr | 258 | // types to be the same, so all optionals of pointer types use x_ptr |
| 258 | // instead of x_optional. | 259 | // instead of x_optional. |
| 259 | ConstPtrSpecialNull, | 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 | enum ConstPtrMut { | 267 | enum ConstPtrMut { |
src/analyze.cpp+7| ... | @@ -5280,6 +5280,11 @@ static uint32_t hash_const_val_ptr(ZigValue *const_val) { | ... | @@ -5280,6 +5280,11 @@ static uint32_t hash_const_val_ptr(ZigValue *const_val) { |
| 5280 | hash_val += hash_ptr(const_val->data.x_ptr.data.base_array.array_val); | 5280 | hash_val += hash_ptr(const_val->data.x_ptr.data.base_array.array_val); |
| 5281 | hash_val += hash_size(const_val->data.x_ptr.data.base_array.elem_index); | 5281 | hash_val += hash_size(const_val->data.x_ptr.data.base_array.elem_index); |
| 5282 | return hash_val; | 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 | case ConstPtrSpecialBaseStruct: | 5288 | case ConstPtrSpecialBaseStruct: |
| 5284 | hash_val += (uint32_t)3518317043; | 5289 | hash_val += (uint32_t)3518317043; |
| 5285 | hash_val += hash_ptr(const_val->data.x_ptr.data.base_struct.struct_val); | 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,6 +6751,7 @@ bool const_values_equal_ptr(ZigValue *a, ZigValue *b) { |
| 6746 | return false; | 6751 | return false; |
| 6747 | return true; | 6752 | return true; |
| 6748 | case ConstPtrSpecialBaseArray: | 6753 | case ConstPtrSpecialBaseArray: |
| 6754 | case ConstPtrSpecialSubArray: | ||
| 6749 | if (a->data.x_ptr.data.base_array.array_val != b->data.x_ptr.data.base_array.array_val) { | 6755 | if (a->data.x_ptr.data.base_array.array_val != b->data.x_ptr.data.base_array.array_val) { |
| 6750 | return false; | 6756 | return false; |
| 6751 | } | 6757 | } |
| ... | @@ -7003,6 +7009,7 @@ static void render_const_val_ptr(CodeGen *g, Buf *buf, ZigValue *const_val, ZigT | ... | @@ -7003,6 +7009,7 @@ static void render_const_val_ptr(CodeGen *g, Buf *buf, ZigValue *const_val, ZigT |
| 7003 | render_const_value(g, buf, const_ptr_pointee(nullptr, g, const_val, nullptr)); | 7009 | render_const_value(g, buf, const_ptr_pointee(nullptr, g, const_val, nullptr)); |
| 7004 | return; | 7010 | return; |
| 7005 | case ConstPtrSpecialBaseArray: | 7011 | case ConstPtrSpecialBaseArray: |
| 7012 | case ConstPtrSpecialSubArray: | ||
| 7006 | buf_appendf(buf, "*"); | 7013 | buf_appendf(buf, "*"); |
| 7007 | // TODO we need a source node for const_ptr_pointee because it can generate compile errors | 7014 | // TODO we need a source node for const_ptr_pointee because it can generate compile errors |
| 7008 | render_const_value(g, buf, const_ptr_pointee(nullptr, g, const_val, nullptr)); | 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,8 +5418,6 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutableGen *executable, IrI |
| 5418 | ZigType *array_type = array_ptr_type->data.pointer.child_type; | 5418 | ZigType *array_type = array_ptr_type->data.pointer.child_type; |
| 5419 | LLVMValueRef array_ptr = get_handle_value(g, array_ptr_ptr, array_type, array_ptr_type); | 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 | bool want_runtime_safety = instruction->safety_check_on && ir_want_runtime_safety(g, &instruction->base); | 5421 | bool want_runtime_safety = instruction->safety_check_on && ir_want_runtime_safety(g, &instruction->base); |
| 5424 | 5422 | ||
| 5425 | ZigType *result_type = instruction->base.value->type; | 5423 | ZigType *result_type = instruction->base.value->type; |
| ... | @@ -5472,6 +5470,8 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutableGen *executable, IrI | ... | @@ -5472,6 +5470,8 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutableGen *executable, IrI |
| 5472 | } | 5470 | } |
| 5473 | } | 5471 | } |
| 5474 | if (!type_has_bits(g, array_type)) { | 5472 | if (!type_has_bits(g, array_type)) { |
| 5473 | LLVMValueRef tmp_struct_ptr = ir_llvm_value(g, instruction->result_loc); | ||
| 5474 | |||
| 5475 | LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, slice_len_index, ""); | 5475 | LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, slice_len_index, ""); |
| 5476 | 5476 | ||
| 5477 | // TODO if runtime safety is on, store 0xaaaaaaa in ptr field | 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,20 +5486,20 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutableGen *executable, IrI |
| 5486 | }; | 5486 | }; |
| 5487 | LLVMValueRef slice_start_ptr = LLVMBuildInBoundsGEP(g->builder, array_ptr, indices, 2, ""); | 5487 | LLVMValueRef slice_start_ptr = LLVMBuildInBoundsGEP(g->builder, array_ptr, indices, 2, ""); |
| 5488 | if (result_type->id == ZigTypeIdPointer) { | 5488 | if (result_type->id == ZigTypeIdPointer) { |
| 5489 | ir_assert(instruction->result_loc == nullptr, &instruction->base); | ||
| 5489 | LLVMTypeRef result_ptr_type = get_llvm_type(g, result_type); | 5490 | LLVMTypeRef result_ptr_type = get_llvm_type(g, result_type); |
| 5490 | LLVMValueRef bitcasted = LLVMBuildBitCast(g->builder, slice_start_ptr, result_ptr_type, ""); | 5491 | return 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; | ||
| 5493 | } else { | 5492 | } else { |
| 5493 | LLVMValueRef tmp_struct_ptr = ir_llvm_value(g, instruction->result_loc); | ||
| 5494 | LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, slice_ptr_index, ""); | 5494 | LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, slice_ptr_index, ""); |
| 5495 | gen_store_untyped(g, slice_start_ptr, ptr_field_ptr, 0, false); | 5495 | gen_store_untyped(g, slice_start_ptr, ptr_field_ptr, 0, false); |
| 5496 | 5496 | ||
| 5497 | LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, slice_len_index, ""); | 5497 | LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, slice_len_index, ""); |
| 5498 | LLVMValueRef len_value = LLVMBuildNSWSub(g->builder, end_val, start_val, ""); | 5498 | LLVMValueRef len_value = LLVMBuildNSWSub(g->builder, end_val, start_val, ""); |
| 5499 | gen_store_untyped(g, len_value, len_field_ptr, 0, false); | 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 | } else if (array_type->id == ZigTypeIdPointer) { | 5503 | } else if (array_type->id == ZigTypeIdPointer) { |
| 5504 | assert(array_type->data.pointer.ptr_len != PtrLenSingle); | 5504 | assert(array_type->data.pointer.ptr_len != PtrLenSingle); |
| 5505 | LLVMValueRef start_val = ir_llvm_value(g, instruction->start); | 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,12 +5515,12 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutableGen *executable, IrI |
| 5515 | 5515 | ||
| 5516 | LLVMValueRef slice_start_ptr = LLVMBuildInBoundsGEP(g->builder, array_ptr, &start_val, 1, ""); | 5516 | LLVMValueRef slice_start_ptr = LLVMBuildInBoundsGEP(g->builder, array_ptr, &start_val, 1, ""); |
| 5517 | if (result_type->id == ZigTypeIdPointer) { | 5517 | if (result_type->id == ZigTypeIdPointer) { |
| 5518 | ir_assert(instruction->result_loc == nullptr, &instruction->base); | ||
| 5518 | LLVMTypeRef result_ptr_type = get_llvm_type(g, result_type); | 5519 | LLVMTypeRef result_ptr_type = get_llvm_type(g, result_type); |
| 5519 | LLVMValueRef bitcasted = LLVMBuildBitCast(g->builder, slice_start_ptr, result_ptr_type, ""); | 5520 | return LLVMBuildBitCast(g->builder, slice_start_ptr, result_ptr_type, ""); |
| 5520 | gen_store_untyped(g, bitcasted, tmp_struct_ptr, 0, false); | ||
| 5521 | return bitcasted; | ||
| 5522 | } | 5521 | } |
| 5523 | 5522 | ||
| 5523 | LLVMValueRef tmp_struct_ptr = ir_llvm_value(g, instruction->result_loc); | ||
| 5524 | if (type_has_bits(g, array_type)) { | 5524 | if (type_has_bits(g, array_type)) { |
| 5525 | size_t gen_ptr_index = result_type->data.structure.fields[slice_ptr_index]->gen_index; | 5525 | size_t gen_ptr_index = result_type->data.structure.fields[slice_ptr_index]->gen_index; |
| 5526 | LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, gen_ptr_index, ""); | 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,9 +5537,6 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutableGen *executable, IrI |
| 5537 | assert(array_type->data.structure.special == StructSpecialSlice); | 5537 | assert(array_type->data.structure.special == StructSpecialSlice); |
| 5538 | assert(LLVMGetTypeKind(LLVMTypeOf(array_ptr)) == LLVMPointerTypeKind); | 5538 | assert(LLVMGetTypeKind(LLVMTypeOf(array_ptr)) == LLVMPointerTypeKind); |
| 5539 | assert(LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(array_ptr))) == LLVMStructTypeKind); | 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 | size_t ptr_index = array_type->data.structure.fields[slice_ptr_index]->gen_index; | 5541 | size_t ptr_index = array_type->data.structure.fields[slice_ptr_index]->gen_index; |
| 5545 | assert(ptr_index != SIZE_MAX); | 5542 | assert(ptr_index != SIZE_MAX); |
| ... | @@ -5578,11 +5575,11 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutableGen *executable, IrI | ... | @@ -5578,11 +5575,11 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutableGen *executable, IrI |
| 5578 | 5575 | ||
| 5579 | LLVMValueRef slice_start_ptr = LLVMBuildInBoundsGEP(g->builder, src_ptr, &start_val, 1, ""); | 5576 | LLVMValueRef slice_start_ptr = LLVMBuildInBoundsGEP(g->builder, src_ptr, &start_val, 1, ""); |
| 5580 | if (result_type->id == ZigTypeIdPointer) { | 5577 | if (result_type->id == ZigTypeIdPointer) { |
| 5578 | ir_assert(instruction->result_loc == nullptr, &instruction->base); | ||
| 5581 | LLVMTypeRef result_ptr_type = get_llvm_type(g, result_type); | 5579 | LLVMTypeRef result_ptr_type = get_llvm_type(g, result_type); |
| 5582 | LLVMValueRef bitcasted = LLVMBuildBitCast(g->builder, slice_start_ptr, result_ptr_type, ""); | 5580 | return LLVMBuildBitCast(g->builder, slice_start_ptr, result_ptr_type, ""); |
| 5583 | gen_store_untyped(g, bitcasted, tmp_struct_ptr, 0, false); | ||
| 5584 | return bitcasted; | ||
| 5585 | } else { | 5581 | } else { |
| 5582 | LLVMValueRef tmp_struct_ptr = ir_llvm_value(g, instruction->result_loc); | ||
| 5586 | LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, (unsigned)ptr_index, ""); | 5583 | LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, (unsigned)ptr_index, ""); |
| 5587 | gen_store_untyped(g, slice_start_ptr, ptr_field_ptr, 0, false); | 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,7 +6673,6 @@ static LLVMValueRef gen_const_ptr_array_recursive(CodeGen *g, ZigValue *array_co |
| 6676 | }; | 6673 | }; |
| 6677 | return LLVMConstInBoundsGEP(base_ptr, indices, 2); | 6674 | return LLVMConstInBoundsGEP(base_ptr, indices, 2); |
| 6678 | } else { | 6675 | } else { |
| 6679 | assert(parent->id == ConstParentIdScalar); | ||
| 6680 | return base_ptr; | 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,6 +6900,7 @@ static LLVMValueRef gen_const_val_ptr(CodeGen *g, ZigValue *const_val, const cha |
| 6904 | return const_val->llvm_value; | 6900 | return const_val->llvm_value; |
| 6905 | } | 6901 | } |
| 6906 | case ConstPtrSpecialBaseArray: | 6902 | case ConstPtrSpecialBaseArray: |
| 6903 | case ConstPtrSpecialSubArray: | ||
| 6907 | { | 6904 | { |
| 6908 | ZigValue *array_const_val = const_val->data.x_ptr.data.base_array.array_val; | 6905 | ZigValue *array_const_val = const_val->data.x_ptr.data.base_array.array_val; |
| 6909 | assert(array_const_val->type->id == ZigTypeIdArray); | 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,14 +784,32 @@ static ZigValue *const_ptr_pointee_unchecked_no_isf(CodeGen *g, ZigValue *const_ |
| 784 | break; | 784 | break; |
| 785 | case ConstPtrSpecialBaseArray: { | 785 | case ConstPtrSpecialBaseArray: { |
| 786 | ZigValue *array_val = const_val->data.x_ptr.data.base_array.array_val; | 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 | result = array_val->type->data.array.sentinel; | 789 | result = array_val->type->data.array.sentinel; |
| 789 | } else { | 790 | } else { |
| 790 | expand_undef_array(g, array_val); | 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 | break; | 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 | case ConstPtrSpecialBaseStruct: { | 813 | case ConstPtrSpecialBaseStruct: { |
| 796 | ZigValue *struct_val = const_val->data.x_ptr.data.base_struct.struct_val; | 814 | ZigValue *struct_val = const_val->data.x_ptr.data.base_struct.struct_val; |
| 797 | expand_undef_struct(g, struct_val); | 815 | expand_undef_struct(g, struct_val); |
| ... | @@ -3727,8 +3745,8 @@ static IrInstGen *ir_build_slice_gen(IrAnalyze *ira, IrInst *source_instruction, | ... | @@ -3727,8 +3745,8 @@ static IrInstGen *ir_build_slice_gen(IrAnalyze *ira, IrInst *source_instruction, |
| 3727 | 3745 | ||
| 3728 | ir_ref_inst_gen(ptr, ira->new_irb.current_basic_block); | 3746 | ir_ref_inst_gen(ptr, ira->new_irb.current_basic_block); |
| 3729 | ir_ref_inst_gen(start, ira->new_irb.current_basic_block); | 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); | 3748 | if (end != nullptr) ir_ref_inst_gen(end, ira->new_irb.current_basic_block); |
| 3731 | ir_ref_inst_gen(result_loc, 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 | return &instruction->base; | 3751 | return &instruction->base; |
| 3734 | } | 3752 | } |
| ... | @@ -12672,40 +12690,63 @@ static IrInstGen *ir_resolve_ptr_of_array_to_slice(IrAnalyze *ira, IrInst* sourc | ... | @@ -12672,40 +12690,63 @@ static IrInstGen *ir_resolve_ptr_of_array_to_slice(IrAnalyze *ira, IrInst* sourc |
| 12672 | Error err; | 12690 | Error err; |
| 12673 | 12691 | ||
| 12674 | assert(array_ptr->value->type->id == ZigTypeIdPointer); | 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))) { | 12695 | ZigType *array_type = array_ptr->value->type->data.pointer.child_type; |
| 12677 | return ira->codegen->invalid_inst_gen; | 12696 | const size_t array_len = array_type->data.array.len; |
| 12678 | } | ||
| 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 | 12712 | if ((err = type_resolve(ira->codegen, array_ptr->value->type, ResolveStatusAlignmentKnown))) { |
| 12685 | // alignment | 12713 | return ira->codegen->invalid_inst_gen; |
| 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)); | ||
| 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 | if (instr_is_comptime(array_ptr)) { | 12719 | if (instr_is_comptime(array_ptr)) { |
| 12692 | ZigValue *array_ptr_val = ir_resolve_const(ira, array_ptr, UndefBad); | 12720 | ZigValue *array_ptr_val = ir_resolve_const(ira, array_ptr, UndefBad); |
| 12693 | if (array_ptr_val == nullptr) | 12721 | if (array_ptr_val == nullptr) |
| 12694 | return ira->codegen->invalid_inst_gen; | 12722 | return ira->codegen->invalid_inst_gen; |
| 12695 | ZigValue *pointee = const_ptr_pointee(ira, ira->codegen, array_ptr_val, source_instr->source_node); | 12723 | ir_assert(is_slice(wanted_type), source_instr); |
| 12696 | if (pointee == nullptr) | 12724 | bool wanted_const = wanted_type->data.structure.fields[slice_ptr_index]->type_entry->data.pointer.is_const; |
| 12697 | return ira->codegen->invalid_inst_gen; | 12725 | // Optimization to avoid creating unnecessary ZigValue in const_ptr_pointee |
| 12698 | if (pointee->special != ConstValSpecialRuntime) { | 12726 | if (array_ptr_val->data.x_ptr.special == ConstPtrSpecialSubArray) { |
| 12699 | assert(array_ptr_val->type->id == ZigTypeIdPointer); | 12727 | ZigValue *array_val = array_ptr_val->data.x_ptr.data.base_array.array_val; |
| 12700 | ZigType *array_type = array_ptr_val->type->data.pointer.child_type; | 12728 | if (array_val->special != ConstValSpecialRuntime) { |
| 12701 | assert(is_slice(wanted_type)); | 12729 | IrInstGen *result = ir_const(ira, source_instr, wanted_type); |
| 12702 | bool is_const = wanted_type->data.structure.fields[slice_ptr_index]->type_entry->data.pointer.is_const; | 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); | 12744 | 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); | 12745 | init_const_slice(ira->codegen, result->value, pointee, 0, array_type->data.array.len, wanted_const); |
| 12706 | result->value->data.x_struct.fields[slice_ptr_index]->data.x_ptr.mut = array_ptr_val->data.x_ptr.mut; | 12746 | 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; | 12747 | result->value->type = wanted_type; |
| 12708 | return result; | 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,6 +19972,7 @@ static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source |
| 19931 | dst_size, buf_ptr(&pointee->type->name), src_size)); | 19972 | dst_size, buf_ptr(&pointee->type->name), src_size)); |
| 19932 | return ErrorSemanticAnalyzeFail; | 19973 | return ErrorSemanticAnalyzeFail; |
| 19933 | } | 19974 | } |
| 19975 | case ConstPtrSpecialSubArray: | ||
| 19934 | case ConstPtrSpecialBaseArray: { | 19976 | case ConstPtrSpecialBaseArray: { |
| 19935 | ZigValue *array_val = ptr_val->data.x_ptr.data.base_array.array_val; | 19977 | ZigValue *array_val = ptr_val->data.x_ptr.data.base_array.array_val; |
| 19936 | assert(array_val->type->id == ZigTypeIdArray); | 19978 | assert(array_val->type->id == ZigTypeIdArray); |
| ... | @@ -20814,6 +20856,7 @@ static IrInstGen *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstSrcElemP | ... | @@ -20814,6 +20856,7 @@ static IrInstGen *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstSrcElemP |
| 20814 | } | 20856 | } |
| 20815 | break; | 20857 | break; |
| 20816 | case ConstPtrSpecialBaseArray: | 20858 | case ConstPtrSpecialBaseArray: |
| 20859 | case ConstPtrSpecialSubArray: | ||
| 20817 | { | 20860 | { |
| 20818 | size_t offset = array_ptr_val->data.x_ptr.data.base_array.elem_index; | 20861 | size_t offset = array_ptr_val->data.x_ptr.data.base_array.elem_index; |
| 20819 | new_index = offset + index; | 20862 | new_index = offset + index; |
| ... | @@ -20884,6 +20927,7 @@ static IrInstGen *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstSrcElemP | ... | @@ -20884,6 +20927,7 @@ static IrInstGen *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstSrcElemP |
| 20884 | out_val->data.x_ptr.special = ConstPtrSpecialRef; | 20927 | out_val->data.x_ptr.special = ConstPtrSpecialRef; |
| 20885 | out_val->data.x_ptr.data.ref.pointee = ptr_field->data.x_ptr.data.ref.pointee; | 20928 | out_val->data.x_ptr.data.ref.pointee = ptr_field->data.x_ptr.data.ref.pointee; |
| 20886 | break; | 20929 | break; |
| 20930 | case ConstPtrSpecialSubArray: | ||
| 20887 | case ConstPtrSpecialBaseArray: | 20931 | case ConstPtrSpecialBaseArray: |
| 20888 | { | 20932 | { |
| 20889 | size_t offset = ptr_field->data.x_ptr.data.base_array.elem_index; | 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,6 +25938,7 @@ static IrInstGen *ir_analyze_instruction_memset(IrAnalyze *ira, IrInstSrcMemset |
| 25894 | start = 0; | 25938 | start = 0; |
| 25895 | bound_end = 1; | 25939 | bound_end = 1; |
| 25896 | break; | 25940 | break; |
| 25941 | case ConstPtrSpecialSubArray: | ||
| 25897 | case ConstPtrSpecialBaseArray: | 25942 | case ConstPtrSpecialBaseArray: |
| 25898 | { | 25943 | { |
| 25899 | ZigValue *array_val = dest_ptr_val->data.x_ptr.data.base_array.array_val; | 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,6 +26072,7 @@ static IrInstGen *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstSrcMemcpy |
| 26027 | dest_start = 0; | 26072 | dest_start = 0; |
| 26028 | dest_end = 1; | 26073 | dest_end = 1; |
| 26029 | break; | 26074 | break; |
| 26075 | case ConstPtrSpecialSubArray: | ||
| 26030 | case ConstPtrSpecialBaseArray: | 26076 | case ConstPtrSpecialBaseArray: |
| 26031 | { | 26077 | { |
| 26032 | ZigValue *array_val = dest_ptr_val->data.x_ptr.data.base_array.array_val; | 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,6 +26116,7 @@ static IrInstGen *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstSrcMemcpy |
| 26070 | src_start = 0; | 26116 | src_start = 0; |
| 26071 | src_end = 1; | 26117 | src_end = 1; |
| 26072 | break; | 26118 | break; |
| 26119 | case ConstPtrSpecialSubArray: | ||
| 26073 | case ConstPtrSpecialBaseArray: | 26120 | case ConstPtrSpecialBaseArray: |
| 26074 | { | 26121 | { |
| 26075 | ZigValue *array_val = src_ptr_val->data.x_ptr.data.base_array.array_val; | 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,7 +26266,8 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i |
| 26219 | ZigType *return_type; | 26266 | ZigType *return_type; |
| 26220 | 26267 | ||
| 26221 | if (value_is_comptime(casted_start->value) && | 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 | ZigValue *start_val = ir_resolve_const(ira, casted_start, UndefBad); | 26272 | ZigValue *start_val = ir_resolve_const(ira, casted_start, UndefBad); |
| 26225 | if (!start_val) | 26273 | if (!start_val) |
| ... | @@ -26244,13 +26292,16 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i | ... | @@ -26244,13 +26292,16 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i |
| 26244 | return ira->codegen->invalid_inst_gen; | 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 | ZigType *return_array_type = get_array_type(ira->codegen, elem_type, end_scalar - start_scalar, | 26299 | ZigType *return_array_type = get_array_type(ira->codegen, elem_type, end_scalar - start_scalar, |
| 26248 | array_sentinel); | 26300 | array_sentinel); |
| 26249 | return_type = get_pointer_to_type_extra(ira->codegen, return_array_type, | 26301 | return_type = get_pointer_to_type_extra(ira->codegen, return_array_type, |
| 26250 | non_sentinel_slice_ptr_type->data.pointer.is_const, | 26302 | non_sentinel_slice_ptr_type->data.pointer.is_const, |
| 26251 | non_sentinel_slice_ptr_type->data.pointer.is_volatile, | 26303 | non_sentinel_slice_ptr_type->data.pointer.is_volatile, |
| 26252 | PtrLenSingle, | 26304 | PtrLenSingle, ptr_byte_alignment, 0, 0, false); |
| 26253 | 0, 0, 0, false); | ||
| 26254 | } else if (sentinel_val != nullptr) { | 26305 | } else if (sentinel_val != nullptr) { |
| 26255 | ZigType *slice_ptr_type = adjust_ptr_sentinel(ira->codegen, non_sentinel_slice_ptr_type, sentinel_val); | 26306 | ZigType *slice_ptr_type = adjust_ptr_sentinel(ira->codegen, non_sentinel_slice_ptr_type, sentinel_val); |
| 26256 | return_type = get_slice_type(ira->codegen, slice_ptr_type); | 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,6 +26334,10 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i |
| 26283 | abs_offset = 0; | 26334 | abs_offset = 0; |
| 26284 | rel_end = SIZE_MAX; | 26335 | rel_end = SIZE_MAX; |
| 26285 | ptr_is_undef = true; | 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 | } else { | 26341 | } else { |
| 26287 | array_val = const_ptr_pointee(ira, ira->codegen, parent_ptr, instruction->base.base.source_node); | 26342 | array_val = const_ptr_pointee(ira, ira->codegen, parent_ptr, instruction->base.base.source_node); |
| 26288 | if (array_val == nullptr) | 26343 | if (array_val == nullptr) |
| ... | @@ -26325,6 +26380,7 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i | ... | @@ -26325,6 +26380,7 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i |
| 26325 | rel_end = 1; | 26380 | rel_end = 1; |
| 26326 | } | 26381 | } |
| 26327 | break; | 26382 | break; |
| 26383 | case ConstPtrSpecialSubArray: | ||
| 26328 | case ConstPtrSpecialBaseArray: | 26384 | case ConstPtrSpecialBaseArray: |
| 26329 | array_val = parent_ptr->data.x_ptr.data.base_array.array_val; | 26385 | array_val = parent_ptr->data.x_ptr.data.base_array.array_val; |
| 26330 | abs_offset = parent_ptr->data.x_ptr.data.base_array.elem_index; | 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,6 +26431,7 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i |
| 26375 | abs_offset = SIZE_MAX; | 26431 | abs_offset = SIZE_MAX; |
| 26376 | rel_end = 1; | 26432 | rel_end = 1; |
| 26377 | break; | 26433 | break; |
| 26434 | case ConstPtrSpecialSubArray: | ||
| 26378 | case ConstPtrSpecialBaseArray: | 26435 | case ConstPtrSpecialBaseArray: |
| 26379 | array_val = parent_ptr->data.x_ptr.data.base_array.array_val; | 26436 | array_val = parent_ptr->data.x_ptr.data.base_array.array_val; |
| 26380 | abs_offset = parent_ptr->data.x_ptr.data.base_array.elem_index; | 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,6 +26511,9 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i |
| 26454 | if (array_val) { | 26511 | if (array_val) { |
| 26455 | size_t index = abs_offset + start_scalar; | 26512 | size_t index = abs_offset + start_scalar; |
| 26456 | init_const_ptr_array(ira->codegen, ptr_val, array_val, index, return_type_is_const, PtrLenUnknown); | 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 | if (array_type->id == ZigTypeIdArray) { | 26517 | if (array_type->id == ZigTypeIdArray) { |
| 26458 | ptr_val->data.x_ptr.mut = ptr_ptr->value->data.x_ptr.mut; | 26518 | ptr_val->data.x_ptr.mut = ptr_ptr->value->data.x_ptr.mut; |
| 26459 | } else if (is_slice(array_type)) { | 26519 | } else if (is_slice(array_type)) { |
| ... | @@ -26463,7 +26523,7 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i | ... | @@ -26463,7 +26523,7 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i |
| 26463 | } | 26523 | } |
| 26464 | } else if (ptr_is_undef) { | 26524 | } else if (ptr_is_undef) { |
| 26465 | ptr_val->type = get_pointer_to_type(ira->codegen, parent_ptr->type->data.pointer.child_type, | 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 | ptr_val->special = ConstValSpecialUndef; | 26527 | ptr_val->special = ConstValSpecialUndef; |
| 26468 | } else switch (parent_ptr->data.x_ptr.special) { | 26528 | } else switch (parent_ptr->data.x_ptr.special) { |
| 26469 | case ConstPtrSpecialInvalid: | 26529 | case ConstPtrSpecialInvalid: |
| ... | @@ -26473,6 +26533,7 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i | ... | @@ -26473,6 +26533,7 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i |
| 26473 | init_const_ptr_ref(ira->codegen, ptr_val, parent_ptr->data.x_ptr.data.ref.pointee, | 26533 | init_const_ptr_ref(ira->codegen, ptr_val, parent_ptr->data.x_ptr.data.ref.pointee, |
| 26474 | return_type_is_const); | 26534 | return_type_is_const); |
| 26475 | break; | 26535 | break; |
| 26536 | case ConstPtrSpecialSubArray: | ||
| 26476 | case ConstPtrSpecialBaseArray: | 26537 | case ConstPtrSpecialBaseArray: |
| 26477 | zig_unreachable(); | 26538 | zig_unreachable(); |
| 26478 | case ConstPtrSpecialBaseStruct: | 26539 | case ConstPtrSpecialBaseStruct: |
| ... | @@ -26500,20 +26561,6 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i | ... | @@ -26500,20 +26561,6 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i |
| 26500 | return result; | 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 | if (generate_non_null_assert) { | 26564 | if (generate_non_null_assert) { |
| 26518 | IrInstGen *ptr_val = ir_get_deref(ira, &instruction->base.base, ptr_ptr, nullptr); | 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,6 +26570,24 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i |
| 26523 | ir_build_assert_non_null(ira, &instruction->base.base, ptr_val); | 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 | return ir_build_slice_gen(ira, &instruction->base.base, return_type, ptr_ptr, | 26591 | return ir_build_slice_gen(ira, &instruction->base.base, return_type, ptr_ptr, |
| 26527 | casted_start, end, instruction->safety_check_on, result_loc); | 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,18 +171,19 @@ test "runtime known array index has best alignment possible" { |
| 171 | 171 | ||
| 172 | // because pointer is align 2 and u32 align % 2 == 0 we can assume align 2 | 172 | // because pointer is align 2 and u32 align % 2 == 0 we can assume align 2 |
| 173 | var smaller align(2) = [_]u32{ 1, 2, 3, 4 }; | 173 | var smaller align(2) = [_]u32{ 1, 2, 3, 4 }; |
| 174 | comptime expect(@TypeOf(smaller[0..]) == []align(2) u32); | 174 | var runtime_zero: usize = 0; |
| 175 | comptime expect(@TypeOf(smaller[0..].ptr) == [*]align(2) u32); | 175 | comptime expect(@TypeOf(smaller[runtime_zero..]) == []align(2) u32); |
| 176 | testIndex(smaller[0..].ptr, 0, *align(2) u32); | 176 | comptime expect(@TypeOf(smaller[runtime_zero..].ptr) == [*]align(2) u32); |
| 177 | testIndex(smaller[0..].ptr, 1, *align(2) u32); | 177 | testIndex(smaller[runtime_zero..].ptr, 0, *align(2) u32); |
| 178 | testIndex(smaller[0..].ptr, 2, *align(2) u32); | 178 | testIndex(smaller[runtime_zero..].ptr, 1, *align(2) u32); |
| 179 | testIndex(smaller[0..].ptr, 3, *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 | // has to use ABI alignment because index known at runtime only | 182 | // has to use ABI alignment because index known at runtime only |
| 182 | testIndex2(array[0..].ptr, 0, *u8); | 183 | testIndex2(array[runtime_zero..].ptr, 0, *u8); |
| 183 | testIndex2(array[0..].ptr, 1, *u8); | 184 | testIndex2(array[runtime_zero..].ptr, 1, *u8); |
| 184 | testIndex2(array[0..].ptr, 2, *u8); | 185 | testIndex2(array[runtime_zero..].ptr, 2, *u8); |
| 185 | testIndex2(array[0..].ptr, 3, *u8); | 186 | testIndex2(array[runtime_zero..].ptr, 3, *u8); |
| 186 | } | 187 | } |
| 187 | fn testIndex(smaller: [*]align(2) u32, index: usize, comptime T: type) void { | 188 | fn testIndex(smaller: [*]align(2) u32, index: usize, comptime T: type) void { |
| 188 | comptime expect(@TypeOf(&smaller[index]) == T); | 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,7 +435,8 @@ fn incrementVoidPtrValue(value: ?*c_void) void { |
| 435 | 435 | ||
| 436 | test "implicit cast from [*]T to ?*c_void" { | 436 | test "implicit cast from [*]T to ?*c_void" { |
| 437 | var a = [_]u8{ 3, 2, 1 }; | 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 | expect(std.mem.eql(u8, &a, &[_]u8{ 4, 3, 2 })); | 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,7 +524,7 @@ test "comptime slice of slice preserves comptime var" { |
| 524 | test "comptime slice of pointer preserves comptime var" { | 524 | test "comptime slice of pointer preserves comptime var" { |
| 525 | comptime { | 525 | comptime { |
| 526 | var buff: [10]u8 = undefined; | 526 | var buff: [10]u8 = undefined; |
| 527 | var a = buff[0..].ptr; | 527 | var a = @ptrCast([*]u8, &buff); |
| 528 | a[0..1][0] = 1; | 528 | a[0..1][0] = 1; |
| 529 | expect(buff[0..][0..][0] == 1); | 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,8 +102,8 @@ test "memcpy and memset intrinsics" { |
| 102 | var foo: [20]u8 = undefined; | 102 | var foo: [20]u8 = undefined; |
| 103 | var bar: [20]u8 = undefined; | 103 | var bar: [20]u8 = undefined; |
| 104 | 104 | ||
| 105 | @memset(foo[0..].ptr, 'A', foo.len); | 105 | @memset(&foo, 'A', foo.len); |
| 106 | @memcpy(bar[0..].ptr, foo[0..].ptr, bar.len); | 106 | @memcpy(&bar, &foo, bar.len); |
| 107 | 107 | ||
| 108 | if (bar[11] != 'A') unreachable; | 108 | if (bar[11] != 'A') unreachable; |
| 109 | } | 109 | } |
| ... | @@ -565,12 +565,16 @@ test "volatile load and store" { | ... | @@ -565,12 +565,16 @@ test "volatile load and store" { |
| 565 | expect(ptr.* == 1235); | 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 | comptime { | 569 | comptime { |
| 570 | expect(@TypeOf("aoeu"[0..]) == []const u8); | 570 | expect(@TypeOf("aoeu"[0..]) == *const [4:0]u8); |
| 571 | const array = [_]i32{ 1, 2, 3, 4 }; | 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 | test "pointer child field" { | 580 | test "pointer child field" { |
test/stage1/behavior/ptrcast.zig+1-1| ... | @@ -13,7 +13,7 @@ fn testReinterpretBytesAsInteger() void { | ... | @@ -13,7 +13,7 @@ fn testReinterpretBytesAsInteger() void { |
| 13 | builtin.Endian.Little => 0xab785634, | 13 | builtin.Endian.Little => 0xab785634, |
| 14 | builtin.Endian.Big => 0x345678ab, | 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 | test "reinterpret bytes of an array into an extern struct" { | 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 +7,7 @@ const mem = std.mem; |
| 7 | const x = @intToPtr([*]i32, 0x1000)[0..0x500]; | 7 | const x = @intToPtr([*]i32, 0x1000)[0..0x500]; |
| 8 | const y = x[0x100..]; | 8 | const y = x[0x100..]; |
| 9 | test "compile time slice of pointer to hard coded address" { | 9 | test "compile time slice of pointer to hard coded address" { |
| 10 | expect(@ptrToInt(x.ptr) == 0x1000); | 10 | expect(@ptrToInt(x) == 0x1000); |
| 11 | expect(x.len == 0x500); | 11 | expect(x.len == 0x500); |
| 12 | 12 | ||
| 13 | expect(@ptrToInt(y.ptr) == 0x1100); | 13 | expect(@ptrToInt(y.ptr) == 0x1100); |
| ... | @@ -47,7 +47,9 @@ test "C pointer slice access" { | ... | @@ -47,7 +47,9 @@ test "C pointer slice access" { |
| 47 | var buf: [10]u32 = [1]u32{42} ** 10; | 47 | var buf: [10]u32 = [1]u32{42} ** 10; |
| 48 | const c_ptr = @ptrCast([*c]const u32, &buf); | 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 | for (c_ptr[0..5]) |*cl| { | 54 | for (c_ptr[0..5]) |*cl| { |
| 53 | expectEqual(@as(u32, 42), cl.*); | 55 | expectEqual(@as(u32, 42), cl.*); |
| ... | @@ -107,7 +109,9 @@ test "obtaining a null terminated slice" { | ... | @@ -107,7 +109,9 @@ test "obtaining a null terminated slice" { |
| 107 | const ptr2 = buf[0..runtime_len :0]; | 109 | const ptr2 = buf[0..runtime_len :0]; |
| 108 | // ptr2 is a null-terminated slice | 110 | // ptr2 is a null-terminated slice |
| 109 | comptime expect(@TypeOf(ptr2) == [:0]u8); | 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 | test "empty array to slice" { | 117 | test "empty array to slice" { |
test/stage1/behavior/struct.zig+2-2| ... | @@ -409,8 +409,8 @@ const Bitfields = packed struct { | ... | @@ -409,8 +409,8 @@ const Bitfields = packed struct { |
| 409 | test "native bit field understands endianness" { | 409 | test "native bit field understands endianness" { |
| 410 | var all: u64 = 0x7765443322221111; | 410 | var all: u64 = 0x7765443322221111; |
| 411 | var bytes: [8]u8 = undefined; | 411 | var bytes: [8]u8 = undefined; |
| 412 | @memcpy(bytes[0..].ptr, @ptrCast([*]u8, &all), 8); | 412 | @memcpy(&bytes, @ptrCast([*]u8, &all), 8); |
| 413 | var bitfields = @ptrCast(*Bitfields, bytes[0..].ptr).*; | 413 | var bitfields = @ptrCast(*Bitfields, &bytes).*; |
| 414 | 414 | ||
| 415 | expect(bitfields.f1 == 0x1111); | 415 | expect(bitfields.f1 == 0x1111); |
| 416 | expect(bitfields.f2 == 0x2222); | 416 | expect(bitfields.f2 == 0x2222); |