| ... | ... | @@ -3866,8 +3866,8 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com |
| 3866 | 3866 | const dummy_ptr = try trash_block.addTy(.alloc, mut_final_ptr_ty); |
| 3867 | 3867 | const empty_trash_count = trash_block.instructions.items.len; |
| 3868 | 3868 | |
| 3869 | | for (placeholders, 0..) |bitcast_inst, i| { |
| 3870 | | const sub_ptr_ty = sema.typeOf(Air.indexToRef(bitcast_inst)); |
| 3869 | for (peer_inst_list, placeholders) |peer_inst, placeholder_inst| { |
| 3870 | const sub_ptr_ty = sema.typeOf(Air.indexToRef(placeholder_inst)); |
| 3871 | 3871 | |
| 3872 | 3872 | if (mut_final_ptr_ty.eql(sub_ptr_ty, sema.mod)) { |
| 3873 | 3873 | // New result location type is the same as the old one; nothing |
| ... | ... | @@ -3875,39 +3875,54 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com |
| 3875 | 3875 | continue; |
| 3876 | 3876 | } |
| 3877 | 3877 | |
| 3878 | | var bitcast_block = block.makeSubBlock(); |
| 3879 | | defer bitcast_block.instructions.deinit(gpa); |
| 3878 | var replacement_block = block.makeSubBlock(); |
| 3879 | defer replacement_block.instructions.deinit(gpa); |
| 3880 | 3880 | |
| 3881 | | trash_block.instructions.shrinkRetainingCapacity(empty_trash_count); |
| 3882 | | const sub_ptr = try sema.coerceResultPtr(&bitcast_block, src, ptr, dummy_ptr, peer_inst_list[i], &trash_block); |
| 3881 | const result = switch (sema.air_instructions.items(.tag)[placeholder_inst]) { |
| 3882 | .bitcast => result: { |
| 3883 | trash_block.instructions.shrinkRetainingCapacity(empty_trash_count); |
| 3884 | const sub_ptr = try sema.coerceResultPtr(&replacement_block, src, ptr, dummy_ptr, peer_inst, &trash_block); |
| 3885 | |
| 3886 | assert(replacement_block.instructions.items.len > 0); |
| 3887 | break :result sub_ptr; |
| 3888 | }, |
| 3889 | .store => result: { |
| 3890 | const bin_op = sema.air_instructions.items(.data)[placeholder_inst].bin_op; |
| 3891 | try sema.storePtr2(&replacement_block, src, bin_op.lhs, src, bin_op.rhs, src, .bitcast); |
| 3892 | break :result .void_value; |
| 3893 | }, |
| 3894 | else => unreachable, |
| 3895 | }; |
| 3883 | 3896 | |
| 3884 | | assert(bitcast_block.instructions.items.len > 0); |
| 3885 | 3897 | // If only one instruction is produced then we can replace the bitcast |
| 3886 | 3898 | // placeholder instruction with this instruction; no need for an entire block. |
| 3887 | | if (bitcast_block.instructions.items.len == 1) { |
| 3888 | | const only_inst = bitcast_block.instructions.items[0]; |
| 3889 | | sema.air_instructions.set(bitcast_inst, sema.air_instructions.get(only_inst)); |
| 3899 | if (replacement_block.instructions.items.len == 1) { |
| 3900 | const only_inst = replacement_block.instructions.items[0]; |
| 3901 | sema.air_instructions.set(placeholder_inst, sema.air_instructions.get(only_inst)); |
| 3890 | 3902 | continue; |
| 3891 | 3903 | } |
| 3892 | 3904 | |
| 3893 | 3905 | // Here we replace the placeholder bitcast instruction with a block |
| 3894 | 3906 | // that does the coerce_result_ptr logic. |
| 3895 | | _ = try bitcast_block.addBr(bitcast_inst, sub_ptr); |
| 3896 | | const ty_inst = sema.air_instructions.items(.data)[bitcast_inst].ty_op.ty; |
| 3907 | _ = try replacement_block.addBr(placeholder_inst, result); |
| 3908 | const ty_inst = if (result == .void_value) |
| 3909 | .void_type |
| 3910 | else |
| 3911 | sema.air_instructions.items(.data)[placeholder_inst].ty_op.ty; |
| 3897 | 3912 | try sema.air_extra.ensureUnusedCapacity( |
| 3898 | 3913 | gpa, |
| 3899 | | @typeInfo(Air.Block).Struct.fields.len + bitcast_block.instructions.items.len, |
| 3914 | @typeInfo(Air.Block).Struct.fields.len + replacement_block.instructions.items.len, |
| 3900 | 3915 | ); |
| 3901 | | sema.air_instructions.set(bitcast_inst, .{ |
| 3916 | sema.air_instructions.set(placeholder_inst, .{ |
| 3902 | 3917 | .tag = .block, |
| 3903 | 3918 | .data = .{ .ty_pl = .{ |
| 3904 | 3919 | .ty = ty_inst, |
| 3905 | 3920 | .payload = sema.addExtraAssumeCapacity(Air.Block{ |
| 3906 | | .body_len = @intCast(u32, bitcast_block.instructions.items.len), |
| 3921 | .body_len = @intCast(u32, replacement_block.instructions.items.len), |
| 3907 | 3922 | }), |
| 3908 | 3923 | } }, |
| 3909 | 3924 | }); |
| 3910 | | sema.air_extra.appendSliceAssumeCapacity(bitcast_block.instructions.items); |
| 3925 | sema.air_extra.appendSliceAssumeCapacity(replacement_block.instructions.items); |
| 3911 | 3926 | } |
| 3912 | 3927 | }, |
| 3913 | 3928 | else => unreachable, |
| ... | ... | @@ -4916,7 +4931,7 @@ fn zirStoreToBlockPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE |
| 4916 | 4931 | }, |
| 4917 | 4932 | .inferred_alloc => { |
| 4918 | 4933 | const inferred_alloc = ptr_val.castTag(.inferred_alloc).?; |
| 4919 | | return sema.storeToInferredAlloc(block, src, ptr, operand, inferred_alloc); |
| 4934 | return sema.storeToInferredAlloc(block, ptr, operand, inferred_alloc); |
| 4920 | 4935 | }, |
| 4921 | 4936 | else => break :blk, |
| 4922 | 4937 | } |
| ... | ... | @@ -4945,7 +4960,7 @@ fn zirStoreToInferredPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compi |
| 4945 | 4960 | }, |
| 4946 | 4961 | .inferred_alloc => { |
| 4947 | 4962 | const inferred_alloc = ptr_val.castTag(.inferred_alloc).?; |
| 4948 | | return sema.storeToInferredAlloc(block, src, ptr, operand, inferred_alloc); |
| 4963 | return sema.storeToInferredAlloc(block, ptr, operand, inferred_alloc); |
| 4949 | 4964 | }, |
| 4950 | 4965 | else => unreachable, |
| 4951 | 4966 | } |
| ... | ... | @@ -4954,27 +4969,19 @@ fn zirStoreToInferredPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compi |
| 4954 | 4969 | fn storeToInferredAlloc( |
| 4955 | 4970 | sema: *Sema, |
| 4956 | 4971 | block: *Block, |
| 4957 | | src: LazySrcLoc, |
| 4958 | 4972 | ptr: Air.Inst.Ref, |
| 4959 | 4973 | operand: Air.Inst.Ref, |
| 4960 | 4974 | inferred_alloc: *Value.Payload.InferredAlloc, |
| 4961 | 4975 | ) CompileError!void { |
| 4962 | | const operand_ty = sema.typeOf(operand); |
| 4963 | | // Create a runtime bitcast instruction with exactly the type the pointer wants. |
| 4964 | | const target = sema.mod.getTarget(); |
| 4965 | | const ptr_ty = try Type.ptr(sema.arena, sema.mod, .{ |
| 4966 | | .pointee_type = operand_ty, |
| 4967 | | .@"align" = inferred_alloc.data.alignment, |
| 4968 | | .@"addrspace" = target_util.defaultAddressSpace(target, .local), |
| 4969 | | }); |
| 4970 | | const bitcasted_ptr = try block.addBitCast(ptr_ty, ptr); |
| 4976 | // Create a store instruction as a placeholder. This will be replaced by a |
| 4977 | // proper store sequence once we know the stored type. |
| 4978 | const dummy_store = try block.addBinOp(.store, ptr, operand); |
| 4971 | 4979 | // Add the stored instruction to the set we will use to resolve peer types |
| 4972 | 4980 | // for the inferred allocation. |
| 4973 | 4981 | try inferred_alloc.data.prongs.append(sema.arena, .{ |
| 4974 | 4982 | .stored_inst = operand, |
| 4975 | | .placeholder = Air.refToIndex(bitcasted_ptr).?, |
| 4983 | .placeholder = Air.refToIndex(dummy_store).?, |
| 4976 | 4984 | }); |
| 4977 | | return sema.storePtr2(block, src, bitcasted_ptr, src, operand, src, .bitcast); |
| 4978 | 4985 | } |
| 4979 | 4986 | |
| 4980 | 4987 | fn storeToInferredAllocComptime( |