aboutsummaryrefslogtreecommitdiff
path: root/src/value.zig
diff options
context:
space:
mode:
authorCody Tapscott <topolarity@tapscott.me>2022-03-11 14:22:53 -0700
committerAndrew Kelley <andrew@ziglang.org>2022-03-14 21:42:43 -0700
commit5fa057053ce32274b878077e5abff82335530fc8 (patch)
tree79350e7a8e22ba6fa27477b15ef0c7d01cd79059 /src/value.zig
parent54426bdc82ad361bb580f9678dd23417c350282a (diff)
downloadzig-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.zig23
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()) {