authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-09-14 21:57:01-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-09-14 21:57:01-07:00
log5d8fec3d4cdfa58b54756c4368bdb3e76d21380f
treebf300a4a12b43ca4f9487193cc3fb6b0b15e4b90
parent6acd903a9510d0e145b7bba3a9d42d4b9c07cc34
parent5e39ab460073b0068d30a74488abf83333761c8d

Merge remote-tracking branch 'origin/master' into stage2-zig-cc


19 files changed, 651 insertions(+), 169 deletions(-)

.builds/freebsd.yml+2-2
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1image: freebsd/latest1image: freebsd/latest
2secrets:2secrets:
3 - 6c60aaee-92e7-4e7d-812c-114817689b4d3 - 51bfddf5-86a6-4e01-8576-358c72a4a0a4
4 - dd0bd962-7664-4d3e-b0f3-41c9ee96b8b84 - 5cfede76-914e-4071-893e-e5e2e6ae3cea
5sources:5sources:
6 - https://github.com/ziglang/zig6 - https://github.com/ziglang/zig
7tasks:7tasks:
ci/srht/freebsd_script+4-6
...@@ -28,11 +28,8 @@ make $JOBS install...@@ -28,11 +28,8 @@ make $JOBS install
2828
29release/bin/zig build test-fmt29release/bin/zig build test-fmt
30release/bin/zig build test-behavior30release/bin/zig build test-behavior
3131# TODO get these tests passing on freebsd and re-enable
32# This test is disabled because it triggers "out of memory" on the sr.ht CI service.32#release/bin/zig build test-std
33# See https://github.com/ziglang/zig/issues/3210
34# release/bin/zig build test-std
35
36release/bin/zig build test-compiler-rt33release/bin/zig build test-compiler-rt
37release/bin/zig build test-compare-output34release/bin/zig build test-compare-output
38release/bin/zig build test-standalone35release/bin/zig build test-standalone
...@@ -44,7 +41,8 @@ release/bin/zig build test-translate-c...@@ -44,7 +41,8 @@ release/bin/zig build test-translate-c
44release/bin/zig build test-run-translated-c41release/bin/zig build test-run-translated-c
45# TODO disabled until we are shipping self-hosted42# TODO disabled until we are shipping self-hosted
46#release/bin/zig build test-gen-h43#release/bin/zig build test-gen-h
47release/bin/zig build test-compile-errors44# TODO disabled to save time and hit that 45 minute limit
45#release/bin/zig build test-compile-errors
48release/bin/zig build docs46release/bin/zig build docs
4947
50if [ -f ~/.s3cfg ]; then48if [ -f ~/.s3cfg ]; then
ci/srht/on_master_success+1-1
...@@ -36,4 +36,4 @@ jq <$YML_FILE -sR '{...@@ -36,4 +36,4 @@ jq <$YML_FILE -sR '{
36 -H Authorization:"token $OAUTH_TOKEN" \36 -H Authorization:"token $OAUTH_TOKEN" \
37 -H Content-Type:application/json \37 -H Content-Type:application/json \
38 -X POST \38 -X POST \
39 -d @- "https://builds.sr.ht/api/jobs"39 -d @- "https://builds.hut.lavatech.top/api/jobs"
lib/std/builtin.zig-1
...@@ -317,7 +317,6 @@ pub const TypeInfo = union(enum) {...@@ -317,7 +317,6 @@ pub const TypeInfo = union(enum) {
317 /// therefore must be kept in sync with the compiler implementation.317 /// therefore must be kept in sync with the compiler implementation.
318 pub const UnionField = struct {318 pub const UnionField = struct {
319 name: []const u8,319 name: []const u8,
320 enum_field: ?EnumField,
321 field_type: type,320 field_type: type,
322 };321 };
323322
lib/std/fmt.zig+1-1
...@@ -399,7 +399,7 @@ pub fn formatType(...@@ -399,7 +399,7 @@ pub fn formatType(
399 try writer.writeAll(@tagName(@as(UnionTagType, value)));399 try writer.writeAll(@tagName(@as(UnionTagType, value)));
400 try writer.writeAll(" = ");400 try writer.writeAll(" = ");
401 inline for (info.fields) |u_field| {401 inline for (info.fields) |u_field| {
402 if (@enumToInt(@as(UnionTagType, value)) == u_field.enum_field.?.value) {402 if (value == @field(UnionTagType, u_field.name)) {
403 try formatType(@field(value, u_field.name), fmt, options, writer, max_depth - 1);403 try formatType(@field(value, u_field.name), fmt, options, writer, max_depth - 1);
404 }404 }
405 }405 }
lib/std/hash/auto_hash.zig+2-3
...@@ -139,9 +139,8 @@ pub fn hash(hasher: anytype, key: anytype, comptime strat: HashStrategy) void {...@@ -139,9 +139,8 @@ pub fn hash(hasher: anytype, key: anytype, comptime strat: HashStrategy) void {
139 const tag = meta.activeTag(key);139 const tag = meta.activeTag(key);
140 const s = hash(hasher, tag, strat);140 const s = hash(hasher, tag, strat);
141 inline for (info.fields) |field| {141 inline for (info.fields) |field| {
142 const enum_field = field.enum_field.?;142 if (@field(tag_type, field.name) == tag) {
143 if (enum_field.value == @enumToInt(tag)) {143 hash(hasher, @field(key, field.name), strat);
144 hash(hasher, @field(key, enum_field.name), strat);
145 // TODO use a labelled break when it does not crash the compiler. cf #2908144 // TODO use a labelled break when it does not crash the compiler. cf #2908
146 // break :blk;145 // break :blk;
147 return;146 return;
lib/std/hash/crc.zig+1-4
...@@ -71,10 +71,7 @@ pub fn Crc32WithPoly(comptime poly: Polynomial) type {...@@ -71,10 +71,7 @@ pub fn Crc32WithPoly(comptime poly: Polynomial) type {
71 const p = input[i .. i + 8];71 const p = input[i .. i + 8];
7272
73 // Unrolling this way gives ~50Mb/s increase73 // Unrolling this way gives ~50Mb/s increase
74 self.crc ^= (@as(u32, p[0]) << 0);74 self.crc ^= std.mem.readIntLittle(u32, p[0..4]);
75 self.crc ^= (@as(u32, p[1]) << 8);
76 self.crc ^= (@as(u32, p[2]) << 16);
77 self.crc ^= (@as(u32, p[3]) << 24);
7875
79 self.crc =76 self.crc =
80 lookup_tables[0][p[7]] ^77 lookup_tables[0][p[7]] ^
lib/std/io/serialization.zig+2-2
...@@ -156,7 +156,7 @@ pub fn Deserializer(comptime endian: builtin.Endian, comptime packing: Packing,...@@ -156,7 +156,7 @@ pub fn Deserializer(comptime endian: builtin.Endian, comptime packing: Packing,
156 const tag = try self.deserializeInt(TagInt);156 const tag = try self.deserializeInt(TagInt);
157157
158 inline for (info.fields) |field_info| {158 inline for (info.fields) |field_info| {
159 if (field_info.enum_field.?.value == tag) {159 if (@enumToInt(@field(TagType, field_info.name)) == tag) {
160 const name = field_info.name;160 const name = field_info.name;
161 const FieldType = field_info.field_type;161 const FieldType = field_info.field_type;
162 ptr.* = @unionInit(C, name, undefined);162 ptr.* = @unionInit(C, name, undefined);
...@@ -320,7 +320,7 @@ pub fn Serializer(comptime endian: builtin.Endian, comptime packing: Packing, co...@@ -320,7 +320,7 @@ pub fn Serializer(comptime endian: builtin.Endian, comptime packing: Packing, co
320 // value, but @field requires a comptime value. Our alternative320 // value, but @field requires a comptime value. Our alternative
321 // is to check each field for a match321 // is to check each field for a match
322 inline for (info.fields) |field_info| {322 inline for (info.fields) |field_info| {
323 if (field_info.enum_field.?.value == @enumToInt(active_tag)) {323 if (@field(TagType, field_info.name) == active_tag) {
324 const name = field_info.name;324 const name = field_info.name;
325 const FieldType = field_info.field_type;325 const FieldType = field_info.field_type;
326 try self.serialize(@field(value, name));326 try self.serialize(@field(value, name));
lib/std/json.zig+2-2
...@@ -1613,7 +1613,7 @@ pub fn parseFree(comptime T: type, value: T, options: ParseOptions) void {...@@ -1613,7 +1613,7 @@ pub fn parseFree(comptime T: type, value: T, options: ParseOptions) void {
1613 .Union => |unionInfo| {1613 .Union => |unionInfo| {
1614 if (unionInfo.tag_type) |UnionTagType| {1614 if (unionInfo.tag_type) |UnionTagType| {
1615 inline for (unionInfo.fields) |u_field| {1615 inline for (unionInfo.fields) |u_field| {
1616 if (@enumToInt(@as(UnionTagType, value)) == u_field.enum_field.?.value) {1616 if (value == @field(UnionTagType, u_field.name)) {
1617 parseFree(u_field.field_type, @field(value, u_field.name), options);1617 parseFree(u_field.field_type, @field(value, u_field.name), options);
1618 break;1618 break;
1619 }1619 }
...@@ -2458,7 +2458,7 @@ pub fn stringify(...@@ -2458,7 +2458,7 @@ pub fn stringify(
2458 const info = @typeInfo(T).Union;2458 const info = @typeInfo(T).Union;
2459 if (info.tag_type) |UnionTagType| {2459 if (info.tag_type) |UnionTagType| {
2460 inline for (info.fields) |u_field| {2460 inline for (info.fields) |u_field| {
2461 if (@enumToInt(@as(UnionTagType, value)) == u_field.enum_field.?.value) {2461 if (value == @field(UnionTagType, u_field.name)) {
2462 return try stringify(@field(value, u_field.name), options, out_stream);2462 return try stringify(@field(value, u_field.name), options, out_stream);
2463 }2463 }
2464 }2464 }
lib/std/meta.zig+7-5
...@@ -465,10 +465,13 @@ pub fn TagPayloadType(comptime U: type, tag: @TagType(U)) type {...@@ -465,10 +465,13 @@ pub fn TagPayloadType(comptime U: type, tag: @TagType(U)) type {
465 testing.expect(trait.is(.Union)(U));465 testing.expect(trait.is(.Union)(U));
466466
467 const info = @typeInfo(U).Union;467 const info = @typeInfo(U).Union;
468 const tag_info = @typeInfo(@TagType(U)).Enum;
468469
469 inline for (info.fields) |field_info| {470 inline for (info.fields) |field_info| {
470 if (field_info.enum_field.?.value == @enumToInt(tag)) return field_info.field_type;471 if (comptime mem.eql(u8, field_info.name, @tagName(tag)))
472 return field_info.field_type;
471 }473 }
474
472 unreachable;475 unreachable;
473}476}
474477
...@@ -504,15 +507,14 @@ pub fn eql(a: anytype, b: @TypeOf(a)) bool {...@@ -504,15 +507,14 @@ pub fn eql(a: anytype, b: @TypeOf(a)) bool {
504 }507 }
505 },508 },
506 .Union => |info| {509 .Union => |info| {
507 if (info.tag_type) |_| {510 if (info.tag_type) |Tag| {
508 const tag_a = activeTag(a);511 const tag_a = activeTag(a);
509 const tag_b = activeTag(b);512 const tag_b = activeTag(b);
510 if (tag_a != tag_b) return false;513 if (tag_a != tag_b) return false;
511514
512 inline for (info.fields) |field_info| {515 inline for (info.fields) |field_info| {
513 const enum_field = field_info.enum_field.?;516 if (@field(Tag, field_info.name) == tag_a) {
514 if (enum_field.value == @enumToInt(tag_a)) {517 return eql(@field(a, field_info.name), @field(b, field_info.name));
515 return eql(@field(a, enum_field.name), @field(b, enum_field.name));
516 }518 }
517 }519 }
518 return false;520 return false;
lib/std/os.zig+9-1
...@@ -320,6 +320,7 @@ pub const ReadError = error{...@@ -320,6 +320,7 @@ pub const ReadError = error{
320/// Linux has a limit on how many bytes may be transferred in one `read` call, which is `0x7ffff000`320/// Linux has a limit on how many bytes may be transferred in one `read` call, which is `0x7ffff000`
321/// on both 64-bit and 32-bit systems. This is due to using a signed C int as the return value, as321/// on both 64-bit and 32-bit systems. This is due to using a signed C int as the return value, as
322/// well as stuffing the errno codes into the last `4096` values. This is noted on the `read` man page.322/// well as stuffing the errno codes into the last `4096` values. This is noted on the `read` man page.
323/// The limit on Darwin is `0x7fffffff`, trying to read more than that returns EINVAL.
323/// For POSIX the limit is `math.maxInt(isize)`.324/// For POSIX the limit is `math.maxInt(isize)`.
324pub fn read(fd: fd_t, buf: []u8) ReadError!usize {325pub fn read(fd: fd_t, buf: []u8) ReadError!usize {
325 if (builtin.os.tag == .windows) {326 if (builtin.os.tag == .windows) {
...@@ -353,6 +354,7 @@ pub fn read(fd: fd_t, buf: []u8) ReadError!usize {...@@ -353,6 +354,7 @@ pub fn read(fd: fd_t, buf: []u8) ReadError!usize {
353 // Prevents EINVAL.354 // Prevents EINVAL.
354 const max_count = switch (std.Target.current.os.tag) {355 const max_count = switch (std.Target.current.os.tag) {
355 .linux => 0x7ffff000,356 .linux => 0x7ffff000,
357 .macosx, .ios, .watchos, .tvos => math.maxInt(i32),
356 else => math.maxInt(isize),358 else => math.maxInt(isize),
357 };359 };
358 const adjusted_len = math.min(max_count, buf.len);360 const adjusted_len = math.min(max_count, buf.len);
...@@ -693,6 +695,7 @@ pub const WriteError = error{...@@ -693,6 +695,7 @@ pub const WriteError = error{
693/// Linux has a limit on how many bytes may be transferred in one `write` call, which is `0x7ffff000`695/// Linux has a limit on how many bytes may be transferred in one `write` call, which is `0x7ffff000`
694/// on both 64-bit and 32-bit systems. This is due to using a signed C int as the return value, as696/// on both 64-bit and 32-bit systems. This is due to using a signed C int as the return value, as
695/// well as stuffing the errno codes into the last `4096` values. This is noted on the `write` man page.697/// well as stuffing the errno codes into the last `4096` values. This is noted on the `write` man page.
698/// The limit on Darwin is `0x7fffffff`, trying to read more than that returns EINVAL.
696/// The corresponding POSIX limit is `math.maxInt(isize)`.699/// The corresponding POSIX limit is `math.maxInt(isize)`.
697pub fn write(fd: fd_t, bytes: []const u8) WriteError!usize {700pub fn write(fd: fd_t, bytes: []const u8) WriteError!usize {
698 if (builtin.os.tag == .windows) {701 if (builtin.os.tag == .windows) {
...@@ -726,6 +729,7 @@ pub fn write(fd: fd_t, bytes: []const u8) WriteError!usize {...@@ -726,6 +729,7 @@ pub fn write(fd: fd_t, bytes: []const u8) WriteError!usize {
726729
727 const max_count = switch (std.Target.current.os.tag) {730 const max_count = switch (std.Target.current.os.tag) {
728 .linux => 0x7ffff000,731 .linux => 0x7ffff000,
732 .macosx, .ios, .watchos, .tvos => math.maxInt(i32),
729 else => math.maxInt(isize),733 else => math.maxInt(isize),
730 };734 };
731 const adjusted_len = math.min(max_count, bytes.len);735 const adjusted_len = math.min(max_count, bytes.len);
...@@ -851,6 +855,7 @@ pub const PWriteError = WriteError || error{Unseekable};...@@ -851,6 +855,7 @@ pub const PWriteError = WriteError || error{Unseekable};
851/// Linux has a limit on how many bytes may be transferred in one `pwrite` call, which is `0x7ffff000`855/// Linux has a limit on how many bytes may be transferred in one `pwrite` call, which is `0x7ffff000`
852/// on both 64-bit and 32-bit systems. This is due to using a signed C int as the return value, as856/// on both 64-bit and 32-bit systems. This is due to using a signed C int as the return value, as
853/// well as stuffing the errno codes into the last `4096` values. This is noted on the `write` man page.857/// well as stuffing the errno codes into the last `4096` values. This is noted on the `write` man page.
858/// The limit on Darwin is `0x7fffffff`, trying to write more than that returns EINVAL.
854/// The corresponding POSIX limit is `math.maxInt(isize)`.859/// The corresponding POSIX limit is `math.maxInt(isize)`.
855pub fn pwrite(fd: fd_t, bytes: []const u8, offset: u64) PWriteError!usize {860pub fn pwrite(fd: fd_t, bytes: []const u8, offset: u64) PWriteError!usize {
856 if (std.Target.current.os.tag == .windows) {861 if (std.Target.current.os.tag == .windows) {
...@@ -888,6 +893,7 @@ pub fn pwrite(fd: fd_t, bytes: []const u8, offset: u64) PWriteError!usize {...@@ -888,6 +893,7 @@ pub fn pwrite(fd: fd_t, bytes: []const u8, offset: u64) PWriteError!usize {
888 // Prevent EINVAL.893 // Prevent EINVAL.
889 const max_count = switch (std.Target.current.os.tag) {894 const max_count = switch (std.Target.current.os.tag) {
890 .linux => 0x7ffff000,895 .linux => 0x7ffff000,
896 .macosx, .ios, .watchos, .tvos => math.maxInt(i32),
891 else => math.maxInt(isize),897 else => math.maxInt(isize),
892 };898 };
893 const adjusted_len = math.min(max_count, bytes.len);899 const adjusted_len = math.min(max_count, bytes.len);
...@@ -3084,7 +3090,7 @@ pub fn connect(sockfd: socket_t, sock_addr: *const sockaddr, len: socklen_t) Con...@@ -3084,7 +3090,7 @@ pub fn connect(sockfd: socket_t, sock_addr: *const sockaddr, len: socklen_t) Con
3084 .WSAECONNREFUSED => return error.ConnectionRefused,3090 .WSAECONNREFUSED => return error.ConnectionRefused,
3085 .WSAETIMEDOUT => return error.ConnectionTimedOut,3091 .WSAETIMEDOUT => return error.ConnectionTimedOut,
3086 .WSAEHOSTUNREACH // TODO: should we return NetworkUnreachable in this case as well?3092 .WSAEHOSTUNREACH // TODO: should we return NetworkUnreachable in this case as well?
3087 , .WSAENETUNREACH => return error.NetworkUnreachable,3093 , .WSAENETUNREACH => return error.NetworkUnreachable,
3088 .WSAEFAULT => unreachable,3094 .WSAEFAULT => unreachable,
3089 .WSAEINVAL => unreachable,3095 .WSAEINVAL => unreachable,
3090 .WSAEISCONN => unreachable,3096 .WSAEISCONN => unreachable,
...@@ -4711,6 +4717,7 @@ fn count_iovec_bytes(iovs: []const iovec_const) usize {...@@ -4711,6 +4717,7 @@ fn count_iovec_bytes(iovs: []const iovec_const) usize {
4711/// Linux has a limit on how many bytes may be transferred in one `sendfile` call, which is `0x7ffff000`4717/// Linux has a limit on how many bytes may be transferred in one `sendfile` call, which is `0x7ffff000`
4712/// on both 64-bit and 32-bit systems. This is due to using a signed C int as the return value, as4718/// on both 64-bit and 32-bit systems. This is due to using a signed C int as the return value, as
4713/// well as stuffing the errno codes into the last `4096` values. This is cited on the `sendfile` man page.4719/// well as stuffing the errno codes into the last `4096` values. This is cited on the `sendfile` man page.
4720/// The limit on Darwin is `0x7fffffff`, trying to write more than that returns EINVAL.
4714/// The corresponding POSIX limit on this is `math.maxInt(isize)`.4721/// The corresponding POSIX limit on this is `math.maxInt(isize)`.
4715pub fn sendfile(4722pub fn sendfile(
4716 out_fd: fd_t,4723 out_fd: fd_t,
...@@ -4733,6 +4740,7 @@ pub fn sendfile(...@@ -4733,6 +4740,7 @@ pub fn sendfile(
4733 });4740 });
4734 const max_count = switch (std.Target.current.os.tag) {4741 const max_count = switch (std.Target.current.os.tag) {
4735 .linux => 0x7ffff000,4742 .linux => 0x7ffff000,
4743 .macosx, .ios, .watchos, .tvos => math.maxInt(i32),
4736 else => math.maxInt(size_t),4744 else => math.maxInt(size_t),
4737 };4745 };
47384746
lib/std/os/linux/bpf.zig+1
...@@ -12,6 +12,7 @@ const expectError = std.testing.expectError;...@@ -12,6 +12,7 @@ const expectError = std.testing.expectError;
12const expect = std.testing.expect;12const expect = std.testing.expect;
1313
14pub const btf = @import("bpf/btf.zig");14pub const btf = @import("bpf/btf.zig");
15pub const kern = @import("bpf/kern.zig");
1516
16// instruction classes17// instruction classes
17pub const LD = 0x00;18pub const LD = 0x00;
lib/std/os/linux/bpf/helpers.zig created+157
...@@ -0,0 +1,157 @@
1// SPDX-License-Identifier: MIT
2// Copyright (c) 2015-2020 Zig Contributors
3// This file is part of [zig](https://ziglang.org/), which is MIT licensed.
4// The MIT license requires this copyright notice to be included in all copies
5// and substantial portions of the software.
6const kern = @import("kern.zig");
7
8// in BPF, all the helper calls
9// TODO: when https://github.com/ziglang/zig/issues/1717 is here, make a nice
10// function that uses the Helper enum
11//
12// Note, these function signatures were created from documentation found in
13// '/usr/include/linux/bpf.h'
14pub const map_lookup_elem = @intToPtr(fn (map: *const kern.MapDef, key: ?*const c_void) ?*c_void, 1);
15pub const map_update_elem = @intToPtr(fn (map: *const kern.MapDef, key: ?*const c_void, value: ?*const c_void, flags: u64) c_long, 2);
16pub const map_delete_elem = @intToPtr(fn (map: *const kern.MapDef, key: ?*const c_void) c_long, 3);
17pub const probe_read = @intToPtr(fn (dst: ?*c_void, size: u32, unsafe_ptr: ?*const c_void) c_long, 4);
18pub const ktime_get_ns = @intToPtr(fn () u64, 5);
19pub const trace_printk = @intToPtr(fn (fmt: [*:0]const u8, fmt_size: u32, arg1: u64, arg2: u64, arg3: u64) c_long, 6);
20pub const get_prandom_u32 = @intToPtr(fn () u32, 7);
21pub const get_smp_processor_id = @intToPtr(fn () u32, 8);
22pub const skb_store_bytes = @intToPtr(fn (skb: *kern.SkBuff, offset: u32, from: ?*const c_void, len: u32, flags: u64) c_long, 9);
23pub const l3_csum_replace = @intToPtr(fn (skb: *kern.SkBuff, offset: u32, from: u64, to: u64, size: u64) c_long, 10);
24pub const l4_csum_replace = @intToPtr(fn (skb: *kern.SkBuff, offset: u32, from: u64, to: u64, flags: u64) c_long, 11);
25pub const tail_call = @intToPtr(fn (ctx: ?*c_void, prog_array_map: *const kern.MapDef, index: u32) c_long, 12);
26pub const clone_redirect = @intToPtr(fn (skb: *kern.SkBuff, ifindex: u32, flags: u64) c_long, 13);
27pub const get_current_pid_tgid = @intToPtr(fn () u64, 14);
28pub const get_current_uid_gid = @intToPtr(fn () u64, 15);
29pub const get_current_comm = @intToPtr(fn (buf: ?*c_void, size_of_buf: u32) c_long, 16);
30pub const get_cgroup_classid = @intToPtr(fn (skb: *kern.SkBuff) u32, 17);
31// Note vlan_proto is big endian
32pub const skb_vlan_push = @intToPtr(fn (skb: *kern.SkBuff, vlan_proto: u16, vlan_tci: u16) c_long, 18);
33pub const skb_vlan_pop = @intToPtr(fn (skb: *kern.SkBuff) c_long, 19);
34pub const skb_get_tunnel_key = @intToPtr(fn (skb: *kern.SkBuff, key: *kern.TunnelKey, size: u32, flags: u64) c_long, 20);
35pub const skb_set_tunnel_key = @intToPtr(fn (skb: *kern.SkBuff, key: *kern.TunnelKey, size: u32, flags: u64) c_long, 21);
36pub const perf_event_read = @intToPtr(fn (map: *const kern.MapDef, flags: u64) u64, 22);
37pub const redirect = @intToPtr(fn (ifindex: u32, flags: u64) c_long, 23);
38pub const get_route_realm = @intToPtr(fn (skb: *kern.SkBuff) u32, 24);
39pub const perf_event_output = @intToPtr(fn (ctx: ?*c_void, map: *const kern.MapDef, flags: u64, data: ?*c_void, size: u64) c_long, 25);
40pub const skb_load_bytes = @intToPtr(fn (skb: ?*c_void, offset: u32, to: ?*c_void, len: u32) c_long, 26);
41pub const get_stackid = @intToPtr(fn (ctx: ?*c_void, map: *const kern.MapDef, flags: u64) c_long, 27);
42// from and to point to __be32
43pub const csum_diff = @intToPtr(fn (from: *u32, from_size: u32, to: *u32, to_size: u32, seed: u32) i64, 28);
44pub const skb_get_tunnel_opt = @intToPtr(fn (skb: *kern.SkBuff, opt: ?*c_void, size: u32) c_long, 29);
45pub const skb_set_tunnel_opt = @intToPtr(fn (skb: *kern.SkBuff, opt: ?*c_void, size: u32) c_long, 30);
46// proto is __be16
47pub const skb_change_proto = @intToPtr(fn (skb: *kern.SkBuff, proto: u16, flags: u64) c_long, 31);
48pub const skb_change_type = @intToPtr(fn (skb: *kern.SkBuff, skb_type: u32) c_long, 32);
49pub const skb_under_cgroup = @intToPtr(fn (skb: *kern.SkBuff, map: ?*const c_void, index: u32) c_long, 33);
50pub const get_hash_recalc = @intToPtr(fn (skb: *kern.SkBuff) u32, 34);
51pub const get_current_task = @intToPtr(fn () u64, 35);
52pub const probe_write_user = @intToPtr(fn (dst: ?*c_void, src: ?*const c_void, len: u32) c_long, 36);
53pub const current_task_under_cgroup = @intToPtr(fn (map: *const kern.MapDef, index: u32) c_long, 37);
54pub const skb_change_tail = @intToPtr(fn (skb: *kern.SkBuff, len: u32, flags: u64) c_long, 38);
55pub const skb_pull_data = @intToPtr(fn (skb: *kern.SkBuff, len: u32) c_long, 39);
56pub const csum_update = @intToPtr(fn (skb: *kern.SkBuff, csum: u32) i64, 40);
57pub const set_hash_invalid = @intToPtr(fn (skb: *kern.SkBuff) void, 41);
58pub const get_numa_node_id = @intToPtr(fn () c_long, 42);
59pub const skb_change_head = @intToPtr(fn (skb: *kern.SkBuff, len: u32, flags: u64) c_long, 43);
60pub const xdp_adjust_head = @intToPtr(fn (xdp_md: *kern.XdpMd, delta: c_int) c_long, 44);
61pub const probe_read_str = @intToPtr(fn (dst: ?*c_void, size: u32, unsafe_ptr: ?*const c_void) c_long, 45);
62pub const get_socket_cookie = @intToPtr(fn (ctx: ?*c_void) u64, 46);
63pub const get_socket_uid = @intToPtr(fn (skb: *kern.SkBuff) u32, 47);
64pub const set_hash = @intToPtr(fn (skb: *kern.SkBuff, hash: u32) c_long, 48);
65pub const setsockopt = @intToPtr(fn (bpf_socket: *kern.SockOps, level: c_int, optname: c_int, optval: ?*c_void, optlen: c_int) c_long, 49);
66pub const skb_adjust_room = @intToPtr(fn (skb: *kern.SkBuff, len_diff: i32, mode: u32, flags: u64) c_long, 50);
67pub const redirect_map = @intToPtr(fn (map: *const kern.MapDef, key: u32, flags: u64) c_long, 51);
68pub const sk_redirect_map = @intToPtr(fn (skb: *kern.SkBuff, map: *const kern.MapDef, key: u32, flags: u64) c_long, 52);
69pub const sock_map_update = @intToPtr(fn (skops: *kern.SockOps, map: *const kern.MapDef, key: ?*c_void, flags: u64) c_long, 53);
70pub const xdp_adjust_meta = @intToPtr(fn (xdp_md: *kern.XdpMd, delta: c_int) c_long, 54);
71pub const perf_event_read_value = @intToPtr(fn (map: *const kern.MapDef, flags: u64, buf: *kern.PerfEventValue, buf_size: u32) c_long, 55);
72pub const perf_prog_read_value = @intToPtr(fn (ctx: *kern.PerfEventData, buf: *kern.PerfEventValue, buf_size: u32) c_long, 56);
73pub const getsockopt = @intToPtr(fn (bpf_socket: ?*c_void, level: c_int, optname: c_int, optval: ?*c_void, optlen: c_int) c_long, 57);
74pub const override_return = @intToPtr(fn (regs: *PtRegs, rc: u64) c_long, 58);
75pub const sock_ops_cb_flags_set = @intToPtr(fn (bpf_sock: *kern.SockOps, argval: c_int) c_long, 59);
76pub const msg_redirect_map = @intToPtr(fn (msg: *kern.SkMsgMd, map: *const kern.MapDef, key: u32, flags: u64) c_long, 60);
77pub const msg_apply_bytes = @intToPtr(fn (msg: *kern.SkMsgMd, bytes: u32) c_long, 61);
78pub const msg_cork_bytes = @intToPtr(fn (msg: *kern.SkMsgMd, bytes: u32) c_long, 62);
79pub const msg_pull_data = @intToPtr(fn (msg: *kern.SkMsgMd, start: u32, end: u32, flags: u64) c_long, 63);
80pub const bind = @intToPtr(fn (ctx: *kern.BpfSockAddr, addr: *kern.SockAddr, addr_len: c_int) c_long, 64);
81pub const xdp_adjust_tail = @intToPtr(fn (xdp_md: *kern.XdpMd, delta: c_int) c_long, 65);
82pub const skb_get_xfrm_state = @intToPtr(fn (skb: *kern.SkBuff, index: u32, xfrm_state: *kern.XfrmState, size: u32, flags: u64) c_long, 66);
83pub const get_stack = @intToPtr(fn (ctx: ?*c_void, buf: ?*c_void, size: u32, flags: u64) c_long, 67);
84pub const skb_load_bytes_relative = @intToPtr(fn (skb: ?*const c_void, offset: u32, to: ?*c_void, len: u32, start_header: u32) c_long, 68);
85pub const fib_lookup = @intToPtr(fn (ctx: ?*c_void, params: *kern.FibLookup, plen: c_int, flags: u32) c_long, 69);
86pub const sock_hash_update = @intToPtr(fn (skops: *kern.SockOps, map: *const kern.MapDef, key: ?*c_void, flags: u64) c_long, 70);
87pub const msg_redirect_hash = @intToPtr(fn (msg: *kern.SkMsgMd, map: *const kern.MapDef, key: ?*c_void, flags: u64) c_long, 71);
88pub const sk_redirect_hash = @intToPtr(fn (skb: *kern.SkBuff, map: *const kern.MapDef, key: ?*c_void, flags: u64) c_long, 72);
89pub const lwt_push_encap = @intToPtr(fn (skb: *kern.SkBuff, typ: u32, hdr: ?*c_void, len: u32) c_long, 73);
90pub const lwt_seg6_store_bytes = @intToPtr(fn (skb: *kern.SkBuff, offset: u32, from: ?*const c_void, len: u32) c_long, 74);
91pub const lwt_seg6_adjust_srh = @intToPtr(fn (skb: *kern.SkBuff, offset: u32, delta: i32) c_long, 75);
92pub const lwt_seg6_action = @intToPtr(fn (skb: *kern.SkBuff, action: u32, param: ?*c_void, param_len: u32) c_long, 76);
93pub const rc_repeat = @intToPtr(fn (ctx: ?*c_void) c_long, 77);
94pub const rc_keydown = @intToPtr(fn (ctx: ?*c_void, protocol: u32, scancode: u64, toggle: u32) c_long, 78);
95pub const skb_cgroup_id = @intToPtr(fn (skb: *kern.SkBuff) u64, 79);
96pub const get_current_cgroup_id = @intToPtr(fn () u64, 80);
97pub const get_local_storage = @intToPtr(fn (map: ?*c_void, flags: u64) ?*c_void, 81);
98pub const sk_select_reuseport = @intToPtr(fn (reuse: *kern.SkReusePortMd, map: *const kern.MapDef, key: ?*c_void, flags: u64) c_long, 82);
99pub const skb_ancestor_cgroup_id = @intToPtr(fn (skb: *kern.SkBuff, ancestor_level: c_int) u64, 83);
100pub const sk_lookup_tcp = @intToPtr(fn (ctx: ?*c_void, tuple: *kern.SockTuple, tuple_size: u32, netns: u64, flags: u64) ?*kern.Sock, 84);
101pub const sk_lookup_udp = @intToPtr(fn (ctx: ?*c_void, tuple: *kern.SockTuple, tuple_size: u32, netns: u64, flags: u64) ?*kern.Sock, 85);
102pub const sk_release = @intToPtr(fn (sock: *kern.Sock) c_long, 86);
103pub const map_push_elem = @intToPtr(fn (map: *const kern.MapDef, value: ?*const c_void, flags: u64) c_long, 87);
104pub const map_pop_elem = @intToPtr(fn (map: *const kern.MapDef, value: ?*c_void) c_long, 88);
105pub const map_peek_elem = @intToPtr(fn (map: *const kern.MapDef, value: ?*c_void) c_long, 89);
106pub const msg_push_data = @intToPtr(fn (msg: *kern.SkMsgMd, start: u32, len: u32, flags: u64) c_long, 90);
107pub const msg_pop_data = @intToPtr(fn (msg: *kern.SkMsgMd, start: u32, len: u32, flags: u64) c_long, 91);
108pub const rc_pointer_rel = @intToPtr(fn (ctx: ?*c_void, rel_x: i32, rel_y: i32) c_long, 92);
109pub const spin_lock = @intToPtr(fn (lock: *kern.SpinLock) c_long, 93);
110pub const spin_unlock = @intToPtr(fn (lock: *kern.SpinLock) c_long, 94);
111pub const sk_fullsock = @intToPtr(fn (sk: *kern.Sock) ?*SkFullSock, 95);
112pub const tcp_sock = @intToPtr(fn (sk: *kern.Sock) ?*kern.TcpSock, 96);
113pub const skb_ecn_set_ce = @intToPtr(fn (skb: *kern.SkBuff) c_long, 97);
114pub const get_listener_sock = @intToPtr(fn (sk: *kern.Sock) ?*kern.Sock, 98);
115pub const skc_lookup_tcp = @intToPtr(fn (ctx: ?*c_void, tuple: *kern.SockTuple, tuple_size: u32, netns: u64, flags: u64) ?*kern.Sock, 99);
116pub const tcp_check_syncookie = @intToPtr(fn (sk: *kern.Sock, iph: ?*c_void, iph_len: u32, th: *TcpHdr, th_len: u32) c_long, 100);
117pub const sysctl_get_name = @intToPtr(fn (ctx: *kern.SysCtl, buf: ?*u8, buf_len: c_ulong, flags: u64) c_long, 101);
118pub const sysctl_get_current_value = @intToPtr(fn (ctx: *kern.SysCtl, buf: ?*u8, buf_len: c_ulong) c_long, 102);
119pub const sysctl_get_new_value = @intToPtr(fn (ctx: *kern.SysCtl, buf: ?*u8, buf_len: c_ulong) c_long, 103);
120pub const sysctl_set_new_value = @intToPtr(fn (ctx: *kern.SysCtl, buf: ?*const u8, buf_len: c_ulong) c_long, 104);
121pub const strtol = @intToPtr(fn (buf: *const u8, buf_len: c_ulong, flags: u64, res: *c_long) c_long, 105);
122pub const strtoul = @intToPtr(fn (buf: *const u8, buf_len: c_ulong, flags: u64, res: *c_ulong) c_long, 106);
123pub const sk_storage_get = @intToPtr(fn (map: *const kern.MapDef, sk: *kern.Sock, value: ?*c_void, flags: u64) ?*c_void, 107);
124pub const sk_storage_delete = @intToPtr(fn (map: *const kern.MapDef, sk: *kern.Sock) c_long, 108);
125pub const send_signal = @intToPtr(fn (sig: u32) c_long, 109);
126pub const tcp_gen_syncookie = @intToPtr(fn (sk: *kern.Sock, iph: ?*c_void, iph_len: u32, th: *TcpHdr, th_len: u32) i64, 110);
127pub const skb_output = @intToPtr(fn (ctx: ?*c_void, map: *const kern.MapDef, flags: u64, data: ?*c_void, size: u64) c_long, 111);
128pub const probe_read_user = @intToPtr(fn (dst: ?*c_void, size: u32, unsafe_ptr: ?*const c_void) c_long, 112);
129pub const probe_read_kernel = @intToPtr(fn (dst: ?*c_void, size: u32, unsafe_ptr: ?*const c_void) c_long, 113);
130pub const probe_read_user_str = @intToPtr(fn (dst: ?*c_void, size: u32, unsafe_ptr: ?*const c_void) c_long, 114);
131pub const probe_read_kernel_str = @intToPtr(fn (dst: ?*c_void, size: u32, unsafe_ptr: ?*const c_void) c_long, 115);
132pub const tcp_send_ack = @intToPtr(fn (tp: ?*c_void, rcv_nxt: u32) c_long, 116);
133pub const send_signal_thread = @intToPtr(fn (sig: u32) c_long, 117);
134pub const jiffies64 = @intToPtr(fn () u64, 118);
135pub const read_branch_records = @intToPtr(fn (ctx: *kern.PerfEventData, buf: ?*c_void, size: u32, flags: u64) c_long, 119);
136pub const get_ns_current_pid_tgid = @intToPtr(fn (dev: u64, ino: u64, nsdata: *kern.PidNsInfo, size: u32) c_long, 120);
137pub const xdp_output = @intToPtr(fn (ctx: ?*c_void, map: *const kern.MapDef, flags: u64, data: ?*c_void, size: u64) c_long, 121);
138pub const get_netns_cookie = @intToPtr(fn (ctx: ?*c_void) u64, 122);
139pub const get_current_ancestor_cgroup_id = @intToPtr(fn (ancestor_level: c_int) u64, 123);
140pub const sk_assign = @intToPtr(fn (skb: *kern.SkBuff, sk: *kern.Sock, flags: u64) c_long, 124);
141pub const ktime_get_boot_ns = @intToPtr(fn () u64, 125);
142pub const seq_printf = @intToPtr(fn (m: *kern.SeqFile, fmt: ?*const u8, fmt_size: u32, data: ?*const c_void, data_len: u32) c_long, 126);
143pub const seq_write = @intToPtr(fn (m: *kern.SeqFile, data: ?*const u8, len: u32) c_long, 127);
144pub const sk_cgroup_id = @intToPtr(fn (sk: *kern.BpfSock) u64, 128);
145pub const sk_ancestor_cgroup_id = @intToPtr(fn (sk: *kern.BpfSock, ancestor_level: c_long) u64, 129);
146pub const ringbuf_output = @intToPtr(fn (ringbuf: ?*c_void, data: ?*c_void, size: u64, flags: u64) ?*c_void, 130);
147pub const ringbuf_reserve = @intToPtr(fn (ringbuf: ?*c_void, size: u64, flags: u64) ?*c_void, 131);
148pub const ringbuf_submit = @intToPtr(fn (data: ?*c_void, flags: u64) void, 132);
149pub const ringbuf_discard = @intToPtr(fn (data: ?*c_void, flags: u64) void, 133);
150pub const ringbuf_query = @intToPtr(fn (ringbuf: ?*c_void, flags: u64) u64, 134);
151pub const csum_level = @intToPtr(fn (skb: *kern.SkBuff, level: u64) c_long, 134);
152pub const skc_to_tcp6_sock = @intToPtr(fn (sk: ?*c_void) ?*kern.Tcp6Sock, 135);
153pub const skc_to_tcp_sock = @intToPtr(fn (sk: ?*c_void) ?*kern.TcpSock, 136);
154pub const skc_to_tcp_timewait_sock = @intToPtr(fn (sk: ?*c_void) ?*kern.TcpTimewaitSock, 137);
155pub const skc_to_tcp_request_sock = @intToPtr(fn (sk: ?*c_void) ?*kern.TcpRequestSock, 138);
156pub const skc_to_udp6_sock = @intToPtr(fn (sk: ?*c_void) ?*kern.Udp6Sock, 139);
157pub const get_task_stack = @intToPtr(fn (task: ?*c_void, buf: ?*c_void, size: u32, flags: u64) c_long, 140);
lib/std/os/linux/bpf/kern.zig created+39
...@@ -0,0 +1,39 @@
1// SPDX-License-Identifier: MIT
2// Copyright (c) 2015-2020 Zig Contributors
3// This file is part of [zig](https://ziglang.org/), which is MIT licensed.
4// The MIT license requires this copyright notice to be included in all copies
5// and substantial portions of the software.
6const std = @import("../../../std.zig");
7
8const in_bpf_program = switch (std.builtin.arch) {
9 .bpfel, .bpfeb => true,
10 else => false,
11};
12
13pub const helpers = if (in_bpf_program) @import("helpers.zig") else struct {};
14
15pub const BpfSock = @Type(.Opaque);
16pub const BpfSockAddr = @Type(.Opaque);
17pub const FibLookup = @Type(.Opaque);
18pub const MapDef = @Type(.Opaque);
19pub const PerfEventData = @Type(.Opaque);
20pub const PerfEventValue = @Type(.Opaque);
21pub const PidNsInfo = @Type(.Opaque);
22pub const SeqFile = @Type(.Opaque);
23pub const SkBuff = @Type(.Opaque);
24pub const SkMsgMd = @Type(.Opaque);
25pub const SkReusePortMd = @Type(.Opaque);
26pub const Sock = @Type(.Opaque);
27pub const SockAddr = @Type(.Opaque);
28pub const SockOps = @Type(.Opaque);
29pub const SockTuple = @Type(.Opaque);
30pub const SpinLock = @Type(.Opaque);
31pub const SysCtl = @Type(.Opaque);
32pub const Tcp6Sock = @Type(.Opaque);
33pub const TcpRequestSock = @Type(.Opaque);
34pub const TcpSock = @Type(.Opaque);
35pub const TcpTimewaitSock = @Type(.Opaque);
36pub const TunnelKey = @Type(.Opaque);
37pub const Udp6Sock = @Type(.Opaque);
38pub const XdpMd = @Type(.Opaque);
39pub const XfrmState = @Type(.Opaque);
src/analyze.cpp+147-116
...@@ -2379,7 +2379,10 @@ static Error resolve_union_alignment(CodeGen *g, ZigType *union_type) {...@@ -2379,7 +2379,10 @@ static Error resolve_union_alignment(CodeGen *g, ZigType *union_type) {
2379 if (field->gen_index == UINT32_MAX)2379 if (field->gen_index == UINT32_MAX)
2380 continue;2380 continue;
23812381
2382 AstNode *align_expr = field->decl_node->data.struct_field.align_expr;2382 AstNode *align_expr = nullptr;
2383 if (union_type->data.unionation.decl_node->type == NodeTypeContainerDecl) {
2384 align_expr = field->decl_node->data.struct_field.align_expr;
2385 }
2383 if (align_expr != nullptr) {2386 if (align_expr != nullptr) {
2384 if (!analyze_const_align(g, &union_type->data.unionation.decls_scope->base, align_expr,2387 if (!analyze_const_align(g, &union_type->data.unionation.decls_scope->base, align_expr,
2385 &field->align))2388 &field->align))
...@@ -2475,9 +2478,6 @@ static Error resolve_union_type(CodeGen *g, ZigType *union_type) {...@@ -2475,9 +2478,6 @@ static Error resolve_union_type(CodeGen *g, ZigType *union_type) {
24752478
2476 AstNode *decl_node = union_type->data.unionation.decl_node;2479 AstNode *decl_node = union_type->data.unionation.decl_node;
24772480
2478
2479 assert(decl_node->type == NodeTypeContainerDecl);
2480
2481 uint32_t field_count = union_type->data.unionation.src_field_count;2481 uint32_t field_count = union_type->data.unionation.src_field_count;
2482 TypeUnionField *most_aligned_union_member = union_type->data.unionation.most_aligned_union_member;2482 TypeUnionField *most_aligned_union_member = union_type->data.unionation.most_aligned_union_member;
24832483
...@@ -2610,16 +2610,16 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {...@@ -2610,16 +2610,16 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {
2610 if (decl_node->type == NodeTypeContainerDecl) {2610 if (decl_node->type == NodeTypeContainerDecl) {
2611 assert(!enum_type->data.enumeration.fields);2611 assert(!enum_type->data.enumeration.fields);
2612 field_count = (uint32_t)decl_node->data.container_decl.fields.length;2612 field_count = (uint32_t)decl_node->data.container_decl.fields.length;
2613 if (field_count == 0) {
2614 add_node_error(g, decl_node, buf_sprintf("enums must have 1 or more fields"));
2615
2616 enum_type->data.enumeration.src_field_count = field_count;
2617 enum_type->data.enumeration.fields = nullptr;
2618 enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
2619 return ErrorSemanticAnalyzeFail;
2620 }
2621 } else {2613 } else {
2622 field_count = enum_type->data.enumeration.src_field_count;2614 field_count = enum_type->data.enumeration.src_field_count + enum_type->data.enumeration.non_exhaustive;
2615 }
2616
2617 if (field_count == 0) {
2618 add_node_error(g, decl_node, buf_sprintf("enums must have 1 or more fields"));
2619 enum_type->data.enumeration.src_field_count = field_count;
2620 enum_type->data.enumeration.fields = nullptr;
2621 enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
2622 return ErrorSemanticAnalyzeFail;
2623 }2623 }
26242624
2625 Scope *scope = &enum_type->data.enumeration.decls_scope->base;2625 Scope *scope = &enum_type->data.enumeration.decls_scope->base;
...@@ -3062,7 +3062,6 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {...@@ -3062,7 +3062,6 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {
3062 return ErrorNone;3062 return ErrorNone;
30633063
3064 AstNode *decl_node = union_type->data.unionation.decl_node;3064 AstNode *decl_node = union_type->data.unionation.decl_node;
3065 assert(decl_node->type == NodeTypeContainerDecl);
30663065
3067 if (union_type->data.unionation.resolve_loop_flag_zero_bits) {3066 if (union_type->data.unionation.resolve_loop_flag_zero_bits) {
3068 if (union_type->data.unionation.resolve_status != ResolveStatusInvalid) {3067 if (union_type->data.unionation.resolve_status != ResolveStatusInvalid) {
...@@ -3076,30 +3075,51 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {...@@ -3076,30 +3075,51 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {
30763075
3077 union_type->data.unionation.resolve_loop_flag_zero_bits = true;3076 union_type->data.unionation.resolve_loop_flag_zero_bits = true;
30783077
3079 assert(union_type->data.unionation.fields == nullptr);3078 uint32_t field_count;
3080 uint32_t field_count = (uint32_t)decl_node->data.container_decl.fields.length;3079 if (decl_node->type == NodeTypeContainerDecl) {
3080 assert(union_type->data.unionation.fields == nullptr);
3081 field_count = (uint32_t)decl_node->data.container_decl.fields.length;
3082 union_type->data.unionation.src_field_count = field_count;
3083 union_type->data.unionation.fields = heap::c_allocator.allocate<TypeUnionField>(field_count);
3084 union_type->data.unionation.fields_by_name.init(field_count);
3085 } else {
3086 field_count = union_type->data.unionation.src_field_count;
3087 assert(field_count == 0 || union_type->data.unionation.fields != nullptr);
3088 }
3089
3081 if (field_count == 0) {3090 if (field_count == 0) {
3082 add_node_error(g, decl_node, buf_sprintf("unions must have 1 or more fields"));3091 add_node_error(g, decl_node, buf_sprintf("unions must have 1 or more fields"));
3083 union_type->data.unionation.src_field_count = field_count;3092 union_type->data.unionation.src_field_count = field_count;
3084 union_type->data.unionation.resolve_status = ResolveStatusInvalid;3093 union_type->data.unionation.resolve_status = ResolveStatusInvalid;
3085 return ErrorSemanticAnalyzeFail;3094 return ErrorSemanticAnalyzeFail;
3086 }3095 }
3087 union_type->data.unionation.src_field_count = field_count;
3088 union_type->data.unionation.fields = heap::c_allocator.allocate<TypeUnionField>(field_count);
3089 union_type->data.unionation.fields_by_name.init(field_count);
30903096
3091 Scope *scope = &union_type->data.unionation.decls_scope->base;3097 Scope *scope = &union_type->data.unionation.decls_scope->base;
30923098
3093 HashMap<BigInt, AstNode *, bigint_hash, bigint_eql> occupied_tag_values = {};3099 HashMap<BigInt, AstNode *, bigint_hash, bigint_eql> occupied_tag_values = {};
30943100
3095 AstNode *enum_type_node = decl_node->data.container_decl.init_arg_expr;3101 bool is_auto_enum; // union(enum) or union(enum(expr))
3096 union_type->data.unionation.have_explicit_tag_type = decl_node->data.container_decl.auto_enum ||3102 bool is_explicit_enum; // union(expr)
3097 enum_type_node != nullptr;3103 AstNode *enum_type_node; // expr in union(enum(expr)) or union(expr)
3098 bool auto_layout = (union_type->data.unionation.layout == ContainerLayoutAuto);3104 if (decl_node->type == NodeTypeContainerDecl) {
3099 bool want_safety = (field_count >= 2) && (auto_layout || enum_type_node != nullptr) && !(g->build_mode == BuildModeFastRelease || g->build_mode == BuildModeSmallRelease);3105 is_auto_enum = decl_node->data.container_decl.auto_enum;
3106 is_explicit_enum = decl_node->data.container_decl.init_arg_expr != nullptr;
3107 enum_type_node = decl_node->data.container_decl.init_arg_expr;
3108 } else {
3109 is_auto_enum = false;
3110 is_explicit_enum = union_type->data.unionation.tag_type != nullptr;
3111 enum_type_node = nullptr;
3112 }
3113 union_type->data.unionation.have_explicit_tag_type = is_auto_enum || is_explicit_enum;
3114
3115 bool is_auto_layout = union_type->data.unionation.layout == ContainerLayoutAuto;
3116 bool want_safety = (field_count >= 2)
3117 && (is_auto_layout || is_explicit_enum)
3118 && !(g->build_mode == BuildModeFastRelease || g->build_mode == BuildModeSmallRelease);
3100 ZigType *tag_type;3119 ZigType *tag_type;
3101 bool create_enum_type = decl_node->data.container_decl.auto_enum || (enum_type_node == nullptr && want_safety);3120 bool create_enum_type = is_auto_enum || (!is_explicit_enum && want_safety);
3102 bool *covered_enum_fields;3121 bool *covered_enum_fields;
3122 bool *is_zero_bits = heap::c_allocator.allocate<bool>(field_count);
3103 ZigLLVMDIEnumerator **di_enumerators;3123 ZigLLVMDIEnumerator **di_enumerators;
3104 if (create_enum_type) {3124 if (create_enum_type) {
3105 occupied_tag_values.init(field_count);3125 occupied_tag_values.init(field_count);
...@@ -3157,71 +3177,81 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {...@@ -3157,71 +3177,81 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {
3157 return err;3177 return err;
3158 }3178 }
3159 tag_type = enum_type;3179 tag_type = enum_type;
3160 covered_enum_fields = heap::c_allocator.allocate<bool>(enum_type->data.enumeration.src_field_count);
3161 } else {3180 } else {
3162 tag_type = nullptr;3181 if (decl_node->type == NodeTypeContainerDecl) {
3182 tag_type = nullptr;
3183 } else {
3184 tag_type = union_type->data.unionation.tag_type;
3185 }
3186 }
3187 if (tag_type != nullptr) {
3188 covered_enum_fields = heap::c_allocator.allocate<bool>(tag_type->data.enumeration.src_field_count);
3163 }3189 }
3164 union_type->data.unionation.tag_type = tag_type;3190 union_type->data.unionation.tag_type = tag_type;
31653191
3166 uint32_t gen_field_index = 0;
3167 for (uint32_t i = 0; i < field_count; i += 1) {3192 for (uint32_t i = 0; i < field_count; i += 1) {
3168 AstNode *field_node = decl_node->data.container_decl.fields.at(i);
3169 Buf *field_name = field_node->data.struct_field.name;
3170 TypeUnionField *union_field = &union_type->data.unionation.fields[i];3193 TypeUnionField *union_field = &union_type->data.unionation.fields[i];
3171 union_field->name = field_node->data.struct_field.name;3194 if (decl_node->type == NodeTypeContainerDecl) {
3172 union_field->decl_node = field_node;3195 AstNode *field_node = decl_node->data.container_decl.fields.at(i);
3173 union_field->gen_index = UINT32_MAX;3196 union_field->name = field_node->data.struct_field.name;
31743197 union_field->decl_node = field_node;
3175 auto field_entry = union_type->data.unionation.fields_by_name.put_unique(union_field->name, union_field);3198 union_field->gen_index = UINT32_MAX;
3176 if (field_entry != nullptr) {3199 is_zero_bits[i] = false;
3177 ErrorMsg *msg = add_node_error(g, field_node,
3178 buf_sprintf("duplicate union field: '%s'", buf_ptr(union_field->name)));
3179 add_error_note(g, msg, field_entry->value->decl_node, buf_sprintf("other field here"));
3180 union_type->data.unionation.resolve_status = ResolveStatusInvalid;
3181 return ErrorSemanticAnalyzeFail;
3182 }
31833200
3184 bool field_is_zero_bits;3201 auto field_entry = union_type->data.unionation.fields_by_name.put_unique(union_field->name, union_field);
3185 if (field_node->data.struct_field.type == nullptr) {3202 if (field_entry != nullptr) {
3186 if (decl_node->data.container_decl.auto_enum ||3203 ErrorMsg *msg = add_node_error(g, union_field->decl_node,
3187 decl_node->data.container_decl.init_arg_expr != nullptr)3204 buf_sprintf("duplicate union field: '%s'", buf_ptr(union_field->name)));
3188 {3205 add_error_note(g, msg, field_entry->value->decl_node, buf_sprintf("other field here"));
3189 union_field->type_entry = g->builtin_types.entry_void;
3190 field_is_zero_bits = true;
3191 } else {
3192 add_node_error(g, field_node, buf_sprintf("union field missing type"));
3193 union_type->data.unionation.resolve_status = ResolveStatusInvalid;3206 union_type->data.unionation.resolve_status = ResolveStatusInvalid;
3194 return ErrorSemanticAnalyzeFail;3207 return ErrorSemanticAnalyzeFail;
3195 }3208 }
3196 } else {3209
3197 ZigValue *field_type_val = analyze_const_value(g, scope,3210 if (field_node->data.struct_field.type == nullptr) {
3198 field_node->data.struct_field.type, g->builtin_types.entry_type, nullptr, LazyOkNoUndef);3211 if (is_auto_enum || is_explicit_enum) {
3199 if (type_is_invalid(field_type_val->type)) {3212 union_field->type_entry = g->builtin_types.entry_void;
3200 union_type->data.unionation.resolve_status = ResolveStatusInvalid;3213 is_zero_bits[i] = true;
3201 return ErrorSemanticAnalyzeFail;3214 } else {
3215 add_node_error(g, field_node, buf_sprintf("union field missing type"));
3216 union_type->data.unionation.resolve_status = ResolveStatusInvalid;
3217 return ErrorSemanticAnalyzeFail;
3218 }
3219 } else {
3220 ZigValue *field_type_val = analyze_const_value(g, scope,
3221 field_node->data.struct_field.type, g->builtin_types.entry_type, nullptr, LazyOkNoUndef);
3222 if (type_is_invalid(field_type_val->type)) {
3223 union_type->data.unionation.resolve_status = ResolveStatusInvalid;
3224 return ErrorSemanticAnalyzeFail;
3225 }
3226 assert(field_type_val->special != ConstValSpecialRuntime);
3227 union_field->type_val = field_type_val;
3202 }3228 }
3203 assert(field_type_val->special != ConstValSpecialRuntime);
3204 union_field->type_val = field_type_val;
3205 if (union_type->data.unionation.resolve_status == ResolveStatusInvalid)
3206 return ErrorSemanticAnalyzeFail;
32073229
3230 if (field_node->data.struct_field.value != nullptr && !is_auto_enum) {
3231 ErrorMsg *msg = add_node_error(g, field_node->data.struct_field.value,
3232 buf_create_from_str("untagged union field assignment"));
3233 add_error_note(g, msg, decl_node, buf_create_from_str("consider 'union(enum)' here"));
3234 }
3235 }
3236
3237 if (union_field->type_val != nullptr) {
3208 bool field_is_opaque_type;3238 bool field_is_opaque_type;
3209 if ((err = type_val_resolve_is_opaque_type(g, field_type_val, &field_is_opaque_type))) {3239 if ((err = type_val_resolve_is_opaque_type(g, union_field->type_val, &field_is_opaque_type))) {
3210 union_type->data.unionation.resolve_status = ResolveStatusInvalid;3240 union_type->data.unionation.resolve_status = ResolveStatusInvalid;
3211 return ErrorSemanticAnalyzeFail;3241 return ErrorSemanticAnalyzeFail;
3212 }3242 }
3213 if (field_is_opaque_type) {3243 if (field_is_opaque_type) {
3214 add_node_error(g, field_node,3244 add_node_error(g, union_field->decl_node,
3215 buf_create_from_str(3245 buf_create_from_str(
3216 "opaque types have unknown size and therefore cannot be directly embedded in unions"));3246 "opaque types have unknown size and therefore cannot be directly embedded in unions"));
3217 union_type->data.unionation.resolve_status = ResolveStatusInvalid;3247 union_type->data.unionation.resolve_status = ResolveStatusInvalid;
3218 return ErrorSemanticAnalyzeFail;3248 return ErrorSemanticAnalyzeFail;
3219 }3249 }
32203250
3221 switch (type_val_resolve_requires_comptime(g, field_type_val)) {3251 switch (type_val_resolve_requires_comptime(g, union_field->type_val)) {
3222 case ReqCompTimeInvalid:3252 case ReqCompTimeInvalid:
3223 if (g->trace_err != nullptr) {3253 if (g->trace_err != nullptr) {
3224 g->trace_err = add_error_note(g, g->trace_err, field_node,3254 g->trace_err = add_error_note(g, g->trace_err, union_field->decl_node,
3225 buf_create_from_str("while checking this field"));3255 buf_create_from_str("while checking this field"));
3226 }3256 }
3227 union_type->data.unionation.resolve_status = ResolveStatusInvalid;3257 union_type->data.unionation.resolve_status = ResolveStatusInvalid;
...@@ -3233,29 +3263,25 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {...@@ -3233,29 +3263,25 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {
3233 break;3263 break;
3234 }3264 }
32353265
3236 if ((err = type_val_resolve_zero_bits(g, field_type_val, union_type, nullptr, &field_is_zero_bits))) {3266 if ((err = type_val_resolve_zero_bits(g, union_field->type_val, union_type, nullptr, &is_zero_bits[i]))) {
3237 union_type->data.unionation.resolve_status = ResolveStatusInvalid;3267 union_type->data.unionation.resolve_status = ResolveStatusInvalid;
3238 return ErrorSemanticAnalyzeFail;3268 return ErrorSemanticAnalyzeFail;
3239 }3269 }
3240 }3270 }
32413271
3242 if (field_node->data.struct_field.value != nullptr && !decl_node->data.container_decl.auto_enum) {
3243 ErrorMsg *msg = add_node_error(g, field_node->data.struct_field.value,
3244 buf_create_from_str("untagged union field assignment"));
3245 add_error_note(g, msg, decl_node, buf_create_from_str("consider 'union(enum)' here"));
3246 }
3247
3248 if (create_enum_type) {3272 if (create_enum_type) {
3249 di_enumerators[i] = ZigLLVMCreateDebugEnumerator(g->dbuilder, buf_ptr(field_name), i);3273 di_enumerators[i] = ZigLLVMCreateDebugEnumerator(g->dbuilder, buf_ptr(union_field->name), i);
3250 union_field->enum_field = &tag_type->data.enumeration.fields[i];3274 union_field->enum_field = &tag_type->data.enumeration.fields[i];
3251 union_field->enum_field->name = field_name;3275 union_field->enum_field->name = union_field->name;
3252 union_field->enum_field->decl_index = i;3276 union_field->enum_field->decl_index = i;
3253 union_field->enum_field->decl_node = field_node;3277 union_field->enum_field->decl_node = union_field->decl_node;
32543278
3255 auto prev_entry = tag_type->data.enumeration.fields_by_name.put_unique(union_field->enum_field->name, union_field->enum_field);3279 auto prev_entry = tag_type->data.enumeration.fields_by_name.put_unique(union_field->enum_field->name, union_field->enum_field);
3256 assert(prev_entry == nullptr); // caught by union de-duplicator above3280 assert(prev_entry == nullptr); // caught by union de-duplicator above
32573281
3258 AstNode *tag_value = field_node->data.struct_field.value;3282 AstNode *tag_value = decl_node->type == NodeTypeContainerDecl
3283 ? union_field->decl_node->data.struct_field.value : nullptr;
3284
3259 // In this first pass we resolve explicit tag values.3285 // In this first pass we resolve explicit tag values.
3260 // In a second pass we will fill in the unspecified ones.3286 // In a second pass we will fill in the unspecified ones.
3261 if (tag_value != nullptr) {3287 if (tag_value != nullptr) {
...@@ -3283,11 +3309,11 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {...@@ -3283,11 +3309,11 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {
3283 return ErrorSemanticAnalyzeFail;3309 return ErrorSemanticAnalyzeFail;
3284 }3310 }
3285 }3311 }
3286 } else if (enum_type_node != nullptr) {3312 } else if (tag_type != nullptr) {
3287 union_field->enum_field = find_enum_type_field(tag_type, field_name);3313 union_field->enum_field = find_enum_type_field(tag_type, union_field->name);
3288 if (union_field->enum_field == nullptr) {3314 if (union_field->enum_field == nullptr) {
3289 ErrorMsg *msg = add_node_error(g, field_node,3315 ErrorMsg *msg = add_node_error(g, union_field->decl_node,
3290 buf_sprintf("enum field not found: '%s'", buf_ptr(field_name)));3316 buf_sprintf("enum field not found: '%s'", buf_ptr(union_field->name)));
3291 add_error_note(g, msg, tag_type->data.enumeration.decl_node,3317 add_error_note(g, msg, tag_type->data.enumeration.decl_node,
3292 buf_sprintf("enum declared here"));3318 buf_sprintf("enum declared here"));
3293 union_type->data.unionation.resolve_status = ResolveStatusInvalid;3319 union_type->data.unionation.resolve_status = ResolveStatusInvalid;
...@@ -3296,21 +3322,23 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {...@@ -3296,21 +3322,23 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {
3296 covered_enum_fields[union_field->enum_field->decl_index] = true;3322 covered_enum_fields[union_field->enum_field->decl_index] = true;
3297 } else {3323 } else {
3298 union_field->enum_field = heap::c_allocator.create<TypeEnumField>();3324 union_field->enum_field = heap::c_allocator.create<TypeEnumField>();
3299 union_field->enum_field->name = field_name;3325 union_field->enum_field->name = union_field->name;
3300 union_field->enum_field->decl_index = i;3326 union_field->enum_field->decl_index = i;
3301 bigint_init_unsigned(&union_field->enum_field->value, i);3327 bigint_init_unsigned(&union_field->enum_field->value, i);
3302 }3328 }
3303 assert(union_field->enum_field != nullptr);3329 assert(union_field->enum_field != nullptr);
3330 }
33043331
3305 if (field_is_zero_bits)3332 uint32_t gen_field_index = 0;
3306 continue;3333 for (uint32_t i = 0; i < field_count; i += 1) {
33073334 TypeUnionField *union_field = &union_type->data.unionation.fields[i];
3308 union_field->gen_index = gen_field_index;3335 if (!is_zero_bits[i]) {
3309 gen_field_index += 1;3336 union_field->gen_index = gen_field_index;
3337 gen_field_index += 1;
3338 }
3310 }3339 }
33113340
3312 bool src_have_tag = decl_node->data.container_decl.auto_enum ||3341 bool src_have_tag = is_auto_enum || is_explicit_enum;
3313 decl_node->data.container_decl.init_arg_expr != nullptr;
33143342
3315 if (src_have_tag && union_type->data.unionation.layout != ContainerLayoutAuto) {3343 if (src_have_tag && union_type->data.unionation.layout != ContainerLayoutAuto) {
3316 const char *qual_str;3344 const char *qual_str;
...@@ -3324,8 +3352,7 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {...@@ -3324,8 +3352,7 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {
3324 qual_str = "extern";3352 qual_str = "extern";
3325 break;3353 break;
3326 }3354 }
3327 AstNode *source_node = (decl_node->data.container_decl.init_arg_expr != nullptr) ?3355 AstNode *source_node = enum_type_node != nullptr ? enum_type_node : decl_node;
3328 decl_node->data.container_decl.init_arg_expr : decl_node;
3329 add_node_error(g, source_node,3356 add_node_error(g, source_node,
3330 buf_sprintf("%s union does not support enum tag type", qual_str));3357 buf_sprintf("%s union does not support enum tag type", qual_str));
3331 union_type->data.unionation.resolve_status = ResolveStatusInvalid;3358 union_type->data.unionation.resolve_status = ResolveStatusInvalid;
...@@ -3333,43 +3360,47 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {...@@ -3333,43 +3360,47 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {
3333 }3360 }
33343361
3335 if (create_enum_type) {3362 if (create_enum_type) {
3336 // Now iterate again and populate the unspecified tag values3363 if (decl_node->type == NodeTypeContainerDecl) {
3337 uint32_t next_maybe_unoccupied_index = 0;3364 // Now iterate again and populate the unspecified tag values
3365 uint32_t next_maybe_unoccupied_index = 0;
33383366
3339 for (uint32_t field_i = 0; field_i < field_count; field_i += 1) {3367 for (uint32_t field_i = 0; field_i < field_count; field_i += 1) {
3340 AstNode *field_node = decl_node->data.container_decl.fields.at(field_i);3368 AstNode *field_node = decl_node->data.container_decl.fields.at(field_i);
3341 TypeUnionField *union_field = &union_type->data.unionation.fields[field_i];3369 TypeUnionField *union_field = &union_type->data.unionation.fields[field_i];
3342 AstNode *tag_value = field_node->data.struct_field.value;3370 AstNode *tag_value = field_node->data.struct_field.value;
33433371
3344 if (tag_value == nullptr) {3372 if (tag_value == nullptr) {
3345 if (occupied_tag_values.size() == 0) {3373 if (occupied_tag_values.size() == 0) {
3346 bigint_init_unsigned(&union_field->enum_field->value, next_maybe_unoccupied_index);3374 bigint_init_unsigned(&union_field->enum_field->value, next_maybe_unoccupied_index);
3347 next_maybe_unoccupied_index += 1;
3348 } else {
3349 BigInt proposed_value;
3350 for (;;) {
3351 bigint_init_unsigned(&proposed_value, next_maybe_unoccupied_index);
3352 next_maybe_unoccupied_index += 1;3375 next_maybe_unoccupied_index += 1;
3353 auto entry = occupied_tag_values.put_unique(proposed_value, field_node);3376 } else {
3354 if (entry != nullptr) {3377 BigInt proposed_value;
3355 continue;3378 for (;;) {
3379 bigint_init_unsigned(&proposed_value, next_maybe_unoccupied_index);
3380 next_maybe_unoccupied_index += 1;
3381 auto entry = occupied_tag_values.put_unique(proposed_value, field_node);
3382 if (entry != nullptr) {
3383 continue;
3384 }
3385 break;
3356 }3386 }
3357 break;3387 bigint_init_bigint(&union_field->enum_field->value, &proposed_value);
3358 }3388 }
3359 bigint_init_bigint(&union_field->enum_field->value, &proposed_value);
3360 }3389 }
3361 }3390 }
3362 }3391 }
3363 } else if (enum_type_node != nullptr) {3392 } else if (tag_type != nullptr) {
3364 for (uint32_t i = 0; i < tag_type->data.enumeration.src_field_count; i += 1) {3393 for (uint32_t i = 0; i < tag_type->data.enumeration.src_field_count; i += 1) {
3365 TypeEnumField *enum_field = &tag_type->data.enumeration.fields[i];3394 TypeEnumField *enum_field = &tag_type->data.enumeration.fields[i];
3366 if (!covered_enum_fields[i]) {3395 if (!covered_enum_fields[i]) {
3367 AstNode *enum_decl_node = tag_type->data.enumeration.decl_node;
3368 AstNode *field_node = enum_decl_node->data.container_decl.fields.at(i);
3369 ErrorMsg *msg = add_node_error(g, decl_node,3396 ErrorMsg *msg = add_node_error(g, decl_node,
3370 buf_sprintf("enum field missing: '%s'", buf_ptr(enum_field->name)));3397 buf_sprintf("enum field missing: '%s'", buf_ptr(enum_field->name)));
3371 add_error_note(g, msg, field_node,3398 if (decl_node->type == NodeTypeContainerDecl) {
3372 buf_sprintf("declared here"));3399 AstNode *enum_decl_node = tag_type->data.enumeration.decl_node;
3400 AstNode *field_node = enum_decl_node->data.container_decl.fields.at(i);
3401 add_error_note(g, msg, field_node,
3402 buf_sprintf("declared here"));
3403 }
3373 union_type->data.unionation.resolve_status = ResolveStatusInvalid;3404 union_type->data.unionation.resolve_status = ResolveStatusInvalid;
3374 }3405 }
3375 }3406 }
...@@ -8357,7 +8388,7 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveS...@@ -8357,7 +8388,7 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveS
8357 ZigLLVMDIFile *di_file;8388 ZigLLVMDIFile *di_file;
8358 ZigLLVMDIScope *di_scope;8389 ZigLLVMDIScope *di_scope;
8359 unsigned line;8390 unsigned line;
8360 if (decl_node != nullptr && !struct_type->data.structure.created_by_at_type) {8391 if (decl_node != nullptr) {
8361 Scope *scope = &struct_type->data.structure.decls_scope->base;8392 Scope *scope = &struct_type->data.structure.decls_scope->base;
8362 ZigType *import = get_scope_import(scope);8393 ZigType *import = get_scope_import(scope);
8363 di_file = import->data.structure.root_struct->di_file;8394 di_file = import->data.structure.root_struct->di_file;
...@@ -8720,7 +8751,7 @@ static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveSta...@@ -8720,7 +8751,7 @@ static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveSta
87208751
8721 uint64_t store_size_in_bits = union_field->type_entry->size_in_bits;8752 uint64_t store_size_in_bits = union_field->type_entry->size_in_bits;
8722 uint64_t abi_align_in_bits = 8*union_field->type_entry->abi_align;8753 uint64_t abi_align_in_bits = 8*union_field->type_entry->abi_align;
8723 AstNode *field_node = decl_node->data.container_decl.fields.at(i);8754 AstNode *field_node = union_field->decl_node;
8724 union_inner_di_types[union_field->gen_index] = ZigLLVMCreateDebugMemberType(g->dbuilder,8755 union_inner_di_types[union_field->gen_index] = ZigLLVMCreateDebugMemberType(g->dbuilder,
8725 ZigLLVMTypeToScope(union_type->llvm_di_type), buf_ptr(union_field->enum_field->name),8756 ZigLLVMTypeToScope(union_type->llvm_di_type), buf_ptr(union_field->enum_field->name),
8726 import->data.structure.root_struct->di_file, (unsigned)(field_node->line + 1),8757 import->data.structure.root_struct->di_file, (unsigned)(field_node->line + 1),
src/ir.cpp+85-20
...@@ -25424,8 +25424,6 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy...@@ -25424,8 +25424,6 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy
2542425424
25425 init_const_slice(ira->codegen, fields[2], union_field_array, 0, union_field_count, false);25425 init_const_slice(ira->codegen, fields[2], union_field_array, 0, union_field_count, false);
2542625426
25427 ZigType *type_info_enum_field_type = ir_type_info_get_type(ira, "EnumField", nullptr);
25428
25429 for (uint32_t union_field_index = 0; union_field_index < union_field_count; union_field_index++) {25427 for (uint32_t union_field_index = 0; union_field_index < union_field_count; union_field_index++) {
25430 TypeUnionField *union_field = &type_entry->data.unionation.fields[union_field_index];25428 TypeUnionField *union_field = &type_entry->data.unionation.fields[union_field_index];
25431 ZigValue *union_field_val = &union_field_array->data.x_array.data.s_none.elements[union_field_index];25429 ZigValue *union_field_val = &union_field_array->data.x_array.data.s_none.elements[union_field_index];
...@@ -25433,20 +25431,10 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy...@@ -25433,20 +25431,10 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy
25433 union_field_val->special = ConstValSpecialStatic;25431 union_field_val->special = ConstValSpecialStatic;
25434 union_field_val->type = type_info_union_field_type;25432 union_field_val->type = type_info_union_field_type;
2543525433
25436 ZigValue **inner_fields = alloc_const_vals_ptrs(ira->codegen, 3);25434 ZigValue **inner_fields = alloc_const_vals_ptrs(ira->codegen, 2);
25437 inner_fields[1]->special = ConstValSpecialStatic;25435 inner_fields[1]->special = ConstValSpecialStatic;
25438 inner_fields[1]->type = get_optional_type(ira->codegen, type_info_enum_field_type);25436 inner_fields[1]->type = ira->codegen->builtin_types.entry_type;
2543925437 inner_fields[1]->data.x_type = union_field->type_entry;
25440 if (fields[1]->data.x_optional == nullptr) {
25441 inner_fields[1]->data.x_optional = nullptr;
25442 } else {
25443 inner_fields[1]->data.x_optional = ira->codegen->pass1_arena->create<ZigValue>();
25444 make_enum_field_val(ira, inner_fields[1]->data.x_optional, union_field->enum_field, type_info_enum_field_type);
25445 }
25446
25447 inner_fields[2]->special = ConstValSpecialStatic;
25448 inner_fields[2]->type = ira->codegen->builtin_types.entry_type;
25449 inner_fields[2]->data.x_type = union_field->type_entry;
2545025438
25451 ZigValue *name = create_const_str_lit(ira->codegen, union_field->name)->data.x_ptr.data.ref.pointee;25439 ZigValue *name = create_const_str_lit(ira->codegen, union_field->name)->data.x_ptr.data.ref.pointee;
25452 init_const_slice(ira->codegen, inner_fields[0], name, 0, buf_len(union_field->name), true);25440 init_const_slice(ira->codegen, inner_fields[0], name, 0, buf_len(union_field->name), true);
...@@ -26102,7 +26090,8 @@ static ZigType *type_info_to_type(IrAnalyze *ira, IrInst *source_instr, ZigTypeI...@@ -26102,7 +26090,8 @@ static ZigType *type_info_to_type(IrAnalyze *ira, IrInst *source_instr, ZigTypeI
26102 entry->data.structure.layout = layout;26090 entry->data.structure.layout = layout;
26103 entry->data.structure.special = is_tuple ? StructSpecialInferredTuple : StructSpecialNone;26091 entry->data.structure.special = is_tuple ? StructSpecialInferredTuple : StructSpecialNone;
26104 entry->data.structure.created_by_at_type = true;26092 entry->data.structure.created_by_at_type = true;
26105 entry->data.structure.decls_scope = create_decls_scope(ira->codegen, nullptr, nullptr, entry, entry, &entry->name);26093 entry->data.structure.decls_scope = create_decls_scope(
26094 ira->codegen, source_instr->source_node, source_instr->scope, entry, get_scope_import(source_instr->scope), &entry->name);
2610626095
26107 assert(fields_ptr->data.x_ptr.special == ConstPtrSpecialBaseArray);26096 assert(fields_ptr->data.x_ptr.special == ConstPtrSpecialBaseArray);
26108 assert(fields_ptr->data.x_ptr.data.base_array.elem_index == 0);26097 assert(fields_ptr->data.x_ptr.data.base_array.elem_index == 0);
...@@ -26226,13 +26215,89 @@ static ZigType *type_info_to_type(IrAnalyze *ira, IrInst *source_instr, ZigTypeI...@@ -26226,13 +26215,89 @@ static ZigType *type_info_to_type(IrAnalyze *ira, IrInst *source_instr, ZigTypeI
26226 return ira->codegen->invalid_inst_gen->value->type;26215 return ira->codegen->invalid_inst_gen->value->type;
26227 field->value = *field_int_value;26216 field->value = *field_int_value;
26228 }26217 }
26218 return entry;
26219 }
26220 case ZigTypeIdUnion: {
26221 assert(payload->special == ConstValSpecialStatic);
26222 assert(payload->type == ir_type_info_get_type(ira, "Union", nullptr));
2622926223
26224 ZigValue *layout_value = get_const_field(ira, source_instr->source_node, payload, "layout", 0);
26225 if (layout_value == nullptr)
26226 return ira->codegen->invalid_inst_gen->value->type;
26227 assert(layout_value->special == ConstValSpecialStatic);
26228 assert(layout_value->type == ir_type_info_get_type(ira, "ContainerLayout", nullptr));
26229 ContainerLayout layout = (ContainerLayout)bigint_as_u32(&layout_value->data.x_enum_tag);
26230
26231 ZigType *tag_type = get_const_field_meta_type_optional(ira, source_instr->source_node, payload, "tag_type", 1);
26232 if (tag_type != nullptr && type_is_invalid(tag_type)) {
26233 return ira->codegen->invalid_inst_gen->value->type;
26234 }
26235 if (tag_type != nullptr && tag_type->id != ZigTypeIdEnum) {
26236 ir_add_error(ira, source_instr, buf_sprintf(
26237 "expected enum type, found '%s'", type_id_name(tag_type->id)));
26238 return ira->codegen->invalid_inst_gen->value->type;
26239 }
26240
26241 ZigValue *fields_value = get_const_field(ira, source_instr->source_node, payload, "fields", 2);
26242 if (fields_value == nullptr)
26243 return ira->codegen->invalid_inst_gen->value->type;
26244
26245 assert(fields_value->special == ConstValSpecialStatic);
26246 assert(is_slice(fields_value->type));
26247 ZigValue *fields_ptr = fields_value->data.x_struct.fields[slice_ptr_index];
26248 ZigValue *fields_len_value = fields_value->data.x_struct.fields[slice_len_index];
26249 size_t fields_len = bigint_as_usize(&fields_len_value->data.x_bigint);
26250
26251 ZigValue *decls_value = get_const_field(ira, source_instr->source_node, payload, "decls", 3);
26252 if (decls_value == nullptr)
26253 return ira->codegen->invalid_inst_gen->value->type;
26254
26255 assert(decls_value->special == ConstValSpecialStatic);
26256 assert(is_slice(decls_value->type));
26257 ZigValue *decls_len_value = decls_value->data.x_struct.fields[slice_len_index];
26258 size_t decls_len = bigint_as_usize(&decls_len_value->data.x_bigint);
26259 if (decls_len != 0) {
26260 ir_add_error(ira, source_instr, buf_create_from_str("TypeInfo.Union.decls must be empty for @Type"));
26261 return ira->codegen->invalid_inst_gen->value->type;
26262 }
26263
26264 ZigType *entry = new_type_table_entry(ZigTypeIdUnion);
26265 buf_init_from_buf(&entry->name,
26266 get_anon_type_name(ira->codegen, ira->old_irb.exec, "union", source_instr->scope, source_instr->source_node, &entry->name));
26267 entry->data.unionation.decl_node = source_instr->source_node;
26268 entry->data.unionation.fields = heap::c_allocator.allocate<TypeUnionField>(fields_len);
26269 entry->data.unionation.fields_by_name.init(fields_len);
26270 entry->data.unionation.decls_scope = create_decls_scope(
26271 ira->codegen, source_instr->source_node, source_instr->scope, entry, get_scope_import(source_instr->scope), &entry->name);
26272 entry->data.unionation.tag_type = tag_type;
26273 entry->data.unionation.src_field_count = fields_len;
26274 entry->data.unionation.layout = layout;
26275
26276 assert(fields_ptr->data.x_ptr.special == ConstPtrSpecialBaseArray);
26277 assert(fields_ptr->data.x_ptr.data.base_array.elem_index == 0);
26278 ZigValue *fields_arr = fields_ptr->data.x_ptr.data.base_array.array_val;
26279 assert(fields_arr->special == ConstValSpecialStatic);
26280 assert(fields_arr->data.x_array.special == ConstArraySpecialNone);
26281 for (size_t i = 0; i < fields_len; i++) {
26282 ZigValue *field_value = &fields_arr->data.x_array.data.s_none.elements[i];
26283 assert(field_value->type == ir_type_info_get_type(ira, "UnionField", nullptr));
26284 TypeUnionField *field = &entry->data.unionation.fields[i];
26285 field->name = buf_alloc();
26286 if ((err = get_const_field_buf(ira, source_instr->source_node, field_value, "name", 0, field->name)))
26287 return ira->codegen->invalid_inst_gen->value->type;
26288 if (entry->data.unionation.fields_by_name.put_unique(field->name, field) != nullptr) {
26289 ir_add_error(ira, source_instr, buf_sprintf("duplicate union field '%s'", buf_ptr(field->name)));
26290 return ira->codegen->invalid_inst_gen->value->type;
26291 }
26292 field->decl_node = source_instr->source_node;
26293 ZigValue *type_value = get_const_field(ira, source_instr->source_node, field_value, "field_type", 1);
26294 if (type_value == nullptr)
26295 return ira->codegen->invalid_inst_gen->value->type;
26296 field->type_val = type_value;
26297 field->type_entry = type_value->data.x_type;
26298 }
26230 return entry;26299 return entry;
26231 }26300 }
26232 case ZigTypeIdUnion:
26233 ir_add_error(ira, source_instr, buf_sprintf(
26234 "TODO implement @Type for 'TypeInfo.%s': see https://github.com/ziglang/zig/issues/2907", type_id_name(tagTypeId)));
26235 return ira->codegen->invalid_inst_gen->value->type;
26236 case ZigTypeIdFn:26301 case ZigTypeIdFn:
26237 case ZigTypeIdBoundFn:26302 case ZigTypeIdBoundFn:
26238 ir_add_error(ira, source_instr, buf_sprintf(26303 ir_add_error(ira, source_instr, buf_sprintf(
test/compile_errors.zig+130-1
...@@ -10,6 +10,135 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -10,6 +10,135 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
10 "tmp.zig:2:37: error: expected type '[:1]const u8', found '*const [2:2]u8'",10 "tmp.zig:2:37: error: expected type '[:1]const u8', found '*const [2:2]u8'",
11 });11 });
1212
13 cases.add("@Type for union with opaque field",
14 \\const TypeInfo = @import("builtin").TypeInfo;
15 \\const Untagged = @Type(.{
16 \\ .Union = .{
17 \\ .layout = .Auto,
18 \\ .tag_type = null,
19 \\ .fields = &[_]TypeInfo.UnionField{
20 \\ .{ .name = "foo", .field_type = @Type(.Opaque) },
21 \\ },
22 \\ .decls = &[_]TypeInfo.Declaration{},
23 \\ },
24 \\});
25 \\export fn entry() void {
26 \\ _ = Untagged{};
27 \\}
28 , &[_][]const u8{
29 "tmp.zig:2:25: error: opaque types have unknown size and therefore cannot be directly embedded in unions",
30 "tmp.zig:13:17: note: referenced here",
31 });
32
33 cases.add("@Type for union with zero fields",
34 \\const TypeInfo = @import("builtin").TypeInfo;
35 \\const Untagged = @Type(.{
36 \\ .Union = .{
37 \\ .layout = .Auto,
38 \\ .tag_type = null,
39 \\ .fields = &[_]TypeInfo.UnionField{},
40 \\ .decls = &[_]TypeInfo.Declaration{},
41 \\ },
42 \\});
43 \\export fn entry() void {
44 \\ _ = Untagged{};
45 \\}
46 , &[_][]const u8{
47 "tmp.zig:2:25: error: unions must have 1 or more fields",
48 "tmp.zig:11:17: note: referenced here",
49 });
50
51 cases.add("@Type for exhaustive enum with zero fields",
52 \\const TypeInfo = @import("builtin").TypeInfo;
53 \\const Tag = @Type(.{
54 \\ .Enum = .{
55 \\ .layout = .Auto,
56 \\ .tag_type = u1,
57 \\ .fields = &[_]TypeInfo.EnumField{},
58 \\ .decls = &[_]TypeInfo.Declaration{},
59 \\ .is_exhaustive = true,
60 \\ },
61 \\});
62 \\export fn entry() void {
63 \\ _ = @intToEnum(Tag, 0);
64 \\}
65 , &[_][]const u8{
66 "tmp.zig:2:20: error: enums must have 1 or more fields",
67 "tmp.zig:12:9: note: referenced here",
68 });
69
70 cases.add("@Type for tagged union with extra union field",
71 \\const TypeInfo = @import("builtin").TypeInfo;
72 \\const Tag = @Type(.{
73 \\ .Enum = .{
74 \\ .layout = .Auto,
75 \\ .tag_type = u1,
76 \\ .fields = &[_]TypeInfo.EnumField{
77 \\ .{ .name = "signed", .value = 0 },
78 \\ .{ .name = "unsigned", .value = 1 },
79 \\ },
80 \\ .decls = &[_]TypeInfo.Declaration{},
81 \\ .is_exhaustive = true,
82 \\ },
83 \\});
84 \\const Tagged = @Type(.{
85 \\ .Union = .{
86 \\ .layout = .Auto,
87 \\ .tag_type = Tag,
88 \\ .fields = &[_]TypeInfo.UnionField{
89 \\ .{ .name = "signed", .field_type = i32 },
90 \\ .{ .name = "unsigned", .field_type = u32 },
91 \\ .{ .name = "arst", .field_type = f32 },
92 \\ },
93 \\ .decls = &[_]TypeInfo.Declaration{},
94 \\ },
95 \\});
96 \\export fn entry() void {
97 \\ var tagged = Tagged{ .signed = -1 };
98 \\ tagged = .{ .unsigned = 1 };
99 \\}
100 , &[_][]const u8{
101 "tmp.zig:14:23: error: enum field not found: 'arst'",
102 "tmp.zig:2:20: note: enum declared here",
103 "tmp.zig:27:24: note: referenced here",
104 });
105
106 cases.add("@Type for tagged union with extra enum field",
107 \\const TypeInfo = @import("builtin").TypeInfo;
108 \\const Tag = @Type(.{
109 \\ .Enum = .{
110 \\ .layout = .Auto,
111 \\ .tag_type = u2,
112 \\ .fields = &[_]TypeInfo.EnumField{
113 \\ .{ .name = "signed", .value = 0 },
114 \\ .{ .name = "unsigned", .value = 1 },
115 \\ .{ .name = "arst", .field_type = 2 },
116 \\ },
117 \\ .decls = &[_]TypeInfo.Declaration{},
118 \\ .is_exhaustive = true,
119 \\ },
120 \\});
121 \\const Tagged = @Type(.{
122 \\ .Union = .{
123 \\ .layout = .Auto,
124 \\ .tag_type = Tag,
125 \\ .fields = &[_]TypeInfo.UnionField{
126 \\ .{ .name = "signed", .field_type = i32 },
127 \\ .{ .name = "unsigned", .field_type = u32 },
128 \\ },
129 \\ .decls = &[_]TypeInfo.Declaration{},
130 \\ },
131 \\});
132 \\export fn entry() void {
133 \\ var tagged = Tagged{ .signed = -1 };
134 \\ tagged = .{ .unsigned = 1 };
135 \\}
136 , &[_][]const u8{
137 "tmp.zig:9:32: error: no member named 'field_type' in struct 'std.builtin.EnumField'",
138 "tmp.zig:18:21: note: referenced here",
139 "tmp.zig:27:18: note: referenced here",
140 });
141
13 cases.add("@Type with undefined",142 cases.add("@Type with undefined",
14 \\comptime {143 \\comptime {
15 \\ _ = @Type(.{ .Array = .{ .len = 0, .child = u8, .sentinel = undefined } });144 \\ _ = @Type(.{ .Array = .{ .len = 0, .child = u8, .sentinel = undefined } });
...@@ -7419,7 +7548,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -7419,7 +7548,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
7419 });7548 });
74207549
7421 cases.add( // fixed bug #20327550 cases.add( // fixed bug #2032
7422 "compile diagnostic string for top level decl type",7551 "compile diagnostic string for top level decl type",
7423 \\export fn entry() void {7552 \\export fn entry() void {
7424 \\ var foo: u32 = @This(){};7553 \\ var foo: u32 = @This(){};
7425 \\}7554 \\}
test/stage1/behavior/type.zig+61
...@@ -313,3 +313,64 @@ test "Type.Enum" {...@@ -313,3 +313,64 @@ test "Type.Enum" {
313 testing.expectEqual(@as(u32, 5), @enumToInt(Bar.b));313 testing.expectEqual(@as(u32, 5), @enumToInt(Bar.b));
314 testing.expectEqual(@as(u32, 6), @enumToInt(@intToEnum(Bar, 6)));314 testing.expectEqual(@as(u32, 6), @enumToInt(@intToEnum(Bar, 6)));
315}315}
316
317test "Type.Union" {
318 const Untagged = @Type(.{
319 .Union = .{
320 .layout = .Auto,
321 .tag_type = null,
322 .fields = &[_]TypeInfo.UnionField{
323 .{ .name = "int", .field_type = i32 },
324 .{ .name = "float", .field_type = f32 },
325 },
326 .decls = &[_]TypeInfo.Declaration{},
327 },
328 });
329 var untagged = Untagged{ .int = 1 };
330 untagged.float = 2.0;
331 untagged.int = 3;
332 testing.expectEqual(@as(i32, 3), untagged.int);
333
334 const PackedUntagged = @Type(.{
335 .Union = .{
336 .layout = .Packed,
337 .tag_type = null,
338 .fields = &[_]TypeInfo.UnionField{
339 .{ .name = "signed", .field_type = i32 },
340 .{ .name = "unsigned", .field_type = u32 },
341 },
342 .decls = &[_]TypeInfo.Declaration{},
343 },
344 });
345 var packed_untagged = PackedUntagged{ .signed = -1 };
346 testing.expectEqual(@as(i32, -1), packed_untagged.signed);
347 testing.expectEqual(~@as(u32, 0), packed_untagged.unsigned);
348
349 const Tag = @Type(.{
350 .Enum = .{
351 .layout = .Auto,
352 .tag_type = u1,
353 .fields = &[_]TypeInfo.EnumField{
354 .{ .name = "signed", .value = 0 },
355 .{ .name = "unsigned", .value = 1 },
356 },
357 .decls = &[_]TypeInfo.Declaration{},
358 .is_exhaustive = true,
359 },
360 });
361 const Tagged = @Type(.{
362 .Union = .{
363 .layout = .Auto,
364 .tag_type = Tag,
365 .fields = &[_]TypeInfo.UnionField{
366 .{ .name = "signed", .field_type = i32 },
367 .{ .name = "unsigned", .field_type = u32 },
368 },
369 .decls = &[_]TypeInfo.Declaration{},
370 },
371 });
372 var tagged = Tagged{ .signed = -1 };
373 testing.expectEqual(Tag.signed, tagged);
374 tagged = .{ .unsigned = 1 };
375 testing.expectEqual(Tag.unsigned, tagged);
376}
test/stage1/behavior/type_info.zig-4
...@@ -198,8 +198,6 @@ fn testUnion() void {...@@ -198,8 +198,6 @@ fn testUnion() void {
198 expect(typeinfo_info.Union.layout == .Auto);198 expect(typeinfo_info.Union.layout == .Auto);
199 expect(typeinfo_info.Union.tag_type.? == TypeId);199 expect(typeinfo_info.Union.tag_type.? == TypeId);
200 expect(typeinfo_info.Union.fields.len == 25);200 expect(typeinfo_info.Union.fields.len == 25);
201 expect(typeinfo_info.Union.fields[4].enum_field != null);
202 expect(typeinfo_info.Union.fields[4].enum_field.?.value == 4);
203 expect(typeinfo_info.Union.fields[4].field_type == @TypeOf(@typeInfo(u8).Int));201 expect(typeinfo_info.Union.fields[4].field_type == @TypeOf(@typeInfo(u8).Int));
204 expect(typeinfo_info.Union.decls.len == 21);202 expect(typeinfo_info.Union.decls.len == 21);
205203
...@@ -213,7 +211,6 @@ fn testUnion() void {...@@ -213,7 +211,6 @@ fn testUnion() void {
213 expect(notag_union_info.Union.tag_type == null);211 expect(notag_union_info.Union.tag_type == null);
214 expect(notag_union_info.Union.layout == .Auto);212 expect(notag_union_info.Union.layout == .Auto);
215 expect(notag_union_info.Union.fields.len == 2);213 expect(notag_union_info.Union.fields.len == 2);
216 expect(notag_union_info.Union.fields[0].enum_field == null);
217 expect(notag_union_info.Union.fields[1].field_type == u32);214 expect(notag_union_info.Union.fields[1].field_type == u32);
218215
219 const TestExternUnion = extern union {216 const TestExternUnion = extern union {
...@@ -223,7 +220,6 @@ fn testUnion() void {...@@ -223,7 +220,6 @@ fn testUnion() void {
223 const extern_union_info = @typeInfo(TestExternUnion);220 const extern_union_info = @typeInfo(TestExternUnion);
224 expect(extern_union_info.Union.layout == .Extern);221 expect(extern_union_info.Union.layout == .Extern);
225 expect(extern_union_info.Union.tag_type == null);222 expect(extern_union_info.Union.tag_type == null);
226 expect(extern_union_info.Union.fields[0].enum_field == null);
227 expect(extern_union_info.Union.fields[0].field_type == *c_void);223 expect(extern_union_info.Union.fields[0].field_type == *c_void);
228}224}
229225