diff options
| author | Robin Voetter <robin@voetter.nl> | 2021-10-24 16:34:42 +0200 |
|---|---|---|
| committer | Robin Voetter <robin@voetter.nl> | 2021-10-25 20:41:15 +0200 |
| commit | 0942bf73c90eabf87d0ca965b50beb0fd9a8fc8c (patch) | |
| tree | 52576cb867ea0baad15b87d0a4ca4591d7226f02 /src | |
| parent | ed7328119f2194f1b64085c08c88a5a656bfc597 (diff) | |
| download | zig-0942bf73c90eabf87d0ca965b50beb0fd9a8fc8c.tar.gz zig-0942bf73c90eabf87d0ca965b50beb0fd9a8fc8c.zip | |
stage2: improve slicing
* Allow slicing many- and c-pointers.
* Allow comptime pointer arithmetic on undefined values.
* Return the correct type for slicing of slices.
Diffstat (limited to 'src')
| -rw-r--r-- | src/Sema.zig | 47 |
1 files changed, 37 insertions, 10 deletions
diff --git a/src/Sema.zig b/src/Sema.zig index a87e0739e8..d290ea8ec0 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -7989,11 +7989,16 @@ fn analyzePtrArithmetic( const offset = try sema.coerce(block, Type.usize, uncasted_offset, offset_src); // TODO adjust the return type according to alignment and other factors const runtime_src = rs: { - if (try sema.resolveDefinedValue(block, ptr_src, ptr)) |ptr_val| { - if (try sema.resolveDefinedValue(block, offset_src, offset)) |offset_val| { + if (try sema.resolveMaybeUndefVal(block, ptr_src, ptr)) |ptr_val| { + if (try sema.resolveMaybeUndefVal(block, offset_src, offset)) |offset_val| { const ptr_ty = sema.typeOf(ptr); - const offset_int = offset_val.toUnsignedInt(); const new_ptr_ty = ptr_ty; // TODO modify alignment + + if (ptr_val.isUndef() or offset_val.isUndef()) { + return sema.addConstUndef(new_ptr_ty); + } + + const offset_int = offset_val.toUnsignedInt(); if (ptr_val.getUnsignedInt()) |addr| { const target = sema.mod.getTarget(); const elem_ty = ptr_ty.childType(); @@ -13206,8 +13211,8 @@ fn analyzeSlice( var elem_ty = ptr_ptr_child_ty.childType(); switch (ptr_ptr_child_ty.zigTypeTag()) { .Array => {}, - .Pointer => { - if (ptr_ptr_child_ty.isSinglePointer()) { + .Pointer => switch (ptr_ptr_child_ty.ptrSize()) { + .One => { const double_child_ty = ptr_ptr_child_ty.childType(); if (double_child_ty.zigTypeTag() == .Array) { ptr_or_slice = try sema.analyzeLoad(block, src, ptr_ptr, ptr_src); @@ -13217,10 +13222,23 @@ fn analyzeSlice( } else { return sema.fail(block, ptr_src, "slice of single-item pointer", .{}); } - } + }, + .Many, .C => { + ptr_or_slice = try sema.analyzeLoad(block, src, ptr_ptr, ptr_src); + slice_ty = ptr_ptr_child_ty; + array_ty = ptr_ptr_child_ty; + elem_ty = ptr_ptr_child_ty.childType(); + }, + .Slice => { + ptr_or_slice = try sema.analyzeLoad(block, src, ptr_ptr, ptr_src); + slice_ty = ptr_ptr_child_ty; + array_ty = ptr_ptr_child_ty; + elem_ty = ptr_ptr_child_ty.childType(); + }, }, else => return sema.fail(block, ptr_src, "slice of non-array type '{}'", .{ptr_ptr_child_ty}), } + const ptr = if (slice_ty.isSlice()) try sema.analyzeSlicePtr(block, src, ptr_or_slice, slice_ty, ptr_src) else @@ -13252,7 +13270,6 @@ fn analyzeSlice( const new_len = try sema.analyzeArithmetic(block, .sub, end, start, src, end_src, start_src); - const opt_new_ptr_val = try sema.resolveDefinedValue(block, ptr_src, new_ptr); const opt_new_len_val = try sema.resolveDefinedValue(block, src, new_len); const new_ptr_ty_info = sema.typeOf(new_ptr).ptrInfo().data; @@ -13276,11 +13293,21 @@ fn analyzeSlice( .size = .One, }); - if (opt_new_ptr_val) |new_ptr_val| { - return sema.addConstant(return_ty, new_ptr_val); - } else { + const opt_new_ptr_val = try sema.resolveMaybeUndefVal(block, ptr_src, new_ptr); + const new_ptr_val = opt_new_ptr_val orelse { return block.addBitCast(return_ty, new_ptr); + }; + + if (!new_ptr_val.isUndef()) { + return sema.addConstant(return_ty, new_ptr_val); } + + // Special case: @as([]i32, undefined)[x..x] + if (new_len_int == 0) { + return sema.addConstUndef(return_ty); + } + + return sema.fail(block, ptr_src, "non-zero length slice of undefined pointer", .{}); } const return_ty = try Type.ptr(sema.arena, .{ |
