| ... | ... | @@ -19212,9 +19212,9 @@ fn elemValArray( |
| 19212 | 19212 | elem_index: Air.Inst.Ref, |
| 19213 | 19213 | ) CompileError!Air.Inst.Ref { |
| 19214 | 19214 | const array_ty = sema.typeOf(array); |
| 19215 | | const array_sent = array_ty.sentinel() != null; |
| 19215 | const array_sent = array_ty.sentinel(); |
| 19216 | 19216 | const array_len = array_ty.arrayLen(); |
| 19217 | | const array_len_s = array_len + @boolToInt(array_sent); |
| 19217 | const array_len_s = array_len + @boolToInt(array_sent != null); |
| 19218 | 19218 | const elem_ty = array_ty.childType(); |
| 19219 | 19219 | |
| 19220 | 19220 | if (array_len_s == 0) { |
| ... | ... | @@ -19228,8 +19228,13 @@ fn elemValArray( |
| 19228 | 19228 | |
| 19229 | 19229 | if (maybe_index_val) |index_val| { |
| 19230 | 19230 | const index = @intCast(usize, index_val.toUnsignedInt(target)); |
| 19231 | if (array_sent) |s| { |
| 19232 | if (index == array_len) { |
| 19233 | return sema.addConstant(elem_ty, s); |
| 19234 | } |
| 19235 | } |
| 19231 | 19236 | if (index >= array_len_s) { |
| 19232 | | const sentinel_label: []const u8 = if (array_sent) " +1 (sentinel)" else ""; |
| 19237 | const sentinel_label: []const u8 = if (array_sent != null) " +1 (sentinel)" else ""; |
| 19233 | 19238 | return sema.fail(block, elem_index_src, "index {d} outside array of length {d}{s}", .{ index, array_len, sentinel_label }); |
| 19234 | 19239 | } |
| 19235 | 19240 | } |
| ... | ... | @@ -19269,7 +19274,7 @@ fn elemValArray( |
| 19269 | 19274 | // Runtime check is only needed if unable to comptime check |
| 19270 | 19275 | if (maybe_index_val == null) { |
| 19271 | 19276 | const len_inst = try sema.addIntUnsigned(Type.usize, array_len); |
| 19272 | | const cmp_op: Air.Inst.Tag = if (array_sent) .cmp_lte else .cmp_lt; |
| 19277 | const cmp_op: Air.Inst.Tag = if (array_sent != null) .cmp_lte else .cmp_lt; |
| 19273 | 19278 | try sema.panicIndexOutOfBounds(block, elem_index_src, elem_index, len_inst, cmp_op); |
| 19274 | 19279 | } |
| 19275 | 19280 | } |
| ... | ... | @@ -20521,27 +20526,67 @@ fn storePtrVal( |
| 20521 | 20526 | operand_val: Value, |
| 20522 | 20527 | operand_ty: Type, |
| 20523 | 20528 | ) !void { |
| 20524 | | var mut_kit = try beginComptimePtrMutation(sema, block, src, ptr_val); |
| 20529 | var mut_kit = try beginComptimePtrMutation(sema, block, src, ptr_val, operand_ty); |
| 20525 | 20530 | try sema.checkComptimeVarStore(block, src, mut_kit.decl_ref_mut); |
| 20526 | 20531 | |
| 20527 | | const bitcasted_val = try sema.bitCastVal(block, src, operand_val, operand_ty, mut_kit.ty, 0); |
| 20532 | switch (mut_kit.pointee) { |
| 20533 | .direct => |val_ptr| { |
| 20534 | if (mut_kit.decl_ref_mut.runtime_index == .comptime_field_ptr) { |
| 20535 | if (!operand_val.eql(val_ptr.*, operand_ty, sema.mod)) { |
| 20536 | // TODO add note showing where default value is provided |
| 20537 | return sema.fail(block, src, "value stored in comptime field does not match the default value of the field", .{}); |
| 20538 | } |
| 20539 | return; |
| 20540 | } |
| 20541 | const arena = mut_kit.beginArena(sema.mod); |
| 20542 | defer mut_kit.finishArena(sema.mod); |
| 20528 | 20543 | |
| 20529 | | if (mut_kit.decl_ref_mut.runtime_index == .comptime_field_ptr) { |
| 20530 | | if (!mut_kit.val.eql(bitcasted_val, mut_kit.ty, sema.mod)) { |
| 20531 | | return sema.fail(block, src, "value stored in comptime field does not match the default value of the field", .{}); |
| 20532 | | } |
| 20533 | | return; |
| 20534 | | } |
| 20544 | val_ptr.* = try operand_val.copy(arena); |
| 20545 | }, |
| 20546 | .reinterpret => |reinterpret| { |
| 20547 | const target = sema.mod.getTarget(); |
| 20548 | const abi_size = try sema.usizeCast(block, src, mut_kit.ty.abiSize(target)); |
| 20549 | const buffer = try sema.gpa.alloc(u8, abi_size); |
| 20550 | defer sema.gpa.free(buffer); |
| 20551 | reinterpret.val_ptr.*.writeToMemory(mut_kit.ty, sema.mod, buffer); |
| 20552 | operand_val.writeToMemory(operand_ty, sema.mod, buffer[reinterpret.byte_offset..]); |
| 20535 | 20553 | |
| 20536 | | const arena = mut_kit.beginArena(sema.mod); |
| 20537 | | defer mut_kit.finishArena(sema.mod); |
| 20554 | const arena = mut_kit.beginArena(sema.mod); |
| 20555 | defer mut_kit.finishArena(sema.mod); |
| 20538 | 20556 | |
| 20539 | | mut_kit.val.* = try bitcasted_val.copy(arena); |
| 20557 | reinterpret.val_ptr.* = try Value.readFromMemory(mut_kit.ty, sema.mod, buffer, arena); |
| 20558 | }, |
| 20559 | .bad_decl_ty, .bad_ptr_ty => { |
| 20560 | // TODO show the decl declaration site in a note and explain whether the decl |
| 20561 | // or the pointer is the problematic type |
| 20562 | return sema.fail(block, src, "comptime mutation of a reinterpreted pointer requires type '{}' to have a well-defined memory layout", .{mut_kit.ty.fmt(sema.mod)}); |
| 20563 | }, |
| 20564 | } |
| 20540 | 20565 | } |
| 20541 | 20566 | |
| 20542 | 20567 | const ComptimePtrMutationKit = struct { |
| 20543 | 20568 | decl_ref_mut: Value.Payload.DeclRefMut.Data, |
| 20544 | | val: *Value, |
| 20569 | pointee: union(enum) { |
| 20570 | /// The pointer type matches the actual comptime Value so a direct |
| 20571 | /// modification is possible. |
| 20572 | direct: *Value, |
| 20573 | /// The largest parent Value containing pointee and having a well-defined memory layout. |
| 20574 | /// This is used for bitcasting, if direct dereferencing failed. |
| 20575 | reinterpret: struct { |
| 20576 | val_ptr: *Value, |
| 20577 | byte_offset: usize, |
| 20578 | }, |
| 20579 | /// If the root decl could not be used as parent, this means `ty` is the type that |
| 20580 | /// caused that by not having a well-defined layout. |
| 20581 | /// This one means the Decl that owns the value trying to be modified does not |
| 20582 | /// have a well defined memory layout. |
| 20583 | bad_decl_ty, |
| 20584 | /// If the root decl could not be used as parent, this means `ty` is the type that |
| 20585 | /// caused that by not having a well-defined layout. |
| 20586 | /// This one means the pointer type that is being stored through does not |
| 20587 | /// have a well defined memory layout. |
| 20588 | bad_ptr_ty, |
| 20589 | }, |
| 20545 | 20590 | ty: Type, |
| 20546 | 20591 | decl_arena: std.heap.ArenaAllocator = undefined, |
| 20547 | 20592 | |
| ... | ... | @@ -20563,354 +20608,469 @@ fn beginComptimePtrMutation( |
| 20563 | 20608 | block: *Block, |
| 20564 | 20609 | src: LazySrcLoc, |
| 20565 | 20610 | ptr_val: Value, |
| 20611 | ptr_elem_ty: Type, |
| 20566 | 20612 | ) CompileError!ComptimePtrMutationKit { |
| 20567 | | |
| 20568 | | // TODO: Update this to behave like `beginComptimePtrLoad` and properly check/use |
| 20569 | | // `container_ty` and `array_ty`, instead of trusting that the parent decl type |
| 20570 | | // matches the type used to derive the elem_ptr/field_ptr/etc. |
| 20571 | | // |
| 20572 | | // This is needed because the types will not match if the pointer we're mutating |
| 20573 | | // through is reinterpreting comptime memory. |
| 20574 | | |
| 20613 | const target = sema.mod.getTarget(); |
| 20575 | 20614 | switch (ptr_val.tag()) { |
| 20576 | 20615 | .decl_ref_mut => { |
| 20577 | 20616 | const decl_ref_mut = ptr_val.castTag(.decl_ref_mut).?.data; |
| 20578 | 20617 | const decl = sema.mod.declPtr(decl_ref_mut.decl_index); |
| 20579 | | return ComptimePtrMutationKit{ |
| 20580 | | .decl_ref_mut = decl_ref_mut, |
| 20581 | | .val = &decl.val, |
| 20582 | | .ty = decl.ty, |
| 20583 | | }; |
| 20618 | return beginComptimePtrMutationInner(sema, block, src, decl.ty, &decl.val, ptr_elem_ty, decl_ref_mut); |
| 20584 | 20619 | }, |
| 20585 | 20620 | .comptime_field_ptr => { |
| 20586 | 20621 | const payload = ptr_val.castTag(.comptime_field_ptr).?.data; |
| 20587 | 20622 | const duped = try sema.arena.create(Value); |
| 20588 | 20623 | duped.* = payload.field_val; |
| 20589 | | return ComptimePtrMutationKit{ |
| 20590 | | .decl_ref_mut = .{ |
| 20591 | | .decl_index = @intToEnum(Module.Decl.Index, 0), |
| 20592 | | .runtime_index = .comptime_field_ptr, |
| 20593 | | }, |
| 20594 | | .val = duped, |
| 20595 | | .ty = payload.field_ty, |
| 20596 | | }; |
| 20624 | return beginComptimePtrMutationInner(sema, block, src, payload.field_ty, duped, ptr_elem_ty, .{ |
| 20625 | .decl_index = @intToEnum(Module.Decl.Index, 0), |
| 20626 | .runtime_index = .comptime_field_ptr, |
| 20627 | }); |
| 20597 | 20628 | }, |
| 20598 | 20629 | .elem_ptr => { |
| 20599 | 20630 | const elem_ptr = ptr_val.castTag(.elem_ptr).?.data; |
| 20600 | | var parent = try beginComptimePtrMutation(sema, block, src, elem_ptr.array_ptr); |
| 20601 | | switch (parent.ty.zigTypeTag()) { |
| 20602 | | .Array, .Vector => { |
| 20603 | | const check_len = parent.ty.arrayLenIncludingSentinel(); |
| 20604 | | if (elem_ptr.index >= check_len) { |
| 20605 | | // TODO have the parent include the decl so we can say "declared here" |
| 20606 | | return sema.fail(block, src, "comptime store of index {d} out of bounds of array length {d}", .{ |
| 20607 | | elem_ptr.index, check_len, |
| 20608 | | }); |
| 20609 | | } |
| 20610 | | const elem_ty = parent.ty.childType(); |
| 20611 | | switch (parent.val.tag()) { |
| 20612 | | .undef => { |
| 20613 | | // An array has been initialized to undefined at comptime and now we |
| 20614 | | // are for the first time setting an element. We must change the representation |
| 20615 | | // of the array from `undef` to `array`. |
| 20616 | | const arena = parent.beginArena(sema.mod); |
| 20617 | | defer parent.finishArena(sema.mod); |
| 20618 | | |
| 20619 | | const array_len_including_sentinel = |
| 20620 | | try sema.usizeCast(block, src, parent.ty.arrayLenIncludingSentinel()); |
| 20621 | | const elems = try arena.alloc(Value, array_len_including_sentinel); |
| 20622 | | mem.set(Value, elems, Value.undef); |
| 20623 | | |
| 20624 | | parent.val.* = try Value.Tag.aggregate.create(arena, elems); |
| 20625 | | |
| 20626 | | return ComptimePtrMutationKit{ |
| 20627 | | .decl_ref_mut = parent.decl_ref_mut, |
| 20628 | | .val = &elems[elem_ptr.index], |
| 20629 | | .ty = elem_ty, |
| 20630 | | }; |
| 20631 | | }, |
| 20632 | | .bytes => { |
| 20633 | | // An array is memory-optimized to store a slice of bytes, but we are about |
| 20634 | | // to modify an individual field and the representation has to change. |
| 20635 | | // If we wanted to avoid this, there would need to be special detection |
| 20636 | | // elsewhere to identify when writing a value to an array element that is stored |
| 20637 | | // using the `bytes` tag, and handle it without making a call to this function. |
| 20638 | | const arena = parent.beginArena(sema.mod); |
| 20639 | | defer parent.finishArena(sema.mod); |
| 20640 | | |
| 20641 | | const bytes = parent.val.castTag(.bytes).?.data; |
| 20642 | | const dest_len = parent.ty.arrayLenIncludingSentinel(); |
| 20643 | | // bytes.len may be one greater than dest_len because of the case when |
| 20644 | | // assigning `[N:S]T` to `[N]T`. This is allowed; the sentinel is omitted. |
| 20645 | | assert(bytes.len >= dest_len); |
| 20646 | | const elems = try arena.alloc(Value, @intCast(usize, dest_len)); |
| 20647 | | for (elems) |*elem, i| { |
| 20648 | | elem.* = try Value.Tag.int_u64.create(arena, bytes[i]); |
| 20649 | | } |
| 20650 | | |
| 20651 | | parent.val.* = try Value.Tag.aggregate.create(arena, elems); |
| 20652 | | |
| 20653 | | return ComptimePtrMutationKit{ |
| 20654 | | .decl_ref_mut = parent.decl_ref_mut, |
| 20655 | | .val = &elems[elem_ptr.index], |
| 20656 | | .ty = elem_ty, |
| 20657 | | }; |
| 20658 | | }, |
| 20659 | | .str_lit => { |
| 20660 | | // An array is memory-optimized to store a slice of bytes, but we are about |
| 20661 | | // to modify an individual field and the representation has to change. |
| 20662 | | // If we wanted to avoid this, there would need to be special detection |
| 20663 | | // elsewhere to identify when writing a value to an array element that is stored |
| 20664 | | // using the `str_lit` tag, and handle it without making a call to this function. |
| 20665 | | const arena = parent.beginArena(sema.mod); |
| 20666 | | defer parent.finishArena(sema.mod); |
| 20667 | | |
| 20668 | | const str_lit = parent.val.castTag(.str_lit).?.data; |
| 20669 | | const dest_len = parent.ty.arrayLenIncludingSentinel(); |
| 20670 | | const bytes = sema.mod.string_literal_bytes.items[str_lit.index..][0..str_lit.len]; |
| 20671 | | const elems = try arena.alloc(Value, @intCast(usize, dest_len)); |
| 20672 | | for (bytes) |byte, i| { |
| 20673 | | elems[i] = try Value.Tag.int_u64.create(arena, byte); |
| 20674 | | } |
| 20675 | | if (parent.ty.sentinel()) |sent_val| { |
| 20676 | | assert(elems.len == bytes.len + 1); |
| 20677 | | elems[bytes.len] = sent_val; |
| 20678 | | } |
| 20679 | | |
| 20680 | | parent.val.* = try Value.Tag.aggregate.create(arena, elems); |
| 20681 | | |
| 20682 | | return ComptimePtrMutationKit{ |
| 20683 | | .decl_ref_mut = parent.decl_ref_mut, |
| 20684 | | .val = &elems[elem_ptr.index], |
| 20685 | | .ty = elem_ty, |
| 20686 | | }; |
| 20687 | | }, |
| 20688 | | .repeated => { |
| 20689 | | // An array is memory-optimized to store only a single element value, and |
| 20690 | | // that value is understood to be the same for the entire length of the array. |
| 20691 | | // However, now we want to modify an individual field and so the |
| 20692 | | // representation has to change. If we wanted to avoid this, there would |
| 20693 | | // need to be special detection elsewhere to identify when writing a value to an |
| 20694 | | // array element that is stored using the `repeated` tag, and handle it |
| 20695 | | // without making a call to this function. |
| 20696 | | const arena = parent.beginArena(sema.mod); |
| 20697 | | defer parent.finishArena(sema.mod); |
| 20631 | var parent = try beginComptimePtrMutation(sema, block, src, elem_ptr.array_ptr, elem_ptr.elem_ty); |
| 20632 | switch (parent.pointee) { |
| 20633 | .direct => |val_ptr| switch (parent.ty.zigTypeTag()) { |
| 20634 | .Array, .Vector => { |
| 20635 | const check_len = parent.ty.arrayLenIncludingSentinel(); |
| 20636 | if (elem_ptr.index >= check_len) { |
| 20637 | // TODO have the parent include the decl so we can say "declared here" |
| 20638 | return sema.fail(block, src, "comptime store of index {d} out of bounds of array length {d}", .{ |
| 20639 | elem_ptr.index, check_len, |
| 20640 | }); |
| 20641 | } |
| 20642 | const elem_ty = parent.ty.childType(); |
| 20643 | switch (val_ptr.tag()) { |
| 20644 | .undef => { |
| 20645 | // An array has been initialized to undefined at comptime and now we |
| 20646 | // are for the first time setting an element. We must change the representation |
| 20647 | // of the array from `undef` to `array`. |
| 20648 | const arena = parent.beginArena(sema.mod); |
| 20649 | defer parent.finishArena(sema.mod); |
| 20650 | |
| 20651 | const array_len_including_sentinel = |
| 20652 | try sema.usizeCast(block, src, parent.ty.arrayLenIncludingSentinel()); |
| 20653 | const elems = try arena.alloc(Value, array_len_including_sentinel); |
| 20654 | mem.set(Value, elems, Value.undef); |
| 20655 | |
| 20656 | val_ptr.* = try Value.Tag.aggregate.create(arena, elems); |
| 20657 | |
| 20658 | return beginComptimePtrMutationInner( |
| 20659 | sema, |
| 20660 | block, |
| 20661 | src, |
| 20662 | elem_ty, |
| 20663 | &elems[elem_ptr.index], |
| 20664 | ptr_elem_ty, |
| 20665 | parent.decl_ref_mut, |
| 20666 | ); |
| 20667 | }, |
| 20668 | .bytes => { |
| 20669 | // An array is memory-optimized to store a slice of bytes, but we are about |
| 20670 | // to modify an individual field and the representation has to change. |
| 20671 | // If we wanted to avoid this, there would need to be special detection |
| 20672 | // elsewhere to identify when writing a value to an array element that is stored |
| 20673 | // using the `bytes` tag, and handle it without making a call to this function. |
| 20674 | const arena = parent.beginArena(sema.mod); |
| 20675 | defer parent.finishArena(sema.mod); |
| 20676 | |
| 20677 | const bytes = val_ptr.castTag(.bytes).?.data; |
| 20678 | const dest_len = parent.ty.arrayLenIncludingSentinel(); |
| 20679 | // bytes.len may be one greater than dest_len because of the case when |
| 20680 | // assigning `[N:S]T` to `[N]T`. This is allowed; the sentinel is omitted. |
| 20681 | assert(bytes.len >= dest_len); |
| 20682 | const elems = try arena.alloc(Value, @intCast(usize, dest_len)); |
| 20683 | for (elems) |*elem, i| { |
| 20684 | elem.* = try Value.Tag.int_u64.create(arena, bytes[i]); |
| 20685 | } |
| 20698 | 20686 | |
| 20699 | | const repeated_val = try parent.val.castTag(.repeated).?.data.copy(arena); |
| 20700 | | const array_len_including_sentinel = |
| 20701 | | try sema.usizeCast(block, src, parent.ty.arrayLenIncludingSentinel()); |
| 20702 | | const elems = try arena.alloc(Value, array_len_including_sentinel); |
| 20703 | | mem.set(Value, elems, repeated_val); |
| 20687 | val_ptr.* = try Value.Tag.aggregate.create(arena, elems); |
| 20704 | 20688 | |
| 20705 | | parent.val.* = try Value.Tag.aggregate.create(arena, elems); |
| 20689 | return beginComptimePtrMutationInner( |
| 20690 | sema, |
| 20691 | block, |
| 20692 | src, |
| 20693 | elem_ty, |
| 20694 | &elems[elem_ptr.index], |
| 20695 | ptr_elem_ty, |
| 20696 | parent.decl_ref_mut, |
| 20697 | ); |
| 20698 | }, |
| 20699 | .str_lit => { |
| 20700 | // An array is memory-optimized to store a slice of bytes, but we are about |
| 20701 | // to modify an individual field and the representation has to change. |
| 20702 | // If we wanted to avoid this, there would need to be special detection |
| 20703 | // elsewhere to identify when writing a value to an array element that is stored |
| 20704 | // using the `str_lit` tag, and handle it without making a call to this function. |
| 20705 | const arena = parent.beginArena(sema.mod); |
| 20706 | defer parent.finishArena(sema.mod); |
| 20707 | |
| 20708 | const str_lit = val_ptr.castTag(.str_lit).?.data; |
| 20709 | const dest_len = parent.ty.arrayLenIncludingSentinel(); |
| 20710 | const bytes = sema.mod.string_literal_bytes.items[str_lit.index..][0..str_lit.len]; |
| 20711 | const elems = try arena.alloc(Value, @intCast(usize, dest_len)); |
| 20712 | for (bytes) |byte, i| { |
| 20713 | elems[i] = try Value.Tag.int_u64.create(arena, byte); |
| 20714 | } |
| 20715 | if (parent.ty.sentinel()) |sent_val| { |
| 20716 | assert(elems.len == bytes.len + 1); |
| 20717 | elems[bytes.len] = sent_val; |
| 20718 | } |
| 20706 | 20719 | |
| 20707 | | return ComptimePtrMutationKit{ |
| 20708 | | .decl_ref_mut = parent.decl_ref_mut, |
| 20709 | | .val = &elems[elem_ptr.index], |
| 20710 | | .ty = elem_ty, |
| 20711 | | }; |
| 20712 | | }, |
| 20720 | val_ptr.* = try Value.Tag.aggregate.create(arena, elems); |
| 20713 | 20721 | |
| 20714 | | .aggregate => return ComptimePtrMutationKit{ |
| 20715 | | .decl_ref_mut = parent.decl_ref_mut, |
| 20716 | | .val = &parent.val.castTag(.aggregate).?.data[elem_ptr.index], |
| 20717 | | .ty = elem_ty, |
| 20718 | | }, |
| 20722 | return beginComptimePtrMutationInner( |
| 20723 | sema, |
| 20724 | block, |
| 20725 | src, |
| 20726 | elem_ty, |
| 20727 | &elems[elem_ptr.index], |
| 20728 | ptr_elem_ty, |
| 20729 | parent.decl_ref_mut, |
| 20730 | ); |
| 20731 | }, |
| 20732 | .repeated => { |
| 20733 | // An array is memory-optimized to store only a single element value, and |
| 20734 | // that value is understood to be the same for the entire length of the array. |
| 20735 | // However, now we want to modify an individual field and so the |
| 20736 | // representation has to change. If we wanted to avoid this, there would |
| 20737 | // need to be special detection elsewhere to identify when writing a value to an |
| 20738 | // array element that is stored using the `repeated` tag, and handle it |
| 20739 | // without making a call to this function. |
| 20740 | const arena = parent.beginArena(sema.mod); |
| 20741 | defer parent.finishArena(sema.mod); |
| 20742 | |
| 20743 | const repeated_val = try val_ptr.castTag(.repeated).?.data.copy(arena); |
| 20744 | const array_len_including_sentinel = |
| 20745 | try sema.usizeCast(block, src, parent.ty.arrayLenIncludingSentinel()); |
| 20746 | const elems = try arena.alloc(Value, array_len_including_sentinel); |
| 20747 | mem.set(Value, elems, repeated_val); |
| 20748 | |
| 20749 | val_ptr.* = try Value.Tag.aggregate.create(arena, elems); |
| 20750 | |
| 20751 | return beginComptimePtrMutationInner( |
| 20752 | sema, |
| 20753 | block, |
| 20754 | src, |
| 20755 | elem_ty, |
| 20756 | &elems[elem_ptr.index], |
| 20757 | ptr_elem_ty, |
| 20758 | parent.decl_ref_mut, |
| 20759 | ); |
| 20760 | }, |
| 20719 | 20761 | |
| 20720 | | .the_only_possible_value => { |
| 20721 | | const duped = try sema.arena.create(Value); |
| 20722 | | duped.* = Value.initTag(.the_only_possible_value); |
| 20723 | | return ComptimePtrMutationKit{ |
| 20724 | | .decl_ref_mut = parent.decl_ref_mut, |
| 20725 | | .val = duped, |
| 20726 | | .ty = elem_ty, |
| 20727 | | }; |
| 20728 | | }, |
| 20762 | .aggregate => return beginComptimePtrMutationInner( |
| 20763 | sema, |
| 20764 | block, |
| 20765 | src, |
| 20766 | elem_ty, |
| 20767 | &val_ptr.castTag(.aggregate).?.data[elem_ptr.index], |
| 20768 | ptr_elem_ty, |
| 20769 | parent.decl_ref_mut, |
| 20770 | ), |
| 20771 | |
| 20772 | .the_only_possible_value => { |
| 20773 | const duped = try sema.arena.create(Value); |
| 20774 | duped.* = Value.initTag(.the_only_possible_value); |
| 20775 | return beginComptimePtrMutationInner( |
| 20776 | sema, |
| 20777 | block, |
| 20778 | src, |
| 20779 | elem_ty, |
| 20780 | duped, |
| 20781 | ptr_elem_ty, |
| 20782 | parent.decl_ref_mut, |
| 20783 | ); |
| 20784 | }, |
| 20729 | 20785 | |
| 20730 | | else => unreachable, |
| 20731 | | } |
| 20786 | else => unreachable, |
| 20787 | } |
| 20788 | }, |
| 20789 | else => { |
| 20790 | if (elem_ptr.index != 0) { |
| 20791 | // TODO include a "declared here" note for the decl |
| 20792 | return sema.fail(block, src, "out of bounds comptime store of index {d}", .{ |
| 20793 | elem_ptr.index, |
| 20794 | }); |
| 20795 | } |
| 20796 | return beginComptimePtrMutationInner( |
| 20797 | sema, |
| 20798 | block, |
| 20799 | src, |
| 20800 | parent.ty, |
| 20801 | val_ptr, |
| 20802 | ptr_elem_ty, |
| 20803 | parent.decl_ref_mut, |
| 20804 | ); |
| 20805 | }, |
| 20732 | 20806 | }, |
| 20733 | | else => { |
| 20734 | | if (elem_ptr.index != 0) { |
| 20735 | | // TODO include a "declared here" note for the decl |
| 20736 | | return sema.fail(block, src, "out of bounds comptime store of index {d}", .{ |
| 20737 | | elem_ptr.index, |
| 20738 | | }); |
| 20807 | .reinterpret => |reinterpret| { |
| 20808 | if (!elem_ptr.elem_ty.hasWellDefinedLayout()) { |
| 20809 | // Even though the parent value type has well-defined memory layout, our |
| 20810 | // pointer type does not. |
| 20811 | return ComptimePtrMutationKit{ |
| 20812 | .decl_ref_mut = parent.decl_ref_mut, |
| 20813 | .pointee = .bad_ptr_ty, |
| 20814 | .ty = elem_ptr.elem_ty, |
| 20815 | }; |
| 20739 | 20816 | } |
| 20817 | |
| 20818 | const elem_abi_size_u64 = try sema.typeAbiSize(block, src, elem_ptr.elem_ty); |
| 20819 | const elem_abi_size = try sema.usizeCast(block, src, elem_abi_size_u64); |
| 20740 | 20820 | return ComptimePtrMutationKit{ |
| 20741 | 20821 | .decl_ref_mut = parent.decl_ref_mut, |
| 20742 | | .val = parent.val, |
| 20822 | .pointee = .{ .reinterpret = .{ |
| 20823 | .val_ptr = reinterpret.val_ptr, |
| 20824 | .byte_offset = reinterpret.byte_offset + elem_abi_size * elem_ptr.index, |
| 20825 | } }, |
| 20743 | 20826 | .ty = parent.ty, |
| 20744 | 20827 | }; |
| 20745 | 20828 | }, |
| 20829 | .bad_decl_ty, .bad_ptr_ty => return parent, |
| 20746 | 20830 | } |
| 20747 | 20831 | }, |
| 20748 | 20832 | .field_ptr => { |
| 20749 | 20833 | const field_ptr = ptr_val.castTag(.field_ptr).?.data; |
| 20750 | | var parent = try beginComptimePtrMutation(sema, block, src, field_ptr.container_ptr); |
| 20751 | 20834 | const field_index = @intCast(u32, field_ptr.field_index); |
| 20752 | | switch (parent.val.tag()) { |
| 20753 | | .undef => { |
| 20754 | | // A struct or union has been initialized to undefined at comptime and now we |
| 20755 | | // are for the first time setting a field. We must change the representation |
| 20756 | | // of the struct/union from `undef` to `struct`/`union`. |
| 20757 | | const arena = parent.beginArena(sema.mod); |
| 20758 | | defer parent.finishArena(sema.mod); |
| 20759 | 20835 | |
| 20760 | | switch (parent.ty.zigTypeTag()) { |
| 20761 | | .Struct => { |
| 20762 | | const fields = try arena.alloc(Value, parent.ty.structFieldCount()); |
| 20763 | | mem.set(Value, fields, Value.undef); |
| 20836 | var parent = try beginComptimePtrMutation(sema, block, src, field_ptr.container_ptr, field_ptr.container_ty); |
| 20837 | switch (parent.pointee) { |
| 20838 | .direct => |val_ptr| switch (val_ptr.tag()) { |
| 20839 | .undef => { |
| 20840 | // A struct or union has been initialized to undefined at comptime and now we |
| 20841 | // are for the first time setting a field. We must change the representation |
| 20842 | // of the struct/union from `undef` to `struct`/`union`. |
| 20843 | const arena = parent.beginArena(sema.mod); |
| 20844 | defer parent.finishArena(sema.mod); |
| 20845 | |
| 20846 | switch (parent.ty.zigTypeTag()) { |
| 20847 | .Struct => { |
| 20848 | const fields = try arena.alloc(Value, parent.ty.structFieldCount()); |
| 20849 | mem.set(Value, fields, Value.undef); |
| 20850 | |
| 20851 | val_ptr.* = try Value.Tag.aggregate.create(arena, fields); |
| 20852 | |
| 20853 | return beginComptimePtrMutationInner( |
| 20854 | sema, |
| 20855 | block, |
| 20856 | src, |
| 20857 | parent.ty.structFieldType(field_index), |
| 20858 | &fields[field_index], |
| 20859 | ptr_elem_ty, |
| 20860 | parent.decl_ref_mut, |
| 20861 | ); |
| 20862 | }, |
| 20863 | .Union => { |
| 20864 | const payload = try arena.create(Value.Payload.Union); |
| 20865 | payload.* = .{ .data = .{ |
| 20866 | .tag = try Value.Tag.enum_field_index.create(arena, field_index), |
| 20867 | .val = Value.undef, |
| 20868 | } }; |
| 20764 | 20869 | |
| 20765 | | parent.val.* = try Value.Tag.aggregate.create(arena, fields); |
| 20870 | val_ptr.* = Value.initPayload(&payload.base); |
| 20766 | 20871 | |
| 20767 | | return ComptimePtrMutationKit{ |
| 20768 | | .decl_ref_mut = parent.decl_ref_mut, |
| 20769 | | .val = &fields[field_index], |
| 20770 | | .ty = parent.ty.structFieldType(field_index), |
| 20771 | | }; |
| 20772 | | }, |
| 20773 | | .Union => { |
| 20774 | | const payload = try arena.create(Value.Payload.Union); |
| 20775 | | payload.* = .{ .data = .{ |
| 20776 | | .tag = try Value.Tag.enum_field_index.create(arena, field_index), |
| 20777 | | .val = Value.undef, |
| 20778 | | } }; |
| 20872 | return beginComptimePtrMutationInner( |
| 20873 | sema, |
| 20874 | block, |
| 20875 | src, |
| 20876 | parent.ty.structFieldType(field_index), |
| 20877 | &payload.data.val, |
| 20878 | ptr_elem_ty, |
| 20879 | parent.decl_ref_mut, |
| 20880 | ); |
| 20881 | }, |
| 20882 | .Pointer => { |
| 20883 | assert(parent.ty.isSlice()); |
| 20884 | val_ptr.* = try Value.Tag.slice.create(arena, .{ |
| 20885 | .ptr = Value.undef, |
| 20886 | .len = Value.undef, |
| 20887 | }); |
| 20888 | |
| 20889 | switch (field_index) { |
| 20890 | Value.Payload.Slice.ptr_index => return beginComptimePtrMutationInner( |
| 20891 | sema, |
| 20892 | block, |
| 20893 | src, |
| 20894 | parent.ty.slicePtrFieldType(try sema.arena.create(Type.SlicePtrFieldTypeBuffer)), |
| 20895 | &val_ptr.castTag(.slice).?.data.ptr, |
| 20896 | ptr_elem_ty, |
| 20897 | parent.decl_ref_mut, |
| 20898 | ), |
| 20899 | Value.Payload.Slice.len_index => return beginComptimePtrMutationInner( |
| 20900 | sema, |
| 20901 | block, |
| 20902 | src, |
| 20903 | Type.usize, |
| 20904 | &val_ptr.castTag(.slice).?.data.len, |
| 20905 | ptr_elem_ty, |
| 20906 | parent.decl_ref_mut, |
| 20907 | ), |
| 20908 | |
| 20909 | else => unreachable, |
| 20910 | } |
| 20911 | }, |
| 20912 | else => unreachable, |
| 20913 | } |
| 20914 | }, |
| 20915 | .aggregate => return beginComptimePtrMutationInner( |
| 20916 | sema, |
| 20917 | block, |
| 20918 | src, |
| 20919 | parent.ty.structFieldType(field_index), |
| 20920 | &val_ptr.castTag(.aggregate).?.data[field_index], |
| 20921 | ptr_elem_ty, |
| 20922 | parent.decl_ref_mut, |
| 20923 | ), |
| 20779 | 20924 | |
| 20780 | | parent.val.* = Value.initPayload(&payload.base); |
| 20925 | .@"union" => { |
| 20926 | // We need to set the active field of the union. |
| 20927 | const arena = parent.beginArena(sema.mod); |
| 20928 | defer parent.finishArena(sema.mod); |
| 20781 | 20929 | |
| 20782 | | return ComptimePtrMutationKit{ |
| 20783 | | .decl_ref_mut = parent.decl_ref_mut, |
| 20784 | | .val = &payload.data.val, |
| 20785 | | .ty = parent.ty.structFieldType(field_index), |
| 20786 | | }; |
| 20787 | | }, |
| 20788 | | .Pointer => { |
| 20789 | | assert(parent.ty.isSlice()); |
| 20790 | | parent.val.* = try Value.Tag.slice.create(arena, .{ |
| 20791 | | .ptr = Value.undef, |
| 20792 | | .len = Value.undef, |
| 20793 | | }); |
| 20930 | const payload = &val_ptr.castTag(.@"union").?.data; |
| 20931 | payload.tag = try Value.Tag.enum_field_index.create(arena, field_index); |
| 20794 | 20932 | |
| 20795 | | switch (field_index) { |
| 20796 | | Value.Payload.Slice.ptr_index => return ComptimePtrMutationKit{ |
| 20797 | | .decl_ref_mut = parent.decl_ref_mut, |
| 20798 | | .val = &parent.val.castTag(.slice).?.data.ptr, |
| 20799 | | .ty = parent.ty.slicePtrFieldType(try sema.arena.create(Type.SlicePtrFieldTypeBuffer)), |
| 20800 | | }, |
| 20801 | | Value.Payload.Slice.len_index => return ComptimePtrMutationKit{ |
| 20802 | | .decl_ref_mut = parent.decl_ref_mut, |
| 20803 | | .val = &parent.val.castTag(.slice).?.data.len, |
| 20804 | | .ty = Type.usize, |
| 20805 | | }, |
| 20806 | | else => unreachable, |
| 20807 | | } |
| 20808 | | }, |
| 20809 | | else => unreachable, |
| 20810 | | } |
| 20811 | | }, |
| 20812 | | .aggregate => return ComptimePtrMutationKit{ |
| 20813 | | .decl_ref_mut = parent.decl_ref_mut, |
| 20814 | | .val = &parent.val.castTag(.aggregate).?.data[field_index], |
| 20815 | | .ty = parent.ty.structFieldType(field_index), |
| 20816 | | }, |
| 20817 | | .@"union" => { |
| 20818 | | // We need to set the active field of the union. |
| 20819 | | const arena = parent.beginArena(sema.mod); |
| 20820 | | defer parent.finishArena(sema.mod); |
| 20933 | return beginComptimePtrMutationInner( |
| 20934 | sema, |
| 20935 | block, |
| 20936 | src, |
| 20937 | parent.ty.structFieldType(field_index), |
| 20938 | &payload.val, |
| 20939 | ptr_elem_ty, |
| 20940 | parent.decl_ref_mut, |
| 20941 | ); |
| 20942 | }, |
| 20943 | .slice => switch (field_index) { |
| 20944 | Value.Payload.Slice.ptr_index => return beginComptimePtrMutationInner( |
| 20945 | sema, |
| 20946 | block, |
| 20947 | src, |
| 20948 | parent.ty.slicePtrFieldType(try sema.arena.create(Type.SlicePtrFieldTypeBuffer)), |
| 20949 | &val_ptr.castTag(.slice).?.data.ptr, |
| 20950 | ptr_elem_ty, |
| 20951 | parent.decl_ref_mut, |
| 20952 | ), |
| 20953 | |
| 20954 | Value.Payload.Slice.len_index => return beginComptimePtrMutationInner( |
| 20955 | sema, |
| 20956 | block, |
| 20957 | src, |
| 20958 | Type.usize, |
| 20959 | &val_ptr.castTag(.slice).?.data.len, |
| 20960 | ptr_elem_ty, |
| 20961 | parent.decl_ref_mut, |
| 20962 | ), |
| 20821 | 20963 | |
| 20822 | | const payload = &parent.val.castTag(.@"union").?.data; |
| 20823 | | payload.tag = try Value.Tag.enum_field_index.create(arena, field_index); |
| 20964 | else => unreachable, |
| 20965 | }, |
| 20824 | 20966 | |
| 20967 | else => unreachable, |
| 20968 | }, |
| 20969 | .reinterpret => |reinterpret| { |
| 20970 | const field_offset_u64 = field_ptr.container_ty.structFieldOffset(field_index, target); |
| 20971 | const field_offset = try sema.usizeCast(block, src, field_offset_u64); |
| 20825 | 20972 | return ComptimePtrMutationKit{ |
| 20826 | 20973 | .decl_ref_mut = parent.decl_ref_mut, |
| 20827 | | .val = &payload.val, |
| 20828 | | .ty = parent.ty.structFieldType(field_index), |
| 20974 | .pointee = .{ .reinterpret = .{ |
| 20975 | .val_ptr = reinterpret.val_ptr, |
| 20976 | .byte_offset = reinterpret.byte_offset + field_offset, |
| 20977 | } }, |
| 20978 | .ty = parent.ty, |
| 20829 | 20979 | }; |
| 20830 | 20980 | }, |
| 20831 | | .slice => switch (field_index) { |
| 20832 | | Value.Payload.Slice.ptr_index => return ComptimePtrMutationKit{ |
| 20833 | | .decl_ref_mut = parent.decl_ref_mut, |
| 20834 | | .val = &parent.val.castTag(.slice).?.data.ptr, |
| 20835 | | .ty = parent.ty.slicePtrFieldType(try sema.arena.create(Type.SlicePtrFieldTypeBuffer)), |
| 20836 | | }, |
| 20837 | | Value.Payload.Slice.len_index => return ComptimePtrMutationKit{ |
| 20838 | | .decl_ref_mut = parent.decl_ref_mut, |
| 20839 | | .val = &parent.val.castTag(.slice).?.data.len, |
| 20840 | | .ty = Type.usize, |
| 20841 | | }, |
| 20842 | | else => unreachable, |
| 20843 | | }, |
| 20844 | | |
| 20845 | | else => unreachable, |
| 20981 | .bad_decl_ty, .bad_ptr_ty => return parent, |
| 20846 | 20982 | } |
| 20847 | 20983 | }, |
| 20848 | 20984 | .eu_payload_ptr => { |
| 20849 | 20985 | const eu_ptr = ptr_val.castTag(.eu_payload_ptr).?.data; |
| 20850 | | var parent = try beginComptimePtrMutation(sema, block, src, eu_ptr.container_ptr); |
| 20851 | | const payload_ty = parent.ty.errorUnionPayload(); |
| 20852 | | switch (parent.val.tag()) { |
| 20853 | | else => { |
| 20854 | | // An error union has been initialized to undefined at comptime and now we |
| 20855 | | // are for the first time setting the payload. We must change the |
| 20856 | | // representation of the error union from `undef` to `opt_payload`. |
| 20857 | | const arena = parent.beginArena(sema.mod); |
| 20858 | | defer parent.finishArena(sema.mod); |
| 20859 | | |
| 20860 | | const payload = try arena.create(Value.Payload.SubValue); |
| 20861 | | payload.* = .{ |
| 20862 | | .base = .{ .tag = .eu_payload }, |
| 20863 | | .data = Value.undef, |
| 20864 | | }; |
| 20986 | var parent = try beginComptimePtrMutation(sema, block, src, eu_ptr.container_ptr, eu_ptr.container_ty); |
| 20987 | switch (parent.pointee) { |
| 20988 | .direct => |val_ptr| { |
| 20989 | const payload_ty = parent.ty.errorUnionPayload(); |
| 20990 | switch (val_ptr.tag()) { |
| 20991 | else => { |
| 20992 | // An error union has been initialized to undefined at comptime and now we |
| 20993 | // are for the first time setting the payload. We must change the |
| 20994 | // representation of the error union from `undef` to `opt_payload`. |
| 20995 | const arena = parent.beginArena(sema.mod); |
| 20996 | defer parent.finishArena(sema.mod); |
| 20997 | |
| 20998 | const payload = try arena.create(Value.Payload.SubValue); |
| 20999 | payload.* = .{ |
| 21000 | .base = .{ .tag = .eu_payload }, |
| 21001 | .data = Value.undef, |
| 21002 | }; |
| 20865 | 21003 | |
| 20866 | | parent.val.* = Value.initPayload(&payload.base); |
| 21004 | val_ptr.* = Value.initPayload(&payload.base); |
| 20867 | 21005 | |
| 20868 | | return ComptimePtrMutationKit{ |
| 20869 | | .decl_ref_mut = parent.decl_ref_mut, |
| 20870 | | .val = &payload.data, |
| 20871 | | .ty = payload_ty, |
| 20872 | | }; |
| 21006 | return ComptimePtrMutationKit{ |
| 21007 | .decl_ref_mut = parent.decl_ref_mut, |
| 21008 | .pointee = .{ .direct = &payload.data }, |
| 21009 | .ty = payload_ty, |
| 21010 | }; |
| 21011 | }, |
| 21012 | .eu_payload => return ComptimePtrMutationKit{ |
| 21013 | .decl_ref_mut = parent.decl_ref_mut, |
| 21014 | .pointee = .{ .direct = &val_ptr.castTag(.eu_payload).?.data }, |
| 21015 | .ty = payload_ty, |
| 21016 | }, |
| 21017 | } |
| 20873 | 21018 | }, |
| 20874 | | .eu_payload => return ComptimePtrMutationKit{ |
| 21019 | .bad_decl_ty, .bad_ptr_ty => return parent, |
| 21020 | // Even though the parent value type has well-defined memory layout, our |
| 21021 | // pointer type does not. |
| 21022 | .reinterpret => return ComptimePtrMutationKit{ |
| 20875 | 21023 | .decl_ref_mut = parent.decl_ref_mut, |
| 20876 | | .val = &parent.val.castTag(.eu_payload).?.data, |
| 20877 | | .ty = payload_ty, |
| 21024 | .pointee = .bad_ptr_ty, |
| 21025 | .ty = eu_ptr.container_ty, |
| 20878 | 21026 | }, |
| 20879 | 21027 | } |
| 20880 | 21028 | }, |
| 20881 | 21029 | .opt_payload_ptr => { |
| 20882 | 21030 | const opt_ptr = ptr_val.castTag(.opt_payload_ptr).?.data; |
| 20883 | | var parent = try beginComptimePtrMutation(sema, block, src, opt_ptr.container_ptr); |
| 20884 | | const payload_ty = try parent.ty.optionalChildAlloc(sema.arena); |
| 20885 | | switch (parent.val.tag()) { |
| 20886 | | .undef, .null_value => { |
| 20887 | | // An optional has been initialized to undefined at comptime and now we |
| 20888 | | // are for the first time setting the payload. We must change the |
| 20889 | | // representation of the optional from `undef` to `opt_payload`. |
| 20890 | | const arena = parent.beginArena(sema.mod); |
| 20891 | | defer parent.finishArena(sema.mod); |
| 20892 | | |
| 20893 | | const payload = try arena.create(Value.Payload.SubValue); |
| 20894 | | payload.* = .{ |
| 20895 | | .base = .{ .tag = .opt_payload }, |
| 20896 | | .data = Value.undef, |
| 20897 | | }; |
| 21031 | var parent = try beginComptimePtrMutation(sema, block, src, opt_ptr.container_ptr, opt_ptr.container_ty); |
| 21032 | switch (parent.pointee) { |
| 21033 | .direct => |val_ptr| { |
| 21034 | const payload_ty = try parent.ty.optionalChildAlloc(sema.arena); |
| 21035 | switch (val_ptr.tag()) { |
| 21036 | .undef, .null_value => { |
| 21037 | // An optional has been initialized to undefined at comptime and now we |
| 21038 | // are for the first time setting the payload. We must change the |
| 21039 | // representation of the optional from `undef` to `opt_payload`. |
| 21040 | const arena = parent.beginArena(sema.mod); |
| 21041 | defer parent.finishArena(sema.mod); |
| 20898 | 21042 | |
| 20899 | | parent.val.* = Value.initPayload(&payload.base); |
| 21043 | const payload = try arena.create(Value.Payload.SubValue); |
| 21044 | payload.* = .{ |
| 21045 | .base = .{ .tag = .opt_payload }, |
| 21046 | .data = Value.undef, |
| 21047 | }; |
| 20900 | 21048 | |
| 20901 | | return ComptimePtrMutationKit{ |
| 20902 | | .decl_ref_mut = parent.decl_ref_mut, |
| 20903 | | .val = &payload.data, |
| 20904 | | .ty = payload_ty, |
| 20905 | | }; |
| 21049 | val_ptr.* = Value.initPayload(&payload.base); |
| 21050 | |
| 21051 | return ComptimePtrMutationKit{ |
| 21052 | .decl_ref_mut = parent.decl_ref_mut, |
| 21053 | .pointee = .{ .direct = &payload.data }, |
| 21054 | .ty = payload_ty, |
| 21055 | }; |
| 21056 | }, |
| 21057 | .opt_payload => return ComptimePtrMutationKit{ |
| 21058 | .decl_ref_mut = parent.decl_ref_mut, |
| 21059 | .pointee = .{ .direct = &val_ptr.castTag(.opt_payload).?.data }, |
| 21060 | .ty = payload_ty, |
| 21061 | }, |
| 21062 | |
| 21063 | else => unreachable, |
| 21064 | } |
| 20906 | 21065 | }, |
| 20907 | | .opt_payload => return ComptimePtrMutationKit{ |
| 21066 | .bad_decl_ty, .bad_ptr_ty => return parent, |
| 21067 | // Even though the parent value type has well-defined memory layout, our |
| 21068 | // pointer type does not. |
| 21069 | .reinterpret => return ComptimePtrMutationKit{ |
| 20908 | 21070 | .decl_ref_mut = parent.decl_ref_mut, |
| 20909 | | .val = &parent.val.castTag(.opt_payload).?.data, |
| 20910 | | .ty = payload_ty, |
| 21071 | .pointee = .bad_ptr_ty, |
| 21072 | .ty = opt_ptr.container_ty, |
| 20911 | 21073 | }, |
| 20912 | | |
| 20913 | | else => unreachable, |
| 20914 | 21074 | } |
| 20915 | 21075 | }, |
| 20916 | 21076 | .decl_ref => unreachable, // isComptimeMutablePtr() has been checked already |
| ... | ... | @@ -20918,10 +21078,63 @@ fn beginComptimePtrMutation( |
| 20918 | 21078 | } |
| 20919 | 21079 | } |
| 20920 | 21080 | |
| 21081 | fn beginComptimePtrMutationInner( |
| 21082 | sema: *Sema, |
| 21083 | block: *Block, |
| 21084 | src: LazySrcLoc, |
| 21085 | decl_ty: Type, |
| 21086 | decl_val: *Value, |
| 21087 | ptr_elem_ty: Type, |
| 21088 | decl_ref_mut: Value.Payload.DeclRefMut.Data, |
| 21089 | ) CompileError!ComptimePtrMutationKit { |
| 21090 | const target = sema.mod.getTarget(); |
| 21091 | const coerce_ok = (try sema.coerceInMemoryAllowed(block, ptr_elem_ty, decl_ty, true, target, src, src)) == .ok; |
| 21092 | if (coerce_ok) { |
| 21093 | return ComptimePtrMutationKit{ |
| 21094 | .decl_ref_mut = decl_ref_mut, |
| 21095 | .pointee = .{ .direct = decl_val }, |
| 21096 | .ty = decl_ty, |
| 21097 | }; |
| 21098 | } |
| 21099 | |
| 21100 | // Handle the case that the decl is an array and we're actually trying to point to an element. |
| 21101 | if (decl_ty.isArrayOrVector()) { |
| 21102 | const decl_elem_ty = decl_ty.childType(); |
| 21103 | if ((try sema.coerceInMemoryAllowed(block, ptr_elem_ty, decl_elem_ty, true, target, src, src)) == .ok) { |
| 21104 | return ComptimePtrMutationKit{ |
| 21105 | .decl_ref_mut = decl_ref_mut, |
| 21106 | .pointee = .{ .direct = decl_val }, |
| 21107 | .ty = decl_ty, |
| 21108 | }; |
| 21109 | } |
| 21110 | } |
| 21111 | |
| 21112 | if (!decl_ty.hasWellDefinedLayout()) { |
| 21113 | return ComptimePtrMutationKit{ |
| 21114 | .decl_ref_mut = decl_ref_mut, |
| 21115 | .pointee = .{ .bad_decl_ty = {} }, |
| 21116 | .ty = decl_ty, |
| 21117 | }; |
| 21118 | } |
| 21119 | if (!ptr_elem_ty.hasWellDefinedLayout()) { |
| 21120 | return ComptimePtrMutationKit{ |
| 21121 | .decl_ref_mut = decl_ref_mut, |
| 21122 | .pointee = .{ .bad_ptr_ty = {} }, |
| 21123 | .ty = ptr_elem_ty, |
| 21124 | }; |
| 21125 | } |
| 21126 | return ComptimePtrMutationKit{ |
| 21127 | .decl_ref_mut = decl_ref_mut, |
| 21128 | .pointee = .{ .reinterpret = .{ |
| 21129 | .val_ptr = decl_val, |
| 21130 | .byte_offset = 0, |
| 21131 | } }, |
| 21132 | .ty = decl_ty, |
| 21133 | }; |
| 21134 | } |
| 21135 | |
| 20921 | 21136 | const TypedValueAndOffset = struct { |
| 20922 | 21137 | tv: TypedValue, |
| 20923 | | /// The starting byte offset of `val` from `root_val`. |
| 20924 | | /// If the type does not have a well-defined memory layout, this is null. |
| 20925 | 21138 | byte_offset: usize, |
| 20926 | 21139 | }; |
| 20927 | 21140 | |
| ... | ... | @@ -21197,7 +21410,7 @@ fn bitCast( |
| 21197 | 21410 | return block.addBitCast(dest_ty, inst); |
| 21198 | 21411 | } |
| 21199 | 21412 | |
| 21200 | | pub fn bitCastVal( |
| 21413 | fn bitCastVal( |
| 21201 | 21414 | sema: *Sema, |
| 21202 | 21415 | block: *Block, |
| 21203 | 21416 | src: LazySrcLoc, |