| author | |
| committer | |
| log | 6ab0ac161e02c2361b72d124423509556b9332fa |
| tree | 39eccc6bfb4cf7109b2b454f4facca929b594aab |
| parent | 2a628fd401bf057a71175c8b723375fd4f375a84 |
| signature |
6 files changed, 172 insertions(+), 20 deletions(-)
src-self-hosted/Module.zig+66| ... | ... | @@ -2591,6 +2591,72 @@ pub fn analyzeIsErr(self: *Module, scope: *Scope, src: usize, operand: *Inst) In |
| 2591 | 2591 | return self.fail(scope, src, "TODO implement analysis of iserr", .{}); |
| 2592 | 2592 | } |
| 2593 | 2593 | |
| 2594 | pub fn analyzeSlice(self: *Module, scope: *Scope, src: usize, array_ptr: *Inst, start: *Inst, end_opt: ?*Inst, sentinel_opt: ?*Inst) InnerError!*Inst { | |
| 2595 | const ptr_child = switch (array_ptr.ty.zigTypeTag()) { | |
| 2596 | .Pointer => array_ptr.ty.elemType(), | |
| 2597 | else => return self.fail(scope, src, "expected pointer, found '{}'", .{array_ptr.ty}), | |
| 2598 | }; | |
| 2599 | ||
| 2600 | var array_type = ptr_child; | |
| 2601 | const elem_type = switch (ptr_child.zigTypeTag()) { | |
| 2602 | .Array => ptr_child.elemType(), | |
| 2603 | .Pointer => blk: { | |
| 2604 | if (ptr_child.isSinglePointer()) { | |
| 2605 | if (ptr_child.elemType().zigTypeTag() == .Array) { | |
| 2606 | array_type = ptr_child.elemType(); | |
| 2607 | break :blk ptr_child.elemType().elemType(); | |
| 2608 | } | |
| 2609 | ||
| 2610 | return self.fail(scope, src, "slice of single-item pointer", .{}); | |
| 2611 | } | |
| 2612 | break :blk ptr_child.elemType(); | |
| 2613 | }, | |
| 2614 | else => return self.fail(scope, src, "slice of non-array type '{}'", .{ptr_child}), | |
| 2615 | }; | |
| 2616 | ||
| 2617 | const slice_sentinel = if (sentinel_opt) |sentinel| blk: { | |
| 2618 | const casted = try self.coerce(scope, elem_type, sentinel); | |
| 2619 | break :blk try self.resolveConstValue(scope, casted); | |
| 2620 | } else null; | |
| 2621 | ||
| 2622 | var return_ptr_size: std.builtin.TypeInfo.Pointer.Size = .Slice; | |
| 2623 | var return_elem_type = elem_type; | |
| 2624 | if (end_opt) |end| { | |
| 2625 | if (end.value()) |end_val| { | |
| 2626 | if (start.value()) |start_val| { | |
| 2627 | const start_u64 = start_val.toUnsignedInt(); | |
| 2628 | const end_u64 = end_val.toUnsignedInt(); | |
| 2629 | if (start_u64 > end_u64) { | |
| 2630 | return self.fail(scope, src, "out of bounds slice", .{}); | |
| 2631 | } | |
| 2632 | ||
| 2633 | const len = end_u64 - start_u64; | |
| 2634 | const array_sentinel = if (array_type.zigTypeTag() == .Array and end_u64 == array_type.arrayLen()) | |
| 2635 | array_type.sentinel() | |
| 2636 | else | |
| 2637 | slice_sentinel; | |
| 2638 | return_elem_type = try self.arrayType(scope, len, array_sentinel, elem_type); | |
| 2639 | return_ptr_size = .One; | |
| 2640 | } | |
| 2641 | } | |
| 2642 | } | |
| 2643 | const return_type = try self.ptrType( | |
| 2644 | scope, | |
| 2645 | src, | |
| 2646 | return_elem_type, | |
| 2647 | if (end_opt == null) slice_sentinel else null, | |
| 2648 | 0, // TODO alignment | |
| 2649 | 0, | |
| 2650 | 0, | |
| 2651 | !ptr_child.isConstPtr(), | |
| 2652 | ptr_child.isAllowzeroPtr(), | |
| 2653 | ptr_child.isVolatilePtr(), | |
| 2654 | return_ptr_size, | |
| 2655 | ); | |
| 2656 | ||
| 2657 | return self.fail(scope, src, "TODO implement analysis of slice", .{}); | |
| 2658 | } | |
| 2659 | ||
| 2594 | 2660 | /// Asserts that lhs and rhs types are both numeric. |
| 2595 | 2661 | pub fn cmpNumeric( |
| 2596 | 2662 | self: *Module, |
src-self-hosted/codegen.zig+1-1| ... | ... | @@ -132,7 +132,7 @@ pub fn generateSymbol( |
| 132 | 132 | .Array => { |
| 133 | 133 | // TODO populate .debug_info for the array |
| 134 | 134 | if (typed_value.val.cast(Value.Payload.Bytes)) |payload| { |
| 135 | if (typed_value.ty.arraySentinel()) |sentinel| { | |
| 135 | if (typed_value.ty.sentinel()) |sentinel| { | |
| 136 | 136 | try code.ensureCapacity(code.items.len + payload.data.len + 1); |
| 137 | 137 | code.appendSliceAssumeCapacity(payload.data); |
| 138 | 138 | const prev_len = code.items.len; |
src-self-hosted/codegen/c.zig+1-1| ... | ... | @@ -85,7 +85,7 @@ fn genArray(file: *C, decl: *Decl) !void { |
| 85 | 85 | const name = try map(file.base.allocator, mem.span(decl.name)); |
| 86 | 86 | defer file.base.allocator.free(name); |
| 87 | 87 | if (tv.val.cast(Value.Payload.Bytes)) |payload| |
| 88 | if (tv.ty.arraySentinel()) |sentinel| | |
| 88 | if (tv.ty.sentinel()) |sentinel| | |
| 89 | 89 | if (sentinel.toUnsignedInt() == 0) |
| 90 | 90 | try file.constants.writer().print("const char *const {} = \"{}\";\n", .{ name, payload.data }) |
| 91 | 91 | else |
src-self-hosted/type.zig+93-15| ... | ... | @@ -191,8 +191,8 @@ pub const Type = extern union { |
| 191 | 191 | return false; |
| 192 | 192 | if (!a.elemType().eql(b.elemType())) |
| 193 | 193 | return false; |
| 194 | const sentinel_a = a.arraySentinel(); | |
| 195 | const sentinel_b = b.arraySentinel(); | |
| 194 | const sentinel_a = a.sentinel(); | |
| 195 | const sentinel_b = b.sentinel(); | |
| 196 | 196 | if (sentinel_a) |sa| { |
| 197 | 197 | if (sentinel_b) |sb| { |
| 198 | 198 | return sa.eql(sb); |
| ... | ... | @@ -630,8 +630,8 @@ pub const Type = extern union { |
| 630 | 630 | const payload = @fieldParentPtr(Payload.Pointer, "base", ty.ptr_otherwise); |
| 631 | 631 | if (payload.sentinel) |some| switch (payload.size) { |
| 632 | 632 | .One, .C => unreachable, |
| 633 | .Many => try out_stream.writeAll("[*:{}]"), | |
| 634 | .Slice => try out_stream.writeAll("[:{}]"), | |
| 633 | .Many => try out_stream.print("[*:{}]", .{some}), | |
| 634 | .Slice => try out_stream.print("[:{}]", .{some}), | |
| 635 | 635 | } else switch (payload.size) { |
| 636 | 636 | .One => try out_stream.writeAll("*"), |
| 637 | 637 | .Many => try out_stream.writeAll("[*]"), |
| ... | ... | @@ -1341,6 +1341,81 @@ pub const Type = extern union { |
| 1341 | 1341 | }; |
| 1342 | 1342 | } |
| 1343 | 1343 | |
| 1344 | pub fn isAllowzeroPtr(self: Type) bool { | |
| 1345 | return switch (self.tag()) { | |
| 1346 | .u8, | |
| 1347 | .i8, | |
| 1348 | .u16, | |
| 1349 | .i16, | |
| 1350 | .u32, | |
| 1351 | .i32, | |
| 1352 | .u64, | |
| 1353 | .i64, | |
| 1354 | .usize, | |
| 1355 | .isize, | |
| 1356 | .c_short, | |
| 1357 | .c_ushort, | |
| 1358 | .c_int, | |
| 1359 | .c_uint, | |
| 1360 | .c_long, | |
| 1361 | .c_ulong, | |
| 1362 | .c_longlong, | |
| 1363 | .c_ulonglong, | |
| 1364 | .c_longdouble, | |
| 1365 | .f16, | |
| 1366 | .f32, | |
| 1367 | .f64, | |
| 1368 | .f128, | |
| 1369 | .c_void, | |
| 1370 | .bool, | |
| 1371 | .void, | |
| 1372 | .type, | |
| 1373 | .anyerror, | |
| 1374 | .comptime_int, | |
| 1375 | .comptime_float, | |
| 1376 | .noreturn, | |
| 1377 | .@"null", | |
| 1378 | .@"undefined", | |
| 1379 | .array, | |
| 1380 | .array_sentinel, | |
| 1381 | .array_u8, | |
| 1382 | .array_u8_sentinel_0, | |
| 1383 | .fn_noreturn_no_args, | |
| 1384 | .fn_void_no_args, | |
| 1385 | .fn_naked_noreturn_no_args, | |
| 1386 | .fn_ccc_void_no_args, | |
| 1387 | .function, | |
| 1388 | .int_unsigned, | |
| 1389 | .int_signed, | |
| 1390 | .single_mut_pointer, | |
| 1391 | .single_const_pointer, | |
| 1392 | .many_const_pointer, | |
| 1393 | .many_mut_pointer, | |
| 1394 | .c_const_pointer, | |
| 1395 | .c_mut_pointer, | |
| 1396 | .const_slice, | |
| 1397 | .mut_slice, | |
| 1398 | .single_const_pointer_to_comptime_int, | |
| 1399 | .const_slice_u8, | |
| 1400 | .optional, | |
| 1401 | .optional_single_mut_pointer, | |
| 1402 | .optional_single_const_pointer, | |
| 1403 | .enum_literal, | |
| 1404 | .error_union, | |
| 1405 | .@"anyframe", | |
| 1406 | .anyframe_T, | |
| 1407 | .anyerror_void_error_union, | |
| 1408 | .error_set, | |
| 1409 | .error_set_single, | |
| 1410 | => false, | |
| 1411 | ||
| 1412 | .pointer => { | |
| 1413 | const payload = @fieldParentPtr(Payload.Pointer, "base", self.ptr_otherwise); | |
| 1414 | return payload.@"allowzero"; | |
| 1415 | }, | |
| 1416 | }; | |
| 1417 | } | |
| 1418 | ||
| 1344 | 1419 | /// Asserts that the type is an optional |
| 1345 | 1420 | pub fn isPtrLikeOptional(self: Type) bool { |
| 1346 | 1421 | switch (self.tag()) { |
| ... | ... | @@ -1585,8 +1660,8 @@ pub const Type = extern union { |
| 1585 | 1660 | }; |
| 1586 | 1661 | } |
| 1587 | 1662 | |
| 1588 | /// Asserts the type is an array or vector. | |
| 1589 | pub fn arraySentinel(self: Type) ?Value { | |
| 1663 | /// Asserts the type is an array, pointer or vector. | |
| 1664 | pub fn sentinel(self: Type) ?Value { | |
| 1590 | 1665 | return switch (self.tag()) { |
| 1591 | 1666 | .u8, |
| 1592 | 1667 | .i8, |
| ... | ... | @@ -1626,16 +1701,8 @@ pub const Type = extern union { |
| 1626 | 1701 | .fn_naked_noreturn_no_args, |
| 1627 | 1702 | .fn_ccc_void_no_args, |
| 1628 | 1703 | .function, |
| 1629 | .pointer, | |
| 1630 | .single_const_pointer, | |
| 1631 | .single_mut_pointer, | |
| 1632 | .many_const_pointer, | |
| 1633 | .many_mut_pointer, | |
| 1634 | .c_const_pointer, | |
| 1635 | .c_mut_pointer, | |
| 1636 | 1704 | .const_slice, |
| 1637 | 1705 | .mut_slice, |
| 1638 | .single_const_pointer_to_comptime_int, | |
| 1639 | 1706 | .const_slice_u8, |
| 1640 | 1707 | .int_unsigned, |
| 1641 | 1708 | .int_signed, |
| ... | ... | @@ -1651,7 +1718,18 @@ pub const Type = extern union { |
| 1651 | 1718 | .error_set_single, |
| 1652 | 1719 | => unreachable, |
| 1653 | 1720 | |
| 1654 | .array, .array_u8 => return null, | |
| 1721 | .single_const_pointer, | |
| 1722 | .single_mut_pointer, | |
| 1723 | .many_const_pointer, | |
| 1724 | .many_mut_pointer, | |
| 1725 | .c_const_pointer, | |
| 1726 | .c_mut_pointer, | |
| 1727 | .single_const_pointer_to_comptime_int, | |
| 1728 | .array, | |
| 1729 | .array_u8, | |
| 1730 | => return null, | |
| 1731 | ||
| 1732 | .pointer => return self.cast(Payload.Pointer).?.sentinel, | |
| 1655 | 1733 | .array_sentinel => return self.cast(Payload.ArraySentinel).?.sentinel, |
| 1656 | 1734 | .array_u8_sentinel_0 => return Value.initTag(.zero), |
| 1657 | 1735 | }; |
src-self-hosted/zir.zig+1-1| ... | ... | @@ -2596,7 +2596,7 @@ const EmitZIR = struct { |
| 2596 | 2596 | var len_pl = Value.Payload.Int_u64{ .int = ty.arrayLen() }; |
| 2597 | 2597 | const len = Value.initPayload(&len_pl.base); |
| 2598 | 2598 | |
| 2599 | const inst = if (ty.arraySentinel()) |sentinel| blk: { | |
| 2599 | const inst = if (ty.sentinel()) |sentinel| blk: { | |
| 2600 | 2600 | const inst = try self.arena.allocator.create(Inst.ArrayTypeSentinel); |
| 2601 | 2601 | inst.* = .{ |
| 2602 | 2602 | .base = .{ |
src-self-hosted/zir_sema.zig+10-2| ... | ... | @@ -1175,11 +1175,19 @@ fn analyzeInstElemPtr(mod: *Module, scope: *Scope, inst: *zir.Inst.ElemPtr) Inne |
| 1175 | 1175 | } |
| 1176 | 1176 | |
| 1177 | 1177 | fn analyzeInstSlice(mod: *Module, scope: *Scope, inst: *zir.Inst.Slice) InnerError!*Inst { |
| 1178 | return mod.fail(scope, inst.base.src, "TODO implement analyzeInstSlice", .{}); | |
| 1178 | const array_ptr = try resolveInst(mod, scope, inst.positionals.array_ptr); | |
| 1179 | const start = try resolveInst(mod, scope, inst.positionals.start); | |
| 1180 | const end = if (inst.kw_args.end) |end| try resolveInst(mod, scope, end) else null; | |
| 1181 | const sentinel = if (inst.kw_args.sentinel) |sentinel| try resolveInst(mod, scope, sentinel) else null; | |
| 1182 | ||
| 1183 | return mod.analyzeSlice(scope, inst.base.src, array_ptr, start, end, sentinel); | |
| 1179 | 1184 | } |
| 1180 | 1185 | |
| 1181 | 1186 | fn analyzeInstSliceStart(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerError!*Inst { |
| 1182 | return mod.fail(scope, inst.base.src, "TODO implement analyzeInstSliceStart", .{}); | |
| 1187 | const array_ptr = try resolveInst(mod, scope, inst.positionals.lhs); | |
| 1188 | const start = try resolveInst(mod, scope, inst.positionals.rhs); | |
| 1189 | ||
| 1190 | return mod.analyzeSlice(scope, inst.base.src, array_ptr, start, null, null); | |
| 1183 | 1191 | } |
| 1184 | 1192 | |
| 1185 | 1193 | fn analyzeInstShl(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerError!*Inst { |