From d312d64c9aa058293d69b2bf97c51f4caa7a2d9d Mon Sep 17 00:00:00 2001 From: Vexu Date: Thu, 20 Aug 2020 16:37:28 +0300 Subject: [PATCH] stage2: slice types --- src-self-hosted/Module.zig | 5 +- src-self-hosted/astgen.zig | 50 +++++++++++-------- src-self-hosted/type.zig | 97 +++++++++++++++++++++++++++++------- src-self-hosted/zir.zig | 20 +++++--- src-self-hosted/zir_sema.zig | 2 + 5 files changed, 127 insertions(+), 47 deletions(-) diff --git a/src-self-hosted/Module.zig b/src-self-hosted/Module.zig index 2dd64c64bc..4893aaba7a 100644 --- a/src-self-hosted/Module.zig +++ b/src-self-hosted/Module.zig @@ -3146,6 +3146,9 @@ pub fn floatSub(self: *Module, scope: *Scope, float_type: Type, src: usize, lhs: } pub fn simplePtrType(self: *Module, scope: *Scope, src: usize, elem_ty: Type, mutable: bool, size: std.builtin.TypeInfo.Pointer.Size) Allocator.Error!Type { + if (size == .Slice and elem_ty.eql(Type.initTag(.u8))) { + return Type.initTag(.const_slice_u8); + } // TODO stage1 type inference bug const T = Type.Tag; @@ -3156,7 +3159,7 @@ pub fn simplePtrType(self: *Module, scope: *Scope, src: usize, elem_ty: Type, mu .One => if (mutable) T.single_mut_pointer else T.single_const_pointer, .Many => if (mutable) T.many_mut_pointer else T.many_const_pointer, .C => if (mutable) T.c_mut_pointer else T.c_const_pointer, - else => unreachable, + .Slice => if (mutable) T.mut_slice else T.const_slice, }, }, .pointee_type = elem_ty, diff --git a/src-self-hosted/astgen.zig b/src-self-hosted/astgen.zig index 832e6848b3..8276b191cb 100644 --- a/src-self-hosted/astgen.zig +++ b/src-self-hosted/astgen.zig @@ -262,6 +262,7 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerEr .EnumLiteral => return rlWrap(mod, scope, rl, try enumLiteral(mod, scope, node.castTag(.EnumLiteral).?)), .MultilineStringLiteral => return rlWrap(mod, scope, rl, try multilineStrLiteral(mod, scope, node.castTag(.MultilineStringLiteral).?)), .CharLiteral => return rlWrap(mod, scope, rl, try charLiteral(mod, scope, node.castTag(.CharLiteral).?)), + .SliceType => return rlWrap(mod, scope, rl, try sliceType(mod, scope, node.castTag(.SliceType).?)), .Defer => return mod.failNode(scope, node, "TODO implement astgen.expr for .Defer", .{}), .Catch => return mod.failNode(scope, node, "TODO implement astgen.expr for .Catch", .{}), @@ -275,7 +276,6 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerEr .NegationWrap => return mod.failNode(scope, node, "TODO implement astgen.expr for .NegationWrap", .{}), .Resume => return mod.failNode(scope, node, "TODO implement astgen.expr for .Resume", .{}), .Try => return mod.failNode(scope, node, "TODO implement astgen.expr for .Try", .{}), - .SliceType => return mod.failNode(scope, node, "TODO implement astgen.expr for .SliceType", .{}), .Slice => return mod.failNode(scope, node, "TODO implement astgen.expr for .Slice", .{}), .ArrayAccess => return mod.failNode(scope, node, "TODO implement astgen.expr for .ArrayAccess", .{}), .ArrayInitializer => return mod.failNode(scope, node, "TODO implement astgen.expr for .ArrayInitializer", .{}), @@ -569,15 +569,16 @@ fn optionalType(mod: *Module, scope: *Scope, node: *ast.Node.SimplePrefixOp) Inn return addZIRUnOp(mod, scope, src, .optional_type, operand); } +fn sliceType(mod: *Module, scope: *Scope, node: *ast.Node.SliceType) InnerError!*zir.Inst { + const tree = scope.tree(); + const src = tree.token_locs[node.op_token].start; + return ptrSliceType(mod, scope, src, &node.ptr_info, node.rhs, .Slice); +} + fn ptrType(mod: *Module, scope: *Scope, node: *ast.Node.PtrType) InnerError!*zir.Inst { const tree = scope.tree(); const src = tree.token_locs[node.op_token].start; - const meta_type = try addZIRInstConst(mod, scope, src, .{ - .ty = Type.initTag(.type), - .val = Value.initTag(.type_type), - }); - - const size: std.builtin.TypeInfo.Pointer.Size = switch (tree.token_ids[node.op_token]) { + return ptrSliceType(mod, scope, src, &node.ptr_info, node.rhs, switch (tree.token_ids[node.op_token]) { .Asterisk, .AsteriskAsterisk => .One, // TODO stage1 type inference bug .LBracket => @as(std.builtin.TypeInfo.Pointer.Size, switch (tree.token_ids[node.op_token + 2]) { @@ -585,43 +586,50 @@ fn ptrType(mod: *Module, scope: *Scope, node: *ast.Node.PtrType) InnerError!*zir else => .Many, }), else => unreachable, - }; + }); +} - const simple = node.ptr_info.allowzero_token == null and - node.ptr_info.align_info == null and - node.ptr_info.volatile_token == null and - node.ptr_info.sentinel == null; +fn ptrSliceType(mod: *Module, scope: *Scope, src: usize, ptr_info: *ast.PtrInfo, rhs: *ast.Node, size: std.builtin.TypeInfo.Pointer.Size) InnerError!*zir.Inst { + const meta_type = try addZIRInstConst(mod, scope, src, .{ + .ty = Type.initTag(.type), + .val = Value.initTag(.type_type), + }); + + const simple = ptr_info.allowzero_token == null and + ptr_info.align_info == null and + ptr_info.volatile_token == null and + ptr_info.sentinel == null; if (simple) { - const child_type = try expr(mod, scope, .{ .ty = meta_type }, node.rhs); - const mutable = node.ptr_info.const_token == null; + const child_type = try expr(mod, scope, .{ .ty = meta_type }, rhs); + const mutable = ptr_info.const_token == null; // TODO stage1 type inference bug const T = zir.Inst.Tag; return addZIRUnOp(mod, scope, src, switch (size) { .One => if (mutable) T.single_mut_ptr_type else T.single_const_ptr_type, .Many => if (mutable) T.many_mut_ptr_type else T.many_const_ptr_type, .C => if (mutable) T.c_mut_ptr_type else T.c_const_ptr_type, - else => unreachable, + .Slice => if (mutable) T.mut_slice_type else T.mut_slice_type, }, child_type); } var kw_args: std.meta.fieldInfo(zir.Inst.PtrType, "kw_args").field_type = .{}; kw_args.size = size; - kw_args.@"allowzero" = node.ptr_info.allowzero_token != null; - if (node.ptr_info.align_info) |some| { + kw_args.@"allowzero" = ptr_info.allowzero_token != null; + if (ptr_info.align_info) |some| { kw_args.@"align" = try expr(mod, scope, .none, some.node); if (some.bit_range) |bit_range| { kw_args.align_bit_start = try expr(mod, scope, .none, bit_range.start); kw_args.align_bit_end = try expr(mod, scope, .none, bit_range.end); } } - kw_args.mutable = node.ptr_info.const_token == null; - kw_args.@"volatile" = node.ptr_info.volatile_token != null; - if (node.ptr_info.sentinel) |some| { + kw_args.mutable = ptr_info.const_token == null; + kw_args.@"volatile" = ptr_info.volatile_token != null; + if (ptr_info.sentinel) |some| { kw_args.sentinel = try expr(mod, scope, .none, some); } - const child_type = try expr(mod, scope, .{ .ty = meta_type }, node.rhs); + const child_type = try expr(mod, scope, .{ .ty = meta_type }, rhs); if (kw_args.sentinel) |some| { kw_args.sentinel = try addZIRBinOp(mod, scope, some.src, .as, child_type, some); } diff --git a/src-self-hosted/type.zig b/src-self-hosted/type.zig index 2c326b9308..2218c49200 100644 --- a/src-self-hosted/type.zig +++ b/src-self-hosted/type.zig @@ -74,6 +74,8 @@ pub const Type = extern union { .many_mut_pointer, .c_const_pointer, .c_mut_pointer, + .const_slice, + .mut_slice, .pointer, => return .Pointer, @@ -122,6 +124,8 @@ pub const Type = extern union { .many_mut_pointer, .c_const_pointer, .c_mut_pointer, + .const_slice, + .mut_slice, .optional_single_const_pointer, .optional_single_mut_pointer, => @fieldParentPtr(Payload.PointerSimple, "base", self.ptr_otherwise), @@ -388,6 +392,8 @@ pub const Type = extern union { .many_mut_pointer, .c_const_pointer, .c_mut_pointer, + .const_slice, + .mut_slice, .optional_single_mut_pointer, .optional_single_const_pointer, => return self.copyPayloadSingleField(allocator, Payload.PointerSimple, "pointee_type"), @@ -550,6 +556,18 @@ pub const Type = extern union { ty = payload.pointee_type; continue; }, + .const_slice => { + const payload = @fieldParentPtr(Payload.PointerSimple, "base", ty.ptr_otherwise); + try out_stream.writeAll("[]const "); + ty = payload.pointee_type; + continue; + }, + .mut_slice => { + const payload = @fieldParentPtr(Payload.PointerSimple, "base", ty.ptr_otherwise); + try out_stream.writeAll("[]"); + ty = payload.pointee_type; + continue; + }, .int_signed => { const payload = @fieldParentPtr(Payload.IntSigned, "base", ty.ptr_otherwise); return out_stream.print("i{}", .{payload.bits}); @@ -701,14 +719,7 @@ pub const Type = extern union { // TODO lazy types .array => self.elemType().hasCodeGenBits() and self.arrayLen() != 0, .array_u8 => self.arrayLen() != 0, - .array_sentinel => self.elemType().hasCodeGenBits(), - .single_const_pointer => self.elemType().hasCodeGenBits(), - .single_mut_pointer => self.elemType().hasCodeGenBits(), - .many_const_pointer => self.elemType().hasCodeGenBits(), - .many_mut_pointer => self.elemType().hasCodeGenBits(), - .c_const_pointer => self.elemType().hasCodeGenBits(), - .c_mut_pointer => self.elemType().hasCodeGenBits(), - .pointer => self.elemType().hasCodeGenBits(), + .array_sentinel, .single_const_pointer, .single_mut_pointer, .many_const_pointer, .many_mut_pointer, .c_const_pointer, .c_mut_pointer, .const_slice, .mut_slice, .pointer => self.elemType().hasCodeGenBits(), .int_signed => self.cast(Payload.IntSigned).?.bits == 0, .int_unsigned => self.cast(Payload.IntUnsigned).?.bits == 0, @@ -763,6 +774,8 @@ pub const Type = extern union { .many_mut_pointer, .c_const_pointer, .c_mut_pointer, + .const_slice, + .mut_slice, .optional_single_const_pointer, .optional_single_mut_pointer, => return @divExact(target.cpu.arch.ptrBitWidth(), 8), @@ -868,10 +881,12 @@ pub const Type = extern union { .i32, .u32 => return 4, .i64, .u64 => return 8, - .isize, - .usize - => return @divExact(target.cpu.arch.ptrBitWidth(), 8), - .const_slice_u8 => return @divExact(target.cpu.arch.ptrBitWidth(), 8) * 2, + .isize, .usize => return @divExact(target.cpu.arch.ptrBitWidth(), 8), + + .const_slice, + .mut_slice, + .const_slice_u8, + => return @divExact(target.cpu.arch.ptrBitWidth(), 8) * 2, .optional_single_const_pointer, .optional_single_mut_pointer, @@ -992,6 +1007,8 @@ pub const Type = extern union { .many_mut_pointer, .c_const_pointer, .c_mut_pointer, + .const_slice, + .mut_slice, => false, .single_const_pointer, @@ -1062,7 +1079,10 @@ pub const Type = extern union { .enum_literal, => false, - .const_slice_u8 => true, + .const_slice, + .mut_slice, + .const_slice_u8, + => true, .pointer => self.cast(Payload.Pointer).?.size == .Slice, }; @@ -1121,6 +1141,7 @@ pub const Type = extern union { .optional_single_mut_pointer, .optional_single_const_pointer, .enum_literal, + .mut_slice, => false, .single_const_pointer, @@ -1128,6 +1149,7 @@ pub const Type = extern union { .c_const_pointer, .single_const_pointer_to_comptime_int, .const_slice_u8, + .const_slice, => true, .pointer => !self.cast(Payload.Pointer).?.mutable, @@ -1186,6 +1208,8 @@ pub const Type = extern union { .many_mut_pointer, .c_const_pointer, .c_mut_pointer, + .const_slice, + .mut_slice, .single_const_pointer_to_comptime_int, .const_slice_u8, .optional, @@ -1307,12 +1331,15 @@ pub const Type = extern union { .array => self.cast(Payload.Array).?.elem_type, .array_sentinel => self.cast(Payload.ArraySentinel).?.elem_type, - .single_const_pointer => self.castPointer().?.pointee_type, - .single_mut_pointer => self.castPointer().?.pointee_type, - .many_const_pointer => self.castPointer().?.pointee_type, - .many_mut_pointer => self.castPointer().?.pointee_type, - .c_const_pointer => self.castPointer().?.pointee_type, - .c_mut_pointer => self.castPointer().?.pointee_type, + .single_const_pointer, + .single_mut_pointer, + .many_const_pointer, + .many_mut_pointer, + .c_const_pointer, + .c_mut_pointer, + .const_slice, + .mut_slice, + => self.castPointer().?.pointee_type, .array_u8, .array_u8_sentinel_0, .const_slice_u8 => Type.initTag(.u8), .single_const_pointer_to_comptime_int => Type.initTag(.comptime_int), .pointer => self.cast(Payload.Pointer).?.pointee_type, @@ -1411,6 +1438,8 @@ pub const Type = extern union { .many_mut_pointer, .c_const_pointer, .c_mut_pointer, + .const_slice, + .mut_slice, .single_const_pointer_to_comptime_int, .const_slice_u8, .int_unsigned, @@ -1476,6 +1505,8 @@ pub const Type = extern union { .many_mut_pointer, .c_const_pointer, .c_mut_pointer, + .const_slice, + .mut_slice, .single_const_pointer_to_comptime_int, .const_slice_u8, .int_unsigned, @@ -1531,6 +1562,8 @@ pub const Type = extern union { .many_mut_pointer, .c_const_pointer, .c_mut_pointer, + .const_slice, + .mut_slice, .single_const_pointer_to_comptime_int, .const_slice_u8, .int_unsigned, @@ -1597,6 +1630,8 @@ pub const Type = extern union { .many_mut_pointer, .c_const_pointer, .c_mut_pointer, + .const_slice, + .mut_slice, .single_const_pointer_to_comptime_int, .const_slice_u8, .int_signed, @@ -1663,6 +1698,8 @@ pub const Type = extern union { .many_mut_pointer, .c_const_pointer, .c_mut_pointer, + .const_slice, + .mut_slice, .single_const_pointer_to_comptime_int, .const_slice_u8, .optional, @@ -1727,6 +1764,8 @@ pub const Type = extern union { .many_mut_pointer, .c_const_pointer, .c_mut_pointer, + .const_slice, + .mut_slice, .single_const_pointer_to_comptime_int, .const_slice_u8, .int_unsigned, @@ -1820,6 +1859,8 @@ pub const Type = extern union { .many_mut_pointer, .c_const_pointer, .c_mut_pointer, + .const_slice, + .mut_slice, .single_const_pointer_to_comptime_int, .const_slice_u8, .u8, @@ -1889,6 +1930,8 @@ pub const Type = extern union { .many_mut_pointer, .c_const_pointer, .c_mut_pointer, + .const_slice, + .mut_slice, .single_const_pointer_to_comptime_int, .const_slice_u8, .u8, @@ -1957,6 +2000,8 @@ pub const Type = extern union { .many_mut_pointer, .c_const_pointer, .c_mut_pointer, + .const_slice, + .mut_slice, .single_const_pointer_to_comptime_int, .const_slice_u8, .u8, @@ -2025,6 +2070,8 @@ pub const Type = extern union { .many_mut_pointer, .c_const_pointer, .c_mut_pointer, + .const_slice, + .mut_slice, .single_const_pointer_to_comptime_int, .const_slice_u8, .u8, @@ -2090,6 +2137,8 @@ pub const Type = extern union { .many_mut_pointer, .c_const_pointer, .c_mut_pointer, + .const_slice, + .mut_slice, .single_const_pointer_to_comptime_int, .const_slice_u8, .u8, @@ -2155,6 +2204,8 @@ pub const Type = extern union { .many_mut_pointer, .c_const_pointer, .c_mut_pointer, + .const_slice, + .mut_slice, .single_const_pointer_to_comptime_int, .const_slice_u8, .u8, @@ -2240,6 +2291,8 @@ pub const Type = extern union { .many_mut_pointer, .c_const_pointer, .c_mut_pointer, + .const_slice, + .mut_slice, .single_const_pointer_to_comptime_int, .const_slice_u8, .optional, @@ -2290,6 +2343,8 @@ pub const Type = extern union { .array_sentinel, .array_u8_sentinel_0, .const_slice_u8, + .const_slice, + .mut_slice, .c_void, .optional, .optional_single_mut_pointer, @@ -2392,6 +2447,8 @@ pub const Type = extern union { .single_mut_pointer, .many_const_pointer, .many_mut_pointer, + .const_slice, + .mut_slice, .optional, .optional_single_mut_pointer, .optional_single_const_pointer, @@ -2467,6 +2524,8 @@ pub const Type = extern union { many_mut_pointer, c_const_pointer, c_mut_pointer, + const_slice, + mut_slice, int_signed, int_unsigned, function, diff --git a/src-self-hosted/zir.zig b/src-self-hosted/zir.zig index db0ec242cc..a3ea1f11ab 100644 --- a/src-self-hosted/zir.zig +++ b/src-self-hosted/zir.zig @@ -194,18 +194,22 @@ pub const Inst = struct { shl, /// Integer shift-right. Arithmetic or logical depending on the signedness of the integer type. shr, - /// Create a const pointer type based on the element type. `*const T` + /// Create a const pointer type with element type T. `*const T` single_const_ptr_type, - /// Create a mutable pointer type based on the element type. `*T` + /// Create a mutable pointer type with element type T. `*T` single_mut_ptr_type, - /// Create a const pointer type based on the element type. `[*]const T` + /// Create a const pointer type with element type T. `[*]const T` many_const_ptr_type, - /// Create a mutable pointer type based on the element type. `[*]T` + /// Create a mutable pointer type with element type T. `[*]T` many_mut_ptr_type, - /// Create a const pointer type based on the element type. `[*c]const T` + /// Create a const pointer type with element type T. `[*c]const T` c_const_ptr_type, - /// Create a mutable pointer type based on the element type. `[*c]T` + /// Create a mutable pointer type with element type T. `[*c]T` c_mut_ptr_type, + /// Create a mutable slice type with element type T. `[]T` + mut_slice_type, + /// Create a const slice type with element type T. `[]T` + const_slice_type, /// Create a pointer type with attributes ptr_type, /// Write a value to a pointer. For loading, see `deref`. @@ -274,6 +278,8 @@ pub const Inst = struct { .many_mut_ptr_type, .c_const_ptr_type, .c_mut_ptr_type, + .mut_slice_type, + .const_slice_type, .optional_type, .unwrap_optional_safe, .unwrap_optional_unsafe, @@ -416,6 +422,8 @@ pub const Inst = struct { .many_mut_ptr_type, .c_const_ptr_type, .c_mut_ptr_type, + .mut_slice_type, + .const_slice_type, .store, .str, .sub, diff --git a/src-self-hosted/zir_sema.zig b/src-self-hosted/zir_sema.zig index ea3b85b29a..75ec7f6306 100644 --- a/src-self-hosted/zir_sema.zig +++ b/src-self-hosted/zir_sema.zig @@ -57,6 +57,8 @@ pub fn analyzeInst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError! .many_mut_ptr_type => return analyzeInstSimplePtrType(mod, scope, old_inst.castTag(.many_mut_ptr_type).?, true, .Many), .c_const_ptr_type => return analyzeInstSimplePtrType(mod, scope, old_inst.castTag(.c_const_ptr_type).?, false, .C), .c_mut_ptr_type => return analyzeInstSimplePtrType(mod, scope, old_inst.castTag(.c_mut_ptr_type).?, true, .C), + .const_slice_type => return analyzeInstSimplePtrType(mod, scope, old_inst.castTag(.const_slice_type).?, false, .Slice), + .mut_slice_type => return analyzeInstSimplePtrType(mod, scope, old_inst.castTag(.mut_slice_type).?, true, .Slice), .ptr_type => return analyzeInstPtrType(mod, scope, old_inst.castTag(.ptr_type).?), .store => return analyzeInstStore(mod, scope, old_inst.castTag(.store).?), .str => return analyzeInstStr(mod, scope, old_inst.castTag(.str).?),