authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-04-24 17:31:52-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-04-24 17:44:07-07:00
logff2ec0dc5ad272113379ff485bb71c6c1637d948
tree64a073251b80178a293434d8df9aa4cc5998bf4c
parente018e64a53eb7fdffedb3efadb862f400f9e9f70

AstGen: implement `@Vector`


5 files changed, 82 insertions(+), 15 deletions(-)

src/AstGen.zig+9
...@@ -1808,6 +1808,7 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: ast.Node.Index) Inner...@@ -1808,6 +1808,7 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: ast.Node.Index) Inner
1808 .array_mul,1808 .array_mul,
1809 .array_type,1809 .array_type,
1810 .array_type_sentinel,1810 .array_type_sentinel,
1811 .vector_type,
1811 .elem_type,1812 .elem_type,
1812 .indexable_ptr_len,1813 .indexable_ptr_len,
1813 .anyframe_type,1814 .anyframe_type,
...@@ -6510,6 +6511,14 @@ fn builtinCall(...@@ -6510,6 +6511,14 @@ fn builtinCall(
6510 });6511 });
6511 return rvalue(gz, scope, rl, result, node);6512 return rvalue(gz, scope, rl, result, node);
6512 },6513 },
6514 .Vector => {
6515 const result = try gz.addPlNode(.vector_type, node, Zir.Inst.Bin{
6516 .lhs = try comptimeExpr(gz, scope, .{.ty = .u32_type}, params[0]),
6517 .rhs = try typeExpr(gz, scope, params[1]),
6518 });
6519 return rvalue(gz, scope, rl, result, node);
6520 },
6521
6513 }6522 }
6514 // zig fmt: on6523 // zig fmt: on
6515}6524}
src/BuiltinFn.zig+8
...@@ -104,6 +104,7 @@ pub const Tag = enum {...@@ -104,6 +104,7 @@ pub const Tag = enum {
104 type_name,104 type_name,
105 TypeOf,105 TypeOf,
106 union_init,106 union_init,
107 Vector,
107};108};
108109
109tag: Tag,110tag: Tag,
...@@ -848,5 +849,12 @@ pub const list = list: {...@@ -848,5 +849,12 @@ pub const list = list: {
848 .param_count = 3,849 .param_count = 3,
849 },850 },
850 },851 },
852 .{
853 "@Vector",
854 .{
855 .tag = .Vector,
856 .param_count = 2,
857 },
858 },
851 });859 });
852};860};
src/Sema.zig+16
...@@ -143,6 +143,7 @@ pub fn analyzeBody(...@@ -143,6 +143,7 @@ pub fn analyzeBody(
143 .array_mul => try sema.zirArrayMul(block, inst),143 .array_mul => try sema.zirArrayMul(block, inst),
144 .array_type => try sema.zirArrayType(block, inst),144 .array_type => try sema.zirArrayType(block, inst),
145 .array_type_sentinel => try sema.zirArrayTypeSentinel(block, inst),145 .array_type_sentinel => try sema.zirArrayTypeSentinel(block, inst),
146 .vector_type => try sema.zirVectorType(block, inst),
146 .as => try sema.zirAs(block, inst),147 .as => try sema.zirAs(block, inst),
147 .as_node => try sema.zirAsNode(block, inst),148 .as_node => try sema.zirAsNode(block, inst),
148 .bit_and => try sema.zirBitwise(block, inst, .bit_and),149 .bit_and => try sema.zirBitwise(block, inst, .bit_and),
...@@ -2143,6 +2144,21 @@ fn zirElemType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerErro...@@ -2143,6 +2144,21 @@ fn zirElemType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerErro
2143 return sema.mod.constType(sema.arena, src, elem_type);2144 return sema.mod.constType(sema.arena, src, elem_type);
2144}2145}
21452146
2147fn zirVectorType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
2148 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
2149 const src = inst_data.src();
2150 const elem_type_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
2151 const len_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node };
2152 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
2153 const len = try sema.resolveAlreadyCoercedInt(block, len_src, extra.lhs, u32);
2154 const elem_type = try sema.resolveType(block, elem_type_src, extra.rhs);
2155 const vector_type = try Type.Tag.vector.create(sema.arena, .{
2156 .len = len,
2157 .elem_type = elem_type,
2158 });
2159 return sema.mod.constType(sema.arena, src, vector_type);
2160}
2161
2146fn zirArrayType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {2162fn zirArrayType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
2147 const tracy = trace(@src());2163 const tracy = trace(@src());
2148 defer tracy.end();2164 defer tracy.end();
src/Zir.zig+6
...@@ -158,6 +158,10 @@ pub const Inst = struct {...@@ -158,6 +158,10 @@ pub const Inst = struct {
158 /// `[N:S]T` syntax. No source location provided.158 /// `[N:S]T` syntax. No source location provided.
159 /// Uses the `array_type_sentinel` field.159 /// Uses the `array_type_sentinel` field.
160 array_type_sentinel,160 array_type_sentinel,
161 /// `@Vector` builtin.
162 /// Uses the `pl_node` union field with `Bin` payload.
163 /// lhs is length, rhs is element type.
164 vector_type,
161 /// Given an array type, returns the element type.165 /// Given an array type, returns the element type.
162 /// Uses the `un_node` union field.166 /// Uses the `un_node` union field.
163 elem_type,167 elem_type,
...@@ -952,6 +956,7 @@ pub const Inst = struct {...@@ -952,6 +956,7 @@ pub const Inst = struct {
952 .array_mul,956 .array_mul,
953 .array_type,957 .array_type,
954 .array_type_sentinel,958 .array_type_sentinel,
959 .vector_type,
955 .elem_type,960 .elem_type,
956 .indexable_ptr_len,961 .indexable_ptr_len,
957 .anyframe_type,962 .anyframe_type,
...@@ -2542,6 +2547,7 @@ const Writer = struct {...@@ -2542,6 +2547,7 @@ const Writer = struct {
2542 .atomic_load,2547 .atomic_load,
2543 .bitcast,2548 .bitcast,
2544 .bitcast_result_ptr,2549 .bitcast_result_ptr,
2550 .vector_type,
2545 => try self.writePlNodeBin(stream, inst),2551 => try self.writePlNodeBin(stream, inst),
25462552
2547 .@"export" => try self.writePlNodeExport(stream, inst),2553 .@"export" => try self.writePlNodeExport(stream, inst),
src/type.zig+43-15
...@@ -69,7 +69,14 @@ pub const Type = extern union {...@@ -69,7 +69,14 @@ pub const Type = extern union {
69 .fn_ccc_void_no_args => return .Fn,69 .fn_ccc_void_no_args => return .Fn,
70 .function => return .Fn,70 .function => return .Fn,
7171
72 .array, .array_u8_sentinel_0, .array_u8, .array_sentinel => return .Array,72 .array,
73 .array_u8_sentinel_0,
74 .array_u8,
75 .array_sentinel,
76 => return .Array,
77
78 .vector => return .Vector,
79
73 .single_const_pointer_to_comptime_int,80 .single_const_pointer_to_comptime_int,
74 .const_slice_u8,81 .const_slice_u8,
75 .single_const_pointer,82 .single_const_pointer,
...@@ -438,7 +445,7 @@ pub const Type = extern union {...@@ -438,7 +445,7 @@ pub const Type = extern union {
438 const info_b = b.intInfo(@as(Target, undefined));445 const info_b = b.intInfo(@as(Target, undefined));
439 return info_a.signedness == info_b.signedness and info_a.bits == info_b.bits;446 return info_a.signedness == info_b.signedness and info_a.bits == info_b.bits;
440 },447 },
441 .Array => {448 .Array, .Vector => {
442 if (a.arrayLen() != b.arrayLen())449 if (a.arrayLen() != b.arrayLen())
443 return false;450 return false;
444 if (!a.elemType().eql(b.elemType()))451 if (!a.elemType().eql(b.elemType()))
...@@ -487,7 +494,6 @@ pub const Type = extern union {...@@ -487,7 +494,6 @@ pub const Type = extern union {
487 .BoundFn,494 .BoundFn,
488 .Opaque,495 .Opaque,
489 .Frame,496 .Frame,
490 .Vector,
491 => std.debug.panic("TODO implement Type equality comparison of {} and {}", .{ a, b }),497 => std.debug.panic("TODO implement Type equality comparison of {} and {}", .{ a, b }),
492 }498 }
493 }499 }
...@@ -522,7 +528,7 @@ pub const Type = extern union {...@@ -522,7 +528,7 @@ pub const Type = extern union {
522 std.hash.autoHash(&hasher, info.bits);528 std.hash.autoHash(&hasher, info.bits);
523 }529 }
524 },530 },
525 .Array => {531 .Array, .Vector => {
526 std.hash.autoHash(&hasher, self.arrayLen());532 std.hash.autoHash(&hasher, self.arrayLen());
527 std.hash.autoHash(&hasher, self.elemType().hash());533 std.hash.autoHash(&hasher, self.elemType().hash());
528 // TODO hash array sentinel534 // TODO hash array sentinel
...@@ -552,7 +558,6 @@ pub const Type = extern union {...@@ -552,7 +558,6 @@ pub const Type = extern union {
552 .Opaque,558 .Opaque,
553 .Frame,559 .Frame,
554 .AnyFrame,560 .AnyFrame,
555 .Vector,
556 .EnumLiteral,561 .EnumLiteral,
557 => {562 => {
558 // TODO implement more type hashing563 // TODO implement more type hashing
...@@ -647,6 +652,13 @@ pub const Type = extern union {...@@ -647,6 +652,13 @@ pub const Type = extern union {
647 .int_unsigned,652 .int_unsigned,
648 => return self.copyPayloadShallow(allocator, Payload.Bits),653 => return self.copyPayloadShallow(allocator, Payload.Bits),
649654
655 .vector => {
656 const payload = self.castTag(.vector).?.data;
657 return Tag.vector.create(allocator, .{
658 .len = payload.len,
659 .elem_type = try payload.elem_type.copy(allocator),
660 });
661 },
650 .array => {662 .array => {
651 const payload = self.castTag(.array).?.data;663 const payload = self.castTag(.array).?.data;
652 return Tag.array.create(allocator, .{664 return Tag.array.create(allocator, .{
...@@ -839,6 +851,12 @@ pub const Type = extern union {...@@ -839,6 +851,12 @@ pub const Type = extern union {
839 const len = ty.castTag(.array_u8_sentinel_0).?.data;851 const len = ty.castTag(.array_u8_sentinel_0).?.data;
840 return writer.print("[{d}:0]u8", .{len});852 return writer.print("[{d}:0]u8", .{len});
841 },853 },
854 .vector => {
855 const payload = ty.castTag(.vector).?.data;
856 try writer.print("@Vector({d}, ", .{payload.len});
857 try payload.elem_type.format("", .{}, writer);
858 return writer.writeAll(")");
859 },
842 .array => {860 .array => {
843 const payload = ty.castTag(.array).?.data;861 const payload = ty.castTag(.array).?.data;
844 try writer.print("[{d}]", .{payload.len});862 try writer.print("[{d}]", .{payload.len});
...@@ -1116,7 +1134,7 @@ pub const Type = extern union {...@@ -1116,7 +1134,7 @@ pub const Type = extern union {
1116 },1134 },
11171135
1118 // TODO lazy types1136 // TODO lazy types
1119 .array => self.elemType().hasCodeGenBits() and self.arrayLen() != 0,1137 .array, .vector => self.elemType().hasCodeGenBits() and self.arrayLen() != 0,
1120 .array_u8 => self.arrayLen() != 0,1138 .array_u8 => self.arrayLen() != 0,
1121 .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(),1139 .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(),
1122 .int_signed, .int_unsigned => self.cast(Payload.Bits).?.data != 0,1140 .int_signed, .int_unsigned => self.cast(Payload.Bits).?.data != 0,
...@@ -1264,6 +1282,10 @@ pub const Type = extern union {...@@ -1264,6 +1282,10 @@ pub const Type = extern union {
12641282
1265 .array, .array_sentinel => return self.elemType().abiAlignment(target),1283 .array, .array_sentinel => return self.elemType().abiAlignment(target),
12661284
1285 // TODO audit this - is there any more complicated logic to determine
1286 // ABI alignment of vectors?
1287 .vector => return 16,
1288
1267 .int_signed, .int_unsigned => {1289 .int_signed, .int_unsigned => {
1268 const bits: u16 = self.cast(Payload.Bits).?.data;1290 const bits: u16 = self.cast(Payload.Bits).?.data;
1269 return std.math.ceilPowerOfTwoPromote(u16, (bits + 7) / 8);1291 return std.math.ceilPowerOfTwoPromote(u16, (bits + 7) / 8);
...@@ -1386,8 +1408,8 @@ pub const Type = extern union {...@@ -1386,8 +1408,8 @@ pub const Type = extern union {
13861408
1387 .array_u8 => self.castTag(.array_u8).?.data,1409 .array_u8 => self.castTag(.array_u8).?.data,
1388 .array_u8_sentinel_0 => self.castTag(.array_u8_sentinel_0).?.data + 1,1410 .array_u8_sentinel_0 => self.castTag(.array_u8_sentinel_0).?.data + 1,
1389 .array => {1411 .array, .vector => {
1390 const payload = self.castTag(.array).?.data;1412 const payload = self.cast(Payload.Array).?.data;
1391 const elem_size = std.math.max(payload.elem_type.abiAlignment(target), payload.elem_type.abiSize(target));1413 const elem_size = std.math.max(payload.elem_type.abiAlignment(target), payload.elem_type.abiSize(target));
1392 return payload.len * elem_size;1414 return payload.len * elem_size;
1393 },1415 },
...@@ -1534,6 +1556,11 @@ pub const Type = extern union {...@@ -1534,6 +1556,11 @@ pub const Type = extern union {
15341556
1535 .bool => 1,1557 .bool => 1,
15361558
1559 .vector => {
1560 const payload = self.castTag(.vector).?.data;
1561 const elem_bit_size = payload.elem_type.bitSize(target);
1562 return elem_bit_size * payload.len;
1563 },
1537 .array_u8 => 8 * self.castTag(.array_u8).?.data,1564 .array_u8 => 8 * self.castTag(.array_u8).?.data,
1538 .array_u8_sentinel_0 => 8 * (self.castTag(.array_u8_sentinel_0).?.data + 1),1565 .array_u8_sentinel_0 => 8 * (self.castTag(.array_u8_sentinel_0).?.data + 1),
1539 .array => {1566 .array => {
...@@ -1811,7 +1838,6 @@ pub const Type = extern union {...@@ -1811,7 +1838,6 @@ pub const Type = extern union {
1811 .Enum,1838 .Enum,
1812 .Frame,1839 .Frame,
1813 .AnyFrame,1840 .AnyFrame,
1814 .Vector,
1815 => return true,1841 => return true,
18161842
1817 .Opaque => return is_extern,1843 .Opaque => return is_extern,
...@@ -1830,7 +1856,7 @@ pub const Type = extern union {...@@ -1830,7 +1856,7 @@ pub const Type = extern union {
1830 var buf: Payload.ElemType = undefined;1856 var buf: Payload.ElemType = undefined;
1831 return ty.optionalChild(&buf).isValidVarType(is_extern);1857 return ty.optionalChild(&buf).isValidVarType(is_extern);
1832 },1858 },
1833 .Pointer, .Array => ty = ty.elemType(),1859 .Pointer, .Array, .Vector => ty = ty.elemType(),
1834 .ErrorUnion => ty = ty.errorUnionChild(),1860 .ErrorUnion => ty = ty.errorUnionChild(),
18351861
1836 .Fn => @panic("TODO fn isValidVarType"),1862 .Fn => @panic("TODO fn isValidVarType"),
...@@ -1846,6 +1872,7 @@ pub const Type = extern union {...@@ -1846,6 +1872,7 @@ pub const Type = extern union {
1846 /// Asserts the type is a pointer or array type.1872 /// Asserts the type is a pointer or array type.
1847 pub fn elemType(self: Type) Type {1873 pub fn elemType(self: Type) Type {
1848 return switch (self.tag()) {1874 return switch (self.tag()) {
1875 .vector => self.castTag(.vector).?.data.elem_type,
1849 .array => self.castTag(.array).?.data.elem_type,1876 .array => self.castTag(.array).?.data.elem_type,
1850 .array_sentinel => self.castTag(.array_sentinel).?.data.elem_type,1877 .array_sentinel => self.castTag(.array_sentinel).?.data.elem_type,
1851 .single_const_pointer,1878 .single_const_pointer,
...@@ -1936,6 +1963,7 @@ pub const Type = extern union {...@@ -1936,6 +1963,7 @@ pub const Type = extern union {
1936 /// Asserts the type is an array or vector.1963 /// Asserts the type is an array or vector.
1937 pub fn arrayLen(self: Type) u64 {1964 pub fn arrayLen(self: Type) u64 {
1938 return switch (self.tag()) {1965 return switch (self.tag()) {
1966 .vector => self.castTag(.vector).?.data.len,
1939 .array => self.castTag(.array).?.data.len,1967 .array => self.castTag(.array).?.data.len,
1940 .array_sentinel => self.castTag(.array_sentinel).?.data.len,1968 .array_sentinel => self.castTag(.array_sentinel).?.data.len,
1941 .array_u8 => self.castTag(.array_u8).?.data,1969 .array_u8 => self.castTag(.array_u8).?.data,
...@@ -1955,6 +1983,7 @@ pub const Type = extern union {...@@ -1955,6 +1983,7 @@ pub const Type = extern union {
1955 .c_const_pointer,1983 .c_const_pointer,
1956 .c_mut_pointer,1984 .c_mut_pointer,
1957 .single_const_pointer_to_comptime_int,1985 .single_const_pointer_to_comptime_int,
1986 .vector,
1958 .array,1987 .array,
1959 .array_u8,1988 .array_u8,
1960 .manyptr_u8,1989 .manyptr_u8,
...@@ -2325,7 +2354,7 @@ pub const Type = extern union {...@@ -2325,7 +2354,7 @@ pub const Type = extern union {
2325 return null;2354 return null;
2326 }2355 }
2327 },2356 },
2328 .array, .array_u8 => {2357 .vector, .array, .array_u8 => {
2329 if (ty.arrayLen() == 0)2358 if (ty.arrayLen() == 0)
2330 return Value.initTag(.empty_array);2359 return Value.initTag(.empty_array);
2331 ty = ty.elemType();2360 ty = ty.elemType();
...@@ -2730,6 +2759,7 @@ pub const Type = extern union {...@@ -2730,6 +2759,7 @@ pub const Type = extern union {
2730 array_u8_sentinel_0,2759 array_u8_sentinel_0,
2731 array,2760 array,
2732 array_sentinel,2761 array_sentinel,
2762 vector,
2733 pointer,2763 pointer,
2734 single_const_pointer,2764 single_const_pointer,
2735 single_mut_pointer,2765 single_mut_pointer,
...@@ -2845,7 +2875,7 @@ pub const Type = extern union {...@@ -2845,7 +2875,7 @@ pub const Type = extern union {
28452875
2846 .error_set => Payload.ErrorSet,2876 .error_set => Payload.ErrorSet,
28472877
2848 .array => Payload.Array,2878 .array, .vector => Payload.Array,
2849 .array_sentinel => Payload.ArraySentinel,2879 .array_sentinel => Payload.ArraySentinel,
2850 .pointer => Payload.Pointer,2880 .pointer => Payload.Pointer,
2851 .function => Payload.Function,2881 .function => Payload.Function,
...@@ -2888,9 +2918,7 @@ pub const Type = extern union {...@@ -2888,9 +2918,7 @@ pub const Type = extern union {
2888 };2918 };
28892919
2890 pub const Array = struct {2920 pub const Array = struct {
2891 pub const base_tag = Tag.array;2921 base: Payload,
2892
2893 base: Payload = Payload{ .tag = base_tag },
2894 data: struct {2922 data: struct {
2895 len: u64,2923 len: u64,
2896 elem_type: Type,2924 elem_type: Type,