| ... | ... | @@ -4491,7 +4491,7 @@ fn validateUnionInit( |
| 4491 | 4491 | _ = try sema.unionFieldIndex(block, union_ty, field_name, field_src); |
| 4492 | 4492 | const air_tags = sema.air_instructions.items(.tag); |
| 4493 | 4493 | const air_datas = sema.air_instructions.items(.data); |
| 4494 | | const field_ptr_air_ref = sema.inst_map.get(field_ptr).?; |
| 4494 | const field_ptr_ref = sema.inst_map.get(field_ptr).?; |
| 4495 | 4495 | |
| 4496 | 4496 | // Our task here is to determine if the union is comptime-known. In such case, |
| 4497 | 4497 | // we erase the runtime AIR instructions for initializing the union, and replace |
| ... | ... | @@ -4521,31 +4521,25 @@ fn validateUnionInit( |
| 4521 | 4521 | var make_runtime = false; |
| 4522 | 4522 | while (block_index > 0) : (block_index -= 1) { |
| 4523 | 4523 | const store_inst = block.instructions.items[block_index]; |
| 4524 | | if (Air.indexToRef(store_inst) == field_ptr_air_ref) break; |
| 4524 | if (Air.indexToRef(store_inst) == field_ptr_ref) break; |
| 4525 | 4525 | switch (air_tags[store_inst]) { |
| 4526 | 4526 | .store, .store_safe => {}, |
| 4527 | 4527 | else => continue, |
| 4528 | 4528 | } |
| 4529 | 4529 | const bin_op = air_datas[store_inst].bin_op; |
| 4530 | | var lhs = bin_op.lhs; |
| 4531 | | if (Air.refToIndex(lhs)) |lhs_index| { |
| 4532 | | if (air_tags[lhs_index] == .bitcast) { |
| 4533 | | lhs = air_datas[lhs_index].ty_op.operand; |
| 4534 | | block_index -= 1; |
| 4535 | | } |
| 4536 | | } |
| 4537 | | if (lhs != field_ptr_air_ref) continue; |
| 4538 | | while (block_index > 0) : (block_index -= 1) { |
| 4539 | | const block_inst = block.instructions.items[block_index - 1]; |
| 4540 | | if (air_tags[block_inst] != .dbg_stmt) break; |
| 4541 | | } |
| 4542 | | if (block_index > 0 and |
| 4543 | | field_ptr_air_ref == Air.indexToRef(block.instructions.items[block_index - 1])) |
| 4544 | | { |
| 4545 | | first_block_index = @min(first_block_index, block_index - 1); |
| 4546 | | } else { |
| 4547 | | first_block_index = @min(first_block_index, block_index); |
| 4548 | | } |
| 4530 | var ptr_ref = bin_op.lhs; |
| 4531 | if (Air.refToIndex(ptr_ref)) |ptr_inst| if (air_tags[ptr_inst] == .bitcast) { |
| 4532 | ptr_ref = air_datas[ptr_inst].ty_op.operand; |
| 4533 | }; |
| 4534 | if (ptr_ref != field_ptr_ref) continue; |
| 4535 | first_block_index = @min(if (Air.refToIndex(field_ptr_ref)) |field_ptr_inst| |
| 4536 | std.mem.lastIndexOfScalar( |
| 4537 | Air.Inst.Index, |
| 4538 | block.instructions.items[0..block_index], |
| 4539 | field_ptr_inst, |
| 4540 | ).? |
| 4541 | else |
| 4542 | block_index, first_block_index); |
| 4549 | 4543 | init_val = try sema.resolveMaybeUndefValAllowVariablesMaybeRuntime(bin_op.rhs, &make_runtime); |
| 4550 | 4544 | break; |
| 4551 | 4545 | } |
| ... | ... | @@ -4557,7 +4551,29 @@ fn validateUnionInit( |
| 4557 | 4551 | if (init_val) |val| { |
| 4558 | 4552 | // Our task is to delete all the `field_ptr` and `store` instructions, and insert |
| 4559 | 4553 | // instead a single `store` to the result ptr with a comptime union value. |
| 4560 | | block.instructions.shrinkRetainingCapacity(first_block_index); |
| 4554 | block_index = first_block_index; |
| 4555 | for (block.instructions.items[first_block_index..]) |cur_inst| { |
| 4556 | switch (air_tags[cur_inst]) { |
| 4557 | .struct_field_ptr, |
| 4558 | .struct_field_ptr_index_0, |
| 4559 | .struct_field_ptr_index_1, |
| 4560 | .struct_field_ptr_index_2, |
| 4561 | .struct_field_ptr_index_3, |
| 4562 | => if (Air.indexToRef(cur_inst) == field_ptr_ref) continue, |
| 4563 | .bitcast => if (air_datas[cur_inst].ty_op.operand == field_ptr_ref) continue, |
| 4564 | .store, .store_safe => { |
| 4565 | var ptr_ref = air_datas[cur_inst].bin_op.lhs; |
| 4566 | if (Air.refToIndex(ptr_ref)) |ptr_inst| if (air_tags[ptr_inst] == .bitcast) { |
| 4567 | ptr_ref = air_datas[ptr_inst].ty_op.operand; |
| 4568 | }; |
| 4569 | if (ptr_ref == field_ptr_ref) continue; |
| 4570 | }, |
| 4571 | else => {}, |
| 4572 | } |
| 4573 | block.instructions.items[block_index] = cur_inst; |
| 4574 | block_index += 1; |
| 4575 | } |
| 4576 | block.instructions.shrinkRetainingCapacity(block_index); |
| 4561 | 4577 | |
| 4562 | 4578 | var union_val = try mod.intern(.{ .un = .{ |
| 4563 | 4579 | .ty = union_ty.toIntern(), |
| ... | ... | @@ -4590,6 +4606,9 @@ fn validateStructInit( |
| 4590 | 4606 | const gpa = sema.gpa; |
| 4591 | 4607 | const ip = &mod.intern_pool; |
| 4592 | 4608 | |
| 4609 | const field_indices = try gpa.alloc(u32, instrs.len); |
| 4610 | defer gpa.free(field_indices); |
| 4611 | |
| 4593 | 4612 | // Maps field index to field_ptr index of where it was already initialized. |
| 4594 | 4613 | const found_fields = try gpa.alloc(Zir.Inst.Index, struct_ty.structFieldCount(mod)); |
| 4595 | 4614 | defer gpa.free(found_fields); |
| ... | ... | @@ -4597,7 +4616,7 @@ fn validateStructInit( |
| 4597 | 4616 | |
| 4598 | 4617 | var struct_ptr_zir_ref: Zir.Inst.Ref = undefined; |
| 4599 | 4618 | |
| 4600 | | for (instrs) |field_ptr| { |
| 4619 | for (instrs, field_indices) |field_ptr, *field_index| { |
| 4601 | 4620 | const field_ptr_data = sema.code.instructions.items(.data)[field_ptr].pl_node; |
| 4602 | 4621 | const field_src: LazySrcLoc = .{ .node_offset_initializer = field_ptr_data.src_node }; |
| 4603 | 4622 | const field_ptr_extra = sema.code.extraData(Zir.Inst.Field, field_ptr_data.payload_index).data; |
| ... | ... | @@ -4606,12 +4625,12 @@ fn validateStructInit( |
| 4606 | 4625 | gpa, |
| 4607 | 4626 | sema.code.nullTerminatedString(field_ptr_extra.field_name_start), |
| 4608 | 4627 | ); |
| 4609 | | const field_index = if (struct_ty.isTuple(mod)) |
| 4628 | field_index.* = if (struct_ty.isTuple(mod)) |
| 4610 | 4629 | try sema.tupleFieldIndex(block, struct_ty, field_name, field_src) |
| 4611 | 4630 | else |
| 4612 | 4631 | try sema.structFieldIndex(block, struct_ty, field_name, field_src); |
| 4613 | | if (found_fields[field_index] != 0) { |
| 4614 | | const other_field_ptr = found_fields[field_index]; |
| 4632 | if (found_fields[field_index.*] != 0) { |
| 4633 | const other_field_ptr = found_fields[field_index.*]; |
| 4615 | 4634 | const other_field_ptr_data = sema.code.instructions.items(.data)[other_field_ptr].pl_node; |
| 4616 | 4635 | const other_field_src: LazySrcLoc = .{ .node_offset_initializer = other_field_ptr_data.src_node }; |
| 4617 | 4636 | const msg = msg: { |
| ... | ... | @@ -4622,7 +4641,7 @@ fn validateStructInit( |
| 4622 | 4641 | }; |
| 4623 | 4642 | return sema.failWithOwnedErrorMsg(msg); |
| 4624 | 4643 | } |
| 4625 | | found_fields[field_index] = field_ptr; |
| 4644 | found_fields[field_index.*] = field_ptr; |
| 4626 | 4645 | } |
| 4627 | 4646 | |
| 4628 | 4647 | var root_msg: ?*Module.ErrorMsg = null; |
| ... | ... | @@ -4708,7 +4727,7 @@ fn validateStructInit( |
| 4708 | 4727 | continue; |
| 4709 | 4728 | } |
| 4710 | 4729 | |
| 4711 | | const field_ptr_air_ref = sema.inst_map.get(field_ptr).?; |
| 4730 | const field_ptr_ref = sema.inst_map.get(field_ptr).?; |
| 4712 | 4731 | |
| 4713 | 4732 | //std.debug.print("validateStructInit (field_ptr_air_inst=%{d}):\n", .{ |
| 4714 | 4733 | // field_ptr_air_inst, |
| ... | ... | @@ -4738,7 +4757,7 @@ fn validateStructInit( |
| 4738 | 4757 | var block_index = block.instructions.items.len - 1; |
| 4739 | 4758 | while (block_index > 0) : (block_index -= 1) { |
| 4740 | 4759 | const store_inst = block.instructions.items[block_index]; |
| 4741 | | if (Air.indexToRef(store_inst) == field_ptr_air_ref) { |
| 4760 | if (Air.indexToRef(store_inst) == field_ptr_ref) { |
| 4742 | 4761 | struct_is_comptime = false; |
| 4743 | 4762 | continue :field; |
| 4744 | 4763 | } |
| ... | ... | @@ -4747,26 +4766,19 @@ fn validateStructInit( |
| 4747 | 4766 | else => continue, |
| 4748 | 4767 | } |
| 4749 | 4768 | const bin_op = air_datas[store_inst].bin_op; |
| 4750 | | var lhs = bin_op.lhs; |
| 4751 | | { |
| 4752 | | const lhs_index = Air.refToIndex(lhs) orelse continue; |
| 4753 | | if (air_tags[lhs_index] == .bitcast) { |
| 4754 | | lhs = air_datas[lhs_index].ty_op.operand; |
| 4755 | | block_index -= 1; |
| 4756 | | } |
| 4757 | | } |
| 4758 | | if (lhs != field_ptr_air_ref) continue; |
| 4759 | | while (block_index > 0) : (block_index -= 1) { |
| 4760 | | const block_inst = block.instructions.items[block_index - 1]; |
| 4761 | | if (air_tags[block_inst] != .dbg_stmt) break; |
| 4762 | | } |
| 4763 | | if (block_index > 0 and |
| 4764 | | field_ptr_air_ref == Air.indexToRef(block.instructions.items[block_index - 1])) |
| 4765 | | { |
| 4766 | | first_block_index = @min(first_block_index, block_index - 1); |
| 4767 | | } else { |
| 4768 | | first_block_index = @min(first_block_index, block_index); |
| 4769 | | } |
| 4769 | var ptr_ref = bin_op.lhs; |
| 4770 | if (Air.refToIndex(ptr_ref)) |ptr_inst| if (air_tags[ptr_inst] == .bitcast) { |
| 4771 | ptr_ref = air_datas[ptr_inst].ty_op.operand; |
| 4772 | }; |
| 4773 | if (ptr_ref != field_ptr_ref) continue; |
| 4774 | first_block_index = @min(if (Air.refToIndex(field_ptr_ref)) |field_ptr_inst| |
| 4775 | std.mem.lastIndexOfScalar( |
| 4776 | Air.Inst.Index, |
| 4777 | block.instructions.items[0..block_index], |
| 4778 | field_ptr_inst, |
| 4779 | ).? |
| 4780 | else |
| 4781 | block_index, first_block_index); |
| 4770 | 4782 | if (try sema.resolveMaybeUndefValAllowVariablesMaybeRuntime(bin_op.rhs, &make_runtime)) |val| { |
| 4771 | 4783 | field_values[i] = val.toIntern(); |
| 4772 | 4784 | } else if (require_comptime) { |
| ... | ... | @@ -4822,8 +4834,40 @@ fn validateStructInit( |
| 4822 | 4834 | if (struct_is_comptime) { |
| 4823 | 4835 | // Our task is to delete all the `field_ptr` and `store` instructions, and insert |
| 4824 | 4836 | // instead a single `store` to the struct_ptr with a comptime struct value. |
| 4837 | var init_index: usize = 0; |
| 4838 | var field_ptr_ref = Air.Inst.Ref.none; |
| 4839 | var block_index = first_block_index; |
| 4840 | for (block.instructions.items[first_block_index..]) |cur_inst| { |
| 4841 | while (field_ptr_ref == .none and init_index < instrs.len) : (init_index += 1) { |
| 4842 | const field_ty = struct_ty.structFieldType(field_indices[init_index], mod); |
| 4843 | if (try field_ty.onePossibleValue(mod)) |_| continue; |
| 4844 | field_ptr_ref = sema.inst_map.get(instrs[init_index]).?; |
| 4845 | } |
| 4846 | switch (air_tags[cur_inst]) { |
| 4847 | .struct_field_ptr, |
| 4848 | .struct_field_ptr_index_0, |
| 4849 | .struct_field_ptr_index_1, |
| 4850 | .struct_field_ptr_index_2, |
| 4851 | .struct_field_ptr_index_3, |
| 4852 | => if (Air.indexToRef(cur_inst) == field_ptr_ref) continue, |
| 4853 | .bitcast => if (air_datas[cur_inst].ty_op.operand == field_ptr_ref) continue, |
| 4854 | .store, .store_safe => { |
| 4855 | var ptr_ref = air_datas[cur_inst].bin_op.lhs; |
| 4856 | if (Air.refToIndex(ptr_ref)) |ptr_inst| if (air_tags[ptr_inst] == .bitcast) { |
| 4857 | ptr_ref = air_datas[ptr_inst].ty_op.operand; |
| 4858 | }; |
| 4859 | if (ptr_ref == field_ptr_ref) { |
| 4860 | field_ptr_ref = .none; |
| 4861 | continue; |
| 4862 | } |
| 4863 | }, |
| 4864 | else => {}, |
| 4865 | } |
| 4866 | block.instructions.items[block_index] = cur_inst; |
| 4867 | block_index += 1; |
| 4868 | } |
| 4869 | block.instructions.shrinkRetainingCapacity(block_index); |
| 4825 | 4870 | |
| 4826 | | block.instructions.shrinkRetainingCapacity(first_block_index); |
| 4827 | 4871 | var struct_val = try mod.intern(.{ .aggregate = .{ |
| 4828 | 4872 | .ty = struct_ty.toIntern(), |
| 4829 | 4873 | .storage = .{ .elems = field_values }, |
| ... | ... | @@ -4950,7 +4994,7 @@ fn zirValidateArrayInit( |
| 4950 | 4994 | } |
| 4951 | 4995 | } |
| 4952 | 4996 | |
| 4953 | | const elem_ptr_air_ref = sema.inst_map.get(elem_ptr).?; |
| 4997 | const elem_ptr_ref = sema.inst_map.get(elem_ptr).?; |
| 4954 | 4998 | |
| 4955 | 4999 | // We expect to see something like this in the current block AIR: |
| 4956 | 5000 | // %a = elem_ptr(...) |
| ... | ... | @@ -4975,7 +5019,7 @@ fn zirValidateArrayInit( |
| 4975 | 5019 | var block_index = block.instructions.items.len - 1; |
| 4976 | 5020 | while (block_index > 0) : (block_index -= 1) { |
| 4977 | 5021 | const store_inst = block.instructions.items[block_index]; |
| 4978 | | if (Air.indexToRef(store_inst) == elem_ptr_air_ref) { |
| 5022 | if (Air.indexToRef(store_inst) == elem_ptr_ref) { |
| 4979 | 5023 | array_is_comptime = false; |
| 4980 | 5024 | continue :outer; |
| 4981 | 5025 | } |
| ... | ... | @@ -4984,26 +5028,19 @@ fn zirValidateArrayInit( |
| 4984 | 5028 | else => continue, |
| 4985 | 5029 | } |
| 4986 | 5030 | const bin_op = air_datas[store_inst].bin_op; |
| 4987 | | var lhs = bin_op.lhs; |
| 4988 | | { |
| 4989 | | const lhs_index = Air.refToIndex(lhs) orelse continue; |
| 4990 | | if (air_tags[lhs_index] == .bitcast) { |
| 4991 | | lhs = air_datas[lhs_index].ty_op.operand; |
| 4992 | | block_index -= 1; |
| 4993 | | } |
| 4994 | | } |
| 4995 | | if (lhs != elem_ptr_air_ref) continue; |
| 4996 | | while (block_index > 0) : (block_index -= 1) { |
| 4997 | | const block_inst = block.instructions.items[block_index - 1]; |
| 4998 | | if (air_tags[block_inst] != .dbg_stmt) break; |
| 4999 | | } |
| 5000 | | if (block_index > 0 and |
| 5001 | | elem_ptr_air_ref == Air.indexToRef(block.instructions.items[block_index - 1])) |
| 5002 | | { |
| 5003 | | first_block_index = @min(first_block_index, block_index - 1); |
| 5004 | | } else { |
| 5005 | | first_block_index = @min(first_block_index, block_index); |
| 5006 | | } |
| 5031 | var ptr_ref = bin_op.lhs; |
| 5032 | if (Air.refToIndex(ptr_ref)) |ptr_inst| if (air_tags[ptr_inst] == .bitcast) { |
| 5033 | ptr_ref = air_datas[ptr_inst].ty_op.operand; |
| 5034 | }; |
| 5035 | if (ptr_ref != elem_ptr_ref) continue; |
| 5036 | first_block_index = @min(if (Air.refToIndex(elem_ptr_ref)) |elem_ptr_inst| |
| 5037 | std.mem.lastIndexOfScalar( |
| 5038 | Air.Inst.Index, |
| 5039 | block.instructions.items[0..block_index], |
| 5040 | elem_ptr_inst, |
| 5041 | ).? |
| 5042 | else |
| 5043 | block_index, first_block_index); |
| 5007 | 5044 | if (try sema.resolveMaybeUndefValAllowVariablesMaybeRuntime(bin_op.rhs, &make_runtime)) |val| { |
| 5008 | 5045 | element_vals[i] = val.toIntern(); |
| 5009 | 5046 | } else { |
| ... | ... | @@ -5028,7 +5065,33 @@ fn zirValidateArrayInit( |
| 5028 | 5065 | |
| 5029 | 5066 | // Our task is to delete all the `elem_ptr` and `store` instructions, and insert |
| 5030 | 5067 | // instead a single `store` to the array_ptr with a comptime struct value. |
| 5031 | | block.instructions.shrinkRetainingCapacity(first_block_index); |
| 5068 | var elem_index: usize = 0; |
| 5069 | var elem_ptr_ref = Air.Inst.Ref.none; |
| 5070 | var block_index = first_block_index; |
| 5071 | for (block.instructions.items[first_block_index..]) |cur_inst| { |
| 5072 | while (elem_ptr_ref == .none and elem_index < instrs.len) : (elem_index += 1) { |
| 5073 | if (array_ty.isTuple(mod) and array_ty.structFieldIsComptime(elem_index, mod)) continue; |
| 5074 | elem_ptr_ref = sema.inst_map.get(instrs[elem_index]).?; |
| 5075 | } |
| 5076 | switch (air_tags[cur_inst]) { |
| 5077 | .ptr_elem_ptr => if (Air.indexToRef(cur_inst) == elem_ptr_ref) continue, |
| 5078 | .bitcast => if (air_datas[cur_inst].ty_op.operand == elem_ptr_ref) continue, |
| 5079 | .store, .store_safe => { |
| 5080 | var ptr_ref = air_datas[cur_inst].bin_op.lhs; |
| 5081 | if (Air.refToIndex(ptr_ref)) |ptr_inst| if (air_tags[ptr_inst] == .bitcast) { |
| 5082 | ptr_ref = air_datas[ptr_inst].ty_op.operand; |
| 5083 | }; |
| 5084 | if (ptr_ref == elem_ptr_ref) { |
| 5085 | elem_ptr_ref = .none; |
| 5086 | continue; |
| 5087 | } |
| 5088 | }, |
| 5089 | else => {}, |
| 5090 | } |
| 5091 | block.instructions.items[block_index] = cur_inst; |
| 5092 | block_index += 1; |
| 5093 | } |
| 5094 | block.instructions.shrinkRetainingCapacity(block_index); |
| 5032 | 5095 | |
| 5033 | 5096 | var array_val = try mod.intern(.{ .aggregate = .{ |
| 5034 | 5097 | .ty = array_ty.toIntern(), |