diff options
| author | Cody Tapscott <topolarity@tapscott.me> | 2022-03-11 14:22:53 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2022-03-14 21:42:43 -0700 |
| commit | 5fa057053ce32274b878077e5abff82335530fc8 (patch) | |
| tree | 79350e7a8e22ba6fa27477b15ef0c7d01cd79059 /src/value.zig | |
| parent | 54426bdc82ad361bb580f9678dd23417c350282a (diff) | |
| download | zig-5fa057053ce32274b878077e5abff82335530fc8.tar.gz zig-5fa057053ce32274b878077e5abff82335530fc8.zip | |
stage2 sema: Respect container_ty of parent ptrs
The core change here is that we no longer blindly trust that parent
pointers (.elem_ptr, .field_ptr, .eu_payload_ptr, .union_payload_ptr)
were derived from the "true" type of the underlying decl. When types
diverge, direct dereference fails and we are forced to bitcast, as
usual.
In order to maximize our chances to have a successful bitcast, this
includes several changes to the dereference procedure:
- `root` is now `parent` and is the largest Value containing the
dereference target, with the condition that its layout and the
byte offset of the target within are both well-defined.
- If the target cannot be dereferenced directly, because the
pointers were not derived from the true type of the underlying
decl, then it is returned as null.
- `beginComptimePtrDeref` now accepts an optional array_ty param,
which is used to directly dereference an array from an elem_ptr,
if necessary. This allows us to dereference array types without
well-defined layouts (e.g. `[N]?u8`) at an offset
The load_ty also allows us to correctly "over-read" an .elem_ptr to an
array of [N]T, if necessary. This makes direct dereference work for
array types even in the presence of an offset, which is necessary if
the array has no well-defined layout (e.g. loading from `[6]?u8`)
Diffstat (limited to 'src/value.zig')
| -rw-r--r-- | src/value.zig | 23 |
1 files changed, 23 insertions, 0 deletions
diff --git a/src/value.zig b/src/value.zig index f997b554a3..af5ee75737 100644 --- a/src/value.zig +++ b/src/value.zig @@ -2412,6 +2412,29 @@ pub const Value = extern union { } } + // Asserts that the provided start/end are in-bounds. + pub fn sliceArray(val: Value, arena: Allocator, start: usize, end: usize) error{OutOfMemory}!Value { + return switch (val.tag()) { + .empty_array_sentinel => if (start == 0 and end == 1) val else Value.initTag(.empty_array), + .bytes => Tag.bytes.create(arena, val.castTag(.bytes).?.data[start..end]), + .array => Tag.array.create(arena, val.castTag(.array).?.data[start..end]), + .slice => sliceArray(val.castTag(.slice).?.data.ptr, arena, start, end), + + .decl_ref => sliceArray(val.castTag(.decl_ref).?.data.val, arena, start, end), + .decl_ref_mut => sliceArray(val.castTag(.decl_ref_mut).?.data.decl.val, arena, start, end), + .elem_ptr => blk: { + const elem_ptr = val.castTag(.elem_ptr).?.data; + break :blk sliceArray(elem_ptr.array_ptr, arena, start + elem_ptr.index, end + elem_ptr.index); + }, + + .repeated, + .the_only_possible_value, + => val, + + else => unreachable, + }; + } + pub fn fieldValue(val: Value, allocator: Allocator, index: usize) error{OutOfMemory}!Value { _ = allocator; switch (val.tag()) { |
