| ... | @@ -2503,6 +2503,13 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com | ... | @@ -2503,6 +2503,13 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com |
| 2503 | try sema.requireRuntimeBlock(block, src); | 2503 | try sema.requireRuntimeBlock(block, src); |
| 2504 | try sema.resolveTypeLayout(block, ty_src, final_elem_ty); | 2504 | try sema.resolveTypeLayout(block, ty_src, final_elem_ty); |
| 2505 | | 2505 | |
| | 2506 | const final_ptr_ty = try Type.ptr(sema.arena, .{ |
| | 2507 | .pointee_type = final_elem_ty, |
| | 2508 | .mutable = var_is_mut, |
| | 2509 | .@"align" = inferred_alloc.data.alignment, |
| | 2510 | .@"addrspace" = target_util.defaultAddressSpace(target, .local), |
| | 2511 | }); |
| | 2512 | |
| 2506 | if (var_is_mut) { | 2513 | if (var_is_mut) { |
| 2507 | try sema.validateVarType(block, ty_src, final_elem_ty, false); | 2514 | try sema.validateVarType(block, ty_src, final_elem_ty, false); |
| 2508 | } else ct: { | 2515 | } else ct: { |
| ... | @@ -2534,8 +2541,6 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com | ... | @@ -2534,8 +2541,6 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com |
| 2534 | if (store_op.lhs != Air.indexToRef(bitcast_inst)) break :ct; | 2541 | if (store_op.lhs != Air.indexToRef(bitcast_inst)) break :ct; |
| 2535 | if (air_datas[bitcast_inst].ty_op.operand != Air.indexToRef(const_inst)) break :ct; | 2542 | if (air_datas[bitcast_inst].ty_op.operand != Air.indexToRef(const_inst)) break :ct; |
| 2536 | | 2543 | |
| 2537 | const bitcast_ty_ref = air_datas[bitcast_inst].ty_op.ty; | | |
| 2538 | | | |
| 2539 | const new_decl = d: { | 2544 | const new_decl = d: { |
| 2540 | var anon_decl = try block.startAnonDecl(src); | 2545 | var anon_decl = try block.startAnonDecl(src); |
| 2541 | defer anon_decl.deinit(); | 2546 | defer anon_decl.deinit(); |
| ... | @@ -2551,17 +2556,15 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com | ... | @@ -2551,17 +2556,15 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com |
| 2551 | // block so that codegen does not see it. | 2556 | // block so that codegen does not see it. |
| 2552 | block.instructions.shrinkRetainingCapacity(block.instructions.items.len - 3); | 2557 | block.instructions.shrinkRetainingCapacity(block.instructions.items.len - 3); |
| 2553 | sema.air_values.items[value_index] = try Value.Tag.decl_ref.create(sema.arena, new_decl); | 2558 | sema.air_values.items[value_index] = try Value.Tag.decl_ref.create(sema.arena, new_decl); |
| 2554 | air_datas[ptr_inst].ty_pl.ty = bitcast_ty_ref; | 2559 | // Would be nice if we could just assign `bitcast_ty_ref` to |
| | 2560 | // `air_datas[ptr_inst].ty_pl.ty`, wouldn't it? Alas, that is almost correct, |
| | 2561 | // except that the pointer is mutable and we need to make it constant here. |
| | 2562 | air_datas[ptr_inst].ty_pl.ty = try sema.addType(final_ptr_ty); |
| 2555 | | 2563 | |
| 2556 | return; | 2564 | return; |
| 2557 | } | 2565 | } |
| 2558 | | 2566 | |
| 2559 | // Change it to a normal alloc. | 2567 | // Change it to a normal alloc. |
| 2560 | const final_ptr_ty = try Type.ptr(sema.arena, .{ | | |
| 2561 | .pointee_type = final_elem_ty, | | |
| 2562 | .@"align" = inferred_alloc.data.alignment, | | |
| 2563 | .@"addrspace" = target_util.defaultAddressSpace(target, .local), | | |
| 2564 | }); | | |
| 2565 | sema.air_instructions.set(ptr_inst, .{ | 2568 | sema.air_instructions.set(ptr_inst, .{ |
| 2566 | .tag = .alloc, | 2569 | .tag = .alloc, |
| 2567 | .data = .{ .ty = final_ptr_ty }, | 2570 | .data = .{ .ty = final_ptr_ty }, |
| ... | @@ -15609,12 +15612,16 @@ fn analyzeSlice( | ... | @@ -15609,12 +15612,16 @@ fn analyzeSlice( |
| 15609 | var slice_ty = ptr_ptr_ty; | 15612 | var slice_ty = ptr_ptr_ty; |
| 15610 | var ptr_or_slice = ptr_ptr; | 15613 | var ptr_or_slice = ptr_ptr; |
| 15611 | var elem_ty = ptr_ptr_child_ty.childType(); | 15614 | var elem_ty = ptr_ptr_child_ty.childType(); |
| | 15615 | var ptr_sentinel: ?Value = null; |
| 15612 | switch (ptr_ptr_child_ty.zigTypeTag()) { | 15616 | switch (ptr_ptr_child_ty.zigTypeTag()) { |
| 15613 | .Array => {}, | 15617 | .Array => { |
| | 15618 | ptr_sentinel = ptr_ptr_child_ty.sentinel(); |
| | 15619 | }, |
| 15614 | .Pointer => switch (ptr_ptr_child_ty.ptrSize()) { | 15620 | .Pointer => switch (ptr_ptr_child_ty.ptrSize()) { |
| 15615 | .One => { | 15621 | .One => { |
| 15616 | const double_child_ty = ptr_ptr_child_ty.childType(); | 15622 | const double_child_ty = ptr_ptr_child_ty.childType(); |
| 15617 | if (double_child_ty.zigTypeTag() == .Array) { | 15623 | if (double_child_ty.zigTypeTag() == .Array) { |
| | 15624 | ptr_sentinel = double_child_ty.sentinel(); |
| 15618 | ptr_or_slice = try sema.analyzeLoad(block, src, ptr_ptr, ptr_src); | 15625 | ptr_or_slice = try sema.analyzeLoad(block, src, ptr_ptr, ptr_src); |
| 15619 | slice_ty = ptr_ptr_child_ty; | 15626 | slice_ty = ptr_ptr_child_ty; |
| 15620 | array_ty = double_child_ty; | 15627 | array_ty = double_child_ty; |
| ... | @@ -15624,12 +15631,14 @@ fn analyzeSlice( | ... | @@ -15624,12 +15631,14 @@ fn analyzeSlice( |
| 15624 | } | 15631 | } |
| 15625 | }, | 15632 | }, |
| 15626 | .Many, .C => { | 15633 | .Many, .C => { |
| | 15634 | ptr_sentinel = ptr_ptr_child_ty.sentinel(); |
| 15627 | ptr_or_slice = try sema.analyzeLoad(block, src, ptr_ptr, ptr_src); | 15635 | ptr_or_slice = try sema.analyzeLoad(block, src, ptr_ptr, ptr_src); |
| 15628 | slice_ty = ptr_ptr_child_ty; | 15636 | slice_ty = ptr_ptr_child_ty; |
| 15629 | array_ty = ptr_ptr_child_ty; | 15637 | array_ty = ptr_ptr_child_ty; |
| 15630 | elem_ty = ptr_ptr_child_ty.childType(); | 15638 | elem_ty = ptr_ptr_child_ty.childType(); |
| 15631 | }, | 15639 | }, |
| 15632 | .Slice => { | 15640 | .Slice => { |
| | 15641 | ptr_sentinel = ptr_ptr_child_ty.sentinel(); |
| 15633 | ptr_or_slice = try sema.analyzeLoad(block, src, ptr_ptr, ptr_src); | 15642 | ptr_or_slice = try sema.analyzeLoad(block, src, ptr_ptr, ptr_src); |
| 15634 | slice_ty = ptr_ptr_child_ty; | 15643 | slice_ty = ptr_ptr_child_ty; |
| 15635 | array_ty = ptr_ptr_child_ty; | 15644 | array_ty = ptr_ptr_child_ty; |
| ... | @@ -15647,29 +15656,67 @@ fn analyzeSlice( | ... | @@ -15647,29 +15656,67 @@ fn analyzeSlice( |
| 15647 | const start = try sema.coerce(block, Type.usize, uncasted_start, start_src); | 15656 | const start = try sema.coerce(block, Type.usize, uncasted_start, start_src); |
| 15648 | const new_ptr = try analyzePtrArithmetic(sema, block, src, ptr, start, .ptr_add, ptr_src, start_src); | 15657 | const new_ptr = try analyzePtrArithmetic(sema, block, src, ptr, start, .ptr_add, ptr_src, start_src); |
| 15649 | | 15658 | |
| | 15659 | // true if and only if the end index of the slice, implicitly or explicitly, equals |
| | 15660 | // the length of the underlying object being sliced. we might learn the length of the |
| | 15661 | // underlying object because it is an array (which has the length in the type), or |
| | 15662 | // we might learn of the length because it is a comptime-known slice value. |
| | 15663 | var end_is_len = uncasted_end_opt == .none; |
| 15650 | const end = e: { | 15664 | const end = e: { |
| 15651 | if (uncasted_end_opt != .none) { | | |
| 15652 | break :e try sema.coerce(block, Type.usize, uncasted_end_opt, end_src); | | |
| 15653 | } | | |
| 15654 | | | |
| 15655 | if (array_ty.zigTypeTag() == .Array) { | 15665 | if (array_ty.zigTypeTag() == .Array) { |
| 15656 | break :e try sema.addConstant( | 15666 | const len_val = try Value.Tag.int_u64.create(sema.arena, array_ty.arrayLen()); |
| 15657 | Type.usize, | 15667 | |
| 15658 | try Value.Tag.int_u64.create(sema.arena, array_ty.arrayLen()), | 15668 | if (!end_is_len) { |
| 15659 | ); | 15669 | const end = try sema.coerce(block, Type.usize, uncasted_end_opt, end_src); |
| | 15670 | if (try sema.resolveMaybeUndefVal(block, end_src, end)) |end_val| { |
| | 15671 | if (end_val.eql(len_val, Type.usize)) { |
| | 15672 | end_is_len = true; |
| | 15673 | } |
| | 15674 | } |
| | 15675 | break :e end; |
| | 15676 | } |
| | 15677 | |
| | 15678 | break :e try sema.addConstant(Type.usize, len_val); |
| 15660 | } else if (slice_ty.isSlice()) { | 15679 | } else if (slice_ty.isSlice()) { |
| | 15680 | if (!end_is_len) { |
| | 15681 | const end = try sema.coerce(block, Type.usize, uncasted_end_opt, end_src); |
| | 15682 | if (try sema.resolveDefinedValue(block, end_src, end)) |end_val| { |
| | 15683 | if (try sema.resolveDefinedValue(block, src, ptr_or_slice)) |slice_val| { |
| | 15684 | var int_payload: Value.Payload.U64 = .{ |
| | 15685 | .base = .{ .tag = .int_u64 }, |
| | 15686 | .data = slice_val.sliceLen(), |
| | 15687 | }; |
| | 15688 | const slice_len_val = Value.initPayload(&int_payload.base); |
| | 15689 | if (end_val.eql(slice_len_val, Type.usize)) { |
| | 15690 | end_is_len = true; |
| | 15691 | } |
| | 15692 | } |
| | 15693 | } |
| | 15694 | break :e end; |
| | 15695 | } |
| 15661 | break :e try sema.analyzeSliceLen(block, src, ptr_or_slice); | 15696 | break :e try sema.analyzeSliceLen(block, src, ptr_or_slice); |
| 15662 | } | 15697 | } |
| | 15698 | if (!end_is_len) { |
| | 15699 | break :e try sema.coerce(block, Type.usize, uncasted_end_opt, end_src); |
| | 15700 | } |
| 15663 | return sema.fail(block, end_src, "slice of pointer must include end value", .{}); | 15701 | return sema.fail(block, end_src, "slice of pointer must include end value", .{}); |
| 15664 | }; | 15702 | }; |
| 15665 | | 15703 | |
| 15666 | const slice_sentinel = if (sentinel_opt != .none) blk: { | 15704 | const sentinel = s: { |
| 15667 | const casted = try sema.coerce(block, elem_ty, sentinel_opt, sentinel_src); | 15705 | if (sentinel_opt != .none) { |
| 15668 | break :blk try sema.resolveConstValue(block, sentinel_src, casted); | 15706 | const casted = try sema.coerce(block, elem_ty, sentinel_opt, sentinel_src); |
| 15669 | } else null; | 15707 | break :s try sema.resolveConstValue(block, sentinel_src, casted); |
| | 15708 | } |
| | 15709 | // If we are slicing to the end of something that is sentinel-terminated |
| | 15710 | // then the resulting slice type is also sentinel-terminated. |
| | 15711 | if (end_is_len) { |
| | 15712 | if (ptr_sentinel) |sent| { |
| | 15713 | break :s sent; |
| | 15714 | } |
| | 15715 | } |
| | 15716 | break :s null; |
| | 15717 | }; |
| 15670 | | 15718 | |
| 15671 | const new_len = try sema.analyzeArithmetic(block, .sub, end, start, src, end_src, start_src); | 15719 | const new_len = try sema.analyzeArithmetic(block, .sub, end, start, src, end_src, start_src); |
| 15672 | | | |
| 15673 | const opt_new_len_val = try sema.resolveDefinedValue(block, src, new_len); | 15720 | const opt_new_len_val = try sema.resolveDefinedValue(block, src, new_len); |
| 15674 | | 15721 | |
| 15675 | const new_ptr_ty_info = sema.typeOf(new_ptr).ptrInfo().data; | 15722 | const new_ptr_ty_info = sema.typeOf(new_ptr).ptrInfo().data; |
| ... | @@ -15678,11 +15725,6 @@ fn analyzeSlice( | ... | @@ -15678,11 +15725,6 @@ fn analyzeSlice( |
| 15678 | if (opt_new_len_val) |new_len_val| { | 15725 | if (opt_new_len_val) |new_len_val| { |
| 15679 | const new_len_int = new_len_val.toUnsignedInt(); | 15726 | const new_len_int = new_len_val.toUnsignedInt(); |
| 15680 | | 15727 | |
| 15681 | const sentinel = if (array_ty.zigTypeTag() == .Array and new_len_int == array_ty.arrayLen()) | | |
| 15682 | array_ty.sentinel() | | |
| 15683 | else | | |
| 15684 | slice_sentinel; | | |
| 15685 | | | |
| 15686 | const return_ty = try Type.ptr(sema.arena, .{ | 15728 | const return_ty = try Type.ptr(sema.arena, .{ |
| 15687 | .pointee_type = try Type.array(sema.arena, new_len_int, sentinel, elem_ty), | 15729 | .pointee_type = try Type.array(sema.arena, new_len_int, sentinel, elem_ty), |
| 15688 | .sentinel = null, | 15730 | .sentinel = null, |
| ... | @@ -15713,7 +15755,7 @@ fn analyzeSlice( | ... | @@ -15713,7 +15755,7 @@ fn analyzeSlice( |
| 15713 | | 15755 | |
| 15714 | const return_ty = try Type.ptr(sema.arena, .{ | 15756 | const return_ty = try Type.ptr(sema.arena, .{ |
| 15715 | .pointee_type = elem_ty, | 15757 | .pointee_type = elem_ty, |
| 15716 | .sentinel = slice_sentinel, | 15758 | .sentinel = sentinel, |
| 15717 | .@"align" = new_ptr_ty_info.@"align", | 15759 | .@"align" = new_ptr_ty_info.@"align", |
| 15718 | .@"addrspace" = new_ptr_ty_info.@"addrspace", | 15760 | .@"addrspace" = new_ptr_ty_info.@"addrspace", |
| 15719 | .mutable = new_ptr_ty_info.mutable, | 15761 | .mutable = new_ptr_ty_info.mutable, |