authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2020-08-28 15:51:27+03:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2020-09-03 15:05:47+03:00
log6ab0ac161e02c2361b72d124423509556b9332fa
tree39eccc6bfb4cf7109b2b454f4facca929b594aab
parent2a628fd401bf057a71175c8b723375fd4f375a84
signature Commit is signed but in an unrecognized format.

stage2: slice return type analysis


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,6 +2591,72 @@ pub fn analyzeIsErr(self: *Module, scope: *Scope, src: usize, operand: *Inst) In
2591 return self.fail(scope, src, "TODO implement analysis of iserr", .{});2591 return self.fail(scope, src, "TODO implement analysis of iserr", .{});
2592}2592}
25932593
2594pub 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/// Asserts that lhs and rhs types are both numeric.2660/// Asserts that lhs and rhs types are both numeric.
2595pub fn cmpNumeric(2661pub fn cmpNumeric(
2596 self: *Module,2662 self: *Module,
src-self-hosted/codegen.zig+1-1
...@@ -132,7 +132,7 @@ pub fn generateSymbol(...@@ -132,7 +132,7 @@ pub fn generateSymbol(
132 .Array => {132 .Array => {
133 // TODO populate .debug_info for the array133 // TODO populate .debug_info for the array
134 if (typed_value.val.cast(Value.Payload.Bytes)) |payload| {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 try code.ensureCapacity(code.items.len + payload.data.len + 1);136 try code.ensureCapacity(code.items.len + payload.data.len + 1);
137 code.appendSliceAssumeCapacity(payload.data);137 code.appendSliceAssumeCapacity(payload.data);
138 const prev_len = code.items.len;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,7 +85,7 @@ fn genArray(file: *C, decl: *Decl) !void {
85 const name = try map(file.base.allocator, mem.span(decl.name));85 const name = try map(file.base.allocator, mem.span(decl.name));
86 defer file.base.allocator.free(name);86 defer file.base.allocator.free(name);
87 if (tv.val.cast(Value.Payload.Bytes)) |payload|87 if (tv.val.cast(Value.Payload.Bytes)) |payload|
88 if (tv.ty.arraySentinel()) |sentinel|88 if (tv.ty.sentinel()) |sentinel|
89 if (sentinel.toUnsignedInt() == 0)89 if (sentinel.toUnsignedInt() == 0)
90 try file.constants.writer().print("const char *const {} = \"{}\";\n", .{ name, payload.data })90 try file.constants.writer().print("const char *const {} = \"{}\";\n", .{ name, payload.data })
91 else91 else
src-self-hosted/type.zig+93-15
...@@ -191,8 +191,8 @@ pub const Type = extern union {...@@ -191,8 +191,8 @@ pub const Type = extern union {
191 return false;191 return false;
192 if (!a.elemType().eql(b.elemType()))192 if (!a.elemType().eql(b.elemType()))
193 return false;193 return false;
194 const sentinel_a = a.arraySentinel();194 const sentinel_a = a.sentinel();
195 const sentinel_b = b.arraySentinel();195 const sentinel_b = b.sentinel();
196 if (sentinel_a) |sa| {196 if (sentinel_a) |sa| {
197 if (sentinel_b) |sb| {197 if (sentinel_b) |sb| {
198 return sa.eql(sb);198 return sa.eql(sb);
...@@ -630,8 +630,8 @@ pub const Type = extern union {...@@ -630,8 +630,8 @@ pub const Type = extern union {
630 const payload = @fieldParentPtr(Payload.Pointer, "base", ty.ptr_otherwise);630 const payload = @fieldParentPtr(Payload.Pointer, "base", ty.ptr_otherwise);
631 if (payload.sentinel) |some| switch (payload.size) {631 if (payload.sentinel) |some| switch (payload.size) {
632 .One, .C => unreachable,632 .One, .C => unreachable,
633 .Many => try out_stream.writeAll("[*:{}]"),633 .Many => try out_stream.print("[*:{}]", .{some}),
634 .Slice => try out_stream.writeAll("[:{}]"),634 .Slice => try out_stream.print("[:{}]", .{some}),
635 } else switch (payload.size) {635 } else switch (payload.size) {
636 .One => try out_stream.writeAll("*"),636 .One => try out_stream.writeAll("*"),
637 .Many => try out_stream.writeAll("[*]"),637 .Many => try out_stream.writeAll("[*]"),
...@@ -1341,6 +1341,81 @@ pub const Type = extern union {...@@ -1341,6 +1341,81 @@ pub const Type = extern union {
1341 };1341 };
1342 }1342 }
13431343
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 /// Asserts that the type is an optional1419 /// Asserts that the type is an optional
1345 pub fn isPtrLikeOptional(self: Type) bool {1420 pub fn isPtrLikeOptional(self: Type) bool {
1346 switch (self.tag()) {1421 switch (self.tag()) {
...@@ -1585,8 +1660,8 @@ pub const Type = extern union {...@@ -1585,8 +1660,8 @@ pub const Type = extern union {
1585 };1660 };
1586 }1661 }
15871662
1588 /// Asserts the type is an array or vector.1663 /// Asserts the type is an array, pointer or vector.
1589 pub fn arraySentinel(self: Type) ?Value {1664 pub fn sentinel(self: Type) ?Value {
1590 return switch (self.tag()) {1665 return switch (self.tag()) {
1591 .u8,1666 .u8,
1592 .i8,1667 .i8,
...@@ -1626,16 +1701,8 @@ pub const Type = extern union {...@@ -1626,16 +1701,8 @@ pub const Type = extern union {
1626 .fn_naked_noreturn_no_args,1701 .fn_naked_noreturn_no_args,
1627 .fn_ccc_void_no_args,1702 .fn_ccc_void_no_args,
1628 .function,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 .const_slice,1704 .const_slice,
1637 .mut_slice,1705 .mut_slice,
1638 .single_const_pointer_to_comptime_int,
1639 .const_slice_u8,1706 .const_slice_u8,
1640 .int_unsigned,1707 .int_unsigned,
1641 .int_signed,1708 .int_signed,
...@@ -1651,7 +1718,18 @@ pub const Type = extern union {...@@ -1651,7 +1718,18 @@ pub const Type = extern union {
1651 .error_set_single,1718 .error_set_single,
1652 => unreachable,1719 => unreachable,
16531720
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 .array_sentinel => return self.cast(Payload.ArraySentinel).?.sentinel,1733 .array_sentinel => return self.cast(Payload.ArraySentinel).?.sentinel,
1656 .array_u8_sentinel_0 => return Value.initTag(.zero),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,7 +2596,7 @@ const EmitZIR = struct {
2596 var len_pl = Value.Payload.Int_u64{ .int = ty.arrayLen() };2596 var len_pl = Value.Payload.Int_u64{ .int = ty.arrayLen() };
2597 const len = Value.initPayload(&len_pl.base);2597 const len = Value.initPayload(&len_pl.base);
25982598
2599 const inst = if (ty.arraySentinel()) |sentinel| blk: {2599 const inst = if (ty.sentinel()) |sentinel| blk: {
2600 const inst = try self.arena.allocator.create(Inst.ArrayTypeSentinel);2600 const inst = try self.arena.allocator.create(Inst.ArrayTypeSentinel);
2601 inst.* = .{2601 inst.* = .{
2602 .base = .{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,11 +1175,19 @@ fn analyzeInstElemPtr(mod: *Module, scope: *Scope, inst: *zir.Inst.ElemPtr) Inne
1175}1175}
11761176
1177fn analyzeInstSlice(mod: *Module, scope: *Scope, inst: *zir.Inst.Slice) InnerError!*Inst {1177fn 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}
11801185
1181fn analyzeInstSliceStart(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerError!*Inst {1186fn 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}
11841192
1185fn analyzeInstShl(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerError!*Inst {1193fn analyzeInstShl(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerError!*Inst {