From f6d83ba9185dd81106c731e12ab361685fa226c4 Mon Sep 17 00:00:00 2001 From: Vexu <15308111+Vexu@users.noreply.github.com> Date: Tue, 25 Jun 2019 01:12:28 +0300 Subject: [PATCH 01/80] fixed comment formatting in arrays and fn params --- std/zig/parser_test.zig | 38 ++++++++++++++++++++++++++++++++++++++ std/zig/render.zig | 8 ++++---- 2 files changed, 42 insertions(+), 4 deletions(-) diff --git a/std/zig/parser_test.zig b/std/zig/parser_test.zig index 281f09d57b2771b2357a94392cdc0d7f991a4f67..dc3e6190f5d55cd7e515a0912c3c1fa24be871c7 100644 --- a/std/zig/parser_test.zig +++ b/std/zig/parser_test.zig @@ -2234,6 +2234,44 @@ test "zig fmt: multiline string in array" { ); } +test "zig fmt: line comment in array" { + try testTransform( + \\test "a" { + \\ var arr = [_]u32{ + \\ 0 + \\ // 1, + \\ // 2, + \\ }; + \\} + \\ + , + \\test "a" { + \\ var arr = [_]u32{ + \\ 0, // 1, + \\ // 2, + \\ }; + \\} + \\ + ); +} + +test "zig fmt: comment after params" { + try testTransform( + \\fn a( + \\ b: u32 + \\ // c: u32, + \\ // d: u32, + \\) void {} + \\ + , + \\fn a( + \\ b: u32, // c: u32, + \\ // d: u32, + \\) void {} + \\ + ); +} + const std = @import("std"); const mem = std.mem; const warn = std.debug.warn; diff --git a/std/zig/render.zig b/std/zig/render.zig index ef5c8f2346214473ee07382f288eb5be4cb9c07d..b66cbeb86069ead4359caaccbc8dee168657ea39 100644 --- a/std/zig/render.zig +++ b/std/zig/render.zig @@ -658,7 +658,7 @@ fn renderExpression( try renderToken(tree, stream, lbrace, indent, start_col, Space.None); return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space); } - if (exprs.len == 1) { + if (exprs.len == 1 and tree.tokens.at(exprs.at(0).*.lastToken() + 1).id == .RBrace) { const expr = exprs.at(0).*; try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None); @@ -719,7 +719,7 @@ fn renderExpression( while (it.next()) |expr| : (i += 1) { counting_stream.bytes_written = 0; var dummy_col: usize = 0; - try renderExpression(allocator, &counting_stream.stream, tree, 0, &dummy_col, expr.*, Space.None); + try renderExpression(allocator, &counting_stream.stream, tree, indent, &dummy_col, expr.*, Space.None); const width = @intCast(usize, counting_stream.bytes_written); const col = i % row_size; column_widths[col] = std.math.max(column_widths[col], width); @@ -1139,8 +1139,8 @@ fn renderExpression( }); const src_params_trailing_comma = blk: { - const maybe_comma = tree.prevToken(rparen); - break :blk tree.tokens.at(maybe_comma).id == Token.Id.Comma; + const maybe_comma = tree.tokens.at(rparen - 1).id; + break :blk maybe_comma == .Comma or maybe_comma == .LineComment; }; if (!src_params_trailing_comma) { -- 2.54.0 From 7325f80bb2aa1759ea5477b8ea26266ecc607db7 Mon Sep 17 00:00:00 2001 From: Vexu <15308111+Vexu@users.noreply.github.com> Date: Wed, 26 Jun 2019 20:03:38 +0300 Subject: [PATCH 02/80] improved comment indentation in arrays --- std/zig/parser_test.zig | 32 ++++++++++++++++++++++++++++++++ std/zig/render.zig | 37 +++++++++++++++++++++++++++++++------ 2 files changed, 63 insertions(+), 6 deletions(-) diff --git a/std/zig/parser_test.zig b/std/zig/parser_test.zig index dc3e6190f5d55cd7e515a0912c3c1fa24be871c7..3150c5babd7ecce77c51b0b0851ca43cef43c28b 100644 --- a/std/zig/parser_test.zig +++ b/std/zig/parser_test.zig @@ -2272,6 +2272,38 @@ test "zig fmt: comment after params" { ); } +test "zig fmt: comment in array initializer/access" { + try testCanonical( + \\test "a" { + \\ var a = x{ //aa + \\ //bb + \\ }; + \\ var a = []x{ //aa + \\ //bb + \\ }; + \\ var b = [ //aa + \\ _ + \\ ]x{ //aa + \\ //bb + \\ 9, + \\ }; + \\ var c = b[ //aa + \\ 0 + \\ ]; + \\ var d = [_ + \\ //aa + \\ ]x{ //aa + \\ //bb + \\ 9, + \\ }; + \\ var e = d[0 + \\ //aa + \\ ]; + \\} + \\ + ); +} + const std = @import("std"); const mem = std.mem; const warn = std.debug.warn; diff --git a/std/zig/render.zig b/std/zig/render.zig index b66cbeb86069ead4359caaccbc8dee168657ea39..8270577d7aad39be32a70c4659ffe6aea3434036 100644 --- a/std/zig/render.zig +++ b/std/zig/render.zig @@ -427,9 +427,23 @@ fn renderExpression( }, ast.Node.PrefixOp.Op.ArrayType => |array_index| { - try renderToken(tree, stream, prefix_op_node.op_token, indent, start_col, Space.None); // [ - try renderExpression(allocator, stream, tree, indent, start_col, array_index, Space.None); - try renderToken(tree, stream, tree.nextToken(array_index.lastToken()), indent, start_col, Space.None); // ] + const lbracket = prefix_op_node.op_token; + const rbracket = tree.nextToken(array_index.lastToken()); + + try renderToken(tree, stream, lbracket, indent, start_col, Space.None); // [ + + const starts_with_comment = tree.tokens.at(lbracket + 1).id == .LineComment; + const ends_with_comment = tree.tokens.at(rbracket - 1).id == .LineComment; + const new_indent = if (ends_with_comment) indent + indent_delta else indent; + const new_space = if (ends_with_comment) Space.Newline else Space.None; + try renderExpression(allocator, stream, tree, new_indent, start_col, array_index, new_space); + if (starts_with_comment) { + try stream.writeByte('\n'); + } + if (ends_with_comment or starts_with_comment) { + try stream.writeByteNTimes(' ', indent); + } + try renderToken(tree, stream, rbracket, indent, start_col, Space.None); // ] }, ast.Node.PrefixOp.Op.BitNot, ast.Node.PrefixOp.Op.BoolNot, @@ -524,7 +538,18 @@ fn renderExpression( try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None); try renderToken(tree, stream, lbracket, indent, start_col, Space.None); // [ - try renderExpression(allocator, stream, tree, indent, start_col, index_expr, Space.None); + + const starts_with_comment = tree.tokens.at(lbracket + 1).id == .LineComment; + const ends_with_comment = tree.tokens.at(rbracket - 1).id == .LineComment; + const new_indent = if (ends_with_comment) indent + indent_delta else indent; + const new_space = if (ends_with_comment) Space.Newline else Space.None; + try renderExpression(allocator, stream, tree, new_indent, start_col, index_expr, new_space); + if (starts_with_comment) { + try stream.writeByte('\n'); + } + if (ends_with_comment or starts_with_comment) { + try stream.writeByteNTimes(' ', indent); + } return renderToken(tree, stream, rbracket, indent, start_col, space); // ] }, @@ -559,7 +584,7 @@ fn renderExpression( if (field_inits.len == 0) { try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None); - try renderToken(tree, stream, lbrace, indent, start_col, Space.None); + try renderToken(tree, stream, lbrace, indent + indent_delta, start_col, Space.None); return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space); } @@ -2019,7 +2044,7 @@ fn renderTokenOffset( const after_comment_token = tree.tokens.at(token_index + offset); const next_line_indent = switch (after_comment_token.id) { - Token.Id.RParen, Token.Id.RBrace, Token.Id.RBracket => indent - indent_delta, + Token.Id.RParen, Token.Id.RBrace, Token.Id.RBracket => if (indent > indent_delta) indent - indent_delta else 0, else => indent, }; try stream.writeByteNTimes(' ', next_line_indent); -- 2.54.0 From 0063953d1634ce770ce88519c66e3956832ceb7e Mon Sep 17 00:00:00 2001 From: Vexu <15308111+Vexu@users.noreply.github.com> Date: Thu, 27 Jun 2019 00:30:34 +0300 Subject: [PATCH 03/80] added better test cases --- std/zig/parser_test.zig | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/std/zig/parser_test.zig b/std/zig/parser_test.zig index 876d84e173e9c969fbb0ec06390fcb92744e9772..404c82e9b8f4b65ab95f2a3e1ee3af4ddbce8a11 100644 --- a/std/zig/parser_test.zig +++ b/std/zig/parser_test.zig @@ -2265,6 +2265,16 @@ test "zig fmt: line comment in array" { \\} \\ ); + try testCanonical( + \\test "a" { + \\ var arr = [_]u32{ + \\ 0, + \\ // 1, + \\ // 2, + \\ }; + \\} + \\ + ); } test "zig fmt: comment after params" { @@ -2282,6 +2292,14 @@ test "zig fmt: comment after params" { \\) void {} \\ ); + try testCanonical( + \\fn a( + \\ b: u32, + \\ // c: u32, + \\ // d: u32, + \\) void {} + \\ + ); } test "zig fmt: comment in array initializer/access" { -- 2.54.0 From 1b19c28c79ac20c4b8880742172834f881b47dea Mon Sep 17 00:00:00 2001 From: Jonathan Marler Date: Sat, 24 Aug 2019 01:54:44 -0600 Subject: [PATCH 04/80] Fix issue 3058: zig build segfault --- src/analyze.cpp | 9 +++++++-- test/stage1/behavior/union.zig | 10 ++++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/analyze.cpp b/src/analyze.cpp index 35c598ab97af30f7b7d3ff4a5de0add78390bba3..fa239808f5e23295208b15115ab08e02177280b0 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -7198,8 +7198,13 @@ static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveSta ZigType *most_aligned_union_member = union_type->data.unionation.most_aligned_union_member; ZigType *tag_type = union_type->data.unionation.tag_type; if (most_aligned_union_member == nullptr) { - union_type->llvm_type = get_llvm_type(g, tag_type); - union_type->llvm_di_type = get_llvm_di_type(g, tag_type); + if (tag_type == nullptr) { + union_type->llvm_type = g->builtin_types.entry_void->llvm_type; + union_type->llvm_di_type = g->builtin_types.entry_void->llvm_di_type; + } else { + union_type->llvm_type = get_llvm_type(g, tag_type); + union_type->llvm_di_type = get_llvm_di_type(g, tag_type); + } union_type->data.unionation.resolve_status = ResolveStatusLLVMFull; return; } diff --git a/test/stage1/behavior/union.zig b/test/stage1/behavior/union.zig index 7d6a8154ea3152f16a7ad26cd09f37c79fd27016..3df8aef3b022fe2edfde2d42ab76f665d16345b8 100644 --- a/test/stage1/behavior/union.zig +++ b/test/stage1/behavior/union.zig @@ -457,3 +457,13 @@ test "@unionInit can modify a pointer value" { value_ptr.* = @unionInit(UnionInitEnum, "Byte", 2); expect(value.Byte == 2); } + +test "union no tag with struct member" { + const Struct = struct { }; + const Union = union { + s : Struct, + pub fn foo(self: *@This()) void { } + }; + var u = Union { .s = Struct {} }; + u.foo(); +} -- 2.54.0 From 32f4606cece09b6bcf4f553c06c3aaab34f784c6 Mon Sep 17 00:00:00 2001 From: Robin Voetter Date: Wed, 28 Aug 2019 16:35:23 +0200 Subject: [PATCH 05/80] add arm32 linux bits definitions --- std/os/bits/linux.zig | 1 + std/os/bits/linux/arm-eabi.zig | 510 +++++++++++++++++++++++++++++++++ 2 files changed, 511 insertions(+) create mode 100644 std/os/bits/linux/arm-eabi.zig diff --git a/std/os/bits/linux.zig b/std/os/bits/linux.zig index c7d8cc2ad2a546b0a938d222820624b016f47425..0617378da9f50d1a1751a5b3de3b8c247b3666e2 100644 --- a/std/os/bits/linux.zig +++ b/std/os/bits/linux.zig @@ -7,6 +7,7 @@ pub usingnamespace @import("linux/errno.zig"); pub usingnamespace switch (builtin.arch) { .x86_64 => @import("linux/x86_64.zig"), .aarch64 => @import("linux/arm64.zig"), + .arm => @import("linux/arm-eabi.zig"), else => struct {}, }; diff --git a/std/os/bits/linux/arm-eabi.zig b/std/os/bits/linux/arm-eabi.zig new file mode 100644 index 0000000000000000000000000000000000000000..ea4c452eb66d54c7622f40c8aba08eec56114161 --- /dev/null +++ b/std/os/bits/linux/arm-eabi.zig @@ -0,0 +1,510 @@ +// arm-eabi-specific declarations that are intended to be imported into the POSIX namespace. + +const std = @import("../../std.zig"); +const linux = std.os.linux; +const socklen_t = linux.socklen_t; +const iovec = linux.iovec; +const iovec_const = linux.iovec_const; + +pub const SYS_restart_syscall = 0; +pub const SYS_exit = 1; +pub const SYS_fork = 2; +pub const SYS_read = 3; +pub const SYS_write = 4; +pub const SYS_open = 5; +pub const SYS_close = 6; +pub const SYS_creat = 8; +pub const SYS_link = 9; +pub const SYS_unlink = 10; +pub const SYS_execve = 11; +pub const SYS_chdir = 12; +pub const SYS_mknod = 14; +pub const SYS_chmod = 15; +pub const SYS_lchown = 16; +pub const SYS_lseek = 19; +pub const SYS_getpid = 20; +pub const SYS_mount = 21; +pub const SYS_setuid = 23; +pub const SYS_getuid = 24; +pub const SYS_ptrace = 26; +pub const SYS_pause = 29; +pub const SYS_access = 33; +pub const SYS_nice = 34; +pub const SYS_sync = 36; +pub const SYS_kill = 37; +pub const SYS_rename = 38; +pub const SYS_mkdir = 39; +pub const SYS_rmdir = 40; +pub const SYS_dup = 41; +pub const SYS_pipe = 42; +pub const SYS_times = 43; +pub const SYS_brk = 45; +pub const SYS_setgid = 46; +pub const SYS_getgid = 47; +pub const SYS_geteuid = 49; +pub const SYS_getegid = 50; +pub const SYS_acct = 51; +pub const SYS_umount2 = 52; +pub const SYS_ioctl = 54; +pub const SYS_fcntl = 55; +pub const SYS_setpgid = 57; +pub const SYS_umask = 60; +pub const SYS_chroot = 61; +pub const SYS_ustat = 62; +pub const SYS_dup2 = 63; +pub const SYS_getppid = 64; +pub const SYS_getpgrp = 65; +pub const SYS_setsid = 66; +pub const SYS_sigaction = 67; +pub const SYS_setreuid = 70; +pub const SYS_setregid = 71; +pub const SYS_sigsuspend = 72; +pub const SYS_sigpending = 73; +pub const SYS_sethostname = 74; +pub const SYS_setrlimit = 75; +pub const SYS_getrusage = 77; +pub const SYS_gettimeofday = 78; +pub const SYS_settimeofday = 79; +pub const SYS_getgroups = 80; +pub const SYS_setgroups = 81; +pub const SYS_symlink = 83; +pub const SYS_readlink = 85; +pub const SYS_uselib = 86; +pub const SYS_swapon = 87; +pub const SYS_reboot = 88; +pub const SYS_munmap = 91; +pub const SYS_truncate = 92; +pub const SYS_ftruncate = 93; +pub const SYS_fchmod = 94; +pub const SYS_fchown = 95; +pub const SYS_getpriority = 96; +pub const SYS_setpriority = 97; +pub const SYS_statfs = 99; +pub const SYS_fstatfs = 100; +pub const SYS_syslog = 103; +pub const SYS_setitimer = 104; +pub const SYS_getitimer = 105; +pub const SYS_stat = 106; +pub const SYS_lstat = 107; +pub const SYS_fstat = 108; +pub const SYS_vhangup = 111; +pub const SYS_wait4 = 114; +pub const SYS_swapoff = 115; +pub const SYS_sysinfo = 116; +pub const SYS_fsync = 118; +pub const SYS_sigreturn = 119; +pub const SYS_clone = 120; +pub const SYS_setdomainname = 121; +pub const SYS_uname = 122; +pub const SYS_adjtimex = 124; +pub const SYS_mprotect = 125; +pub const SYS_sigprocmask = 126; +pub const SYS_init_module = 128; +pub const SYS_delete_module = 129; +pub const SYS_quotactl = 131; +pub const SYS_getpgid = 132; +pub const SYS_fchdir = 133; +pub const SYS_bdflush = 134; +pub const SYS_sysfs = 135; +pub const SYS_personality = 136; +pub const SYS_setfsuid = 138; +pub const SYS_setfsgid = 139; +pub const SYS__llseek = 140; +pub const SYS_getdents = 141; +pub const SYS__newselect = 142; +pub const SYS_flock = 143; +pub const SYS_msync = 144; +pub const SYS_readv = 145; +pub const SYS_writev = 146; +pub const SYS_getsid = 147; +pub const SYS_fdatasync = 148; +pub const SYS__sysctl = 149; +pub const SYS_mlock = 150; +pub const SYS_munlock = 151; +pub const SYS_mlockall = 152; +pub const SYS_munlockall = 153; +pub const SYS_sched_setparam = 154; +pub const SYS_sched_getparam = 155; +pub const SYS_sched_setscheduler = 156; +pub const SYS_sched_getscheduler = 157; +pub const SYS_sched_yield = 158; +pub const SYS_sched_get_priority_max = 159; +pub const SYS_sched_get_priority_min = 160; +pub const SYS_sched_rr_get_interval = 161; +pub const SYS_nanosleep = 162; +pub const SYS_mremap = 163; +pub const SYS_setresuid = 164; +pub const SYS_getresuid = 165; +pub const SYS_poll = 168; +pub const SYS_nfsservctl = 169; +pub const SYS_setresgid = 170; +pub const SYS_getresgid = 171; +pub const SYS_prctl = 172; +pub const SYS_rt_sigreturn = 173; +pub const SYS_rt_sigaction = 174; +pub const SYS_rt_sigprocmask = 175; +pub const SYS_rt_sigpending = 176; +pub const SYS_rt_sigtimedwait = 177; +pub const SYS_rt_sigqueueinfo = 178; +pub const SYS_rt_sigsuspend = 179; +pub const SYS_pread64 = 180; +pub const SYS_pwrite64 = 181; +pub const SYS_chown = 182; +pub const SYS_getcwd = 183; +pub const SYS_capget = 184; +pub const SYS_capset = 185; +pub const SYS_sigaltstack = 186; +pub const SYS_sendfile = 187; +pub const SYS_vfork = 190; +pub const SYS_ugetrlimit = 191; +pub const SYS_mmap2 = 192; +pub const SYS_truncate64 = 193; +pub const SYS_ftruncate64 = 194; +pub const SYS_stat64 = 195; +pub const SYS_lstat64 = 196; +pub const SYS_fstat64 = 197; +pub const SYS_lchown32 = 198; +pub const SYS_getuid32 = 199; +pub const SYS_getgid32 = 200; +pub const SYS_geteuid32 = 201; +pub const SYS_getegid32 = 202; +pub const SYS_setreuid32 = 203; +pub const SYS_setregid32 = 204; +pub const SYS_getgroups32 = 205; +pub const SYS_setgroups32 = 206; +pub const SYS_fchown32 = 207; +pub const SYS_setresuid32 = 208; +pub const SYS_getresuid32 = 209; +pub const SYS_setresgid32 = 210; +pub const SYS_getresgid32 = 211; +pub const SYS_chown32 = 212; +pub const SYS_setuid32 = 213; +pub const SYS_setgid32 = 214; +pub const SYS_setfsuid32 = 215; +pub const SYS_setfsgid32 = 216; +pub const SYS_getdents64 = 217; +pub const SYS_pivot_root = 218; +pub const SYS_mincore = 219; +pub const SYS_madvise = 220; +pub const SYS_fcntl64 = 221; +pub const SYS_gettid = 224; +pub const SYS_readahead = 225; +pub const SYS_setxattr = 226; +pub const SYS_lsetxattr = 227; +pub const SYS_fsetxattr = 228; +pub const SYS_getxattr = 229; +pub const SYS_lgetxattr = 230; +pub const SYS_fgetxattr = 231; +pub const SYS_listxattr = 232; +pub const SYS_llistxattr = 233; +pub const SYS_flistxattr = 234; +pub const SYS_removexattr = 235; +pub const SYS_lremovexattr = 236; +pub const SYS_fremovexattr = 237; +pub const SYS_tkill = 238; +pub const SYS_sendfile64 = 239; +pub const SYS_futex = 240; +pub const SYS_sched_setaffinity = 241; +pub const SYS_sched_getaffinity = 242; +pub const SYS_io_setup = 243; +pub const SYS_io_destroy = 244; +pub const SYS_io_getevents = 245; +pub const SYS_io_submit = 246; +pub const SYS_io_cancel = 247; +pub const SYS_exit_group = 248; +pub const SYS_lookup_dcookie = 249; +pub const SYS_epoll_create = 250; +pub const SYS_epoll_ctl = 251; +pub const SYS_epoll_wait = 252; +pub const SYS_remap_file_pages = 253; +pub const SYS_set_tid_address = 256; +pub const SYS_timer_create = 257; +pub const SYS_timer_settime = 258; +pub const SYS_timer_gettime = 259; +pub const SYS_timer_getoverrun = 260; +pub const SYS_timer_delete = 261; +pub const SYS_clock_settime = 262; +pub const SYS_clock_gettime = 263; +pub const SYS_clock_getres = 264; +pub const SYS_clock_nanosleep = 265; +pub const SYS_statfs64 = 266; +pub const SYS_fstatfs64 = 267; +pub const SYS_tgkill = 268; +pub const SYS_utimes = 269; +pub const SYS_arm_fadvise64_64 = 270; +pub const SYS_pciconfig_iobase = 271; +pub const SYS_pciconfig_read = 272; +pub const SYS_pciconfig_write = 273; +pub const SYS_mq_open = 274; +pub const SYS_mq_unlink = 275; +pub const SYS_mq_timedsend = 276; +pub const SYS_mq_timedreceive = 277; +pub const SYS_mq_notify = 278; +pub const SYS_mq_getsetattr = 279; +pub const SYS_waitid = 280; +pub const SYS_socket = 281; +pub const SYS_bind = 282; +pub const SYS_connect = 283; +pub const SYS_listen = 284; +pub const SYS_accept = 285; +pub const SYS_getsockname = 286; +pub const SYS_getpeername = 287; +pub const SYS_socketpair = 288; +pub const SYS_send = 289; +pub const SYS_sendto = 290; +pub const SYS_recv = 291; +pub const SYS_recvfrom = 292; +pub const SYS_shutdown = 293; +pub const SYS_setsockopt = 294; +pub const SYS_getsockopt = 295; +pub const SYS_sendmsg = 296; +pub const SYS_recvmsg = 297; +pub const SYS_semop = 298; +pub const SYS_semget = 299; +pub const SYS_semctl = 300; +pub const SYS_msgsnd = 301; +pub const SYS_msgrcv = 302; +pub const SYS_msgget = 303; +pub const SYS_msgctl = 304; +pub const SYS_shmat = 305; +pub const SYS_shmdt = 306; +pub const SYS_shmget = 307; +pub const SYS_shmctl = 308; +pub const SYS_add_key = 309; +pub const SYS_request_key = 310; +pub const SYS_keyctl = 311; +pub const SYS_semtimedop = 312; +pub const SYS_vserver = 313; +pub const SYS_ioprio_set = 314; +pub const SYS_ioprio_get = 315; +pub const SYS_inotify_init = 316; +pub const SYS_inotify_add_watch = 317; +pub const SYS_inotify_rm_watch = 318; +pub const SYS_mbind = 319; +pub const SYS_get_mempolicy = 320; +pub const SYS_set_mempolicy = 321; +pub const SYS_openat = 322; +pub const SYS_mkdirat = 323; +pub const SYS_mknodat = 324; +pub const SYS_fchownat = 325; +pub const SYS_futimesat = 326; +pub const SYS_fstatat64 = 327; +pub const SYS_unlinkat = 328; +pub const SYS_renameat = 329; +pub const SYS_linkat = 330; +pub const SYS_symlinkat = 331; +pub const SYS_readlinkat = 332; +pub const SYS_fchmodat = 333; +pub const SYS_faccessat = 334; +pub const SYS_pselect6 = 335; +pub const SYS_ppoll = 336; +pub const SYS_unshare = 337; +pub const SYS_set_robust_list = 338; +pub const SYS_get_robust_list = 339; +pub const SYS_splice = 340; +pub const SYS_arm_sync_file_range = 341; +pub const SYS_tee = 342; +pub const SYS_vmsplice = 343; +pub const SYS_move_pages = 344; +pub const SYS_getcpu = 345; +pub const SYS_epoll_pwait = 346; +pub const SYS_kexec_load = 347; +pub const SYS_utimensat = 348; +pub const SYS_signalfd = 349; +pub const SYS_timerfd_create = 350; +pub const SYS_eventfd = 351; +pub const SYS_fallocate = 352; +pub const SYS_timerfd_settime = 353; +pub const SYS_timerfd_gettime = 354; +pub const SYS_signalfd4 = 355; +pub const SYS_eventfd2 = 356; +pub const SYS_epoll_create1 = 357; +pub const SYS_dup3 = 358; +pub const SYS_pipe2 = 359; +pub const SYS_inotify_init1 = 360; +pub const SYS_preadv = 361; +pub const SYS_pwritev = 362; +pub const SYS_rt_tgsigqueueinfo = 363; +pub const SYS_perf_event_open = 364; +pub const SYS_recvmmsg = 365; +pub const SYS_accept4 = 366; +pub const SYS_fanotify_init = 367; +pub const SYS_fanotify_mark = 368; +pub const SYS_prlimit64 = 369; +pub const SYS_name_to_handle_at = 370; +pub const SYS_open_by_handle_at = 371; +pub const SYS_clock_adjtime = 372; +pub const SYS_syncfs = 373; +pub const SYS_sendmmsg = 374; +pub const SYS_setns = 375; +pub const SYS_process_vm_readv = 376; +pub const SYS_process_vm_writev = 377; +pub const SYS_kcmp = 378; +pub const SYS_finit_module = 379; +pub const SYS_sched_setattr = 380; +pub const SYS_sched_getattr = 381; +pub const SYS_renameat2 = 382; +pub const SYS_seccomp = 383; +pub const SYS_getrandom = 384; +pub const SYS_memfd_create = 385; +pub const SYS_bpf = 386; +pub const SYS_execveat = 387; +pub const SYS_userfaultfd = 388; +pub const SYS_membarrier = 389; +pub const SYS_mlock2 = 390; +pub const SYS_copy_file_range = 391; +pub const SYS_preadv2 = 392; +pub const SYS_pwritev2 = 393; +pub const SYS_pkey_mprotect = 394; +pub const SYS_pkey_alloc = 395; +pub const SYS_pkey_free = 396; +pub const SYS_statx = 397; +pub const SYS_rseq = 398; +pub const SYS_io_pgetevents = 399; + +pub const O_CREAT = 0o100; +pub const O_EXCL = 0o200; +pub const O_NOCTTY = 0o400; +pub const O_TRUNC = 0o1000; +pub const O_APPEND = 0o2000; +pub const O_NONBLOCK = 0o4000; +pub const O_DSYNC = 0o10000; +pub const O_SYNC = 0o4010000; +pub const O_RSYNC = 0o4010000; +pub const O_DIRECTORY = 0o40000; +pub const O_NOFOLLOW = 0o100000; +pub const O_CLOEXEC = 0o2000000; + +pub const O_ASYNC = 0o20000; +pub const O_DIRECT = 0o200000; +pub const O_LARGEFILE = 0o400000; +pub const O_NOATIME = 0o1000000; +pub const O_PATH = 0o10000000; +pub const O_TMPFILE = 0o20040000; +pub const O_NDELAY = O_NONBLOCK; + +pub const F_DUPFD = 0; +pub const F_GETFD = 1; +pub const F_SETFD = 2; +pub const F_GETFL = 3; +pub const F_SETFL = 4; + +pub const F_SETOWN = 8; +pub const F_GETOWN = 9; +pub const F_SETSIG = 10; +pub const F_GETSIG = 11; + +pub const F_GETLK = 12; +pub const F_SETLK = 13; +pub const F_SETLKW = 14; + +pub const F_SETOWN_EX = 15; +pub const F_GETOWN_EX = 16; + +pub const F_GETOWNER_UIDS = 17; + +/// stack-like segment +pub const MAP_GROWSDOWN = 0x0100; + +/// ETXTBSY +pub const MAP_DENYWRITE = 0x0800; + +/// mark it as an executable +pub const MAP_EXECUTABLE = 0x1000; + +/// pages are locked +pub const MAP_LOCKED = 0x2000; + +/// don't check for reservations +pub const MAP_NORESERVE = 0x4000; + +/// populate (prefault) pagetables +pub const MAP_POPULATE = 0x8000; + +/// do not block on IO +pub const MAP_NONBLOCK = 0x10000; + +/// give out an address that is best suited for process/thread stacks +pub const MAP_STACK = 0x20000; + +/// create a huge page mapping +pub const MAP_HUGETLB = 0x40000; + +/// perform synchronous page faults for the mapping +pub const MAP_SYNC = 0x80000; + +pub const VDSO_USEFUL = true; +pub const VDSO_CGT_SYM = "__vdso_clock_gettime"; +pub const VDSO_CGT_VER = "LINUX_2.6"; + +pub const msghdr = extern struct { + msg_name: ?*sockaddr, + msg_namelen: socklen_t, + msg_iov: [*]iovec, + msg_iovlen: i32, + msg_control: ?*c_void, + msg_controllen: socklen_t, + msg_flags: i32, +}; + +pub const msghdr_const = extern struct { + msg_name: ?*const sockaddr, + msg_namelen: socklen_t, + msg_iov: [*]iovec_const, + msg_iovlen: i32, + msg_control: ?*c_void, + msg_controllen: socklen_t, + msg_flags: i32, +}; + +/// Renamed to Stat to not conflict with the stat function. +/// atime, mtime, and ctime have functions to return `timespec`, +/// because although this is a POSIX API, the layout and names of +/// the structs are inconsistent across operating systems, and +/// in C, macros are used to hide the differences. Here we use +/// methods to accomplish this. +pub const Stat = extern struct { + dev: u64, + __dev_patting: u32, + __ino_truncated: u32, + mode: u32, + nlink: u32, + uid: u32, + gid: u32, + rdev: u64, + __rdev_padding: u32, + size: i64, + blksize: i32, + blocks: i64, + atim: timespec, + mtim: timespec, + ctim: timespec, + ino: u64, + + pub fn atime(self: Stat) timespec { + return self.atim; + } + + pub fn mtime(self: Stat) timespec { + return self.mtim; + } + + pub fn ctime(self: Stat) timespec { + return self.ctim; + } +}; + +pub const timespec = extern struct { + tv_sec: i32, + tv_nsec: i32, +}; + +pub const timeval = extern struct { + tv_sec: i32, + tv_usec: i32, +}; + +pub const timezone = extern struct { + tz_minuteswest: i32, + tz_dsttime: i32, +}; -- 2.54.0 From 50c37c75d1208bb8a0bf5b2792e4a1d69d6f7110 Mon Sep 17 00:00:00 2001 From: Robin Voetter Date: Wed, 28 Aug 2019 17:41:49 +0200 Subject: [PATCH 06/80] add arm32 syscall conventions --- std/os/linux.zig | 1 + std/os/linux/arm-eabi.zig | 80 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+) create mode 100644 std/os/linux/arm-eabi.zig diff --git a/std/os/linux.zig b/std/os/linux.zig index 053f30d265bcd8f7f6f2d67e56639c8efb669b9e..ba679387dd28c52e61aa7e4fb4c756e24ff2ae7a 100644 --- a/std/os/linux.zig +++ b/std/os/linux.zig @@ -17,6 +17,7 @@ pub const is_the_target = builtin.os == .linux; pub usingnamespace switch (builtin.arch) { .x86_64 => @import("linux/x86_64.zig"), .aarch64 => @import("linux/arm64.zig"), + .arm => @import("linux/arm-eabi.zig"), else => struct {}, }; pub usingnamespace @import("bits.zig"); diff --git a/std/os/linux/arm-eabi.zig b/std/os/linux/arm-eabi.zig new file mode 100644 index 0000000000000000000000000000000000000000..3b8eb055d5f6f16e401ed39ed5ae918b06f94773 --- /dev/null +++ b/std/os/linux/arm-eabi.zig @@ -0,0 +1,80 @@ +pub fn syscall0(number: usize) usize { + return asm volatile ("svc #0" + : [ret] "={r0}" (-> usize) + : [number] "{r7}" (number) + ); +} + +pub fn syscall1(number: usize, arg1: usize) usize { + return asm volatile ("svc #0" + : [ret] "={r0}" (-> usize) + : [number] "{r7}" (number), + [arg1] "{r0}" (arg1) + ); +} + +pub fn syscall2(number: usize, arg1: usize, arg2: usize) usize { + return asm volatile ("svc #0" + : [ret] "={r0}" (-> usize) + : [number] "{r7}" (number), + [arg1] "{r0}" (arg1), + [arg2] "{r1}" (arg2) + ); +} + +pub fn syscall3(number: usize, arg1: usize, arg2: usize, arg3: usize) usize { + return asm volatile ("svc #0" + : [ret] "={r0}" (-> usize) + : [number] "{r7}" (number), + [arg1] "{r0}" (arg1), + [arg2] "{r1}" (arg2), + [arg3] "{r2}" (arg3) + ); +} + +pub fn syscall4(number: usize, arg1: usize, arg2: usize, arg3: usize, arg4: usize) usize { + return asm volatile ("svc #0" + : [ret] "={r0}" (-> usize) + : [number] "{r7}" (number), + [arg1] "{r0}" (arg1), + [arg2] "{r1}" (arg2), + [arg3] "{r2}" (arg3), + [arg4] "{r3}" (arg4) + ); +} + +pub fn syscall5(number: usize, arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) usize { + return asm volatile ("svc #0" + : [ret] "={r0}" (-> usize) + : [number] "{r7}" (number), + [arg1] "{r0}" (arg1), + [arg2] "{r1}" (arg2), + [arg3] "{r2}" (arg3), + [arg4] "{r3}" (arg4), + [arg5] "{r4}" (arg5) + ); +} + +pub fn syscall6( + number: usize, + arg1: usize, + arg2: usize, + arg3: usize, + arg4: usize, + arg5: usize, + arg6: usize, +) usize { + return asm volatile ("svc #0" + : [ret] "={r0}" (-> usize) + : [number] "{r7}" (number), + [arg1] "{r0}" (arg1), + [arg2] "{r1}" (arg2), + [arg3] "{r2}" (arg3), + [arg4] "{r3}" (arg4), + [arg5] "{r4}" (arg5), + [arg6] "{r5}" (arg6) + ); +} + +/// This matches the libc clone function. +pub extern fn clone(func: extern fn (arg: usize) u8, stack: usize, flags: u32, arg: usize, ptid: *i32, tls: usize, ctid: *i32) usize; -- 2.54.0 From 223b773e038b7af6ee1dec1c69836c135049d1ba Mon Sep 17 00:00:00 2001 From: Robin Voetter Date: Thu, 29 Aug 2019 00:54:57 +0200 Subject: [PATCH 07/80] Add more syscall constants --- std/os/bits/linux/arm-eabi.zig | 35 ++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/std/os/bits/linux/arm-eabi.zig b/std/os/bits/linux/arm-eabi.zig index ea4c452eb66d54c7622f40c8aba08eec56114161..956e40a2ce0e795cd3e0971f7593610c1f83050f 100644 --- a/std/os/bits/linux/arm-eabi.zig +++ b/std/os/bits/linux/arm-eabi.zig @@ -231,6 +231,7 @@ pub const SYS_statfs64 = 266; pub const SYS_fstatfs64 = 267; pub const SYS_tgkill = 268; pub const SYS_utimes = 269; +pub const SYS_fadvise64_64 = 270; pub const SYS_arm_fadvise64_64 = 270; pub const SYS_pciconfig_iobase = 271; pub const SYS_pciconfig_read = 272; @@ -302,6 +303,7 @@ pub const SYS_unshare = 337; pub const SYS_set_robust_list = 338; pub const SYS_get_robust_list = 339; pub const SYS_splice = 340; +pub const SYS_sync_file_range2 = 341; pub const SYS_arm_sync_file_range = 341; pub const SYS_tee = 342; pub const SYS_vmsplice = 343; @@ -361,6 +363,39 @@ pub const SYS_pkey_free = 396; pub const SYS_statx = 397; pub const SYS_rseq = 398; pub const SYS_io_pgetevents = 399; +pub const SYS_migrate_pages = 400; +pub const SYS_kexec_file_load = 401; +pub const SYS_clock_gettime64 = 403; +pub const SYS_clock_settime64 = 404; +pub const SYS_clock_adjtime64 = 405; +pub const SYS_clock_getres_time64 = 406; +pub const SYS_clock_nanosleep_time64 = 407; +pub const SYS_timer_gettime64 = 408; +pub const SYS_timer_settime64 = 409; +pub const SYS_timerfd_gettime64 = 410; +pub const SYS_timerfd_settime64 = 411; +pub const SYS_utimensat_time64 = 412; +pub const SYS_pselect6_time64 = 413; +pub const SYS_ppoll_time64 = 414; +pub const SYS_io_pgetevents_time64 = 416; +pub const SYS_recvmmsg_time64 = 417; +pub const SYS_mq_timedsend_time64 = 418; +pub const SYS_mq_timedreceive_time64 = 419; +pub const SYS_semtimedop_time64 = 420; +pub const SYS_rt_sigtimedwait_time64 = 421; +pub const SYS_futex_time64 = 422; +pub const SYS_sched_rr_get_interval_time64 = 423; +pub const SYS_pidfd_send_signal = 424; +pub const SYS_io_uring_setup = 425; +pub const SYS_io_uring_enter = 426; +pub const SYS_io_uring_register = 427; + +pub const SYS_breakpoint = 0x0f0001; +pub const SYS_cacheflush = 0x0f0002; +pub const SYS_usr26 = 0x0f0003; +pub const SYS_usr32 = 0x0f0004; +pub const SYS_set_tls = 0x0f0005; +pub const SYS_get_tls = 0x0f0006; pub const O_CREAT = 0o100; pub const O_EXCL = 0o200; -- 2.54.0 From 57de61084e1a805838243e5428e774a591197454 Mon Sep 17 00:00:00 2001 From: Robin Voetter Date: Thu, 29 Aug 2019 00:55:22 +0200 Subject: [PATCH 08/80] Make mmap use SYS_mmap2 if it exists --- std/os/bits/linux/arm-eabi.zig | 2 ++ std/os/linux.zig | 6 +++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/std/os/bits/linux/arm-eabi.zig b/std/os/bits/linux/arm-eabi.zig index 956e40a2ce0e795cd3e0971f7593610c1f83050f..1b45588459a218362a0508a81092416bd742741b 100644 --- a/std/os/bits/linux/arm-eabi.zig +++ b/std/os/bits/linux/arm-eabi.zig @@ -397,6 +397,8 @@ pub const SYS_usr32 = 0x0f0004; pub const SYS_set_tls = 0x0f0005; pub const SYS_get_tls = 0x0f0006; +pub const MMAP2_UNIT = 4096; + pub const O_CREAT = 0o100; pub const O_EXCL = 0o200; pub const O_NOCTTY = 0o400; diff --git a/std/os/linux.zig b/std/os/linux.zig index ba679387dd28c52e61aa7e4fb4c756e24ff2ae7a..7d019001ef3561f234b23252656e2179de022c52 100644 --- a/std/os/linux.zig +++ b/std/os/linux.zig @@ -190,7 +190,11 @@ pub fn umount2(special: [*]const u8, flags: u32) usize { } pub fn mmap(address: ?[*]u8, length: usize, prot: usize, flags: u32, fd: i32, offset: isize) usize { - return syscall6(SYS_mmap, @ptrToInt(address), length, prot, flags, @bitCast(usize, isize(fd)), @bitCast(usize, offset)); + if (@hasDecl(@This(), "SYS_mmap2")) { + return syscall6(SYS_mmap2, @ptrToInt(address), length, prot, flags, @bitCast(usize, isize(fd)), @bitCast(usize, @divTrunc(offset, MMAP2_UNIT))); + } else { + return syscall6(SYS_mmap, @ptrToInt(address), length, prot, flags, @bitCast(usize, isize(fd)), @bitCast(usize, offset)); + } } pub fn mprotect(address: [*]const u8, length: usize, protection: usize) usize { -- 2.54.0 From b3ac323a448e1e8a816eab64777b855396afe6c8 Mon Sep 17 00:00:00 2001 From: Robin Voetter Date: Thu, 29 Aug 2019 01:14:43 +0200 Subject: [PATCH 09/80] TLS initialization, clone definition and _start functionality --- std/os/linux/tls.zig | 3 +++ std/special/c.zig | 29 +++++++++++++++++++++++++++++ std/special/start.zig | 2 +- 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/std/os/linux/tls.zig b/std/os/linux/tls.zig index a10d68663b9dc99365189d5e2d3e4648106b9bbd..63c44d6982206dad6f14249b864d0dc5c6c8e380 100644 --- a/std/os/linux/tls.zig +++ b/std/os/linux/tls.zig @@ -118,6 +118,9 @@ pub fn setThreadPointer(addr: usize) void { : [addr] "r" (addr) ); }, + .arm => |arm| { + _ = std.os.linux.syscall1(std.os.linux.SYS_set_tls, addr); + }, else => @compileError("Unsupported architecture"), } } diff --git a/std/special/c.zig b/std/special/c.zig index 7300b8bf74c34eeef568a111e0e1d72878ed093b..5ac74574292d1669ae6db0c9d10dc772fcdccde5 100644 --- a/std/special/c.zig +++ b/std/special/c.zig @@ -238,6 +238,35 @@ nakedcc fn clone() void { \\ mov x8,#93 // SYS_exit \\ svc #0 ); + } else if (builtin.arch == builtin.Arch.arm) { + asm volatile ( + \\ stmfd sp!,{r4,r5,r6,r7} + \\ mov r7,#120 + \\ mov r6,r3 + \\ mov r5,r0 + \\ mov r0,r2 + \\ and r1,r1,#-16 + \\ ldr r2,[sp,#16] + \\ ldr r3,[sp,#20] + \\ ldr r4,[sp,#24] + \\ svc 0 + \\ tst r0,r0 + \\ beq 1f + \\ ldmfd sp!,{r4,r5,r6,r7} + \\ bx lr + \\ + \\1: mov r0,r6 + \\ tst r5,#1 + \\ bne 1f + \\ mov lr,pc + \\ mov pc,r5 + \\2: mov r7,#1 + \\ svc 0 + \\ + \\1: mov lr,pc + \\ bx r5 + \\ b 2b + ); } else { @compileError("Implement clone() for this arch."); } diff --git a/std/special/start.zig b/std/special/start.zig index 3427ff422dbcd7e40b8435b1b9216583407308a3..fde79a4bafb0c8c9587e19f8fe053a7a275f0478 100644 --- a/std/special/start.zig +++ b/std/special/start.zig @@ -44,7 +44,7 @@ nakedcc fn _start() noreturn { : [argc] "={esp}" (-> [*]usize) ); }, - .aarch64, .aarch64_be => { + .aarch64, .aarch64_be, .arm => { argc_ptr = asm ("mov %[argc], sp" : [argc] "=r" (-> [*]usize) ); -- 2.54.0 From 108a51b11032ba3ed7864a653f87283853e6e318 Mon Sep 17 00:00:00 2001 From: Robin Voetter Date: Thu, 29 Aug 2019 10:34:05 +0200 Subject: [PATCH 10/80] fix issues with debug.zig - Use sys_*stat*64 instead of sys_*stat* where appropriate - Fix overflow when calculating atime, ctime and mtime on File.stat() - Fix compilation error casting getEndPos to usize. --- std/debug.zig | 2 +- std/fs/file.zig | 6 +++--- std/os/bits/linux/arm-eabi.zig | 4 ++-- std/os/linux.zig | 24 ++++++++++++++++++++---- 4 files changed, 26 insertions(+), 10 deletions(-) diff --git a/std/debug.zig b/std/debug.zig index d1c17343efe3ff02711e862c70f5b5a0c2f1617d..a6ef60b6638313b53ffb11697669fd2e0eae709b 100644 --- a/std/debug.zig +++ b/std/debug.zig @@ -1053,7 +1053,7 @@ fn openSelfDebugInfoPosix(allocator: *mem.Allocator) !DwarfInfo { S.self_exe_file = try fs.openSelfExe(); errdefer S.self_exe_file.close(); - const self_exe_mmap_len = mem.alignForward(try S.self_exe_file.getEndPos(), mem.page_size); + const self_exe_mmap_len = mem.alignForward(@intCast(usize, try S.self_exe_file.getEndPos()), mem.page_size); const self_exe_mmap = try os.mmap( null, self_exe_mmap_len, diff --git a/std/fs/file.zig b/std/fs/file.zig index 0014693d40d3f95c8d56194d3980a743be322103..83cbe2378010e4e73545e0aeb5082fd18d346541 100644 --- a/std/fs/file.zig +++ b/std/fs/file.zig @@ -261,9 +261,9 @@ pub const File = struct { return Stat{ .size = @bitCast(u64, st.size), .mode = st.mode, - .atime = atime.tv_sec * std.time.ns_per_s + atime.tv_nsec, - .mtime = mtime.tv_sec * std.time.ns_per_s + mtime.tv_nsec, - .ctime = ctime.tv_sec * std.time.ns_per_s + ctime.tv_nsec, + .atime = @intCast(i64, atime.tv_sec) * std.time.ns_per_s + atime.tv_nsec, + .mtime = @intCast(i64, mtime.tv_sec) * std.time.ns_per_s + mtime.tv_nsec, + .ctime = @intCast(i64, ctime.tv_sec) * std.time.ns_per_s + ctime.tv_nsec, }; } diff --git a/std/os/bits/linux/arm-eabi.zig b/std/os/bits/linux/arm-eabi.zig index 1b45588459a218362a0508a81092416bd742741b..5048a2afc71c2a4ffbb62611684b6b5a0951b716 100644 --- a/std/os/bits/linux/arm-eabi.zig +++ b/std/os/bits/linux/arm-eabi.zig @@ -502,7 +502,7 @@ pub const msghdr_const = extern struct { /// methods to accomplish this. pub const Stat = extern struct { dev: u64, - __dev_patting: u32, + __dev_padding: u32, __ino_truncated: u32, mode: u32, nlink: u32, @@ -512,7 +512,7 @@ pub const Stat = extern struct { __rdev_padding: u32, size: i64, blksize: i32, - blocks: i64, + blocks: u64, atim: timespec, mtim: timespec, ctim: timespec, diff --git a/std/os/linux.zig b/std/os/linux.zig index 7d019001ef3561f234b23252656e2179de022c52..3134ebf64140acf709442cdca5b42114a8d03e1b 100644 --- a/std/os/linux.zig +++ b/std/os/linux.zig @@ -713,22 +713,38 @@ pub fn accept4(fd: i32, noalias addr: *sockaddr, noalias len: *socklen_t, flags: } pub fn fstat(fd: i32, stat_buf: *Stat) usize { - return syscall2(SYS_fstat, @bitCast(usize, isize(fd)), @ptrToInt(stat_buf)); + if (@hasDecl(@This(), "SYS_fstat64")) { + return syscall2(SYS_fstat64, @bitCast(usize, isize(fd)), @ptrToInt(stat_buf)); + } else { + return syscall2(SYS_fstat, @bitCast(usize, isize(fd)), @ptrToInt(stat_buf)); + } } // TODO https://github.com/ziglang/zig/issues/265 pub fn stat(pathname: [*]const u8, statbuf: *Stat) usize { - return syscall2(SYS_stat, @ptrToInt(pathname), @ptrToInt(statbuf)); + if (@hasDecl(@This(), "SYS_stat64")) { + return syscall2(SYS_stat64, @ptrToInt(pathname), @ptrToInt(statbuf)); + } else { + return syscall2(SYS_stat, @ptrToInt(pathname), @ptrToInt(statbuf)); + } } // TODO https://github.com/ziglang/zig/issues/265 pub fn lstat(pathname: [*]const u8, statbuf: *Stat) usize { - return syscall2(SYS_lstat, @ptrToInt(pathname), @ptrToInt(statbuf)); + if (@hasDecl(@This(), "SYS_lstat64")) { + return syscall2(SYS_lstat64, @ptrToInt(pathname), @ptrToInt(statbuf)); + } else { + return syscall2(SYS_lstat, @ptrToInt(pathname), @ptrToInt(statbuf)); + } } // TODO https://github.com/ziglang/zig/issues/265 pub fn fstatat(dirfd: i32, path: [*]const u8, stat_buf: *Stat, flags: u32) usize { - return syscall4(SYS_fstatat, @bitCast(usize, isize(dirfd)), @ptrToInt(path), @ptrToInt(stat_buf), flags); + if (@hasDecl(@This(), "SYS_fstatat64")) { + return syscall4(SYS_fstatat64, @bitCast(usize, isize(dirfd)), @ptrToInt(path), @ptrToInt(stat_buf), flags); + } else { + return syscall4(SYS_fstatat, @bitCast(usize, isize(dirfd)), @ptrToInt(path), @ptrToInt(stat_buf), flags); + } } // TODO https://github.com/ziglang/zig/issues/265 -- 2.54.0 From e4c262b804dded7e47aea0bb61f4578b94a7fa86 Mon Sep 17 00:00:00 2001 From: Robin Voetter Date: Thu, 29 Aug 2019 10:52:50 +0200 Subject: [PATCH 11/80] Don't print line info if source is not available --- std/debug.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/std/debug.zig b/std/debug.zig index a6ef60b6638313b53ffb11697669fd2e0eae709b..8918426e47aee8cc4b546673860752586c906ea3 100644 --- a/std/debug.zig +++ b/std/debug.zig @@ -793,7 +793,7 @@ fn printLineInfo( try out_stream.write(GREEN ++ "^" ++ RESET ++ "\n"); } } else |err| switch (err) { - error.EndOfFile => {}, + error.EndOfFile, error.FileNotFound => {}, else => return err, } } else { -- 2.54.0 From 2323da3a680f48207d35db26f63ea0553e74d956 Mon Sep 17 00:00:00 2001 From: Robin Voetter Date: Thu, 29 Aug 2019 18:12:58 +0200 Subject: [PATCH 12/80] add __aeabi_read_tp --- std/os/bits/linux/arm-eabi.zig | 24 ++++++++++++++++++++++++ std/os/linux/arm-eabi.zig | 8 ++++++++ std/os/linux/tls.zig | 12 ++++++++++++ std/special/c.zig | 2 ++ 4 files changed, 46 insertions(+) diff --git a/std/os/bits/linux/arm-eabi.zig b/std/os/bits/linux/arm-eabi.zig index 5048a2afc71c2a4ffbb62611684b6b5a0951b716..ca80b67fe19adcea75b2da4eb55dacdc7d2fb14b 100644 --- a/std/os/bits/linux/arm-eabi.zig +++ b/std/os/bits/linux/arm-eabi.zig @@ -474,6 +474,30 @@ pub const VDSO_USEFUL = true; pub const VDSO_CGT_SYM = "__vdso_clock_gettime"; pub const VDSO_CGT_VER = "LINUX_2.6"; +pub const HWCAP_SWP = 1 << 0; +pub const HWCAP_HALF = 1 << 1; +pub const HWCAP_THUMB = 1 << 2; +pub const HWCAP_26BIT = 1 << 3; +pub const HWCAP_FAST_MULT = 1 << 4; +pub const HWCAP_FPA = 1 << 5; +pub const HWCAP_VFP = 1 << 6; +pub const HWCAP_EDSP = 1 << 7; +pub const HWCAP_JAVA = 1 << 8; +pub const HWCAP_IWMMXT = 1 << 9; +pub const HWCAP_CRUNCH = 1 << 10; +pub const HWCAP_THUMBEE = 1 << 11; +pub const HWCAP_NEON = 1 << 12; +pub const HWCAP_VFPv3 = 1 << 13; +pub const HWCAP_VFPv3D16 = 1 << 14; +pub const HWCAP_TLS = 1 << 15; +pub const HWCAP_VFPv4 = 1 << 16; +pub const HWCAP_IDIVA = 1 << 17; +pub const HWCAP_IDIVT = 1 << 18; +pub const HWCAP_VFPD32 = 1 << 19; +pub const HWCAP_IDIV = HWCAP_IDIVA | HWCAP_IDIVT; +pub const HWCAP_LPAE = 1 << 20; +pub const HWCAP_EVTSTRM = 1 << 21; + pub const msghdr = extern struct { msg_name: ?*sockaddr, msg_namelen: socklen_t, diff --git a/std/os/linux/arm-eabi.zig b/std/os/linux/arm-eabi.zig index 3b8eb055d5f6f16e401ed39ed5ae918b06f94773..a8cb52d7118ec095a26c55e695aa1c5ce79a972c 100644 --- a/std/os/linux/arm-eabi.zig +++ b/std/os/linux/arm-eabi.zig @@ -78,3 +78,11 @@ pub fn syscall6( /// This matches the libc clone function. pub extern fn clone(func: extern fn (arg: usize) u8, stack: usize, flags: u32, arg: usize, ptid: *i32, tls: usize, ctid: *i32) usize; + +// LLVM calls this when the read-tp-hard feature is set to false. Currently, there is no way to pass +// that to llvm via zig. See https://github.com/ziglang/zig/issues/2883 +pub nakedcc fn getThreadPointer() usize { + return asm volatile("mrc p15, 0, %[ret], c13, c0, 3" + : [ret] "=r" (-> usize) + ); +} \ No newline at end of file diff --git a/std/os/linux/tls.zig b/std/os/linux/tls.zig index 63c44d6982206dad6f14249b864d0dc5c6c8e380..a14b26a5cf00391340a4e14a59c0cd75022ddf0d 100644 --- a/std/os/linux/tls.zig +++ b/std/os/linux/tls.zig @@ -133,6 +133,7 @@ pub fn initTLS() void { var at_phent: usize = undefined; var at_phnum: usize = undefined; var at_phdr: usize = undefined; + var at_hwcap: usize = undefined; var i: usize = 0; while (auxv[i].a_type != std.elf.AT_NULL) : (i += 1) { @@ -140,10 +141,21 @@ pub fn initTLS() void { elf.AT_PHENT => at_phent = auxv[i].a_un.a_val, elf.AT_PHNUM => at_phnum = auxv[i].a_un.a_val, elf.AT_PHDR => at_phdr = auxv[i].a_un.a_val, + elf.AT_HWCAP => at_phdr = auxv[i].a_un.a_val, else => continue, } } + // If the cpu is arm-based, check if it supports the TLS register + if (builtin.arch == builtin.Arch.arm and builtin.os == .linux) { + if (at_hwcap & std.os.linux.HWCAP_TLS == 0) { + // If the CPU does not support TLS via a coprocessor register, + // it could be accessed via a kernel helper function + // see musl/src/thread/arm/ for details + @panic("cpu does not support TLS via coprocessor register"); + } + } + // Sanity check assert(at_phent == @sizeOf(elf.Phdr)); diff --git a/std/special/c.zig b/std/special/c.zig index 5ac74574292d1669ae6db0c9d10dc772fcdccde5..669a771c2edafd0de930ac411af1c1d2b333954a 100644 --- a/std/special/c.zig +++ b/std/special/c.zig @@ -25,6 +25,8 @@ comptime { @export("strncmp", strncmp, .Strong); @export("strerror", strerror, .Strong); @export("strlen", strlen, .Strong); + } else if (builtin.arch == builtin.Arch.arm and builtin.os == .linux) { + @export("__aeabi_read_tp", std.os.linux.getThreadPointer, .Strong); } } -- 2.54.0 From c1f8b201a1419e1f86c116c67de2f5a8c58b9a84 Mon Sep 17 00:00:00 2001 From: Robin Voetter Date: Fri, 30 Aug 2019 12:58:44 +0200 Subject: [PATCH 13/80] Improve comments near un-implemented functionality --- std/os/linux/arm-eabi.zig | 3 ++- std/os/linux/tls.zig | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/std/os/linux/arm-eabi.zig b/std/os/linux/arm-eabi.zig index a8cb52d7118ec095a26c55e695aa1c5ce79a972c..1167c10f0b61387ff75d081f9e1a1a582f975f0e 100644 --- a/std/os/linux/arm-eabi.zig +++ b/std/os/linux/arm-eabi.zig @@ -80,7 +80,8 @@ pub fn syscall6( pub extern fn clone(func: extern fn (arg: usize) u8, stack: usize, flags: u32, arg: usize, ptid: *i32, tls: usize, ctid: *i32) usize; // LLVM calls this when the read-tp-hard feature is set to false. Currently, there is no way to pass -// that to llvm via zig. See https://github.com/ziglang/zig/issues/2883 +// that to llvm via zig, see https://github.com/ziglang/zig/issues/2883. +// LLVM expects libc to provide this function as __aeabi_read_tp, so it is exported if needed from special/c.zig. pub nakedcc fn getThreadPointer() usize { return asm volatile("mrc p15, 0, %[ret], c13, c0, 3" : [ret] "=r" (-> usize) diff --git a/std/os/linux/tls.zig b/std/os/linux/tls.zig index a14b26a5cf00391340a4e14a59c0cd75022ddf0d..1b2687b82c155e7c40ea4dd1c73cdaa93a31b923 100644 --- a/std/os/linux/tls.zig +++ b/std/os/linux/tls.zig @@ -150,9 +150,9 @@ pub fn initTLS() void { if (builtin.arch == builtin.Arch.arm and builtin.os == .linux) { if (at_hwcap & std.os.linux.HWCAP_TLS == 0) { // If the CPU does not support TLS via a coprocessor register, - // it could be accessed via a kernel helper function - // see musl/src/thread/arm/ for details - @panic("cpu does not support TLS via coprocessor register"); + // a kernel helper function can be used instead on certain linux kernels. + // See linux/arch/arm/include/asm/tls.h and musl/src/thread/arm/__set_thread_area.c. + @panic("TODO: Implement ARM fallback TLS functionality"); } } -- 2.54.0 From 4b8325f3815c7fa774bb06ef5d190f039723222b Mon Sep 17 00:00:00 2001 From: Robin Voetter Date: Fri, 30 Aug 2019 13:02:15 +0200 Subject: [PATCH 14/80] Remove unneeded os check --- std/os/linux/tls.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/std/os/linux/tls.zig b/std/os/linux/tls.zig index 1b2687b82c155e7c40ea4dd1c73cdaa93a31b923..8920e28a5b9e7b0ade4589befc949c35eb5e0fc2 100644 --- a/std/os/linux/tls.zig +++ b/std/os/linux/tls.zig @@ -147,7 +147,7 @@ pub fn initTLS() void { } // If the cpu is arm-based, check if it supports the TLS register - if (builtin.arch == builtin.Arch.arm and builtin.os == .linux) { + if (builtin.arch == builtin.Arch.arm) { if (at_hwcap & std.os.linux.HWCAP_TLS == 0) { // If the CPU does not support TLS via a coprocessor register, // a kernel helper function can be used instead on certain linux kernels. -- 2.54.0 From e39c93a2f346e4bfb2653ccf231d736dfb9bce6e Mon Sep 17 00:00:00 2001 From: Robin Voetter Date: Sun, 1 Sep 2019 11:54:57 +0200 Subject: [PATCH 15/80] Replace legacy 16-bit syscalls with 32-bit versions when appropriate --- std/os/linux.zig | 84 ++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 70 insertions(+), 14 deletions(-) diff --git a/std/os/linux.zig b/std/os/linux.zig index 3134ebf64140acf709442cdca5b42114a8d03e1b..e24ba441ccacc167dde517181014520888451cfe 100644 --- a/std/os/linux.zig +++ b/std/os/linux.zig @@ -486,35 +486,67 @@ pub fn nanosleep(req: *const timespec, rem: ?*timespec) usize { } pub fn setuid(uid: u32) usize { - return syscall1(SYS_setuid, uid); + if (@hasDecl(@This(), "SYS_setuid32")) { + return syscall1(SYS_setuid32, uid); + } else { + return syscall1(SYS_setuid, uid); + } } pub fn setgid(gid: u32) usize { - return syscall1(SYS_setgid, gid); + if (@hasDecl(@This(), "SYS_setgid32")) { + return syscall1(SYS_setgid32, gid); + } else { + return syscall1(SYS_setgid, gid); + } } pub fn setreuid(ruid: u32, euid: u32) usize { - return syscall2(SYS_setreuid, ruid, euid); + if (@hasDecl(@This(), "SYS_setreuid32")) { + return syscall2(SYS_setreuid32, ruid, euid)); + } else { + return syscall2(SYS_setreuid, ruid, euid)); + } } pub fn setregid(rgid: u32, egid: u32) usize { - return syscall2(SYS_setregid, rgid, egid); + if (@hasDecl(@This(), "SYS_setregid32")) { + return syscall2(SYS_setregid32, rgid, egid); + } else { + return syscall2(SYS_setregid, rgid, egid); + } } pub fn getuid() u32 { - return u32(syscall0(SYS_getuid)); + if (@hasDecl(@This(), "SYS_getuid32")) { + return u32(syscall0(SYS_getuid32)); + } else { + return u32(syscall0(SYS_getuid)); + } } pub fn getgid() u32 { - return u32(syscall0(SYS_getgid)); + if (@hasDecl(@This(), "SYS_getgid32")) { + return u32(syscall0(SYS_getgid32)); + } else { + return u32(syscall0(SYS_getgid)); + } } pub fn geteuid() u32 { - return u32(syscall0(SYS_geteuid)); + if (@hasDecl(@This(), "SYS_geteuid32")) { + return u32(syscall0(SYS_geteuid32)); + } else { + return u32(syscall0(SYS_geteuid)); + } } pub fn getegid() u32 { - return u32(syscall0(SYS_getegid)); + if (@hasDecl(@This(), "SYS_getegid32")) { + return u32(syscall0(SYS_getegid32)); + } else { + return u32(syscall0(SYS_getegid)); + } } pub fn seteuid(euid: u32) usize { @@ -526,27 +558,51 @@ pub fn setegid(egid: u32) usize { } pub fn getresuid(ruid: *u32, euid: *u32, suid: *u32) usize { - return syscall3(SYS_getresuid, @ptrToInt(ruid), @ptrToInt(euid), @ptrToInt(suid)); + if (@hasDecl(@This(), "SYS_getresuid32")) { + return syscall3(SYS_getresuid32, @ptrToInt(ruid), @ptrToInt(euid), @ptrToInt(suid)); + } else { + return syscall3(SYS_getresuid, @ptrToInt(ruid), @ptrToInt(euid), @ptrToInt(suid)); + } } pub fn getresgid(rgid: *u32, egid: *u32, sgid: *u32) usize { - return syscall3(SYS_getresgid, @ptrToInt(rgid), @ptrToInt(egid), @ptrToInt(sgid)); + if (@hasDecl(@This(), "SYS_getresgid32")) { + return syscall3(SYS_getresgid32, @ptrToInt(rgid), @ptrToInt(egid), @ptrToInt(sgid)); + } else { + return syscall3(SYS_getresgid, @ptrToInt(rgid), @ptrToInt(egid), @ptrToInt(sgid)); + } } pub fn setresuid(ruid: u32, euid: u32, suid: u32) usize { - return syscall3(SYS_setresuid, ruid, euid, suid); + if (@hasDecl(@This(), "SYS_setresuid32")) { + return syscall3(SYS_setresuid32, ruid, euid, suid); + } else { + return syscall3(SYS_setresuid, ruid, euid, suid); + } } pub fn setresgid(rgid: u32, egid: u32, sgid: u32) usize { - return syscall3(SYS_setresgid, rgid, egid, sgid); + if (@hasDecl(@This(), "SYS_setresgid32")) { + return syscall3(SYS_setresgid32, rgid, egid, sgid); + } else { + return syscall3(SYS_setresgid, rgid, egid, sgid); + } } pub fn getgroups(size: usize, list: *u32) usize { - return syscall2(SYS_getgroups, size, @ptrToInt(list)); + if (@hasDecl(@This(), "SYS_getgroups32")) { + return syscall2(SYS_getgroups32, size, @ptrToInt(list)); + } else { + return syscall2(SYS_getgroups, size, @ptrToInt(list)); + } } pub fn setgroups(size: usize, list: *const u32) usize { - return syscall2(SYS_setgroups, size, @ptrToInt(list)); + if (@hasDecl(@This(), "SYS_setgroups32")) { + return syscall2(SYS_setgroups32, size, @ptrToInt(list)); + } else { + return syscall2(SYS_setgroups, size, @ptrToInt(list)); + } } pub fn getpid() i32 { -- 2.54.0 From e9d795b025e55dcd9d8c4378141b996358634863 Mon Sep 17 00:00:00 2001 From: Robin Voetter Date: Sun, 1 Sep 2019 12:08:02 +0200 Subject: [PATCH 16/80] Fix up seteuid and setegid --- std/os/linux.zig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/std/os/linux.zig b/std/os/linux.zig index e24ba441ccacc167dde517181014520888451cfe..7bb59dde41178d81508ca895185a62e81f6b7b8c 100644 --- a/std/os/linux.zig +++ b/std/os/linux.zig @@ -550,11 +550,11 @@ pub fn getegid() u32 { } pub fn seteuid(euid: u32) usize { - return syscall1(SYS_seteuid, euid); + return setreuid(std.math.maxInt(u32), euid); } pub fn setegid(egid: u32) usize { - return syscall1(SYS_setegid, egid); + return setregid(std.math.maxInt(u32), egid); } pub fn getresuid(ruid: *u32, euid: *u32, suid: *u32) usize { -- 2.54.0 From e7912dee9bd63b03415f441b4de9b3babc79c859 Mon Sep 17 00:00:00 2001 From: Robin Voetter Date: Sun, 1 Sep 2019 16:10:36 +0200 Subject: [PATCH 17/80] Fix up preadv, preadv2, pwritev and pwritev2 --- std/os/linux.zig | 42 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 36 insertions(+), 6 deletions(-) diff --git a/std/os/linux.zig b/std/os/linux.zig index 7bb59dde41178d81508ca895185a62e81f6b7b8c..58c402f82981b771e2a9e00a89a68a66f846fa53 100644 --- a/std/os/linux.zig +++ b/std/os/linux.zig @@ -210,11 +210,26 @@ pub fn read(fd: i32, buf: [*]u8, count: usize) usize { } pub fn preadv(fd: i32, iov: [*]const iovec, count: usize, offset: u64) usize { - return syscall4(SYS_preadv, @bitCast(usize, isize(fd)), @ptrToInt(iov), count, offset); + return syscall5( + SYS_preadv, + @bitCast(usize, isize(fd)), + @ptrToInt(iov), + count, + @truncate(usize, offset), + @truncate(usize, offset >> 32), + ); } pub fn preadv2(fd: i32, iov: [*]const iovec, count: usize, offset: u64, flags: kernel_rwf) usize { - return syscall5(SYS_preadv2, @bitCast(usize, isize(fd)), @ptrToInt(iov), count, offset, flags); + return syscall6( + SYS_preadv2, + @bitCast(usize, isize(fd)), + @ptrToInt(iov), + count, + @truncate(usize, offset), + @truncate(usize, offset >> 32), + flags + ); } pub fn readv(fd: i32, iov: [*]const iovec, count: usize) usize { @@ -226,11 +241,26 @@ pub fn writev(fd: i32, iov: [*]const iovec_const, count: usize) usize { } pub fn pwritev(fd: i32, iov: [*]const iovec_const, count: usize, offset: u64) usize { - return syscall4(SYS_pwritev, @bitCast(usize, isize(fd)), @ptrToInt(iov), count, offset); + return syscall5( + SYS_pwritev, + @bitCast(usize, isize(fd)), + @ptrToInt(iov), + count, + @truncate(usize, offset), + @truncate(usize, offset >> 32), + ); } pub fn pwritev2(fd: i32, iov: [*]const iovec_const, count: usize, offset: u64, flags: kernel_rwf) usize { - return syscall5(SYS_pwritev2, @bitCast(usize, isize(fd)), @ptrToInt(iov), count, offset, flags); + return syscall6( + SYS_pwritev2, + @bitCast(usize, isize(fd)), + @ptrToInt(iov), + count, + @truncate(usize, offset), + @truncate(usize, offset >> 32), + flags + ); } // TODO https://github.com/ziglang/zig/issues/265 @@ -503,9 +533,9 @@ pub fn setgid(gid: u32) usize { pub fn setreuid(ruid: u32, euid: u32) usize { if (@hasDecl(@This(), "SYS_setreuid32")) { - return syscall2(SYS_setreuid32, ruid, euid)); + return syscall2(SYS_setreuid32, ruid, euid); } else { - return syscall2(SYS_setreuid, ruid, euid)); + return syscall2(SYS_setreuid, ruid, euid); } } -- 2.54.0 From 00d82e34df92c181d20064c0c2f80feaba9dab03 Mon Sep 17 00:00:00 2001 From: Michael Dusan Date: Mon, 2 Sep 2019 17:45:30 -0400 Subject: [PATCH 18/80] cmake: improve building without git repository - quiet `fatal: not a git repository` message - if git probe fails skip ZIG_VERSION modification --- CMakeLists.txt | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index beb4ac671c506f057c4d4fbfb607cfda58d2aeda..f296f9dee491376b4d23261b17272a762275390b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,14 +23,18 @@ find_program(GIT_EXE NAMES git) if(GIT_EXE) execute_process( COMMAND ${GIT_EXE} -C ${CMAKE_SOURCE_DIR} name-rev HEAD --tags --name-only --no-undefined --always + RESULT_VARIABLE EXIT_STATUS OUTPUT_VARIABLE ZIG_GIT_REV - OUTPUT_STRIP_TRAILING_WHITESPACE) - if(ZIG_GIT_REV MATCHES "\\^0$") - if(NOT("${ZIG_GIT_REV}" STREQUAL "${ZIG_VERSION}^0")) - message("WARNING: Tag does not match configured Zig version") + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_QUIET) + if(EXIT_STATUS EQUAL "0") + if(ZIG_GIT_REV MATCHES "\\^0$") + if(NOT("${ZIG_GIT_REV}" STREQUAL "${ZIG_VERSION}^0")) + message("WARNING: Tag does not match configured Zig version") + endif() + else() + set(ZIG_VERSION "${ZIG_VERSION}+${ZIG_GIT_REV}") endif() - else() - set(ZIG_VERSION "${ZIG_VERSION}+${ZIG_GIT_REV}") endif() endif() message("Configuring zig version ${ZIG_VERSION}") -- 2.54.0 From d74b8567cf6a81550831a9ea02f2cebcb4db9846 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 2 Sep 2019 21:22:35 -0400 Subject: [PATCH 19/80] omit prefix data for async functions sometimes When `@frameSize` is never called, and `@asyncCall` on a runtime-known pointer is never used, no prefix data for async functions is needed. Related: #3160 --- src/all_types.hpp | 1 + src/codegen.cpp | 5 ++++- src/ir.cpp | 3 +++ 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/all_types.hpp b/src/all_types.hpp index 708db8848d805a45129e4797cebf4193a649fa16..1a97cf281469d3bc3ae845cb99d405c2ff000f40 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -1989,6 +1989,7 @@ struct CodeGen { bool system_linker_hack; bool reported_bad_link_libc_error; bool is_dynamic; // shared library rather than static library. dynamic musl rather than static musl. + bool need_frame_size_prefix_data; //////////////////////////// Participates in Input Parameter Cache Hash /////// Note: there is a separate cache hash for builtin.zig, when adding fields, diff --git a/src/codegen.cpp b/src/codegen.cpp index 0b51df1e82c8430dd12e64124908017da64ed054..b694923873a51f8a8f206e282dfecf6558c94f19 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -3775,6 +3775,7 @@ static void render_async_var_decls(CodeGen *g, Scope *scope) { } static LLVMValueRef gen_frame_size(CodeGen *g, LLVMValueRef fn_val) { + assert(g->need_frame_size_prefix_data); LLVMTypeRef usize_llvm_type = g->builtin_types.entry_usize->llvm_type; LLVMTypeRef ptr_usize_llvm_type = LLVMPointerType(usize_llvm_type, 0); LLVMValueRef casted_fn_val = LLVMBuildBitCast(g->builder, fn_val, ptr_usize_llvm_type, ""); @@ -7208,7 +7209,9 @@ static void do_code_gen(CodeGen *g) { LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type; LLVMValueRef size_val = LLVMConstInt(usize_type_ref, fn_table_entry->frame_type->abi_size, false); - ZigLLVMFunctionSetPrefixData(fn_table_entry->llvm_value, size_val); + if (g->need_frame_size_prefix_data) { + ZigLLVMFunctionSetPrefixData(fn_table_entry->llvm_value, size_val); + } if (!g->strip_debug_symbols) { AstNode *source_node = fn_table_entry->proto_node; diff --git a/src/ir.cpp b/src/ir.cpp index 01066e51c30e80ddd06c751e85c2f372e3d792ba..e3b440d0f5c3a55630be16513467887ca005032b 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -15671,6 +15671,7 @@ static IrInstruction *analyze_casted_new_stack(IrAnalyze *ira, IrInstructionCall ZigType *u8_ptr = get_pointer_to_type_extra(ira->codegen, ira->codegen->builtin_types.entry_u8, false, false, PtrLenUnknown, target_fn_align(ira->codegen->zig_target), 0, 0, false); ZigType *u8_slice = get_slice_type(ira->codegen, u8_ptr); + ira->codegen->need_frame_size_prefix_data = true; return ir_implicit_cast(ira, new_stack, u8_slice); } } @@ -22533,6 +22534,8 @@ static IrInstruction *ir_analyze_instruction_frame_size(IrAnalyze *ira, IrInstru return ira->codegen->invalid_instruction; } + ira->codegen->need_frame_size_prefix_data = true; + IrInstruction *result = ir_build_frame_size_gen(&ira->new_irb, instruction->base.scope, instruction->base.source_node, fn); result->value.type = ira->codegen->builtin_types.entry_usize; -- 2.54.0 From a19e73d8ae0bc5b7ac19b1bc72aa1fdb8f86d80f Mon Sep 17 00:00:00 2001 From: Michael Dusan Date: Mon, 27 May 2019 20:07:05 -0400 Subject: [PATCH 20/80] test: add compare-panic `zig build test-compare-panic` Create basic tests to compare panic output. The address field is replaced by a symbolic constant and each expected output is specific to os. Tests will only run for explicitly defined platforms. see also #2485 --- build.zig | 1 + test/compare_panic.zig | 277 +++++++++++++++++++++++++++++++++++++++++ test/tests.zig | 210 +++++++++++++++++++++++++++++++ 3 files changed, 488 insertions(+) create mode 100644 test/compare_panic.zig diff --git a/build.zig b/build.zig index 45758d4075371d16aff83a288d253d879fb5c347..cc0405c21a8481fa0d3aa58306615032a5a4fdc6 100644 --- a/build.zig +++ b/build.zig @@ -138,6 +138,7 @@ pub fn build(b: *Builder) !void { test_step.dependOn(tests.addCompareOutputTests(b, test_filter, modes)); test_step.dependOn(tests.addStandaloneTests(b, test_filter, modes)); + test_step.dependOn(tests.addComparePanicTests(b, test_filter, modes)); test_step.dependOn(tests.addCliTests(b, test_filter, modes)); test_step.dependOn(tests.addCompileErrorTests(b, test_filter, modes)); test_step.dependOn(tests.addAssembleAndLinkTests(b, test_filter, modes)); diff --git a/test/compare_panic.zig b/test/compare_panic.zig new file mode 100644 index 0000000000000000000000000000000000000000..3c71b9626a97b947e1615cc717b86808fa5aa264 --- /dev/null +++ b/test/compare_panic.zig @@ -0,0 +1,277 @@ +const builtin = @import("builtin"); +const std = @import("std"); +const os = std.os; +const tests = @import("tests.zig"); + +pub fn addCases(cases: *tests.ComparePanicContext) void { + const source_return = + \\const std = @import("std"); + \\ + \\pub fn main() !void { + \\ return error.TheSkyIsFalling; + \\} + ; + const source_try_return = + \\const std = @import("std"); + \\ + \\fn foo() !void { + \\ return error.TheSkyIsFalling; + \\} + \\ + \\pub fn main() !void { + \\ try foo(); + \\} + ; + const source_try_try_return_return = + \\const std = @import("std"); + \\ + \\fn foo() !void { + \\ try bar(); + \\} + \\ + \\fn bar() !void { + \\ return make_error(); + \\} + \\ + \\fn make_error() !void { + \\ return error.TheSkyIsFalling; + \\} + \\ + \\pub fn main() !void { + \\ try foo(); + \\} + ; + switch (builtin.os) { + .linux => { + cases.addCase( + "return", + source_return, + [][]const u8{ + // debug + \\error: TheSkyIsFalling + \\source.zig:4:5: [address] in main (test) + \\ + , + // release-safe + \\error: TheSkyIsFalling + \\source.zig:4:5: [address] in std.special.posixCallMainAndExit (test) + \\ + , + // release-fast + \\error: TheSkyIsFalling + \\ + , + // release-small + \\error: TheSkyIsFalling + \\ + }, + ); + cases.addCase( + "try return", + source_try_return, + [][]const u8{ + // debug + \\error: TheSkyIsFalling + \\source.zig:4:5: [address] in foo (test) + \\source.zig:8:5: [address] in main (test) + \\ + , + // release-safe + \\error: TheSkyIsFalling + \\source.zig:4:5: [address] in std.special.posixCallMainAndExit (test) + \\source.zig:8:5: [address] in std.special.posixCallMainAndExit (test) + \\ + , + // release-fast + \\error: TheSkyIsFalling + \\ + , + // release-small + \\error: TheSkyIsFalling + \\ + }, + ); + cases.addCase( + "try try return return", + source_try_try_return_return, + [][]const u8{ + // debug + \\error: TheSkyIsFalling + \\source.zig:12:5: [address] in make_error (test) + \\source.zig:8:5: [address] in bar (test) + \\source.zig:4:5: [address] in foo (test) + \\source.zig:16:5: [address] in main (test) + \\ + , + // release-safe + \\error: TheSkyIsFalling + \\source.zig:12:5: [address] in std.special.posixCallMainAndExit (test) + \\source.zig:8:5: [address] in std.special.posixCallMainAndExit (test) + \\source.zig:4:5: [address] in std.special.posixCallMainAndExit (test) + \\source.zig:16:5: [address] in std.special.posixCallMainAndExit (test) + \\ + , + // release-fast + \\error: TheSkyIsFalling + \\ + , + // release-small + \\error: TheSkyIsFalling + \\ + }, + ); + }, + .macosx => { + cases.addCase( + "return", + source_return, + [][]const u8{ + // debug + \\error: TheSkyIsFalling + \\source.zig:4:5: [address] in _main.0 (test.o) + \\ + , + // release-safe + \\error: TheSkyIsFalling + \\source.zig:4:5: [address] in _main (test.o) + \\ + , + // release-fast + \\error: TheSkyIsFalling + \\ + , + // release-small + \\error: TheSkyIsFalling + \\ + }, + ); + cases.addCase( + "try return", + source_try_return, + [][]const u8{ + // debug + \\error: TheSkyIsFalling + \\source.zig:4:5: [address] in _foo (test.o) + \\source.zig:8:5: [address] in _main.0 (test.o) + \\ + , + // release-safe + \\error: TheSkyIsFalling + \\source.zig:4:5: [address] in _main (test.o) + \\source.zig:8:5: [address] in _main (test.o) + \\ + , + // release-fast + \\error: TheSkyIsFalling + \\ + , + // release-small + \\error: TheSkyIsFalling + \\ + }, + ); + cases.addCase( + "try try return return", + source_try_try_return_return, + [][]const u8{ + // debug + \\error: TheSkyIsFalling + \\source.zig:12:5: [address] in _make_error (test.o) + \\source.zig:8:5: [address] in _bar (test.o) + \\source.zig:4:5: [address] in _foo (test.o) + \\source.zig:16:5: [address] in _main.0 (test.o) + \\ + , + // release-safe + \\error: TheSkyIsFalling + \\source.zig:12:5: [address] in _main (test.o) + \\source.zig:8:5: [address] in _main (test.o) + \\source.zig:4:5: [address] in _main (test.o) + \\source.zig:16:5: [address] in _main (test.o) + \\ + , + // release-fast + \\error: TheSkyIsFalling + \\ + , + // release-small + \\error: TheSkyIsFalling + \\ + }, + ); + }, + .windows => { + cases.addCase( + "return", + source_return, + [][]const u8{ + // debug + \\error: TheSkyIsFalling + \\source.zig:4:5: [address] in main (test.obj) + \\ + , + // release-safe + // --disabled-- results in segmenetation fault + "" + , + // release-fast + \\error: TheSkyIsFalling + \\ + , + // release-small + \\error: TheSkyIsFalling + \\ + }, + ); + cases.addCase( + "try return", + source_try_return, + [][]const u8{ + // debug + \\error: TheSkyIsFalling + \\source.zig:4:5: [address] in foo (test.obj) + \\source.zig:8:5: [address] in main (test.obj) + \\ + , + // release-safe + // --disabled-- results in segmenetation fault + "" + , + // release-fast + \\error: TheSkyIsFalling + \\ + , + // release-small + \\error: TheSkyIsFalling + \\ + }, + ); + cases.addCase( + "try try return return", + source_try_try_return_return, + [][]const u8{ + // debug + \\error: TheSkyIsFalling + \\source.zig:12:5: [address] in make_error (test.obj) + \\source.zig:8:5: [address] in bar (test.obj) + \\source.zig:4:5: [address] in foo (test.obj) + \\source.zig:16:5: [address] in main (test.obj) + \\ + , + // release-safe + // --disabled-- results in segmenetation fault + "" + , + // release-fast + \\error: TheSkyIsFalling + \\ + , + // release-small + \\error: TheSkyIsFalling + \\ + }, + ); + }, + else => {}, + } +} diff --git a/test/tests.zig b/test/tests.zig index f7ef05d3cd51de041cb2b97784dbba5c44ea1cff..1bb9e417e5ab41f6f5c0053571726000b0b19953 100644 --- a/test/tests.zig +++ b/test/tests.zig @@ -16,6 +16,7 @@ const LibExeObjStep = build.LibExeObjStep; const compare_output = @import("compare_output.zig"); const standalone = @import("standalone.zig"); +const compare_panic = @import("compare_panic.zig"); const compile_errors = @import("compile_errors.zig"); const assemble_and_link = @import("assemble_and_link.zig"); const runtime_safety = @import("runtime_safety.zig"); @@ -57,6 +58,21 @@ pub fn addCompareOutputTests(b: *build.Builder, test_filter: ?[]const u8, modes: return cases.step; } +pub fn addComparePanicTests(b: *build.Builder, test_filter: ?[]const u8, modes: []const Mode) *build.Step { + const cases = b.allocator.create(ComparePanicContext) catch unreachable; + cases.* = ComparePanicContext{ + .b = b, + .step = b.step("test-compare-panic", "Run the compare panic tests"), + .test_index = 0, + .test_filter = test_filter, + .modes = modes, + }; + + compare_panic.addCases(cases); + + return cases.step; +} + pub fn addRuntimeSafetyTests(b: *build.Builder, test_filter: ?[]const u8, modes: []const Mode) *build.Step { const cases = b.allocator.create(CompareOutputContext) catch unreachable; cases.* = CompareOutputContext{ @@ -549,6 +565,200 @@ pub const CompareOutputContext = struct { } }; +pub const ComparePanicContext = struct { + b: *build.Builder, + step: *build.Step, + test_index: usize, + test_filter: ?[]const u8, + modes: []const Mode, + + const Expect = [@typeInfo(Mode).Enum.fields.len][]const u8; + + pub fn addCase( + self: *ComparePanicContext, + name: []const u8, + source: []const u8, + expect: Expect, + ) void { + const b = self.b; + + const source_pathname = fs.path.join( + b.allocator, + [][]const u8{ b.cache_root, "source.zig" }, + ) catch unreachable; + + for (self.modes) |mode| { + const expect_for_mode = expect[@enumToInt(mode)]; + if (expect_for_mode.len == 0) continue; + + const annotated_case_name = fmt.allocPrint(self.b.allocator, "{} {} ({})", "compare-panic", name, @tagName(mode)) catch unreachable; + if (self.test_filter) |filter| { + if (mem.indexOf(u8, annotated_case_name, filter) == null) continue; + } + + const exe = b.addExecutable("test", source_pathname); + exe.setBuildMode(mode); + + const write_source = b.addWriteFile(source_pathname, source); + exe.step.dependOn(&write_source.step); + + const run_and_compare = RunAndCompareStep.create( + self, + exe, + annotated_case_name, + mode, + expect_for_mode, + ); + + self.step.dependOn(&run_and_compare.step); + } + } + + const RunAndCompareStep = struct { + step: build.Step, + context: *ComparePanicContext, + exe: *LibExeObjStep, + name: []const u8, + mode: Mode, + expect_output: []const u8, + test_index: usize, + + pub fn create( + context: *ComparePanicContext, + exe: *LibExeObjStep, + name: []const u8, + mode: Mode, + expect_output: []const u8, + ) *RunAndCompareStep { + const allocator = context.b.allocator; + const ptr = allocator.create(RunAndCompareStep) catch unreachable; + ptr.* = RunAndCompareStep{ + .step = build.Step.init("PanicCompareOutputStep", allocator, make), + .context = context, + .exe = exe, + .name = name, + .mode = mode, + .expect_output = expect_output, + .test_index = context.test_index, + }; + ptr.step.dependOn(&exe.step); + context.test_index += 1; + return ptr; + } + + fn make(step: *build.Step) !void { + const self = @fieldParentPtr(RunAndCompareStep, "step", step); + const b = self.context.b; + + const full_exe_path = self.exe.getOutputPath(); + var args = ArrayList([]const u8).init(b.allocator); + defer args.deinit(); + args.append(full_exe_path) catch unreachable; + + warn("Test {}/{} {}...", self.test_index + 1, self.context.test_index, self.name); + + const child = std.ChildProcess.init(args.toSliceConst(), b.allocator) catch unreachable; + defer child.deinit(); + + child.stdin_behavior = .Ignore; + child.stdout_behavior = .Pipe; + child.stderr_behavior = .Pipe; + child.env_map = b.env_map; + + child.spawn() catch |err| debug.panic("Unable to spawn {}: {}\n", full_exe_path, @errorName(err)); + + var stdout = Buffer.initNull(b.allocator); + var stderr = Buffer.initNull(b.allocator); + + var stdout_file_in_stream = child.stdout.?.inStream(); + var stderr_file_in_stream = child.stderr.?.inStream(); + + stdout_file_in_stream.stream.readAllBuffer(&stdout, max_stdout_size) catch unreachable; + stderr_file_in_stream.stream.readAllBuffer(&stderr, max_stdout_size) catch unreachable; + + const term = child.wait() catch |err| { + debug.panic("Unable to spawn {}: {}\n", full_exe_path, @errorName(err)); + }; + + switch (term) { + .Exited => |code| { + const expect_code: u32 = 1; + if (code != expect_code) { + warn("Process {} exited with error code {} but expected code {}\n", full_exe_path, code, expect_code); + printInvocation(args.toSliceConst()); + return error.TestFailed; + } + }, + .Signal => |signum| { + warn("Process {} terminated on signal {}\n", full_exe_path, signum); + printInvocation(args.toSliceConst()); + return error.TestFailed; + }, + .Stopped => |signum| { + warn("Process {} stopped on signal {}\n", full_exe_path, signum); + printInvocation(args.toSliceConst()); + return error.TestFailed; + }, + .Unknown => |code| { + warn("Process {} terminated unexpectedly with error code {}\n", full_exe_path, code); + printInvocation(args.toSliceConst()); + return error.TestFailed; + }, + } + + // process result + // - keep only basename of source file path + // - replace address with symbolic string + // - skip empty lines + const got: []const u8 = got_result: { + var buf = try Buffer.initSize(b.allocator, 0); + defer buf.deinit(); + var bytes = stderr.toSliceConst(); + if (bytes.len != 0 and bytes[bytes.len - 1] == '\n') bytes = bytes[0 .. bytes.len - 1]; + var it = mem.separate(bytes, "\n"); + process_lines: while (it.next()) |line| { + if (line.len == 0) continue; + const delims = []const []const u8{ ":", ":", ":", " in " }; + var marks = []usize{0} ** 4; + // offset search past `[drive]:` on windows + var pos: usize = if (builtin.os == .windows) 2 else 0; + for (delims) |delim, i| { + marks[i] = mem.indexOfPos(u8, line, pos, delim) orelse { + try buf.append(line); + try buf.append("\n"); + continue :process_lines; + }; + pos = marks[i] + delim.len; + } + pos = mem.lastIndexOfScalar(u8, line[0..marks[0]], fs.path.sep) orelse { + try buf.append(line); + try buf.append("\n"); + continue :process_lines; + }; + try buf.append(line[pos + 1 .. marks[2] + delims[2].len]); + try buf.append(" [address]"); + try buf.append(line[marks[3]..]); + try buf.append("\n"); + } + break :got_result buf.toOwnedSlice(); + }; + + if (!mem.eql(u8, self.expect_output, got)) { + warn( + \\ + \\========= Expected this output: ========= + \\{} + \\================================================ + \\{} + \\ + , self.expect_output, got); + return error.TestFailed; + } + warn("OK\n"); + } + }; +}; + pub const CompileErrorContext = struct { b: *build.Builder, step: *build.Step, -- 2.54.0 From 1fd24791a7ea74260c86212e65b13cafd6243863 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 3 Sep 2019 10:05:19 -0400 Subject: [PATCH 21/80] rename compare-panic to compare-stack-traces --- build.zig | 4 +- .../{compare_panic.zig => compare_traces.zig} | 173 +++++++++--------- test/tests.zig | 28 +-- 3 files changed, 101 insertions(+), 104 deletions(-) rename test/{compare_panic.zig => compare_traces.zig} (63%) diff --git a/build.zig b/build.zig index cc0405c21a8481fa0d3aa58306615032a5a4fdc6..f8c095e8250f4c48a62a403537d8c3425eb1abc8 100644 --- a/build.zig +++ b/build.zig @@ -138,13 +138,13 @@ pub fn build(b: *Builder) !void { test_step.dependOn(tests.addCompareOutputTests(b, test_filter, modes)); test_step.dependOn(tests.addStandaloneTests(b, test_filter, modes)); - test_step.dependOn(tests.addComparePanicTests(b, test_filter, modes)); + test_step.dependOn(tests.addCompareStackTracesTests(b, test_filter, modes)); test_step.dependOn(tests.addCliTests(b, test_filter, modes)); - test_step.dependOn(tests.addCompileErrorTests(b, test_filter, modes)); test_step.dependOn(tests.addAssembleAndLinkTests(b, test_filter, modes)); test_step.dependOn(tests.addRuntimeSafetyTests(b, test_filter, modes)); test_step.dependOn(tests.addTranslateCTests(b, test_filter)); test_step.dependOn(tests.addGenHTests(b, test_filter)); + test_step.dependOn(tests.addCompileErrorTests(b, test_filter, modes)); test_step.dependOn(docs_step); } diff --git a/test/compare_panic.zig b/test/compare_traces.zig similarity index 63% rename from test/compare_panic.zig rename to test/compare_traces.zig index 3c71b9626a97b947e1615cc717b86808fa5aa264..3de0fb680a650aa080064935effc55f90326d491 100644 --- a/test/compare_panic.zig +++ b/test/compare_traces.zig @@ -3,7 +3,7 @@ const std = @import("std"); const os = std.os; const tests = @import("tests.zig"); -pub fn addCases(cases: *tests.ComparePanicContext) void { +pub fn addCases(cases: *tests.CompareStackTracesContext) void { const source_return = \\const std = @import("std"); \\ @@ -46,77 +46,77 @@ pub fn addCases(cases: *tests.ComparePanicContext) void { cases.addCase( "return", source_return, - [][]const u8{ - // debug - \\error: TheSkyIsFalling + [_][]const u8{ + // debug + \\error: TheSkyIsFalling \\source.zig:4:5: [address] in main (test) \\ , - // release-safe - \\error: TheSkyIsFalling + // release-safe + \\error: TheSkyIsFalling \\source.zig:4:5: [address] in std.special.posixCallMainAndExit (test) \\ , - // release-fast - \\error: TheSkyIsFalling + // release-fast + \\error: TheSkyIsFalling \\ , - // release-small - \\error: TheSkyIsFalling + // release-small + \\error: TheSkyIsFalling \\ }, ); cases.addCase( "try return", source_try_return, - [][]const u8{ - // debug - \\error: TheSkyIsFalling + [_][]const u8{ + // debug + \\error: TheSkyIsFalling \\source.zig:4:5: [address] in foo (test) \\source.zig:8:5: [address] in main (test) \\ , - // release-safe - \\error: TheSkyIsFalling + // release-safe + \\error: TheSkyIsFalling \\source.zig:4:5: [address] in std.special.posixCallMainAndExit (test) \\source.zig:8:5: [address] in std.special.posixCallMainAndExit (test) \\ , - // release-fast - \\error: TheSkyIsFalling + // release-fast + \\error: TheSkyIsFalling \\ , - // release-small - \\error: TheSkyIsFalling + // release-small + \\error: TheSkyIsFalling \\ }, ); cases.addCase( "try try return return", source_try_try_return_return, - [][]const u8{ - // debug - \\error: TheSkyIsFalling + [_][]const u8{ + // debug + \\error: TheSkyIsFalling \\source.zig:12:5: [address] in make_error (test) \\source.zig:8:5: [address] in bar (test) \\source.zig:4:5: [address] in foo (test) \\source.zig:16:5: [address] in main (test) \\ , - // release-safe - \\error: TheSkyIsFalling + // release-safe + \\error: TheSkyIsFalling \\source.zig:12:5: [address] in std.special.posixCallMainAndExit (test) \\source.zig:8:5: [address] in std.special.posixCallMainAndExit (test) \\source.zig:4:5: [address] in std.special.posixCallMainAndExit (test) \\source.zig:16:5: [address] in std.special.posixCallMainAndExit (test) \\ , - // release-fast - \\error: TheSkyIsFalling + // release-fast + \\error: TheSkyIsFalling \\ , - // release-small - \\error: TheSkyIsFalling + // release-small + \\error: TheSkyIsFalling \\ }, ); @@ -125,77 +125,77 @@ pub fn addCases(cases: *tests.ComparePanicContext) void { cases.addCase( "return", source_return, - [][]const u8{ - // debug - \\error: TheSkyIsFalling + [_][]const u8{ + // debug + \\error: TheSkyIsFalling \\source.zig:4:5: [address] in _main.0 (test.o) \\ , - // release-safe - \\error: TheSkyIsFalling + // release-safe + \\error: TheSkyIsFalling \\source.zig:4:5: [address] in _main (test.o) \\ , - // release-fast - \\error: TheSkyIsFalling + // release-fast + \\error: TheSkyIsFalling \\ , - // release-small - \\error: TheSkyIsFalling + // release-small + \\error: TheSkyIsFalling \\ }, ); cases.addCase( "try return", source_try_return, - [][]const u8{ - // debug - \\error: TheSkyIsFalling + [_][]const u8{ + // debug + \\error: TheSkyIsFalling \\source.zig:4:5: [address] in _foo (test.o) \\source.zig:8:5: [address] in _main.0 (test.o) \\ , - // release-safe - \\error: TheSkyIsFalling + // release-safe + \\error: TheSkyIsFalling \\source.zig:4:5: [address] in _main (test.o) \\source.zig:8:5: [address] in _main (test.o) \\ , - // release-fast - \\error: TheSkyIsFalling + // release-fast + \\error: TheSkyIsFalling \\ , - // release-small - \\error: TheSkyIsFalling + // release-small + \\error: TheSkyIsFalling \\ }, ); cases.addCase( "try try return return", source_try_try_return_return, - [][]const u8{ - // debug - \\error: TheSkyIsFalling + [_][]const u8{ + // debug + \\error: TheSkyIsFalling \\source.zig:12:5: [address] in _make_error (test.o) \\source.zig:8:5: [address] in _bar (test.o) \\source.zig:4:5: [address] in _foo (test.o) \\source.zig:16:5: [address] in _main.0 (test.o) \\ , - // release-safe - \\error: TheSkyIsFalling + // release-safe + \\error: TheSkyIsFalling \\source.zig:12:5: [address] in _main (test.o) \\source.zig:8:5: [address] in _main (test.o) \\source.zig:4:5: [address] in _main (test.o) \\source.zig:16:5: [address] in _main (test.o) \\ , - // release-fast - \\error: TheSkyIsFalling + // release-fast + \\error: TheSkyIsFalling \\ , - // release-small - \\error: TheSkyIsFalling + // release-small + \\error: TheSkyIsFalling \\ }, ); @@ -204,70 +204,67 @@ pub fn addCases(cases: *tests.ComparePanicContext) void { cases.addCase( "return", source_return, - [][]const u8{ - // debug - \\error: TheSkyIsFalling + [_][]const u8{ + // debug + \\error: TheSkyIsFalling \\source.zig:4:5: [address] in main (test.obj) \\ , - // release-safe - // --disabled-- results in segmenetation fault - "" - , - // release-fast - \\error: TheSkyIsFalling + // release-safe + // --disabled-- results in segmenetation fault + "", + // release-fast + \\error: TheSkyIsFalling \\ , - // release-small - \\error: TheSkyIsFalling + // release-small + \\error: TheSkyIsFalling \\ }, ); cases.addCase( "try return", source_try_return, - [][]const u8{ - // debug - \\error: TheSkyIsFalling + [_][]const u8{ + // debug + \\error: TheSkyIsFalling \\source.zig:4:5: [address] in foo (test.obj) \\source.zig:8:5: [address] in main (test.obj) \\ , - // release-safe - // --disabled-- results in segmenetation fault - "" - , - // release-fast - \\error: TheSkyIsFalling + // release-safe + // --disabled-- results in segmenetation fault + "", + // release-fast + \\error: TheSkyIsFalling \\ , - // release-small - \\error: TheSkyIsFalling + // release-small + \\error: TheSkyIsFalling \\ }, ); cases.addCase( "try try return return", source_try_try_return_return, - [][]const u8{ - // debug - \\error: TheSkyIsFalling + [_][]const u8{ + // debug + \\error: TheSkyIsFalling \\source.zig:12:5: [address] in make_error (test.obj) \\source.zig:8:5: [address] in bar (test.obj) \\source.zig:4:5: [address] in foo (test.obj) \\source.zig:16:5: [address] in main (test.obj) \\ , - // release-safe - // --disabled-- results in segmenetation fault - "" - , - // release-fast - \\error: TheSkyIsFalling + // release-safe + // --disabled-- results in segmenetation fault + "", + // release-fast + \\error: TheSkyIsFalling \\ , - // release-small - \\error: TheSkyIsFalling + // release-small + \\error: TheSkyIsFalling \\ }, ); diff --git a/test/tests.zig b/test/tests.zig index 1bb9e417e5ab41f6f5c0053571726000b0b19953..754407df9a8aaae633b98b275a1923922e103d33 100644 --- a/test/tests.zig +++ b/test/tests.zig @@ -16,7 +16,7 @@ const LibExeObjStep = build.LibExeObjStep; const compare_output = @import("compare_output.zig"); const standalone = @import("standalone.zig"); -const compare_panic = @import("compare_panic.zig"); +const compare_panic = @import("compare_traces.zig"); const compile_errors = @import("compile_errors.zig"); const assemble_and_link = @import("assemble_and_link.zig"); const runtime_safety = @import("runtime_safety.zig"); @@ -58,11 +58,11 @@ pub fn addCompareOutputTests(b: *build.Builder, test_filter: ?[]const u8, modes: return cases.step; } -pub fn addComparePanicTests(b: *build.Builder, test_filter: ?[]const u8, modes: []const Mode) *build.Step { - const cases = b.allocator.create(ComparePanicContext) catch unreachable; - cases.* = ComparePanicContext{ +pub fn addCompareStackTracesTests(b: *build.Builder, test_filter: ?[]const u8, modes: []const Mode) *build.Step { + const cases = b.allocator.create(CompareStackTracesContext) catch unreachable; + cases.* = CompareStackTracesContext{ .b = b, - .step = b.step("test-compare-panic", "Run the compare panic tests"), + .step = b.step("test-compare-traces", "Run the compare stack traces tests"), .test_index = 0, .test_filter = test_filter, .modes = modes, @@ -565,7 +565,7 @@ pub const CompareOutputContext = struct { } }; -pub const ComparePanicContext = struct { +pub const CompareStackTracesContext = struct { b: *build.Builder, step: *build.Step, test_index: usize, @@ -575,7 +575,7 @@ pub const ComparePanicContext = struct { const Expect = [@typeInfo(Mode).Enum.fields.len][]const u8; pub fn addCase( - self: *ComparePanicContext, + self: *CompareStackTracesContext, name: []const u8, source: []const u8, expect: Expect, @@ -584,14 +584,14 @@ pub const ComparePanicContext = struct { const source_pathname = fs.path.join( b.allocator, - [][]const u8{ b.cache_root, "source.zig" }, + [_][]const u8{ b.cache_root, "source.zig" }, ) catch unreachable; for (self.modes) |mode| { const expect_for_mode = expect[@enumToInt(mode)]; if (expect_for_mode.len == 0) continue; - const annotated_case_name = fmt.allocPrint(self.b.allocator, "{} {} ({})", "compare-panic", name, @tagName(mode)) catch unreachable; + const annotated_case_name = fmt.allocPrint(self.b.allocator, "{} {} ({})", "compare-stack-traces", name, @tagName(mode)) catch unreachable; if (self.test_filter) |filter| { if (mem.indexOf(u8, annotated_case_name, filter) == null) continue; } @@ -616,7 +616,7 @@ pub const ComparePanicContext = struct { const RunAndCompareStep = struct { step: build.Step, - context: *ComparePanicContext, + context: *CompareStackTracesContext, exe: *LibExeObjStep, name: []const u8, mode: Mode, @@ -624,7 +624,7 @@ pub const ComparePanicContext = struct { test_index: usize, pub fn create( - context: *ComparePanicContext, + context: *CompareStackTracesContext, exe: *LibExeObjStep, name: []const u8, mode: Mode, @@ -633,7 +633,7 @@ pub const ComparePanicContext = struct { const allocator = context.b.allocator; const ptr = allocator.create(RunAndCompareStep) catch unreachable; ptr.* = RunAndCompareStep{ - .step = build.Step.init("PanicCompareOutputStep", allocator, make), + .step = build.Step.init("StackTraceCompareOutputStep", allocator, make), .context = context, .exe = exe, .name = name, @@ -718,8 +718,8 @@ pub const ComparePanicContext = struct { var it = mem.separate(bytes, "\n"); process_lines: while (it.next()) |line| { if (line.len == 0) continue; - const delims = []const []const u8{ ":", ":", ":", " in " }; - var marks = []usize{0} ** 4; + const delims = [_][]const u8{ ":", ":", ":", " in " }; + var marks = [_]usize{0} ** 4; // offset search past `[drive]:` on windows var pos: usize = if (builtin.os == .windows) 2 else 0; for (delims) |delim, i| { -- 2.54.0 From aba67ecf4475a72035b60dbc0284c2076600f2e1 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 3 Sep 2019 10:08:39 -0400 Subject: [PATCH 22/80] rename test-compare-panic to test-stack-traces --- build.zig | 2 +- test/{compare_traces.zig => stack_traces.zig} | 2 +- test/tests.zig | 22 +++++++++---------- 3 files changed, 13 insertions(+), 13 deletions(-) rename test/{compare_traces.zig => stack_traces.zig} (99%) diff --git a/build.zig b/build.zig index f8c095e8250f4c48a62a403537d8c3425eb1abc8..21fa79e863c78cb2796ef6b210aefd2b8d028d07 100644 --- a/build.zig +++ b/build.zig @@ -138,7 +138,7 @@ pub fn build(b: *Builder) !void { test_step.dependOn(tests.addCompareOutputTests(b, test_filter, modes)); test_step.dependOn(tests.addStandaloneTests(b, test_filter, modes)); - test_step.dependOn(tests.addCompareStackTracesTests(b, test_filter, modes)); + test_step.dependOn(tests.addStackTraceTests(b, test_filter, modes)); test_step.dependOn(tests.addCliTests(b, test_filter, modes)); test_step.dependOn(tests.addAssembleAndLinkTests(b, test_filter, modes)); test_step.dependOn(tests.addRuntimeSafetyTests(b, test_filter, modes)); diff --git a/test/compare_traces.zig b/test/stack_traces.zig similarity index 99% rename from test/compare_traces.zig rename to test/stack_traces.zig index 3de0fb680a650aa080064935effc55f90326d491..1a014f07cc221dde90bdd7734d47ebce3d433f70 100644 --- a/test/compare_traces.zig +++ b/test/stack_traces.zig @@ -3,7 +3,7 @@ const std = @import("std"); const os = std.os; const tests = @import("tests.zig"); -pub fn addCases(cases: *tests.CompareStackTracesContext) void { +pub fn addCases(cases: *tests.StackTracesContext) void { const source_return = \\const std = @import("std"); \\ diff --git a/test/tests.zig b/test/tests.zig index 754407df9a8aaae633b98b275a1923922e103d33..99ee5949c3546a66a52fe344ccfa21864ec163b8 100644 --- a/test/tests.zig +++ b/test/tests.zig @@ -16,7 +16,7 @@ const LibExeObjStep = build.LibExeObjStep; const compare_output = @import("compare_output.zig"); const standalone = @import("standalone.zig"); -const compare_panic = @import("compare_traces.zig"); +const stack_traces = @import("stack_traces.zig"); const compile_errors = @import("compile_errors.zig"); const assemble_and_link = @import("assemble_and_link.zig"); const runtime_safety = @import("runtime_safety.zig"); @@ -58,17 +58,17 @@ pub fn addCompareOutputTests(b: *build.Builder, test_filter: ?[]const u8, modes: return cases.step; } -pub fn addCompareStackTracesTests(b: *build.Builder, test_filter: ?[]const u8, modes: []const Mode) *build.Step { - const cases = b.allocator.create(CompareStackTracesContext) catch unreachable; - cases.* = CompareStackTracesContext{ +pub fn addStackTraceTests(b: *build.Builder, test_filter: ?[]const u8, modes: []const Mode) *build.Step { + const cases = b.allocator.create(StackTracesContext) catch unreachable; + cases.* = StackTracesContext{ .b = b, - .step = b.step("test-compare-traces", "Run the compare stack traces tests"), + .step = b.step("test-stack-traces", "Run the stack trace tests"), .test_index = 0, .test_filter = test_filter, .modes = modes, }; - compare_panic.addCases(cases); + stack_traces.addCases(cases); return cases.step; } @@ -565,7 +565,7 @@ pub const CompareOutputContext = struct { } }; -pub const CompareStackTracesContext = struct { +pub const StackTracesContext = struct { b: *build.Builder, step: *build.Step, test_index: usize, @@ -575,7 +575,7 @@ pub const CompareStackTracesContext = struct { const Expect = [@typeInfo(Mode).Enum.fields.len][]const u8; pub fn addCase( - self: *CompareStackTracesContext, + self: *StackTracesContext, name: []const u8, source: []const u8, expect: Expect, @@ -591,7 +591,7 @@ pub const CompareStackTracesContext = struct { const expect_for_mode = expect[@enumToInt(mode)]; if (expect_for_mode.len == 0) continue; - const annotated_case_name = fmt.allocPrint(self.b.allocator, "{} {} ({})", "compare-stack-traces", name, @tagName(mode)) catch unreachable; + const annotated_case_name = fmt.allocPrint(self.b.allocator, "{} {} ({})", "stack-trace", name, @tagName(mode)) catch unreachable; if (self.test_filter) |filter| { if (mem.indexOf(u8, annotated_case_name, filter) == null) continue; } @@ -616,7 +616,7 @@ pub const CompareStackTracesContext = struct { const RunAndCompareStep = struct { step: build.Step, - context: *CompareStackTracesContext, + context: *StackTracesContext, exe: *LibExeObjStep, name: []const u8, mode: Mode, @@ -624,7 +624,7 @@ pub const CompareStackTracesContext = struct { test_index: usize, pub fn create( - context: *CompareStackTracesContext, + context: *StackTracesContext, exe: *LibExeObjStep, name: []const u8, mode: Mode, -- 2.54.0 From e9530ce97bbbda9724dce3d6755217fd7880955c Mon Sep 17 00:00:00 2001 From: Vesa Kaihlavirta Date: Sun, 1 Sep 2019 13:27:26 +0300 Subject: [PATCH 23/80] Fix addition direction, remove superfluous loop counter, add tests --- std/fmt/parse_float.zig | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/std/fmt/parse_float.zig b/std/fmt/parse_float.zig index ce2cc70768f1b35ef39c2764c4330a0dbebaa5c1..d0a826a55ef62d60c978aabe4ed62d7b32639e51 100644 --- a/std/fmt/parse_float.zig +++ b/std/fmt/parse_float.zig @@ -110,9 +110,7 @@ fn convertRepr(comptime T: type, n: FloatRepr) T { q.shiftLeft1(s); // q = p << 1 r.shiftLeft1(q); // r = p << 2 s.shiftLeft1(r); // p = p << 3 - q.add(s); // p = (p << 3) + (p << 1) - - exp -= 1; + s.add(q); // p = (p << 3) + (p << 1) while (s.d2 & mask28 != 0) { q.shiftRight1(s); @@ -402,6 +400,13 @@ test "fmt.parseFloat" { expectEqual((try parseFloat(T, "+0")), 0.0); expectEqual((try parseFloat(T, "-0")), 0.0); + expectEqual((try parseFloat(T, "0e0")), 0); + expectEqual((try parseFloat(T, "2e3")), 2000.0); + expectEqual((try parseFloat(T, "1e0")), 1.0); + expectEqual((try parseFloat(T, "-2e3")), -2000.0); + expectEqual((try parseFloat(T, "-1e0")), -1.0); + expectEqual((try parseFloat(T, "1.234e3")), 1234); + expect(approxEq(T, try parseFloat(T, "3.141"), 3.141, epsilon)); expect(approxEq(T, try parseFloat(T, "-3.141"), -3.141, epsilon)); @@ -413,6 +418,9 @@ test "fmt.parseFloat" { expectEqual((try parseFloat(T, "-INF")), -std.math.inf(T)); if (T != f16) { + expect(approxEq(T, try parseFloat(T, "1e-2"), 0.01, epsilon)); + expect(approxEq(T, try parseFloat(T, "1234e-2"), 12.34, epsilon)); + expect(approxEq(T, try parseFloat(T, "123142.1"), 123142.1, epsilon)); expect(approxEq(T, try parseFloat(T, "-123142.1124"), T(-123142.1124), epsilon)); expect(approxEq(T, try parseFloat(T, "0.7062146892655368"), T(0.7062146892655368), epsilon)); -- 2.54.0 From e673d865fb2dfa6588505d572765ea8c5b4470ee Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 3 Sep 2019 13:02:46 -0400 Subject: [PATCH 24/80] fix stack traces on macos when passing absolute path to root source file The comment added by this commit is copied here: For macOS stack traces, we want to avoid having to parse the compilation unit debug info. As long as each debug info file has a path independent of the compilation unit directory (DW_AT_comp_dir), then we never have to look at the compilation unit debug info. If we provide an absolute path to LLVM here for the compilation unit debug info, LLVM will emit DWARF info that depends on DW_AT_comp_dir. To avoid this, we pass "." for the compilation unit directory. This forces each debug file to have a directory rather than be relative to DW_AT_comp_dir. According to DWARF 5, debug files will no longer reference DW_AT_comp_dir, for the purpose of being able to support the common practice of stripping all but the line number sections from an executable. closes #2700 --- src/codegen.cpp | 15 ++++++++++++++- src/zig_llvm.cpp | 1 + 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/codegen.cpp b/src/codegen.cpp index b694923873a51f8a8f206e282dfecf6558c94f19..293066afd50c54af72c690d0adae0d85b1b33404 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -8457,8 +8457,21 @@ static void init(CodeGen *g) { Buf *producer = buf_sprintf("zig %d.%d.%d", ZIG_VERSION_MAJOR, ZIG_VERSION_MINOR, ZIG_VERSION_PATCH); const char *flags = ""; unsigned runtime_version = 0; + + // For macOS stack traces, we want to avoid having to parse the compilation unit debug + // info. As long as each debug info file has a path independent of the compilation unit + // directory (DW_AT_comp_dir), then we never have to look at the compilation unit debug + // info. If we provide an absolute path to LLVM here for the compilation unit debug info, + // LLVM will emit DWARF info that depends on DW_AT_comp_dir. To avoid this, we pass "." + // for the compilation unit directory. This forces each debug file to have a directory + // rather than be relative to DW_AT_comp_dir. According to DWARF 5, debug files will + // no longer reference DW_AT_comp_dir, for the purpose of being able to support the + // common practice of stripping all but the line number sections from an executable. + const char *compile_unit_dir = target_os_is_darwin(g->zig_target->os) ? "." : + buf_ptr(&g->root_package->root_src_dir); + ZigLLVMDIFile *compile_unit_file = ZigLLVMCreateFile(g->dbuilder, buf_ptr(g->root_out_name), - buf_ptr(&g->root_package->root_src_dir)); + compile_unit_dir); g->compile_unit = ZigLLVMCreateCompileUnit(g->dbuilder, ZigLLVMLang_DW_LANG_C99(), compile_unit_file, buf_ptr(producer), is_optimized, flags, runtime_version, "", 0, !g->strip_debug_symbols); diff --git a/src/zig_llvm.cpp b/src/zig_llvm.cpp index c19abbbac8f18bb08edc14a02d812240cf5d6812..4f25cd3b98803f9ea8b46fabf978c53008523b14 100644 --- a/src/zig_llvm.cpp +++ b/src/zig_llvm.cpp @@ -842,6 +842,7 @@ const char *ZigLLVMGetSubArchTypeName(ZigLLVM_SubArchType sub_arch) { void ZigLLVMAddModuleDebugInfoFlag(LLVMModuleRef module) { unwrap(module)->addModuleFlag(Module::Warning, "Debug Info Version", DEBUG_METADATA_VERSION); + unwrap(module)->addModuleFlag(Module::Warning, "Dwarf Version", 4); } void ZigLLVMAddModuleCodeViewFlag(LLVMModuleRef module) { -- 2.54.0 From be17a4b6c1be11eb4b75db1972a38fc50875ebed Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 3 Sep 2019 14:51:34 -0400 Subject: [PATCH 25/80] fix compiler crash in struct field pointers when the llvm type has not been fully analyzed. This is a regression from lazy values. --- src/codegen.cpp | 7 +++++++ test/stage1/behavior/struct.zig | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/src/codegen.cpp b/src/codegen.cpp index 293066afd50c54af72c690d0adae0d85b1b33404..1710a3b3fd65c77dc91688aad1d1fa14817d3d1d 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -4113,6 +4113,8 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr static LLVMValueRef ir_render_struct_field_ptr(CodeGen *g, IrExecutable *executable, IrInstructionStructFieldPtr *instruction) { + Error err; + if (instruction->base.value.special != ConstValSpecialRuntime) return nullptr; @@ -4130,6 +4132,11 @@ static LLVMValueRef ir_render_struct_field_ptr(CodeGen *g, IrExecutable *executa return struct_ptr; } + ZigType *struct_type = (struct_ptr_type->id == ZigTypeIdPointer) ? + struct_ptr_type->data.pointer.child_type : struct_ptr_type; + if ((err = type_resolve(g, struct_type, ResolveStatusLLVMFull))) + report_errors_and_exit(g); + assert(field->gen_index != SIZE_MAX); return LLVMBuildStructGEP(g->builder, struct_ptr, (unsigned)field->gen_index, ""); } diff --git a/test/stage1/behavior/struct.zig b/test/stage1/behavior/struct.zig index b86b171daf42cf9c3454281178de00a2f0c942e9..0befe4f620d8ddab4dfef9e09780d01e0e7c4ff9 100644 --- a/test/stage1/behavior/struct.zig +++ b/test/stage1/behavior/struct.zig @@ -599,3 +599,36 @@ test "extern fn returns struct by value" { S.entry(); comptime S.entry(); } + +test "for loop over pointers to struct, getting field from struct pointer" { + const S = struct { + const Foo = struct { + name: []const u8, + }; + + var ok = true; + + fn eql(a: []const u8) bool { + return true; + } + + const ArrayList = struct { + fn toSlice(self: *ArrayList) []*Foo { + return ([*]*Foo)(undefined)[0..0]; + } + }; + + fn doTheTest() void { + var objects: ArrayList = undefined; + + for (objects.toSlice()) |obj| { + if (eql(obj.name)) { + ok = false; + } + } + + expect(ok); + } + }; + S.doTheTest(); +} -- 2.54.0 From fc0f8d0359777580c771848361166f97a85deddd Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 3 Sep 2019 16:19:10 -0400 Subject: [PATCH 26/80] zig build: make install prefix available to build.zig and prevent accident of '/' showing up in application/library names --- std/build.zig | 32 ++++++++++++++++++-------------- std/special/build_runner.zig | 2 ++ 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/std/build.zig b/std/build.zig index 27715663f7d936c41dd1516bbda501b6d7d0cced..1ca808c505112982b04563ddf0abc29a4ad2d5f0 100644 --- a/std/build.zig +++ b/std/build.zig @@ -4,6 +4,7 @@ const io = std.io; const fs = std.fs; const mem = std.mem; const debug = std.debug; +const panic = std.debug.panic; const assert = debug.assert; const warn = std.debug.warn; const ArrayList = std.ArrayList; @@ -42,8 +43,8 @@ pub const Builder = struct { top_level_steps: ArrayList(*TopLevelStep), install_prefix: ?[]const u8, dest_dir: ?[]const u8, - lib_dir: ?[]const u8, - exe_dir: ?[]const u8, + lib_dir: []const u8, + exe_dir: []const u8, install_path: []const u8, search_prefixes: ArrayList([]const u8), installed_files: ArrayList(InstalledFile), @@ -129,8 +130,8 @@ pub const Builder = struct { .env_map = env_map, .search_prefixes = ArrayList([]const u8).init(allocator), .install_prefix = null, - .lib_dir = null, - .exe_dir = null, + .lib_dir = undefined, + .exe_dir = undefined, .dest_dir = env_map.get("DESTDIR"), .installed_files = ArrayList(InstalledFile).init(allocator), .install_tls = TopLevelStep{ @@ -163,11 +164,13 @@ pub const Builder = struct { self.allocator.destroy(self); } + /// This function is intended to be called by std/special/build_runner.zig, not a build.zig file. pub fn setInstallPrefix(self: *Builder, optional_prefix: ?[]const u8) void { self.install_prefix = optional_prefix; } - fn resolveInstallPrefix(self: *Builder) void { + /// This function is intended to be called by std/special/build_runner.zig, not a build.zig file. + pub fn resolveInstallPrefix(self: *Builder) void { if (self.dest_dir) |dest_dir| { const install_prefix = self.install_prefix orelse "/usr"; self.install_path = fs.path.join(self.allocator, [_][]const u8{ dest_dir, install_prefix }) catch unreachable; @@ -437,7 +440,7 @@ pub const Builder = struct { .description = description, }; if ((self.available_options_map.put(name, available_option) catch unreachable) != null) { - debug.panic("Option '{}' declared twice", name); + panic("Option '{}' declared twice", name); } self.available_options_list.append(available_option) catch unreachable; @@ -463,8 +466,8 @@ pub const Builder = struct { return null; }, }, - TypeId.Int => debug.panic("TODO integer options to build script"), - TypeId.Float => debug.panic("TODO float options to build script"), + TypeId.Int => panic("TODO integer options to build script"), + TypeId.Float => panic("TODO float options to build script"), TypeId.String => switch (entry.value.value) { UserValue.Flag => { warn("Expected -D{} to be a string, but received a boolean.\n", name); @@ -478,7 +481,7 @@ pub const Builder = struct { }, UserValue.Scalar => |s| return s, }, - TypeId.List => debug.panic("TODO list options to build script"), + TypeId.List => panic("TODO list options to build script"), } } @@ -644,8 +647,6 @@ pub const Builder = struct { } pub fn validateUserInputDidItFail(self: *Builder) bool { - self.resolveInstallPrefix(); - // make sure all args are used var it = self.user_input_options.iterator(); while (true) { @@ -855,7 +856,7 @@ pub const Builder = struct { var stdout_file_in_stream = child.stdout.?.inStream(); try stdout_file_in_stream.stream.readAllBuffer(&stdout, max_output_size); - const term = child.wait() catch |err| std.debug.panic("unable to spawn {}: {}", argv[0], err); + const term = child.wait() catch |err| panic("unable to spawn {}: {}", argv[0], err); switch (term) { .Exited => |code| { if (code != 0) { @@ -882,8 +883,8 @@ pub const Builder = struct { fn getInstallPath(self: *Builder, dir: InstallDir, dest_rel_path: []const u8) []const u8 { const base_dir = switch (dir) { .Prefix => self.install_path, - .Bin => self.exe_dir.?, - .Lib => self.lib_dir.?, + .Bin => self.exe_dir, + .Lib => self.lib_dir, }; return fs.path.resolve( self.allocator, @@ -1318,6 +1319,9 @@ pub const LibExeObjStep = struct { } fn initExtraArgs(builder: *Builder, name: []const u8, root_src: ?[]const u8, kind: Kind, is_dynamic: bool, ver: Version) LibExeObjStep { + if (mem.indexOf(u8, name, "/") != null or mem.indexOf(u8, name, "\\") != null) { + panic("invalid name: '{}'. It looks like a file path, but it is supposed to be the library or application name.", name); + } var self = LibExeObjStep{ .strip = false, .builder = builder, diff --git a/std/special/build_runner.zig b/std/special/build_runner.zig index 4933faca8a22bce38e7f9e1950b64a8acc177c7b..01e307d46e1af16522a1ef0aaf08f51b3336e537 100644 --- a/std/special/build_runner.zig +++ b/std/special/build_runner.zig @@ -123,6 +123,7 @@ pub fn main() !void { } } + builder.resolveInstallPrefix(); try runBuild(builder); if (builder.validateUserInputDidItFail()) @@ -151,6 +152,7 @@ fn usage(builder: *Builder, already_ran_build: bool, out_stream: var) !void { // run the build script to collect the options if (!already_ran_build) { builder.setInstallPrefix(null); + builder.resolveInstallPrefix(); try runBuild(builder); } -- 2.54.0 From f08c6e4fe6ad63145ef69377f36f34e9f04cadec Mon Sep 17 00:00:00 2001 From: Sahnvour Date: Tue, 3 Sep 2019 23:53:05 +0200 Subject: [PATCH 27/80] changing occurrences of HashMap with []const u8 as keys for StringHashMap --- doc/docgen.zig | 4 ++-- src-self-hosted/arg.zig | 4 ++-- src-self-hosted/compilation.zig | 2 +- src-self-hosted/decl.zig | 2 +- src-self-hosted/main.zig | 2 +- src-self-hosted/package.zig | 2 +- src-self-hosted/stage1.zig | 4 ++-- std/buf_map.zig | 4 ++-- std/buf_set.zig | 4 ++-- std/build.zig | 6 +++--- std/json.zig | 4 ++-- std/mem.zig | 37 +++++++++++---------------------- 12 files changed, 31 insertions(+), 44 deletions(-) diff --git a/doc/docgen.zig b/doc/docgen.zig index 458b97d2c04c3ce49c9b07e11cce21c55fa5ce29..a2b4e8501c93478e8ef19697e79a932b9c801ea3 100644 --- a/doc/docgen.zig +++ b/doc/docgen.zig @@ -307,7 +307,7 @@ const Node = union(enum) { const Toc = struct { nodes: []Node, toc: []u8, - urls: std.HashMap([]const u8, Token, mem.hash_slice_u8, mem.eql_slice_u8), + urls: std.StringHashMap(Token), }; const Action = enum { @@ -316,7 +316,7 @@ const Action = enum { }; fn genToc(allocator: *mem.Allocator, tokenizer: *Tokenizer) !Toc { - var urls = std.HashMap([]const u8, Token, mem.hash_slice_u8, mem.eql_slice_u8).init(allocator); + var urls = std.StringHashMap(Token).init(allocator); errdefer urls.deinit(); var header_stack_size: usize = 0; diff --git a/src-self-hosted/arg.zig b/src-self-hosted/arg.zig index 8f95e2d7ef76a11ac145898f9ad950041cb81778..8b0ea5ea6185ef68adb1d26befda601b2872913c 100644 --- a/src-self-hosted/arg.zig +++ b/src-self-hosted/arg.zig @@ -5,7 +5,7 @@ const mem = std.mem; const Allocator = mem.Allocator; const ArrayList = std.ArrayList; -const HashMap = std.HashMap; +const StringHashMap = std.StringHashMap; fn trimStart(slice: []const u8, ch: u8) []const u8 { var i: usize = 0; @@ -73,7 +73,7 @@ fn readFlagArguments(allocator: *Allocator, args: []const []const u8, required: } } -const HashMapFlags = HashMap([]const u8, FlagArg, std.hash.Fnv1a_32.hash, mem.eql_slice_u8); +const HashMapFlags = StringHashMap(FlagArg); // A store for querying found flags and positional arguments. pub const Args = struct { diff --git a/src-self-hosted/compilation.zig b/src-self-hosted/compilation.zig index a64e52a2b628558e0f3b905c9591ee5017c52a49..1e71a5e561a88fd2f9b7564b597b956a14120ae8 100644 --- a/src-self-hosted/compilation.zig +++ b/src-self-hosted/compilation.zig @@ -249,7 +249,7 @@ pub const Compilation = struct { const ArrayTypeTable = std.HashMap(*const Type.Array.Key, *Type.Array, Type.Array.Key.hash, Type.Array.Key.eql); const PtrTypeTable = std.HashMap(*const Type.Pointer.Key, *Type.Pointer, Type.Pointer.Key.hash, Type.Pointer.Key.eql); const FnTypeTable = std.HashMap(*const Type.Fn.Key, *Type.Fn, Type.Fn.Key.hash, Type.Fn.Key.eql); - const TypeTable = std.HashMap([]const u8, *Type, mem.hash_slice_u8, mem.eql_slice_u8); + const TypeTable = std.StringHashMap(*Type); const CompileErrList = std.ArrayList(*Msg); diff --git a/src-self-hosted/decl.zig b/src-self-hosted/decl.zig index 25fcf195d1adbc738a756957d23ebe3d961ec660..1af06dea3988d336e05918aa626a12d2acb9c626 100644 --- a/src-self-hosted/decl.zig +++ b/src-self-hosted/decl.zig @@ -20,7 +20,7 @@ pub const Decl = struct { // TODO when we destroy the decl, deref the tree scope tree_scope: *Scope.AstTree, - pub const Table = std.HashMap([]const u8, *Decl, mem.hash_slice_u8, mem.eql_slice_u8); + pub const Table = std.StringHashMap(*Decl); pub fn cast(base: *Decl, comptime T: type) ?*T { if (base.id != @field(Id, @typeName(T))) return null; diff --git a/src-self-hosted/main.zig b/src-self-hosted/main.zig index 5136b32735020dbdec0475aeeb0230e8082754a1..52eda5824aef40a55f2e8f926071eb3a43d36f7d 100644 --- a/src-self-hosted/main.zig +++ b/src-self-hosted/main.zig @@ -541,7 +541,7 @@ const Fmt = struct { color: errmsg.Color, loop: *event.Loop, - const SeenMap = std.HashMap([]const u8, void, mem.hash_slice_u8, mem.eql_slice_u8); + const SeenMap = std.StringHashMap(void); }; fn parseLibcPaths(allocator: *Allocator, libc: *LibCInstallation, libc_paths_file: []const u8) void { diff --git a/src-self-hosted/package.zig b/src-self-hosted/package.zig index 0d31731b551e6dd730aaf379c989dc3a8f098244..c8d46c771976f4d86ba663c9faa441ea12e4399d 100644 --- a/src-self-hosted/package.zig +++ b/src-self-hosted/package.zig @@ -10,7 +10,7 @@ pub const Package = struct { /// relative to root_src_dir table: Table, - pub const Table = std.HashMap([]const u8, *Package, mem.hash_slice_u8, mem.eql_slice_u8); + pub const Table = std.StringHashMap(*Package); /// makes internal copies of root_src_dir and root_src_path /// allocator should be an arena allocator because Package never frees anything diff --git a/src-self-hosted/stage1.zig b/src-self-hosted/stage1.zig index b8f13b5d03746eacb88e31a5a9bbadb8297084cc..2f48f2f45076e4ad3d844689c2a09e97826ea974 100644 --- a/src-self-hosted/stage1.zig +++ b/src-self-hosted/stage1.zig @@ -343,7 +343,7 @@ const Fmt = struct { color: errmsg.Color, allocator: *mem.Allocator, - const SeenMap = std.HashMap([]const u8, void, mem.hash_slice_u8, mem.eql_slice_u8); + const SeenMap = std.StringHashMap(void); }; fn printErrMsgToFile( @@ -376,7 +376,7 @@ fn printErrMsgToFile( const text = text_buf.toOwnedSlice(); const stream = &file.outStream().stream; - try stream.print( "{}:{}:{}: error: {}\n", path, start_loc.line + 1, start_loc.column + 1, text); + try stream.print("{}:{}:{}: error: {}\n", path, start_loc.line + 1, start_loc.column + 1, text); if (!color_on) return; diff --git a/std/buf_map.zig b/std/buf_map.zig index 4079d41caf1c94fea99ab75b5158a583ccdf6230..d7aa314157b4aa895bef516c874d9de7c4ed1996 100644 --- a/std/buf_map.zig +++ b/std/buf_map.zig @@ -1,5 +1,5 @@ const std = @import("std.zig"); -const HashMap = std.HashMap; +const StringHashMap = std.StringHashMap; const mem = std.mem; const Allocator = mem.Allocator; const testing = std.testing; @@ -9,7 +9,7 @@ const testing = std.testing; pub const BufMap = struct { hash_map: BufMapHashMap, - const BufMapHashMap = HashMap([]const u8, []const u8, mem.hash_slice_u8, mem.eql_slice_u8); + const BufMapHashMap = StringHashMap([]const u8); pub fn init(allocator: *Allocator) BufMap { var self = BufMap{ .hash_map = BufMapHashMap.init(allocator) }; diff --git a/std/buf_set.zig b/std/buf_set.zig index 33e66a64e86b3f95d08732dbc5e15c8678d02bb4..1a321e89c9eb6ca8ff2ac5b4fa7c176059d46cb4 100644 --- a/std/buf_set.zig +++ b/std/buf_set.zig @@ -1,5 +1,5 @@ const std = @import("std.zig"); -const HashMap = @import("hash_map.zig").HashMap; +const StringHashMap = std.StringHashMap; const mem = @import("mem.zig"); const Allocator = mem.Allocator; const testing = std.testing; @@ -7,7 +7,7 @@ const testing = std.testing; pub const BufSet = struct { hash_map: BufSetHashMap, - const BufSetHashMap = HashMap([]const u8, void, mem.hash_slice_u8, mem.eql_slice_u8); + const BufSetHashMap = StringHashMap(void); pub fn init(a: *Allocator) BufSet { var self = BufSet{ .hash_map = BufSetHashMap.init(a) }; diff --git a/std/build.zig b/std/build.zig index 27715663f7d936c41dd1516bbda501b6d7d0cced..0049dcd035b1931f1bc01429f7b5956c4f838852 100644 --- a/std/build.zig +++ b/std/build.zig @@ -7,7 +7,7 @@ const debug = std.debug; const assert = debug.assert; const warn = std.debug.warn; const ArrayList = std.ArrayList; -const HashMap = std.HashMap; +const StringHashMap = std.StringHashMap; const Allocator = mem.Allocator; const process = std.process; const BufSet = std.BufSet; @@ -60,8 +60,8 @@ pub const Builder = struct { C11, }; - const UserInputOptionsMap = HashMap([]const u8, UserInputOption, mem.hash_slice_u8, mem.eql_slice_u8); - const AvailableOptionsMap = HashMap([]const u8, AvailableOption, mem.hash_slice_u8, mem.eql_slice_u8); + const UserInputOptionsMap = StringHashMap(UserInputOption); + const AvailableOptionsMap = StringHashMap(AvailableOption); const AvailableOption = struct { name: []const u8, diff --git a/std/json.zig b/std/json.zig index 8324c59e32657f0c8e4c5c0ad0b3f2c5966a3d71..f562a672f86d5bdfbe35ab7930903ecdef7d236c 100644 --- a/std/json.zig +++ b/std/json.zig @@ -989,7 +989,7 @@ test "json.validate" { const Allocator = std.mem.Allocator; const ArenaAllocator = std.heap.ArenaAllocator; const ArrayList = std.ArrayList; -const HashMap = std.HashMap; +const StringHashMap = std.StringHashMap; pub const ValueTree = struct { arena: ArenaAllocator, @@ -1000,7 +1000,7 @@ pub const ValueTree = struct { } }; -pub const ObjectMap = HashMap([]const u8, Value, mem.hash_slice_u8, mem.eql_slice_u8); +pub const ObjectMap = StringHashMap(Value); pub const Value = union(enum) { Null, diff --git a/std/mem.zig b/std/mem.zig index 61dc5c7a30e3b1ed7955ce0efced5dc411ae6f9e..62a1ae886af184c9005211914c37f17f02270df4 100644 --- a/std/mem.zig +++ b/std/mem.zig @@ -738,47 +738,34 @@ test "writeIntBig and writeIntLittle" { var buf9: [9]u8 = undefined; writeIntBig(u0, &buf0, 0x0); - testing.expect(eql_slice_u8(buf0[0..], [_]u8{})); + testing.expect(eql(u8, buf0[0..], [_]u8{})); writeIntLittle(u0, &buf0, 0x0); - testing.expect(eql_slice_u8(buf0[0..], [_]u8{})); + testing.expect(eql(u8, buf0[0..], [_]u8{})); writeIntBig(u8, &buf1, 0x12); - testing.expect(eql_slice_u8(buf1[0..], [_]u8{0x12})); + testing.expect(eql(u8, buf1[0..], [_]u8{0x12})); writeIntLittle(u8, &buf1, 0x34); - testing.expect(eql_slice_u8(buf1[0..], [_]u8{0x34})); + testing.expect(eql(u8, buf1[0..], [_]u8{0x34})); writeIntBig(u16, &buf2, 0x1234); - testing.expect(eql_slice_u8(buf2[0..], [_]u8{ 0x12, 0x34 })); + testing.expect(eql(u8, buf2[0..], [_]u8{ 0x12, 0x34 })); writeIntLittle(u16, &buf2, 0x5678); - testing.expect(eql_slice_u8(buf2[0..], [_]u8{ 0x78, 0x56 })); + testing.expect(eql(u8, buf2[0..], [_]u8{ 0x78, 0x56 })); writeIntBig(u72, &buf9, 0x123456789abcdef024); - testing.expect(eql_slice_u8(buf9[0..], [_]u8{ 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x24 })); + testing.expect(eql(u8, buf9[0..], [_]u8{ 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x24 })); writeIntLittle(u72, &buf9, 0xfedcba9876543210ec); - testing.expect(eql_slice_u8(buf9[0..], [_]u8{ 0xec, 0x10, 0x32, 0x54, 0x76, 0x98, 0xba, 0xdc, 0xfe })); + testing.expect(eql(u8, buf9[0..], [_]u8{ 0xec, 0x10, 0x32, 0x54, 0x76, 0x98, 0xba, 0xdc, 0xfe })); writeIntBig(i8, &buf1, -1); - testing.expect(eql_slice_u8(buf1[0..], [_]u8{0xff})); + testing.expect(eql(u8, buf1[0..], [_]u8{0xff})); writeIntLittle(i8, &buf1, -2); - testing.expect(eql_slice_u8(buf1[0..], [_]u8{0xfe})); + testing.expect(eql(u8, buf1[0..], [_]u8{0xfe})); writeIntBig(i16, &buf2, -3); - testing.expect(eql_slice_u8(buf2[0..], [_]u8{ 0xff, 0xfd })); + testing.expect(eql(u8, buf2[0..], [_]u8{ 0xff, 0xfd })); writeIntLittle(i16, &buf2, -4); - testing.expect(eql_slice_u8(buf2[0..], [_]u8{ 0xfc, 0xff })); -} - -pub fn hash_slice_u8(k: []const u8) u32 { - // FNV 32-bit hash - var h: u32 = 2166136261; - for (k) |b| { - h = (h ^ b) *% 16777619; - } - return h; -} - -pub fn eql_slice_u8(a: []const u8, b: []const u8) bool { - return eql(u8, a, b); + testing.expect(eql(u8, buf2[0..], [_]u8{ 0xfc, 0xff })); } /// Returns an iterator that iterates over the slices of `buffer` that are not -- 2.54.0 From 9d6f236728cf433b44048e21f81efdd167fe0098 Mon Sep 17 00:00:00 2001 From: Sahnvour Date: Tue, 3 Sep 2019 23:56:04 +0200 Subject: [PATCH 28/80] add fastpath for std.mem.eql and simplify std.hash_map.eqlString this should also be friendlier to the optimizer --- std/hash_map.zig | 4 +--- std/mem.zig | 1 + 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/std/hash_map.zig b/std/hash_map.zig index 5a852d4302f218b13403c4f7cd011c45727e7d43..4ffe88067b582149010c13df696525824decb43f 100644 --- a/std/hash_map.zig +++ b/std/hash_map.zig @@ -23,9 +23,7 @@ pub fn StringHashMap(comptime V: type) type { } pub fn eqlString(a: []const u8, b: []const u8) bool { - if (a.len != b.len) return false; - if (a.ptr == b.ptr) return true; - return mem.compare(u8, a, b) == .Equal; + return mem.eql(u8, a, b); } pub fn hashString(s: []const u8) u32 { diff --git a/std/mem.zig b/std/mem.zig index 62a1ae886af184c9005211914c37f17f02270df4..2091eb4804f7e7d30c689e6cea495aebdba6d1e5 100644 --- a/std/mem.zig +++ b/std/mem.zig @@ -339,6 +339,7 @@ test "mem.lessThan" { /// Compares two slices and returns whether they are equal. pub fn eql(comptime T: type, a: []const T, b: []const T) bool { if (a.len != b.len) return false; + if (a.ptr == b.ptr) return true; for (a) |item, index| { if (b[index] != item) return false; } -- 2.54.0 From 18620756520d198f581b9a9acbf25c8cbb79ad11 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 3 Sep 2019 18:25:00 -0400 Subject: [PATCH 29/80] fix union field ptr ir instruction --- src/ir.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/ir.cpp b/src/ir.cpp index e3b440d0f5c3a55630be16513467887ca005032b..abf4f477a8c3afb30ba774b292eb04d53dfb4640 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -17464,7 +17464,12 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_ return ir_analyze_container_member_access_inner(ira, bare_type, field_name, source_instr, container_ptr, container_type); } - ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, field->type_entry, + + ZigType *field_type = resolve_union_field_type(ira->codegen, field); + if (field_type == nullptr) + return ira->codegen->invalid_instruction; + + ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, field_type, is_const, is_volatile, PtrLenSingle, 0, 0, 0, false); if (instr_is_comptime(container_ptr)) { ConstExprValue *ptr_val = ir_resolve_const(ira, container_ptr, UndefBad); @@ -17481,7 +17486,7 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_ if (initializing) { ConstExprValue *payload_val = create_const_vals(1); payload_val->special = ConstValSpecialUndef; - payload_val->type = field->type_entry; + payload_val->type = field_type; payload_val->parent.id = ConstParentIdUnion; payload_val->parent.data.p_union.union_val = union_val; -- 2.54.0 From ce14c543d165efbd926ea6bd654d999c625b366f Mon Sep 17 00:00:00 2001 From: Sahnvour Date: Tue, 3 Sep 2019 22:29:04 +0200 Subject: [PATCH 30/80] error message and test for alignment of variables of zero-bit types --- src/analyze.cpp | 4 ++++ src/ir.cpp | 6 ++++++ test/compile_errors.zig | 9 +++++++++ 3 files changed, 19 insertions(+) diff --git a/src/analyze.cpp b/src/analyze.cpp index 188da185150bfe70ad510a150d337dca29d1e6cd..2fd540a64f850441d5ecb7d5dd11625729079add 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -2671,6 +2671,10 @@ static Error resolve_struct_alignment(CodeGen *g, ZigType *struct_type) { } } + if (!type_has_bits(struct_type)) { + assert(struct_type->abi_align == 0); + } + struct_type->data.structure.resolve_loop_flag_other = false; if (struct_type->data.structure.resolve_status == ResolveStatusInvalid) { diff --git a/src/ir.cpp b/src/ir.cpp index abf4f477a8c3afb30ba774b292eb04d53dfb4640..7415a2dd6b182603ad03a71ced0040373fce1a20 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -14839,6 +14839,12 @@ static IrInstruction *ir_analyze_alloca(IrAnalyze *ira, IrInstruction *source_in if (align != 0) { if ((err = type_resolve(ira->codegen, var_type, ResolveStatusAlignmentKnown))) return ira->codegen->invalid_instruction; + if (!type_has_bits(var_type)) { + ir_add_error(ira, source_inst, + buf_sprintf("variable '%s' of zero-bit type '%s' has no in-memory representation, it cannot be aligned", + name_hint, buf_ptr(&var_type->name))); + return ira->codegen->invalid_instruction; + } } assert(result->base.value.data.x_ptr.special != ConstPtrSpecialInvalid); diff --git a/test/compile_errors.zig b/test/compile_errors.zig index 12f17ec790e9fe06a1d3e1fb4c0edfcee6a570f9..871ff63e2365870c70696fdac4ce9d13405496aa 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -6462,4 +6462,13 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { "tmp.zig:5:30: error: expression value is ignored", "tmp.zig:9:30: error: expression value is ignored", ); + + cases.add( + "aligned variable of zero-bit type", + \\export fn f() void { + \\ var s: struct {} align(4) = undefined; + \\} + , + "tmp.zig:2:5: error: variable 's' of zero-bit type 'struct:2:12' has no in-memory representation, it cannot be aligned", + ); } -- 2.54.0 From 77a5f888be664f9ef09e2c93f52338448e992e00 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 3 Sep 2019 22:09:47 -0400 Subject: [PATCH 31/80] emit a compile error if a test becomes async See #3117 --- src/analyze.cpp | 2 +- src/analyze.hpp | 2 ++ src/codegen.cpp | 10 ++++++++++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/analyze.cpp b/src/analyze.cpp index 2fd540a64f850441d5ecb7d5dd11625729079add..e1d6b59ddf0b5e10c109c45e1e34225e3d01c4ba 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -4195,7 +4195,7 @@ bool fn_is_async(ZigFn *fn) { return fn->inferred_async_node != inferred_async_none; } -static void add_async_error_notes(CodeGen *g, ErrorMsg *msg, ZigFn *fn) { +void add_async_error_notes(CodeGen *g, ErrorMsg *msg, ZigFn *fn) { assert(fn->inferred_async_node != nullptr); assert(fn->inferred_async_node != inferred_async_checking); assert(fn->inferred_async_node != inferred_async_none); diff --git a/src/analyze.hpp b/src/analyze.hpp index dc702167e7c4d852bde710deb472fd35cd44c30b..9f2c984992908574c9726b99a7c8ec355a9385dc 100644 --- a/src/analyze.hpp +++ b/src/analyze.hpp @@ -256,4 +256,6 @@ Error type_val_resolve_zero_bits(CodeGen *g, ConstExprValue *type_val, ZigType * ZigType *resolve_union_field_type(CodeGen *g, TypeUnionField *union_field); ZigType *resolve_struct_field_type(CodeGen *g, TypeStructField *struct_field); +void add_async_error_notes(CodeGen *g, ErrorMsg *msg, ZigFn *fn); + #endif diff --git a/src/codegen.cpp b/src/codegen.cpp index 1710a3b3fd65c77dc91688aad1d1fa14817d3d1d..d1499592d2f9264c9fb1e348978caf6c0763ec11 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -8905,6 +8905,15 @@ static void create_test_compile_var_and_add_test_runner(CodeGen *g) { for (size_t i = 0; i < g->test_fns.length; i += 1) { ZigFn *test_fn_entry = g->test_fns.at(i); + if (fn_is_async(test_fn_entry)) { + ErrorMsg *msg = add_node_error(g, test_fn_entry->proto_node, + buf_create_from_str("test functions cannot be async")); + add_error_note(g, msg, test_fn_entry->proto_node, + buf_sprintf("this restriction may be lifted in the future. See https://github.com/ziglang/zig/issues/3117 for more details")); + add_async_error_notes(g, msg, test_fn_entry); + continue; + } + ConstExprValue *this_val = &test_fn_array->data.x_array.data.s_none.elements[i]; this_val->special = ConstValSpecialStatic; this_val->type = struct_type; @@ -8924,6 +8933,7 @@ static void create_test_compile_var_and_add_test_runner(CodeGen *g) { fn_field->data.x_ptr.mut = ConstPtrMutComptimeConst; fn_field->data.x_ptr.data.fn.fn_entry = test_fn_entry; } + report_errors_and_maybe_exit(g); ConstExprValue *test_fn_slice = create_const_slice(g, test_fn_array, 0, g->test_fns.length, true); -- 2.54.0 From b728cb6d4e882592129eef2e37f8fcd8fda78822 Mon Sep 17 00:00:00 2001 From: Jonathan Marler Date: Fri, 23 Aug 2019 09:33:33 -0600 Subject: [PATCH 32/80] Add @Type builtin --- src/all_types.hpp | 8 ++ src/codegen.cpp | 2 + src/ir.cpp | 179 ++++++++++++++++++++++++++++++++++ src/ir_print.cpp | 11 +++ test/compile_errors.zig | 52 ++++++++++ test/stage1/behavior.zig | 1 + test/stage1/behavior/type.zig | 111 +++++++++++++++++++++ 7 files changed, 364 insertions(+) create mode 100644 test/stage1/behavior/type.zig diff --git a/src/all_types.hpp b/src/all_types.hpp index 1a97cf281469d3bc3ae845cb99d405c2ff000f40..4253a346f88719efb3f9249c55280038d8d52ed0 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -1534,6 +1534,7 @@ enum BuiltinFnId { BuiltinFnIdMemberName, BuiltinFnIdField, BuiltinFnIdTypeInfo, + BuiltinFnIdType, BuiltinFnIdHasField, BuiltinFnIdTypeof, BuiltinFnIdAddWithOverflow, @@ -2436,6 +2437,7 @@ enum IrInstructionId { IrInstructionIdByteOffsetOf, IrInstructionIdBitOffsetOf, IrInstructionIdTypeInfo, + IrInstructionIdType, IrInstructionIdHasField, IrInstructionIdTypeId, IrInstructionIdSetEvalBranchQuota, @@ -3472,6 +3474,12 @@ struct IrInstructionTypeInfo { IrInstruction *type_value; }; +struct IrInstructionType { + IrInstruction base; + + IrInstruction *type_info; +}; + struct IrInstructionHasField { IrInstruction base; diff --git a/src/codegen.cpp b/src/codegen.cpp index d1499592d2f9264c9fb1e348978caf6c0763ec11..d7d4b4443711e02382dc02a7609d86b25d02c267 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -5770,6 +5770,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, case IrInstructionIdByteOffsetOf: case IrInstructionIdBitOffsetOf: case IrInstructionIdTypeInfo: + case IrInstructionIdType: case IrInstructionIdHasField: case IrInstructionIdTypeId: case IrInstructionIdSetEvalBranchQuota: @@ -7597,6 +7598,7 @@ static void define_builtin_fns(CodeGen *g) { create_builtin_fn(g, BuiltinFnIdMemberName, "memberName", 2); create_builtin_fn(g, BuiltinFnIdField, "field", 2); create_builtin_fn(g, BuiltinFnIdTypeInfo, "typeInfo", 1); + create_builtin_fn(g, BuiltinFnIdType, "Type", 1); create_builtin_fn(g, BuiltinFnIdHasField, "hasField", 2); create_builtin_fn(g, BuiltinFnIdTypeof, "typeOf", 1); // TODO rename to TypeOf create_builtin_fn(g, BuiltinFnIdAddWithOverflow, "addWithOverflow", 4); diff --git a/src/ir.cpp b/src/ir.cpp index 7415a2dd6b182603ad03a71ced0040373fce1a20..953467c185e01fc2c397d6dda5f528453f4b3e13 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -912,6 +912,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionTypeInfo *) { return IrInstructionIdTypeInfo; } +static constexpr IrInstructionId ir_instruction_id(IrInstructionType *) { + return IrInstructionIdType; +} + static constexpr IrInstructionId ir_instruction_id(IrInstructionHasField *) { return IrInstructionIdHasField; } @@ -2907,6 +2911,15 @@ static IrInstruction *ir_build_type_info(IrBuilder *irb, Scope *scope, AstNode * return &instruction->base; } +static IrInstruction *ir_build_type(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *type_info) { + IrInstructionType *instruction = ir_build_instruction(irb, scope, source_node); + instruction->type_info = type_info; + + ir_ref_instruction(type_info, irb->current_basic_block); + + return &instruction->base; +} + static IrInstruction *ir_build_type_id(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *type_value) { @@ -5046,6 +5059,16 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo IrInstruction *type_info = ir_build_type_info(irb, scope, node, arg0_value); return ir_lval_wrap(irb, scope, type_info, lval, result_loc); } + case BuiltinFnIdType: + { + AstNode *arg_node = node->data.fn_call_expr.params.at(0); + IrInstruction *arg = ir_gen_node(irb, arg_node, scope); + if (arg == irb->codegen->invalid_instruction) + return arg; + + IrInstruction *type = ir_build_type(irb, scope, node, arg); + return ir_lval_wrap(irb, scope, type, lval, result_loc); + } case BuiltinFnIdBreakpoint: return ir_lval_wrap(irb, scope, ir_build_breakpoint(irb, scope, node), lval, result_loc); case BuiltinFnIdReturnAddress: @@ -20104,6 +20127,18 @@ static uint32_t ptr_len_to_size_enum_index(PtrLen ptr_len) { zig_unreachable(); } +static PtrLen size_enum_index_to_ptr_len(uint32_t size_enum_index) { + switch (size_enum_index) { + case 0: + return PtrLenSingle; + case 1: + return PtrLenUnknown; + case 3: + return PtrLenC; + } + zig_unreachable(); +} + static ConstExprValue *create_ptr_like_type_info(IrAnalyze *ira, ZigType *ptr_type_entry) { Error err; ZigType *attrs_type; @@ -20789,6 +20824,147 @@ static IrInstruction *ir_analyze_instruction_type_info(IrAnalyze *ira, return result; } +static ConstExprValue *get_const_field(IrAnalyze *ira, ConstExprValue *struct_value, const char *name, size_t field_index) +{ + ensure_field_index(struct_value->type, name, field_index); + assert(struct_value->data.x_struct.fields[field_index].special == ConstValSpecialStatic); + return &struct_value->data.x_struct.fields[field_index]; +} + +static bool get_const_field_bool(IrAnalyze *ira, ConstExprValue *struct_value, const char *name, size_t field_index) +{ + ConstExprValue *value = get_const_field(ira, struct_value, name, field_index); + assert(value->type == ira->codegen->builtin_types.entry_bool); + return value->data.x_bool; +} + +static BigInt *get_const_field_lit_int(IrAnalyze *ira, ConstExprValue *struct_value, const char *name, size_t field_index) +{ + ConstExprValue *value = get_const_field(ira, struct_value, name, field_index); + assert(value->type == ira->codegen->builtin_types.entry_num_lit_int); + return &value->data.x_bigint; +} + +static ZigType *get_const_field_meta_type(IrAnalyze *ira, ConstExprValue *struct_value, const char *name, size_t field_index) +{ + ConstExprValue *value = get_const_field(ira, struct_value, name, field_index); + assert(value->type == ira->codegen->builtin_types.entry_type); + return value->data.x_type; +} + +static ZigType *type_info_to_type(IrAnalyze *ira, IrInstruction *instruction, ZigTypeId tagTypeId, ConstExprValue *payload) { + switch (tagTypeId) { + case ZigTypeIdInvalid: + zig_unreachable(); + case ZigTypeIdMetaType: + return ira->codegen->builtin_types.entry_type; + case ZigTypeIdVoid: + return ira->codegen->builtin_types.entry_void; + case ZigTypeIdBool: + return ira->codegen->builtin_types.entry_bool; + case ZigTypeIdUnreachable: + return ira->codegen->builtin_types.entry_unreachable; + case ZigTypeIdInt: + assert(payload->special == ConstValSpecialStatic); + assert(payload->type == ir_type_info_get_type(ira, "Int", nullptr)); + return get_int_type(ira->codegen, + get_const_field_bool(ira, payload, "is_signed", 0), + bigint_as_u32(get_const_field_lit_int(ira, payload, "bits", 1))); + case ZigTypeIdFloat: + { + assert(payload->special == ConstValSpecialStatic); + assert(payload->type == ir_type_info_get_type(ira, "Float", nullptr)); + uint32_t bits = bigint_as_u32(get_const_field_lit_int(ira, payload, "bits", 0)); + switch (bits) { + case 16: return ira->codegen->builtin_types.entry_f16; + case 32: return ira->codegen->builtin_types.entry_f32; + case 64: return ira->codegen->builtin_types.entry_f64; + case 128: return ira->codegen->builtin_types.entry_f128; + } + ir_add_error(ira, instruction, + buf_sprintf("%d-bit float unsupported", bits)); + return nullptr; + } + case ZigTypeIdPointer: + { + ZigType *type_info_pointer_type = ir_type_info_get_type(ira, "Pointer", nullptr); + assert(payload->special == ConstValSpecialStatic); + assert(payload->type == type_info_pointer_type); + ConstExprValue *size_value = get_const_field(ira, payload, "size", 0); + assert(size_value->type == ir_type_info_get_type(ira, "Size", type_info_pointer_type)); + uint32_t size_enum_index = bigint_as_u32(&size_value->data.x_enum_tag); + PtrLen ptr_len; + if (size_enum_index == 2) { + ptr_len = PtrLenUnknown; // TODO: is this right? + } else { + ptr_len = size_enum_index_to_ptr_len(size_enum_index); + } + ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, + get_const_field_meta_type(ira, payload, "child", 4), + get_const_field_bool(ira, payload, "is_const", 1), + get_const_field_bool(ira, payload, "is_volatile", 2), + ptr_len, + bigint_as_u32(get_const_field_lit_int(ira, payload, "alignment", 3)), + 0, // bit_offset_in_host??? + 0, // host_int_bytes??? + get_const_field_bool(ira, payload, "is_allowzero", 5) + ); + if (size_enum_index != 2) + return ptr_type; + return get_slice_type(ira->codegen, ptr_type); + } + case ZigTypeIdComptimeFloat: + return ira->codegen->builtin_types.entry_num_lit_float; + case ZigTypeIdComptimeInt: + return ira->codegen->builtin_types.entry_num_lit_int; + case ZigTypeIdUndefined: + return ira->codegen->builtin_types.entry_undef; + case ZigTypeIdNull: + return ira->codegen->builtin_types.entry_null; + case ZigTypeIdArray: + case ZigTypeIdOptional: + case ZigTypeIdErrorUnion: + case ZigTypeIdErrorSet: + case ZigTypeIdEnum: + case ZigTypeIdOpaque: + case ZigTypeIdFnFrame: + case ZigTypeIdAnyFrame: + case ZigTypeIdVector: + case ZigTypeIdEnumLiteral: + ir_add_error(ira, instruction, buf_sprintf( + "TODO implement @Type forr 'TypeInfo.%s': see https://github.com/ziglang/zig/issues/2907\n", type_id_name(tagTypeId))); + return nullptr; + case ZigTypeIdUnion: + case ZigTypeIdFn: + case ZigTypeIdBoundFn: + case ZigTypeIdArgTuple: + case ZigTypeIdStruct: + ir_add_error(ira, instruction, buf_sprintf( + "@Type not availble for 'TypeInfo.%s'\n", type_id_name(tagTypeId))); + return nullptr; + } + zig_unreachable(); +} + +static IrInstruction *ir_analyze_instruction_type(IrAnalyze *ira, IrInstructionType *instruction) { + IrInstruction *type_info_ir = instruction->type_info->child; + if (type_is_invalid(type_info_ir->value.type)) + return ira->codegen->invalid_instruction; + + IrInstruction *casted_ir = ir_implicit_cast(ira, type_info_ir, ir_type_info_get_type(ira, nullptr, nullptr)); + if (type_is_invalid(casted_ir->value.type)) + return ira->codegen->invalid_instruction; + + ConstExprValue *type_info_value = ir_resolve_const(ira, casted_ir, UndefBad); + if (!type_info_value) + return ira->codegen->invalid_instruction; + ZigTypeId typeId = type_id_at_index(bigint_as_usize(&type_info_value->data.x_union.tag)); + ZigType *type = type_info_to_type(ira, type_info_ir, typeId, type_info_value->data.x_union.payload); + if (!type) + return ira->codegen->invalid_instruction; + return ir_const_type(ira, &instruction->base, type); +} + static IrInstruction *ir_analyze_instruction_type_id(IrAnalyze *ira, IrInstructionTypeId *instruction) { @@ -25295,6 +25471,8 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction return ir_analyze_instruction_bit_offset_of(ira, (IrInstructionBitOffsetOf *)instruction); case IrInstructionIdTypeInfo: return ir_analyze_instruction_type_info(ira, (IrInstructionTypeInfo *) instruction); + case IrInstructionIdType: + return ir_analyze_instruction_type(ira, (IrInstructionType *)instruction); case IrInstructionIdHasField: return ir_analyze_instruction_has_field(ira, (IrInstructionHasField *) instruction); case IrInstructionIdTypeId: @@ -25598,6 +25776,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { case IrInstructionIdByteOffsetOf: case IrInstructionIdBitOffsetOf: case IrInstructionIdTypeInfo: + case IrInstructionIdType: case IrInstructionIdHasField: case IrInstructionIdTypeId: case IrInstructionIdAlignCast: diff --git a/src/ir_print.cpp b/src/ir_print.cpp index 6de585ec6fcb21cc01aa3e8cb66f143c5bc33206..25eb01365ff6a47ba92bbfe2cf90e02de36bde6f 100644 --- a/src/ir_print.cpp +++ b/src/ir_print.cpp @@ -280,6 +280,8 @@ static const char* ir_instruction_type_str(IrInstruction* instruction) { return "BitOffsetOf"; case IrInstructionIdTypeInfo: return "TypeInfo"; + case IrInstructionIdType: + return "Type"; case IrInstructionIdHasField: return "HasField"; case IrInstructionIdTypeId: @@ -1627,6 +1629,12 @@ static void ir_print_type_info(IrPrint *irp, IrInstructionTypeInfo *instruction) fprintf(irp->f, ")"); } +static void ir_print_type(IrPrint *irp, IrInstructionType *instruction) { + fprintf(irp->f, "@Type("); + ir_print_other_instruction(irp, instruction->type_info); + fprintf(irp->f, ")"); +} + static void ir_print_has_field(IrPrint *irp, IrInstructionHasField *instruction) { fprintf(irp->f, "@hasField("); ir_print_other_instruction(irp, instruction->container_type); @@ -2258,6 +2266,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction, bool case IrInstructionIdTypeInfo: ir_print_type_info(irp, (IrInstructionTypeInfo *)instruction); break; + case IrInstructionIdType: + ir_print_type(irp, (IrInstructionType *)instruction); + break; case IrInstructionIdHasField: ir_print_has_field(irp, (IrInstructionHasField *)instruction); break; diff --git a/test/compile_errors.zig b/test/compile_errors.zig index 871ff63e2365870c70696fdac4ce9d13405496aa..1438a59539831496049379aa60b5a9215d45159b 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -2,6 +2,58 @@ const tests = @import("tests.zig"); const builtin = @import("builtin"); pub fn addCases(cases: *tests.CompileErrorContext) void { + + cases.add( + "wrong type for @Type", + \\export fn entry() void { + \\ _ = @Type(0); + \\} + , + "tmp.zig:2:15: error: expected type 'builtin.TypeInfo', found 'comptime_int'", + ); + + cases.add( + "@Type with non-constant expression", + \\const builtin = @import("builtin"); + \\var globalTypeInfo : builtin.TypeInfo = undefined; + \\export fn entry() void { + \\ _ = @Type(globalTypeInfo); + \\} + , + "tmp.zig:4:15: error: unable to evaluate constant expression", + ); + + cases.add( + "@Type with TypeInfo.Int", + \\const builtin = @import("builtin"); + \\export fn entry() void { + \\ _ = @Type(builtin.TypeInfo.Int { + \\ .is_signed = true, + \\ .bits = 8, + \\ }); + \\} + , + "tmp.zig:3:36: error: expected type 'builtin.TypeInfo', found 'builtin.Int'", + ); + + cases.add( + "Struct unavailable for @Type", + \\export fn entry() void { + \\ _ = @Type(@typeInfo(struct { })); + \\} + , + "tmp.zig:2:15: error: @Type not availble for 'TypeInfo.Struct'", + ); + + cases.add( + "array not implemented for @Type", + \\export fn entry() void { + \\ _ = @Type(@typeInfo(enum{x})); + \\} + , + "tmp.zig:2:15: error: TODO implement @Type forr 'TypeInfo.Enum': see https://github.com/ziglang/zig/issues/2907", + ); + cases.add( "wrong type for result ptr to @asyncCall", \\export fn entry() void { diff --git a/test/stage1/behavior.zig b/test/stage1/behavior.zig index 23ec3e53ce6adc17ff88fd28506d9a3f7fe9d85f..db6cdad3b10343d3de1c4833b2f15b9517298082 100644 --- a/test/stage1/behavior.zig +++ b/test/stage1/behavior.zig @@ -93,6 +93,7 @@ comptime { _ = @import("behavior/this.zig"); _ = @import("behavior/truncate.zig"); _ = @import("behavior/try.zig"); + _ = @import("behavior/type.zig"); _ = @import("behavior/type_info.zig"); _ = @import("behavior/typename.zig"); _ = @import("behavior/undefined.zig"); diff --git a/test/stage1/behavior/type.zig b/test/stage1/behavior/type.zig new file mode 100644 index 0000000000000000000000000000000000000000..318e07fbdfb742cc0b18b7e5ebdefbc9fe4e5611 --- /dev/null +++ b/test/stage1/behavior/type.zig @@ -0,0 +1,111 @@ +const builtin = @import("builtin"); +const TypeInfo = builtin.TypeInfo; + +const std = @import("std"); +const testing = std.testing; + +fn testTypes(comptime types: []const type) void { + inline for (types) |testType| { + testing.expect(testType == @Type(@typeInfo(testType))); + } +} + +test "Type.MetaType" { + testing.expect(type == @Type(TypeInfo { .Type = undefined })); + testTypes([_]type {type}); +} + +test "Type.Void" { + testing.expect(void == @Type(TypeInfo { .Void = undefined })); + testTypes([_]type {void}); +} + +test "Type.Bool" { + testing.expect(bool == @Type(TypeInfo { .Bool = undefined })); + testTypes([_]type {bool}); +} + +test "Type.NoReturn" { + testing.expect(noreturn == @Type(TypeInfo { .NoReturn = undefined })); + testTypes([_]type {noreturn}); +} + +test "Type.Int" { + testing.expect(u1 == @Type(TypeInfo { .Int = TypeInfo.Int { .is_signed = false, .bits = 1 } })); + testing.expect(i1 == @Type(TypeInfo { .Int = TypeInfo.Int { .is_signed = true, .bits = 1 } })); + testing.expect(u8 == @Type(TypeInfo { .Int = TypeInfo.Int { .is_signed = false, .bits = 8 } })); + testing.expect(i8 == @Type(TypeInfo { .Int = TypeInfo.Int { .is_signed = true, .bits = 8 } })); + testing.expect(u64 == @Type(TypeInfo { .Int = TypeInfo.Int { .is_signed = false, .bits = 64 } })); + testing.expect(i64 == @Type(TypeInfo { .Int = TypeInfo.Int { .is_signed = true, .bits = 64 } })); + testTypes([_]type {u8,u32,i64}); + // TODO: should this work? + //testing.expect(u1 == @Type(TypeInfo.Int { .is_signed = false, .bits = 1 } )); +} + +test "Type.Float" { + testing.expect(f16 == @Type(TypeInfo { .Float = TypeInfo.Float { .bits = 16 } })); + testing.expect(f32 == @Type(TypeInfo { .Float = TypeInfo.Float { .bits = 32 } })); + testing.expect(f64 == @Type(TypeInfo { .Float = TypeInfo.Float { .bits = 64 } })); + testing.expect(f128 == @Type(TypeInfo { .Float = TypeInfo.Float { .bits = 128 } })); + testTypes([_]type {f16, f32, f64, f128}); + // error: 17-bit float unsupported + //testing.expect(f16 == @Type(TypeInfo { .Float = TypeInfo.Float { .bits = 17 } })); +} + +test "Type.Pointer" { + testTypes([_]type { + // One Value Pointer Types + *u8, *const u8, + *volatile u8, *const volatile u8, + *align(4) u8, *const align(4) u8, + *volatile align(4) u8, *const volatile align(4) u8, + *align(8) u8, *const align(8) u8, + *volatile align(8) u8, *const volatile align(8) u8, + *allowzero u8, *const allowzero u8, + *volatile allowzero u8, *const volatile allowzero u8, + *align(4) allowzero u8, *const align(4) allowzero u8, + *volatile align(4) allowzero u8, *const volatile align(4) allowzero u8, + // Many Values Pointer Types + [*]u8, [*]const u8, + [*]volatile u8, [*]const volatile u8, + [*]align(4) u8, [*]const align(4) u8, + [*]volatile align(4) u8, [*]const volatile align(4) u8, + [*]align(8) u8, [*]const align(8) u8, + [*]volatile align(8) u8, [*]const volatile align(8) u8, + [*]allowzero u8, [*]const allowzero u8, + [*]volatile allowzero u8, [*]const volatile allowzero u8, + [*]align(4) allowzero u8, [*]const align(4) allowzero u8, + [*]volatile align(4) allowzero u8, [*]const volatile align(4) allowzero u8, + // Slice Types + []u8, []const u8, + []volatile u8, []const volatile u8, + []align(4) u8, []const align(4) u8, + []volatile align(4) u8, []const volatile align(4) u8, + []align(8) u8, []const align(8) u8, + []volatile align(8) u8, []const volatile align(8) u8, + []allowzero u8, []const allowzero u8, + []volatile allowzero u8, []const volatile allowzero u8, + []align(4) allowzero u8, []const align(4) allowzero u8, + []volatile align(4) allowzero u8, []const volatile align(4) allowzero u8, + // C Pointer Types + [*c]u8, [*c]const u8, + [*c]volatile u8, [*c]const volatile u8, + [*c]align(4) u8, [*c]const align(4) u8, + [*c]volatile align(4) u8, [*c]const volatile align(4) u8, + [*c]align(8) u8, [*c]const align(8) u8, + [*c]volatile align(8) u8, [*c]const volatile align(8) u8, + }); +} + +test "Type.ComptimeFloat" { + testTypes([_]type {comptime_float}); +} +test "Type.ComptimeInt" { + testTypes([_]type {comptime_int}); +} +test "Type.Undefined" { + testTypes([_]type {@typeOf(undefined)}); +} +test "Type.Null" { + testTypes([_]type {@typeOf(null)}); +} -- 2.54.0 From 6a76298740344ba6d82c33b19914238a1233eaa0 Mon Sep 17 00:00:00 2001 From: Robin Voetter Date: Wed, 4 Sep 2019 15:59:51 +0200 Subject: [PATCH 33/80] Add missing clobbers on arm-eabi and arm64 syscall conventions --- std/os/linux/arm-eabi.zig | 7 +++++++ std/os/linux/arm64.zig | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/std/os/linux/arm-eabi.zig b/std/os/linux/arm-eabi.zig index 1167c10f0b61387ff75d081f9e1a1a582f975f0e..a0a00dce8b19f03cd12bcb83e214f849baccc651 100644 --- a/std/os/linux/arm-eabi.zig +++ b/std/os/linux/arm-eabi.zig @@ -2,6 +2,7 @@ pub fn syscall0(number: usize) usize { return asm volatile ("svc #0" : [ret] "={r0}" (-> usize) : [number] "{r7}" (number) + : "memory" ); } @@ -10,6 +11,7 @@ pub fn syscall1(number: usize, arg1: usize) usize { : [ret] "={r0}" (-> usize) : [number] "{r7}" (number), [arg1] "{r0}" (arg1) + : "memory" ); } @@ -19,6 +21,7 @@ pub fn syscall2(number: usize, arg1: usize, arg2: usize) usize { : [number] "{r7}" (number), [arg1] "{r0}" (arg1), [arg2] "{r1}" (arg2) + : "memory" ); } @@ -29,6 +32,7 @@ pub fn syscall3(number: usize, arg1: usize, arg2: usize, arg3: usize) usize { [arg1] "{r0}" (arg1), [arg2] "{r1}" (arg2), [arg3] "{r2}" (arg3) + : "memory" ); } @@ -40,6 +44,7 @@ pub fn syscall4(number: usize, arg1: usize, arg2: usize, arg3: usize, arg4: usiz [arg2] "{r1}" (arg2), [arg3] "{r2}" (arg3), [arg4] "{r3}" (arg4) + : "memory" ); } @@ -52,6 +57,7 @@ pub fn syscall5(number: usize, arg1: usize, arg2: usize, arg3: usize, arg4: usiz [arg3] "{r2}" (arg3), [arg4] "{r3}" (arg4), [arg5] "{r4}" (arg5) + : "memory" ); } @@ -73,6 +79,7 @@ pub fn syscall6( [arg4] "{r3}" (arg4), [arg5] "{r4}" (arg5), [arg6] "{r5}" (arg6) + : "memory" ); } diff --git a/std/os/linux/arm64.zig b/std/os/linux/arm64.zig index 94cf8818de2e282e2f8f17a9b143eddad284fde3..28da9af1c6bb51879387bf71c9bf369b9b44acd1 100644 --- a/std/os/linux/arm64.zig +++ b/std/os/linux/arm64.zig @@ -2,6 +2,7 @@ pub fn syscall0(number: usize) usize { return asm volatile ("svc #0" : [ret] "={x0}" (-> usize) : [number] "{x8}" (number) + : "memory", "cc" ); } @@ -10,6 +11,7 @@ pub fn syscall1(number: usize, arg1: usize) usize { : [ret] "={x0}" (-> usize) : [number] "{x8}" (number), [arg1] "{x0}" (arg1) + : "memory", "cc" ); } @@ -19,6 +21,7 @@ pub fn syscall2(number: usize, arg1: usize, arg2: usize) usize { : [number] "{x8}" (number), [arg1] "{x0}" (arg1), [arg2] "{x1}" (arg2) + : "memory", "cc" ); } @@ -29,6 +32,7 @@ pub fn syscall3(number: usize, arg1: usize, arg2: usize, arg3: usize) usize { [arg1] "{x0}" (arg1), [arg2] "{x1}" (arg2), [arg3] "{x2}" (arg3) + : "memory", "cc" ); } @@ -40,6 +44,7 @@ pub fn syscall4(number: usize, arg1: usize, arg2: usize, arg3: usize, arg4: usiz [arg2] "{x1}" (arg2), [arg3] "{x2}" (arg3), [arg4] "{x3}" (arg4) + : "memory", "cc" ); } @@ -52,6 +57,7 @@ pub fn syscall5(number: usize, arg1: usize, arg2: usize, arg3: usize, arg4: usiz [arg3] "{x2}" (arg3), [arg4] "{x3}" (arg4), [arg5] "{x4}" (arg5) + : "memory", "cc" ); } @@ -73,6 +79,7 @@ pub fn syscall6( [arg4] "{x3}" (arg4), [arg5] "{x4}" (arg5), [arg6] "{x5}" (arg6) + : "memory", "cc" ); } -- 2.54.0 From 77d04c03e3f20c4c60d98e73b876222006aa05fc Mon Sep 17 00:00:00 2001 From: Robin Voetter Date: Wed, 4 Sep 2019 16:23:25 +0200 Subject: [PATCH 34/80] Implement remaining requested changes - Replace @intCast with a checked version (std/debug.zig) - Replace @intCast with i64() when casting from a smaller type (std/fs/file.zig) - Replace `nakedcc` with appropriate calling convention for linking with c (std/os/linux/arm-eabi.zig) - Only check if hwcap contains TLS when the hwcap field actually exists (std/os/linux/tls.zig) --- std/debug.zig | 3 ++- std/fs/file.zig | 6 +++--- std/os/linux/arm-eabi.zig | 2 +- std/os/linux/tls.zig | 6 +++--- 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/std/debug.zig b/std/debug.zig index 8918426e47aee8cc4b546673860752586c906ea3..68e6220a72156ebee04c5b31b98e4e359e68b590 100644 --- a/std/debug.zig +++ b/std/debug.zig @@ -1053,7 +1053,8 @@ fn openSelfDebugInfoPosix(allocator: *mem.Allocator) !DwarfInfo { S.self_exe_file = try fs.openSelfExe(); errdefer S.self_exe_file.close(); - const self_exe_mmap_len = mem.alignForward(@intCast(usize, try S.self_exe_file.getEndPos()), mem.page_size); + const self_exe_len = math.cast(usize, try S.self_exe_file.getEndPos()) catch return error.DebugInfoTooLarge; + const self_exe_mmap_len = mem.alignForward(self_exe_len, mem.page_size); const self_exe_mmap = try os.mmap( null, self_exe_mmap_len, diff --git a/std/fs/file.zig b/std/fs/file.zig index 83cbe2378010e4e73545e0aeb5082fd18d346541..5ecad010265b633411577fa94b75bfc77f9a857a 100644 --- a/std/fs/file.zig +++ b/std/fs/file.zig @@ -261,9 +261,9 @@ pub const File = struct { return Stat{ .size = @bitCast(u64, st.size), .mode = st.mode, - .atime = @intCast(i64, atime.tv_sec) * std.time.ns_per_s + atime.tv_nsec, - .mtime = @intCast(i64, mtime.tv_sec) * std.time.ns_per_s + mtime.tv_nsec, - .ctime = @intCast(i64, ctime.tv_sec) * std.time.ns_per_s + ctime.tv_nsec, + .atime = i64(atime.tv_sec) * std.time.ns_per_s + atime.tv_nsec, + .mtime = i64(mtime.tv_sec) * std.time.ns_per_s + mtime.tv_nsec, + .ctime = i64(ctime.tv_sec) * std.time.ns_per_s + ctime.tv_nsec, }; } diff --git a/std/os/linux/arm-eabi.zig b/std/os/linux/arm-eabi.zig index a0a00dce8b19f03cd12bcb83e214f849baccc651..c8a5bbe3781426605cacaf79efa792d2681d8d2d 100644 --- a/std/os/linux/arm-eabi.zig +++ b/std/os/linux/arm-eabi.zig @@ -89,7 +89,7 @@ pub extern fn clone(func: extern fn (arg: usize) u8, stack: usize, flags: u32, a // LLVM calls this when the read-tp-hard feature is set to false. Currently, there is no way to pass // that to llvm via zig, see https://github.com/ziglang/zig/issues/2883. // LLVM expects libc to provide this function as __aeabi_read_tp, so it is exported if needed from special/c.zig. -pub nakedcc fn getThreadPointer() usize { +pub extern fn getThreadPointer() usize { return asm volatile("mrc p15, 0, %[ret], c13, c0, 3" : [ret] "=r" (-> usize) ); diff --git a/std/os/linux/tls.zig b/std/os/linux/tls.zig index 8920e28a5b9e7b0ade4589befc949c35eb5e0fc2..2ed5f1d75b84dc4a1c2f952c8bf3c1f93f2dd8ba 100644 --- a/std/os/linux/tls.zig +++ b/std/os/linux/tls.zig @@ -133,7 +133,7 @@ pub fn initTLS() void { var at_phent: usize = undefined; var at_phnum: usize = undefined; var at_phdr: usize = undefined; - var at_hwcap: usize = undefined; + var at_hwcap: ?usize = null; var i: usize = 0; while (auxv[i].a_type != std.elf.AT_NULL) : (i += 1) { @@ -147,8 +147,8 @@ pub fn initTLS() void { } // If the cpu is arm-based, check if it supports the TLS register - if (builtin.arch == builtin.Arch.arm) { - if (at_hwcap & std.os.linux.HWCAP_TLS == 0) { + if (at_hwcap) |hwcap| { + if (builtin.arch == builtin.Arch.arm and hwcap & std.os.linux.HWCAP_TLS == 0) { // If the CPU does not support TLS via a coprocessor register, // a kernel helper function can be used instead on certain linux kernels. // See linux/arch/arm/include/asm/tls.h and musl/src/thread/arm/__set_thread_area.c. -- 2.54.0 From ac7703f65f7acc9137e28ded97659fbaadea4e66 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 4 Sep 2019 11:08:28 -0400 Subject: [PATCH 35/80] fixups and add documentation for `@Type` --- doc/docgen.zig | 26 ++++++++++++++-- doc/langref.html.in | 56 ++++++++++++++++++++++++++++++++++- src/all_types.hpp | 8 +++++ src/codegen.cpp | 29 ++++++++++-------- src/ir.cpp | 38 +++++++++++------------- test/compile_errors.zig | 18 +++++------ test/stage1/behavior/type.zig | 4 --- 7 files changed, 130 insertions(+), 49 deletions(-) diff --git a/doc/docgen.zig b/doc/docgen.zig index a2b4e8501c93478e8ef19697e79a932b9c801ea3..eee4c453694c91d11dc99587b66b543b1a25f46d 100644 --- a/doc/docgen.zig +++ b/doc/docgen.zig @@ -321,6 +321,7 @@ fn genToc(allocator: *mem.Allocator, tokenizer: *Tokenizer) !Toc { var header_stack_size: usize = 0; var last_action = Action.Open; + var last_columns: ?u8 = null; var toc_buf = try std.Buffer.initSize(allocator, 0); defer toc_buf.deinit(); @@ -361,7 +362,23 @@ fn genToc(allocator: *mem.Allocator, tokenizer: *Tokenizer) !Toc { _ = try eatToken(tokenizer, Token.Id.Separator); const content_token = try eatToken(tokenizer, Token.Id.TagContent); const content = tokenizer.buffer[content_token.start..content_token.end]; - _ = try eatToken(tokenizer, Token.Id.BracketClose); + var columns: ?u8 = null; + while (true) { + const bracket_tok = tokenizer.next(); + switch (bracket_tok.id) { + .BracketClose => break, + .Separator => continue, + .TagContent => { + const param = tokenizer.buffer[bracket_tok.start..bracket_tok.end]; + if (mem.eql(u8, param, "3col")) { + columns = 3; + } else { + return parseError(tokenizer, bracket_tok, "unrecognized header_open param: {}", param); + } + }, + else => return parseError(tokenizer, bracket_tok, "invalid header_open token"), + } + } header_stack_size += 1; @@ -381,10 +398,15 @@ fn genToc(allocator: *mem.Allocator, tokenizer: *Tokenizer) !Toc { if (last_action == Action.Open) { try toc.writeByte('\n'); try toc.writeByteNTimes(' ', header_stack_size * 4); - try toc.write("
    \n"); + if (last_columns) |n| { + try toc.print("
      \n", n); + } else { + try toc.write("
        \n"); + } } else { last_action = Action.Open; } + last_columns = columns; try toc.writeByteNTimes(' ', 4 + header_stack_size * 4); try toc.print("
      • {}", urlized, urlized, content); } else if (mem.eql(u8, tag_name, "header_close")) { diff --git a/doc/langref.html.in b/doc/langref.html.in index 44b2256813f5b2b4084be0a514d28015a9980584..2ad86d653e21d874507ef51496b5e08419a0d7e9 100644 --- a/doc/langref.html.in +++ b/doc/langref.html.in @@ -6323,7 +6323,7 @@ fn readFile(allocator: *Allocator, filename: []const u8) ![]u8 { {#header_close#} {#header_close#} - {#header_open|Builtin Functions#} + {#header_open|Builtin Functions|3col#}

        Builtin functions are provided by the compiler and are prefixed with @. The {#syntax#}comptime{#endsyntax#} keyword on a parameter means that the parameter must be known @@ -7232,6 +7232,9 @@ fn add(a: i32, b: i32) i32 { return a + b; } This function returns an integer type with the given signness and bit count. The maximum bit count for an integer type is {#syntax#}65535{#endsyntax#}.

        +

        + Deprecated. Use {#link|@Type#}. +

        {#header_close#} {#header_open|@memberCount#} @@ -7871,6 +7874,57 @@ test "integer truncation" {

        {#header_close#} + {#header_open|@Type#} +
        {#syntax#}@Type(comptime info: @import("builtin").TypeInfo) type{#endsyntax#}
        +

        + This function is the inverse of {#link|@typeInfo#}. It reifies type information + into a {#syntax#}type{#endsyntax#}. +

        +

        + It is available for the following types: +

        +
          +
        • {#syntax#}type{#endsyntax#}
        • +
        • {#syntax#}noreturn{#endsyntax#}
        • +
        • {#syntax#}void{#endsyntax#}
        • +
        • {#syntax#}bool{#endsyntax#}
        • +
        • {#link|Integers#}
        • - The maximum bit count for an integer type is {#syntax#}65535{#endsyntax#}. +
        • {#link|Floats#}
        • +
        • {#link|Pointers#}
        • +
        • {#syntax#}comptime_int{#endsyntax#}
        • +
        • {#syntax#}comptime_float{#endsyntax#}
        • +
        • {#syntax#}@typeOf(undefined){#endsyntax#}
        • +
        • {#syntax#}@typeOf(null){#endsyntax#}
        • +
        +

        + For these types it is a + TODO in the compiler to implement: +

        +
          +
        • Array
        • +
        • Optional
        • +
        • ErrorUnion
        • +
        • ErrorSet
        • +
        • Enum
        • +
        • Opaque
        • +
        • FnFrame
        • +
        • AnyFrame
        • +
        • Vector
        • +
        • EnumLiteral
        • +
        +

        + For these types, {#syntax#}@Type{#endsyntax#} is not available. + There is an open proposal to allow unions and structs. +

        +
          +
        • {#link|union#}
        • +
        • {#link|Functions#}
        • +
        • BoundFn
        • +
        • ArgTuple
        • +
        • {#link|struct#}
        • +
        + {#header_close#} + {#header_open|@typeId#}
        {#syntax#}@typeId(comptime T: type) @import("builtin").TypeId{#endsyntax#}

        diff --git a/src/all_types.hpp b/src/all_types.hpp index 4253a346f88719efb3f9249c55280038d8d52ed0..03559ccf12f2f696676121e52706c2c178c985d4 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -54,6 +54,14 @@ enum PtrLen { PtrLenC, }; +// This one corresponds to the builtin.zig enum. +enum BuiltinPtrSize { + BuiltinPtrSizeOne, + BuiltinPtrSizeMany, + BuiltinPtrSizeSlice, + BuiltinPtrSizeC, +}; + enum UndefAllowed { UndefOk, UndefBad, diff --git a/src/codegen.cpp b/src/codegen.cpp index d7d4b4443711e02382dc02a7609d86b25d02c267..13fb0d625d0a52f2f505e9b7cf26d1d5e68de0f6 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -8161,20 +8161,25 @@ Buf *codegen_generate_builtin_source(CodeGen *g) { " };\n" " };\n" "};\n\n"); - assert(ContainerLayoutAuto == 0); - assert(ContainerLayoutExtern == 1); - assert(ContainerLayoutPacked == 2); + static_assert(ContainerLayoutAuto == 0, ""); + static_assert(ContainerLayoutExtern == 1, ""); + static_assert(ContainerLayoutPacked == 2, ""); - assert(CallingConventionUnspecified == 0); - assert(CallingConventionC == 1); - assert(CallingConventionCold == 2); - assert(CallingConventionNaked == 3); - assert(CallingConventionStdcall == 4); - assert(CallingConventionAsync == 5); + static_assert(CallingConventionUnspecified == 0, ""); + static_assert(CallingConventionC == 1, ""); + static_assert(CallingConventionCold == 2, ""); + static_assert(CallingConventionNaked == 3, ""); + static_assert(CallingConventionStdcall == 4, ""); + static_assert(CallingConventionAsync == 5, ""); - assert(FnInlineAuto == 0); - assert(FnInlineAlways == 1); - assert(FnInlineNever == 2); + static_assert(FnInlineAuto == 0, ""); + static_assert(FnInlineAlways == 1, ""); + static_assert(FnInlineNever == 2, ""); + + static_assert(BuiltinPtrSizeOne == 0, ""); + static_assert(BuiltinPtrSizeMany == 1, ""); + static_assert(BuiltinPtrSizeSlice == 2, ""); + static_assert(BuiltinPtrSizeC == 3, ""); } { buf_appendf(contents, diff --git a/src/ir.cpp b/src/ir.cpp index 953467c185e01fc2c397d6dda5f528453f4b3e13..9547b1ec619a0d4a22bfda1e29b7c2b21e8e7622 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -20115,25 +20115,26 @@ static Error ir_make_type_info_decls(IrAnalyze *ira, IrInstruction *source_instr return ErrorNone; } -static uint32_t ptr_len_to_size_enum_index(PtrLen ptr_len) { +static BuiltinPtrSize ptr_len_to_size_enum_index(PtrLen ptr_len) { switch (ptr_len) { case PtrLenSingle: - return 0; + return BuiltinPtrSizeOne; case PtrLenUnknown: - return 1; + return BuiltinPtrSizeMany; case PtrLenC: - return 3; + return BuiltinPtrSizeC; } zig_unreachable(); } -static PtrLen size_enum_index_to_ptr_len(uint32_t size_enum_index) { +static PtrLen size_enum_index_to_ptr_len(BuiltinPtrSize size_enum_index) { switch (size_enum_index) { - case 0: + case BuiltinPtrSizeOne: return PtrLenSingle; - case 1: + case BuiltinPtrSizeMany: + case BuiltinPtrSizeSlice: return PtrLenUnknown; - case 3: + case BuiltinPtrSizeC: return PtrLenC; } zig_unreachable(); @@ -20142,10 +20143,10 @@ static PtrLen size_enum_index_to_ptr_len(uint32_t size_enum_index) { static ConstExprValue *create_ptr_like_type_info(IrAnalyze *ira, ZigType *ptr_type_entry) { Error err; ZigType *attrs_type; - uint32_t size_enum_index; + BuiltinPtrSize size_enum_index; if (is_slice(ptr_type_entry)) { attrs_type = ptr_type_entry->data.structure.fields[slice_ptr_index].type_entry; - size_enum_index = 2; + size_enum_index = BuiltinPtrSizeSlice; } else if (ptr_type_entry->id == ZigTypeIdPointer) { attrs_type = ptr_type_entry; size_enum_index = ptr_len_to_size_enum_index(ptr_type_entry->data.pointer.ptr_len); @@ -20892,21 +20893,16 @@ static ZigType *type_info_to_type(IrAnalyze *ira, IrInstruction *instruction, Zi assert(payload->type == type_info_pointer_type); ConstExprValue *size_value = get_const_field(ira, payload, "size", 0); assert(size_value->type == ir_type_info_get_type(ira, "Size", type_info_pointer_type)); - uint32_t size_enum_index = bigint_as_u32(&size_value->data.x_enum_tag); - PtrLen ptr_len; - if (size_enum_index == 2) { - ptr_len = PtrLenUnknown; // TODO: is this right? - } else { - ptr_len = size_enum_index_to_ptr_len(size_enum_index); - } + BuiltinPtrSize size_enum_index = (BuiltinPtrSize)bigint_as_u32(&size_value->data.x_enum_tag); + PtrLen ptr_len = size_enum_index_to_ptr_len(size_enum_index); ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, get_const_field_meta_type(ira, payload, "child", 4), get_const_field_bool(ira, payload, "is_const", 1), get_const_field_bool(ira, payload, "is_volatile", 2), ptr_len, bigint_as_u32(get_const_field_lit_int(ira, payload, "alignment", 3)), - 0, // bit_offset_in_host??? - 0, // host_int_bytes??? + 0, // bit_offset_in_host + 0, // host_int_bytes get_const_field_bool(ira, payload, "is_allowzero", 5) ); if (size_enum_index != 2) @@ -20932,7 +20928,7 @@ static ZigType *type_info_to_type(IrAnalyze *ira, IrInstruction *instruction, Zi case ZigTypeIdVector: case ZigTypeIdEnumLiteral: ir_add_error(ira, instruction, buf_sprintf( - "TODO implement @Type forr 'TypeInfo.%s': see https://github.com/ziglang/zig/issues/2907\n", type_id_name(tagTypeId))); + "TODO implement @Type for 'TypeInfo.%s': see https://github.com/ziglang/zig/issues/2907", type_id_name(tagTypeId))); return nullptr; case ZigTypeIdUnion: case ZigTypeIdFn: @@ -20940,7 +20936,7 @@ static ZigType *type_info_to_type(IrAnalyze *ira, IrInstruction *instruction, Zi case ZigTypeIdArgTuple: case ZigTypeIdStruct: ir_add_error(ira, instruction, buf_sprintf( - "@Type not availble for 'TypeInfo.%s'\n", type_id_name(tagTypeId))); + "@Type not availble for 'TypeInfo.%s'", type_id_name(tagTypeId))); return nullptr; } zig_unreachable(); diff --git a/test/compile_errors.zig b/test/compile_errors.zig index 1438a59539831496049379aa60b5a9215d45159b..38fca5754de03cff1d9455ca822108944f5a070e 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -2,6 +2,15 @@ const tests = @import("tests.zig"); const builtin = @import("builtin"); pub fn addCases(cases: *tests.CompileErrorContext) void { + cases.add( + "attempt to create 17 bit float type", + \\const builtin = @import("builtin"); + \\comptime { + \\ _ = @Type(builtin.TypeInfo { .Float = builtin.TypeInfo.Float { .bits = 17 } }); + \\} + , + "tmp.zig:3:32: error: 17-bit float unsupported", + ); cases.add( "wrong type for @Type", @@ -45,15 +54,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { "tmp.zig:2:15: error: @Type not availble for 'TypeInfo.Struct'", ); - cases.add( - "array not implemented for @Type", - \\export fn entry() void { - \\ _ = @Type(@typeInfo(enum{x})); - \\} - , - "tmp.zig:2:15: error: TODO implement @Type forr 'TypeInfo.Enum': see https://github.com/ziglang/zig/issues/2907", - ); - cases.add( "wrong type for result ptr to @asyncCall", \\export fn entry() void { diff --git a/test/stage1/behavior/type.zig b/test/stage1/behavior/type.zig index 318e07fbdfb742cc0b18b7e5ebdefbc9fe4e5611..5b2998f08831477bf370c938c48025665c34a4a2 100644 --- a/test/stage1/behavior/type.zig +++ b/test/stage1/behavior/type.zig @@ -38,8 +38,6 @@ test "Type.Int" { testing.expect(u64 == @Type(TypeInfo { .Int = TypeInfo.Int { .is_signed = false, .bits = 64 } })); testing.expect(i64 == @Type(TypeInfo { .Int = TypeInfo.Int { .is_signed = true, .bits = 64 } })); testTypes([_]type {u8,u32,i64}); - // TODO: should this work? - //testing.expect(u1 == @Type(TypeInfo.Int { .is_signed = false, .bits = 1 } )); } test "Type.Float" { @@ -48,8 +46,6 @@ test "Type.Float" { testing.expect(f64 == @Type(TypeInfo { .Float = TypeInfo.Float { .bits = 64 } })); testing.expect(f128 == @Type(TypeInfo { .Float = TypeInfo.Float { .bits = 128 } })); testTypes([_]type {f16, f32, f64, f128}); - // error: 17-bit float unsupported - //testing.expect(f16 == @Type(TypeInfo { .Float = TypeInfo.Float { .bits = 17 } })); } test "Type.Pointer" { -- 2.54.0 From df06976e73e37a36009fb5f43c2310ad610a4a2e Mon Sep 17 00:00:00 2001 From: Robin Voetter Date: Wed, 4 Sep 2019 17:48:01 +0200 Subject: [PATCH 36/80] Only check for TLS support on arm if TLS segment exists --- std/os/linux/tls.zig | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/std/os/linux/tls.zig b/std/os/linux/tls.zig index 2ed5f1d75b84dc4a1c2f952c8bf3c1f93f2dd8ba..3c55013f47b4a2e0876abbd27215474934aa4c58 100644 --- a/std/os/linux/tls.zig +++ b/std/os/linux/tls.zig @@ -133,7 +133,7 @@ pub fn initTLS() void { var at_phent: usize = undefined; var at_phnum: usize = undefined; var at_phdr: usize = undefined; - var at_hwcap: ?usize = null; + var at_hwcap: usize = undefined; var i: usize = 0; while (auxv[i].a_type != std.elf.AT_NULL) : (i += 1) { @@ -146,16 +146,6 @@ pub fn initTLS() void { } } - // If the cpu is arm-based, check if it supports the TLS register - if (at_hwcap) |hwcap| { - if (builtin.arch == builtin.Arch.arm and hwcap & std.os.linux.HWCAP_TLS == 0) { - // If the CPU does not support TLS via a coprocessor register, - // a kernel helper function can be used instead on certain linux kernels. - // See linux/arch/arm/include/asm/tls.h and musl/src/thread/arm/__set_thread_area.c. - @panic("TODO: Implement ARM fallback TLS functionality"); - } - } - // Sanity check assert(at_phent == @sizeOf(elf.Phdr)); @@ -171,6 +161,14 @@ pub fn initTLS() void { } if (tls_phdr) |phdr| { + // If the cpu is arm-based, check if it supports the TLS register + if (builtin.arch == builtin.Arch.arm and hwcap & std.os.linux.HWCAP_TLS == 0) { + // If the CPU does not support TLS via a coprocessor register, + // a kernel helper function can be used instead on certain linux kernels. + // See linux/arch/arm/include/asm/tls.h and musl/src/thread/arm/__set_thread_area.c. + @panic("TODO: Implement ARM fallback TLS functionality"); + } + // Offsets into the allocated TLS area var tcb_offset: usize = undefined; var dtv_offset: usize = undefined; -- 2.54.0 From e540e5b8ec1d90b86d6f41814507e6ae4ae5edd8 Mon Sep 17 00:00:00 2001 From: Timon Kruiper Date: Thu, 11 Jul 2019 15:17:35 +0200 Subject: [PATCH 37/80] Implicit cast from enum literal to optional enum and implicit cast to payload of error union --- src/ir.cpp | 61 +++++++++++++++++++++++++++-------- test/stage1/behavior/enum.zig | 14 ++++++++ 2 files changed, 61 insertions(+), 14 deletions(-) diff --git a/src/ir.cpp b/src/ir.cpp index 9547b1ec619a0d4a22bfda1e29b7c2b21e8e7622..bf0b1188b1f7088cc41ace1f6b90e26103f513c5 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -12081,6 +12081,29 @@ static bool is_pointery_and_elem_is_not_pointery(ZigType *ty) { return false; } +static IrInstruction *ir_analyze_enum_literal(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value, + ZigType *enum_type) +{ + assert(enum_type->id == ZigTypeIdEnum); + + Error err; + if ((err = type_resolve(ira->codegen, enum_type, ResolveStatusZeroBitsKnown))) + return ira->codegen->invalid_instruction; + + TypeEnumField *field = find_enum_type_field(enum_type, value->value.data.x_enum_literal); + if (field == nullptr) { + ErrorMsg *msg = ir_add_error(ira, source_instr, buf_sprintf("enum '%s' has no field named '%s'", + buf_ptr(&enum_type->name), buf_ptr(value->value.data.x_enum_literal))); + add_error_note(ira->codegen, msg, enum_type->data.enumeration.decl_node, + buf_sprintf("'%s' declared here", buf_ptr(&enum_type->name))); + return ira->codegen->invalid_instruction; + } + IrInstruction *result = ir_const(ira, source_instr, enum_type); + bigint_init_bigint(&result->value.data.x_enum_tag, &field->value); + + return result; +} + static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_instr, ZigType *wanted_type, IrInstruction *value, ResultLoc *result_loc) { @@ -12439,21 +12462,31 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst } // cast from enum literal to enum with matching field name - if (actual_type->id == ZigTypeIdEnumLiteral && wanted_type->id == ZigTypeIdEnum) { - if ((err = type_resolve(ira->codegen, wanted_type, ResolveStatusZeroBitsKnown))) - return ira->codegen->invalid_instruction; + if (actual_type->id == ZigTypeIdEnumLiteral && wanted_type->id == ZigTypeIdEnum) + { + return ir_analyze_enum_literal(ira, source_instr, value, wanted_type); + } - TypeEnumField *field = find_enum_type_field(wanted_type, value->value.data.x_enum_literal); - if (field == nullptr) { - ErrorMsg *msg = ir_add_error(ira, source_instr, buf_sprintf("enum '%s' has no field named '%s'", - buf_ptr(&wanted_type->name), buf_ptr(value->value.data.x_enum_literal))); - add_error_note(ira->codegen, msg, wanted_type->data.enumeration.decl_node, - buf_sprintf("'%s' declared here", buf_ptr(&wanted_type->name))); - return ira->codegen->invalid_instruction; - } - IrInstruction *result = ir_const(ira, source_instr, wanted_type); - bigint_init_bigint(&result->value.data.x_enum_tag, &field->value); - return result; + // cast from enum literal to optional enum + if (actual_type->id == ZigTypeIdEnumLiteral && + (wanted_type->id == ZigTypeIdOptional && wanted_type->data.maybe.child_type->id == ZigTypeIdEnum)) + { + IrInstruction *result = ir_analyze_enum_literal(ira, source_instr, value, wanted_type->data.maybe.child_type); + if (result == ira->codegen->invalid_instruction) + return result; + + return ir_analyze_optional_wrap(ira, result, value, wanted_type, result_loc); + } + + // cast from enum literal to error union when payload is an enum + if (actual_type->id == ZigTypeIdEnumLiteral && + (wanted_type->id == ZigTypeIdErrorUnion && wanted_type->data.error_union.payload_type->id == ZigTypeIdEnum)) + { + IrInstruction *result = ir_analyze_enum_literal(ira, source_instr, value, wanted_type->data.error_union.payload_type); + if (result == ira->codegen->invalid_instruction) + return result; + + return ir_analyze_err_wrap_payload(ira, result, value, wanted_type, result_loc); } // cast from union to the enum type of the union diff --git a/test/stage1/behavior/enum.zig b/test/stage1/behavior/enum.zig index d7d34aec882706965d3eaccd39e3b321244f1e72..24ea2f9583c699c7d0a30758a3b737a5d11de9b4 100644 --- a/test/stage1/behavior/enum.zig +++ b/test/stage1/behavior/enum.zig @@ -993,3 +993,17 @@ test "enum with one member and custom tag type" { }; expect(@enumToInt(E2.One) == 2); } + +test "enum literal casting to optional" { + var bar: ?Bar = undefined; + bar = .B; + + expect(bar.? == Bar.B); +} + +test "enum literal casting to error union with payload enum" { + var bar: error{B}!Bar = undefined; + bar = .B; // should never cast to the error set + + expect((try bar) == Bar.B); +} -- 2.54.0 From a7fd14096c8dbc9cb5ed9a3731753b24e32d5757 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 4 Sep 2019 14:44:03 -0400 Subject: [PATCH 38/80] fix typo with tls initialization I tested that hello world cross compiles to armv7 now. closes #3167 --- std/os/linux/tls.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/std/os/linux/tls.zig b/std/os/linux/tls.zig index 3c55013f47b4a2e0876abbd27215474934aa4c58..ea1075e77ae2562ba25552cd76c41ea66446c5d1 100644 --- a/std/os/linux/tls.zig +++ b/std/os/linux/tls.zig @@ -162,7 +162,7 @@ pub fn initTLS() void { if (tls_phdr) |phdr| { // If the cpu is arm-based, check if it supports the TLS register - if (builtin.arch == builtin.Arch.arm and hwcap & std.os.linux.HWCAP_TLS == 0) { + if (builtin.arch == builtin.Arch.arm and at_hwcap & std.os.linux.HWCAP_TLS == 0) { // If the CPU does not support TLS via a coprocessor register, // a kernel helper function can be used instead on certain linux kernels. // See linux/arch/arm/include/asm/tls.h and musl/src/thread/arm/__set_thread_area.c. -- 2.54.0 From fabf45f5fc0a1827913be5675130db5db514c136 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Thu, 5 Sep 2019 12:22:02 +0200 Subject: [PATCH 39/80] Add the noinline keyword for function declarations --- doc/docgen.zig | 1 + src/all_types.hpp | 14 +++++++------- src/analyze.cpp | 3 +-- src/ast_render.cpp | 11 ++++++++--- src/parser.cpp | 19 ++++++++++++++++--- src/tokenizer.cpp | 2 ++ src/tokenizer.hpp | 1 + src/translate_c.cpp | 2 +- std/zig/parse.zig | 6 ++++-- std/zig/parser_test.zig | 3 +++ std/zig/tokenizer.zig | 2 ++ 11 files changed, 46 insertions(+), 18 deletions(-) diff --git a/doc/docgen.zig b/doc/docgen.zig index eee4c453694c91d11dc99587b66b543b1a25f46d..6ce5902dccd2ab36e968d2d87b673ed4a79a3274 100644 --- a/doc/docgen.zig +++ b/doc/docgen.zig @@ -786,6 +786,7 @@ fn tokenizeAndPrintRaw(docgen_tokenizer: *Tokenizer, out: var, source_token: Tok .Keyword_for, .Keyword_if, .Keyword_inline, + .Keyword_noinline, .Keyword_nakedcc, .Keyword_noalias, .Keyword_or, diff --git a/src/all_types.hpp b/src/all_types.hpp index 03559ccf12f2f696676121e52706c2c178c985d4..f1ecfe2be7c77bf99d9821f95ba2ace0aca29271 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -603,6 +603,12 @@ enum CallingConvention { CallingConventionAsync, }; +enum FnInline { + FnInlineAuto, + FnInlineAlways, + FnInlineNever, +}; + struct AstNodeFnProto { VisibMod visib_mod; Buf *name; @@ -612,7 +618,7 @@ struct AstNodeFnProto { bool is_var_args; bool is_extern; bool is_export; - bool is_inline; + FnInline fn_inline; CallingConvention cc; AstNode *fn_def_node; // populated if this is an extern declaration @@ -1453,12 +1459,6 @@ enum FnAnalState { FnAnalStateInvalid, }; -enum FnInline { - FnInlineAuto, - FnInlineAlways, - FnInlineNever, -}; - struct GlobalExport { Buf name; GlobalLinkageId linkage; diff --git a/src/analyze.cpp b/src/analyze.cpp index e1d6b59ddf0b5e10c109c45e1e34225e3d01c4ba..87758df3e19079fda66f76e9e6a8b19688e83b3f 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -3066,8 +3066,7 @@ ZigFn *create_fn(CodeGen *g, AstNode *proto_node) { assert(proto_node->type == NodeTypeFnProto); AstNodeFnProto *fn_proto = &proto_node->data.fn_proto; - FnInline inline_value = fn_proto->is_inline ? FnInlineAlways : FnInlineAuto; - ZigFn *fn_entry = create_fn_raw(g, inline_value); + ZigFn *fn_entry = create_fn_raw(g, fn_proto->fn_inline); fn_entry->proto_node = proto_node; fn_entry->body_node = (proto_node->data.fn_proto.fn_def_node == nullptr) ? nullptr : diff --git a/src/ast_render.cpp b/src/ast_render.cpp index 54a659f7b13dea27c6a499f0ceaf8d142690a5c0..fedd46a48bf789d04f93f878db16882e9edc446a 100644 --- a/src/ast_render.cpp +++ b/src/ast_render.cpp @@ -124,8 +124,13 @@ static const char *export_string(bool is_export) { // zig_unreachable(); //} -static const char *inline_string(bool is_inline) { - return is_inline ? "inline " : ""; +static const char *inline_string(FnInline fn_inline) { + switch (fn_inline) { + case FnInlineAlways: return "inline "; + case FnInlineNever: return "noinline "; + case FnInlineAuto: return ""; + } + zig_unreachable(); } static const char *const_or_var_string(bool is_const) { @@ -436,7 +441,7 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { const char *pub_str = visib_mod_string(node->data.fn_proto.visib_mod); const char *extern_str = extern_string(node->data.fn_proto.is_extern); const char *export_str = export_string(node->data.fn_proto.is_export); - const char *inline_str = inline_string(node->data.fn_proto.is_inline); + const char *inline_str = inline_string(node->data.fn_proto.fn_inline); fprintf(ar->f, "%s%s%s%sfn ", pub_str, inline_str, export_str, extern_str); if (node->data.fn_proto.name != nullptr) { print_symbol(ar, node->data.fn_proto.name); diff --git a/src/parser.cpp b/src/parser.cpp index 21bbc4d2461442f36581dc044245f3c57bc3b61d..ba8757e4aeca2ff076f637bfef3bd8592f33607d 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -578,7 +578,7 @@ static AstNode *ast_parse_top_level_comptime(ParseContext *pc) { } // TopLevelDecl -// <- (KEYWORD_export / KEYWORD_extern STRINGLITERAL? / KEYWORD_inline)? FnProto (SEMICOLON / Block) +// <- (KEYWORD_export / KEYWORD_extern STRINGLITERAL? / (KEYWORD_inline / KEYWORD_noinline))? FnProto (SEMICOLON / Block) // / (KEYWORD_export / KEYWORD_extern STRINGLITERAL?)? KEYWORD_threadlocal? VarDecl // / KEYWORD_use Expr SEMICOLON static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod) { @@ -587,12 +587,14 @@ static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod) { first = eat_token_if(pc, TokenIdKeywordExtern); if (first == nullptr) first = eat_token_if(pc, TokenIdKeywordInline); + if (first == nullptr) + first = eat_token_if(pc, TokenIdKeywordNoInline); if (first != nullptr) { Token *lib_name = nullptr; if (first->id == TokenIdKeywordExtern) lib_name = eat_token_if(pc, TokenIdStringLiteral); - if (first->id != TokenIdKeywordInline) { + if (first->id != TokenIdKeywordInline && first->id != TokenIdKeywordNoInline) { Token *thread_local_kw = eat_token_if(pc, TokenIdKeywordThreadLocal); AstNode *var_decl = ast_parse_var_decl(pc); if (var_decl != nullptr) { @@ -623,8 +625,19 @@ static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod) { fn_proto->data.fn_proto.visib_mod = visib_mod; fn_proto->data.fn_proto.is_extern = first->id == TokenIdKeywordExtern; fn_proto->data.fn_proto.is_export = first->id == TokenIdKeywordExport; - fn_proto->data.fn_proto.is_inline = first->id == TokenIdKeywordInline; + switch (first->id) { + case TokenIdKeywordInline: + fn_proto->data.fn_proto.fn_inline = FnInlineAlways; + break; + case TokenIdKeywordNoInline: + fn_proto->data.fn_proto.fn_inline = FnInlineNever; + break; + default: + fn_proto->data.fn_proto.fn_inline = FnInlineAuto; + break; + } fn_proto->data.fn_proto.lib_name = token_buf(lib_name); + AstNode *res = fn_proto; if (body != nullptr) { res = ast_create_node_copy_line_info(pc, NodeTypeFnDef, fn_proto); diff --git a/src/tokenizer.cpp b/src/tokenizer.cpp index 9c9effcb1076ac60df0d5547f60665b6f5b1436c..8ef320331ae324e3613dafa2f4e6aa79ae915d0f 100644 --- a/src/tokenizer.cpp +++ b/src/tokenizer.cpp @@ -130,6 +130,7 @@ static const struct ZigKeyword zig_keywords[] = { {"for", TokenIdKeywordFor}, {"if", TokenIdKeywordIf}, {"inline", TokenIdKeywordInline}, + {"noinline", TokenIdKeywordNoInline}, {"nakedcc", TokenIdKeywordNakedCC}, {"noalias", TokenIdKeywordNoAlias}, {"null", TokenIdKeywordNull}, @@ -1551,6 +1552,7 @@ const char * token_name(TokenId id) { case TokenIdKeywordFor: return "for"; case TokenIdKeywordIf: return "if"; case TokenIdKeywordInline: return "inline"; + case TokenIdKeywordNoInline: return "noinline"; case TokenIdKeywordNakedCC: return "nakedcc"; case TokenIdKeywordNoAlias: return "noalias"; case TokenIdKeywordNull: return "null"; diff --git a/src/tokenizer.hpp b/src/tokenizer.hpp index ce62f5dc87b21384e707d7d630c4439a0af4ccf1..70d828b39d058a7733205b0ab9f0b9ecd76ae581 100644 --- a/src/tokenizer.hpp +++ b/src/tokenizer.hpp @@ -74,6 +74,7 @@ enum TokenId { TokenIdKeywordFor, TokenIdKeywordIf, TokenIdKeywordInline, + TokenIdKeywordNoInline, TokenIdKeywordLinkSection, TokenIdKeywordNakedCC, TokenIdKeywordNoAlias, diff --git a/src/translate_c.cpp b/src/translate_c.cpp index 69c70958e57f3384a70b746a98f53cddb97ff61d..eb591107836340b1342a3a1202b8d3a266d99485 100644 --- a/src/translate_c.cpp +++ b/src/translate_c.cpp @@ -432,7 +432,7 @@ static AstNode *trans_create_node_inline_fn(Context *c, Buf *fn_name, AstNode *r AstNode *fn_proto = trans_create_node(c, NodeTypeFnProto); fn_proto->data.fn_proto.visib_mod = c->visib_mod; fn_proto->data.fn_proto.name = fn_name; - fn_proto->data.fn_proto.is_inline = true; + fn_proto->data.fn_proto.fn_inline = FnInlineAlways; fn_proto->data.fn_proto.return_type = src_proto_node->data.fn_proto.return_type; // TODO ok for these to alias? fn_def->data.fn_def.fn_proto = fn_proto; diff --git a/std/zig/parse.zig b/std/zig/parse.zig index 0511b6dce079660c02f8a6497f0458c4de05657d..4ffcdc962272431c24c146b26117db5d93ede56f 100644 --- a/std/zig/parse.zig +++ b/std/zig/parse.zig @@ -201,7 +201,7 @@ fn parseTopLevelComptime(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?* } /// TopLevelDecl -/// <- (KEYWORD_export / KEYWORD_extern STRINGLITERAL? / KEYWORD_inline)? FnProto (SEMICOLON / Block) +/// <- (KEYWORD_export / KEYWORD_extern STRINGLITERAL? / (KEYWORD_inline / KEYWORD_noinline))? FnProto (SEMICOLON / Block) /// / (KEYWORD_export / KEYWORD_extern STRINGLITERAL?)? KEYWORD_threadlocal? VarDecl /// / KEYWORD_usingnamespace Expr SEMICOLON fn parseTopLevelDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { @@ -213,6 +213,7 @@ fn parseTopLevelDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node break :blk token; } if (eatToken(it, .Keyword_inline)) |token| break :blk token; + if (eatToken(it, .Keyword_noinline)) |token| break :blk token; break :blk null; }; @@ -232,7 +233,8 @@ fn parseTopLevelDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node } if (extern_export_inline_token) |token| { - if (tree.tokens.at(token).id == .Keyword_inline) { + if (tree.tokens.at(token).id == .Keyword_inline or + tree.tokens.at(token).id == .Keyword_noinline) { putBackToken(it, token); return null; } diff --git a/std/zig/parser_test.zig b/std/zig/parser_test.zig index 821ead9db5f0466556b44ff96f5ee8c7515c4f8f..c1fa399f09a434c9728f6e1e3e7bc22b99b810aa 100644 --- a/std/zig/parser_test.zig +++ b/std/zig/parser_test.zig @@ -1677,14 +1677,17 @@ test "zig fmt: functions" { \\extern "c" fn puts(s: *const u8) c_int; \\export fn puts(s: *const u8) c_int; \\inline fn puts(s: *const u8) c_int; + \\noinline fn puts(s: *const u8) c_int; \\pub extern fn puts(s: *const u8) c_int; \\pub extern "c" fn puts(s: *const u8) c_int; \\pub export fn puts(s: *const u8) c_int; \\pub inline fn puts(s: *const u8) c_int; + \\pub noinline fn puts(s: *const u8) c_int; \\pub extern fn puts(s: *const u8) align(2 + 2) c_int; \\pub extern "c" fn puts(s: *const u8) align(2 + 2) c_int; \\pub export fn puts(s: *const u8) align(2 + 2) c_int; \\pub inline fn puts(s: *const u8) align(2 + 2) c_int; + \\pub noinline fn puts(s: *const u8) align(2 + 2) c_int; \\ ); } diff --git a/std/zig/tokenizer.zig b/std/zig/tokenizer.zig index 4d4ceb07dbf10a8681e57c105d1e794f69081dc6..204121f64c59dd82436aa491d979e3fe13ee20f3 100644 --- a/std/zig/tokenizer.zig +++ b/std/zig/tokenizer.zig @@ -36,6 +36,7 @@ pub const Token = struct { Keyword{ .bytes = "for", .id = Id.Keyword_for }, Keyword{ .bytes = "if", .id = Id.Keyword_if }, Keyword{ .bytes = "inline", .id = Id.Keyword_inline }, + Keyword{ .bytes = "noinline", .id = Id.Keyword_noinline }, Keyword{ .bytes = "nakedcc", .id = Id.Keyword_nakedcc }, Keyword{ .bytes = "noalias", .id = Id.Keyword_noalias }, Keyword{ .bytes = "null", .id = Id.Keyword_null }, @@ -166,6 +167,7 @@ pub const Token = struct { Keyword_for, Keyword_if, Keyword_inline, + Keyword_noinline, Keyword_nakedcc, Keyword_noalias, Keyword_null, -- 2.54.0 From fe153ad2a435e26f9904f05858232305bdffd3ac Mon Sep 17 00:00:00 2001 From: Michael Dusan Date: Wed, 4 Sep 2019 16:04:43 -0400 Subject: [PATCH 40/80] stage1 enhance IR print - print fn name in pass1 - replace scalar with enum IrPass for clarity --- src/analyze.cpp | 6 +++--- src/ir.cpp | 4 ++-- src/ir.hpp | 5 +++++ src/ir_print.cpp | 14 +++++++------- src/ir_print.hpp | 4 ++-- 5 files changed, 19 insertions(+), 14 deletions(-) diff --git a/src/analyze.cpp b/src/analyze.cpp index 87758df3e19079fda66f76e9e6a8b19688e83b3f..5003756be7bf8db88228c832cc36f458d69f1e33 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -4418,7 +4418,7 @@ static void analyze_fn_ir(CodeGen *g, ZigFn *fn, AstNode *return_type_node) { if (g->verbose_ir) { fprintf(stderr, "fn %s() { // (analyzed)\n", buf_ptr(&fn->symbol_name)); - ir_print(g, stderr, &fn->analyzed_executable, 4, 2); + ir_print(g, stderr, &fn->analyzed_executable, 4, IrPassGen); fprintf(stderr, "}\n"); } fn->anal_state = FnAnalStateComplete; @@ -4451,8 +4451,8 @@ static void analyze_fn_body(CodeGen *g, ZigFn *fn_table_entry) { if (g->verbose_ir) { fprintf(stderr, "\n"); ast_render(stderr, fn_table_entry->body_node, 4); - fprintf(stderr, "\n{ // (IR)\n"); - ir_print(g, stderr, &fn_table_entry->ir_executable, 4, 1); + fprintf(stderr, "\nfn %s() { // (IR)\n", buf_ptr(&fn_table_entry->symbol_name)); + ir_print(g, stderr, &fn_table_entry->ir_executable, 4, IrPassSrc); fprintf(stderr, "}\n"); } diff --git a/src/ir.cpp b/src/ir.cpp index bf0b1188b1f7088cc41ace1f6b90e26103f513c5..054fbf00734f3a867f2311289de68f38354af4d6 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -10892,7 +10892,7 @@ ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *nod fprintf(stderr, "\nSource: "); ast_render(stderr, node, 4); fprintf(stderr, "\n{ // (IR)\n"); - ir_print(codegen, stderr, ir_executable, 2, 1); + ir_print(codegen, stderr, ir_executable, 2, IrPassSrc); fprintf(stderr, "}\n"); } IrExecutable *analyzed_executable = allocate(1); @@ -10913,7 +10913,7 @@ ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *nod if (codegen->verbose_ir) { fprintf(stderr, "{ // (analyzed)\n"); - ir_print(codegen, stderr, analyzed_executable, 2, 2); + ir_print(codegen, stderr, analyzed_executable, 2, IrPassGen); fprintf(stderr, "}\n"); } diff --git a/src/ir.hpp b/src/ir.hpp index 3923ea28e8e241c1902134493746ac6748efe70f..d3ec33aef64f68e46bc1f13fcf4ff1f233754a0a 100644 --- a/src/ir.hpp +++ b/src/ir.hpp @@ -10,6 +10,11 @@ #include "all_types.hpp" +enum IrPass { + IrPassSrc, + IrPassGen, +}; + bool ir_gen(CodeGen *g, AstNode *node, Scope *scope, IrExecutable *ir_executable); bool ir_gen_fn(CodeGen *g, ZigFn *fn_entry); diff --git a/src/ir_print.cpp b/src/ir_print.cpp index 25eb01365ff6a47ba92bbfe2cf90e02de36bde6f..85d89cdb88122b991a5aa573cb5b0b951948867c 100644 --- a/src/ir_print.cpp +++ b/src/ir_print.cpp @@ -22,7 +22,7 @@ using InstructionSet = HashMap; struct IrPrint { - size_t pass_num; + IrPass pass; CodeGen *codegen; FILE *f; int indent; @@ -391,7 +391,7 @@ static void ir_print_const_value(IrPrint *irp, ConstExprValue *const_val) { static void ir_print_var_instruction(IrPrint *irp, IrInstruction *instruction) { fprintf(irp->f, "#%" ZIG_PRI_usize "", instruction->debug_id); - if (irp->pass_num == 2 && irp->printed.maybe_get(instruction) == nullptr) { + if (irp->pass != IrPassSrc && irp->printed.maybe_get(instruction) == nullptr) { irp->printed.put(instruction, 0); irp->pending.append(instruction); } @@ -2399,10 +2399,10 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction, bool fprintf(irp->f, "\n"); } -void ir_print(CodeGen *codegen, FILE *f, IrExecutable *executable, int indent_size, size_t pass_num) { +void ir_print(CodeGen *codegen, FILE *f, IrExecutable *executable, int indent_size, IrPass pass) { IrPrint ir_print = {}; IrPrint *irp = &ir_print; - irp->pass_num = pass_num; + irp->pass = pass; irp->codegen = codegen; irp->f = f; irp->indent = indent_size; @@ -2416,7 +2416,7 @@ void ir_print(CodeGen *codegen, FILE *f, IrExecutable *executable, int indent_si fprintf(irp->f, "%s_%" ZIG_PRI_usize ":\n", current_block->name_hint, current_block->debug_id); for (size_t instr_i = 0; instr_i < current_block->instruction_list.length; instr_i += 1) { IrInstruction *instruction = current_block->instruction_list.at(instr_i); - if (irp->pass_num == 2) { + if (irp->pass != IrPassSrc) { irp->printed.put(instruction, 0); irp->pending.clear(); } @@ -2430,10 +2430,10 @@ void ir_print(CodeGen *codegen, FILE *f, IrExecutable *executable, int indent_si irp->printed.deinit(); } -void ir_print_instruction(CodeGen *codegen, FILE *f, IrInstruction *instruction, int indent_size, size_t pass_num) { +void ir_print_instruction(CodeGen *codegen, FILE *f, IrInstruction *instruction, int indent_size, IrPass pass) { IrPrint ir_print = {}; IrPrint *irp = &ir_print; - irp->pass_num = pass_num; + irp->pass = pass; irp->codegen = codegen; irp->f = f; irp->indent = indent_size; diff --git a/src/ir_print.hpp b/src/ir_print.hpp index 3e554ceb95fdd40fdca228cdaeec626cfd15853b..0960af4e6fe8c103cab6d42c3a7b8f003d0a7bdc 100644 --- a/src/ir_print.hpp +++ b/src/ir_print.hpp @@ -12,7 +12,7 @@ #include -void ir_print(CodeGen *codegen, FILE *f, IrExecutable *executable, int indent_size, size_t pass_num); -void ir_print_instruction(CodeGen *codegen, FILE *f, IrInstruction *instruction, int indent_size, size_t pass_num); +void ir_print(CodeGen *codegen, FILE *f, IrExecutable *executable, int indent_size, IrPass pass); +void ir_print_instruction(CodeGen *codegen, FILE *f, IrInstruction *instruction, int indent_size, IrPass pass); #endif -- 2.54.0 From 847a262efdf5f3a359b00f13c101236dc0747f1b Mon Sep 17 00:00:00 2001 From: Vesa Kaihlavirta Date: Wed, 4 Sep 2019 20:02:31 +0300 Subject: [PATCH 41/80] Shorten @field documentation and add an example --- doc/langref.html.in | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/doc/langref.html.in b/doc/langref.html.in index 2ad86d653e21d874507ef51496b5e08419a0d7e9..374fbfcde536bbe267fa9e92f2483f887d118dcf 100644 --- a/doc/langref.html.in +++ b/doc/langref.html.in @@ -6976,10 +6976,28 @@ export fn @"A function name that is a complete sentence."() void {} {#header_open|@field#}

        {#syntax#}@field(lhs: var, comptime field_name: []const u8) (field){#endsyntax#}
        -

        Preforms field access equivalent to {#syntax#}lhs.field_name{#endsyntax#}, except instead - of the field {#syntax#}"field_name"{#endsyntax#}, it accesses the field named by the string - value of {#syntax#}field_name{#endsyntax#}. +

        Performs field access by a compile-time string.

        + {#code_begin|test#} +const std = @import("std"); + +const Point = struct { + x: u32, + y: u32 +}; + +test "field access by string" { + const assert = std.debug.assert; + var p = Point {.x = 0, .y = 0}; + + @field(p, "x") = 4; + @field(p, "y") = @field(p, "x") + 1; + + assert(@field(p, "x") == 4); + assert(@field(p, "y") == 5); +} + {#code_end#} + {#header_close#} {#header_open|@fieldParentPtr#} -- 2.54.0 From 9a358d2d33b0ecdec38ba3698acf8b239c43b667 Mon Sep 17 00:00:00 2001 From: Jonathan Marler Date: Wed, 4 Sep 2019 11:08:49 -0600 Subject: [PATCH 42/80] Add Array support to @Type --- src/ir.cpp | 8 +++++++- test/stage1/behavior/type.zig | 6 ++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/ir.cpp b/src/ir.cpp index 054fbf00734f3a867f2311289de68f38354af4d6..03e084e5ce9330f910abe66e82d852408c5edcc1 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -20942,6 +20942,13 @@ static ZigType *type_info_to_type(IrAnalyze *ira, IrInstruction *instruction, Zi return ptr_type; return get_slice_type(ira->codegen, ptr_type); } + case ZigTypeIdArray: + assert(payload->special == ConstValSpecialStatic); + assert(payload->type == ir_type_info_get_type(ira, "Array", nullptr)); + return get_array_type(ira->codegen, + get_const_field_meta_type(ira, payload, "child", 1), + bigint_as_u64(get_const_field_lit_int(ira, payload, "len", 0)) + ); case ZigTypeIdComptimeFloat: return ira->codegen->builtin_types.entry_num_lit_float; case ZigTypeIdComptimeInt: @@ -20950,7 +20957,6 @@ static ZigType *type_info_to_type(IrAnalyze *ira, IrInstruction *instruction, Zi return ira->codegen->builtin_types.entry_undef; case ZigTypeIdNull: return ira->codegen->builtin_types.entry_null; - case ZigTypeIdArray: case ZigTypeIdOptional: case ZigTypeIdErrorUnion: case ZigTypeIdErrorSet: diff --git a/test/stage1/behavior/type.zig b/test/stage1/behavior/type.zig index 5b2998f08831477bf370c938c48025665c34a4a2..b84369a16490dfbfd6b2ecaa0a06ca3062484e56 100644 --- a/test/stage1/behavior/type.zig +++ b/test/stage1/behavior/type.zig @@ -93,6 +93,12 @@ test "Type.Pointer" { }); } +test "Type.Array" { + testing.expect([123]u8 == @Type(TypeInfo { .Array = TypeInfo.Array { .len = 123, .child = u8 } })); + testing.expect([2]u32 == @Type(TypeInfo { .Array = TypeInfo.Array { .len = 2, .child = u32 } })); + testTypes([_]type {[1]u8, [30]usize, [7]bool}); +} + test "Type.ComptimeFloat" { testTypes([_]type {comptime_float}); } -- 2.54.0 From 0107b19124255179a48cd605f31ed57d5ade28e7 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Thu, 5 Sep 2019 10:17:47 +0200 Subject: [PATCH 43/80] Resolve lazy values when checking for definedness Fixes #3154 --- src/codegen.cpp | 23 +++++++++++++--------- test/stage1/behavior/sizeof_and_typeof.zig | 9 +++++++++ 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/src/codegen.cpp b/src/codegen.cpp index 13fb0d625d0a52f2f505e9b7cf26d1d5e68de0f6..9c8ccd7040e75c60dcabc6ce445252d1a1541cb5 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -183,7 +183,7 @@ static void render_const_val(CodeGen *g, ConstExprValue *const_val, const char * static void render_const_val_global(CodeGen *g, ConstExprValue *const_val, const char *name); static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const char *name); static void generate_error_name_table(CodeGen *g); -static bool value_is_all_undef(ConstExprValue *const_val); +static bool value_is_all_undef(CodeGen *g, ConstExprValue *const_val); static void gen_undef_init(CodeGen *g, uint32_t ptr_align_bytes, ZigType *value_type, LLVMValueRef ptr); static LLVMValueRef build_alloca(CodeGen *g, ZigType *type_entry, const char *name, uint32_t alignment); @@ -3377,7 +3377,7 @@ static LLVMValueRef ir_render_load_ptr(CodeGen *g, IrExecutable *executable, IrI return LLVMBuildTrunc(g->builder, shifted_value, get_llvm_type(g, child_type), ""); } -static bool value_is_all_undef_array(ConstExprValue *const_val, size_t len) { +static bool value_is_all_undef_array(CodeGen *g, ConstExprValue *const_val, size_t len) { switch (const_val->data.x_array.special) { case ConstArraySpecialUndef: return true; @@ -3385,7 +3385,7 @@ static bool value_is_all_undef_array(ConstExprValue *const_val, size_t len) { return false; case ConstArraySpecialNone: for (size_t i = 0; i < len; i += 1) { - if (!value_is_all_undef(&const_val->data.x_array.data.s_none.elements[i])) + if (!value_is_all_undef(g, &const_val->data.x_array.data.s_none.elements[i])) return false; } return true; @@ -3393,7 +3393,12 @@ static bool value_is_all_undef_array(ConstExprValue *const_val, size_t len) { zig_unreachable(); } -static bool value_is_all_undef(ConstExprValue *const_val) { +static bool value_is_all_undef(CodeGen *g, ConstExprValue *const_val) { + Error err; + if (const_val->special == ConstValSpecialLazy && + (err = ir_resolve_lazy(g, nullptr, const_val))) + report_errors_and_exit(g); + switch (const_val->special) { case ConstValSpecialLazy: zig_unreachable(); @@ -3404,14 +3409,14 @@ static bool value_is_all_undef(ConstExprValue *const_val) { case ConstValSpecialStatic: if (const_val->type->id == ZigTypeIdStruct) { for (size_t i = 0; i < const_val->type->data.structure.src_field_count; i += 1) { - if (!value_is_all_undef(&const_val->data.x_struct.fields[i])) + if (!value_is_all_undef(g, &const_val->data.x_struct.fields[i])) return false; } return true; } else if (const_val->type->id == ZigTypeIdArray) { - return value_is_all_undef_array(const_val, const_val->type->data.array.len); + return value_is_all_undef_array(g, const_val, const_val->type->data.array.len); } else if (const_val->type->id == ZigTypeIdVector) { - return value_is_all_undef_array(const_val, const_val->type->data.vector.len); + return value_is_all_undef_array(g, const_val, const_val->type->data.vector.len); } else { return false; } @@ -3532,7 +3537,7 @@ static LLVMValueRef ir_render_store_ptr(CodeGen *g, IrExecutable *executable, Ir return nullptr; } - bool have_init_expr = !value_is_all_undef(&instruction->value->value); + bool have_init_expr = !value_is_all_undef(g, &instruction->value->value); if (have_init_expr) { LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr); LLVMValueRef value = ir_llvm_value(g, instruction->value); @@ -4887,7 +4892,7 @@ static LLVMValueRef ir_render_memset(CodeGen *g, IrExecutable *executable, IrIns ZigType *ptr_type = instruction->dest_ptr->value.type; assert(ptr_type->id == ZigTypeIdPointer); - bool val_is_undef = value_is_all_undef(&instruction->byte->value); + bool val_is_undef = value_is_all_undef(g, &instruction->byte->value); LLVMValueRef fill_char; if (val_is_undef) { fill_char = LLVMConstInt(LLVMInt8Type(), 0xaa, false); diff --git a/test/stage1/behavior/sizeof_and_typeof.zig b/test/stage1/behavior/sizeof_and_typeof.zig index 6f57bfedd506716719408ec924b91081fe24bf50..0369be99892510bf11752ad8d9a4d8bd46561fe9 100644 --- a/test/stage1/behavior/sizeof_and_typeof.zig +++ b/test/stage1/behavior/sizeof_and_typeof.zig @@ -115,3 +115,12 @@ test "branching logic inside @typeOf" { comptime expect(T == i32); expect(S.data == 0); } + +fn fn1(alpha: bool) void { + const n: usize = 7; + const v = if (alpha) n else @sizeOf(usize); +} + +test "lazy @sizeOf result is checked for definedness" { + const f = fn1; +} -- 2.54.0 From 8e3c56b912b7eb6ee551b7e427adbaae0bdcd408 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Sun, 1 Sep 2019 19:47:58 +0200 Subject: [PATCH 44/80] Always resolve the struct field types Packed structs used to skip the zero-sized types and trip some assertions that expected the type reference not to be null. Fixes #3143 --- src/analyze.cpp | 42 +++++++++++++++------------------ test/stage1/behavior/struct.zig | 8 +++++++ 2 files changed, 27 insertions(+), 23 deletions(-) diff --git a/src/analyze.cpp b/src/analyze.cpp index 5003756be7bf8db88228c832cc36f458d69f1e33..386ee4ec46c81b7850051b322092546fed82654e 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -2043,34 +2043,30 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) { // Resolve types for fields - if (!packed) { - for (size_t i = 0; i < field_count; i += 1) { - TypeStructField *field = &struct_type->data.structure.fields[i]; - ZigType *field_type = resolve_struct_field_type(g, field); - if (field_type == nullptr) { - struct_type->data.structure.resolve_status = ResolveStatusInvalid; - return err; - } + for (size_t i = 0; i < field_count; i += 1) { + TypeStructField *field = &struct_type->data.structure.fields[i]; + ZigType *field_type = resolve_struct_field_type(g, field); + if (field_type == nullptr) { + struct_type->data.structure.resolve_status = ResolveStatusInvalid; + return err; + } - if ((err = type_resolve(g, field_type, ResolveStatusSizeKnown))) { - struct_type->data.structure.resolve_status = ResolveStatusInvalid; - return err; - } - - if (struct_type->data.structure.layout == ContainerLayoutExtern && - !type_allowed_in_extern(g, field_type)) - { - add_node_error(g, field->decl_node, - buf_sprintf("extern structs cannot contain fields of type '%s'", - buf_ptr(&field_type->name))); - struct_type->data.structure.resolve_status = ResolveStatusInvalid; - return ErrorSemanticAnalyzeFail; - } + if ((err = type_resolve(g, field_type, ResolveStatusSizeKnown))) { + struct_type->data.structure.resolve_status = ResolveStatusInvalid; + return err; + } + if (struct_type->data.structure.layout == ContainerLayoutExtern && + !type_allowed_in_extern(g, field_type)) + { + add_node_error(g, field->decl_node, + buf_sprintf("extern structs cannot contain fields of type '%s'", + buf_ptr(&field_type->name))); + struct_type->data.structure.resolve_status = ResolveStatusInvalid; + return ErrorSemanticAnalyzeFail; } } - return ErrorNone; } diff --git a/test/stage1/behavior/struct.zig b/test/stage1/behavior/struct.zig index 0befe4f620d8ddab4dfef9e09780d01e0e7c4ff9..8a73615715769165d5d2cb5b99488204532a7130 100644 --- a/test/stage1/behavior/struct.zig +++ b/test/stage1/behavior/struct.zig @@ -632,3 +632,11 @@ test "for loop over pointers to struct, getting field from struct pointer" { }; S.doTheTest(); } + +test "zero-bit field in packed struct" { + const S = packed struct { + x: u10, + y: void, + }; + var x: S = undefined; +} -- 2.54.0 From 866c253e0ee9dd666ba715ebafecb889c8066367 Mon Sep 17 00:00:00 2001 From: Timon Kruiper Date: Wed, 28 Aug 2019 23:12:42 +0200 Subject: [PATCH 45/80] Add compile error when shifting amount is not an int type --- src/ir.cpp | 9 ++++++++- test/compile_errors.zig | 20 ++++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/src/ir.cpp b/src/ir.cpp index 03e084e5ce9330f910abe66e82d852408c5edcc1..7504ed3b44ac83460b4213bc38d2ac7f833af6f4 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -13734,7 +13734,7 @@ static IrInstruction *ir_analyze_bit_shift(IrAnalyze *ira, IrInstructionBinOp *b return ira->codegen->invalid_instruction; if (op1->value.type->id != ZigTypeIdInt && op1->value.type->id != ZigTypeIdComptimeInt) { - ir_add_error(ira, &bin_op_instruction->base, + ir_add_error(ira, bin_op_instruction->op1, buf_sprintf("bit shifting operation expected integer type, found '%s'", buf_ptr(&op1->value.type->name))); return ira->codegen->invalid_instruction; @@ -13744,6 +13744,13 @@ static IrInstruction *ir_analyze_bit_shift(IrAnalyze *ira, IrInstructionBinOp *b if (type_is_invalid(op2->value.type)) return ira->codegen->invalid_instruction; + if (op2->value.type->id != ZigTypeIdInt && op2->value.type->id != ZigTypeIdComptimeInt) { + ir_add_error(ira, bin_op_instruction->op2, + buf_sprintf("shift amount has to be an integer type, but found '%s'", + buf_ptr(&op2->value.type->name))); + return ira->codegen->invalid_instruction; + } + IrInstruction *casted_op2; IrBinOp op_id = bin_op_instruction->op_id; if (op1->value.type->id == ZigTypeIdComptimeInt) { diff --git a/test/compile_errors.zig b/test/compile_errors.zig index 38fca5754de03cff1d9455ca822108944f5a070e..3534ed224789a1d3bbbebdcbdb2785a89f1dc6dc 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -70,6 +70,26 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { "tmp.zig:6:37: error: expected type '*i32', found 'bool'", ); + cases.add( + "shift amount has to be an integer type", + \\export fn entry() void { + \\ const x = 1 << &u8(10); + \\} + , + "tmp.zig:2:23: error: shift amount has to be an integer type, but found '*u8'", + "tmp.zig:2:17: note: referenced here", + ); + + cases.add( + "bit shifting only works on integer types", + \\export fn entry() void { + \\ const x = &u8(1) << 10; + \\} + , + "tmp.zig:2:18: error: bit shifting operation expected integer type, found '*u8'", + "tmp.zig:2:22: note: referenced here", + ); + cases.add( "struct depends on itself via optional field", \\const LhsExpr = struct { -- 2.54.0 From 8f0df86937e140c11a1efc9f94c8ac0bd1b02e2c Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 5 Sep 2019 14:15:39 -0400 Subject: [PATCH 46/80] I'm pretty sure `sp` is the stack pointer on all ARM --- src/target.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/target.cpp b/src/target.cpp index 8d73af6a0178befed90618776e9d77c20007b44f..b87ecbe256b1e455b9b035fedbe3d412744f1133 100644 --- a/src/target.cpp +++ b/src/target.cpp @@ -1393,16 +1393,17 @@ const char *arch_stack_pointer_register_name(ZigLLVM_ArchType arch) { return "esp"; case ZigLLVM_x86_64: return "rsp"; + case ZigLLVM_arm: + case ZigLLVM_armeb: + case ZigLLVM_thumb: + case ZigLLVM_thumbeb: case ZigLLVM_aarch64: + case ZigLLVM_aarch64_be: return "sp"; - case ZigLLVM_arm: - case ZigLLVM_thumb: - case ZigLLVM_aarch64_be: case ZigLLVM_amdgcn: case ZigLLVM_amdil: case ZigLLVM_amdil64: - case ZigLLVM_armeb: case ZigLLVM_arc: case ZigLLVM_avr: case ZigLLVM_bpfeb: @@ -1436,7 +1437,6 @@ const char *arch_stack_pointer_register_name(ZigLLVM_ArchType arch) { case ZigLLVM_systemz: case ZigLLVM_tce: case ZigLLVM_tcele: - case ZigLLVM_thumbeb: case ZigLLVM_wasm32: case ZigLLVM_wasm64: case ZigLLVM_xcore: -- 2.54.0 From 2045b4d93240cd95eee7143f2cfc360eb63c5802 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 5 Sep 2019 14:50:27 -0400 Subject: [PATCH 47/80] prefer result type casting to peer type resolution See #2749 --- src/all_types.hpp | 4 ++ src/ir.cpp | 77 ++++++++++++++++++++++++++------- test/stage1/behavior/if.zig | 12 +++++ test/stage1/behavior/struct.zig | 18 ++++++++ 4 files changed, 96 insertions(+), 15 deletions(-) diff --git a/src/all_types.hpp b/src/all_types.hpp index f1ecfe2be7c77bf99d9821f95ba2ace0aca29271..bc6ab4e8245fc5a24010d00d5b24b222b1b97c85 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -47,6 +47,7 @@ struct ResultLoc; struct ResultLocPeer; struct ResultLocPeerParent; struct ResultLocBitCast; +struct ResultLocReturn; enum PtrLen { PtrLenUnknown, @@ -3584,6 +3585,7 @@ struct IrInstructionAddImplicitReturnType { IrInstruction base; IrInstruction *value; + ResultLocReturn *result_loc_ret; }; // For float ops which take a single argument @@ -3810,6 +3812,8 @@ struct ResultLocVar { struct ResultLocReturn { ResultLoc base; + + bool implicit_return_type_done; }; struct IrSuspendPosition { diff --git a/src/ir.cpp b/src/ir.cpp index 7504ed3b44ac83460b4213bc38d2ac7f833af6f4..eb65c1469ee0ac6e5f2e8954f1ee6fddb5afb816 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -197,6 +197,7 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source static IrInstruction *ir_gen_union_init_expr(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *union_type, IrInstruction *field_name, AstNode *expr_node, LVal lval, ResultLoc *parent_result_loc); +static void ir_reset_result(ResultLoc *result_loc); static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *const_val) { assert(get_src_ptr_type(const_val->type) != nullptr); @@ -3085,10 +3086,11 @@ static IrInstruction *ir_build_save_err_ret_addr(IrBuilder *irb, Scope *scope, A } static IrInstruction *ir_build_add_implicit_return_type(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrInstruction *value) + IrInstruction *value, ResultLocReturn *result_loc_ret) { IrInstructionAddImplicitReturnType *instruction = ir_build_instruction(irb, scope, source_node); instruction->value = value; + instruction->result_loc_ret = result_loc_ret; ir_ref_instruction(value, irb->current_basic_block); @@ -3505,7 +3507,7 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node, return_value = ir_build_const_void(irb, scope, node); } - ir_mark_gen(ir_build_add_implicit_return_type(irb, scope, node, return_value)); + ir_mark_gen(ir_build_add_implicit_return_type(irb, scope, node, return_value, result_loc_ret)); size_t defer_counts[2]; ir_count_defers(irb, scope, outer_scope, defer_counts); @@ -3580,7 +3582,7 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node, ir_set_cursor_at_end_and_append_block(irb, return_block); IrInstruction *err_val_ptr = ir_build_unwrap_err_code(irb, scope, node, err_union_ptr); IrInstruction *err_val = ir_build_load_ptr(irb, scope, node, err_val_ptr); - ir_mark_gen(ir_build_add_implicit_return_type(irb, scope, node, err_val)); + ir_mark_gen(ir_build_add_implicit_return_type(irb, scope, node, err_val, nullptr)); IrInstructionSpillBegin *spill_begin = ir_build_spill_begin(irb, scope, node, err_val, SpillIdRetErrCode); ResultLocReturn *result_loc_ret = allocate(1); @@ -3690,6 +3692,7 @@ static ResultLocPeer *create_peer_result(ResultLocPeerParent *peer_parent) { result->base.id = ResultLocIdPeer; result->base.source_instruction = peer_parent->base.source_instruction; result->parent = peer_parent; + result->base.allow_write_through_const = peer_parent->parent->allow_write_through_const; return result; } @@ -3812,7 +3815,7 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode // no need for save_err_ret_addr because this cannot return error // only generate unconditional defers - ir_mark_gen(ir_build_add_implicit_return_type(irb, child_scope, block_node, result)); + ir_mark_gen(ir_build_add_implicit_return_type(irb, child_scope, block_node, result, nullptr)); ir_gen_defers_for_block(irb, child_scope, outer_block_scope, false); return ir_mark_gen(ir_build_return(irb, child_scope, result->source_node, result)); } @@ -8207,7 +8210,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec } if (!instr_is_unreachable(result)) { - ir_mark_gen(ir_build_add_implicit_return_type(irb, scope, result->source_node, result)); + ir_mark_gen(ir_build_add_implicit_return_type(irb, scope, result->source_node, result, nullptr)); // no need for save_err_ret_addr because this cannot return error ir_mark_gen(ir_build_return(irb, scope, result->source_node, result)); } @@ -12939,7 +12942,9 @@ static IrInstruction *ir_analyze_instruction_add_implicit_return_type(IrAnalyze if (type_is_invalid(value->value.type)) return ir_unreach_error(ira); - ira->src_implicit_return_type_list.append(value); + if (instruction->result_loc_ret == nullptr || !instruction->result_loc_ret->implicit_return_type_done) { + ira->src_implicit_return_type_list.append(value); + } return ir_const_void(ira, &instruction->base); } @@ -14976,6 +14981,24 @@ static void set_up_result_loc_for_inferred_comptime(IrInstruction *ptr) { ptr->value.data.x_ptr.data.ref.pointee = undef_child; } +static bool ir_result_has_type(ResultLoc *result_loc) { + switch (result_loc->id) { + case ResultLocIdInvalid: + case ResultLocIdPeerParent: + zig_unreachable(); + case ResultLocIdNone: + case ResultLocIdPeer: + return false; + case ResultLocIdReturn: + case ResultLocIdInstruction: + case ResultLocIdBitCast: + return true; + case ResultLocIdVar: + return reinterpret_cast(result_loc)->var->decl_node->data.variable_declaration.type != nullptr; + } + zig_unreachable(); +} + // when calling this function, at the callsite must check for result type noreturn and propagate it up static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspend_source_instr, ResultLoc *result_loc, ZigType *value_type, IrInstruction *value, bool force_runtime, bool non_null_comptime) @@ -15105,14 +15128,23 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe bool is_comptime; if (!ir_resolve_comptime(ira, peer_parent->is_comptime->child, &is_comptime)) return ira->codegen->invalid_instruction; - peer_parent->skipped = is_comptime; - if (peer_parent->skipped) { + if (is_comptime) { + peer_parent->skipped = true; if (non_null_comptime) { return ir_resolve_result(ira, suspend_source_instr, peer_parent->parent, value_type, value, force_runtime, non_null_comptime, true); } return nullptr; } + if (ir_result_has_type(peer_parent->parent)) { + if (peer_parent->parent->id == ResultLocIdReturn && value != nullptr) { + reinterpret_cast(peer_parent->parent)->implicit_return_type_done = true; + ira->src_implicit_return_type_list.append(value); + } + peer_parent->skipped = true; + return ir_resolve_result(ira, suspend_source_instr, peer_parent->parent, + value_type, value, force_runtime, true, true); + } if (peer_parent->resolved_type == nullptr) { if (peer_parent->end_bb->suspend_instruction_ref == nullptr) { @@ -15322,9 +15354,11 @@ static void ir_reset_result(ResultLoc *result_loc) { alloca_src->base.child = nullptr; break; } + case ResultLocIdReturn: + reinterpret_cast(result_loc)->implicit_return_type_done = false; + break; case ResultLocIdPeer: case ResultLocIdNone: - case ResultLocIdReturn: case ResultLocIdInstruction: case ResultLocIdBitCast: break; @@ -16880,10 +16914,21 @@ static IrInstruction *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPh return new_incoming_values.at(0); } - ZigType *resolved_type = ir_resolve_peer_types(ira, phi_instruction->base.source_node, nullptr, - new_incoming_values.items, new_incoming_values.length); - if (type_is_invalid(resolved_type)) - return ira->codegen->invalid_instruction; + ZigType *resolved_type; + if (peer_parent != nullptr && ir_result_has_type(peer_parent->parent)) { + if (peer_parent->parent->id == ResultLocIdReturn) { + resolved_type = ira->explicit_return_type; + } else { + ZigType *resolved_loc_ptr_type = peer_parent->parent->resolved_loc->value.type; + ir_assert(resolved_loc_ptr_type->id == ZigTypeIdPointer, &phi_instruction->base); + resolved_type = resolved_loc_ptr_type->data.pointer.child_type; + } + } else { + resolved_type = ir_resolve_peer_types(ira, phi_instruction->base.source_node, nullptr, + new_incoming_values.items, new_incoming_values.length); + if (type_is_invalid(resolved_type)) + return ira->codegen->invalid_instruction; + } switch (type_has_one_possible_value(ira->codegen, resolved_type)) { case OnePossibleValueInvalid: @@ -25055,7 +25100,7 @@ static IrInstruction *ir_analyze_instruction_end_expr(IrAnalyze *ira, IrInstruct if (result_loc->value.type->id == ZigTypeIdUnreachable) return result_loc; - if (!was_written) { + if (!was_written || instruction->result_loc->id == ResultLocIdPeer) { IrInstruction *store_ptr = ir_analyze_store_ptr(ira, &instruction->base, result_loc, value, instruction->result_loc->allow_write_through_const); if (type_is_invalid(store_ptr->value.type)) { @@ -25063,7 +25108,9 @@ static IrInstruction *ir_analyze_instruction_end_expr(IrAnalyze *ira, IrInstruct } } - if (result_loc->value.data.x_ptr.mut == ConstPtrMutInfer) { + if (result_loc->value.data.x_ptr.mut == ConstPtrMutInfer && + instruction->result_loc->id != ResultLocIdPeer) + { if (instr_is_comptime(value)) { result_loc->value.data.x_ptr.mut = ConstPtrMutComptimeConst; } else { diff --git a/test/stage1/behavior/if.zig b/test/stage1/behavior/if.zig index 70712ea85a6f843d3f034ce397daf860377e8ce2..d299817f465b35234fc23ac14045e9cfc7ffa0ea 100644 --- a/test/stage1/behavior/if.zig +++ b/test/stage1/behavior/if.zig @@ -74,3 +74,15 @@ test "const result loc, runtime if cond, else unreachable" { const x = if (t) Num.Two else unreachable; if (x != .Two) @compileError("bad"); } + +test "if prongs cast to expected type instead of peer type resolution" { + const S = struct { + fn doTheTest(f: bool) void { + var x: i32 = 0; + x = if (f) 1 else 2; + expect(x == 2); + } + }; + S.doTheTest(false); + comptime S.doTheTest(false); +} diff --git a/test/stage1/behavior/struct.zig b/test/stage1/behavior/struct.zig index 8a73615715769165d5d2cb5b99488204532a7130..13d2dcc733415a45d5eff7f9a43ea77c2f4702bd 100644 --- a/test/stage1/behavior/struct.zig +++ b/test/stage1/behavior/struct.zig @@ -640,3 +640,21 @@ test "zero-bit field in packed struct" { }; var x: S = undefined; } + +test "struct field init with catch" { + const S = struct { + fn doTheTest() void { + var x: anyerror!isize = 1; + var req = Foo{ + .field = x catch undefined, + }; + expect(req.field == 1); + } + + pub const Foo = extern struct { + field: isize, + }; + }; + S.doTheTest(); + comptime S.doTheTest(); +} -- 2.54.0 From b564e7ca59818e4904fc421fc8b1914cefd79538 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 5 Sep 2019 15:09:13 -0400 Subject: [PATCH 48/80] os: raise maximum file descriptor limit Do a binary search for the maximum RLIMIT_NOFILE. Patch lifted from node.js commit 6820054d2d42ff9274ea0755bea59cfc4f26f353 --- src/os.cpp | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/os.cpp b/src/os.cpp index 5fa70bd2603f11f1a57695d588a0703c101af98e..3a6ed2c286f43c7b5447ba406ec1419bca7207cd 100644 --- a/src/os.cpp +++ b/src/os.cpp @@ -45,6 +45,7 @@ typedef SSIZE_T ssize_t; #include #include #include +#include #include #include #include @@ -1374,6 +1375,29 @@ int os_init(void) { #elif defined(__MACH__) host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &macos_monotonic_clock); host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &macos_calendar_clock); +#endif +#if defined(ZIG_OS_POSIX) + // Raise the open file descriptor limit. + // Code lifted from node.js + struct rlimit lim; + if (getrlimit(RLIMIT_NOFILE, &lim) == 0 && lim.rlim_cur != lim.rlim_max) { + // Do a binary search for the limit. + rlim_t min = lim.rlim_cur; + rlim_t max = 1 << 20; + // But if there's a defined upper bound, don't search, just set it. + if (lim.rlim_max != RLIM_INFINITY) { + min = lim.rlim_max; + max = lim.rlim_max; + } + do { + lim.rlim_cur = min + (max - min) / 2; + if (setrlimit(RLIMIT_NOFILE, &lim)) { + max = lim.rlim_cur; + } else { + min = lim.rlim_cur; + } + } while (min + 1 < max); + } #endif return 0; } -- 2.54.0 From 4a5bc89862aca6f1870cbaa7d398ab2eed3022c3 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 5 Sep 2019 15:17:23 -0400 Subject: [PATCH 49/80] add -l as an alias for --library --- src/main.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index 6f1ccd418c36e9cc20bb1ca8b962d2c384c7c7f3..9e8f2b7d4f38ff1f108ffb855dc33e58ccb0e1e6 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -101,6 +101,7 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) { " --version-script [path] provide a version .map file\n" " --object [obj] add object file to build\n" " -L[dir] alias for --library-path\n" + " -l[lib] alias for --library\n" " -rdynamic add all symbols to the dynamic symbol table\n" " -rpath [path] add directory to the runtime library search path\n" " --subsystem [subsystem] (windows) /SUBSYSTEM: to the linker\n" @@ -688,6 +689,12 @@ int main(int argc, char **argv) { } else if (arg[1] == 'L' && arg[2] != 0) { // alias for --library-path lib_dirs.append(&arg[2]); + } else if (arg[1] == 'l' && arg[2] != 0) { + // alias for --library + const char *l = &arg[2]; + if (strcmp(l, "c") == 0) + have_libc = true; + link_libs.append(l); } else if (arg[1] == 'F' && arg[2] != 0) { framework_dirs.append(&arg[2]); } else if (strcmp(arg, "--pkg-begin") == 0) { @@ -778,7 +785,7 @@ int main(int argc, char **argv) { lib_dirs.append(argv[i]); } else if (strcmp(arg, "-F") == 0) { framework_dirs.append(argv[i]); - } else if (strcmp(arg, "--library") == 0) { + } else if (strcmp(arg, "--library") == 0 || strcmp(arg, "-l") == 0) { if (strcmp(argv[i], "c") == 0) have_libc = true; link_libs.append(argv[i]); -- 2.54.0 From ca70ca7e26aaae3425dad3a2b179f544bacf45e3 Mon Sep 17 00:00:00 2001 From: Timon Kruiper Date: Thu, 5 Sep 2019 18:43:54 +0200 Subject: [PATCH 50/80] Add compiler error when negating invalid type --- src/ir.cpp | 9 +++++++++ test/compile_errors.zig | 13 +++++++++++++ 2 files changed, 22 insertions(+) diff --git a/src/ir.cpp b/src/ir.cpp index eb65c1469ee0ac6e5f2e8954f1ee6fddb5afb816..2da8dea676ab42c06f3bcefa3152ed98602d9252 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -16565,6 +16565,15 @@ static IrInstruction *ir_analyze_negation(IrAnalyze *ira, IrInstructionUnOp *ins if (type_is_invalid(expr_type)) return ira->codegen->invalid_instruction; + if (!(expr_type->id == ZigTypeIdInt || expr_type->id == ZigTypeIdComptimeInt || + expr_type->id == ZigTypeIdFloat || expr_type->id == ZigTypeIdComptimeFloat || + expr_type->id == ZigTypeIdVector)) + { + ir_add_error(ira, &instruction->base, + buf_sprintf("negation of type '%s'", buf_ptr(&expr_type->name))); + return ira->codegen->invalid_instruction; + } + bool is_wrap_op = (instruction->op_id == IrUnOpNegationWrap); ZigType *scalar_type = (expr_type->id == ZigTypeIdVector) ? expr_type->data.vector.elem_type : expr_type; diff --git a/test/compile_errors.zig b/test/compile_errors.zig index 3534ed224789a1d3bbbebdcbdb2785a89f1dc6dc..d9ad5b7f82a10ff1917fa3d63ee16c0741ad77bc 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -2,6 +2,19 @@ const tests = @import("tests.zig"); const builtin = @import("builtin"); pub fn addCases(cases: *tests.CompileErrorContext) void { + cases.add( + "attempt to negate a non-integer, non-float or non-vector type", + \\fn foo() anyerror!u32 { + \\ return 1; + \\} + \\ + \\export fn entry() void { + \\ const x = -foo(); + \\} + , + "tmp.zig:6:15: error: negation of type 'anyerror!u32'", + ); + cases.add( "attempt to create 17 bit float type", \\const builtin = @import("builtin"); -- 2.54.0 From 0a3c6dbda92931eba055c2c6447b7a4412408f17 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 5 Sep 2019 21:55:07 -0400 Subject: [PATCH 51/80] implement `noasync` function calls See #3157 --- doc/docgen.zig | 3 +- src/all_types.hpp | 19 ++++++++--- src/analyze.cpp | 14 +++++--- src/ast_render.cpp | 17 +++++++--- src/codegen.cpp | 56 ++++++++++++++++++++++++++----- src/ir.cpp | 49 +++++++++++++++------------ src/ir_print.cpp | 26 +++++++++++--- src/parser.cpp | 28 +++++++++------- src/tokenizer.cpp | 6 ++-- src/tokenizer.hpp | 1 + src/translate_c.cpp | 2 +- std/zig/tokenizer.zig | 6 ++-- test/stage1/behavior/async_fn.zig | 16 +++++++++ 13 files changed, 175 insertions(+), 68 deletions(-) diff --git a/doc/docgen.zig b/doc/docgen.zig index 6ce5902dccd2ab36e968d2d87b673ed4a79a3274..0ef38dc773ff62f49ddb06f629617f3b66c65d40 100644 --- a/doc/docgen.zig +++ b/doc/docgen.zig @@ -786,9 +786,10 @@ fn tokenizeAndPrintRaw(docgen_tokenizer: *Tokenizer, out: var, source_token: Tok .Keyword_for, .Keyword_if, .Keyword_inline, - .Keyword_noinline, .Keyword_nakedcc, .Keyword_noalias, + .Keyword_noasync, + .Keyword_noinline, .Keyword_or, .Keyword_orelse, .Keyword_packed, diff --git a/src/all_types.hpp b/src/all_types.hpp index bc6ab4e8245fc5a24010d00d5b24b222b1b97c85..ef159986a17abcd058b0911204fa0af6245941bc 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -758,11 +758,17 @@ struct AstNodeUnwrapOptional { AstNode *expr; }; +enum CallModifier { + CallModifierNone, + CallModifierAsync, + CallModifierNoAsync, + CallModifierBuiltin, +}; + struct AstNodeFnCallExpr { AstNode *fn_ref_expr; ZigList params; - bool is_builtin; - bool is_async; + CallModifier modifier; bool seen; // used by @compileLog }; @@ -2730,8 +2736,10 @@ struct IrInstructionCallSrc { ResultLoc *result_loc; IrInstruction *new_stack; + FnInline fn_inline; - bool is_async; + CallModifier modifier; + bool is_async_call_builtin; bool is_comptime; }; @@ -2745,10 +2753,11 @@ struct IrInstructionCallGen { IrInstruction **args; IrInstruction *result_loc; IrInstruction *frame_result_loc; - IrInstruction *new_stack; + FnInline fn_inline; - bool is_async; + CallModifier modifier; + bool is_async_call_builtin; }; diff --git a/src/analyze.cpp b/src/analyze.cpp index 386ee4ec46c81b7850051b322092546fed82654e..fa93a9764cb5fee67d2d3974775e08d0edde4b79 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -4214,7 +4214,7 @@ void add_async_error_notes(CodeGen *g, ErrorMsg *msg, ZigFn *fn) { add_error_note(g, msg, fn->inferred_async_node, buf_sprintf("await here is a suspend point")); } else if (fn->inferred_async_node->type == NodeTypeFnCallExpr && - fn->inferred_async_node->data.fn_call_expr.is_builtin) + fn->inferred_async_node->data.fn_call_expr.modifier == CallModifierBuiltin) { add_error_note(g, msg, fn->inferred_async_node, buf_sprintf("@frame() causes function to be async")); @@ -4228,8 +4228,10 @@ void add_async_error_notes(CodeGen *g, ErrorMsg *msg, ZigFn *fn) { // ErrorIsAsync - yes async // ErrorSemanticAnalyzeFail - compile error emitted result is invalid static Error analyze_callee_async(CodeGen *g, ZigFn *fn, ZigFn *callee, AstNode *call_node, - bool must_not_be_async) + bool must_not_be_async, CallModifier modifier) { + if (modifier == CallModifierNoAsync) + return ErrorNone; if (callee->type_entry->data.fn.fn_type_id.cc != CallingConventionUnspecified) return ErrorNone; if (callee->anal_state == FnAnalStateReady) { @@ -4312,7 +4314,9 @@ static void analyze_fn_async(CodeGen *g, ZigFn *fn, bool resolve_frame) { // TODO function pointer call here, could be anything continue; } - switch (analyze_callee_async(g, fn, call->fn_entry, call->base.source_node, must_not_be_async)) { + switch (analyze_callee_async(g, fn, call->fn_entry, call->base.source_node, must_not_be_async, + call->modifier)) + { case ErrorSemanticAnalyzeFail: fn->anal_state = FnAnalStateInvalid; return; @@ -4329,7 +4333,9 @@ static void analyze_fn_async(CodeGen *g, ZigFn *fn, bool resolve_frame) { } for (size_t i = 0; i < fn->await_list.length; i += 1) { IrInstructionAwaitGen *await = fn->await_list.at(i); - switch (analyze_callee_async(g, fn, await->target_fn, await->base.source_node, must_not_be_async)) { + switch (analyze_callee_async(g, fn, await->target_fn, await->base.source_node, must_not_be_async, + CallModifierNone)) + { case ErrorSemanticAnalyzeFail: fn->anal_state = FnAnalStateInvalid; return; diff --git a/src/ast_render.cpp b/src/ast_render.cpp index fedd46a48bf789d04f93f878db16882e9edc446a..537a74d7b1f86ce29be669c89fcfdfea5dad5cc2 100644 --- a/src/ast_render.cpp +++ b/src/ast_render.cpp @@ -698,11 +698,18 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { } case NodeTypeFnCallExpr: { - if (node->data.fn_call_expr.is_builtin) { - fprintf(ar->f, "@"); - } - if (node->data.fn_call_expr.is_async) { - fprintf(ar->f, "async "); + switch (node->data.fn_call_expr.modifier) { + case CallModifierNone: + break; + case CallModifierBuiltin: + fprintf(ar->f, "@"); + break; + case CallModifierAsync: + fprintf(ar->f, "async "); + break; + case CallModifierNoAsync: + fprintf(ar->f, "noasync "); + break; } AstNode *fn_ref_node = node->data.fn_call_expr.fn_ref_expr; bool grouped = (fn_ref_node->type != NodeTypePrefixOpExpr && fn_ref_node->type != NodeTypePointerType); diff --git a/src/codegen.cpp b/src/codegen.cpp index 9c8ccd7040e75c60dcabc6ce445252d1a1541cb5..03c253ad48b3c7833fff6da6b9b9b5e928af589d 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -186,6 +186,9 @@ static void generate_error_name_table(CodeGen *g); static bool value_is_all_undef(CodeGen *g, ConstExprValue *const_val); static void gen_undef_init(CodeGen *g, uint32_t ptr_align_bytes, ZigType *value_type, LLVMValueRef ptr); static LLVMValueRef build_alloca(CodeGen *g, ZigType *type_entry, const char *name, uint32_t alignment); +static LLVMValueRef gen_await_early_return(CodeGen *g, IrInstruction *source_instr, + LLVMValueRef target_frame_ptr, ZigType *result_type, ZigType *ptr_result_type, + LLVMValueRef result_loc, bool non_async); static void addLLVMAttr(LLVMValueRef val, LLVMAttributeIndex attr_index, const char *attr_name) { unsigned kind_id = LLVMGetEnumAttributeKindForName(attr_name, strlen(attr_name)); @@ -3842,7 +3845,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr LLVMValueRef ret_ptr; if (callee_is_async) { if (instruction->new_stack == nullptr) { - if (instruction->is_async) { + if (instruction->modifier == CallModifierAsync) { frame_result_loc = result_loc; } else { frame_result_loc = ir_llvm_value(g, instruction->frame_result_loc); @@ -3883,7 +3886,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr } } } - if (instruction->is_async) { + if (instruction->modifier == CallModifierAsync) { if (instruction->new_stack == nullptr) { awaiter_init_val = zero; @@ -3908,9 +3911,15 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr // even if prefix_arg_err_ret_stack is true, let the async function do its own // initialization. } else { - // async function called as a normal function - - awaiter_init_val = LLVMBuildPtrToInt(g->builder, g->cur_frame_ptr, usize_type_ref, ""); // caller's own frame pointer + if (instruction->modifier == CallModifierNoAsync && !fn_is_async(g->cur_fn)) { + // Async function called as a normal function, and calling function is not async. + // This is allowed because it was called with `noasync` which asserts that it will + // never suspend. + awaiter_init_val = zero; + } else { + // async function called as a normal function + awaiter_init_val = LLVMBuildPtrToInt(g->builder, g->cur_frame_ptr, usize_type_ref, ""); // caller's own frame pointer + } if (ret_has_bits) { if (result_loc == nullptr) { // return type is a scalar, but we still need a pointer to it. Use the async fn frame. @@ -3951,7 +3960,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr LLVMValueRef ret_ptr_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, frame_ret_start, ""); LLVMBuildStore(g->builder, ret_ptr, ret_ptr_ptr); } - } else if (instruction->is_async) { + } else if (instruction->modifier == CallModifierAsync) { // Async call of blocking function if (instruction->new_stack != nullptr) { zig_panic("TODO @asyncCall of non-async function"); @@ -4048,13 +4057,20 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr gen_param_values.at(arg_i)); } - if (instruction->is_async) { + if (instruction->modifier == CallModifierAsync) { gen_resume(g, fn_val, frame_result_loc, ResumeIdCall); if (instruction->new_stack != nullptr) { return LLVMBuildBitCast(g->builder, frame_result_loc, get_llvm_type(g, instruction->base.value.type), ""); } return nullptr; + } else if (instruction->modifier == CallModifierNoAsync && !fn_is_async(g->cur_fn)) { + gen_resume(g, fn_val, frame_result_loc, ResumeIdCall); + + ZigType *result_type = instruction->base.value.type; + ZigType *ptr_result_type = get_pointer_to_type(g, result_type, true); + return gen_await_early_return(g, &instruction->base, frame_result_loc, + result_type, ptr_result_type, result_loc, true); } else { ZigType *ptr_result_type = get_pointer_to_type(g, src_return_type, true); @@ -4082,7 +4098,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr if (instruction->new_stack == nullptr || instruction->is_async_call_builtin) { result = ZigLLVMBuildCall(g->builder, fn_val, gen_param_values.items, (unsigned)gen_param_values.length, llvm_cc, fn_inline, ""); - } else if (instruction->is_async) { + } else if (instruction->modifier == CallModifierAsync) { zig_panic("TODO @asyncCall of non-async function"); } else { LLVMValueRef stacksave_fn_val = get_stacksave_fn_val(g); @@ -4107,7 +4123,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr LLVMValueRef store_instr = LLVMBuildStore(g->builder, result, result_loc); LLVMSetAlignment(store_instr, get_ptr_align(g, instruction->result_loc->value.type)); return result_loc; - } else if (!callee_is_async && instruction->is_async) { + } else if (!callee_is_async && instruction->modifier == CallModifierAsync) { LLVMBuildStore(g->builder, result, ret_ptr); return result_loc; } else { @@ -7104,6 +7120,28 @@ static void do_code_gen(CodeGen *g) { } if (!is_async) { + // allocate async frames for noasync calls & awaits to async functions + for (size_t i = 0; i < fn_table_entry->call_list.length; i += 1) { + IrInstructionCallGen *call = fn_table_entry->call_list.at(i); + if (call->fn_entry == nullptr) + continue; + if (!fn_is_async(call->fn_entry)) + continue; + if (call->modifier != CallModifierNoAsync) + continue; + if (call->frame_result_loc != nullptr) + continue; + ZigType *callee_frame_type = get_fn_frame_type(g, call->fn_entry); + IrInstructionAllocaGen *alloca_gen = allocate(1); + alloca_gen->base.id = IrInstructionIdAllocaGen; + alloca_gen->base.source_node = call->base.source_node; + alloca_gen->base.scope = call->base.scope; + alloca_gen->base.value.type = get_pointer_to_type(g, callee_frame_type, false); + alloca_gen->base.ref_count = 1; + alloca_gen->name_hint = ""; + fn_table_entry->alloca_gen_list.append(alloca_gen); + call->frame_result_loc = &alloca_gen->base; + } // allocate temporary stack data for (size_t alloca_i = 0; alloca_i < fn_table_entry->alloca_gen_list.length; alloca_i += 1) { IrInstructionAllocaGen *instruction = fn_table_entry->alloca_gen_list.at(alloca_i); diff --git a/src/ir.cpp b/src/ir.cpp index 2da8dea676ab42c06f3bcefa3152ed98602d9252..53ce2d89e18a57b3b0c3232f01541971bef90819 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -1389,7 +1389,7 @@ static IrInstruction *ir_build_union_field_ptr(IrBuilder *irb, Scope *scope, Ast static IrInstruction *ir_build_call_src(IrBuilder *irb, Scope *scope, AstNode *source_node, ZigFn *fn_entry, IrInstruction *fn_ref, size_t arg_count, IrInstruction **args, - bool is_comptime, FnInline fn_inline, bool is_async, bool is_async_call_builtin, + bool is_comptime, FnInline fn_inline, CallModifier modifier, bool is_async_call_builtin, IrInstruction *new_stack, ResultLoc *result_loc) { IrInstructionCallSrc *call_instruction = ir_build_instruction(irb, scope, source_node); @@ -1399,7 +1399,7 @@ static IrInstruction *ir_build_call_src(IrBuilder *irb, Scope *scope, AstNode *s call_instruction->fn_inline = fn_inline; call_instruction->args = args; call_instruction->arg_count = arg_count; - call_instruction->is_async = is_async; + call_instruction->modifier = modifier; call_instruction->is_async_call_builtin = is_async_call_builtin; call_instruction->new_stack = new_stack; call_instruction->result_loc = result_loc; @@ -1407,7 +1407,7 @@ static IrInstruction *ir_build_call_src(IrBuilder *irb, Scope *scope, AstNode *s if (fn_ref != nullptr) ir_ref_instruction(fn_ref, irb->current_basic_block); for (size_t i = 0; i < arg_count; i += 1) ir_ref_instruction(args[i], irb->current_basic_block); - if (is_async && new_stack != nullptr) { + if (modifier == CallModifierAsync && new_stack != nullptr) { // in this case the arg at the end is the return pointer ir_ref_instruction(args[arg_count], irb->current_basic_block); } @@ -1418,7 +1418,7 @@ static IrInstruction *ir_build_call_src(IrBuilder *irb, Scope *scope, AstNode *s static IrInstructionCallGen *ir_build_call_gen(IrAnalyze *ira, IrInstruction *source_instruction, ZigFn *fn_entry, IrInstruction *fn_ref, size_t arg_count, IrInstruction **args, - FnInline fn_inline, bool is_async, IrInstruction *new_stack, bool is_async_call_builtin, + FnInline fn_inline, CallModifier modifier, IrInstruction *new_stack, bool is_async_call_builtin, IrInstruction *result_loc, ZigType *return_type) { IrInstructionCallGen *call_instruction = ir_build_instruction(&ira->new_irb, @@ -1429,7 +1429,7 @@ static IrInstructionCallGen *ir_build_call_gen(IrAnalyze *ira, IrInstruction *so call_instruction->fn_inline = fn_inline; call_instruction->args = args; call_instruction->arg_count = arg_count; - call_instruction->is_async = is_async; + call_instruction->modifier = modifier; call_instruction->is_async_call_builtin = is_async_call_builtin; call_instruction->new_stack = new_stack; call_instruction->result_loc = result_loc; @@ -4412,10 +4412,10 @@ static IrInstruction *ir_gen_async_call(IrBuilder *irb, Scope *scope, AstNode *a args[arg_count] = ret_ptr; - bool is_async = await_node == nullptr; + CallModifier modifier = (await_node == nullptr) ? CallModifierAsync : CallModifierNone; bool is_async_call_builtin = true; IrInstruction *call = ir_build_call_src(irb, scope, call_node, nullptr, fn_ref, arg_count, args, false, - FnInlineAuto, is_async, is_async_call_builtin, bytes, result_loc); + FnInlineAuto, modifier, is_async_call_builtin, bytes, result_loc); return ir_lval_wrap(irb, scope, call, lval, result_loc); } @@ -5302,7 +5302,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo FnInline fn_inline = (builtin_fn->id == BuiltinFnIdInlineCall) ? FnInlineAlways : FnInlineNever; IrInstruction *call = ir_build_call_src(irb, scope, node, nullptr, fn_ref, arg_count, args, false, - fn_inline, false, false, nullptr, result_loc); + fn_inline, CallModifierNone, false, nullptr, result_loc); return ir_lval_wrap(irb, scope, call, lval, result_loc); } case BuiltinFnIdNewStackCall: @@ -5335,7 +5335,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo } IrInstruction *call = ir_build_call_src(irb, scope, node, nullptr, fn_ref, arg_count, args, false, - FnInlineAuto, false, false, new_stack, result_loc); + FnInlineAuto, CallModifierNone, false, new_stack, result_loc); return ir_lval_wrap(irb, scope, call, lval, result_loc); } case BuiltinFnIdAsyncCall: @@ -5624,7 +5624,7 @@ static IrInstruction *ir_gen_fn_call(IrBuilder *irb, Scope *scope, AstNode *node { assert(node->type == NodeTypeFnCallExpr); - if (node->data.fn_call_expr.is_builtin) + if (node->data.fn_call_expr.modifier == CallModifierBuiltin) return ir_gen_builtin_fn_call(irb, scope, node, lval, result_loc); AstNode *fn_ref_node = node->data.fn_call_expr.fn_ref_expr; @@ -5641,9 +5641,8 @@ static IrInstruction *ir_gen_fn_call(IrBuilder *irb, Scope *scope, AstNode *node return args[i]; } - bool is_async = node->data.fn_call_expr.is_async; IrInstruction *fn_call = ir_build_call_src(irb, scope, node, nullptr, fn_ref, arg_count, args, false, - FnInlineAuto, is_async, false, nullptr, result_loc); + FnInlineAuto, node->data.fn_call_expr.modifier, false, nullptr, result_loc); return ir_lval_wrap(irb, scope, fn_call, lval, result_loc); } @@ -7937,7 +7936,7 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *n assert(node->type == NodeTypeAwaitExpr); AstNode *expr_node = node->data.await_expr.expr; - if (expr_node->type == NodeTypeFnCallExpr && expr_node->data.fn_call_expr.is_builtin) { + if (expr_node->type == NodeTypeFnCallExpr && expr_node->data.fn_call_expr.modifier == CallModifierBuiltin) { AstNode *fn_ref_expr = expr_node->data.fn_call_expr.fn_ref_expr; Buf *name = fn_ref_expr->data.symbol_expr.symbol; auto entry = irb->codegen->builtin_fn_table.maybe_get(name); @@ -15408,7 +15407,7 @@ static IrInstruction *ir_analyze_async_call(IrAnalyze *ira, IrInstructionCallSrc ZigType *anyframe_type = get_any_frame_type(ira->codegen, fn_ret_type); IrInstructionCallGen *call_gen = ir_build_call_gen(ira, &call_instruction->base, fn_entry, fn_ref, - arg_count, casted_args, FnInlineAuto, true, casted_new_stack, + arg_count, casted_args, FnInlineAuto, CallModifierAsync, casted_new_stack, call_instruction->is_async_call_builtin, ret_ptr, anyframe_type); return &call_gen->base; } else { @@ -15422,8 +15421,8 @@ static IrInstruction *ir_analyze_async_call(IrAnalyze *ira, IrInstructionCallSrc if (type_is_invalid(result_loc->value.type)) return ira->codegen->invalid_instruction; return &ir_build_call_gen(ira, &call_instruction->base, fn_entry, fn_ref, arg_count, - casted_args, FnInlineAuto, true, casted_new_stack, call_instruction->is_async_call_builtin, - result_loc, frame_type)->base; + casted_args, FnInlineAuto, CallModifierAsync, casted_new_stack, + call_instruction->is_async_call_builtin, result_loc, frame_type)->base; } } static bool ir_analyze_fn_call_inline_arg(IrAnalyze *ira, AstNode *fn_proto_node, @@ -16174,7 +16173,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c return ira->codegen->invalid_instruction; size_t impl_param_count = impl_fn_type_id->param_count; - if (call_instruction->is_async) { + if (call_instruction->modifier == CallModifierAsync) { IrInstruction *result = ir_analyze_async_call(ira, call_instruction, impl_fn, impl_fn->type_entry, nullptr, casted_args, impl_param_count, casted_new_stack); return ir_finish_anal(ira, result); @@ -16201,14 +16200,17 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c result_loc = nullptr; } - if (impl_fn_type_id->cc == CallingConventionAsync && parent_fn_entry->inferred_async_node == nullptr) { + if (impl_fn_type_id->cc == CallingConventionAsync && + parent_fn_entry->inferred_async_node == nullptr && + call_instruction->modifier != CallModifierNoAsync) + { parent_fn_entry->inferred_async_node = fn_ref->source_node; parent_fn_entry->inferred_async_fn = impl_fn; } IrInstructionCallGen *new_call_instruction = ir_build_call_gen(ira, &call_instruction->base, impl_fn, nullptr, impl_param_count, casted_args, fn_inline, - false, casted_new_stack, call_instruction->is_async_call_builtin, result_loc, + call_instruction->modifier, casted_new_stack, call_instruction->is_async_call_builtin, result_loc, impl_fn_type_id->return_type); if (get_scope_typeof(call_instruction->base.scope) == nullptr) { @@ -16325,13 +16327,16 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c if (casted_new_stack != nullptr && type_is_invalid(casted_new_stack->value.type)) return ira->codegen->invalid_instruction; - if (call_instruction->is_async) { + if (call_instruction->modifier == CallModifierAsync) { IrInstruction *result = ir_analyze_async_call(ira, call_instruction, fn_entry, fn_type, fn_ref, casted_args, call_param_count, casted_new_stack); return ir_finish_anal(ira, result); } - if (fn_type_id->cc == CallingConventionAsync && parent_fn_entry->inferred_async_node == nullptr) { + if (fn_type_id->cc == CallingConventionAsync && + parent_fn_entry->inferred_async_node == nullptr && + call_instruction->modifier != CallModifierNoAsync) + { parent_fn_entry->inferred_async_node = fn_ref->source_node; parent_fn_entry->inferred_async_fn = fn_entry; } @@ -16358,7 +16363,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c } IrInstructionCallGen *new_call_instruction = ir_build_call_gen(ira, &call_instruction->base, fn_entry, fn_ref, - call_param_count, casted_args, fn_inline, false, casted_new_stack, + call_param_count, casted_args, fn_inline, call_instruction->modifier, casted_new_stack, call_instruction->is_async_call_builtin, result_loc, return_type); if (get_scope_typeof(call_instruction->base.scope) == nullptr) { parent_fn_entry->call_list.append(new_call_instruction); diff --git a/src/ir_print.cpp b/src/ir_print.cpp index 85d89cdb88122b991a5aa573cb5b0b951948867c..30b87352444ef394a35ea211d16cad9984c25aab 100644 --- a/src/ir_print.cpp +++ b/src/ir_print.cpp @@ -608,8 +608,17 @@ static void ir_print_result_loc(IrPrint *irp, ResultLoc *result_loc) { } static void ir_print_call_src(IrPrint *irp, IrInstructionCallSrc *call_instruction) { - if (call_instruction->is_async) { - fprintf(irp->f, "async "); + switch (call_instruction->modifier) { + case CallModifierNone: + break; + case CallModifierAsync: + fprintf(irp->f, "async "); + break; + case CallModifierNoAsync: + fprintf(irp->f, "noasync "); + break; + case CallModifierBuiltin: + zig_unreachable(); } if (call_instruction->fn_entry) { fprintf(irp->f, "%s", buf_ptr(&call_instruction->fn_entry->symbol_name)); @@ -629,8 +638,17 @@ static void ir_print_call_src(IrPrint *irp, IrInstructionCallSrc *call_instructi } static void ir_print_call_gen(IrPrint *irp, IrInstructionCallGen *call_instruction) { - if (call_instruction->is_async) { - fprintf(irp->f, "async "); + switch (call_instruction->modifier) { + case CallModifierNone: + break; + case CallModifierAsync: + fprintf(irp->f, "async "); + break; + case CallModifierNoAsync: + fprintf(irp->f, "noasync "); + break; + case CallModifierBuiltin: + zig_unreachable(); } if (call_instruction->fn_entry) { fprintf(irp->f, "%s", buf_ptr(&call_instruction->fn_entry->symbol_name)); diff --git a/src/parser.cpp b/src/parser.cpp index ba8757e4aeca2ff076f637bfef3bd8592f33607d..96071daa0739cc1ef46ffb3663ef78d735f27589 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -113,7 +113,7 @@ static AstNode *ast_parse_multiply_op(ParseContext *pc); static AstNode *ast_parse_prefix_op(ParseContext *pc); static AstNode *ast_parse_prefix_type_op(ParseContext *pc); static AstNode *ast_parse_suffix_op(ParseContext *pc); -static AstNode *ast_parse_fn_call_argumnets(ParseContext *pc); +static AstNode *ast_parse_fn_call_arguments(ParseContext *pc); static AstNode *ast_parse_array_type_start(ParseContext *pc); static AstNode *ast_parse_ptr_type_start(ParseContext *pc); static AstNode *ast_parse_container_decl_auto(ParseContext *pc); @@ -1403,12 +1403,14 @@ static AstNode *ast_parse_error_union_expr(ParseContext *pc) { } // SuffixExpr -// <- KEYWORD_async PrimaryTypeExpr SuffixOp* FnCallArguments +// <- KEYWORD_async PrimaryTypeExpr SuffixOp* FnCallArguments +// / KEYWORD_noasync PrimaryTypeExpr SuffixOp* FnCallArguments // / PrimaryTypeExpr (SuffixOp / FnCallArguments)* static AstNode *ast_parse_suffix_expr(ParseContext *pc) { - Token *async_token = eat_token_if(pc, TokenIdKeywordAsync); - if (async_token != nullptr) { - if (eat_token_if(pc, TokenIdKeywordFn) != nullptr) { + Token *async_token = eat_token(pc); + bool is_async = async_token->id == TokenIdKeywordAsync; + if (is_async || async_token->id == TokenIdKeywordNoAsync) { + if (is_async && eat_token_if(pc, TokenIdKeywordFn) != nullptr) { // HACK: If we see the keyword `fn`, then we assume that // we are parsing an async fn proto, and not a call. // We therefore put back all tokens consumed by the async @@ -1447,24 +1449,24 @@ static AstNode *ast_parse_suffix_expr(ParseContext *pc) { child = suffix; } - // TODO: Both *_async_prefix and *_fn_call_argumnets returns an + // TODO: Both *_async_prefix and *_fn_call_arguments returns an // AstNode *. All we really want here is the arguments of // the call we parse. We therefor "leak" the node for now. // Wait till we get async rework to fix this. - AstNode *args = ast_parse_fn_call_argumnets(pc); + AstNode *args = ast_parse_fn_call_arguments(pc); if (args == nullptr) ast_invalid_token_error(pc, peek_token(pc)); assert(args->type == NodeTypeFnCallExpr); AstNode *res = ast_create_node(pc, NodeTypeFnCallExpr, async_token); - res->data.fn_call_expr.is_async = true; + res->data.fn_call_expr.modifier = is_async ? CallModifierAsync : CallModifierNoAsync; res->data.fn_call_expr.seen = false; res->data.fn_call_expr.fn_ref_expr = child; res->data.fn_call_expr.params = args->data.fn_call_expr.params; - res->data.fn_call_expr.is_builtin = false; return res; } + put_back_token(pc); AstNode *res = ast_parse_primary_type_expr(pc); if (res == nullptr) @@ -1496,7 +1498,7 @@ static AstNode *ast_parse_suffix_expr(ParseContext *pc) { continue; } - AstNode * call = ast_parse_fn_call_argumnets(pc); + AstNode * call = ast_parse_fn_call_arguments(pc); if (call != nullptr) { assert(call->type == NodeTypeFnCallExpr); call->data.fn_call_expr.fn_ref_expr = res; @@ -1552,7 +1554,7 @@ static AstNode *ast_parse_primary_type_expr(ParseContext *pc) { name = buf_create_from_str("export"); } - AstNode *res = ast_expect(pc, ast_parse_fn_call_argumnets); + AstNode *res = ast_expect(pc, ast_parse_fn_call_arguments); AstNode *name_sym = ast_create_node(pc, NodeTypeSymbol, token); name_sym->data.symbol_expr.symbol = name; @@ -1560,7 +1562,7 @@ static AstNode *ast_parse_primary_type_expr(ParseContext *pc) { res->line = at_sign->start_line; res->column = at_sign->start_column; res->data.fn_call_expr.fn_ref_expr = name_sym; - res->data.fn_call_expr.is_builtin = true; + res->data.fn_call_expr.modifier = CallModifierBuiltin; return res; } @@ -2672,7 +2674,7 @@ static AstNode *ast_parse_suffix_op(ParseContext *pc) { } // FnCallArguments <- LPAREN ExprList RPAREN -static AstNode *ast_parse_fn_call_argumnets(ParseContext *pc) { +static AstNode *ast_parse_fn_call_arguments(ParseContext *pc) { Token *paren = eat_token_if(pc, TokenIdLParen); if (paren == nullptr) return nullptr; diff --git a/src/tokenizer.cpp b/src/tokenizer.cpp index 8ef320331ae324e3613dafa2f4e6aa79ae915d0f..465f652288fb30b37a5cc48cf43284dd36a6431f 100644 --- a/src/tokenizer.cpp +++ b/src/tokenizer.cpp @@ -130,9 +130,10 @@ static const struct ZigKeyword zig_keywords[] = { {"for", TokenIdKeywordFor}, {"if", TokenIdKeywordIf}, {"inline", TokenIdKeywordInline}, - {"noinline", TokenIdKeywordNoInline}, {"nakedcc", TokenIdKeywordNakedCC}, {"noalias", TokenIdKeywordNoAlias}, + {"noasync", TokenIdKeywordNoAsync}, + {"noinline", TokenIdKeywordNoInline}, {"null", TokenIdKeywordNull}, {"or", TokenIdKeywordOr}, {"orelse", TokenIdKeywordOrElse}, @@ -1552,9 +1553,10 @@ const char * token_name(TokenId id) { case TokenIdKeywordFor: return "for"; case TokenIdKeywordIf: return "if"; case TokenIdKeywordInline: return "inline"; - case TokenIdKeywordNoInline: return "noinline"; case TokenIdKeywordNakedCC: return "nakedcc"; case TokenIdKeywordNoAlias: return "noalias"; + case TokenIdKeywordNoAsync: return "noasync"; + case TokenIdKeywordNoInline: return "noinline"; case TokenIdKeywordNull: return "null"; case TokenIdKeywordOr: return "or"; case TokenIdKeywordOrElse: return "orelse"; diff --git a/src/tokenizer.hpp b/src/tokenizer.hpp index 70d828b39d058a7733205b0ab9f0b9ecd76ae581..a3d1a600082f1b3a4b9758f8481957afaca2837a 100644 --- a/src/tokenizer.hpp +++ b/src/tokenizer.hpp @@ -78,6 +78,7 @@ enum TokenId { TokenIdKeywordLinkSection, TokenIdKeywordNakedCC, TokenIdKeywordNoAlias, + TokenIdKeywordNoAsync, TokenIdKeywordNull, TokenIdKeywordOr, TokenIdKeywordOrElse, diff --git a/src/translate_c.cpp b/src/translate_c.cpp index eb591107836340b1342a3a1202b8d3a266d99485..7a4ad3f57df929d5f607754415a94a5f439fde38 100644 --- a/src/translate_c.cpp +++ b/src/translate_c.cpp @@ -253,7 +253,7 @@ static AstNode *trans_create_node_symbol_str(Context *c, const char *name) { static AstNode *trans_create_node_builtin_fn_call(Context *c, Buf *name) { AstNode *node = trans_create_node(c, NodeTypeFnCallExpr); node->data.fn_call_expr.fn_ref_expr = trans_create_node_symbol(c, name); - node->data.fn_call_expr.is_builtin = true; + node->data.fn_call_expr.modifier = CallModifierBuiltin; return node; } diff --git a/std/zig/tokenizer.zig b/std/zig/tokenizer.zig index 204121f64c59dd82436aa491d979e3fe13ee20f3..19fb233567d4c99ef9f8595b12e9c0c75dd8c23a 100644 --- a/std/zig/tokenizer.zig +++ b/std/zig/tokenizer.zig @@ -36,9 +36,10 @@ pub const Token = struct { Keyword{ .bytes = "for", .id = Id.Keyword_for }, Keyword{ .bytes = "if", .id = Id.Keyword_if }, Keyword{ .bytes = "inline", .id = Id.Keyword_inline }, - Keyword{ .bytes = "noinline", .id = Id.Keyword_noinline }, Keyword{ .bytes = "nakedcc", .id = Id.Keyword_nakedcc }, Keyword{ .bytes = "noalias", .id = Id.Keyword_noalias }, + Keyword{ .bytes = "noasync", .id = Id.Keyword_noasync }, + Keyword{ .bytes = "noinline", .id = Id.Keyword_noinline }, Keyword{ .bytes = "null", .id = Id.Keyword_null }, Keyword{ .bytes = "or", .id = Id.Keyword_or }, Keyword{ .bytes = "orelse", .id = Id.Keyword_orelse }, @@ -167,9 +168,10 @@ pub const Token = struct { Keyword_for, Keyword_if, Keyword_inline, - Keyword_noinline, Keyword_nakedcc, Keyword_noalias, + Keyword_noasync, + Keyword_noinline, Keyword_null, Keyword_or, Keyword_orelse, diff --git a/test/stage1/behavior/async_fn.zig b/test/stage1/behavior/async_fn.zig index ad8e949f8b193dbc93659ae60c29f49c9d0b366a..a898889f5c9cfc1ff3840514f05ac463ba079711 100644 --- a/test/stage1/behavior/async_fn.zig +++ b/test/stage1/behavior/async_fn.zig @@ -1092,3 +1092,19 @@ test "recursive call of await @asyncCall with struct return type" { expect(res.y == 2); expect(res.z == 3); } + +test "noasync function call" { + const S = struct { + fn doTheTest() void { + const result = noasync add(50, 100); + expect(result == 150); + } + fn add(a: i32, b: i32) i32 { + if (a > 100) { + suspend; + } + return a + b; + } + }; + S.doTheTest(); +} -- 2.54.0 From 7d303ae861b807c84ca99078b63fe35a69f712d7 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Fri, 6 Sep 2019 12:50:51 -0400 Subject: [PATCH 52/80] runtime safety for noasync function calls See #3157 --- src/all_types.hpp | 1 + src/codegen.cpp | 21 +++++++++++++++++++++ test/runtime_safety.zig | 15 +++++++++++++++ 3 files changed, 37 insertions(+) diff --git a/src/all_types.hpp b/src/all_types.hpp index ef159986a17abcd058b0911204fa0af6245941bc..afe8bd0675bf5d0d58c749c3247223d6cde5d847 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -1680,6 +1680,7 @@ enum PanicMsgId { PanicMsgIdResumedAnAwaitingFn, PanicMsgIdFrameTooSmall, PanicMsgIdResumedFnPendingAwait, + PanicMsgIdBadNoAsyncCall, PanicMsgIdCount, }; diff --git a/src/codegen.cpp b/src/codegen.cpp index 03c253ad48b3c7833fff6da6b9b9b5e928af589d..6c03be32c3188e7c8169b22210bdf0c31ada3595 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -923,6 +923,8 @@ static Buf *panic_msg_buf(PanicMsgId msg_id) { return buf_create_from_str("frame too small"); case PanicMsgIdResumedFnPendingAwait: return buf_create_from_str("resumed an async function which can only be awaited"); + case PanicMsgIdBadNoAsyncCall: + return buf_create_from_str("async function called with noasync suspended"); } zig_unreachable(); } @@ -4067,6 +4069,25 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr } else if (instruction->modifier == CallModifierNoAsync && !fn_is_async(g->cur_fn)) { gen_resume(g, fn_val, frame_result_loc, ResumeIdCall); + if (ir_want_runtime_safety(g, &instruction->base)) { + LLVMValueRef awaiter_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, + frame_awaiter_index, ""); + LLVMValueRef all_ones = LLVMConstAllOnes(usize_type_ref); + LLVMValueRef prev_val = gen_maybe_atomic_op(g, LLVMAtomicRMWBinOpXchg, awaiter_ptr, + all_ones, LLVMAtomicOrderingRelease); + LLVMValueRef ok_val = LLVMBuildICmp(g->builder, LLVMIntEQ, prev_val, all_ones, ""); + + LLVMBasicBlockRef bad_block = LLVMAppendBasicBlock(g->cur_fn_val, "NoAsyncPanic"); + LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "NoAsyncOk"); + LLVMBuildCondBr(g->builder, ok_val, ok_block, bad_block); + + // The async function suspended, but this noasync call asserted it wouldn't. + LLVMPositionBuilderAtEnd(g->builder, bad_block); + gen_safety_crash(g, PanicMsgIdBadNoAsyncCall); + + LLVMPositionBuilderAtEnd(g->builder, ok_block); + } + ZigType *result_type = instruction->base.value.type; ZigType *ptr_result_type = get_pointer_to_type(g, result_type, true); return gen_await_early_return(g, &instruction->base, frame_result_loc, diff --git a/test/runtime_safety.zig b/test/runtime_safety.zig index 07a8c3910a213ff99fea1482745def4a41dbe339..17f0f3230c2138b4c19ec049d46d96f0803a82be 100644 --- a/test/runtime_safety.zig +++ b/test/runtime_safety.zig @@ -1,6 +1,21 @@ const tests = @import("tests.zig"); pub fn addCases(cases: *tests.CompareOutputContext) void { + cases.addRuntimeSafety("noasync function call, callee suspends", + \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn { + \\ @import("std").os.exit(126); + \\} + \\pub fn main() void { + \\ _ = noasync add(101, 100); + \\} + \\fn add(a: i32, b: i32) i32 { + \\ if (a > 100) { + \\ suspend; + \\ } + \\ return a + b; + \\} + ); + cases.addRuntimeSafety("awaiting twice", \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn { \\ @import("std").os.exit(126); -- 2.54.0 From 9423d382fb1c9e95f1d8cd7f6db8a917b082a97a Mon Sep 17 00:00:00 2001 From: emekoi Date: Fri, 6 Sep 2019 16:03:34 -0500 Subject: [PATCH 53/80] fixed compiler error for gcc 9.2.0 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f296f9dee491376b4d23261b17272a762275390b..d44cf5890f57d121484c97f017f7b4716232ba00 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -505,7 +505,7 @@ endif() if(MSVC) set(EXE_CFLAGS "${EXE_CFLAGS}") else() - set(EXE_CFLAGS "${EXE_CFLAGS} -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -D_GNU_SOURCE -fvisibility-inlines-hidden -fno-exceptions -fno-rtti -Werror=strict-prototypes -Werror=old-style-definition -Werror=type-limits -Wno-missing-braces") + set(EXE_CFLAGS "${EXE_CFLAGS} -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -D_GNU_SOURCE -fvisibility-inlines-hidden -fno-exceptions -fno-rtti -Werror=type-limits -Wno-missing-braces") if(MINGW) set(EXE_CFLAGS "${EXE_CFLAGS} -Wno-format") endif() -- 2.54.0 From 9ca8d9e21ad657b023c23db5c440fb79a3303771 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Fri, 6 Sep 2019 16:17:39 -0400 Subject: [PATCH 54/80] fix await used in an expression generating bad LLVM --- src/analyze.cpp | 112 +++++++++++++++++++++--------- src/analyze.hpp | 4 ++ src/codegen.cpp | 25 ++++--- test/stage1/behavior/async_fn.zig | 16 +++++ 4 files changed, 113 insertions(+), 44 deletions(-) diff --git a/src/analyze.cpp b/src/analyze.cpp index fa93a9764cb5fee67d2d3974775e08d0edde4b79..c7da62042816341729ee20e9ddb829e7cfe8a826 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -4232,31 +4232,40 @@ static Error analyze_callee_async(CodeGen *g, ZigFn *fn, ZigFn *callee, AstNode { if (modifier == CallModifierNoAsync) return ErrorNone; - if (callee->type_entry->data.fn.fn_type_id.cc != CallingConventionUnspecified) - return ErrorNone; - if (callee->anal_state == FnAnalStateReady) { - analyze_fn_body(g, callee); - if (callee->anal_state == FnAnalStateInvalid) { - return ErrorSemanticAnalyzeFail; - } + bool callee_is_async = false; + switch (callee->type_entry->data.fn.fn_type_id.cc) { + case CallingConventionUnspecified: + break; + case CallingConventionAsync: + callee_is_async = true; + break; + default: + return ErrorNone; } - bool callee_is_async; - if (callee->anal_state == FnAnalStateComplete) { - analyze_fn_async(g, callee, true); - if (callee->anal_state == FnAnalStateInvalid) { - return ErrorSemanticAnalyzeFail; + if (!callee_is_async) { + if (callee->anal_state == FnAnalStateReady) { + analyze_fn_body(g, callee); + if (callee->anal_state == FnAnalStateInvalid) { + return ErrorSemanticAnalyzeFail; + } } - callee_is_async = fn_is_async(callee); - } else { - // If it's already been determined, use that value. Otherwise - // assume non-async, emit an error later if it turned out to be async. - if (callee->inferred_async_node == nullptr || - callee->inferred_async_node == inferred_async_checking) - { - callee->assumed_non_async = call_node; - callee_is_async = false; + if (callee->anal_state == FnAnalStateComplete) { + analyze_fn_async(g, callee, true); + if (callee->anal_state == FnAnalStateInvalid) { + return ErrorSemanticAnalyzeFail; + } + callee_is_async = fn_is_async(callee); } else { - callee_is_async = callee->inferred_async_node != inferred_async_none; + // If it's already been determined, use that value. Otherwise + // assume non-async, emit an error later if it turned out to be async. + if (callee->inferred_async_node == nullptr || + callee->inferred_async_node == inferred_async_checking) + { + callee->assumed_non_async = call_node; + callee_is_async = false; + } else { + callee_is_async = callee->inferred_async_node != inferred_async_none; + } } } if (callee_is_async) { @@ -4333,6 +4342,8 @@ static void analyze_fn_async(CodeGen *g, ZigFn *fn, bool resolve_frame) { } for (size_t i = 0; i < fn->await_list.length; i += 1) { IrInstructionAwaitGen *await = fn->await_list.at(i); + // TODO If this is a noasync await, it doesn't count + // https://github.com/ziglang/zig/issues/3157 switch (analyze_callee_async(g, fn, await->target_fn, await->base.source_node, must_not_be_async, CallModifierNone)) { @@ -5771,15 +5782,39 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) { if (!fn_is_async(callee)) continue; - IrInstructionAllocaGen *alloca_gen = allocate(1); - alloca_gen->base.id = IrInstructionIdAllocaGen; - alloca_gen->base.source_node = call->base.source_node; - alloca_gen->base.scope = call->base.scope; - alloca_gen->base.value.type = get_pointer_to_type(g, callee_frame_type, false); - alloca_gen->base.ref_count = 1; - alloca_gen->name_hint = ""; - fn->alloca_gen_list.append(alloca_gen); - call->frame_result_loc = &alloca_gen->base; + call->frame_result_loc = ir_create_alloca(g, call->base.scope, call->base.source_node, fn, + callee_frame_type, ""); + } + // Since this frame is async, an await might represent a suspend point, and + // therefore need to spill. + for (size_t i = 0; i < fn->await_list.length; i += 1) { + IrInstructionAwaitGen *await = fn->await_list.at(i); + // TODO If this is a noasync await, it doesn't need to spill + // https://github.com/ziglang/zig/issues/3157 + if (await->result_loc != nullptr) { + // If there's a result location, that is the spill + continue; + } + if (!type_has_bits(await->base.value.type)) + continue; + if (await->base.value.special != ConstValSpecialRuntime) + continue; + if (await->base.ref_count == 0) + continue; + if (await->target_fn != nullptr) { + // we might not need to suspend + analyze_fn_async(g, await->target_fn, false); + if (await->target_fn->anal_state == FnAnalStateInvalid) { + frame_type->data.frame.locals_struct = g->builtin_types.entry_invalid; + return ErrorSemanticAnalyzeFail; + } + if (!fn_is_async(await->target_fn)) { + // This await does not represent a suspend point. No spill needed. + continue; + } + } + await->result_loc = ir_create_alloca(g, await->base.scope, await->base.source_node, fn, + await->base.value.type, ""); } FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id; ZigType *ptr_return_type = get_pointer_to_type(g, fn_type_id->return_type, false); @@ -8505,3 +8540,18 @@ void src_assert(bool ok, AstNode *source_node) { const char *msg = "assertion failed. This is a bug in the Zig compiler."; stage2_panic(msg, strlen(msg)); } + +IrInstruction *ir_create_alloca(CodeGen *g, Scope *scope, AstNode *source_node, ZigFn *fn, + ZigType *var_type, const char *name_hint) +{ + IrInstructionAllocaGen *alloca_gen = allocate(1); + alloca_gen->base.id = IrInstructionIdAllocaGen; + alloca_gen->base.source_node = source_node; + alloca_gen->base.scope = scope; + alloca_gen->base.value.type = get_pointer_to_type(g, var_type, false); + alloca_gen->base.ref_count = 1; + alloca_gen->name_hint = name_hint; + fn->alloca_gen_list.append(alloca_gen); + return &alloca_gen->base; +} + diff --git a/src/analyze.hpp b/src/analyze.hpp index 9f2c984992908574c9726b99a7c8ec355a9385dc..2178327571f24d684bf6e10eed49daf69afd844b 100644 --- a/src/analyze.hpp +++ b/src/analyze.hpp @@ -258,4 +258,8 @@ ZigType *resolve_struct_field_type(CodeGen *g, TypeStructField *struct_field); void add_async_error_notes(CodeGen *g, ErrorMsg *msg, ZigFn *fn); +IrInstruction *ir_create_alloca(CodeGen *g, Scope *scope, AstNode *source_node, ZigFn *fn, + ZigType *var_type, const char *name_hint); + + #endif diff --git a/src/codegen.cpp b/src/codegen.cpp index 6c03be32c3188e7c8169b22210bdf0c31ada3595..bbb1d9fc8715b35165705d42f57a8865309577da 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -1661,6 +1661,14 @@ static LLVMValueRef ir_llvm_value(CodeGen *g, IrInstruction *instruction) { if (!type_has_bits(instruction->value.type)) return nullptr; if (!instruction->llvm_value) { + if (instruction->id == IrInstructionIdAwaitGen) { + IrInstructionAwaitGen *await = reinterpret_cast(instruction); + if (await->result_loc != nullptr) { + instruction->llvm_value = get_handle_value(g, ir_llvm_value(g, await->result_loc), + await->result_loc->value.type->data.pointer.child_type, await->result_loc->value.type); + return instruction->llvm_value; + } + } src_assert(instruction->value.special != ConstValSpecialRuntime, instruction->source_node); assert(instruction->value.type); render_const_val(g, &instruction->value, ""); @@ -5645,7 +5653,6 @@ static LLVMValueRef ir_render_await(CodeGen *g, IrExecutable *executable, IrInst // At this point resuming the function will continue from resume_bb. // This code is as if it is running inside the suspend block. - // supply the awaiter return pointer if (type_has_bits(result_type)) { LLVMValueRef awaiter_ret_ptr_ptr = LLVMBuildStructGEP(g->builder, target_frame_ptr, frame_ret_start + 1, ""); @@ -5703,9 +5710,8 @@ static LLVMValueRef ir_render_await(CodeGen *g, IrExecutable *executable, IrInst LLVMBuildBr(g->builder, end_bb); LLVMPositionBuilderAtEnd(g->builder, end_bb); - if (type_has_bits(result_type) && result_loc != nullptr) { - return get_handle_value(g, result_loc, result_type, ptr_result_type); - } + // Rely on the spill for the llvm_value to be populated. + // See the implementation of ir_llvm_value. return nullptr; } @@ -7153,15 +7159,8 @@ static void do_code_gen(CodeGen *g) { if (call->frame_result_loc != nullptr) continue; ZigType *callee_frame_type = get_fn_frame_type(g, call->fn_entry); - IrInstructionAllocaGen *alloca_gen = allocate(1); - alloca_gen->base.id = IrInstructionIdAllocaGen; - alloca_gen->base.source_node = call->base.source_node; - alloca_gen->base.scope = call->base.scope; - alloca_gen->base.value.type = get_pointer_to_type(g, callee_frame_type, false); - alloca_gen->base.ref_count = 1; - alloca_gen->name_hint = ""; - fn_table_entry->alloca_gen_list.append(alloca_gen); - call->frame_result_loc = &alloca_gen->base; + call->frame_result_loc = ir_create_alloca(g, call->base.scope, call->base.source_node, + fn_table_entry, callee_frame_type, ""); } // allocate temporary stack data for (size_t alloca_i = 0; alloca_i < fn_table_entry->alloca_gen_list.length; alloca_i += 1) { diff --git a/test/stage1/behavior/async_fn.zig b/test/stage1/behavior/async_fn.zig index a898889f5c9cfc1ff3840514f05ac463ba079711..3079a7b98a1f8f2ba3650d91a73f6e7ce4994a64 100644 --- a/test/stage1/behavior/async_fn.zig +++ b/test/stage1/behavior/async_fn.zig @@ -1108,3 +1108,19 @@ test "noasync function call" { }; S.doTheTest(); } + +test "await used in expression and awaiting fn with no suspend but async calling convention" { + const S = struct { + fn atest() void { + var f1 = async add(1, 2); + var f2 = async add(3, 4); + + const sum = (await f1) + (await f2); + expect(sum == 10); + } + async fn add(a: i32, b: i32) i32 { + return a + b; + } + }; + _ = async S.atest(); +} -- 2.54.0 From d1a98ccff481183d7fc53e45a902ef273c3d6aeb Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sat, 7 Sep 2019 00:12:15 -0400 Subject: [PATCH 55/80] implement spills when expressions used across suspend points closes #3077 --- src/all_types.hpp | 23 +++++ src/analyze.cpp | 159 +++++++++++++++++++++++++++--- src/analyze.hpp | 2 +- src/codegen.cpp | 17 +++- src/ir.cpp | 12 ++- std/event/future.zig | 6 +- test/stage1/behavior/async_fn.zig | 28 ++++-- 7 files changed, 218 insertions(+), 29 deletions(-) diff --git a/src/all_types.hpp b/src/all_types.hpp index afe8bd0675bf5d0d58c749c3247223d6cde5d847..8ba3e4f484f47d82368741608a3247733063c768 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -2124,6 +2124,7 @@ enum ScopeId { ScopeIdCompTime, ScopeIdRuntime, ScopeIdTypeOf, + ScopeIdExpr, }; struct Scope { @@ -2271,6 +2272,24 @@ struct ScopeTypeOf { Scope base; }; +enum MemoizedBool { + MemoizedBoolUnknown, + MemoizedBoolFalse, + MemoizedBoolTrue, +}; + +// This scope is created for each expression. +// It's used to identify when an instruction needs to be spilled, +// so that it can be accessed after a suspend point. +struct ScopeExpr { + Scope base; + + ScopeExpr **children_ptr; + size_t children_len; + + MemoizedBool need_spill; +}; + // synchronized with code in define_builtin_compile_vars enum AtomicOrder { AtomicOrderUnordered, @@ -2510,6 +2529,10 @@ struct IrInstruction { // with this child field. IrInstruction *child; IrBasicBlock *owner_bb; + // Nearly any instruction can have to be stored as a local variable before suspending + // and then loaded after resuming, in case there is an expression with a suspend point + // in it, such as: x + await y + IrInstruction *spill; IrInstructionId id; // true if this instruction was generated by zig and not from user code bool is_gen; diff --git a/src/analyze.cpp b/src/analyze.cpp index c7da62042816341729ee20e9ddb829e7cfe8a826..bbb5b7192b1b405031c1f3f427489727543135d8 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -96,6 +96,30 @@ static ScopeDecls **get_container_scope_ptr(ZigType *type_entry) { zig_unreachable(); } +static ScopeExpr *find_expr_scope(Scope *scope) { + for (;;) { + switch (scope->id) { + case ScopeIdExpr: + return reinterpret_cast(scope); + case ScopeIdDefer: + case ScopeIdDeferExpr: + case ScopeIdDecls: + case ScopeIdFnDef: + case ScopeIdCompTime: + case ScopeIdVarDecl: + case ScopeIdCImport: + case ScopeIdSuspend: + case ScopeIdTypeOf: + case ScopeIdBlock: + return nullptr; + case ScopeIdLoop: + case ScopeIdRuntime: + scope = scope->parent; + continue; + } + } +} + ScopeDecls *get_container_scope(ZigType *type_entry) { return *get_container_scope_ptr(type_entry); } @@ -203,6 +227,20 @@ Scope *create_typeof_scope(CodeGen *g, AstNode *node, Scope *parent) { return &scope->base; } +Scope *create_expr_scope(CodeGen *g, AstNode *node, Scope *parent) { + ScopeExpr *scope = allocate(1); + init_scope(g, &scope->base, ScopeIdExpr, node, parent); + ScopeExpr *parent_expr = find_expr_scope(parent); + if (parent_expr != nullptr) { + size_t new_len = parent_expr->children_len + 1; + parent_expr->children_ptr = reallocate_nonzero( + parent_expr->children_ptr, parent_expr->children_len, new_len); + parent_expr->children_ptr[parent_expr->children_len] = scope; + parent_expr->children_len = new_len; + } + return &scope->base; +} + ZigType *get_scope_import(Scope *scope) { while (scope) { if (scope->id == ScopeIdDecls) { @@ -5654,6 +5692,69 @@ static ZigType *get_async_fn_type(CodeGen *g, ZigType *orig_fn_type) { return fn_type; } +// Traverse up to the very top ExprScope, which has children. +// We have just arrived at the top from a child. That child, +// and its next siblings, do not need to be marked. But the previous +// siblings do. +// x + (await y) +// vs +// (await y) + x +static void mark_suspension_point(Scope *scope) { + ScopeExpr *child_expr_scope = (scope->id == ScopeIdExpr) ? reinterpret_cast(scope) : nullptr; + for (;;) { + scope = scope->parent; + switch (scope->id) { + case ScopeIdDefer: + case ScopeIdDeferExpr: + case ScopeIdDecls: + case ScopeIdFnDef: + case ScopeIdCompTime: + case ScopeIdVarDecl: + case ScopeIdCImport: + case ScopeIdSuspend: + case ScopeIdTypeOf: + case ScopeIdBlock: + return; + case ScopeIdLoop: + case ScopeIdRuntime: + continue; + case ScopeIdExpr: { + ScopeExpr *parent_expr_scope = reinterpret_cast(scope); + if (child_expr_scope != nullptr) { + for (size_t i = 0; parent_expr_scope->children_ptr[i] != child_expr_scope; i += 1) { + assert(i < parent_expr_scope->children_len); + parent_expr_scope->children_ptr[i]->need_spill = MemoizedBoolTrue; + } + } + parent_expr_scope->need_spill = MemoizedBoolTrue; + child_expr_scope = parent_expr_scope; + continue; + } + } + } +} + +static bool scope_needs_spill(Scope *scope) { + ScopeExpr *scope_expr = find_expr_scope(scope); + if (scope_expr == nullptr) return false; + + switch (scope_expr->need_spill) { + case MemoizedBoolUnknown: + if (scope_needs_spill(scope_expr->base.parent)) { + scope_expr->need_spill = MemoizedBoolTrue; + return true; + } else { + scope_expr->need_spill = MemoizedBoolFalse; + return false; + } + case MemoizedBoolFalse: + return false; + case MemoizedBoolTrue: + return true; + } + zig_unreachable(); +} + static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) { Error err; @@ -5786,21 +5887,17 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) { callee_frame_type, ""); } // Since this frame is async, an await might represent a suspend point, and - // therefore need to spill. + // therefore need to spill. It also needs to mark expr scopes as having to spill. + // For example: foo() + await z + // The funtion call result of foo() must be spilled. for (size_t i = 0; i < fn->await_list.length; i += 1) { IrInstructionAwaitGen *await = fn->await_list.at(i); - // TODO If this is a noasync await, it doesn't need to spill + // TODO If this is a noasync await, it doesn't suspend // https://github.com/ziglang/zig/issues/3157 - if (await->result_loc != nullptr) { - // If there's a result location, that is the spill + if (await->base.value.special != ConstValSpecialRuntime) { + // Known at comptime. No spill, no suspend. continue; } - if (!type_has_bits(await->base.value.type)) - continue; - if (await->base.value.special != ConstValSpecialRuntime) - continue; - if (await->base.ref_count == 0) - continue; if (await->target_fn != nullptr) { // we might not need to suspend analyze_fn_async(g, await->target_fn, false); @@ -5809,13 +5906,53 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) { return ErrorSemanticAnalyzeFail; } if (!fn_is_async(await->target_fn)) { - // This await does not represent a suspend point. No spill needed. + // This await does not represent a suspend point. No spill needed, + // and no need to mark ExprScope. continue; } } + // This await is a suspend point, but it might not need a spill. + // We do need to mark the ExprScope as having a suspend point in it. + mark_suspension_point(await->base.scope); + + if (await->result_loc != nullptr) { + // If there's a result location, that is the spill + continue; + } + if (await->base.ref_count == 0) + continue; + if (!type_has_bits(await->base.value.type)) + continue; await->result_loc = ir_create_alloca(g, await->base.scope, await->base.source_node, fn, await->base.value.type, ""); } + // Now that we've marked all the expr scopes that have to spill, we go over the instructions + // and spill the relevant ones. + for (size_t block_i = 0; block_i < fn->analyzed_executable.basic_block_list.length; block_i += 1) { + IrBasicBlock *block = fn->analyzed_executable.basic_block_list.at(block_i); + for (size_t instr_i = 0; instr_i < block->instruction_list.length; instr_i += 1) { + IrInstruction *instruction = block->instruction_list.at(instr_i); + if (instruction->id == IrInstructionIdAwaitGen || + instruction->id == IrInstructionIdVarPtr || + instruction->id == IrInstructionIdDeclRef || + instruction->id == IrInstructionIdAllocaGen) + { + // This instruction does its own spilling specially, or otherwise doesn't need it. + continue; + } + if (instruction->value.special != ConstValSpecialRuntime) + continue; + if (instruction->ref_count == 0) + continue; + if (!type_has_bits(instruction->value.type)) + continue; + if (scope_needs_spill(instruction->scope)) { + instruction->spill = ir_create_alloca(g, instruction->scope, instruction->source_node, + fn, instruction->value.type, ""); + } + } + } + FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id; ZigType *ptr_return_type = get_pointer_to_type(g, fn_type_id->return_type, false); diff --git a/src/analyze.hpp b/src/analyze.hpp index 2178327571f24d684bf6e10eed49daf69afd844b..55bf9aba30c4e244a3de78050f43df9003f33a2d 100644 --- a/src/analyze.hpp +++ b/src/analyze.hpp @@ -114,6 +114,7 @@ ScopeFnDef *create_fndef_scope(CodeGen *g, AstNode *node, Scope *parent, ZigFn * Scope *create_comptime_scope(CodeGen *g, AstNode *node, Scope *parent); Scope *create_runtime_scope(CodeGen *g, AstNode *node, Scope *parent, IrInstruction *is_comptime); Scope *create_typeof_scope(CodeGen *g, AstNode *node, Scope *parent); +Scope *create_expr_scope(CodeGen *g, AstNode *node, Scope *parent); void init_const_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *str); ConstExprValue *create_const_str_lit(CodeGen *g, Buf *str); @@ -261,5 +262,4 @@ void add_async_error_notes(CodeGen *g, ErrorMsg *msg, ZigFn *fn); IrInstruction *ir_create_alloca(CodeGen *g, Scope *scope, AstNode *source_node, ZigFn *fn, ZigType *var_type, const char *name_hint); - #endif diff --git a/src/codegen.cpp b/src/codegen.cpp index bbb1d9fc8715b35165705d42f57a8865309577da..134569374e2b70abe9b3d644d6079872e2523cf6 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -649,6 +649,7 @@ static ZigLLVMDIScope *get_di_scope(CodeGen *g, Scope *scope) { case ScopeIdCompTime: case ScopeIdRuntime: case ScopeIdTypeOf: + case ScopeIdExpr: return get_di_scope(g, scope->parent); } zig_unreachable(); @@ -1644,7 +1645,6 @@ static void gen_assign_raw(CodeGen *g, LLVMValueRef ptr, ZigType *ptr_type, LLVMValueRef ored_value = LLVMBuildOr(g->builder, shifted_value, anded_containing_int, ""); gen_store(g, ored_value, ptr, ptr_type); - return; } static void gen_var_debug_decl(CodeGen *g, ZigVar *var) { @@ -1664,11 +1664,16 @@ static LLVMValueRef ir_llvm_value(CodeGen *g, IrInstruction *instruction) { if (instruction->id == IrInstructionIdAwaitGen) { IrInstructionAwaitGen *await = reinterpret_cast(instruction); if (await->result_loc != nullptr) { - instruction->llvm_value = get_handle_value(g, ir_llvm_value(g, await->result_loc), + return get_handle_value(g, ir_llvm_value(g, await->result_loc), await->result_loc->value.type->data.pointer.child_type, await->result_loc->value.type); - return instruction->llvm_value; } } + if (instruction->spill != nullptr) { + ZigType *ptr_type = instruction->spill->value.type; + src_assert(ptr_type->id == ZigTypeIdPointer, instruction->source_node); + return get_handle_value(g, ir_llvm_value(g, instruction->spill), + ptr_type->data.pointer.child_type, instruction->spill->value.type); + } src_assert(instruction->value.special != ConstValSpecialRuntime, instruction->source_node); assert(instruction->value.type); render_const_val(g, &instruction->value, ""); @@ -3786,6 +3791,7 @@ static void render_async_var_decls(CodeGen *g, Scope *scope) { case ScopeIdCompTime: case ScopeIdRuntime: case ScopeIdTypeOf: + case ScopeIdExpr: scope = scope->parent; continue; } @@ -6049,6 +6055,11 @@ static void ir_render(CodeGen *g, ZigFn *fn_entry) { set_debug_location(g, instruction); } instruction->llvm_value = ir_render_instruction(g, executable, instruction); + if (instruction->spill != nullptr) { + LLVMValueRef spill_ptr = ir_llvm_value(g, instruction->spill); + gen_assign_raw(g, spill_ptr, instruction->spill->value.type, instruction->llvm_value); + instruction->llvm_value = nullptr; + } } current_block->llvm_exit_block = LLVMGetInsertBlock(g->builder); } diff --git a/src/ir.cpp b/src/ir.cpp index 53ce2d89e18a57b3b0c3232f01541971bef90819..1a0aad36e97547a49009d4e3891f4dcebc6376bc 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -3364,6 +3364,7 @@ static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_sco case ScopeIdCompTime: case ScopeIdRuntime: case ScopeIdTypeOf: + case ScopeIdExpr: scope = scope->parent; continue; case ScopeIdDeferExpr: @@ -3420,6 +3421,7 @@ static bool ir_gen_defers_for_block(IrBuilder *irb, Scope *inner_scope, Scope *o case ScopeIdCompTime: case ScopeIdRuntime: case ScopeIdTypeOf: + case ScopeIdExpr: scope = scope->parent; continue; case ScopeIdDeferExpr: @@ -8158,7 +8160,15 @@ static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, Scope *sc result_loc = no_result_loc(); ir_build_reset_result(irb, scope, node, result_loc); } - IrInstruction *result = ir_gen_node_raw(irb, node, scope, lval, result_loc); + Scope *child_scope; + if (irb->exec->is_inline || + (irb->exec->fn_entry != nullptr && irb->exec->fn_entry->child_scope == scope)) + { + child_scope = scope; + } else { + child_scope = create_expr_scope(irb->codegen, node, scope); + } + IrInstruction *result = ir_gen_node_raw(irb, node, child_scope, lval, result_loc); if (result == irb->codegen->invalid_instruction) { if (irb->exec->first_err_trace_msg == nullptr) { irb->exec->first_err_trace_msg = irb->codegen->trace_err; diff --git a/std/event/future.zig b/std/event/future.zig index 117765a5254df633fa90ed8f842f4e8c959e8650..b55b795de6fa501a33d087e51282dc8fcb67f7f7 100644 --- a/std/event/future.zig +++ b/std/event/future.zig @@ -104,11 +104,7 @@ fn testFuture(loop: *Loop) void { var b = async waitOnFuture(&future); resolveFuture(&future); - // TODO https://github.com/ziglang/zig/issues/3077 - //const result = (await a) + (await b); - const a_result = await a; - const b_result = await b; - const result = a_result + b_result; + const result = (await a) + (await b); testing.expect(result == 12); } diff --git a/test/stage1/behavior/async_fn.zig b/test/stage1/behavior/async_fn.zig index 3079a7b98a1f8f2ba3650d91a73f6e7ce4994a64..cef950fe0cde2fca2a8dc5df7f5338aa74e68f0f 100644 --- a/test/stage1/behavior/async_fn.zig +++ b/test/stage1/behavior/async_fn.zig @@ -921,12 +921,10 @@ fn recursiveAsyncFunctionTest(comptime suspending_implementation: bool) type { var sum: u32 = 0; f1_awaited = true; - const result_f1 = await f1; // TODO https://github.com/ziglang/zig/issues/3077 - sum += try result_f1; + sum += try await f1; f2_awaited = true; - const result_f2 = await f2; // TODO https://github.com/ziglang/zig/issues/3077 - sum += try result_f2; + sum += try await f2; return sum; } @@ -943,8 +941,7 @@ fn recursiveAsyncFunctionTest(comptime suspending_implementation: bool) type { fn amain(result: *u32) void { var x = async fib(std.heap.direct_allocator, 10); - const res = await x; // TODO https://github.com/ziglang/zig/issues/3077 - result.* = res catch unreachable; + result.* = (await x) catch unreachable; } }; } @@ -1002,8 +999,7 @@ test "@asyncCall using the result location inside the frame" { return 1234; } fn getAnswer(f: anyframe->i32, out: *i32) void { - var res = await f; // TODO https://github.com/ziglang/zig/issues/3077 - out.* = res; + out.* = await f; } }; var data: i32 = 1; @@ -1124,3 +1120,19 @@ test "await used in expression and awaiting fn with no suspend but async calling }; _ = async S.atest(); } + +test "await used in expression after a fn call" { + const S = struct { + fn atest() void { + var f1 = async add(3, 4); + var sum: i32 = 0; + sum = foo() + await f1; + expect(sum == 8); + } + async fn add(a: i32, b: i32) i32 { + return a + b; + } + fn foo() i32 { return 1; } + }; + _ = async S.atest(); +} -- 2.54.0 From 9a18db8a80c96d206297e865d203b2a7d8a803ba Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sat, 7 Sep 2019 00:27:45 -0400 Subject: [PATCH 56/80] properly spill expressions with async function calls --- src/analyze.cpp | 2 ++ test/stage1/behavior/async_fn.zig | 15 +++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/src/analyze.cpp b/src/analyze.cpp index bbb5b7192b1b405031c1f3f427489727543135d8..d751dbdb97e17d8f34eeb0cde984769b1b6aece5 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -5883,6 +5883,8 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) { if (!fn_is_async(callee)) continue; + mark_suspension_point(call->base.scope); + call->frame_result_loc = ir_create_alloca(g, call->base.scope, call->base.source_node, fn, callee_frame_type, ""); } diff --git a/test/stage1/behavior/async_fn.zig b/test/stage1/behavior/async_fn.zig index cef950fe0cde2fca2a8dc5df7f5338aa74e68f0f..f5669f0fca1f9c5a770fb090222e8cdb8833384c 100644 --- a/test/stage1/behavior/async_fn.zig +++ b/test/stage1/behavior/async_fn.zig @@ -1136,3 +1136,18 @@ test "await used in expression after a fn call" { }; _ = async S.atest(); } + +test "async fn call used in expression after a fn call" { + const S = struct { + fn atest() void { + var sum: i32 = 0; + sum = foo() + add(3, 4); + expect(sum == 8); + } + async fn add(a: i32, b: i32) i32 { + return a + b; + } + fn foo() i32 { return 1; } + }; + _ = async S.atest(); +} -- 2.54.0 From 99fd42404a5aa98e15bc1ceaf56bcc0fe570943f Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sat, 7 Sep 2019 14:46:59 -0400 Subject: [PATCH 57/80] update process_headers tool for glibc 2.30 --- tools/process_headers.zig | 396 +++++++------------------------------- 1 file changed, 70 insertions(+), 326 deletions(-) diff --git a/tools/process_headers.zig b/tools/process_headers.zig index d18e25355f44c15ff0dfa2fbd4d9f1ad80d0e6d9..420c118cb976ccbbe697ce2a25609d40caaab8da 100644 --- a/tools/process_headers.zig +++ b/tools/process_headers.zig @@ -20,6 +20,7 @@ const assert = std.debug.assert; const LibCTarget = struct { name: []const u8, arch: MultiArch, + abi: MultiAbi, }; const MultiArch = union(enum) { @@ -39,396 +40,129 @@ const MultiArch = union(enum) { } }; +const MultiAbi = union(enum) { + musl, + specific: Abi, + + fn eql(a: MultiAbi, b: MultiAbi) bool { + if (@enumToInt(a) != @enumToInt(b)) + return false; + if (@TagType(MultiAbi)(a) != .specific) + return true; + return a.specific == b.specific; + } +}; + const glibc_targets = [_]LibCTarget{ LibCTarget{ .name = "aarch64_be-linux-gnu", - .zig_arch = Arch.aarch64_be, - .zig_abi = Abi.gnu, + .arch = MultiArch {.specific = Arch.aarch64_be}, + .abi = MultiAbi {.specific = Abi.gnu}, }, LibCTarget{ .name = "aarch64-linux-gnu", - .zig_arch = Arch.aarch64, - .zig_abi = Abi.gnu, - }, - LibCTarget{ - .name = "aarch64-linux-gnu-disable-multi-arch", - .zig_arch = Arch.aarch64, - .zig_abi = null, - }, - LibCTarget{ - .name = "alpha-linux-gnu", - .zig_arch = null, - .zig_abi = Abi.gnu, + .arch = MultiArch {.specific = Arch.aarch64}, + .abi = MultiAbi {.specific = Abi.gnu}, }, LibCTarget{ .name = "armeb-linux-gnueabi", - .zig_arch = Arch.armeb, - .zig_abi = Abi.gnueabi, - }, - LibCTarget{ - .name = "armeb-linux-gnueabi-be8", - .zig_arch = Arch.armeb, - .zig_abi = null, + .arch = MultiArch {.specific = Arch.armeb}, + .abi = MultiAbi {.specific = Abi.gnueabi}, }, LibCTarget{ .name = "armeb-linux-gnueabihf", - .zig_arch = Arch.armeb, - .zig_abi = Abi.gnueabihf, - }, - LibCTarget{ - .name = "armeb-linux-gnueabihf-be8", - .zig_arch = Arch.armeb, - .zig_abi = null, + .arch = MultiArch {.specific = Arch.armeb}, + .abi = MultiAbi {.specific = Abi.gnueabihf}, }, LibCTarget{ .name = "arm-linux-gnueabi", - .zig_arch = Arch.arm, - .zig_abi = Abi.gnueabi, + .arch = MultiArch {.specific = Arch.arm}, + .abi = MultiAbi {.specific = Abi.gnueabi}, }, LibCTarget{ .name = "arm-linux-gnueabihf", - .zig_arch = Arch.arm, - .zig_abi = Abi.gnueabihf, - }, - LibCTarget{ - .name = "arm-linux-gnueabihf-v7a", - .zig_arch = Arch.arm, - .zig_abi = null, - }, - LibCTarget{ - .name = "arm-linux-gnueabihf-v7a-disable-multi-arch", - .zig_arch = null, - .zig_abi = null, - }, - LibCTarget{ - .name = "hppa-linux-gnu", - .zig_arch = null, - .zig_abi = Abi.gnu, - }, - LibCTarget{ - .name = "i486-linux-gnu", - .zig_arch = null, - .zig_abi = Abi.gnu, - }, - LibCTarget{ - .name = "i586-linux-gnu", - .zig_arch = null, - .zig_abi = Abi.gnu, - }, - LibCTarget{ - .name = "i686-gnu", - .zig_arch = Arch.i386, - .zig_abi = Abi.gnu, + .arch = MultiArch {.specific = Arch.arm}, + .abi = MultiAbi {.specific = Abi.gnueabihf}, }, LibCTarget{ .name = "i686-linux-gnu", - .zig_arch = Arch.i386, - .zig_abi = Abi.gnu, - }, - LibCTarget{ - .name = "i686-linux-gnu-disable-multi-arch", - .zig_arch = null, - .zig_abi = null, - }, - LibCTarget{ - .name = "i686-linux-gnu-enable-obsolete", - .zig_arch = Arch.i386, - .zig_abi = null, - }, - LibCTarget{ - .name = "i686-linux-gnu-static-pie", - .zig_arch = Arch.i386, - .zig_abi = null, - }, - LibCTarget{ - .name = "ia64-linux-gnu", - .zig_arch = null, - .zig_abi = null, - }, - LibCTarget{ - .name = "m68k-linux-gnu", - .zig_arch = null, - .zig_abi = null, - }, - LibCTarget{ - .name = "m68k-linux-gnu-coldfire", - .zig_arch = null, - .zig_abi = null, - }, - LibCTarget{ - .name = "m68k-linux-gnu-coldfire-soft", - .zig_arch = null, - .zig_abi = null, - }, - LibCTarget{ - .name = "microblazeel-linux-gnu", - .zig_arch = null, - .zig_abi = null, - }, - LibCTarget{ - .name = "microblaze-linux-gnu", - .zig_arch = null, - .zig_abi = null, + .arch = MultiArch {.specific = Arch.i386}, + .abi = MultiAbi {.specific = Abi.gnu}, }, LibCTarget{ .name = "mips64el-linux-gnu-n32", - .zig_arch = Arch.mips64el, - .zig_abi = Abi.gnuabin32, - }, - LibCTarget{ - .name = "mips64el-linux-gnu-n32-nan2008", - .zig_arch = Arch.mips64el, - .zig_abi = null, - }, - LibCTarget{ - .name = "mips64el-linux-gnu-n32-nan2008-soft", - .zig_arch = Arch.mips64el, - .zig_abi = null, - }, - LibCTarget{ - .name = "mips64el-linux-gnu-n32-soft", - .zig_arch = Arch.mips64el, - .zig_abi = null, + .arch = MultiArch {.specific = Arch.mips64el}, + .abi = MultiAbi {.specific = Abi.gnuabin32}, }, LibCTarget{ .name = "mips64el-linux-gnu-n64", - .zig_arch = Arch.mips64el, - .zig_abi = Abi.gnuabi64, - }, - LibCTarget{ - .name = "mips64el-linux-gnu-n64-nan2008", - .zig_arch = Arch.mips64el, - .zig_abi = null, - }, - LibCTarget{ - .name = "mips64el-linux-gnu-n64-nan2008-soft", - .zig_arch = Arch.mips64el, - .zig_abi = null, - }, - LibCTarget{ - .name = "mips64el-linux-gnu-n64-soft", - .zig_arch = Arch.mips64el, - .zig_abi = null, + .arch = MultiArch {.specific = Arch.mips64el}, + .abi = MultiAbi {.specific = Abi.gnuabi64}, }, LibCTarget{ .name = "mips64-linux-gnu-n32", - .zig_arch = Arch.mips64, - .zig_abi = Abi.gnuabin32, - }, - LibCTarget{ - .name = "mips64-linux-gnu-n32-nan2008", - .zig_arch = Arch.mips64, - .zig_abi = null, - }, - LibCTarget{ - .name = "mips64-linux-gnu-n32-nan2008-soft", - .zig_arch = Arch.mips64, - .zig_abi = null, - }, - LibCTarget{ - .name = "mips64-linux-gnu-n32-soft", - .zig_arch = Arch.mips64, - .zig_abi = null, + .arch = MultiArch {.specific = Arch.mips64}, + .abi = MultiAbi {.specific = Abi.gnuabin32}, }, LibCTarget{ .name = "mips64-linux-gnu-n64", - .zig_arch = Arch.mips64, - .zig_abi = Abi.gnuabi64, - }, - LibCTarget{ - .name = "mips64-linux-gnu-n64-nan2008", - .zig_arch = Arch.mips64, - .zig_abi = null, - }, - LibCTarget{ - .name = "mips64-linux-gnu-n64-nan2008-soft", - .zig_arch = Arch.mips64, - .zig_abi = null, - }, - LibCTarget{ - .name = "mips64-linux-gnu-n64-soft", - .zig_arch = Arch.mips64, - .zig_abi = null, + .arch = MultiArch {.specific = Arch.mips64}, + .abi = MultiAbi {.specific = Abi.gnuabi64}, }, LibCTarget{ .name = "mipsel-linux-gnu", - .zig_arch = Arch.mipsel, - .zig_abi = Abi.gnu, - }, - LibCTarget{ - .name = "mipsel-linux-gnu-nan2008", - .zig_arch = Arch.mipsel, - .zig_abi = null, - }, - LibCTarget{ - .name = "mipsel-linux-gnu-nan2008-soft", - .zig_arch = Arch.mipsel, - .zig_abi = null, - }, - LibCTarget{ - .name = "mipsel-linux-gnu-soft", - .zig_arch = Arch.mipsel, - .zig_abi = null, + .arch = MultiArch {.specific = Arch.mipsel}, + .abi = MultiAbi {.specific = Abi.gnu}, }, LibCTarget{ .name = "mips-linux-gnu", - .zig_arch = Arch.mips, - .zig_abi = Abi.gnu, - }, - LibCTarget{ - .name = "mips-linux-gnu-nan2008", - .zig_arch = Arch.mips, - .zig_abi = null, - }, - LibCTarget{ - .name = "mips-linux-gnu-nan2008-soft", - .zig_arch = Arch.mips, - .zig_abi = null, - }, - LibCTarget{ - .name = "mips-linux-gnu-soft", - .zig_arch = Arch.mips, - .zig_abi = null, + .arch = MultiArch {.specific = Arch.mips}, + .abi = MultiAbi {.specific = Abi.gnu}, }, LibCTarget{ .name = "powerpc64le-linux-gnu", - .zig_arch = Arch.powerpc64le, - .zig_abi = Abi.gnu, + .arch = MultiArch {.specific = Arch.powerpc64le}, + .abi = MultiAbi {.specific = Abi.gnu}, }, LibCTarget{ .name = "powerpc64-linux-gnu", - .zig_arch = Arch.powerpc64, - .zig_abi = Abi.gnu, + .arch = MultiArch {.specific = Arch.powerpc64}, + .abi = MultiAbi {.specific = Abi.gnu}, }, LibCTarget{ .name = "powerpc-linux-gnu", - .zig_arch = Arch.powerpc, - .zig_abi = Abi.gnu, - }, - LibCTarget{ - .name = "powerpc-linux-gnu-power4", - .zig_arch = Arch.powerpc, - .zig_abi = null, - }, - LibCTarget{ - .name = "powerpc-linux-gnu-soft", - .zig_arch = Arch.powerpc, - .zig_abi = null, - }, - LibCTarget{ - .name = "powerpc-linux-gnuspe", - .zig_arch = Arch.powerpc, - .zig_abi = null, - }, - LibCTarget{ - .name = "powerpc-linux-gnuspe-e500v1", - .zig_arch = Arch.powerpc, - .zig_abi = null, + .arch = MultiArch {.specific = Arch.powerpc}, + .abi = MultiAbi {.specific = Abi.gnu}, }, LibCTarget{ .name = "riscv64-linux-gnu-rv64imac-lp64", - .zig_arch = Arch.riscv64, - .zig_abi = Abi.gnu, - }, - LibCTarget{ - .name = "riscv64-linux-gnu-rv64imafdc-lp64", - .zig_arch = Arch.riscv64, - .zig_abi = null, - }, - LibCTarget{ - .name = "riscv64-linux-gnu-rv64imafdc-lp64d", - .zig_arch = Arch.riscv64, - .zig_abi = null, - }, - LibCTarget{ - .name = "s390-linux-gnu", - .zig_arch = null, - .zig_abi = Abi.gnu, + .arch = MultiArch {.specific = Arch.riscv64}, + .abi = MultiAbi {.specific = Abi.gnu}, }, LibCTarget{ .name = "s390x-linux-gnu", - .zig_arch = Arch.s390x, - .zig_abi = Abi.gnu, - }, - LibCTarget{ - .name = "sh3eb-linux-gnu", - .zig_arch = null, - .zig_abi = Abi.gnu, - }, - LibCTarget{ - .name = "sh3-linux-gnu", - .zig_arch = null, - .zig_abi = Abi.gnu, - }, - LibCTarget{ - .name = "sh4eb-linux-gnu", - .zig_arch = null, - .zig_abi = Abi.gnu, - }, - LibCTarget{ - .name = "sh4eb-linux-gnu-soft", - .zig_arch = null, - .zig_abi = null, - }, - LibCTarget{ - .name = "sh4-linux-gnu", - .zig_arch = null, - .zig_abi = Abi.gnu, - }, - LibCTarget{ - .name = "sh4-linux-gnu-soft", - .zig_arch = null, - .zig_abi = null, + .arch = MultiArch {.specific = Arch.s390x}, + .abi = MultiAbi {.specific = Abi.gnu}, }, LibCTarget{ .name = "sparc64-linux-gnu", - .zig_arch = Arch.sparc, - .zig_abi = Abi.gnu, - }, - LibCTarget{ - .name = "sparc64-linux-gnu-disable-multi-arch", - .zig_arch = Arch.sparc, - .zig_abi = null, + .arch = MultiArch {.specific = Arch.sparc}, + .abi = MultiAbi {.specific = Abi.gnu}, }, LibCTarget{ .name = "sparcv9-linux-gnu", - .zig_arch = Arch.sparcv9, - .zig_abi = Abi.gnu, - }, - LibCTarget{ - .name = "sparcv9-linux-gnu-disable-multi-arch", - .zig_arch = Arch.sparcv9, - .zig_abi = null, + .arch = MultiArch {.specific = Arch.sparcv9}, + .abi = MultiAbi {.specific = Abi.gnu}, }, LibCTarget{ .name = "x86_64-linux-gnu", - .zig_arch = Arch.x86_64, - .zig_abi = Abi.gnu, - }, - LibCTarget{ - .name = "x86_64-linux-gnu-disable-multi-arch", - .zig_arch = Arch.x86_64, - .zig_abi = null, - }, - LibCTarget{ - .name = "x86_64-linux-gnu-enable-obsolete", - .zig_arch = Arch.x86_64, - .zig_abi = null, - }, - LibCTarget{ - .name = "x86_64-linux-gnu-static-pie", - .zig_arch = Arch.x86_64, - .zig_abi = null, + .arch = MultiArch {.specific = Arch.x86_64}, + .abi = MultiAbi {.specific = Abi.gnu}, }, LibCTarget{ .name = "x86_64-linux-gnu-x32", - .zig_arch = Arch.x86_64, - .zig_abi = Abi.gnux32, - }, - LibCTarget{ - .name = "x86_64-linux-gnu-x32-static-pie", - .zig_arch = Arch.x86_64, - .zig_abi = null, + .arch = MultiArch {.specific = Arch.x86_64}, + .abi = MultiAbi {.specific = Abi.gnux32}, }, }; @@ -436,42 +170,52 @@ const musl_targets = [_]LibCTarget{ LibCTarget{ .name = "aarch64", .arch = MultiArch.aarch64, + .abi = MultiAbi.musl, }, LibCTarget{ .name = "arm", .arch = MultiArch.arm, + .abi = MultiAbi.musl, }, LibCTarget{ .name = "i386", .arch = MultiArch{ .specific = .i386 }, + .abi = MultiAbi.musl, }, LibCTarget{ .name = "mips", .arch = MultiArch.mips, + .abi = MultiAbi.musl, }, LibCTarget{ .name = "mips64", .arch = MultiArch.mips64, + .abi = MultiAbi.musl, }, LibCTarget{ .name = "powerpc", .arch = MultiArch{ .specific = .powerpc }, + .abi = MultiAbi.musl, }, LibCTarget{ .name = "powerpc64", .arch = MultiArch.powerpc64, + .abi = MultiAbi.musl, }, LibCTarget{ .name = "riscv64", .arch = MultiArch{ .specific = .riscv64 }, + .abi = MultiAbi.musl, }, LibCTarget{ .name = "s390x", .arch = MultiArch{ .specific = .s390x }, + .abi = MultiAbi.musl, }, LibCTarget{ .name = "x86_64", .arch = MultiArch{ .specific = .x86_64 }, + .abi = MultiAbi.musl, }, }; @@ -562,7 +306,7 @@ pub fn main() !void { var libc_targets: []const LibCTarget = undefined; switch (vendor) { .musl => libc_targets = musl_targets, - .glibc => @panic("TODO this regressed"), // glibc_targets, + .glibc => libc_targets = glibc_targets, } var path_table = PathTable.init(allocator); @@ -577,7 +321,7 @@ pub fn main() !void { .arch = libc_target.arch, .abi = switch (vendor) { .musl => .musl, - else => @panic("TODO this regressed"), + .glibc => libc_target.abi.specific, }, .os = .linux, }; -- 2.54.0 From 45ab9d5fd6c581d6879eae8a58c67a7b5b18fadf Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sat, 7 Sep 2019 14:59:38 -0400 Subject: [PATCH 58/80] update glibc headers to 2.30 --- .../include/aarch64-linux-gnu/bits/hwcap.h | 5 +- .../aarch64-linux-gnu/gnu/stubs-lp64.h | 6 - .../include/aarch64_be-linux-gnu/bits/hwcap.h | 5 +- .../aarch64_be-linux-gnu/gnu/stubs-lp64_be.h | 6 - .../bits/dirent_ext.h} | 26 +- .../include/generic-glibc/bits/fcntl-linux.h | 2 + lib/libc/include/generic-glibc/bits/in.h | 1 + .../bits/{xtitypes.h => signal_ext.h} | 24 +- .../bits/socket-constants.h} | 35 +-- lib/libc/include/generic-glibc/bits/socket.h | 98 +------- .../generic-glibc/bits/statx-generic.h | 60 +++++ lib/libc/include/generic-glibc/bits/statx.h | 80 +----- lib/libc/include/generic-glibc/bits/stropts.h | 230 ------------------ lib/libc/include/generic-glibc/bits/syscall.h | 156 +++++++++++- lib/libc/include/generic-glibc/bits/types.h | 19 +- .../generic-glibc/bits/types/struct_statx.h | 55 +++++ .../bits/types/struct_statx_timestamp.h} | 26 +- lib/libc/include/generic-glibc/dirent.h | 2 + lib/libc/include/generic-glibc/dlfcn.h | 12 + lib/libc/include/generic-glibc/elf.h | 32 ++- lib/libc/include/generic-glibc/features.h | 2 +- .../{bits => finclude}/math-vector-fortran.h | 0 lib/libc/include/generic-glibc/gconv.h | 11 +- lib/libc/include/generic-glibc/gnu/stubs-32.h | 2 - .../gnu/stubs-64.h | 6 - .../include/generic-glibc/gnu/stubs-hard.h | 6 - .../generic-glibc/gnu/stubs-n32_hard.h | 2 - .../generic-glibc/gnu/stubs-n64_hard.h | 2 - .../generic-glibc/gnu/stubs-o32_hard.h | 2 - .../include/generic-glibc/gnu/stubs-soft.h | 6 - lib/libc/include/generic-glibc/malloc.h | 20 +- lib/libc/include/generic-glibc/math.h | 17 +- lib/libc/include/generic-glibc/netinet/igmp.h | 1 + lib/libc/include/generic-glibc/netinet/in.h | 1 + lib/libc/include/generic-glibc/netinet/udp.h | 1 + lib/libc/include/generic-glibc/pthread.h | 36 +++ lib/libc/include/generic-glibc/resolv.h | 4 - lib/libc/include/generic-glibc/search.h | 7 + lib/libc/include/generic-glibc/semaphore.h | 30 ++- lib/libc/include/generic-glibc/signal.h | 3 + lib/libc/include/generic-glibc/stdlib.h | 13 +- lib/libc/include/generic-glibc/stropts.h | 92 ------- lib/libc/include/generic-glibc/sys/cdefs.h | 8 + lib/libc/include/generic-glibc/sys/ifunc.h | 42 ++++ lib/libc/include/generic-glibc/sys/io.h | 168 +++++++++++-- lib/libc/include/generic-glibc/sys/stropts.h | 1 - lib/libc/include/generic-glibc/sys/sysctl.h | 5 +- lib/libc/include/generic-glibc/sys/types.h | 33 +-- .../{bits => finclude}/math-vector-fortran.h | 0 lib/libc/include/i386-linux-gnu/sys/io.h | 183 -------------- .../mips-linux-gnu/bits/socket-constants.h | 38 +++ .../bits/socket-constants.h | 38 +++ .../bits/socket-constants.h | 38 +++ .../bits/socket-constants.h | 38 +++ .../bits/socket-constants.h | 38 +++ .../mipsel-linux-gnu/bits/socket-constants.h | 38 +++ .../powerpc-linux-gnu/bits/fenvinline.h | 37 ++- .../powerpc-linux-gnu/bits/socket-constants.h | 38 +++ .../include/powerpc-linux-gnu/fpu_control.h | 72 +++--- .../powerpc64-linux-gnu/bits/fenvinline.h | 37 ++- .../bits/socket-constants.h | 38 +++ .../include/powerpc64-linux-gnu/fpu_control.h | 72 +++--- .../powerpc64-linux-gnu/gnu/stubs-64-v1.h | 2 - .../powerpc64le-linux-gnu/bits/fenvinline.h | 37 ++- .../bits/socket-constants.h | 38 +++ .../powerpc64le-linux-gnu/fpu_control.h | 72 +++--- .../powerpc64le-linux-gnu/gnu/stubs-64-v2.h | 2 - .../riscv64-linux-gnu/gnu/stubs-lp64.h | 6 - lib/libc/include/s390x-linux-gnu/bits/hwcap.h | 6 +- .../sparc-linux-gnu/bits/socket-constants.h | 38 +++ .../include/sparc-linux-gnu/gnu/stubs-64.h | 26 -- .../sparcv9-linux-gnu/bits/socket-constants.h | 38 +++ .../include/sparcv9-linux-gnu/gnu/stubs-32.h | 26 -- .../{bits => finclude}/math-vector-fortran.h | 0 .../include/x86_64-linux-gnu/gnu/stubs-64.h | 4 - lib/libc/include/x86_64-linux-gnu/sys/io.h | 183 -------------- .../x86_64-linux-gnux32/bits/xtitypes.h | 33 --- .../{bits => finclude}/math-vector-fortran.h | 0 .../x86_64-linux-gnux32/gnu/stubs-x32.h | 4 - lib/libc/include/x86_64-linux-gnux32/sys/io.h | 183 -------------- 80 files changed, 1338 insertions(+), 1466 deletions(-) rename lib/libc/include/{i386-linux-gnu/bits/xtitypes.h => generic-glibc/bits/dirent_ext.h} (58%) rename lib/libc/include/generic-glibc/bits/{xtitypes.h => signal_ext.h} (58%) rename lib/libc/include/{x86_64-linux-gnu/bits/xtitypes.h => generic-glibc/bits/socket-constants.h} (56%) create mode 100644 lib/libc/include/generic-glibc/bits/statx-generic.h delete mode 100644 lib/libc/include/generic-glibc/bits/stropts.h create mode 100644 lib/libc/include/generic-glibc/bits/types/struct_statx.h rename lib/libc/include/{s390x-linux-gnu/bits/xtitypes.h => generic-glibc/bits/types/struct_statx_timestamp.h} (61%) rename lib/libc/include/generic-glibc/{bits => finclude}/math-vector-fortran.h (100%) rename lib/libc/include/{s390x-linux-gnu => generic-glibc}/gnu/stubs-64.h (77%) delete mode 100644 lib/libc/include/generic-glibc/stropts.h create mode 100644 lib/libc/include/generic-glibc/sys/ifunc.h delete mode 100644 lib/libc/include/generic-glibc/sys/stropts.h rename lib/libc/include/i386-linux-gnu/{bits => finclude}/math-vector-fortran.h (100%) delete mode 100644 lib/libc/include/i386-linux-gnu/sys/io.h create mode 100644 lib/libc/include/mips-linux-gnu/bits/socket-constants.h create mode 100644 lib/libc/include/mips64-linux-gnuabi64/bits/socket-constants.h create mode 100644 lib/libc/include/mips64-linux-gnuabin32/bits/socket-constants.h create mode 100644 lib/libc/include/mips64el-linux-gnuabi64/bits/socket-constants.h create mode 100644 lib/libc/include/mips64el-linux-gnuabin32/bits/socket-constants.h create mode 100644 lib/libc/include/mipsel-linux-gnu/bits/socket-constants.h create mode 100644 lib/libc/include/powerpc-linux-gnu/bits/socket-constants.h create mode 100644 lib/libc/include/powerpc64-linux-gnu/bits/socket-constants.h create mode 100644 lib/libc/include/powerpc64le-linux-gnu/bits/socket-constants.h create mode 100644 lib/libc/include/sparc-linux-gnu/bits/socket-constants.h delete mode 100644 lib/libc/include/sparc-linux-gnu/gnu/stubs-64.h create mode 100644 lib/libc/include/sparcv9-linux-gnu/bits/socket-constants.h delete mode 100644 lib/libc/include/sparcv9-linux-gnu/gnu/stubs-32.h rename lib/libc/include/x86_64-linux-gnu/{bits => finclude}/math-vector-fortran.h (100%) delete mode 100644 lib/libc/include/x86_64-linux-gnu/sys/io.h delete mode 100644 lib/libc/include/x86_64-linux-gnux32/bits/xtitypes.h rename lib/libc/include/x86_64-linux-gnux32/{bits => finclude}/math-vector-fortran.h (100%) delete mode 100644 lib/libc/include/x86_64-linux-gnux32/sys/io.h diff --git a/lib/libc/include/aarch64-linux-gnu/bits/hwcap.h b/lib/libc/include/aarch64-linux-gnu/bits/hwcap.h index bdeaa1e1d48c751b7526f2aa9022a9c1de46a441..629784d923f10be1739a787a4f7ebcc58b864536 100644 --- a/lib/libc/include/aarch64-linux-gnu/bits/hwcap.h +++ b/lib/libc/include/aarch64-linux-gnu/bits/hwcap.h @@ -50,4 +50,7 @@ #define HWCAP_USCAT (1 << 25) #define HWCAP_ILRCPC (1 << 26) #define HWCAP_FLAGM (1 << 27) -#define HWCAP_SSBS (1 << 28) \ No newline at end of file +#define HWCAP_SSBS (1 << 28) +#define HWCAP_SB (1 << 29) +#define HWCAP_PACA (1 << 30) +#define HWCAP_PACG (1UL << 31) \ No newline at end of file diff --git a/lib/libc/include/aarch64-linux-gnu/gnu/stubs-lp64.h b/lib/libc/include/aarch64-linux-gnu/gnu/stubs-lp64.h index 9a016fc113c547b20901b62c980e643203ea104a..342cde4c989c7bd3ab06cbee253345bc1e906016 100644 --- a/lib/libc/include/aarch64-linux-gnu/gnu/stubs-lp64.h +++ b/lib/libc/include/aarch64-linux-gnu/gnu/stubs-lp64.h @@ -13,15 +13,9 @@ #define __stub___compat_query_module #define __stub___compat_uselib #define __stub_chflags -#define __stub_fattach #define __stub_fchflags -#define __stub_fdetach -#define __stub_getmsg -#define __stub_getpmsg #define __stub_gtty #define __stub_lchmod -#define __stub_putmsg -#define __stub_putpmsg #define __stub_revoke #define __stub_setlogin #define __stub_sigreturn diff --git a/lib/libc/include/aarch64_be-linux-gnu/bits/hwcap.h b/lib/libc/include/aarch64_be-linux-gnu/bits/hwcap.h index bdeaa1e1d48c751b7526f2aa9022a9c1de46a441..629784d923f10be1739a787a4f7ebcc58b864536 100644 --- a/lib/libc/include/aarch64_be-linux-gnu/bits/hwcap.h +++ b/lib/libc/include/aarch64_be-linux-gnu/bits/hwcap.h @@ -50,4 +50,7 @@ #define HWCAP_USCAT (1 << 25) #define HWCAP_ILRCPC (1 << 26) #define HWCAP_FLAGM (1 << 27) -#define HWCAP_SSBS (1 << 28) \ No newline at end of file +#define HWCAP_SSBS (1 << 28) +#define HWCAP_SB (1 << 29) +#define HWCAP_PACA (1 << 30) +#define HWCAP_PACG (1UL << 31) \ No newline at end of file diff --git a/lib/libc/include/aarch64_be-linux-gnu/gnu/stubs-lp64_be.h b/lib/libc/include/aarch64_be-linux-gnu/gnu/stubs-lp64_be.h index 9a016fc113c547b20901b62c980e643203ea104a..342cde4c989c7bd3ab06cbee253345bc1e906016 100644 --- a/lib/libc/include/aarch64_be-linux-gnu/gnu/stubs-lp64_be.h +++ b/lib/libc/include/aarch64_be-linux-gnu/gnu/stubs-lp64_be.h @@ -13,15 +13,9 @@ #define __stub___compat_query_module #define __stub___compat_uselib #define __stub_chflags -#define __stub_fattach #define __stub_fchflags -#define __stub_fdetach -#define __stub_getmsg -#define __stub_getpmsg #define __stub_gtty #define __stub_lchmod -#define __stub_putmsg -#define __stub_putpmsg #define __stub_revoke #define __stub_setlogin #define __stub_sigreturn diff --git a/lib/libc/include/i386-linux-gnu/bits/xtitypes.h b/lib/libc/include/generic-glibc/bits/dirent_ext.h similarity index 58% rename from lib/libc/include/i386-linux-gnu/bits/xtitypes.h rename to lib/libc/include/generic-glibc/bits/dirent_ext.h index 1eb0c84d8f7da38decba2447f2091bcbac71ca9d..fd2a6ebfde6eb109d24bd4c3e17d08321343bc46 100644 --- a/lib/libc/include/i386-linux-gnu/bits/xtitypes.h +++ b/lib/libc/include/generic-glibc/bits/dirent_ext.h @@ -1,5 +1,5 @@ -/* bits/xtitypes.h -- Define some types used by . x86-64. - Copyright (C) 2002-2019 Free Software Foundation, Inc. +/* System-specific extensions of . Linux version. + Copyright (C) 2019 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -16,18 +16,18 @@ License along with the GNU C Library; if not, see . */ -#ifndef _STROPTS_H -# error "Never include directly; use instead." +#ifndef _DIRENT_H +# error "Never include directly; use instead." #endif -#ifndef _BITS_XTITYPES_H -#define _BITS_XTITYPES_H 1 - -#include - -/* This type is used by some structs in . */ -typedef __SLONG32_TYPE __t_scalar_t; -typedef __ULONG32_TYPE __t_uscalar_t; +__BEGIN_DECLS +#ifdef __USE_GNU +/* Read from the directory descriptor FD into LENGTH bytes at BUFFER. + Return the number of bytes read on success (0 for end of + directory), and -1 for failure. */ +extern __ssize_t getdents64 (int __fd, void *__buffer, size_t __length) + __THROW __nonnull ((2)); +#endif -#endif /* bits/xtitypes.h */ \ No newline at end of file +__END_DECLS \ No newline at end of file diff --git a/lib/libc/include/generic-glibc/bits/fcntl-linux.h b/lib/libc/include/generic-glibc/bits/fcntl-linux.h index f993e3b6f311d1ee6d6f77a7d92bd1bc980c46ef..869be9f8abfcddd94090055d682115d4f0273e3d 100644 --- a/lib/libc/include/generic-glibc/bits/fcntl-linux.h +++ b/lib/libc/include/generic-glibc/bits/fcntl-linux.h @@ -284,6 +284,8 @@ struct f_owner_ex # define F_SEAL_SHRINK 0x0002 /* Prevent file from shrinking. */ # define F_SEAL_GROW 0x0004 /* Prevent file from growing. */ # define F_SEAL_WRITE 0x0008 /* Prevent writes. */ +# define F_SEAL_FUTURE_WRITE 0x0010 /* Prevent future writes while + mapped. */ #endif #ifdef __USE_GNU diff --git a/lib/libc/include/generic-glibc/bits/in.h b/lib/libc/include/generic-glibc/bits/in.h index a33b7e7f145b12c03b704d69fb206dacc70bacfe..08757c8eab9aeec53fb892ef87ba5d08991e5a62 100644 --- a/lib/libc/include/generic-glibc/bits/in.h +++ b/lib/libc/include/generic-glibc/bits/in.h @@ -192,6 +192,7 @@ struct in_pktinfo #define IPV6_JOIN_ANYCAST 27 #define IPV6_LEAVE_ANYCAST 28 #define IPV6_MULTICAST_ALL 29 +#define IPV6_ROUTER_ALERT_ISOLATE 30 #define IPV6_IPSEC_POLICY 34 #define IPV6_XFRM_POLICY 35 #define IPV6_HDRINCL 36 diff --git a/lib/libc/include/generic-glibc/bits/xtitypes.h b/lib/libc/include/generic-glibc/bits/signal_ext.h similarity index 58% rename from lib/libc/include/generic-glibc/bits/xtitypes.h rename to lib/libc/include/generic-glibc/bits/signal_ext.h index a84ace3507b8ae72d909aa1698f918af868b8f54..1a937faf9be4822a288ce57ee64b88d7916497d1 100644 --- a/lib/libc/include/generic-glibc/bits/xtitypes.h +++ b/lib/libc/include/generic-glibc/bits/signal_ext.h @@ -1,5 +1,5 @@ -/* bits/xtitypes.h -- Define some types used by . Generic. - Copyright (C) 2002-2019 Free Software Foundation, Inc. +/* System-specific extensions of , Linux version. + Copyright (C) 2019 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -16,18 +16,16 @@ License along with the GNU C Library; if not, see . */ -#ifndef _STROPTS_H -# error "Never include directly; use instead." +#ifndef _SIGNAL_H +# error "Never include directly; use instead." #endif -#ifndef _BITS_XTITYPES_H -#define _BITS_XTITYPES_H 1 +#ifdef __USE_GNU -#include +/* Send SIGNAL to the thread TID in the thread group (process) + identified by TGID. This function behaves like kill, but also + fails with ESRCH if the specified TID does not belong to the + specified thread group. */ +extern int tgkill (__pid_t __tgid, __pid_t __tid, int __signal); -/* This type is used by some structs in . */ -typedef __SLONGWORD_TYPE __t_scalar_t; -typedef __ULONGWORD_TYPE __t_uscalar_t; - - -#endif /* bits/xtitypes.h */ \ No newline at end of file +#endif /* __USE_GNU */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-linux-gnu/bits/xtitypes.h b/lib/libc/include/generic-glibc/bits/socket-constants.h similarity index 56% rename from lib/libc/include/x86_64-linux-gnu/bits/xtitypes.h rename to lib/libc/include/generic-glibc/bits/socket-constants.h index 1eb0c84d8f7da38decba2447f2091bcbac71ca9d..b5dd49b6df2c98c965bd2f0e953da4fbeb0ca359 100644 --- a/lib/libc/include/x86_64-linux-gnu/bits/xtitypes.h +++ b/lib/libc/include/generic-glibc/bits/socket-constants.h @@ -1,5 +1,5 @@ -/* bits/xtitypes.h -- Define some types used by . x86-64. - Copyright (C) 2002-2019 Free Software Foundation, Inc. +/* Socket constants which vary among Linux architectures. + Copyright (C) 2019 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -16,18 +16,23 @@ License along with the GNU C Library; if not, see . */ -#ifndef _STROPTS_H -# error "Never include directly; use instead." +#ifndef _SYS_SOCKET_H +# error "Never include directly; use instead." #endif -#ifndef _BITS_XTITYPES_H -#define _BITS_XTITYPES_H 1 - -#include - -/* This type is used by some structs in . */ -typedef __SLONG32_TYPE __t_scalar_t; -typedef __ULONG32_TYPE __t_uscalar_t; - - -#endif /* bits/xtitypes.h */ \ No newline at end of file +#define SOL_SOCKET 1 +#define SO_ACCEPTCONN 30 +#define SO_BROADCAST 6 +#define SO_DONTROUTE 5 +#define SO_ERROR 4 +#define SO_KEEPALIVE 9 +#define SO_LINGER 13 +#define SO_OOBINLINE 10 +#define SO_RCVBUF 8 +#define SO_RCVLOWAT 18 +#define SO_RCVTIMEO 20 +#define SO_REUSEADDR 2 +#define SO_SNDBUF 7 +#define SO_SNDLOWAT 19 +#define SO_SNDTIMEO 21 +#define SO_TYPE 3 \ No newline at end of file diff --git a/lib/libc/include/generic-glibc/bits/socket.h b/lib/libc/include/generic-glibc/bits/socket.h index 75c0b750a1a03d79f601ae48dc0922ed66139df2..6702cca1406a3a3a3daef1c5bef2af2e092d55fd 100644 --- a/lib/libc/include/generic-glibc/bits/socket.h +++ b/lib/libc/include/generic-glibc/bits/socket.h @@ -349,98 +349,12 @@ struct ucred }; #endif -/* Ugly workaround for unclean kernel headers. */ -#ifndef __USE_MISC -# ifndef FIOGETOWN -# define __SYS_SOCKET_H_undef_FIOGETOWN -# endif -# ifndef FIOSETOWN -# define __SYS_SOCKET_H_undef_FIOSETOWN -# endif -# ifndef SIOCATMARK -# define __SYS_SOCKET_H_undef_SIOCATMARK -# endif -# ifndef SIOCGPGRP -# define __SYS_SOCKET_H_undef_SIOCGPGRP -# endif -# ifndef SIOCGSTAMP -# define __SYS_SOCKET_H_undef_SIOCGSTAMP -# endif -# ifndef SIOCGSTAMPNS -# define __SYS_SOCKET_H_undef_SIOCGSTAMPNS -# endif -# ifndef SIOCSPGRP -# define __SYS_SOCKET_H_undef_SIOCSPGRP -# endif -#endif -#ifndef IOCSIZE_MASK -# define __SYS_SOCKET_H_undef_IOCSIZE_MASK -#endif -#ifndef IOCSIZE_SHIFT -# define __SYS_SOCKET_H_undef_IOCSIZE_SHIFT -#endif -#ifndef IOC_IN -# define __SYS_SOCKET_H_undef_IOC_IN -#endif -#ifndef IOC_INOUT -# define __SYS_SOCKET_H_undef_IOC_INOUT -#endif -#ifndef IOC_OUT -# define __SYS_SOCKET_H_undef_IOC_OUT -#endif - -/* Get socket manipulation related informations from kernel headers. */ -#include - -#ifndef __USE_MISC -# ifdef __SYS_SOCKET_H_undef_FIOGETOWN -# undef __SYS_SOCKET_H_undef_FIOGETOWN -# undef FIOGETOWN -# endif -# ifdef __SYS_SOCKET_H_undef_FIOSETOWN -# undef __SYS_SOCKET_H_undef_FIOSETOWN -# undef FIOSETOWN -# endif -# ifdef __SYS_SOCKET_H_undef_SIOCATMARK -# undef __SYS_SOCKET_H_undef_SIOCATMARK -# undef SIOCATMARK -# endif -# ifdef __SYS_SOCKET_H_undef_SIOCGPGRP -# undef __SYS_SOCKET_H_undef_SIOCGPGRP -# undef SIOCGPGRP -# endif -# ifdef __SYS_SOCKET_H_undef_SIOCGSTAMP -# undef __SYS_SOCKET_H_undef_SIOCGSTAMP -# undef SIOCGSTAMP -# endif -# ifdef __SYS_SOCKET_H_undef_SIOCGSTAMPNS -# undef __SYS_SOCKET_H_undef_SIOCGSTAMPNS -# undef SIOCGSTAMPNS -# endif -# ifdef __SYS_SOCKET_H_undef_SIOCSPGRP -# undef __SYS_SOCKET_H_undef_SIOCSPGRP -# undef SIOCSPGRP -# endif -#endif -#ifdef __SYS_SOCKET_H_undef_IOCSIZE_MASK -# undef __SYS_SOCKET_H_undef_IOCSIZE_MASK -# undef IOCSIZE_MASK -#endif -#ifdef __SYS_SOCKET_H_undef_IOCSIZE_SHIFT -# undef __SYS_SOCKET_H_undef_IOCSIZE_SHIFT -# undef IOCSIZE_SHIFT -#endif -#ifdef __SYS_SOCKET_H_undef_IOC_IN -# undef __SYS_SOCKET_H_undef_IOC_IN -# undef IOC_IN -#endif -#ifdef __SYS_SOCKET_H_undef_IOC_INOUT -# undef __SYS_SOCKET_H_undef_IOC_INOUT -# undef IOC_INOUT -#endif -#ifdef __SYS_SOCKET_H_undef_IOC_OUT -# undef __SYS_SOCKET_H_undef_IOC_OUT -# undef IOC_OUT +#ifdef __USE_MISC +# include +# include +#else +# define SO_DEBUG 1 +# include #endif /* Structure used to manipulate the SO_LINGER option. */ diff --git a/lib/libc/include/generic-glibc/bits/statx-generic.h b/lib/libc/include/generic-glibc/bits/statx-generic.h new file mode 100644 index 0000000000000000000000000000000000000000..f2c2e208b15eaa4683575a425d568830af80ee1d --- /dev/null +++ b/lib/libc/include/generic-glibc/bits/statx-generic.h @@ -0,0 +1,60 @@ +/* Generic statx-related definitions and declarations. + Copyright (C) 2018-2019 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +/* This interface is based on in Linux. */ + +#ifndef _SYS_STAT_H +# error Never include directly, include instead. +#endif + +#include +#include + +#ifndef STATX_TYPE +# define STATX_TYPE 0x0001U +# define STATX_MODE 0x0002U +# define STATX_NLINK 0x0004U +# define STATX_UID 0x0008U +# define STATX_GID 0x0010U +# define STATX_ATIME 0x0020U +# define STATX_MTIME 0x0040U +# define STATX_CTIME 0x0080U +# define STATX_INO 0x0100U +# define STATX_SIZE 0x0200U +# define STATX_BLOCKS 0x0400U +# define STATX_BASIC_STATS 0x07ffU +# define STATX_ALL 0x0fffU +# define STATX_BTIME 0x0800U +# define STATX__RESERVED 0x80000000U + +# define STATX_ATTR_COMPRESSED 0x0004 +# define STATX_ATTR_IMMUTABLE 0x0010 +# define STATX_ATTR_APPEND 0x0020 +# define STATX_ATTR_NODUMP 0x0040 +# define STATX_ATTR_ENCRYPTED 0x0800 +# define STATX_ATTR_AUTOMOUNT 0x1000 +#endif /* !STATX_TYPE */ + +__BEGIN_DECLS + +/* Fill *BUF with information about PATH in DIRFD. */ +int statx (int __dirfd, const char *__restrict __path, int __flags, + unsigned int __mask, struct statx *__restrict __buf) + __THROW __nonnull ((2, 5)); + +__END_DECLS \ No newline at end of file diff --git a/lib/libc/include/generic-glibc/bits/statx.h b/lib/libc/include/generic-glibc/bits/statx.h index 552e8cd16beef85906fc402027a29d4c014101f0..dbfe1127fe697c3c5bc83082353ed16a92323d46 100644 --- a/lib/libc/include/generic-glibc/bits/statx.h +++ b/lib/libc/include/generic-glibc/bits/statx.h @@ -1,4 +1,4 @@ -/* statx-related definitions and declarations. +/* statx-related definitions and declarations. Linux version. Copyright (C) 2018-2019 Free Software Foundation, Inc. This file is part of the GNU C Library. @@ -19,73 +19,19 @@ /* This interface is based on in Linux. */ #ifndef _SYS_STAT_H -# error Never include directly, include instead. +# error Never include directly, include instead. #endif -struct statx_timestamp -{ - __int64_t tv_sec; - __uint32_t tv_nsec; - __int32_t __statx_timestamp_pad1[1]; -}; +/* Use the Linux kernel header if available. */ -/* Warning: The kernel may add additional fields to this struct in the - future. Only use this struct for calling the statx function, not - for storing data. (Expansion will be controlled by the mask - argument of the statx function.) */ -struct statx -{ - __uint32_t stx_mask; - __uint32_t stx_blksize; - __uint64_t stx_attributes; - __uint32_t stx_nlink; - __uint32_t stx_uid; - __uint32_t stx_gid; - __uint16_t stx_mode; - __uint16_t __statx_pad1[1]; - __uint64_t stx_ino; - __uint64_t stx_size; - __uint64_t stx_blocks; - __uint64_t stx_attributes_mask; - struct statx_timestamp stx_atime; - struct statx_timestamp stx_btime; - struct statx_timestamp stx_ctime; - struct statx_timestamp stx_mtime; - __uint32_t stx_rdev_major; - __uint32_t stx_rdev_minor; - __uint32_t stx_dev_major; - __uint32_t stx_dev_minor; - __uint64_t __statx_pad2[14]; -}; - -#define STATX_TYPE 0x0001U -#define STATX_MODE 0x0002U -#define STATX_NLINK 0x0004U -#define STATX_UID 0x0008U -#define STATX_GID 0x0010U -#define STATX_ATIME 0x0020U -#define STATX_MTIME 0x0040U -#define STATX_CTIME 0x0080U -#define STATX_INO 0x0100U -#define STATX_SIZE 0x0200U -#define STATX_BLOCKS 0x0400U -#define STATX_BASIC_STATS 0x07ffU -#define STATX_ALL 0x0fffU -#define STATX_BTIME 0x0800U -#define STATX__RESERVED 0x80000000U - -#define STATX_ATTR_COMPRESSED 0x0004 -#define STATX_ATTR_IMMUTABLE 0x0010 -#define STATX_ATTR_APPEND 0x0020 -#define STATX_ATTR_NODUMP 0x0040 -#define STATX_ATTR_ENCRYPTED 0x0800 -#define STATX_ATTR_AUTOMOUNT 0x1000 - -__BEGIN_DECLS - -/* Fill *BUF with information about PATH in DIRFD. */ -int statx (int __dirfd, const char *__restrict __path, int __flags, - unsigned int __mask, struct statx *__restrict __buf) - __THROW __nonnull ((2, 5)); +/* Use "" to work around incorrect macro expansion of the + __has_include argument (GCC PR 80005). */ +#if __glibc_has_include ("linux/stat.h") +# include "linux/stat.h" +# ifdef STATX_TYPE +# define __statx_timestamp_defined 1 +# define __statx_defined 1 +# endif +#endif -__END_DECLS \ No newline at end of file +#include \ No newline at end of file diff --git a/lib/libc/include/generic-glibc/bits/stropts.h b/lib/libc/include/generic-glibc/bits/stropts.h deleted file mode 100644 index 7248aae1c83936968a1bb7bbb71efd62bcdeb69c..0000000000000000000000000000000000000000 --- a/lib/libc/include/generic-glibc/bits/stropts.h +++ /dev/null @@ -1,230 +0,0 @@ -/* Copyright (C) 1998-2019 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - . */ - -#ifndef _STROPTS_H -# error "Never include directly; use instead." -#endif - -#ifndef _BITS_STROPTS_H -#define _BITS_STROPTS_H 1 - -#include - -/* Macros used as `request' argument to `ioctl'. */ -#define __SID ('S' << 8) - -#define I_NREAD (__SID | 1) /* Counts the number of data bytes in the data - block in the first message. */ -#define I_PUSH (__SID | 2) /* Push STREAMS module onto top of the current - STREAM, just below the STREAM head. */ -#define I_POP (__SID | 3) /* Remove STREAMS module from just below the - STREAM head. */ -#define I_LOOK (__SID | 4) /* Retrieve the name of the module just below - the STREAM head and place it in a character - string. */ -#define I_FLUSH (__SID | 5) /* Flush all input and/or output. */ -#define I_SRDOPT (__SID | 6) /* Sets the read mode. */ -#define I_GRDOPT (__SID | 7) /* Returns the current read mode setting. */ -#define I_STR (__SID | 8) /* Construct an internal STREAMS `ioctl' - message and send that message downstream. */ -#define I_SETSIG (__SID | 9) /* Inform the STREAM head that the process - wants the SIGPOLL signal issued. */ -#define I_GETSIG (__SID |10) /* Return the events for which the calling - process is currently registered to be sent - a SIGPOLL signal. */ -#define I_FIND (__SID |11) /* Compares the names of all modules currently - present in the STREAM to the name pointed to - by `arg'. */ -#define I_LINK (__SID |12) /* Connect two STREAMs. */ -#define I_UNLINK (__SID |13) /* Disconnects the two STREAMs. */ -#define I_PEEK (__SID |15) /* Allows a process to retrieve the information - in the first message on the STREAM head read - queue without taking the message off the - queue. */ -#define I_FDINSERT (__SID |16) /* Create a message from the specified - buffer(s), adds information about another - STREAM, and send the message downstream. */ -#define I_SENDFD (__SID |17) /* Requests the STREAM associated with `fildes' - to send a message, containing a file - pointer, to the STREAM head at the other end - of a STREAMS pipe. */ -#define I_RECVFD (__SID |14) /* Non-EFT definition. */ -#define I_SWROPT (__SID |19) /* Set the write mode. */ -#define I_GWROPT (__SID |20) /* Return the current write mode setting. */ -#define I_LIST (__SID |21) /* List all the module names on the STREAM, up - to and including the topmost driver name. */ -#define I_PLINK (__SID |22) /* Connect two STREAMs with a persistent - link. */ -#define I_PUNLINK (__SID |23) /* Disconnect the two STREAMs that were - connected with a persistent link. */ -#define I_FLUSHBAND (__SID |28) /* Flush only band specified. */ -#define I_CKBAND (__SID |29) /* Check if the message of a given priority - band exists on the STREAM head read - queue. */ -#define I_GETBAND (__SID |30) /* Return the priority band of the first - message on the STREAM head read queue. */ -#define I_ATMARK (__SID |31) /* See if the current message on the STREAM - head read queue is "marked" by some module - downstream. */ -#define I_SETCLTIME (__SID |32) /* Set the time the STREAM head will delay when - a STREAM is closing and there is data on - the write queues. */ -#define I_GETCLTIME (__SID |33) /* Get current value for closing timeout. */ -#define I_CANPUT (__SID |34) /* Check if a certain band is writable. */ - - -/* Used in `I_LOOK' request. */ -#define FMNAMESZ 8 /* compatibility w/UnixWare/Solaris. */ - -/* Flush options. */ -#define FLUSHR 0x01 /* Flush read queues. */ -#define FLUSHW 0x02 /* Flush write queues. */ -#define FLUSHRW 0x03 /* Flush read and write queues. */ -#ifdef __USE_GNU -# define FLUSHBAND 0x04 /* Flush only specified band. */ -#endif - -/* Possible arguments for `I_SETSIG'. */ -#define S_INPUT 0x0001 /* A message, other than a high-priority - message, has arrived. */ -#define S_HIPRI 0x0002 /* A high-priority message is present. */ -#define S_OUTPUT 0x0004 /* The write queue for normal data is no longer - full. */ -#define S_MSG 0x0008 /* A STREAMS signal message that contains the - SIGPOLL signal reaches the front of the - STREAM head read queue. */ -#define S_ERROR 0x0010 /* Notification of an error condition. */ -#define S_HANGUP 0x0020 /* Notification of a hangup. */ -#define S_RDNORM 0x0040 /* A normal message has arrived. */ -#define S_WRNORM S_OUTPUT -#define S_RDBAND 0x0080 /* A message with a non-zero priority has - arrived. */ -#define S_WRBAND 0x0100 /* The write queue for a non-zero priority - band is no longer full. */ -#define S_BANDURG 0x0200 /* When used in conjunction with S_RDBAND, - SIGURG is generated instead of SIGPOLL when - a priority message reaches the front of the - STREAM head read queue. */ - -/* Option for `I_PEEK'. */ -#define RS_HIPRI 0x01 /* Only look for high-priority messages. */ - -/* Options for `I_SRDOPT'. */ -#define RNORM 0x0000 /* Byte-STREAM mode, the default. */ -#define RMSGD 0x0001 /* Message-discard mode. */ -#define RMSGN 0x0002 /* Message-nondiscard mode. */ -#define RPROTDAT 0x0004 /* Deliver the control part of a message as - data. */ -#define RPROTDIS 0x0008 /* Discard the control part of a message, - delivering any data part. */ -#define RPROTNORM 0x0010 /* Fail `read' with EBADMSG if a message - containing a control part is at the front - of the STREAM head read queue. */ -#ifdef __USE_GNU -# define RPROTMASK 0x001C /* The RPROT bits */ -#endif - -/* Possible mode for `I_SWROPT'. */ -#define SNDZERO 0x001 /* Send a zero-length message downstream when a - `write' of 0 bytes occurs. */ -#ifdef __USE_GNU -# define SNDPIPE 0x002 /* Send SIGPIPE on write and putmsg if - sd_werror is set. */ -#endif - -/* Arguments for `I_ATMARK'. */ -#define ANYMARK 0x01 /* Check if the message is marked. */ -#define LASTMARK 0x02 /* Check if the message is the last one marked - on the queue. */ - -/* Argument for `I_UNLINK'. */ -#ifdef __USE_GNU -# define MUXID_ALL (-1) /* Unlink all STREAMs linked to the STREAM - associated with `fildes'. */ -#endif - - -/* Macros for `getmsg', `getpmsg', `putmsg' and `putpmsg'. */ -#define MSG_HIPRI 0x01 /* Send/receive high priority message. */ -#define MSG_ANY 0x02 /* Receive any message. */ -#define MSG_BAND 0x04 /* Receive message from specified band. */ - -/* Values returned by getmsg and getpmsg */ -#define MORECTL 1 /* More control information is left in - message. */ -#define MOREDATA 2 /* More data is left in message. */ - - -/* Structure used for the I_FLUSHBAND ioctl on streams. */ -struct bandinfo - { - unsigned char bi_pri; - int bi_flag; - }; - -struct strbuf - { - int maxlen; /* Maximum buffer length. */ - int len; /* Length of data. */ - char *buf; /* Pointer to buffer. */ - }; - -struct strpeek - { - struct strbuf ctlbuf; - struct strbuf databuf; - t_uscalar_t flags; /* UnixWare/Solaris compatibility. */ - }; - -struct strfdinsert - { - struct strbuf ctlbuf; - struct strbuf databuf; - t_uscalar_t flags; /* UnixWare/Solaris compatibility. */ - int fildes; - int offset; - }; - -struct strioctl - { - int ic_cmd; - int ic_timout; - int ic_len; - char *ic_dp; - }; - -struct strrecvfd - { - int fd; - uid_t uid; - gid_t gid; - char __fill[8]; /* UnixWare/Solaris compatibility */ - }; - - -struct str_mlist - { - char l_name[FMNAMESZ + 1]; - }; - -struct str_list - { - int sl_nmods; - struct str_mlist *sl_modlist; - }; - -#endif /* bits/stropts.h */ \ No newline at end of file diff --git a/lib/libc/include/generic-glibc/bits/syscall.h b/lib/libc/include/generic-glibc/bits/syscall.h index 6ac44124c14a2cea4a816d2af44ab9f6bdb31852..0fb3664008186f5318ea62a65a72011090e0a720 100644 --- a/lib/libc/include/generic-glibc/bits/syscall.h +++ b/lib/libc/include/generic-glibc/bits/syscall.h @@ -1,11 +1,11 @@ /* Generated at libc build time from syscall list. */ -/* The system call list corresponds to kernel 4.20. */ +/* The system call list corresponds to kernel 5.2. */ #ifndef _SYSCALL_H # error "Never use directly; include instead." #endif -#define __GLIBC_LINUX_VERSION_CODE 267264 +#define __GLIBC_LINUX_VERSION_CODE 328192 #ifdef __NR_FAST_atomic_update # define SYS_FAST_atomic_update __NR_FAST_atomic_update @@ -115,6 +115,10 @@ # define SYS_break __NR_break #endif +#ifdef __NR_breakpoint +# define SYS_breakpoint __NR_breakpoint +#endif + #ifdef __NR_brk # define SYS_brk __NR_brk #endif @@ -159,22 +163,42 @@ # define SYS_clock_adjtime __NR_clock_adjtime #endif +#ifdef __NR_clock_adjtime64 +# define SYS_clock_adjtime64 __NR_clock_adjtime64 +#endif + #ifdef __NR_clock_getres # define SYS_clock_getres __NR_clock_getres #endif +#ifdef __NR_clock_getres_time64 +# define SYS_clock_getres_time64 __NR_clock_getres_time64 +#endif + #ifdef __NR_clock_gettime # define SYS_clock_gettime __NR_clock_gettime #endif +#ifdef __NR_clock_gettime64 +# define SYS_clock_gettime64 __NR_clock_gettime64 +#endif + #ifdef __NR_clock_nanosleep # define SYS_clock_nanosleep __NR_clock_nanosleep #endif +#ifdef __NR_clock_nanosleep_time64 +# define SYS_clock_nanosleep_time64 __NR_clock_nanosleep_time64 +#endif + #ifdef __NR_clock_settime # define SYS_clock_settime __NR_clock_settime #endif +#ifdef __NR_clock_settime64 +# define SYS_clock_settime64 __NR_clock_settime64 +#endif + #ifdef __NR_clone # define SYS_clone __NR_clone #endif @@ -367,6 +391,10 @@ # define SYS_fork __NR_fork #endif +#ifdef __NR_fp_udfiex_crtl +# define SYS_fp_udfiex_crtl __NR_fp_udfiex_crtl +#endif + #ifdef __NR_free_hugepages # define SYS_free_hugepages __NR_free_hugepages #endif @@ -375,10 +403,26 @@ # define SYS_fremovexattr __NR_fremovexattr #endif +#ifdef __NR_fsconfig +# define SYS_fsconfig __NR_fsconfig +#endif + #ifdef __NR_fsetxattr # define SYS_fsetxattr __NR_fsetxattr #endif +#ifdef __NR_fsmount +# define SYS_fsmount __NR_fsmount +#endif + +#ifdef __NR_fsopen +# define SYS_fsopen __NR_fsopen +#endif + +#ifdef __NR_fspick +# define SYS_fspick __NR_fspick +#endif + #ifdef __NR_fstat # define SYS_fstat __NR_fstat #endif @@ -419,6 +463,10 @@ # define SYS_futex __NR_futex #endif +#ifdef __NR_futex_time64 +# define SYS_futex_time64 __NR_futex_time64 +#endif + #ifdef __NR_futimesat # define SYS_futimesat __NR_futimesat #endif @@ -439,6 +487,10 @@ # define SYS_get_thread_area __NR_get_thread_area #endif +#ifdef __NR_get_tls +# define SYS_get_tls __NR_get_tls +#endif + #ifdef __NR_getcpu # define SYS_getcpu __NR_getcpu #endif @@ -655,6 +707,10 @@ # define SYS_io_pgetevents __NR_io_pgetevents #endif +#ifdef __NR_io_pgetevents_time64 +# define SYS_io_pgetevents_time64 __NR_io_pgetevents_time64 +#endif + #ifdef __NR_io_setup # define SYS_io_setup __NR_io_setup #endif @@ -663,6 +719,18 @@ # define SYS_io_submit __NR_io_submit #endif +#ifdef __NR_io_uring_enter +# define SYS_io_uring_enter __NR_io_uring_enter +#endif + +#ifdef __NR_io_uring_register +# define SYS_io_uring_register __NR_io_uring_register +#endif + +#ifdef __NR_io_uring_setup +# define SYS_io_uring_setup __NR_io_uring_setup +#endif + #ifdef __NR_ioctl # define SYS_ioctl __NR_ioctl #endif @@ -847,6 +915,10 @@ # define SYS_mount __NR_mount #endif +#ifdef __NR_move_mount +# define SYS_move_mount __NR_move_mount +#endif + #ifdef __NR_move_pages # define SYS_move_pages __NR_move_pages #endif @@ -875,10 +947,18 @@ # define SYS_mq_timedreceive __NR_mq_timedreceive #endif +#ifdef __NR_mq_timedreceive_time64 +# define SYS_mq_timedreceive_time64 __NR_mq_timedreceive_time64 +#endif + #ifdef __NR_mq_timedsend # define SYS_mq_timedsend __NR_mq_timedsend #endif +#ifdef __NR_mq_timedsend_time64 +# define SYS_mq_timedsend_time64 __NR_mq_timedsend_time64 +#endif + #ifdef __NR_mq_unlink # define SYS_mq_unlink __NR_mq_unlink #endif @@ -951,6 +1031,10 @@ # define SYS_old_adjtimex __NR_old_adjtimex #endif +#ifdef __NR_old_getpagesize +# define SYS_old_getpagesize __NR_old_getpagesize +#endif + #ifdef __NR_oldfstat # define SYS_oldfstat __NR_oldfstat #endif @@ -983,6 +1067,10 @@ # define SYS_open_by_handle_at __NR_open_by_handle_at #endif +#ifdef __NR_open_tree +# define SYS_open_tree __NR_open_tree +#endif + #ifdef __NR_openat # define SYS_openat __NR_openat #endif @@ -1459,6 +1547,10 @@ # define SYS_personality __NR_personality #endif +#ifdef __NR_pidfd_send_signal +# define SYS_pidfd_send_signal __NR_pidfd_send_signal +#endif + #ifdef __NR_pipe # define SYS_pipe __NR_pipe #endif @@ -1491,6 +1583,10 @@ # define SYS_ppoll __NR_ppoll #endif +#ifdef __NR_ppoll_time64 +# define SYS_ppoll_time64 __NR_ppoll_time64 +#endif + #ifdef __NR_prctl # define SYS_prctl __NR_prctl #endif @@ -1531,6 +1627,10 @@ # define SYS_pselect6 __NR_pselect6 #endif +#ifdef __NR_pselect6_time64 +# define SYS_pselect6_time64 __NR_pselect6_time64 +#endif + #ifdef __NR_ptrace # define SYS_ptrace __NR_ptrace #endif @@ -1599,6 +1699,10 @@ # define SYS_recvmmsg __NR_recvmmsg #endif +#ifdef __NR_recvmmsg_time64 +# define SYS_recvmmsg_time64 __NR_recvmmsg_time64 +#endif + #ifdef __NR_recvmsg # define SYS_recvmsg __NR_recvmsg #endif @@ -1671,6 +1775,10 @@ # define SYS_rt_sigtimedwait __NR_rt_sigtimedwait #endif +#ifdef __NR_rt_sigtimedwait_time64 +# define SYS_rt_sigtimedwait_time64 __NR_rt_sigtimedwait_time64 +#endif + #ifdef __NR_rt_tgsigqueueinfo # define SYS_rt_tgsigqueueinfo __NR_rt_tgsigqueueinfo #endif @@ -1731,6 +1839,10 @@ # define SYS_sched_rr_get_interval __NR_sched_rr_get_interval #endif +#ifdef __NR_sched_rr_get_interval_time64 +# define SYS_sched_rr_get_interval_time64 __NR_sched_rr_get_interval_time64 +#endif + #ifdef __NR_sched_set_affinity # define SYS_sched_set_affinity __NR_sched_set_affinity #endif @@ -1783,6 +1895,10 @@ # define SYS_semtimedop __NR_semtimedop #endif +#ifdef __NR_semtimedop_time64 +# define SYS_semtimedop_time64 __NR_semtimedop_time64 +#endif + #ifdef __NR_send # define SYS_send __NR_send #endif @@ -1823,6 +1939,10 @@ # define SYS_set_tid_address __NR_set_tid_address #endif +#ifdef __NR_set_tls +# define SYS_set_tls __NR_set_tls +#endif + #ifdef __NR_setdomainname # define SYS_setdomainname __NR_setdomainname #endif @@ -2171,10 +2291,18 @@ # define SYS_timer_gettime __NR_timer_gettime #endif +#ifdef __NR_timer_gettime64 +# define SYS_timer_gettime64 __NR_timer_gettime64 +#endif + #ifdef __NR_timer_settime # define SYS_timer_settime __NR_timer_settime #endif +#ifdef __NR_timer_settime64 +# define SYS_timer_settime64 __NR_timer_settime64 +#endif + #ifdef __NR_timerfd # define SYS_timerfd __NR_timerfd #endif @@ -2187,10 +2315,18 @@ # define SYS_timerfd_gettime __NR_timerfd_gettime #endif +#ifdef __NR_timerfd_gettime64 +# define SYS_timerfd_gettime64 __NR_timerfd_gettime64 +#endif + #ifdef __NR_timerfd_settime # define SYS_timerfd_settime __NR_timerfd_settime #endif +#ifdef __NR_timerfd_settime64 +# define SYS_timerfd_settime64 __NR_timerfd_settime64 +#endif + #ifdef __NR_times # define SYS_times __NR_times #endif @@ -2211,6 +2347,10 @@ # define SYS_tuxcall __NR_tuxcall #endif +#ifdef __NR_udftrap +# define SYS_udftrap __NR_udftrap +#endif + #ifdef __NR_ugetrlimit # define SYS_ugetrlimit __NR_ugetrlimit #endif @@ -2255,6 +2395,14 @@ # define SYS_userfaultfd __NR_userfaultfd #endif +#ifdef __NR_usr26 +# define SYS_usr26 __NR_usr26 +#endif + +#ifdef __NR_usr32 +# define SYS_usr32 __NR_usr32 +#endif + #ifdef __NR_ustat # define SYS_ustat __NR_ustat #endif @@ -2267,6 +2415,10 @@ # define SYS_utimensat __NR_utimensat #endif +#ifdef __NR_utimensat_time64 +# define SYS_utimensat_time64 __NR_utimensat_time64 +#endif + #ifdef __NR_utimes # define SYS_utimes __NR_utimes #endif diff --git a/lib/libc/include/generic-glibc/bits/types.h b/lib/libc/include/generic-glibc/bits/types.h index 124eb5cb585ac2440ea0caf4ac331bb1ad40dfe9..3548ed5a4acad1a8d16ecdd8bff7f68227785e4f 100644 --- a/lib/libc/include/generic-glibc/bits/types.h +++ b/lib/libc/include/generic-glibc/bits/types.h @@ -87,7 +87,7 @@ __extension__ typedef unsigned long long int __uintmax_t; 32 -- "natural" 32-bit type (always int) 64 -- "natural" 64-bit type (long or long long) LONG32 -- 32-bit type, traditionally long - QUAD -- 64-bit type, always long long + QUAD -- 64-bit type, traditionally long long WORD -- natural type of __WORDSIZE bits (int or long) LONGWORD -- type of __WORDSIZE bits, traditionally long @@ -113,14 +113,14 @@ __extension__ typedef unsigned long long int __uintmax_t; #define __SLONGWORD_TYPE long int #define __ULONGWORD_TYPE unsigned long int #if __WORDSIZE == 32 -# define __SQUAD_TYPE __quad_t -# define __UQUAD_TYPE __u_quad_t +# define __SQUAD_TYPE __int64_t +# define __UQUAD_TYPE __uint64_t # define __SWORD_TYPE int # define __UWORD_TYPE unsigned int # define __SLONG32_TYPE long int # define __ULONG32_TYPE unsigned long int -# define __S64_TYPE __quad_t -# define __U64_TYPE __u_quad_t +# define __S64_TYPE __int64_t +# define __U64_TYPE __uint64_t /* We want __extension__ before typedef's that use nonstandard base types such as `long long' in C89 mode. */ # define __STD_TYPE __extension__ typedef @@ -213,10 +213,13 @@ __STD_TYPE __U32_TYPE __socklen_t; It is not currently necessary for this to be machine-specific. */ typedef int __sig_atomic_t; -#if __TIMESIZE == 64 +/* Seconds since the Epoch, visible to user code when time_t is too + narrow only for consistency with the old way of widening too-narrow + types. User code should never use __time64_t. */ +#if __TIMESIZE == 64 && defined __LIBC # define __time64_t __time_t -#else -__STD_TYPE __TIME64_T_TYPE __time64_t; /* Seconds since the Epoch. */ +#elif __TIMESIZE != 64 +__STD_TYPE __TIME64_T_TYPE __time64_t; #endif #undef __STD_TYPE diff --git a/lib/libc/include/generic-glibc/bits/types/struct_statx.h b/lib/libc/include/generic-glibc/bits/types/struct_statx.h new file mode 100644 index 0000000000000000000000000000000000000000..52ae740099641daba56251c7b027de585a7168e5 --- /dev/null +++ b/lib/libc/include/generic-glibc/bits/types/struct_statx.h @@ -0,0 +1,55 @@ +/* Definition of the generic version of struct statx. + Copyright (C) 2018-2019 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#ifndef _SYS_STAT_H +# error Never include directly, include instead. +#endif + +#ifndef __statx_defined +#define __statx_defined 1 + +/* Warning: The kernel may add additional fields to this struct in the + future. Only use this struct for calling the statx function, not + for storing data. (Expansion will be controlled by the mask + argument of the statx function.) */ +struct statx +{ + __uint32_t stx_mask; + __uint32_t stx_blksize; + __uint64_t stx_attributes; + __uint32_t stx_nlink; + __uint32_t stx_uid; + __uint32_t stx_gid; + __uint16_t stx_mode; + __uint16_t __statx_pad1[1]; + __uint64_t stx_ino; + __uint64_t stx_size; + __uint64_t stx_blocks; + __uint64_t stx_attributes_mask; + struct statx_timestamp stx_atime; + struct statx_timestamp stx_btime; + struct statx_timestamp stx_ctime; + struct statx_timestamp stx_mtime; + __uint32_t stx_rdev_major; + __uint32_t stx_rdev_minor; + __uint32_t stx_dev_major; + __uint32_t stx_dev_minor; + __uint64_t __statx_pad2[14]; +}; + +#endif /* __statx_defined */ \ No newline at end of file diff --git a/lib/libc/include/s390x-linux-gnu/bits/xtitypes.h b/lib/libc/include/generic-glibc/bits/types/struct_statx_timestamp.h similarity index 61% rename from lib/libc/include/s390x-linux-gnu/bits/xtitypes.h rename to lib/libc/include/generic-glibc/bits/types/struct_statx_timestamp.h index 5a67a56a51085be057881fd7bbde76345d566df4..786c2b5f9bbbfb910ab481f8a2247ddffc0d2b71 100644 --- a/lib/libc/include/s390x-linux-gnu/bits/xtitypes.h +++ b/lib/libc/include/generic-glibc/bits/types/struct_statx_timestamp.h @@ -1,5 +1,5 @@ -/* bits/xtitypes.h -- Define some types used by . S390/S390x - Copyright (C) 2002-2019 Free Software Foundation, Inc. +/* Definition of the generic version of struct statx_timestamp. + Copyright (C) 2018-2019 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -16,18 +16,18 @@ License along with the GNU C Library; if not, see . */ -#ifndef _STROPTS_H -# error "Never include directly; use instead." +#ifndef _SYS_STAT_H +# error Never include directly, include instead. #endif -#ifndef _BITS_XTITYPES_H -#define _BITS_XTITYPES_H 1 +#ifndef __statx_timestamp_defined +#define __statx_timestamp_defined 1 -#include +struct statx_timestamp +{ + __int64_t tv_sec; + __uint32_t tv_nsec; + __int32_t __statx_timestamp_pad1[1]; +}; -/* This type is used by some structs in . */ -typedef __S32_TYPE __t_scalar_t; -typedef __U32_TYPE __t_uscalar_t; - - -#endif /* bits/xtitypes.h */ \ No newline at end of file +#endif /* __statx_timestamp_defined */ \ No newline at end of file diff --git a/lib/libc/include/generic-glibc/dirent.h b/lib/libc/include/generic-glibc/dirent.h index ae3518630e81335c6b9152e953406bc335e15775..a74737d55c17afe5d6797ddddc22fb5335a02802 100644 --- a/lib/libc/include/generic-glibc/dirent.h +++ b/lib/libc/include/generic-glibc/dirent.h @@ -401,4 +401,6 @@ extern int versionsort64 (const struct dirent64 **__e1, __END_DECLS +#include + #endif /* dirent.h */ \ No newline at end of file diff --git a/lib/libc/include/generic-glibc/dlfcn.h b/lib/libc/include/generic-glibc/dlfcn.h index ae3e77394177679c54808d07c31af71d085ebe45..8fb19d4cb38e99dea1aa8ace5f28a657b5743dd5 100644 --- a/lib/libc/include/generic-glibc/dlfcn.h +++ b/lib/libc/include/generic-glibc/dlfcn.h @@ -180,7 +180,19 @@ typedef struct { size_t dls_size; /* Size in bytes of the whole buffer. */ unsigned int dls_cnt; /* Number of elements in `dls_serpath'. */ +# if __GNUC_PREREQ (3, 0) + /* The zero-length array avoids an unwanted array subscript check by + the compiler, while the surrounding anonymous union preserves the + historic size of the type. At the time of writing, GNU C does + not support structs with flexible array members in unions. */ + __extension__ union + { + Dl_serpath dls_serpath[0]; /* Actually longer, dls_cnt elements. */ + Dl_serpath __dls_serpath_pad[1]; + }; +# else Dl_serpath dls_serpath[1]; /* Actually longer, dls_cnt elements. */ +# endif } Dl_serinfo; #endif /* __USE_GNU */ diff --git a/lib/libc/include/generic-glibc/elf.h b/lib/libc/include/generic-glibc/elf.h index 6ad285589607d3f46b58dc242c2222fa1e7c3600..70a52f4318bb8a13e7002cdc38f39715138449f8 100644 --- a/lib/libc/include/generic-glibc/elf.h +++ b/lib/libc/include/generic-glibc/elf.h @@ -360,7 +360,7 @@ typedef struct #define EM_RISCV 243 /* RISC-V */ #define EM_BPF 247 /* Linux BPF -- in-kernel virtual machine */ -#define EM_CSKY 252 /* C_SKY */ +#define EM_CSKY 252 /* C-SKY */ #define EM_NUM 253 @@ -809,9 +809,16 @@ typedef struct #define NT_ARM_SYSTEM_CALL 0x404 /* ARM system call number */ #define NT_ARM_SVE 0x405 /* ARM Scalable Vector Extension registers */ +#define NT_ARM_PAC_MASK 0x406 /* ARM pointer authentication + code masks. */ +#define NT_ARM_PACA_KEYS 0x407 /* ARM pointer authentication + address keys. */ +#define NT_ARM_PACG_KEYS 0x408 /* ARM pointer authentication + generic key. */ #define NT_VMCOREDD 0x700 /* Vmcore Device Dump Note. */ #define NT_MIPS_DSP 0x800 /* MIPS DSP ASE registers. */ #define NT_MIPS_FP_MODE 0x801 /* MIPS floating-point mode. */ +#define NT_MIPS_MSA 0x802 /* MIPS SIMD registers. */ /* Legal values for the note segment descriptor types for object files. */ @@ -987,6 +994,9 @@ typedef struct #define DF_1_SINGLETON 0x02000000 /* Singleton symbols are used. */ #define DF_1_STUB 0x04000000 #define DF_1_PIE 0x08000000 +#define DF_1_KMOD 0x10000000 +#define DF_1_WEAKFILTER 0x20000000 +#define DF_1_NOCOMMON 0x40000000 /* Flags for the feature selection in DT_FEATURE_1. */ #define DTF_1_PARINIT 0x00000001 @@ -2854,6 +2864,13 @@ enum #define R_AARCH64_TLSDESC 1031 /* TLS Descriptor. */ #define R_AARCH64_IRELATIVE 1032 /* STT_GNU_IFUNC relocation. */ +/* AArch64 specific values for the Dyn d_tag field. */ +#define DT_AARCH64_VARIANT_PCS (DT_LOPROC + 5) +#define DT_AARCH64_NUM 6 + +/* AArch64 specific values for the st_other field. */ +#define STO_AARCH64_VARIANT_PCS 0x80 + /* ARM relocs. */ #define R_ARM_NONE 0 /* No reloc */ @@ -3022,7 +3039,7 @@ enum /* Keep this the last entry. */ #define R_ARM_NUM 256 -/* csky */ +/* C-SKY */ #define R_CKCORE_NONE 0 /* no reloc */ #define R_CKCORE_ADDR32 1 /* direct 32 bit (S + A) */ #define R_CKCORE_PCRELIMM8BY4 2 /* disp ((S + A - P) >> 2) & 0xff */ @@ -3086,6 +3103,17 @@ enum #define R_CKCORE_TLS_DTPOFF32 57 #define R_CKCORE_TLS_TPOFF32 58 +/* C-SKY elf header definition. */ +#define EF_CSKY_ABIMASK 0XF0000000 +#define EF_CSKY_OTHER 0X0FFF0000 +#define EF_CSKY_PROCESSOR 0X0000FFFF + +#define EF_CSKY_ABIV1 0X10000000 +#define EF_CSKY_ABIV2 0X20000000 + +/* C-SKY attributes section. */ +#define SHT_CSKY_ATTRIBUTES (SHT_LOPROC + 1) + /* IA-64 specific declarations. */ /* Processor specific flags for the Ehdr e_flags field. */ diff --git a/lib/libc/include/generic-glibc/features.h b/lib/libc/include/generic-glibc/features.h index 0a952454efbeb8136fbde4c0219bbfd19e55d438..b95876b7329b1aa0ed68dee22d212451b15d1d21 100644 --- a/lib/libc/include/generic-glibc/features.h +++ b/lib/libc/include/generic-glibc/features.h @@ -439,7 +439,7 @@ /* Major and minor version number of the GNU C library package. Use these macros to test for features in specific releases. */ #define __GLIBC__ 2 -#define __GLIBC_MINOR__ 29 +#define __GLIBC_MINOR__ 30 #define __GLIBC_PREREQ(maj, min) \ ((__GLIBC__ << 16) + __GLIBC_MINOR__ >= ((maj) << 16) + (min)) diff --git a/lib/libc/include/generic-glibc/bits/math-vector-fortran.h b/lib/libc/include/generic-glibc/finclude/math-vector-fortran.h similarity index 100% rename from lib/libc/include/generic-glibc/bits/math-vector-fortran.h rename to lib/libc/include/generic-glibc/finclude/math-vector-fortran.h diff --git a/lib/libc/include/generic-glibc/gconv.h b/lib/libc/include/generic-glibc/gconv.h index 700ee97ee949adac149af3000c1dcc85ded50ee5..d5500cf7cadfddb8ba4c2509e7702750053d604e 100644 --- a/lib/libc/include/generic-glibc/gconv.h +++ b/lib/libc/include/generic-glibc/gconv.h @@ -86,6 +86,8 @@ struct __gconv_step struct __gconv_loaded_object *__shlib_handle; const char *__modname; + /* For internal use by glibc. (Accesses to this member must occur + when the internal __gconv_lock mutex is acquired). */ int __counter; char *__from_name; @@ -142,13 +144,4 @@ typedef struct __gconv_info __extension__ struct __gconv_step_data __data[0]; } *__gconv_t; -/* Transliteration using the locale's data. */ -extern int __gconv_transliterate (struct __gconv_step *step, - struct __gconv_step_data *step_data, - const unsigned char *inbufstart, - const unsigned char **inbufp, - const unsigned char *inbufend, - unsigned char **outbufstart, - size_t *irreversible); - #endif /* gconv.h */ \ No newline at end of file diff --git a/lib/libc/include/generic-glibc/gnu/stubs-32.h b/lib/libc/include/generic-glibc/gnu/stubs-32.h index f5b3f7db153abd27b767b3c12f5b20f849ae1566..12c0d956e888c32e986e3c565258f46fd89d16d5 100644 --- a/lib/libc/include/generic-glibc/gnu/stubs-32.h +++ b/lib/libc/include/generic-glibc/gnu/stubs-32.h @@ -8,9 +8,7 @@ #endif #define __stub_chflags -#define __stub_fattach #define __stub_fchflags -#define __stub_fdetach #define __stub_gtty #define __stub_lchmod #define __stub_revoke diff --git a/lib/libc/include/s390x-linux-gnu/gnu/stubs-64.h b/lib/libc/include/generic-glibc/gnu/stubs-64.h similarity index 77% rename from lib/libc/include/s390x-linux-gnu/gnu/stubs-64.h rename to lib/libc/include/generic-glibc/gnu/stubs-64.h index b7ab3fcab453fa39046c1704fb94738b317bbcdb..12c0d956e888c32e986e3c565258f46fd89d16d5 100644 --- a/lib/libc/include/s390x-linux-gnu/gnu/stubs-64.h +++ b/lib/libc/include/generic-glibc/gnu/stubs-64.h @@ -8,15 +8,9 @@ #endif #define __stub_chflags -#define __stub_fattach #define __stub_fchflags -#define __stub_fdetach -#define __stub_getmsg #define __stub_gtty #define __stub_lchmod -#define __stub_pkey_alloc -#define __stub_pkey_free -#define __stub_putmsg #define __stub_revoke #define __stub_setlogin #define __stub_sigreturn diff --git a/lib/libc/include/generic-glibc/gnu/stubs-hard.h b/lib/libc/include/generic-glibc/gnu/stubs-hard.h index 8fa59209a2d8498393ec5e22841bc95bd52bebe1..add0d4871d222fa48b5e65acd31f3fb407701eed 100644 --- a/lib/libc/include/generic-glibc/gnu/stubs-hard.h +++ b/lib/libc/include/generic-glibc/gnu/stubs-hard.h @@ -11,15 +11,9 @@ #define __stub___compat_get_kernel_syms #define __stub___compat_query_module #define __stub_chflags -#define __stub_fattach #define __stub_fchflags -#define __stub_fdetach -#define __stub_getmsg -#define __stub_getpmsg #define __stub_gtty #define __stub_lchmod -#define __stub_putmsg -#define __stub_putpmsg #define __stub_revoke #define __stub_setlogin #define __stub_sigreturn diff --git a/lib/libc/include/generic-glibc/gnu/stubs-n32_hard.h b/lib/libc/include/generic-glibc/gnu/stubs-n32_hard.h index a09b281b5e9d862a2239b29f0703cf4ea785ec20..d4c69865ed693a09b564350de79484f0bead9801 100644 --- a/lib/libc/include/generic-glibc/gnu/stubs-n32_hard.h +++ b/lib/libc/include/generic-glibc/gnu/stubs-n32_hard.h @@ -10,9 +10,7 @@ #define __stub___compat_bdflush #define __stub___compat_uselib #define __stub_chflags -#define __stub_fattach #define __stub_fchflags -#define __stub_fdetach #define __stub_gtty #define __stub_lchmod #define __stub_revoke diff --git a/lib/libc/include/generic-glibc/gnu/stubs-n64_hard.h b/lib/libc/include/generic-glibc/gnu/stubs-n64_hard.h index a09b281b5e9d862a2239b29f0703cf4ea785ec20..d4c69865ed693a09b564350de79484f0bead9801 100644 --- a/lib/libc/include/generic-glibc/gnu/stubs-n64_hard.h +++ b/lib/libc/include/generic-glibc/gnu/stubs-n64_hard.h @@ -10,9 +10,7 @@ #define __stub___compat_bdflush #define __stub___compat_uselib #define __stub_chflags -#define __stub_fattach #define __stub_fchflags -#define __stub_fdetach #define __stub_gtty #define __stub_lchmod #define __stub_revoke diff --git a/lib/libc/include/generic-glibc/gnu/stubs-o32_hard.h b/lib/libc/include/generic-glibc/gnu/stubs-o32_hard.h index f5b3f7db153abd27b767b3c12f5b20f849ae1566..12c0d956e888c32e986e3c565258f46fd89d16d5 100644 --- a/lib/libc/include/generic-glibc/gnu/stubs-o32_hard.h +++ b/lib/libc/include/generic-glibc/gnu/stubs-o32_hard.h @@ -8,9 +8,7 @@ #endif #define __stub_chflags -#define __stub_fattach #define __stub_fchflags -#define __stub_fdetach #define __stub_gtty #define __stub_lchmod #define __stub_revoke diff --git a/lib/libc/include/generic-glibc/gnu/stubs-soft.h b/lib/libc/include/generic-glibc/gnu/stubs-soft.h index 8fa59209a2d8498393ec5e22841bc95bd52bebe1..add0d4871d222fa48b5e65acd31f3fb407701eed 100644 --- a/lib/libc/include/generic-glibc/gnu/stubs-soft.h +++ b/lib/libc/include/generic-glibc/gnu/stubs-soft.h @@ -11,15 +11,9 @@ #define __stub___compat_get_kernel_syms #define __stub___compat_query_module #define __stub_chflags -#define __stub_fattach #define __stub_fchflags -#define __stub_fdetach -#define __stub_getmsg -#define __stub_getpmsg #define __stub_gtty #define __stub_lchmod -#define __stub_putmsg -#define __stub_putpmsg #define __stub_revoke #define __stub_setlogin #define __stub_sigreturn diff --git a/lib/libc/include/generic-glibc/malloc.h b/lib/libc/include/generic-glibc/malloc.h index 79b8e4aded403ab980b3f9e819c3d81f5b4f7a9f..684e19581d79ded377ba32be267faddd7ba3eb30 100644 --- a/lib/libc/include/generic-glibc/malloc.h +++ b/lib/libc/include/generic-glibc/malloc.h @@ -35,11 +35,12 @@ __BEGIN_DECLS /* Allocate SIZE bytes of memory. */ -extern void *malloc (size_t __size) __THROW __attribute_malloc__ __wur; +extern void *malloc (size_t __size) __THROW __attribute_malloc__ + __attribute_alloc_size__ ((1)) __wur; /* Allocate NMEMB elements of SIZE bytes each, all initialized to 0. */ extern void *calloc (size_t __nmemb, size_t __size) -__THROW __attribute_malloc__ __wur; +__THROW __attribute_malloc__ __attribute_alloc_size__ ((1, 2)) __wur; /* Re-allocate the previously allocated block in __ptr, making the new block SIZE bytes long. */ @@ -47,7 +48,7 @@ __THROW __attribute_malloc__ __wur; the same pointer that was passed to it, aliasing needs to be allowed between objects pointed by the old and new pointers. */ extern void *realloc (void *__ptr, size_t __size) -__THROW __attribute_warn_unused_result__; +__THROW __attribute_warn_unused_result__ __attribute_alloc_size__ ((2)); /* Re-allocate the previously allocated block in PTR, making the new block large enough for NMEMB elements of SIZE bytes each. */ @@ -55,21 +56,23 @@ __THROW __attribute_warn_unused_result__; the same pointer that was passed to it, aliasing needs to be allowed between objects pointed by the old and new pointers. */ extern void *reallocarray (void *__ptr, size_t __nmemb, size_t __size) -__THROW __attribute_warn_unused_result__; +__THROW __attribute_warn_unused_result__ __attribute_alloc_size__ ((2, 3)); /* Free a block allocated by `malloc', `realloc' or `calloc'. */ extern void free (void *__ptr) __THROW; /* Allocate SIZE bytes allocated to ALIGNMENT bytes. */ extern void *memalign (size_t __alignment, size_t __size) -__THROW __attribute_malloc__ __wur; +__THROW __attribute_malloc__ __attribute_alloc_size__ ((2)) __wur; /* Allocate SIZE bytes on a page boundary. */ -extern void *valloc (size_t __size) __THROW __attribute_malloc__ __wur; +extern void *valloc (size_t __size) __THROW __attribute_malloc__ + __attribute_alloc_size__ ((1)) __wur; /* Equivalent to valloc(minimum-page-that-holds(n)), that is, round up __size to nearest pagesize. */ -extern void *pvalloc (size_t __size) __THROW __attribute_malloc__ __wur; +extern void *pvalloc (size_t __size) __THROW __attribute_malloc__ + __attribute_alloc_size__ ((1)) __wur; /* Underlying allocation function; successive calls should return contiguous pieces of memory. */ @@ -156,9 +159,6 @@ extern void *(*__MALLOC_HOOK_VOLATILE __memalign_hook)(size_t __alignment, __MALLOC_DEPRECATED; extern void (*__MALLOC_HOOK_VOLATILE __after_morecore_hook) (void); -/* Activate a standard set of debugging hooks. */ -extern void __malloc_check_init (void) __THROW __MALLOC_DEPRECATED; - __END_DECLS #endif /* malloc.h */ \ No newline at end of file diff --git a/lib/libc/include/generic-glibc/math.h b/lib/libc/include/generic-glibc/math.h index 4a9cc395f8aeae014d27769236f197d3395556ac..a4b822ece8f4ad9257fbc2797b0b4c2691218867 100644 --- a/lib/libc/include/generic-glibc/math.h +++ b/lib/libc/include/generic-glibc/math.h @@ -874,7 +874,8 @@ enum the __SUPPORT_SNAN__ check may be skipped for those versions. */ /* Return number of classification appropriate for X. */ -# if __GNUC_PREREQ (4,4) && !defined __SUPPORT_SNAN__ \ +# if ((__GNUC_PREREQ (4,4) && !defined __SUPPORT_SNAN__) \ + || __glibc_clang_prereq (2,8)) \ && (!defined __OPTIMIZE_SIZE__ || defined __cplusplus) /* The check for __cplusplus allows the use of the builtin, even when optimization for size is on. This is provided for @@ -889,7 +890,7 @@ enum # endif /* Return nonzero value if sign of X is negative. */ -# if __GNUC_PREREQ (6,0) +# if __GNUC_PREREQ (6,0) || __glibc_clang_prereq (3,3) # define signbit(x) __builtin_signbit (x) # elif defined __cplusplus /* In C++ mode, __MATH_TG cannot be used, because it relies on @@ -907,14 +908,16 @@ enum # endif /* Return nonzero value if X is not +-Inf or NaN. */ -# if __GNUC_PREREQ (4,4) && !defined __SUPPORT_SNAN__ +# if (__GNUC_PREREQ (4,4) && !defined __SUPPORT_SNAN__) \ + || __glibc_clang_prereq (2,8) # define isfinite(x) __builtin_isfinite (x) # else # define isfinite(x) __MATH_TG ((x), __finite, (x)) # endif /* Return nonzero value if X is neither zero, subnormal, Inf, nor NaN. */ -# if __GNUC_PREREQ (4,4) && !defined __SUPPORT_SNAN__ +# if (__GNUC_PREREQ (4,4) && !defined __SUPPORT_SNAN__) \ + || __glibc_clang_prereq (2,8) # define isnormal(x) __builtin_isnormal (x) # else # define isnormal(x) (fpclassify (x) == FP_NORMAL) @@ -922,7 +925,8 @@ enum /* Return nonzero value if X is a NaN. We could use `fpclassify' but we already have this functions `__isnan' and it is faster. */ -# if __GNUC_PREREQ (4,4) && !defined __SUPPORT_SNAN__ +# if (__GNUC_PREREQ (4,4) && !defined __SUPPORT_SNAN__) \ + || __glibc_clang_prereq (2,8) # define isnan(x) __builtin_isnan (x) # else # define isnan(x) __MATH_TG ((x), __isnan, (x)) @@ -939,7 +943,8 @@ enum # define isinf(x) \ (__builtin_types_compatible_p (__typeof (x), _Float128) \ ? __isinff128 (x) : __builtin_isinf_sign (x)) -# elif __GNUC_PREREQ (4,4) && !defined __SUPPORT_SNAN__ +# elif (__GNUC_PREREQ (4,4) && !defined __SUPPORT_SNAN__) \ + || __glibc_clang_prereq (3,7) # define isinf(x) __builtin_isinf_sign (x) # else # define isinf(x) __MATH_TG ((x), __isinf, (x)) diff --git a/lib/libc/include/generic-glibc/netinet/igmp.h b/lib/libc/include/generic-glibc/netinet/igmp.h index f4052af414e1ac5c8befb5b320137124fbe1c0a7..1502d9ab036ca2eb45ee486c01f5f35269994b49 100644 --- a/lib/libc/include/generic-glibc/netinet/igmp.h +++ b/lib/libc/include/generic-glibc/netinet/igmp.h @@ -86,6 +86,7 @@ struct igmp { #define IGMP_MTRACE_RESP 0x1e /* traceroute resp.(to sender)*/ #define IGMP_MTRACE 0x1f /* mcast traceroute messages */ +#define IGMP_MRDISC_ADV 0x30 /* From RFC4286. */ #define IGMP_MAX_HOST_REPORT_DELAY 10 /* max delay for response to */ /* query (in seconds) according */ diff --git a/lib/libc/include/generic-glibc/netinet/in.h b/lib/libc/include/generic-glibc/netinet/in.h index 8d0a0e2dcbecae9ae1cbe0be290935060cac5570..d02bbd5cafcfac8b306f1df7271687c0a03e3c67 100644 --- a/lib/libc/include/generic-glibc/netinet/in.h +++ b/lib/libc/include/generic-glibc/netinet/in.h @@ -204,6 +204,7 @@ enum #define INADDR_UNSPEC_GROUP ((in_addr_t) 0xe0000000) /* 224.0.0.0 */ #define INADDR_ALLHOSTS_GROUP ((in_addr_t) 0xe0000001) /* 224.0.0.1 */ #define INADDR_ALLRTRS_GROUP ((in_addr_t) 0xe0000002) /* 224.0.0.2 */ +#define INADDR_ALLSNOOPERS_GROUP ((in_addr_t) 0xe000006a) /* 224.0.0.106 */ #define INADDR_MAX_LOCAL_GROUP ((in_addr_t) 0xe00000ff) /* 224.0.0.255 */ #if !__USE_KERNEL_IPV6_DEFS diff --git a/lib/libc/include/generic-glibc/netinet/udp.h b/lib/libc/include/generic-glibc/netinet/udp.h index 409f88b2cfe6c2b14cc5686f9b54f3af12027e2c..c2c87b3201d5227f089f838422dfa5d21c0ed828 100644 --- a/lib/libc/include/generic-glibc/netinet/udp.h +++ b/lib/libc/include/generic-glibc/netinet/udp.h @@ -82,6 +82,7 @@ struct udphdr #define UDP_NO_CHECK6_RX 102 /* Disable accepting checksum for UDP over IPv6. */ #define UDP_SEGMENT 103 /* Set GSO segmentation size. */ +#define UDP_GRO 104 /* This socket can receive UDP GRO packets. */ /* UDP encapsulation types */ #define UDP_ENCAP_ESPINUDP_NON_IKE 1 /* draft-ietf-ipsec-nat-t-ike-00/01 */ diff --git a/lib/libc/include/generic-glibc/pthread.h b/lib/libc/include/generic-glibc/pthread.h index 0edb831a05093019c2439a02e6a66dad08170df6..2a93e215c42ffdb48d830068d55b634f3f0c3e7e 100644 --- a/lib/libc/include/generic-glibc/pthread.h +++ b/lib/libc/include/generic-glibc/pthread.h @@ -770,6 +770,13 @@ extern int pthread_mutex_timedlock (pthread_mutex_t *__restrict __mutex, __abstime) __THROWNL __nonnull ((1, 2)); #endif +#ifdef __USE_GNU +extern int pthread_mutex_clocklock (pthread_mutex_t *__restrict __mutex, + clockid_t __clockid, + const struct timespec *__restrict + __abstime) __THROWNL __nonnull ((1, 3)); +#endif + /* Unlock a mutex. */ extern int pthread_mutex_unlock (pthread_mutex_t *__mutex) __THROWNL __nonnull ((1)); @@ -909,6 +916,13 @@ extern int pthread_rwlock_timedrdlock (pthread_rwlock_t *__restrict __rwlock, __abstime) __THROWNL __nonnull ((1, 2)); # endif +# ifdef __USE_GNU +extern int pthread_rwlock_clockrdlock (pthread_rwlock_t *__restrict __rwlock, + clockid_t __clockid, + const struct timespec *__restrict + __abstime) __THROWNL __nonnull ((1, 3)); +# endif + /* Acquire write lock for RWLOCK. */ extern int pthread_rwlock_wrlock (pthread_rwlock_t *__rwlock) __THROWNL __nonnull ((1)); @@ -924,6 +938,13 @@ extern int pthread_rwlock_timedwrlock (pthread_rwlock_t *__restrict __rwlock, __abstime) __THROWNL __nonnull ((1, 2)); # endif +# ifdef __USE_GNU +extern int pthread_rwlock_clockwrlock (pthread_rwlock_t *__restrict __rwlock, + clockid_t __clockid, + const struct timespec *__restrict + __abstime) __THROWNL __nonnull ((1, 3)); +# endif + /* Unlock RWLOCK. */ extern int pthread_rwlock_unlock (pthread_rwlock_t *__rwlock) __THROWNL __nonnull ((1)); @@ -1003,6 +1024,21 @@ extern int pthread_cond_timedwait (pthread_cond_t *__restrict __cond, const struct timespec *__restrict __abstime) __nonnull ((1, 2, 3)); +# ifdef __USE_GNU +/* Wait for condition variable COND to be signaled or broadcast until + ABSTIME measured by the specified clock. MUTEX is assumed to be + locked before. CLOCK is the clock to use. ABSTIME is an absolute + time specification against CLOCK's epoch. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern int pthread_cond_clockwait (pthread_cond_t *__restrict __cond, + pthread_mutex_t *__restrict __mutex, + __clockid_t __clock_id, + const struct timespec *__restrict __abstime) + __nonnull ((1, 2, 4)); +# endif + /* Functions for handling condition variable attributes. */ /* Initialize condition variable attribute ATTR. */ diff --git a/lib/libc/include/generic-glibc/resolv.h b/lib/libc/include/generic-glibc/resolv.h index 8dba91c8021e317fef65c334daa417a2f030b546..184e6a0074495ea1a2792be30108b5891bcf9262 100644 --- a/lib/libc/include/generic-glibc/resolv.h +++ b/lib/libc/include/generic-glibc/resolv.h @@ -115,11 +115,7 @@ struct res_sym { #define RES_DEFNAMES 0x00000080 /* use default domain name */ #define RES_STAYOPEN 0x00000100 /* Keep TCP socket open */ #define RES_DNSRCH 0x00000200 /* search up local domain tree */ -#define RES_INSECURE1 0x00000400 /* type 1 security disabled */ -#define RES_INSECURE2 0x00000800 /* type 2 security disabled */ #define RES_NOALIASES 0x00001000 /* shuts off HOSTALIASES feature */ -#define RES_USE_INET6 \ - __glibc_macro_warning ("RES_USE_INET6 is deprecated") 0x00002000 #define RES_ROTATE 0x00004000 /* rotate ns list after each query */ #define RES_NOCHECKNAME \ __glibc_macro_warning ("RES_NOCHECKNAME is deprecated") 0x00008000 diff --git a/lib/libc/include/generic-glibc/search.h b/lib/libc/include/generic-glibc/search.h index f0dd98bc795acaf0725c01e152c452668e074b30..8ea76038916962740b64d36e42608a3168f6b5f6 100644 --- a/lib/libc/include/generic-glibc/search.h +++ b/lib/libc/include/generic-glibc/search.h @@ -150,6 +150,13 @@ typedef void (*__action_fn_t) (const void *__nodep, VISIT __value, extern void twalk (const void *__root, __action_fn_t __action); #ifdef __USE_GNU +/* Like twalk, but pass down a closure parameter instead of the + level. */ +extern void twalk_r (const void *__root, + void (*) (const void *__nodep, VISIT __value, + void *__closure), + void *__closure); + /* Callback type for function to free a tree node. If the keys are atomic data this function should do nothing. */ typedef void (*__free_fn_t) (void *__nodep); diff --git a/lib/libc/include/generic-glibc/semaphore.h b/lib/libc/include/generic-glibc/semaphore.h index c3d78053e94cf22a7f59bc6fedabd1ac83787079..595dec7abd77e38f35d1e056b0d3b26a8d1afbb0 100644 --- a/lib/libc/include/generic-glibc/semaphore.h +++ b/lib/libc/include/generic-glibc/semaphore.h @@ -33,24 +33,26 @@ __BEGIN_DECLS /* Initialize semaphore object SEM to VALUE. If PSHARED then share it with other processes. */ extern int sem_init (sem_t *__sem, int __pshared, unsigned int __value) - __THROW; + __THROW __nonnull ((1)); + /* Free resources associated with semaphore object SEM. */ -extern int sem_destroy (sem_t *__sem) __THROW; +extern int sem_destroy (sem_t *__sem) __THROW __nonnull ((1)); /* Open a named semaphore NAME with open flags OFLAG. */ -extern sem_t *sem_open (const char *__name, int __oflag, ...) __THROW; +extern sem_t *sem_open (const char *__name, int __oflag, ...) + __THROW __nonnull ((1)); /* Close descriptor for named semaphore SEM. */ -extern int sem_close (sem_t *__sem) __THROW; +extern int sem_close (sem_t *__sem) __THROW __nonnull ((1)); /* Remove named semaphore NAME. */ -extern int sem_unlink (const char *__name) __THROW; +extern int sem_unlink (const char *__name) __THROW __nonnull ((1)); /* Wait for SEM being posted. This function is a cancellation point and therefore not marked with __THROW. */ -extern int sem_wait (sem_t *__sem); +extern int sem_wait (sem_t *__sem) __nonnull ((1)); #ifdef __USE_XOPEN2K /* Similar to `sem_wait' but wait only until ABSTIME. @@ -58,18 +60,26 @@ extern int sem_wait (sem_t *__sem); This function is a cancellation point and therefore not marked with __THROW. */ extern int sem_timedwait (sem_t *__restrict __sem, - const struct timespec *__restrict __abstime); + const struct timespec *__restrict __abstime) + __nonnull ((1, 2)); +#endif + +#ifdef __USE_GNU +extern int sem_clockwait (sem_t *__restrict __sem, + clockid_t clock, + const struct timespec *__restrict __abstime) + __nonnull ((1, 3)); #endif /* Test whether SEM is posted. */ -extern int sem_trywait (sem_t *__sem) __THROWNL; +extern int sem_trywait (sem_t *__sem) __THROWNL __nonnull ((1)); /* Post SEM. */ -extern int sem_post (sem_t *__sem) __THROWNL; +extern int sem_post (sem_t *__sem) __THROWNL __nonnull ((1)); /* Get current value of SEM and store it in *SVAL. */ extern int sem_getvalue (sem_t *__restrict __sem, int *__restrict __sval) - __THROW; + __THROW __nonnull ((1, 2)); __END_DECLS diff --git a/lib/libc/include/generic-glibc/signal.h b/lib/libc/include/generic-glibc/signal.h index 944f3179aa9c542a3f52b7ad53a3399a06daf191..12999bc8deb16b471940649afa5360a6c50abf9c 100644 --- a/lib/libc/include/generic-glibc/signal.h +++ b/lib/libc/include/generic-glibc/signal.h @@ -370,6 +370,9 @@ extern int __libc_current_sigrtmax (void) __THROW; #define SIGRTMIN (__libc_current_sigrtmin ()) #define SIGRTMAX (__libc_current_sigrtmax ()) +/* System-specific extensions. */ +#include + __END_DECLS #endif /* not signal.h */ \ No newline at end of file diff --git a/lib/libc/include/generic-glibc/stdlib.h b/lib/libc/include/generic-glibc/stdlib.h index 152d7c0148cb9995c18c264383012fb0b60fc3db..cfe0bf33182a6aadf830b7071c1302eb4eae4299 100644 --- a/lib/libc/include/generic-glibc/stdlib.h +++ b/lib/libc/include/generic-glibc/stdlib.h @@ -536,10 +536,11 @@ extern int lcong48_r (unsigned short int __param[7], #endif /* Use misc or X/Open. */ /* Allocate SIZE bytes of memory. */ -extern void *malloc (size_t __size) __THROW __attribute_malloc__ __wur; +extern void *malloc (size_t __size) __THROW __attribute_malloc__ + __attribute_alloc_size__ ((1)) __wur; /* Allocate NMEMB elements of SIZE bytes each, all initialized to 0. */ extern void *calloc (size_t __nmemb, size_t __size) - __THROW __attribute_malloc__ __wur; + __THROW __attribute_malloc__ __attribute_alloc_size__ ((1, 2)) __wur; /* Re-allocate the previously allocated block in PTR, making the new block SIZE bytes long. */ @@ -547,7 +548,7 @@ extern void *calloc (size_t __nmemb, size_t __size) the same pointer that was passed to it, aliasing needs to be allowed between objects pointed by the old and new pointers. */ extern void *realloc (void *__ptr, size_t __size) - __THROW __attribute_warn_unused_result__; + __THROW __attribute_warn_unused_result__ __attribute_alloc_size__ ((2)); #ifdef __USE_MISC /* Re-allocate the previously allocated block in PTR, making the new @@ -556,7 +557,8 @@ extern void *realloc (void *__ptr, size_t __size) the same pointer that was passed to it, aliasing needs to be allowed between objects pointed by the old and new pointers. */ extern void *reallocarray (void *__ptr, size_t __nmemb, size_t __size) - __THROW __attribute_warn_unused_result__; + __THROW __attribute_warn_unused_result__ + __attribute_alloc_size__ ((2, 3)); #endif /* Free a block allocated by `malloc', `realloc' or `calloc'. */ @@ -569,7 +571,8 @@ extern void free (void *__ptr) __THROW; #if (defined __USE_XOPEN_EXTENDED && !defined __USE_XOPEN2K) \ || defined __USE_MISC /* Allocate SIZE bytes on a page boundary. The storage cannot be freed. */ -extern void *valloc (size_t __size) __THROW __attribute_malloc__ __wur; +extern void *valloc (size_t __size) __THROW __attribute_malloc__ + __attribute_alloc_size__ ((1)) __wur; #endif #ifdef __USE_XOPEN2K diff --git a/lib/libc/include/generic-glibc/stropts.h b/lib/libc/include/generic-glibc/stropts.h deleted file mode 100644 index 4f13402a1b2480a507c4bc872a98a9ed8a72eac5..0000000000000000000000000000000000000000 --- a/lib/libc/include/generic-glibc/stropts.h +++ /dev/null @@ -1,92 +0,0 @@ -/* Copyright (C) 1998-2019 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - . */ - -#ifndef _STROPTS_H -#define _STROPTS_H 1 - -#include -#include -#include - -#ifndef __gid_t_defined -typedef __gid_t gid_t; -# define __gid_t_defined -#endif - -#ifndef __uid_t_defined -typedef __uid_t uid_t; -# define __uid_t_defined -#endif - -typedef __t_scalar_t t_scalar_t; -typedef __t_uscalar_t t_uscalar_t; - -/* Get system specific constants. */ -#include - - -__BEGIN_DECLS - -/* Test whether FILDES is associated with a STREAM-based file. */ -extern int isastream (int __fildes) __THROW; - -/* Receive next message from a STREAMS file. - - This function is a cancellation point and therefore not marked with - __THROW. */ -extern int getmsg (int __fildes, struct strbuf *__restrict __ctlptr, - struct strbuf *__restrict __dataptr, - int *__restrict __flagsp); - -/* Receive next message from a STREAMS file, with *FLAGSP allowing to - control which message. - - This function is a cancellation point and therefore not marked with - __THROW. */ -extern int getpmsg (int __fildes, struct strbuf *__restrict __ctlptr, - struct strbuf *__restrict __dataptr, - int *__restrict __bandp, int *__restrict __flagsp); - -/* Perform the I/O control operation specified by REQUEST on FD. - One argument may follow; its presence and type depend on REQUEST. - Return value depends on REQUEST. Usually -1 indicates error. */ -extern int ioctl (int __fd, unsigned long int __request, ...) __THROW; - -/* Send a message on a STREAM. - - This function is a cancellation point and therefore not marked with - __THROW. */ -extern int putmsg (int __fildes, const struct strbuf *__ctlptr, - const struct strbuf *__dataptr, int __flags); - -/* Send a message on a STREAM to the BAND. - - This function is a cancellation point and therefore not marked with - __THROW. */ -extern int putpmsg (int __fildes, const struct strbuf *__ctlptr, - const struct strbuf *__dataptr, int __band, int __flags); - -/* Attach a STREAMS-based file descriptor FILDES to a file PATH in the - file system name space. */ -extern int fattach (int __fildes, const char *__path) __THROW; - -/* Detach a name PATH from a STREAMS-based file descriptor. */ -extern int fdetach (const char *__path) __THROW; - -__END_DECLS - -#endif /* stropts.h */ \ No newline at end of file diff --git a/lib/libc/include/generic-glibc/sys/cdefs.h b/lib/libc/include/generic-glibc/sys/cdefs.h index 5b813a0f441402fb1fa7751a406383dc2b80e282..fad225653759e55418387276c906a17ae2eaf5bf 100644 --- a/lib/libc/include/generic-glibc/sys/cdefs.h +++ b/lib/libc/include/generic-glibc/sys/cdefs.h @@ -412,6 +412,14 @@ # define __glibc_has_attribute(attr) 0 #endif +#ifdef __has_include +/* Do not use a function-like macro, so that __has_include can inhibit + macro expansion. */ +# define __glibc_has_include __has_include +#else +# define __glibc_has_include(header) 0 +#endif + #if (!defined _Noreturn \ && (defined __STDC_VERSION__ ? __STDC_VERSION__ : 0) < 201112 \ && !__GNUC_PREREQ (4,7)) diff --git a/lib/libc/include/generic-glibc/sys/ifunc.h b/lib/libc/include/generic-glibc/sys/ifunc.h new file mode 100644 index 0000000000000000000000000000000000000000..06e9a42847bf146397f645d7a60c3df828cc783c --- /dev/null +++ b/lib/libc/include/generic-glibc/sys/ifunc.h @@ -0,0 +1,42 @@ +/* Definitions used by AArch64 indirect function resolvers. + Copyright (C) 2019 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#ifndef _SYS_IFUNC_H +#define _SYS_IFUNC_H + +/* A second argument is passed to the ifunc resolver. */ +#define _IFUNC_ARG_HWCAP (1ULL << 62) + +/* The prototype of a gnu indirect function resolver on AArch64 is + + ElfW(Addr) ifunc_resolver (uint64_t, const __ifunc_arg_t *); + + the first argument should have the _IFUNC_ARG_HWCAP bit set and + the remaining bits should match the AT_HWCAP settings. */ + +/* Second argument to an ifunc resolver. */ +struct __ifunc_arg_t +{ + unsigned long _size; /* Size of the struct, so it can grow. */ + unsigned long _hwcap; + unsigned long _hwcap2; +}; + +typedef struct __ifunc_arg_t __ifunc_arg_t; + +#endif \ No newline at end of file diff --git a/lib/libc/include/generic-glibc/sys/io.h b/lib/libc/include/generic-glibc/sys/io.h index ba1a73b0939292f3d7a126a49804f7f95249b433..c27e96f4af7aab65cf910cec2ef8c9a9d42487e4 100644 --- a/lib/libc/include/generic-glibc/sys/io.h +++ b/lib/libc/include/generic-glibc/sys/io.h @@ -12,36 +12,172 @@ Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library. If not, see + License along with the GNU C Library; if not, see . */ #ifndef _SYS_IO_H - #define _SYS_IO_H 1 + #include __BEGIN_DECLS /* If TURN_ON is TRUE, request for permission to do direct i/o on the port numbers in the range [FROM,FROM+NUM-1]. Otherwise, turn I/O - permission off for that range. This call requires root privileges. */ + permission off for that range. This call requires root privileges. + + Portability note: not all Linux platforms support this call. Most + platforms based on the PC I/O architecture probably will, however. + E.g., Linux/Alpha for Alpha PCs supports this. */ extern int ioperm (unsigned long int __from, unsigned long int __num, - int __turn_on) __THROW; + int __turn_on) __THROW; -/* Set the I/O privilege level to LEVEL. If LEVEL is nonzero, - permission to access any I/O port is granted. This call requires - root privileges. */ +/* Set the I/O privilege level to LEVEL. If LEVEL>3, permission to + access any I/O port is granted. This call requires root + privileges. */ extern int iopl (int __level) __THROW; -/* The functions that actually perform reads and writes. */ -extern unsigned char inb (unsigned long int __port) __THROW; -extern unsigned short int inw (unsigned long int __port) __THROW; -extern unsigned long int inl (unsigned long int __port) __THROW; - -extern void outb (unsigned char __value, unsigned long int __port) __THROW; -extern void outw (unsigned short __value, unsigned long int __port) __THROW; -extern void outl (unsigned long __value, unsigned long int __port) __THROW; +#if defined __GNUC__ && __GNUC__ >= 2 + +static __inline unsigned char +inb (unsigned short int __port) +{ + unsigned char _v; + + __asm__ __volatile__ ("inb %w1,%0":"=a" (_v):"Nd" (__port)); + return _v; +} + +static __inline unsigned char +inb_p (unsigned short int __port) +{ + unsigned char _v; + + __asm__ __volatile__ ("inb %w1,%0\noutb %%al,$0x80":"=a" (_v):"Nd" (__port)); + return _v; +} + +static __inline unsigned short int +inw (unsigned short int __port) +{ + unsigned short _v; + + __asm__ __volatile__ ("inw %w1,%0":"=a" (_v):"Nd" (__port)); + return _v; +} + +static __inline unsigned short int +inw_p (unsigned short int __port) +{ + unsigned short int _v; + + __asm__ __volatile__ ("inw %w1,%0\noutb %%al,$0x80":"=a" (_v):"Nd" (__port)); + return _v; +} + +static __inline unsigned int +inl (unsigned short int __port) +{ + unsigned int _v; + + __asm__ __volatile__ ("inl %w1,%0":"=a" (_v):"Nd" (__port)); + return _v; +} + +static __inline unsigned int +inl_p (unsigned short int __port) +{ + unsigned int _v; + __asm__ __volatile__ ("inl %w1,%0\noutb %%al,$0x80":"=a" (_v):"Nd" (__port)); + return _v; +} + +static __inline void +outb (unsigned char __value, unsigned short int __port) +{ + __asm__ __volatile__ ("outb %b0,%w1": :"a" (__value), "Nd" (__port)); +} + +static __inline void +outb_p (unsigned char __value, unsigned short int __port) +{ + __asm__ __volatile__ ("outb %b0,%w1\noutb %%al,$0x80": :"a" (__value), + "Nd" (__port)); +} + +static __inline void +outw (unsigned short int __value, unsigned short int __port) +{ + __asm__ __volatile__ ("outw %w0,%w1": :"a" (__value), "Nd" (__port)); + +} + +static __inline void +outw_p (unsigned short int __value, unsigned short int __port) +{ + __asm__ __volatile__ ("outw %w0,%w1\noutb %%al,$0x80": :"a" (__value), + "Nd" (__port)); +} + +static __inline void +outl (unsigned int __value, unsigned short int __port) +{ + __asm__ __volatile__ ("outl %0,%w1": :"a" (__value), "Nd" (__port)); +} + +static __inline void +outl_p (unsigned int __value, unsigned short int __port) +{ + __asm__ __volatile__ ("outl %0,%w1\noutb %%al,$0x80": :"a" (__value), + "Nd" (__port)); +} + +static __inline void +insb (unsigned short int __port, void *__addr, unsigned long int __count) +{ + __asm__ __volatile__ ("cld ; rep ; insb":"=D" (__addr), "=c" (__count) + :"d" (__port), "0" (__addr), "1" (__count)); +} + +static __inline void +insw (unsigned short int __port, void *__addr, unsigned long int __count) +{ + __asm__ __volatile__ ("cld ; rep ; insw":"=D" (__addr), "=c" (__count) + :"d" (__port), "0" (__addr), "1" (__count)); +} + +static __inline void +insl (unsigned short int __port, void *__addr, unsigned long int __count) +{ + __asm__ __volatile__ ("cld ; rep ; insl":"=D" (__addr), "=c" (__count) + :"d" (__port), "0" (__addr), "1" (__count)); +} + +static __inline void +outsb (unsigned short int __port, const void *__addr, + unsigned long int __count) +{ + __asm__ __volatile__ ("cld ; rep ; outsb":"=S" (__addr), "=c" (__count) + :"d" (__port), "0" (__addr), "1" (__count)); +} + +static __inline void +outsw (unsigned short int __port, const void *__addr, + unsigned long int __count) +{ + __asm__ __volatile__ ("cld ; rep ; outsw":"=S" (__addr), "=c" (__count) + :"d" (__port), "0" (__addr), "1" (__count)); +} + +static __inline void +outsl (unsigned short int __port, const void *__addr, + unsigned long int __count) +{ + __asm__ __volatile__ ("cld ; rep ; outsl":"=S" (__addr), "=c" (__count) + :"d" (__port), "0" (__addr), "1" (__count)); +} + +#endif /* GNU C */ __END_DECLS - #endif /* _SYS_IO_H */ \ No newline at end of file diff --git a/lib/libc/include/generic-glibc/sys/stropts.h b/lib/libc/include/generic-glibc/sys/stropts.h deleted file mode 100644 index 27152138427d8a207535e5b826786eb4a2c778a6..0000000000000000000000000000000000000000 --- a/lib/libc/include/generic-glibc/sys/stropts.h +++ /dev/null @@ -1 +0,0 @@ -#include \ No newline at end of file diff --git a/lib/libc/include/generic-glibc/sys/sysctl.h b/lib/libc/include/generic-glibc/sys/sysctl.h index b1ebb39054ff63bb34522e1257314bc363851910..9af38782b66a9210f957723b8dd0e29e6fdb51c8 100644 --- a/lib/libc/include/generic-glibc/sys/sysctl.h +++ b/lib/libc/include/generic-glibc/sys/sysctl.h @@ -18,6 +18,8 @@ #ifndef _SYS_SYSCTL_H #define _SYS_SYSCTL_H 1 +#warning "The header is deprecated and will be removed." + #include #define __need_size_t #include @@ -66,7 +68,8 @@ __BEGIN_DECLS /* Read or write system parameters. */ extern int sysctl (int *__name, int __nlen, void *__oldval, - size_t *__oldlenp, void *__newval, size_t __newlen) __THROW; + size_t *__oldlenp, void *__newval, size_t __newlen) __THROW + __attribute_deprecated__; __END_DECLS diff --git a/lib/libc/include/generic-glibc/sys/types.h b/lib/libc/include/generic-glibc/sys/types.h index 91228897806397e56f0341aa854c399550ae42a8..c7728532fd76234f3df23b7f6e06a1d4dc30cff0 100644 --- a/lib/libc/include/generic-glibc/sys/types.h +++ b/lib/libc/include/generic-glibc/sys/types.h @@ -154,37 +154,20 @@ typedef unsigned int uint; #include -#if !__GNUC_PREREQ (2, 7) - /* These were defined by ISO C without the first `_'. */ -typedef unsigned char u_int8_t; -typedef unsigned short int u_int16_t; -typedef unsigned int u_int32_t; -# if __WORDSIZE == 64 -typedef unsigned long int u_int64_t; -# else -__extension__ typedef unsigned long long int u_int64_t; -# endif - -typedef int register_t; - -#else - -/* For GCC 2.7 and later, we can use specific type-size attributes. */ -# define __u_intN_t(N, MODE) \ - typedef unsigned int u_int##N##_t __attribute__ ((__mode__ (MODE))) - -__u_intN_t (8, __QI__); -__u_intN_t (16, __HI__); -__u_intN_t (32, __SI__); -__u_intN_t (64, __DI__); +typedef __uint8_t u_int8_t; +typedef __uint16_t u_int16_t; +typedef __uint32_t u_int32_t; +typedef __uint64_t u_int64_t; +#if __GNUC_PREREQ (2, 7) typedef int register_t __attribute__ ((__mode__ (__word__))); - +#else +typedef int register_t; +#endif /* Some code from BIND tests this macro to see if the types above are defined. */ -#endif #define __BIT_TYPES_DEFINED__ 1 diff --git a/lib/libc/include/i386-linux-gnu/bits/math-vector-fortran.h b/lib/libc/include/i386-linux-gnu/finclude/math-vector-fortran.h similarity index 100% rename from lib/libc/include/i386-linux-gnu/bits/math-vector-fortran.h rename to lib/libc/include/i386-linux-gnu/finclude/math-vector-fortran.h diff --git a/lib/libc/include/i386-linux-gnu/sys/io.h b/lib/libc/include/i386-linux-gnu/sys/io.h deleted file mode 100644 index c27e96f4af7aab65cf910cec2ef8c9a9d42487e4..0000000000000000000000000000000000000000 --- a/lib/libc/include/i386-linux-gnu/sys/io.h +++ /dev/null @@ -1,183 +0,0 @@ -/* Copyright (C) 1996-2019 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - . */ - -#ifndef _SYS_IO_H -#define _SYS_IO_H 1 - -#include - -__BEGIN_DECLS - -/* If TURN_ON is TRUE, request for permission to do direct i/o on the - port numbers in the range [FROM,FROM+NUM-1]. Otherwise, turn I/O - permission off for that range. This call requires root privileges. - - Portability note: not all Linux platforms support this call. Most - platforms based on the PC I/O architecture probably will, however. - E.g., Linux/Alpha for Alpha PCs supports this. */ -extern int ioperm (unsigned long int __from, unsigned long int __num, - int __turn_on) __THROW; - -/* Set the I/O privilege level to LEVEL. If LEVEL>3, permission to - access any I/O port is granted. This call requires root - privileges. */ -extern int iopl (int __level) __THROW; - -#if defined __GNUC__ && __GNUC__ >= 2 - -static __inline unsigned char -inb (unsigned short int __port) -{ - unsigned char _v; - - __asm__ __volatile__ ("inb %w1,%0":"=a" (_v):"Nd" (__port)); - return _v; -} - -static __inline unsigned char -inb_p (unsigned short int __port) -{ - unsigned char _v; - - __asm__ __volatile__ ("inb %w1,%0\noutb %%al,$0x80":"=a" (_v):"Nd" (__port)); - return _v; -} - -static __inline unsigned short int -inw (unsigned short int __port) -{ - unsigned short _v; - - __asm__ __volatile__ ("inw %w1,%0":"=a" (_v):"Nd" (__port)); - return _v; -} - -static __inline unsigned short int -inw_p (unsigned short int __port) -{ - unsigned short int _v; - - __asm__ __volatile__ ("inw %w1,%0\noutb %%al,$0x80":"=a" (_v):"Nd" (__port)); - return _v; -} - -static __inline unsigned int -inl (unsigned short int __port) -{ - unsigned int _v; - - __asm__ __volatile__ ("inl %w1,%0":"=a" (_v):"Nd" (__port)); - return _v; -} - -static __inline unsigned int -inl_p (unsigned short int __port) -{ - unsigned int _v; - __asm__ __volatile__ ("inl %w1,%0\noutb %%al,$0x80":"=a" (_v):"Nd" (__port)); - return _v; -} - -static __inline void -outb (unsigned char __value, unsigned short int __port) -{ - __asm__ __volatile__ ("outb %b0,%w1": :"a" (__value), "Nd" (__port)); -} - -static __inline void -outb_p (unsigned char __value, unsigned short int __port) -{ - __asm__ __volatile__ ("outb %b0,%w1\noutb %%al,$0x80": :"a" (__value), - "Nd" (__port)); -} - -static __inline void -outw (unsigned short int __value, unsigned short int __port) -{ - __asm__ __volatile__ ("outw %w0,%w1": :"a" (__value), "Nd" (__port)); - -} - -static __inline void -outw_p (unsigned short int __value, unsigned short int __port) -{ - __asm__ __volatile__ ("outw %w0,%w1\noutb %%al,$0x80": :"a" (__value), - "Nd" (__port)); -} - -static __inline void -outl (unsigned int __value, unsigned short int __port) -{ - __asm__ __volatile__ ("outl %0,%w1": :"a" (__value), "Nd" (__port)); -} - -static __inline void -outl_p (unsigned int __value, unsigned short int __port) -{ - __asm__ __volatile__ ("outl %0,%w1\noutb %%al,$0x80": :"a" (__value), - "Nd" (__port)); -} - -static __inline void -insb (unsigned short int __port, void *__addr, unsigned long int __count) -{ - __asm__ __volatile__ ("cld ; rep ; insb":"=D" (__addr), "=c" (__count) - :"d" (__port), "0" (__addr), "1" (__count)); -} - -static __inline void -insw (unsigned short int __port, void *__addr, unsigned long int __count) -{ - __asm__ __volatile__ ("cld ; rep ; insw":"=D" (__addr), "=c" (__count) - :"d" (__port), "0" (__addr), "1" (__count)); -} - -static __inline void -insl (unsigned short int __port, void *__addr, unsigned long int __count) -{ - __asm__ __volatile__ ("cld ; rep ; insl":"=D" (__addr), "=c" (__count) - :"d" (__port), "0" (__addr), "1" (__count)); -} - -static __inline void -outsb (unsigned short int __port, const void *__addr, - unsigned long int __count) -{ - __asm__ __volatile__ ("cld ; rep ; outsb":"=S" (__addr), "=c" (__count) - :"d" (__port), "0" (__addr), "1" (__count)); -} - -static __inline void -outsw (unsigned short int __port, const void *__addr, - unsigned long int __count) -{ - __asm__ __volatile__ ("cld ; rep ; outsw":"=S" (__addr), "=c" (__count) - :"d" (__port), "0" (__addr), "1" (__count)); -} - -static __inline void -outsl (unsigned short int __port, const void *__addr, - unsigned long int __count) -{ - __asm__ __volatile__ ("cld ; rep ; outsl":"=S" (__addr), "=c" (__count) - :"d" (__port), "0" (__addr), "1" (__count)); -} - -#endif /* GNU C */ - -__END_DECLS -#endif /* _SYS_IO_H */ \ No newline at end of file diff --git a/lib/libc/include/mips-linux-gnu/bits/socket-constants.h b/lib/libc/include/mips-linux-gnu/bits/socket-constants.h new file mode 100644 index 0000000000000000000000000000000000000000..cfd1839b98efe6dee095434c69a0183802cb243c --- /dev/null +++ b/lib/libc/include/mips-linux-gnu/bits/socket-constants.h @@ -0,0 +1,38 @@ +/* Socket constants which vary among Linux architectures. Version for MIPS. + Copyright (C) 2019 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#ifndef _SYS_SOCKET_H +# error "Never include directly; use instead." +#endif + +#define SOL_SOCKET 65535 +#define SO_ACCEPTCONN 4105 +#define SO_BROADCAST 32 +#define SO_DONTROUTE 16 +#define SO_ERROR 4103 +#define SO_KEEPALIVE 8 +#define SO_LINGER 128 +#define SO_OOBINLINE 256 +#define SO_RCVBUF 4098 +#define SO_RCVLOWAT 4100 +#define SO_RCVTIMEO 4102 +#define SO_REUSEADDR 4 +#define SO_SNDBUF 4097 +#define SO_SNDLOWAT 4099 +#define SO_SNDTIMEO 4101 +#define SO_TYPE 4104 \ No newline at end of file diff --git a/lib/libc/include/mips64-linux-gnuabi64/bits/socket-constants.h b/lib/libc/include/mips64-linux-gnuabi64/bits/socket-constants.h new file mode 100644 index 0000000000000000000000000000000000000000..cfd1839b98efe6dee095434c69a0183802cb243c --- /dev/null +++ b/lib/libc/include/mips64-linux-gnuabi64/bits/socket-constants.h @@ -0,0 +1,38 @@ +/* Socket constants which vary among Linux architectures. Version for MIPS. + Copyright (C) 2019 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#ifndef _SYS_SOCKET_H +# error "Never include directly; use instead." +#endif + +#define SOL_SOCKET 65535 +#define SO_ACCEPTCONN 4105 +#define SO_BROADCAST 32 +#define SO_DONTROUTE 16 +#define SO_ERROR 4103 +#define SO_KEEPALIVE 8 +#define SO_LINGER 128 +#define SO_OOBINLINE 256 +#define SO_RCVBUF 4098 +#define SO_RCVLOWAT 4100 +#define SO_RCVTIMEO 4102 +#define SO_REUSEADDR 4 +#define SO_SNDBUF 4097 +#define SO_SNDLOWAT 4099 +#define SO_SNDTIMEO 4101 +#define SO_TYPE 4104 \ No newline at end of file diff --git a/lib/libc/include/mips64-linux-gnuabin32/bits/socket-constants.h b/lib/libc/include/mips64-linux-gnuabin32/bits/socket-constants.h new file mode 100644 index 0000000000000000000000000000000000000000..cfd1839b98efe6dee095434c69a0183802cb243c --- /dev/null +++ b/lib/libc/include/mips64-linux-gnuabin32/bits/socket-constants.h @@ -0,0 +1,38 @@ +/* Socket constants which vary among Linux architectures. Version for MIPS. + Copyright (C) 2019 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#ifndef _SYS_SOCKET_H +# error "Never include directly; use instead." +#endif + +#define SOL_SOCKET 65535 +#define SO_ACCEPTCONN 4105 +#define SO_BROADCAST 32 +#define SO_DONTROUTE 16 +#define SO_ERROR 4103 +#define SO_KEEPALIVE 8 +#define SO_LINGER 128 +#define SO_OOBINLINE 256 +#define SO_RCVBUF 4098 +#define SO_RCVLOWAT 4100 +#define SO_RCVTIMEO 4102 +#define SO_REUSEADDR 4 +#define SO_SNDBUF 4097 +#define SO_SNDLOWAT 4099 +#define SO_SNDTIMEO 4101 +#define SO_TYPE 4104 \ No newline at end of file diff --git a/lib/libc/include/mips64el-linux-gnuabi64/bits/socket-constants.h b/lib/libc/include/mips64el-linux-gnuabi64/bits/socket-constants.h new file mode 100644 index 0000000000000000000000000000000000000000..cfd1839b98efe6dee095434c69a0183802cb243c --- /dev/null +++ b/lib/libc/include/mips64el-linux-gnuabi64/bits/socket-constants.h @@ -0,0 +1,38 @@ +/* Socket constants which vary among Linux architectures. Version for MIPS. + Copyright (C) 2019 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#ifndef _SYS_SOCKET_H +# error "Never include directly; use instead." +#endif + +#define SOL_SOCKET 65535 +#define SO_ACCEPTCONN 4105 +#define SO_BROADCAST 32 +#define SO_DONTROUTE 16 +#define SO_ERROR 4103 +#define SO_KEEPALIVE 8 +#define SO_LINGER 128 +#define SO_OOBINLINE 256 +#define SO_RCVBUF 4098 +#define SO_RCVLOWAT 4100 +#define SO_RCVTIMEO 4102 +#define SO_REUSEADDR 4 +#define SO_SNDBUF 4097 +#define SO_SNDLOWAT 4099 +#define SO_SNDTIMEO 4101 +#define SO_TYPE 4104 \ No newline at end of file diff --git a/lib/libc/include/mips64el-linux-gnuabin32/bits/socket-constants.h b/lib/libc/include/mips64el-linux-gnuabin32/bits/socket-constants.h new file mode 100644 index 0000000000000000000000000000000000000000..cfd1839b98efe6dee095434c69a0183802cb243c --- /dev/null +++ b/lib/libc/include/mips64el-linux-gnuabin32/bits/socket-constants.h @@ -0,0 +1,38 @@ +/* Socket constants which vary among Linux architectures. Version for MIPS. + Copyright (C) 2019 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#ifndef _SYS_SOCKET_H +# error "Never include directly; use instead." +#endif + +#define SOL_SOCKET 65535 +#define SO_ACCEPTCONN 4105 +#define SO_BROADCAST 32 +#define SO_DONTROUTE 16 +#define SO_ERROR 4103 +#define SO_KEEPALIVE 8 +#define SO_LINGER 128 +#define SO_OOBINLINE 256 +#define SO_RCVBUF 4098 +#define SO_RCVLOWAT 4100 +#define SO_RCVTIMEO 4102 +#define SO_REUSEADDR 4 +#define SO_SNDBUF 4097 +#define SO_SNDLOWAT 4099 +#define SO_SNDTIMEO 4101 +#define SO_TYPE 4104 \ No newline at end of file diff --git a/lib/libc/include/mipsel-linux-gnu/bits/socket-constants.h b/lib/libc/include/mipsel-linux-gnu/bits/socket-constants.h new file mode 100644 index 0000000000000000000000000000000000000000..cfd1839b98efe6dee095434c69a0183802cb243c --- /dev/null +++ b/lib/libc/include/mipsel-linux-gnu/bits/socket-constants.h @@ -0,0 +1,38 @@ +/* Socket constants which vary among Linux architectures. Version for MIPS. + Copyright (C) 2019 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#ifndef _SYS_SOCKET_H +# error "Never include directly; use instead." +#endif + +#define SOL_SOCKET 65535 +#define SO_ACCEPTCONN 4105 +#define SO_BROADCAST 32 +#define SO_DONTROUTE 16 +#define SO_ERROR 4103 +#define SO_KEEPALIVE 8 +#define SO_LINGER 128 +#define SO_OOBINLINE 256 +#define SO_RCVBUF 4098 +#define SO_RCVLOWAT 4100 +#define SO_RCVTIMEO 4102 +#define SO_REUSEADDR 4 +#define SO_SNDBUF 4097 +#define SO_SNDLOWAT 4099 +#define SO_SNDTIMEO 4101 +#define SO_TYPE 4104 \ No newline at end of file diff --git a/lib/libc/include/powerpc-linux-gnu/bits/fenvinline.h b/lib/libc/include/powerpc-linux-gnu/bits/fenvinline.h index 1552e48c7aaf868cebfa1356d8c89953eb6a73af..efb8a356e21568176f88b8e80dda9591056f8f3c 100644 --- a/lib/libc/include/powerpc-linux-gnu/bits/fenvinline.h +++ b/lib/libc/include/powerpc-linux-gnu/bits/fenvinline.h @@ -18,13 +18,36 @@ #if defined __GNUC__ && !defined _SOFT_FLOAT && !defined __NO_FPRS__ -/* Inline definition for fegetround. */ -# define __fegetround() \ - (__extension__ ({ int __fegetround_result; \ - __asm__ __volatile__ \ - ("mcrfs 7,7 ; mfcr %0" \ - : "=r"(__fegetround_result) : : "cr7"); \ - __fegetround_result & 3; })) +/* Inline definitions for fegetround. */ +# define __fegetround_ISA300() \ + (__extension__ ({ \ + union { double __d; unsigned long long __ll; } __u; \ + __asm__ __volatile__ ( \ + ".machine push; .machine \"power9\"; mffsl %0; .machine pop" \ + : "=f" (__u.__d)); \ + __u.__ll & 0x0000000000000003LL; \ + })) + +# define __fegetround_ISA2() \ + (__extension__ ({ \ + int __fegetround_result; \ + __asm__ __volatile__ ("mcrfs 7,7 ; mfcr %0" \ + : "=r"(__fegetround_result) : : "cr7"); \ + __fegetround_result & 3; \ + })) + +# ifdef _ARCH_PWR9 +# define __fegetround() __fegetround_ISA300() +# elif defined __BUILTIN_CPU_SUPPORTS__ +# define __fegetround() \ + (__glibc_likely (__builtin_cpu_supports ("arch_3_00")) \ + ? __fegetround_ISA300() \ + : __fegetround_ISA2() \ + ) +# else +# define __fegetround() __fegetround_ISA2() +# endif + # define fegetround() __fegetround () # ifndef __NO_MATH_INLINES diff --git a/lib/libc/include/powerpc-linux-gnu/bits/socket-constants.h b/lib/libc/include/powerpc-linux-gnu/bits/socket-constants.h new file mode 100644 index 0000000000000000000000000000000000000000..705f575fe09b97742a7c74d11ae0b378bf3fa4fc --- /dev/null +++ b/lib/libc/include/powerpc-linux-gnu/bits/socket-constants.h @@ -0,0 +1,38 @@ +/* Socket constants which vary among Linux architectures. Version for POWER. + Copyright (C) 2019 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#ifndef _SYS_SOCKET_H +# error "Never include directly; use instead." +#endif + +#define SOL_SOCKET 1 +#define SO_ACCEPTCONN 30 +#define SO_BROADCAST 6 +#define SO_DONTROUTE 5 +#define SO_ERROR 4 +#define SO_KEEPALIVE 9 +#define SO_LINGER 13 +#define SO_OOBINLINE 10 +#define SO_RCVBUF 8 +#define SO_RCVLOWAT 16 +#define SO_RCVTIMEO 18 +#define SO_REUSEADDR 2 +#define SO_SNDBUF 7 +#define SO_SNDLOWAT 17 +#define SO_SNDTIMEO 19 +#define SO_TYPE 3 \ No newline at end of file diff --git a/lib/libc/include/powerpc-linux-gnu/fpu_control.h b/lib/libc/include/powerpc-linux-gnu/fpu_control.h index 78a7a291ac01b829891f52e0c457139281cbb952..db5055a812e59a01925a62a031b0d01e58b6953e 100644 --- a/lib/libc/include/powerpc-linux-gnu/fpu_control.h +++ b/lib/libc/include/powerpc-linux-gnu/fpu_control.h @@ -19,6 +19,10 @@ #ifndef _FPU_CONTROL_H #define _FPU_CONTROL_H +#if defined __SPE__ || (defined __NO_FPRS__ && !defined _SOFT_FLOAT) +# error "SPE/e500 is no longer supported" +#endif + #ifdef _SOFT_FLOAT # define _FPU_RESERVED 0xffffffff @@ -28,41 +32,6 @@ typedef unsigned int fpu_control_t; # define _FPU_SETCW(cw) (void) (cw) extern fpu_control_t __fpu_control; -#elif defined __NO_FPRS__ /* e500 */ - -/* rounding control */ -# define _FPU_RC_NEAREST 0x00 /* RECOMMENDED */ -# define _FPU_RC_DOWN 0x03 -# define _FPU_RC_UP 0x02 -# define _FPU_RC_ZERO 0x01 - -/* masking of interrupts */ -# define _FPU_MASK_ZM 0x10 /* zero divide */ -# define _FPU_MASK_OM 0x04 /* overflow */ -# define _FPU_MASK_UM 0x08 /* underflow */ -# define _FPU_MASK_XM 0x40 /* inexact */ -# define _FPU_MASK_IM 0x20 /* invalid operation */ - -# define _FPU_RESERVED 0x00c10080 /* These bits are reserved and not changed. */ - -/* Correct IEEE semantics require traps to be enabled at the hardware - level; the kernel then does the emulation and determines whether - generation of signals from those traps was enabled using prctl. */ -# define _FPU_DEFAULT 0x0000003c /* Default value. */ -# define _FPU_IEEE _FPU_DEFAULT - -/* Type of the control word. */ -typedef unsigned int fpu_control_t; - -/* Macros for accessing the hardware control word. */ -# define _FPU_GETCW(cw) \ - __asm__ volatile ("mfspefscr %0" : "=r" (cw)) -# define _FPU_SETCW(cw) \ - __asm__ volatile ("mtspefscr %0" : : "r" (cw)) - -/* Default control word set at startup. */ -extern fpu_control_t __fpu_control; - #else /* PowerPC 6xx floating-point. */ /* rounding control */ @@ -71,6 +40,8 @@ extern fpu_control_t __fpu_control; # define _FPU_RC_UP 0x02 # define _FPU_RC_ZERO 0x01 +# define _FPU_MASK_RC (_FPU_RC_NEAREST|_FPU_RC_DOWN|_FPU_RC_UP|_FPU_RC_ZERO) + # define _FPU_MASK_NI 0x04 /* non-ieee mode */ /* masking of interrupts */ @@ -96,20 +67,43 @@ typedef unsigned int fpu_control_t; /* Macros for accessing the hardware control word. */ # define _FPU_GETCW(cw) \ ({union { double __d; unsigned long long __ll; } __u; \ - register double __fr; \ - __asm__ ("mffs %0" : "=f" (__fr)); \ - __u.__d = __fr; \ + __asm__ __volatile__("mffs %0" : "=f" (__u.__d)); \ (cw) = (fpu_control_t) __u.__ll; \ (fpu_control_t) __u.__ll; \ }) +# define _FPU_GET_RC_ISA300() \ + ({union { double __d; unsigned long long __ll; } __u; \ + __asm__ __volatile__( \ + ".machine push; .machine \"power9\"; mffsl %0; .machine pop" \ + : "=f" (__u.__d)); \ + (fpu_control_t) (__u.__ll & _FPU_MASK_RC); \ + }) + +# ifdef _ARCH_PWR9 +# define _FPU_GET_RC() _FPU_GET_RC_ISA300() +# elif defined __BUILTIN_CPU_SUPPORTS__ +# define _FPU_GET_RC() \ + ({fpu_control_t __rc; \ + __rc = __glibc_likely (__builtin_cpu_supports ("arch_3_00")) \ + ? _FPU_GET_RC_ISA300 () \ + : _FPU_GETCW (__rc) & _FPU_MASK_RC; \ + __rc; \ + }) +# else +# define _FPU_GET_RC() \ + ({fpu_control_t __rc = _FPU_GETCW (__rc) & _FPU_MASK_RC; \ + __rc; \ + }) +# endif + # define _FPU_SETCW(cw) \ { union { double __d; unsigned long long __ll; } __u; \ register double __fr; \ __u.__ll = 0xfff80000LL << 32; /* This is a QNaN. */ \ __u.__ll |= (cw) & 0xffffffffLL; \ __fr = __u.__d; \ - __asm__ ("mtfsf 255,%0" : : "f" (__fr)); \ + __asm__ __volatile__("mtfsf 255,%0" : : "f" (__fr)); \ } /* Default control word set at startup. */ diff --git a/lib/libc/include/powerpc64-linux-gnu/bits/fenvinline.h b/lib/libc/include/powerpc64-linux-gnu/bits/fenvinline.h index 1552e48c7aaf868cebfa1356d8c89953eb6a73af..efb8a356e21568176f88b8e80dda9591056f8f3c 100644 --- a/lib/libc/include/powerpc64-linux-gnu/bits/fenvinline.h +++ b/lib/libc/include/powerpc64-linux-gnu/bits/fenvinline.h @@ -18,13 +18,36 @@ #if defined __GNUC__ && !defined _SOFT_FLOAT && !defined __NO_FPRS__ -/* Inline definition for fegetround. */ -# define __fegetround() \ - (__extension__ ({ int __fegetround_result; \ - __asm__ __volatile__ \ - ("mcrfs 7,7 ; mfcr %0" \ - : "=r"(__fegetround_result) : : "cr7"); \ - __fegetround_result & 3; })) +/* Inline definitions for fegetround. */ +# define __fegetround_ISA300() \ + (__extension__ ({ \ + union { double __d; unsigned long long __ll; } __u; \ + __asm__ __volatile__ ( \ + ".machine push; .machine \"power9\"; mffsl %0; .machine pop" \ + : "=f" (__u.__d)); \ + __u.__ll & 0x0000000000000003LL; \ + })) + +# define __fegetround_ISA2() \ + (__extension__ ({ \ + int __fegetround_result; \ + __asm__ __volatile__ ("mcrfs 7,7 ; mfcr %0" \ + : "=r"(__fegetround_result) : : "cr7"); \ + __fegetround_result & 3; \ + })) + +# ifdef _ARCH_PWR9 +# define __fegetround() __fegetround_ISA300() +# elif defined __BUILTIN_CPU_SUPPORTS__ +# define __fegetround() \ + (__glibc_likely (__builtin_cpu_supports ("arch_3_00")) \ + ? __fegetround_ISA300() \ + : __fegetround_ISA2() \ + ) +# else +# define __fegetround() __fegetround_ISA2() +# endif + # define fegetround() __fegetround () # ifndef __NO_MATH_INLINES diff --git a/lib/libc/include/powerpc64-linux-gnu/bits/socket-constants.h b/lib/libc/include/powerpc64-linux-gnu/bits/socket-constants.h new file mode 100644 index 0000000000000000000000000000000000000000..705f575fe09b97742a7c74d11ae0b378bf3fa4fc --- /dev/null +++ b/lib/libc/include/powerpc64-linux-gnu/bits/socket-constants.h @@ -0,0 +1,38 @@ +/* Socket constants which vary among Linux architectures. Version for POWER. + Copyright (C) 2019 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#ifndef _SYS_SOCKET_H +# error "Never include directly; use instead." +#endif + +#define SOL_SOCKET 1 +#define SO_ACCEPTCONN 30 +#define SO_BROADCAST 6 +#define SO_DONTROUTE 5 +#define SO_ERROR 4 +#define SO_KEEPALIVE 9 +#define SO_LINGER 13 +#define SO_OOBINLINE 10 +#define SO_RCVBUF 8 +#define SO_RCVLOWAT 16 +#define SO_RCVTIMEO 18 +#define SO_REUSEADDR 2 +#define SO_SNDBUF 7 +#define SO_SNDLOWAT 17 +#define SO_SNDTIMEO 19 +#define SO_TYPE 3 \ No newline at end of file diff --git a/lib/libc/include/powerpc64-linux-gnu/fpu_control.h b/lib/libc/include/powerpc64-linux-gnu/fpu_control.h index 78a7a291ac01b829891f52e0c457139281cbb952..db5055a812e59a01925a62a031b0d01e58b6953e 100644 --- a/lib/libc/include/powerpc64-linux-gnu/fpu_control.h +++ b/lib/libc/include/powerpc64-linux-gnu/fpu_control.h @@ -19,6 +19,10 @@ #ifndef _FPU_CONTROL_H #define _FPU_CONTROL_H +#if defined __SPE__ || (defined __NO_FPRS__ && !defined _SOFT_FLOAT) +# error "SPE/e500 is no longer supported" +#endif + #ifdef _SOFT_FLOAT # define _FPU_RESERVED 0xffffffff @@ -28,41 +32,6 @@ typedef unsigned int fpu_control_t; # define _FPU_SETCW(cw) (void) (cw) extern fpu_control_t __fpu_control; -#elif defined __NO_FPRS__ /* e500 */ - -/* rounding control */ -# define _FPU_RC_NEAREST 0x00 /* RECOMMENDED */ -# define _FPU_RC_DOWN 0x03 -# define _FPU_RC_UP 0x02 -# define _FPU_RC_ZERO 0x01 - -/* masking of interrupts */ -# define _FPU_MASK_ZM 0x10 /* zero divide */ -# define _FPU_MASK_OM 0x04 /* overflow */ -# define _FPU_MASK_UM 0x08 /* underflow */ -# define _FPU_MASK_XM 0x40 /* inexact */ -# define _FPU_MASK_IM 0x20 /* invalid operation */ - -# define _FPU_RESERVED 0x00c10080 /* These bits are reserved and not changed. */ - -/* Correct IEEE semantics require traps to be enabled at the hardware - level; the kernel then does the emulation and determines whether - generation of signals from those traps was enabled using prctl. */ -# define _FPU_DEFAULT 0x0000003c /* Default value. */ -# define _FPU_IEEE _FPU_DEFAULT - -/* Type of the control word. */ -typedef unsigned int fpu_control_t; - -/* Macros for accessing the hardware control word. */ -# define _FPU_GETCW(cw) \ - __asm__ volatile ("mfspefscr %0" : "=r" (cw)) -# define _FPU_SETCW(cw) \ - __asm__ volatile ("mtspefscr %0" : : "r" (cw)) - -/* Default control word set at startup. */ -extern fpu_control_t __fpu_control; - #else /* PowerPC 6xx floating-point. */ /* rounding control */ @@ -71,6 +40,8 @@ extern fpu_control_t __fpu_control; # define _FPU_RC_UP 0x02 # define _FPU_RC_ZERO 0x01 +# define _FPU_MASK_RC (_FPU_RC_NEAREST|_FPU_RC_DOWN|_FPU_RC_UP|_FPU_RC_ZERO) + # define _FPU_MASK_NI 0x04 /* non-ieee mode */ /* masking of interrupts */ @@ -96,20 +67,43 @@ typedef unsigned int fpu_control_t; /* Macros for accessing the hardware control word. */ # define _FPU_GETCW(cw) \ ({union { double __d; unsigned long long __ll; } __u; \ - register double __fr; \ - __asm__ ("mffs %0" : "=f" (__fr)); \ - __u.__d = __fr; \ + __asm__ __volatile__("mffs %0" : "=f" (__u.__d)); \ (cw) = (fpu_control_t) __u.__ll; \ (fpu_control_t) __u.__ll; \ }) +# define _FPU_GET_RC_ISA300() \ + ({union { double __d; unsigned long long __ll; } __u; \ + __asm__ __volatile__( \ + ".machine push; .machine \"power9\"; mffsl %0; .machine pop" \ + : "=f" (__u.__d)); \ + (fpu_control_t) (__u.__ll & _FPU_MASK_RC); \ + }) + +# ifdef _ARCH_PWR9 +# define _FPU_GET_RC() _FPU_GET_RC_ISA300() +# elif defined __BUILTIN_CPU_SUPPORTS__ +# define _FPU_GET_RC() \ + ({fpu_control_t __rc; \ + __rc = __glibc_likely (__builtin_cpu_supports ("arch_3_00")) \ + ? _FPU_GET_RC_ISA300 () \ + : _FPU_GETCW (__rc) & _FPU_MASK_RC; \ + __rc; \ + }) +# else +# define _FPU_GET_RC() \ + ({fpu_control_t __rc = _FPU_GETCW (__rc) & _FPU_MASK_RC; \ + __rc; \ + }) +# endif + # define _FPU_SETCW(cw) \ { union { double __d; unsigned long long __ll; } __u; \ register double __fr; \ __u.__ll = 0xfff80000LL << 32; /* This is a QNaN. */ \ __u.__ll |= (cw) & 0xffffffffLL; \ __fr = __u.__d; \ - __asm__ ("mtfsf 255,%0" : : "f" (__fr)); \ + __asm__ __volatile__("mtfsf 255,%0" : : "f" (__fr)); \ } /* Default control word set at startup. */ diff --git a/lib/libc/include/powerpc64-linux-gnu/gnu/stubs-64-v1.h b/lib/libc/include/powerpc64-linux-gnu/gnu/stubs-64-v1.h index f5b3f7db153abd27b767b3c12f5b20f849ae1566..12c0d956e888c32e986e3c565258f46fd89d16d5 100644 --- a/lib/libc/include/powerpc64-linux-gnu/gnu/stubs-64-v1.h +++ b/lib/libc/include/powerpc64-linux-gnu/gnu/stubs-64-v1.h @@ -8,9 +8,7 @@ #endif #define __stub_chflags -#define __stub_fattach #define __stub_fchflags -#define __stub_fdetach #define __stub_gtty #define __stub_lchmod #define __stub_revoke diff --git a/lib/libc/include/powerpc64le-linux-gnu/bits/fenvinline.h b/lib/libc/include/powerpc64le-linux-gnu/bits/fenvinline.h index 1552e48c7aaf868cebfa1356d8c89953eb6a73af..efb8a356e21568176f88b8e80dda9591056f8f3c 100644 --- a/lib/libc/include/powerpc64le-linux-gnu/bits/fenvinline.h +++ b/lib/libc/include/powerpc64le-linux-gnu/bits/fenvinline.h @@ -18,13 +18,36 @@ #if defined __GNUC__ && !defined _SOFT_FLOAT && !defined __NO_FPRS__ -/* Inline definition for fegetround. */ -# define __fegetround() \ - (__extension__ ({ int __fegetround_result; \ - __asm__ __volatile__ \ - ("mcrfs 7,7 ; mfcr %0" \ - : "=r"(__fegetround_result) : : "cr7"); \ - __fegetround_result & 3; })) +/* Inline definitions for fegetround. */ +# define __fegetround_ISA300() \ + (__extension__ ({ \ + union { double __d; unsigned long long __ll; } __u; \ + __asm__ __volatile__ ( \ + ".machine push; .machine \"power9\"; mffsl %0; .machine pop" \ + : "=f" (__u.__d)); \ + __u.__ll & 0x0000000000000003LL; \ + })) + +# define __fegetround_ISA2() \ + (__extension__ ({ \ + int __fegetround_result; \ + __asm__ __volatile__ ("mcrfs 7,7 ; mfcr %0" \ + : "=r"(__fegetround_result) : : "cr7"); \ + __fegetround_result & 3; \ + })) + +# ifdef _ARCH_PWR9 +# define __fegetround() __fegetround_ISA300() +# elif defined __BUILTIN_CPU_SUPPORTS__ +# define __fegetround() \ + (__glibc_likely (__builtin_cpu_supports ("arch_3_00")) \ + ? __fegetround_ISA300() \ + : __fegetround_ISA2() \ + ) +# else +# define __fegetround() __fegetround_ISA2() +# endif + # define fegetround() __fegetround () # ifndef __NO_MATH_INLINES diff --git a/lib/libc/include/powerpc64le-linux-gnu/bits/socket-constants.h b/lib/libc/include/powerpc64le-linux-gnu/bits/socket-constants.h new file mode 100644 index 0000000000000000000000000000000000000000..705f575fe09b97742a7c74d11ae0b378bf3fa4fc --- /dev/null +++ b/lib/libc/include/powerpc64le-linux-gnu/bits/socket-constants.h @@ -0,0 +1,38 @@ +/* Socket constants which vary among Linux architectures. Version for POWER. + Copyright (C) 2019 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#ifndef _SYS_SOCKET_H +# error "Never include directly; use instead." +#endif + +#define SOL_SOCKET 1 +#define SO_ACCEPTCONN 30 +#define SO_BROADCAST 6 +#define SO_DONTROUTE 5 +#define SO_ERROR 4 +#define SO_KEEPALIVE 9 +#define SO_LINGER 13 +#define SO_OOBINLINE 10 +#define SO_RCVBUF 8 +#define SO_RCVLOWAT 16 +#define SO_RCVTIMEO 18 +#define SO_REUSEADDR 2 +#define SO_SNDBUF 7 +#define SO_SNDLOWAT 17 +#define SO_SNDTIMEO 19 +#define SO_TYPE 3 \ No newline at end of file diff --git a/lib/libc/include/powerpc64le-linux-gnu/fpu_control.h b/lib/libc/include/powerpc64le-linux-gnu/fpu_control.h index 78a7a291ac01b829891f52e0c457139281cbb952..db5055a812e59a01925a62a031b0d01e58b6953e 100644 --- a/lib/libc/include/powerpc64le-linux-gnu/fpu_control.h +++ b/lib/libc/include/powerpc64le-linux-gnu/fpu_control.h @@ -19,6 +19,10 @@ #ifndef _FPU_CONTROL_H #define _FPU_CONTROL_H +#if defined __SPE__ || (defined __NO_FPRS__ && !defined _SOFT_FLOAT) +# error "SPE/e500 is no longer supported" +#endif + #ifdef _SOFT_FLOAT # define _FPU_RESERVED 0xffffffff @@ -28,41 +32,6 @@ typedef unsigned int fpu_control_t; # define _FPU_SETCW(cw) (void) (cw) extern fpu_control_t __fpu_control; -#elif defined __NO_FPRS__ /* e500 */ - -/* rounding control */ -# define _FPU_RC_NEAREST 0x00 /* RECOMMENDED */ -# define _FPU_RC_DOWN 0x03 -# define _FPU_RC_UP 0x02 -# define _FPU_RC_ZERO 0x01 - -/* masking of interrupts */ -# define _FPU_MASK_ZM 0x10 /* zero divide */ -# define _FPU_MASK_OM 0x04 /* overflow */ -# define _FPU_MASK_UM 0x08 /* underflow */ -# define _FPU_MASK_XM 0x40 /* inexact */ -# define _FPU_MASK_IM 0x20 /* invalid operation */ - -# define _FPU_RESERVED 0x00c10080 /* These bits are reserved and not changed. */ - -/* Correct IEEE semantics require traps to be enabled at the hardware - level; the kernel then does the emulation and determines whether - generation of signals from those traps was enabled using prctl. */ -# define _FPU_DEFAULT 0x0000003c /* Default value. */ -# define _FPU_IEEE _FPU_DEFAULT - -/* Type of the control word. */ -typedef unsigned int fpu_control_t; - -/* Macros for accessing the hardware control word. */ -# define _FPU_GETCW(cw) \ - __asm__ volatile ("mfspefscr %0" : "=r" (cw)) -# define _FPU_SETCW(cw) \ - __asm__ volatile ("mtspefscr %0" : : "r" (cw)) - -/* Default control word set at startup. */ -extern fpu_control_t __fpu_control; - #else /* PowerPC 6xx floating-point. */ /* rounding control */ @@ -71,6 +40,8 @@ extern fpu_control_t __fpu_control; # define _FPU_RC_UP 0x02 # define _FPU_RC_ZERO 0x01 +# define _FPU_MASK_RC (_FPU_RC_NEAREST|_FPU_RC_DOWN|_FPU_RC_UP|_FPU_RC_ZERO) + # define _FPU_MASK_NI 0x04 /* non-ieee mode */ /* masking of interrupts */ @@ -96,20 +67,43 @@ typedef unsigned int fpu_control_t; /* Macros for accessing the hardware control word. */ # define _FPU_GETCW(cw) \ ({union { double __d; unsigned long long __ll; } __u; \ - register double __fr; \ - __asm__ ("mffs %0" : "=f" (__fr)); \ - __u.__d = __fr; \ + __asm__ __volatile__("mffs %0" : "=f" (__u.__d)); \ (cw) = (fpu_control_t) __u.__ll; \ (fpu_control_t) __u.__ll; \ }) +# define _FPU_GET_RC_ISA300() \ + ({union { double __d; unsigned long long __ll; } __u; \ + __asm__ __volatile__( \ + ".machine push; .machine \"power9\"; mffsl %0; .machine pop" \ + : "=f" (__u.__d)); \ + (fpu_control_t) (__u.__ll & _FPU_MASK_RC); \ + }) + +# ifdef _ARCH_PWR9 +# define _FPU_GET_RC() _FPU_GET_RC_ISA300() +# elif defined __BUILTIN_CPU_SUPPORTS__ +# define _FPU_GET_RC() \ + ({fpu_control_t __rc; \ + __rc = __glibc_likely (__builtin_cpu_supports ("arch_3_00")) \ + ? _FPU_GET_RC_ISA300 () \ + : _FPU_GETCW (__rc) & _FPU_MASK_RC; \ + __rc; \ + }) +# else +# define _FPU_GET_RC() \ + ({fpu_control_t __rc = _FPU_GETCW (__rc) & _FPU_MASK_RC; \ + __rc; \ + }) +# endif + # define _FPU_SETCW(cw) \ { union { double __d; unsigned long long __ll; } __u; \ register double __fr; \ __u.__ll = 0xfff80000LL << 32; /* This is a QNaN. */ \ __u.__ll |= (cw) & 0xffffffffLL; \ __fr = __u.__d; \ - __asm__ ("mtfsf 255,%0" : : "f" (__fr)); \ + __asm__ __volatile__("mtfsf 255,%0" : : "f" (__fr)); \ } /* Default control word set at startup. */ diff --git a/lib/libc/include/powerpc64le-linux-gnu/gnu/stubs-64-v2.h b/lib/libc/include/powerpc64le-linux-gnu/gnu/stubs-64-v2.h index f5b3f7db153abd27b767b3c12f5b20f849ae1566..12c0d956e888c32e986e3c565258f46fd89d16d5 100644 --- a/lib/libc/include/powerpc64le-linux-gnu/gnu/stubs-64-v2.h +++ b/lib/libc/include/powerpc64le-linux-gnu/gnu/stubs-64-v2.h @@ -8,9 +8,7 @@ #endif #define __stub_chflags -#define __stub_fattach #define __stub_fchflags -#define __stub_fdetach #define __stub_gtty #define __stub_lchmod #define __stub_revoke diff --git a/lib/libc/include/riscv64-linux-gnu/gnu/stubs-lp64.h b/lib/libc/include/riscv64-linux-gnu/gnu/stubs-lp64.h index 90477e3afc03b3582faaa99879921fa5ee5fd289..6ac6614fb702c4f61436986523163d21ef1210b6 100644 --- a/lib/libc/include/riscv64-linux-gnu/gnu/stubs-lp64.h +++ b/lib/libc/include/riscv64-linux-gnu/gnu/stubs-lp64.h @@ -13,9 +13,7 @@ #define __stub___compat_query_module #define __stub___compat_uselib #define __stub_chflags -#define __stub_fattach #define __stub_fchflags -#define __stub_fdetach #define __stub_feclearexcept #define __stub_fedisableexcept #define __stub_feenableexcept @@ -33,12 +31,8 @@ #define __stub_fesetround #define __stub_fetestexcept #define __stub_feupdateenv -#define __stub_getmsg -#define __stub_getpmsg #define __stub_gtty #define __stub_lchmod -#define __stub_putmsg -#define __stub_putpmsg #define __stub_revoke #define __stub_setlogin #define __stub_sigreturn diff --git a/lib/libc/include/s390x-linux-gnu/bits/hwcap.h b/lib/libc/include/s390x-linux-gnu/bits/hwcap.h index 87b4bd47c615130eccc83ab9ca5983f7bec7a54e..76ab321e19cea39f5d881c68364b8e4340104331 100644 --- a/lib/libc/include/s390x-linux-gnu/bits/hwcap.h +++ b/lib/libc/include/s390x-linux-gnu/bits/hwcap.h @@ -38,4 +38,8 @@ #define HWCAP_S390_VX 2048 #define HWCAP_S390_VXD 4096 #define HWCAP_S390_VXE 8192 -#define HWCAP_S390_GS 16384 \ No newline at end of file +#define HWCAP_S390_GS 16384 +#define HWCAP_S390_VXRS_EXT2 32768 +#define HWCAP_S390_VXRS_PDE 65536 +#define HWCAP_S390_SORT 131072 +#define HWCAP_S390_DFLT 262144 \ No newline at end of file diff --git a/lib/libc/include/sparc-linux-gnu/bits/socket-constants.h b/lib/libc/include/sparc-linux-gnu/bits/socket-constants.h new file mode 100644 index 0000000000000000000000000000000000000000..8334fc24e4b6e9485599a4e8004bb26b1c31d83d --- /dev/null +++ b/lib/libc/include/sparc-linux-gnu/bits/socket-constants.h @@ -0,0 +1,38 @@ +/* Socket constants which vary among Linux architectures. Version for SPARC. + Copyright (C) 2019 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#ifndef _SYS_SOCKET_H +# error "Never include directly; use instead." +#endif + +#define SOL_SOCKET 65535 +#define SO_ACCEPTCONN 32768 +#define SO_BROADCAST 32 +#define SO_DONTROUTE 16 +#define SO_ERROR 4103 +#define SO_KEEPALIVE 8 +#define SO_LINGER 128 +#define SO_OOBINLINE 256 +#define SO_RCVBUF 4098 +#define SO_RCVLOWAT 2048 +#define SO_RCVTIMEO 8192 +#define SO_REUSEADDR 4 +#define SO_SNDBUF 4097 +#define SO_SNDLOWAT 4096 +#define SO_SNDTIMEO 16384 +#define SO_TYPE 4104 \ No newline at end of file diff --git a/lib/libc/include/sparc-linux-gnu/gnu/stubs-64.h b/lib/libc/include/sparc-linux-gnu/gnu/stubs-64.h deleted file mode 100644 index cab3cfc7601f869957a36a08ba121e66228e344b..0000000000000000000000000000000000000000 --- a/lib/libc/include/sparc-linux-gnu/gnu/stubs-64.h +++ /dev/null @@ -1,26 +0,0 @@ -/* This file is automatically generated. - It defines a symbol `__stub_FUNCTION' for each function - in the C library which is a stub, meaning it will fail - every time called, usually setting errno to ENOSYS. */ - -#ifdef _LIBC - #error Applications may not define the macro _LIBC -#endif - -#define __stub_chflags -#define __stub_fattach -#define __stub_fchflags -#define __stub_fdetach -#define __stub_getmsg -#define __stub_getpmsg -#define __stub_gtty -#define __stub_lchmod -#define __stub_pkey_alloc -#define __stub_pkey_free -#define __stub_putmsg -#define __stub_putpmsg -#define __stub_revoke -#define __stub_setlogin -#define __stub_sigreturn -#define __stub_sstk -#define __stub_stty \ No newline at end of file diff --git a/lib/libc/include/sparcv9-linux-gnu/bits/socket-constants.h b/lib/libc/include/sparcv9-linux-gnu/bits/socket-constants.h new file mode 100644 index 0000000000000000000000000000000000000000..8334fc24e4b6e9485599a4e8004bb26b1c31d83d --- /dev/null +++ b/lib/libc/include/sparcv9-linux-gnu/bits/socket-constants.h @@ -0,0 +1,38 @@ +/* Socket constants which vary among Linux architectures. Version for SPARC. + Copyright (C) 2019 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#ifndef _SYS_SOCKET_H +# error "Never include directly; use instead." +#endif + +#define SOL_SOCKET 65535 +#define SO_ACCEPTCONN 32768 +#define SO_BROADCAST 32 +#define SO_DONTROUTE 16 +#define SO_ERROR 4103 +#define SO_KEEPALIVE 8 +#define SO_LINGER 128 +#define SO_OOBINLINE 256 +#define SO_RCVBUF 4098 +#define SO_RCVLOWAT 2048 +#define SO_RCVTIMEO 8192 +#define SO_REUSEADDR 4 +#define SO_SNDBUF 4097 +#define SO_SNDLOWAT 4096 +#define SO_SNDTIMEO 16384 +#define SO_TYPE 4104 \ No newline at end of file diff --git a/lib/libc/include/sparcv9-linux-gnu/gnu/stubs-32.h b/lib/libc/include/sparcv9-linux-gnu/gnu/stubs-32.h deleted file mode 100644 index cab3cfc7601f869957a36a08ba121e66228e344b..0000000000000000000000000000000000000000 --- a/lib/libc/include/sparcv9-linux-gnu/gnu/stubs-32.h +++ /dev/null @@ -1,26 +0,0 @@ -/* This file is automatically generated. - It defines a symbol `__stub_FUNCTION' for each function - in the C library which is a stub, meaning it will fail - every time called, usually setting errno to ENOSYS. */ - -#ifdef _LIBC - #error Applications may not define the macro _LIBC -#endif - -#define __stub_chflags -#define __stub_fattach -#define __stub_fchflags -#define __stub_fdetach -#define __stub_getmsg -#define __stub_getpmsg -#define __stub_gtty -#define __stub_lchmod -#define __stub_pkey_alloc -#define __stub_pkey_free -#define __stub_putmsg -#define __stub_putpmsg -#define __stub_revoke -#define __stub_setlogin -#define __stub_sigreturn -#define __stub_sstk -#define __stub_stty \ No newline at end of file diff --git a/lib/libc/include/x86_64-linux-gnu/bits/math-vector-fortran.h b/lib/libc/include/x86_64-linux-gnu/finclude/math-vector-fortran.h similarity index 100% rename from lib/libc/include/x86_64-linux-gnu/bits/math-vector-fortran.h rename to lib/libc/include/x86_64-linux-gnu/finclude/math-vector-fortran.h diff --git a/lib/libc/include/x86_64-linux-gnu/gnu/stubs-64.h b/lib/libc/include/x86_64-linux-gnu/gnu/stubs-64.h index e3f5d47f5f17ab365ce1ef1b1db69f072391004f..5ce8c64bbad318f500673d421b3bb09251156df4 100644 --- a/lib/libc/include/x86_64-linux-gnu/gnu/stubs-64.h +++ b/lib/libc/include/x86_64-linux-gnu/gnu/stubs-64.h @@ -9,13 +9,9 @@ #define __stub___compat_bdflush #define __stub_chflags -#define __stub_fattach #define __stub_fchflags -#define __stub_fdetach -#define __stub_getmsg #define __stub_gtty #define __stub_lchmod -#define __stub_putmsg #define __stub_revoke #define __stub_setlogin #define __stub_sigreturn diff --git a/lib/libc/include/x86_64-linux-gnu/sys/io.h b/lib/libc/include/x86_64-linux-gnu/sys/io.h deleted file mode 100644 index c27e96f4af7aab65cf910cec2ef8c9a9d42487e4..0000000000000000000000000000000000000000 --- a/lib/libc/include/x86_64-linux-gnu/sys/io.h +++ /dev/null @@ -1,183 +0,0 @@ -/* Copyright (C) 1996-2019 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - . */ - -#ifndef _SYS_IO_H -#define _SYS_IO_H 1 - -#include - -__BEGIN_DECLS - -/* If TURN_ON is TRUE, request for permission to do direct i/o on the - port numbers in the range [FROM,FROM+NUM-1]. Otherwise, turn I/O - permission off for that range. This call requires root privileges. - - Portability note: not all Linux platforms support this call. Most - platforms based on the PC I/O architecture probably will, however. - E.g., Linux/Alpha for Alpha PCs supports this. */ -extern int ioperm (unsigned long int __from, unsigned long int __num, - int __turn_on) __THROW; - -/* Set the I/O privilege level to LEVEL. If LEVEL>3, permission to - access any I/O port is granted. This call requires root - privileges. */ -extern int iopl (int __level) __THROW; - -#if defined __GNUC__ && __GNUC__ >= 2 - -static __inline unsigned char -inb (unsigned short int __port) -{ - unsigned char _v; - - __asm__ __volatile__ ("inb %w1,%0":"=a" (_v):"Nd" (__port)); - return _v; -} - -static __inline unsigned char -inb_p (unsigned short int __port) -{ - unsigned char _v; - - __asm__ __volatile__ ("inb %w1,%0\noutb %%al,$0x80":"=a" (_v):"Nd" (__port)); - return _v; -} - -static __inline unsigned short int -inw (unsigned short int __port) -{ - unsigned short _v; - - __asm__ __volatile__ ("inw %w1,%0":"=a" (_v):"Nd" (__port)); - return _v; -} - -static __inline unsigned short int -inw_p (unsigned short int __port) -{ - unsigned short int _v; - - __asm__ __volatile__ ("inw %w1,%0\noutb %%al,$0x80":"=a" (_v):"Nd" (__port)); - return _v; -} - -static __inline unsigned int -inl (unsigned short int __port) -{ - unsigned int _v; - - __asm__ __volatile__ ("inl %w1,%0":"=a" (_v):"Nd" (__port)); - return _v; -} - -static __inline unsigned int -inl_p (unsigned short int __port) -{ - unsigned int _v; - __asm__ __volatile__ ("inl %w1,%0\noutb %%al,$0x80":"=a" (_v):"Nd" (__port)); - return _v; -} - -static __inline void -outb (unsigned char __value, unsigned short int __port) -{ - __asm__ __volatile__ ("outb %b0,%w1": :"a" (__value), "Nd" (__port)); -} - -static __inline void -outb_p (unsigned char __value, unsigned short int __port) -{ - __asm__ __volatile__ ("outb %b0,%w1\noutb %%al,$0x80": :"a" (__value), - "Nd" (__port)); -} - -static __inline void -outw (unsigned short int __value, unsigned short int __port) -{ - __asm__ __volatile__ ("outw %w0,%w1": :"a" (__value), "Nd" (__port)); - -} - -static __inline void -outw_p (unsigned short int __value, unsigned short int __port) -{ - __asm__ __volatile__ ("outw %w0,%w1\noutb %%al,$0x80": :"a" (__value), - "Nd" (__port)); -} - -static __inline void -outl (unsigned int __value, unsigned short int __port) -{ - __asm__ __volatile__ ("outl %0,%w1": :"a" (__value), "Nd" (__port)); -} - -static __inline void -outl_p (unsigned int __value, unsigned short int __port) -{ - __asm__ __volatile__ ("outl %0,%w1\noutb %%al,$0x80": :"a" (__value), - "Nd" (__port)); -} - -static __inline void -insb (unsigned short int __port, void *__addr, unsigned long int __count) -{ - __asm__ __volatile__ ("cld ; rep ; insb":"=D" (__addr), "=c" (__count) - :"d" (__port), "0" (__addr), "1" (__count)); -} - -static __inline void -insw (unsigned short int __port, void *__addr, unsigned long int __count) -{ - __asm__ __volatile__ ("cld ; rep ; insw":"=D" (__addr), "=c" (__count) - :"d" (__port), "0" (__addr), "1" (__count)); -} - -static __inline void -insl (unsigned short int __port, void *__addr, unsigned long int __count) -{ - __asm__ __volatile__ ("cld ; rep ; insl":"=D" (__addr), "=c" (__count) - :"d" (__port), "0" (__addr), "1" (__count)); -} - -static __inline void -outsb (unsigned short int __port, const void *__addr, - unsigned long int __count) -{ - __asm__ __volatile__ ("cld ; rep ; outsb":"=S" (__addr), "=c" (__count) - :"d" (__port), "0" (__addr), "1" (__count)); -} - -static __inline void -outsw (unsigned short int __port, const void *__addr, - unsigned long int __count) -{ - __asm__ __volatile__ ("cld ; rep ; outsw":"=S" (__addr), "=c" (__count) - :"d" (__port), "0" (__addr), "1" (__count)); -} - -static __inline void -outsl (unsigned short int __port, const void *__addr, - unsigned long int __count) -{ - __asm__ __volatile__ ("cld ; rep ; outsl":"=S" (__addr), "=c" (__count) - :"d" (__port), "0" (__addr), "1" (__count)); -} - -#endif /* GNU C */ - -__END_DECLS -#endif /* _SYS_IO_H */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-linux-gnux32/bits/xtitypes.h b/lib/libc/include/x86_64-linux-gnux32/bits/xtitypes.h deleted file mode 100644 index 1eb0c84d8f7da38decba2447f2091bcbac71ca9d..0000000000000000000000000000000000000000 --- a/lib/libc/include/x86_64-linux-gnux32/bits/xtitypes.h +++ /dev/null @@ -1,33 +0,0 @@ -/* bits/xtitypes.h -- Define some types used by . x86-64. - Copyright (C) 2002-2019 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - . */ - -#ifndef _STROPTS_H -# error "Never include directly; use instead." -#endif - -#ifndef _BITS_XTITYPES_H -#define _BITS_XTITYPES_H 1 - -#include - -/* This type is used by some structs in . */ -typedef __SLONG32_TYPE __t_scalar_t; -typedef __ULONG32_TYPE __t_uscalar_t; - - -#endif /* bits/xtitypes.h */ \ No newline at end of file diff --git a/lib/libc/include/x86_64-linux-gnux32/bits/math-vector-fortran.h b/lib/libc/include/x86_64-linux-gnux32/finclude/math-vector-fortran.h similarity index 100% rename from lib/libc/include/x86_64-linux-gnux32/bits/math-vector-fortran.h rename to lib/libc/include/x86_64-linux-gnux32/finclude/math-vector-fortran.h diff --git a/lib/libc/include/x86_64-linux-gnux32/gnu/stubs-x32.h b/lib/libc/include/x86_64-linux-gnux32/gnu/stubs-x32.h index 34fab3804addf33cd9142b4462b752746cfe0bcc..9f943854b07f1094d20f08fc8e9cd81f8e4e5eb1 100644 --- a/lib/libc/include/x86_64-linux-gnux32/gnu/stubs-x32.h +++ b/lib/libc/include/x86_64-linux-gnux32/gnu/stubs-x32.h @@ -14,13 +14,9 @@ #define __stub___compat_query_module #define __stub___compat_uselib #define __stub_chflags -#define __stub_fattach #define __stub_fchflags -#define __stub_fdetach -#define __stub_getmsg #define __stub_gtty #define __stub_lchmod -#define __stub_putmsg #define __stub_revoke #define __stub_setlogin #define __stub_sigreturn diff --git a/lib/libc/include/x86_64-linux-gnux32/sys/io.h b/lib/libc/include/x86_64-linux-gnux32/sys/io.h deleted file mode 100644 index c27e96f4af7aab65cf910cec2ef8c9a9d42487e4..0000000000000000000000000000000000000000 --- a/lib/libc/include/x86_64-linux-gnux32/sys/io.h +++ /dev/null @@ -1,183 +0,0 @@ -/* Copyright (C) 1996-2019 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - . */ - -#ifndef _SYS_IO_H -#define _SYS_IO_H 1 - -#include - -__BEGIN_DECLS - -/* If TURN_ON is TRUE, request for permission to do direct i/o on the - port numbers in the range [FROM,FROM+NUM-1]. Otherwise, turn I/O - permission off for that range. This call requires root privileges. - - Portability note: not all Linux platforms support this call. Most - platforms based on the PC I/O architecture probably will, however. - E.g., Linux/Alpha for Alpha PCs supports this. */ -extern int ioperm (unsigned long int __from, unsigned long int __num, - int __turn_on) __THROW; - -/* Set the I/O privilege level to LEVEL. If LEVEL>3, permission to - access any I/O port is granted. This call requires root - privileges. */ -extern int iopl (int __level) __THROW; - -#if defined __GNUC__ && __GNUC__ >= 2 - -static __inline unsigned char -inb (unsigned short int __port) -{ - unsigned char _v; - - __asm__ __volatile__ ("inb %w1,%0":"=a" (_v):"Nd" (__port)); - return _v; -} - -static __inline unsigned char -inb_p (unsigned short int __port) -{ - unsigned char _v; - - __asm__ __volatile__ ("inb %w1,%0\noutb %%al,$0x80":"=a" (_v):"Nd" (__port)); - return _v; -} - -static __inline unsigned short int -inw (unsigned short int __port) -{ - unsigned short _v; - - __asm__ __volatile__ ("inw %w1,%0":"=a" (_v):"Nd" (__port)); - return _v; -} - -static __inline unsigned short int -inw_p (unsigned short int __port) -{ - unsigned short int _v; - - __asm__ __volatile__ ("inw %w1,%0\noutb %%al,$0x80":"=a" (_v):"Nd" (__port)); - return _v; -} - -static __inline unsigned int -inl (unsigned short int __port) -{ - unsigned int _v; - - __asm__ __volatile__ ("inl %w1,%0":"=a" (_v):"Nd" (__port)); - return _v; -} - -static __inline unsigned int -inl_p (unsigned short int __port) -{ - unsigned int _v; - __asm__ __volatile__ ("inl %w1,%0\noutb %%al,$0x80":"=a" (_v):"Nd" (__port)); - return _v; -} - -static __inline void -outb (unsigned char __value, unsigned short int __port) -{ - __asm__ __volatile__ ("outb %b0,%w1": :"a" (__value), "Nd" (__port)); -} - -static __inline void -outb_p (unsigned char __value, unsigned short int __port) -{ - __asm__ __volatile__ ("outb %b0,%w1\noutb %%al,$0x80": :"a" (__value), - "Nd" (__port)); -} - -static __inline void -outw (unsigned short int __value, unsigned short int __port) -{ - __asm__ __volatile__ ("outw %w0,%w1": :"a" (__value), "Nd" (__port)); - -} - -static __inline void -outw_p (unsigned short int __value, unsigned short int __port) -{ - __asm__ __volatile__ ("outw %w0,%w1\noutb %%al,$0x80": :"a" (__value), - "Nd" (__port)); -} - -static __inline void -outl (unsigned int __value, unsigned short int __port) -{ - __asm__ __volatile__ ("outl %0,%w1": :"a" (__value), "Nd" (__port)); -} - -static __inline void -outl_p (unsigned int __value, unsigned short int __port) -{ - __asm__ __volatile__ ("outl %0,%w1\noutb %%al,$0x80": :"a" (__value), - "Nd" (__port)); -} - -static __inline void -insb (unsigned short int __port, void *__addr, unsigned long int __count) -{ - __asm__ __volatile__ ("cld ; rep ; insb":"=D" (__addr), "=c" (__count) - :"d" (__port), "0" (__addr), "1" (__count)); -} - -static __inline void -insw (unsigned short int __port, void *__addr, unsigned long int __count) -{ - __asm__ __volatile__ ("cld ; rep ; insw":"=D" (__addr), "=c" (__count) - :"d" (__port), "0" (__addr), "1" (__count)); -} - -static __inline void -insl (unsigned short int __port, void *__addr, unsigned long int __count) -{ - __asm__ __volatile__ ("cld ; rep ; insl":"=D" (__addr), "=c" (__count) - :"d" (__port), "0" (__addr), "1" (__count)); -} - -static __inline void -outsb (unsigned short int __port, const void *__addr, - unsigned long int __count) -{ - __asm__ __volatile__ ("cld ; rep ; outsb":"=S" (__addr), "=c" (__count) - :"d" (__port), "0" (__addr), "1" (__count)); -} - -static __inline void -outsw (unsigned short int __port, const void *__addr, - unsigned long int __count) -{ - __asm__ __volatile__ ("cld ; rep ; outsw":"=S" (__addr), "=c" (__count) - :"d" (__port), "0" (__addr), "1" (__count)); -} - -static __inline void -outsl (unsigned short int __port, const void *__addr, - unsigned long int __count) -{ - __asm__ __volatile__ ("cld ; rep ; outsl":"=S" (__addr), "=c" (__count) - :"d" (__port), "0" (__addr), "1" (__count)); -} - -#endif /* GNU C */ - -__END_DECLS -#endif /* _SYS_IO_H */ \ No newline at end of file -- 2.54.0 From b21ad07767822070903633476f74f167c1793758 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sat, 7 Sep 2019 15:04:09 -0400 Subject: [PATCH 59/80] update glibc ABI lists to 2.30 --- lib/libc/glibc/abi.txt | 330 ++++++++++++++++++++++++++++++++++++++++ lib/libc/glibc/fns.txt | 22 +++ lib/libc/glibc/vers.txt | 1 + tools/update_glibc.zig | 2 +- 4 files changed, 354 insertions(+), 1 deletion(-) diff --git a/lib/libc/glibc/abi.txt b/lib/libc/glibc/abi.txt index 244596c4e32606698c63b57eb1938603284679aa..c2a19e8c910c10c7759cfbbc641b1d63df311f11 100644 --- a/lib/libc/glibc/abi.txt +++ b/lib/libc/glibc/abi.txt @@ -514,6 +514,7 @@ aarch64-linux-gnu aarch64_be-linux-gnu 29 29 29 + 29 29 @@ -655,6 +656,18 @@ aarch64-linux-gnu aarch64_be-linux-gnu + + + + + + + + + + + + @@ -1928,6 +1941,7 @@ aarch64-linux-gnu aarch64_be-linux-gnu 29 29 29 +40 29 29 29 @@ -2048,6 +2062,7 @@ aarch64-linux-gnu aarch64_be-linux-gnu 29 29 29 +40 29 29 29 @@ -2721,6 +2736,7 @@ aarch64-linux-gnu aarch64_be-linux-gnu 29 29 29 +40 29 29 29 @@ -2749,6 +2765,7 @@ aarch64-linux-gnu aarch64_be-linux-gnu 29 29 29 +40 29 29 29 @@ -2776,6 +2793,8 @@ aarch64-linux-gnu aarch64_be-linux-gnu 29 29 29 +40 +40 29 29 29 @@ -3002,6 +3021,7 @@ aarch64-linux-gnu aarch64_be-linux-gnu 29 29 29 +40 29 29 29 @@ -3370,6 +3390,7 @@ aarch64-linux-gnu aarch64_be-linux-gnu 37 37 29 +40 38 38 38 @@ -3443,6 +3464,7 @@ aarch64-linux-gnu aarch64_be-linux-gnu 29 29 29 +40 29 29 29 @@ -4218,6 +4240,7 @@ s390x-linux-gnu 5 5 5 + 27 27 @@ -4330,12 +4353,18 @@ s390x-linux-gnu 16 16 16 +40 +40 16 38 38 38 16 38 +40 +40 +40 +40 16 16 16 @@ -4356,6 +4385,8 @@ s390x-linux-gnu 16 16 16 +40 +40 16 16 16 @@ -4368,8 +4399,12 @@ s390x-linux-gnu 16 16 16 +40 +40 16 16 +40 +40 16 16 5 @@ -5632,6 +5667,7 @@ s390x-linux-gnu 5 5 5 +40 5 5 5 @@ -5752,6 +5788,7 @@ s390x-linux-gnu 5 5 5 +40 5 5 5 @@ -6425,6 +6462,7 @@ s390x-linux-gnu 5 5 5 13 +40 5 13 5 13 5 13 @@ -6453,6 +6491,7 @@ s390x-linux-gnu 5 5 5 +40 24 16 5 @@ -6480,6 +6519,8 @@ s390x-linux-gnu 16 5 5 +40 +40 5 5 5 @@ -6706,6 +6747,7 @@ s390x-linux-gnu 5 5 5 +40 5 5 5 @@ -7074,6 +7116,7 @@ s390x-linux-gnu 37 37 5 16 +40 38 38 38 @@ -7147,6 +7190,7 @@ s390x-linux-gnu 5 5 5 +40 5 5 5 @@ -7922,6 +7966,7 @@ arm-linux-gnueabi armeb-linux-gnueabi arm-linux-gnueabihf armeb-linux-gnueabihf 16 16 16 + 27 27 @@ -8063,6 +8108,18 @@ arm-linux-gnueabi armeb-linux-gnueabi arm-linux-gnueabihf armeb-linux-gnueabihf + + + + + + + + + + + + @@ -9336,6 +9393,7 @@ arm-linux-gnueabi armeb-linux-gnueabi arm-linux-gnueabihf armeb-linux-gnueabihf 16 16 16 +40 16 16 16 @@ -9456,6 +9514,7 @@ arm-linux-gnueabi armeb-linux-gnueabi arm-linux-gnueabihf armeb-linux-gnueabihf 16 16 16 +40 16 16 16 @@ -10129,6 +10188,7 @@ arm-linux-gnueabi armeb-linux-gnueabi arm-linux-gnueabihf armeb-linux-gnueabihf 16 16 16 +40 16 16 16 @@ -10157,6 +10217,7 @@ arm-linux-gnueabi armeb-linux-gnueabi arm-linux-gnueabihf armeb-linux-gnueabihf 16 16 16 +40 24 16 16 @@ -10184,6 +10245,8 @@ arm-linux-gnueabi armeb-linux-gnueabi arm-linux-gnueabihf armeb-linux-gnueabihf 16 16 16 +40 +40 16 16 16 @@ -10410,6 +10473,7 @@ arm-linux-gnueabi armeb-linux-gnueabi arm-linux-gnueabihf armeb-linux-gnueabihf 16 16 16 +40 16 16 16 @@ -10778,6 +10842,7 @@ arm-linux-gnueabi armeb-linux-gnueabi arm-linux-gnueabihf armeb-linux-gnueabihf 37 16 +40 38 38 38 @@ -10851,6 +10916,7 @@ arm-linux-gnueabi armeb-linux-gnueabi arm-linux-gnueabihf armeb-linux-gnueabihf 16 16 16 +40 16 16 16 @@ -11626,6 +11692,7 @@ sparc-linux-gnu sparcel-linux-gnu 1 0 0 +3 27 27 @@ -11738,12 +11805,18 @@ sparc-linux-gnu sparcel-linux-gnu 16 16 16 +40 +40 16 38 38 38 16 38 +40 +40 +40 +40 16 16 16 @@ -11764,6 +11837,8 @@ sparc-linux-gnu sparcel-linux-gnu 16 16 16 +40 +40 16 16 16 @@ -11776,8 +11851,12 @@ sparc-linux-gnu sparcel-linux-gnu 16 16 16 +40 +40 16 16 +40 +40 16 16 0 @@ -13040,6 +13119,7 @@ sparc-linux-gnu sparcel-linux-gnu 1 1 0 +40 0 5 0 @@ -13160,6 +13240,7 @@ sparc-linux-gnu sparcel-linux-gnu 0 3 0 0 +40 0 0 0 @@ -13833,6 +13914,7 @@ sparc-linux-gnu sparcel-linux-gnu 5 0 0 13 +40 0 13 0 13 0 13 @@ -13861,6 +13943,7 @@ sparc-linux-gnu sparcel-linux-gnu 0 0 0 +40 24 16 0 @@ -13888,6 +13971,8 @@ sparc-linux-gnu sparcel-linux-gnu 16 1 0 +40 +40 1 1 1 @@ -14114,6 +14199,7 @@ sparc-linux-gnu sparcel-linux-gnu 0 0 0 +40 2 0 1 0 1 @@ -14482,6 +14568,7 @@ sparc-linux-gnu sparcel-linux-gnu 37 37 1 16 +40 38 38 38 @@ -14555,6 +14642,7 @@ sparc-linux-gnu sparcel-linux-gnu 0 0 0 +40 0 0 0 @@ -15330,6 +15418,7 @@ sparcv9-linux-gnu 5 5 5 + 27 27 @@ -15471,6 +15560,18 @@ sparcv9-linux-gnu + + + + + + + + + + + + @@ -16744,6 +16845,7 @@ sparcv9-linux-gnu 5 5 5 +40 5 5 5 @@ -16864,6 +16966,7 @@ sparcv9-linux-gnu 5 5 5 +40 5 5 5 @@ -17537,6 +17640,7 @@ sparcv9-linux-gnu 5 5 5 13 +40 5 13 5 13 5 13 @@ -17565,6 +17669,7 @@ sparcv9-linux-gnu 5 5 5 +40 24 16 5 @@ -17592,6 +17697,8 @@ sparcv9-linux-gnu 16 5 5 +40 +40 5 5 5 @@ -17818,6 +17925,7 @@ sparcv9-linux-gnu 5 5 5 +40 5 5 5 @@ -18186,6 +18294,7 @@ sparcv9-linux-gnu 37 37 5 +40 38 38 38 @@ -18259,6 +18368,7 @@ sparcv9-linux-gnu 5 5 5 +40 5 5 5 @@ -19034,6 +19144,7 @@ mips64el-linux-gnuabi64 mips64-linux-gnuabi64 5 0 0 + 27 27 @@ -19175,6 +19286,18 @@ mips64el-linux-gnuabi64 mips64-linux-gnuabi64 + + + + + + + + + + + + @@ -20448,6 +20571,7 @@ mips64el-linux-gnuabi64 mips64-linux-gnuabi64 5 5 0 +40 0 5 0 @@ -20568,6 +20692,7 @@ mips64el-linux-gnuabi64 mips64-linux-gnuabi64 0 5 0 0 +40 0 0 0 @@ -21241,6 +21366,7 @@ mips64el-linux-gnuabi64 mips64-linux-gnuabi64 5 0 0 13 +40 0 13 0 13 0 13 @@ -21269,6 +21395,7 @@ mips64el-linux-gnuabi64 mips64-linux-gnuabi64 0 0 0 +40 24 16 0 @@ -21296,6 +21423,8 @@ mips64el-linux-gnuabi64 mips64-linux-gnuabi64 16 5 0 +40 +40 5 5 5 @@ -21522,6 +21651,7 @@ mips64el-linux-gnuabi64 mips64-linux-gnuabi64 0 0 0 +40 5 0 5 0 5 @@ -21890,6 +22020,7 @@ mips64el-linux-gnuabi64 mips64-linux-gnuabi64 37 37 5 +40 38 38 38 @@ -21963,6 +22094,7 @@ mips64el-linux-gnuabi64 mips64-linux-gnuabi64 0 0 0 +40 0 0 0 @@ -22738,6 +22870,7 @@ mips64el-linux-gnuabin32 mips64-linux-gnuabin32 5 0 0 + 27 27 @@ -22879,6 +23012,18 @@ mips64el-linux-gnuabin32 mips64-linux-gnuabin32 + + + + + + + + + + + + @@ -24152,6 +24297,7 @@ mips64el-linux-gnuabin32 mips64-linux-gnuabin32 5 5 0 +40 0 5 0 @@ -24272,6 +24418,7 @@ mips64el-linux-gnuabin32 mips64-linux-gnuabin32 0 5 0 0 +40 0 0 0 @@ -24945,6 +25092,7 @@ mips64el-linux-gnuabin32 mips64-linux-gnuabin32 5 0 0 13 +40 0 13 0 13 0 13 @@ -24973,6 +25121,7 @@ mips64el-linux-gnuabin32 mips64-linux-gnuabin32 0 0 0 +40 24 16 0 @@ -25000,6 +25149,8 @@ mips64el-linux-gnuabin32 mips64-linux-gnuabin32 16 5 0 +40 +40 5 5 5 @@ -25226,6 +25377,7 @@ mips64el-linux-gnuabin32 mips64-linux-gnuabin32 0 0 0 +40 5 0 5 0 5 @@ -25594,6 +25746,7 @@ mips64el-linux-gnuabin32 mips64-linux-gnuabin32 37 37 5 +40 38 38 38 @@ -25667,6 +25820,7 @@ mips64el-linux-gnuabin32 mips64-linux-gnuabin32 0 0 0 +40 0 0 0 @@ -26442,6 +26596,7 @@ mipsel-linux-gnueabihf mips-linux-gnueabihf 5 0 0 + 27 27 @@ -26583,6 +26738,18 @@ mipsel-linux-gnueabihf mips-linux-gnueabihf + + + + + + + + + + + + @@ -27856,6 +28023,7 @@ mipsel-linux-gnueabihf mips-linux-gnueabihf 5 5 0 +40 0 5 0 @@ -27976,6 +28144,7 @@ mipsel-linux-gnueabihf mips-linux-gnueabihf 0 5 0 0 +40 0 0 0 @@ -28649,6 +28818,7 @@ mipsel-linux-gnueabihf mips-linux-gnueabihf 5 0 0 13 +40 0 13 0 13 0 13 @@ -28677,6 +28847,7 @@ mipsel-linux-gnueabihf mips-linux-gnueabihf 0 0 0 +40 24 16 0 @@ -28704,6 +28875,8 @@ mipsel-linux-gnueabihf mips-linux-gnueabihf 16 5 0 +40 +40 5 5 5 @@ -28930,6 +29103,7 @@ mipsel-linux-gnueabihf mips-linux-gnueabihf 0 0 0 +40 5 0 5 0 5 @@ -29298,6 +29472,7 @@ mipsel-linux-gnueabihf mips-linux-gnueabihf 37 5 +40 38 38 38 @@ -29371,6 +29546,7 @@ mipsel-linux-gnueabihf mips-linux-gnueabihf 0 0 0 +40 0 0 0 @@ -30146,6 +30322,7 @@ mipsel-linux-gnueabi mips-linux-gnueabi 5 0 0 + 27 27 @@ -30287,6 +30464,18 @@ mipsel-linux-gnueabi mips-linux-gnueabi + + + + + + + + + + + + @@ -31560,6 +31749,7 @@ mipsel-linux-gnueabi mips-linux-gnueabi 5 5 0 +40 0 5 0 @@ -31680,6 +31870,7 @@ mipsel-linux-gnueabi mips-linux-gnueabi 0 5 0 0 +40 0 0 0 @@ -32353,6 +32544,7 @@ mipsel-linux-gnueabi mips-linux-gnueabi 5 0 0 13 +40 0 13 0 13 0 13 @@ -32381,6 +32573,7 @@ mipsel-linux-gnueabi mips-linux-gnueabi 0 0 0 +40 24 16 0 @@ -32408,6 +32601,8 @@ mipsel-linux-gnueabi mips-linux-gnueabi 16 5 0 +40 +40 5 5 5 @@ -32634,6 +32829,7 @@ mipsel-linux-gnueabi mips-linux-gnueabi 0 0 0 +40 5 0 5 0 5 @@ -33002,6 +33198,7 @@ mipsel-linux-gnueabi mips-linux-gnueabi 37 5 +40 38 38 38 @@ -33075,6 +33272,7 @@ mipsel-linux-gnueabi mips-linux-gnueabi 0 0 0 +40 0 0 0 @@ -33850,6 +34048,7 @@ x86_64-linux-gnu 10 10 10 + 27 36 27 @@ -33991,6 +34190,18 @@ x86_64-linux-gnu + + + + + + + + + + + + @@ -35264,6 +35475,7 @@ x86_64-linux-gnu 10 10 10 +40 10 10 10 @@ -35384,6 +35596,7 @@ x86_64-linux-gnu 10 10 10 +40 10 10 10 @@ -36057,6 +36270,7 @@ x86_64-linux-gnu 10 10 10 13 +40 10 13 10 13 10 13 @@ -36085,6 +36299,7 @@ x86_64-linux-gnu 10 10 10 +40 24 16 10 @@ -36112,6 +36327,8 @@ x86_64-linux-gnu 16 10 10 +40 +40 10 10 10 @@ -36338,6 +36555,7 @@ x86_64-linux-gnu 10 10 10 +40 10 10 10 @@ -36706,6 +36924,7 @@ x86_64-linux-gnu 37 37 10 +40 38 38 38 @@ -36779,6 +36998,7 @@ x86_64-linux-gnu 10 10 10 +40 10 10 10 @@ -37554,6 +37774,7 @@ x86_64-linux-gnux32 28 28 28 + 28 36 28 @@ -37695,6 +37916,18 @@ x86_64-linux-gnux32 + + + + + + + + + + + + @@ -38968,6 +39201,7 @@ x86_64-linux-gnux32 28 28 28 +40 28 28 28 @@ -39088,6 +39322,7 @@ x86_64-linux-gnux32 28 28 28 +40 28 28 28 @@ -39761,6 +39996,7 @@ x86_64-linux-gnux32 28 28 28 +40 28 28 28 @@ -39789,6 +40025,7 @@ x86_64-linux-gnux32 28 28 28 +40 28 28 28 @@ -39816,6 +40053,8 @@ x86_64-linux-gnux32 28 28 28 +40 +40 28 28 28 @@ -40042,6 +40281,7 @@ x86_64-linux-gnux32 28 28 28 +40 28 28 28 @@ -40410,6 +40650,7 @@ x86_64-linux-gnux32 37 37 28 +40 38 38 38 @@ -40483,6 +40724,7 @@ x86_64-linux-gnux32 28 28 28 +40 28 28 28 @@ -41258,6 +41500,7 @@ i386-linux-gnu 1 0 0 +3 27 36 27 @@ -41399,6 +41642,18 @@ i386-linux-gnu + + + + + + + + + + + + @@ -42672,6 +42927,7 @@ i386-linux-gnu 1 1 0 +40 0 5 0 @@ -42792,6 +43048,7 @@ i386-linux-gnu 0 3 0 0 +40 0 0 0 @@ -43465,6 +43722,7 @@ i386-linux-gnu 5 0 0 13 +40 0 13 0 13 0 13 @@ -43493,6 +43751,7 @@ i386-linux-gnu 0 0 0 +40 24 16 0 @@ -43520,6 +43779,8 @@ i386-linux-gnu 16 1 0 +40 +40 1 1 1 @@ -43746,6 +44007,7 @@ i386-linux-gnu 0 0 0 +40 2 0 1 0 1 @@ -44114,6 +44376,7 @@ i386-linux-gnu 37 37 1 +40 38 38 38 @@ -44187,6 +44450,7 @@ i386-linux-gnu 0 0 0 +40 0 0 0 @@ -44962,6 +45226,7 @@ powerpc64le-linux-gnu 29 29 29 + 29 36 29 @@ -45074,12 +45339,18 @@ powerpc64le-linux-gnu 29 29 29 +40 +40 29 38 38 38 29 38 +40 +40 +40 +40 29 29 29 @@ -45100,6 +45371,8 @@ powerpc64le-linux-gnu 29 29 29 +40 +40 29 29 29 @@ -45112,8 +45385,12 @@ powerpc64le-linux-gnu 29 29 29 +40 +40 29 29 +40 +40 29 29 29 @@ -46376,6 +46653,7 @@ powerpc64le-linux-gnu 29 29 29 +40 29 29 29 @@ -46496,6 +46774,7 @@ powerpc64le-linux-gnu 29 29 29 +40 29 29 29 @@ -47169,6 +47448,7 @@ powerpc64le-linux-gnu 29 29 29 +40 29 29 29 @@ -47197,6 +47477,7 @@ powerpc64le-linux-gnu 29 29 29 +40 29 29 29 @@ -47224,6 +47505,8 @@ powerpc64le-linux-gnu 29 29 29 +40 +40 29 29 29 @@ -47450,6 +47733,7 @@ powerpc64le-linux-gnu 29 29 29 +40 29 29 29 @@ -47818,6 +48102,7 @@ powerpc64le-linux-gnu 37 37 29 +40 38 38 38 @@ -47891,6 +48176,7 @@ powerpc64le-linux-gnu 29 29 29 +40 29 29 29 @@ -48666,6 +48952,7 @@ powerpc64-linux-gnu 12 12 12 + 27 27 @@ -48778,12 +49065,18 @@ powerpc64-linux-gnu 16 16 16 +40 +40 16 38 38 38 16 38 +40 +40 +40 +40 16 16 16 @@ -48804,6 +49097,8 @@ powerpc64-linux-gnu 16 16 16 +40 +40 16 16 16 @@ -48816,8 +49111,12 @@ powerpc64-linux-gnu 16 16 16 +40 +40 16 16 +40 +40 16 16 12 @@ -50080,6 +50379,7 @@ powerpc64-linux-gnu 12 12 12 +40 12 12 12 @@ -50200,6 +50500,7 @@ powerpc64-linux-gnu 12 12 12 +40 12 12 12 @@ -50873,6 +51174,7 @@ powerpc64-linux-gnu 12 12 12 13 +40 12 13 12 13 12 13 @@ -50901,6 +51203,7 @@ powerpc64-linux-gnu 12 12 12 +40 24 16 12 @@ -50928,6 +51231,8 @@ powerpc64-linux-gnu 16 12 12 +40 +40 12 12 12 @@ -51154,6 +51459,7 @@ powerpc64-linux-gnu 12 12 12 +40 12 12 12 @@ -51522,6 +51828,7 @@ powerpc64-linux-gnu 37 12 16 +40 38 38 38 @@ -51595,6 +51902,7 @@ powerpc64-linux-gnu 12 12 12 +40 12 12 12 @@ -52370,6 +52678,7 @@ powerpc-linux-gnueabi powerpc-linux-gnueabihf 1 0 0 +3 27 27 @@ -52482,12 +52791,18 @@ powerpc-linux-gnueabi powerpc-linux-gnueabihf 16 16 16 +40 +40 16 38 38 38 16 38 +40 +40 +40 +40 16 16 16 @@ -52508,6 +52823,8 @@ powerpc-linux-gnueabi powerpc-linux-gnueabihf 16 16 16 +40 +40 16 16 16 @@ -52520,8 +52837,12 @@ powerpc-linux-gnueabi powerpc-linux-gnueabihf 16 16 16 +40 +40 16 16 +40 +40 16 16 0 @@ -53784,6 +54105,7 @@ powerpc-linux-gnueabi powerpc-linux-gnueabihf 1 1 0 +40 0 5 0 @@ -53904,6 +54226,7 @@ powerpc-linux-gnueabi powerpc-linux-gnueabihf 0 3 0 0 +40 0 0 0 @@ -54577,6 +54900,7 @@ powerpc-linux-gnueabi powerpc-linux-gnueabihf 5 0 0 13 +40 0 13 0 13 0 13 @@ -54605,6 +54929,7 @@ powerpc-linux-gnueabi powerpc-linux-gnueabihf 0 0 0 +40 24 16 0 @@ -54632,6 +54957,8 @@ powerpc-linux-gnueabi powerpc-linux-gnueabihf 16 1 0 +40 +40 1 1 1 @@ -54858,6 +55185,7 @@ powerpc-linux-gnueabi powerpc-linux-gnueabihf 0 0 0 +40 2 0 1 0 1 @@ -55226,6 +55554,7 @@ powerpc-linux-gnueabi powerpc-linux-gnueabihf 37 1 16 +40 38 38 38 @@ -55299,6 +55628,7 @@ powerpc-linux-gnueabi powerpc-linux-gnueabihf 0 0 0 +40 0 0 0 diff --git a/lib/libc/glibc/fns.txt b/lib/libc/glibc/fns.txt index 566f6f9aeecc49c34925e68cfdd6b7c896be9415..028892f3ea7a9e0098c461c725cb383a22bf4eee 100644 --- a/lib/libc/glibc/fns.txt +++ b/lib/libc/glibc/fns.txt @@ -513,6 +513,7 @@ __libc_realloc c __libc_sa_len c __libc_start_main c __libc_valloc c +__libpthread_version_placeholder pthread __log10_finite m __log10f128_finite m __log10f_finite m @@ -625,12 +626,18 @@ __nldbl___vswprintf_chk c __nldbl___vsyslog_chk c __nldbl___vwprintf_chk c __nldbl___wprintf_chk c +__nldbl_argp_error c +__nldbl_argp_failure c __nldbl_asprintf c __nldbl_daddl m __nldbl_ddivl m __nldbl_dmull m __nldbl_dprintf c __nldbl_dsubl m +__nldbl_err c +__nldbl_error c +__nldbl_error_at_line c +__nldbl_errx c __nldbl_fprintf c __nldbl_fscanf c __nldbl_fwprintf c @@ -651,6 +658,8 @@ __nldbl_swscanf c __nldbl_syslog c __nldbl_vasprintf c __nldbl_vdprintf c +__nldbl_verr c +__nldbl_verrx c __nldbl_vfprintf c __nldbl_vfscanf c __nldbl_vfwprintf c @@ -663,8 +672,12 @@ __nldbl_vsscanf c __nldbl_vswprintf c __nldbl_vswscanf c __nldbl_vsyslog c +__nldbl_vwarn c +__nldbl_vwarnx c __nldbl_vwprintf c __nldbl_vwscanf c +__nldbl_warn c +__nldbl_warnx c __nldbl_wprintf c __nldbl_wscanf c __nss_configure_lookup c @@ -1927,6 +1940,7 @@ getdate c getdate_err c getdate_r c getdelim c +getdents64 c getdirentries c getdirentries64 c getdomainname c @@ -2047,6 +2061,7 @@ getspnam c getspnam_r c getsubopt c gettext c +gettid c gettimeofday c getttyent c getttynam c @@ -2720,6 +2735,7 @@ pthread_barrierattr_init pthread pthread_barrierattr_setpshared pthread pthread_cancel pthread pthread_cond_broadcast c +pthread_cond_clockwait pthread pthread_cond_destroy c pthread_cond_init c pthread_cond_signal c @@ -2748,6 +2764,7 @@ pthread_key_create pthread pthread_key_delete pthread pthread_kill pthread pthread_kill_other_threads_np pthread +pthread_mutex_clocklock pthread pthread_mutex_consistent pthread pthread_mutex_consistent_np pthread pthread_mutex_destroy c @@ -2775,6 +2792,8 @@ pthread_mutexattr_setrobust pthread pthread_mutexattr_setrobust_np pthread pthread_mutexattr_settype pthread pthread_once pthread +pthread_rwlock_clockrdlock pthread +pthread_rwlock_clockwrlock pthread pthread_rwlock_destroy pthread pthread_rwlock_init pthread pthread_rwlock_rdlock pthread @@ -3001,6 +3020,7 @@ seed48 c seed48_r c seekdir c select c +sem_clockwait pthread sem_close pthread sem_destroy pthread sem_getvalue pthread @@ -3369,6 +3389,7 @@ tgammaf32x m tgammaf64 m tgammaf64x m tgammal m +tgkill c thrd_create pthread thrd_current c thrd_detach pthread @@ -3442,6 +3463,7 @@ ttyname c ttyname_r c ttyslot c twalk c +twalk_r c tzname c tzset c ualarm c diff --git a/lib/libc/glibc/vers.txt b/lib/libc/glibc/vers.txt index bffe5b890af9c5ec4ad0aad94b692e8d01ac9c63..a81ba864c45c947a7da6d44390580e4b68852f94 100644 --- a/lib/libc/glibc/vers.txt +++ b/lib/libc/glibc/vers.txt @@ -38,3 +38,4 @@ GLIBC_2.26 GLIBC_2.27 GLIBC_2.28 GLIBC_2.29 +GLIBC_2.30 diff --git a/tools/update_glibc.zig b/tools/update_glibc.zig index 1bca274124d4f05c50dd7894d6ce79dd08623094..c0a3153aecc53bb426622ce9984a2bd6c9fa3899 100644 --- a/tools/update_glibc.zig +++ b/tools/update_glibc.zig @@ -135,7 +135,7 @@ pub fn main() !void { const allocator = &arena.allocator; const args = try std.process.argsAlloc(allocator); const in_glibc_dir = args[1]; // path to the unzipped tarball of glibc, e.g. ~/downloads/glibc-2.25 - const zig_src_dir = args[2]; // path to the source checkout of zig + const zig_src_dir = args[2]; // path to the source checkout of zig, lib dir, e.g. ~/zig-src/lib const prefix = try fs.path.join(allocator, [_][]const u8{ in_glibc_dir, "sysdeps", "unix", "sysv", "linux" }); const glibc_out_dir = try fs.path.join(allocator, [_][]const u8{ zig_src_dir, "libc", "glibc" }); -- 2.54.0 From 229323e13a074e94ef8a58409c81cfd9ac807dd8 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sat, 7 Sep 2019 17:37:17 -0400 Subject: [PATCH 60/80] fix suspensions inside for loops generating invalid LLVM IR closes #3076 --- src/all_types.hpp | 2 ++ src/analyze.cpp | 26 ++++++++++++++++++++------ src/analyze.hpp | 2 +- src/ir.cpp | 14 +++++++++----- test/stage1/behavior/async_fn.zig | 27 +++++++++++++++++++++++++++ 5 files changed, 59 insertions(+), 12 deletions(-) diff --git a/src/all_types.hpp b/src/all_types.hpp index 8ba3e4f484f47d82368741608a3247733063c768..a9c2409c1961d95a08bc81219cb698a179c5f00f 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -25,6 +25,7 @@ struct ZigFn; struct Scope; struct ScopeBlock; struct ScopeFnDef; +struct ScopeExpr; struct ZigType; struct ZigVar; struct ErrorTableEntry; @@ -2230,6 +2231,7 @@ struct ScopeLoop { ZigList *incoming_values; ZigList *incoming_blocks; ResultLocPeerParent *peer_parent; + ScopeExpr *spill_scope; }; // This scope blocks certain things from working such as comptime continue diff --git a/src/analyze.cpp b/src/analyze.cpp index d751dbdb97e17d8f34eeb0cde984769b1b6aece5..7a91d6b82107b9d4e7061982094b079ce86be11e 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -227,7 +227,7 @@ Scope *create_typeof_scope(CodeGen *g, AstNode *node, Scope *parent) { return &scope->base; } -Scope *create_expr_scope(CodeGen *g, AstNode *node, Scope *parent) { +ScopeExpr *create_expr_scope(CodeGen *g, AstNode *node, Scope *parent) { ScopeExpr *scope = allocate(1); init_scope(g, &scope->base, ScopeIdExpr, node, parent); ScopeExpr *parent_expr = find_expr_scope(parent); @@ -238,7 +238,7 @@ Scope *create_expr_scope(CodeGen *g, AstNode *node, Scope *parent) { parent_expr->children_ptr[parent_expr->children_len] = scope; parent_expr->children_len = new_len; } - return &scope->base; + return scope; } ZigType *get_scope_import(Scope *scope) { @@ -5713,7 +5713,6 @@ static void mark_suspension_point(Scope *scope) { case ScopeIdCImport: case ScopeIdSuspend: case ScopeIdTypeOf: - case ScopeIdBlock: return; case ScopeIdLoop: case ScopeIdRuntime: @@ -5730,6 +5729,14 @@ static void mark_suspension_point(Scope *scope) { child_expr_scope = parent_expr_scope; continue; } + case ScopeIdBlock: + if (scope->parent->parent->id == ScopeIdLoop) { + ScopeLoop *loop_scope = reinterpret_cast(scope->parent->parent); + if (loop_scope->spill_scope != nullptr) { + loop_scope->spill_scope->need_spill = MemoizedBoolTrue; + } + } + return; } } } @@ -5928,6 +5935,15 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) { await->result_loc = ir_create_alloca(g, await->base.scope, await->base.source_node, fn, await->base.value.type, ""); } + for (size_t block_i = 0; block_i < fn->analyzed_executable.basic_block_list.length; block_i += 1) { + IrBasicBlock *block = fn->analyzed_executable.basic_block_list.at(block_i); + for (size_t instr_i = 0; instr_i < block->instruction_list.length; instr_i += 1) { + IrInstruction *instruction = block->instruction_list.at(instr_i); + if (instruction->id == IrInstructionIdSuspendFinish) { + mark_suspension_point(instruction->scope); + } + } + } // Now that we've marked all the expr scopes that have to spill, we go over the instructions // and spill the relevant ones. for (size_t block_i = 0; block_i < fn->analyzed_executable.basic_block_list.length; block_i += 1) { @@ -6395,9 +6411,7 @@ void eval_min_max_value(CodeGen *g, ZigType *type_entry, ConstExprValue *const_v } static void render_const_val_ptr(CodeGen *g, Buf *buf, ConstExprValue *const_val, ZigType *type_entry) { - assert(type_entry->id == ZigTypeIdPointer); - - if (type_entry->data.pointer.child_type->id == ZigTypeIdOpaque) { + if (type_entry->id == ZigTypeIdPointer && type_entry->data.pointer.child_type->id == ZigTypeIdOpaque) { buf_append_buf(buf, &type_entry->name); return; } diff --git a/src/analyze.hpp b/src/analyze.hpp index 55bf9aba30c4e244a3de78050f43df9003f33a2d..78eac4491aad9838e0c69283af191baeec8626d6 100644 --- a/src/analyze.hpp +++ b/src/analyze.hpp @@ -114,7 +114,7 @@ ScopeFnDef *create_fndef_scope(CodeGen *g, AstNode *node, Scope *parent, ZigFn * Scope *create_comptime_scope(CodeGen *g, AstNode *node, Scope *parent); Scope *create_runtime_scope(CodeGen *g, AstNode *node, Scope *parent, IrInstruction *is_comptime); Scope *create_typeof_scope(CodeGen *g, AstNode *node, Scope *parent); -Scope *create_expr_scope(CodeGen *g, AstNode *node, Scope *parent); +ScopeExpr *create_expr_scope(CodeGen *g, AstNode *node, Scope *parent); void init_const_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *str); ConstExprValue *create_const_str_lit(CodeGen *g, Buf *str); diff --git a/src/ir.cpp b/src/ir.cpp index 1a0aad36e97547a49009d4e3891f4dcebc6376bc..6b71fa8d17f8710f57a8d7e047aacbb4f5777a49 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -6474,6 +6474,8 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo IrInstruction *is_comptime = ir_build_const_bool(irb, parent_scope, node, ir_should_inline(irb->exec, parent_scope) || node->data.for_expr.is_inline); + ScopeExpr *spill_scope = create_expr_scope(irb->codegen, node, parent_scope); + AstNode *index_var_source_node; ZigVar *index_var; const char *index_var_name; @@ -6504,11 +6506,11 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo Buf *len_field_name = buf_create_from_str("len"); IrInstruction *len_ref = ir_build_field_ptr(irb, parent_scope, node, array_val_ptr, len_field_name, false); - IrInstruction *len_val = ir_build_load_ptr(irb, parent_scope, node, len_ref); + IrInstruction *len_val = ir_build_load_ptr(irb, &spill_scope->base, node, len_ref); ir_build_br(irb, parent_scope, node, cond_block, is_comptime); ir_set_cursor_at_end_and_append_block(irb, cond_block); - IrInstruction *index_val = ir_build_load_ptr(irb, parent_scope, node, index_ptr); + IrInstruction *index_val = ir_build_load_ptr(irb, &spill_scope->base, node, index_ptr); IrInstruction *cond = ir_build_bin_op(irb, parent_scope, node, IrBinOpCmpLessThan, index_val, len_val, false); IrBasicBlock *after_cond_block = irb->current_basic_block; IrInstruction *void_else_value = else_node ? nullptr : ir_mark_gen(ir_build_const_void(irb, parent_scope, node)); @@ -6518,7 +6520,8 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo ResultLocPeerParent *peer_parent = ir_build_result_peers(irb, cond_br_inst, end_block, result_loc, is_comptime); ir_set_cursor_at_end_and_append_block(irb, body_block); - IrInstruction *elem_ptr = ir_build_elem_ptr(irb, parent_scope, node, array_val_ptr, index_val, false, + Scope *elem_ptr_scope = node->data.for_expr.elem_is_ptr ? parent_scope : &spill_scope->base; + IrInstruction *elem_ptr = ir_build_elem_ptr(irb, elem_ptr_scope, node, array_val_ptr, index_val, false, PtrLenSingle, nullptr); // TODO make it an error to write to element variable or i variable. Buf *elem_var_name = elem_node->data.symbol_expr.symbol; @@ -6526,7 +6529,7 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo Scope *child_scope = elem_var->child_scope; IrInstruction *var_ptr = node->data.for_expr.elem_is_ptr ? - ir_build_ref(irb, parent_scope, elem_node, elem_ptr, true, false) : elem_ptr; + ir_build_ref(irb, &spill_scope->base, elem_node, elem_ptr, true, false) : elem_ptr; ir_build_var_decl_src(irb, parent_scope, elem_node, elem_var, nullptr, var_ptr); ZigList incoming_values = {0}; @@ -6539,6 +6542,7 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo loop_scope->incoming_values = &incoming_values; loop_scope->lval = LValNone; loop_scope->peer_parent = peer_parent; + loop_scope->spill_scope = spill_scope; // Note the body block of the loop is not the place that lval and result_loc are used - // it's actually in break statements, handled similarly to return statements. @@ -8166,7 +8170,7 @@ static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, Scope *sc { child_scope = scope; } else { - child_scope = create_expr_scope(irb->codegen, node, scope); + child_scope = &create_expr_scope(irb->codegen, node, scope)->base; } IrInstruction *result = ir_gen_node_raw(irb, node, child_scope, lval, result_loc); if (result == irb->codegen->invalid_instruction) { diff --git a/test/stage1/behavior/async_fn.zig b/test/stage1/behavior/async_fn.zig index f5669f0fca1f9c5a770fb090222e8cdb8833384c..b8a7196ed69cf659312aafb154624dfe56d8a35c 100644 --- a/test/stage1/behavior/async_fn.zig +++ b/test/stage1/behavior/async_fn.zig @@ -1151,3 +1151,30 @@ test "async fn call used in expression after a fn call" { }; _ = async S.atest(); } + +test "suspend in for loop" { + const S = struct { + var global_frame: ?anyframe = null; + + fn doTheTest() void { + _ = async atest(); + while (global_frame) |f| resume f; + } + + fn atest() void { + expect(func([_]u8{ 1, 2, 3 }) == 6); + } + fn func(stuff: []const u8) u32 { + global_frame = @frame(); + var sum: u32 = 0; + for (stuff) |x| { + suspend; + sum += x; + } + global_frame = null; + return sum; + } + }; + S.doTheTest(); +} + -- 2.54.0 From ec13fa3f4ae49dec7045a61dc380ab3bd9f0a635 Mon Sep 17 00:00:00 2001 From: Gustav Olsson Date: Sun, 8 Sep 2019 14:46:25 +0200 Subject: [PATCH 61/80] forward framework dirs to embedded clang in addition to linker on osx --- src/main.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index 9e8f2b7d4f38ff1f108ffb855dc33e58ccb0e1e6..2f1fb4f5e11c19b089fd5c9a98d3356ba2e854ae 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -784,7 +784,9 @@ int main(int argc, char **argv) { } else if (strcmp(arg, "--library-path") == 0 || strcmp(arg, "-L") == 0) { lib_dirs.append(argv[i]); } else if (strcmp(arg, "-F") == 0) { - framework_dirs.append(argv[i]); + framework_dirs.append(argv[i]); // embedded linker + clang_argv.append("-iframework"); // embedded clang + clang_argv.append(argv[i]); } else if (strcmp(arg, "--library") == 0 || strcmp(arg, "-l") == 0) { if (strcmp(argv[i], "c") == 0) have_libc = true; -- 2.54.0 From 5dde3cd3bdaf5cca0c8aca94483b7227ecc551be Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sun, 8 Sep 2019 15:09:05 -0400 Subject: [PATCH 62/80] move logic for propagating framework dirs to zig cc --- src/codegen.cpp | 5 +++++ src/main.cpp | 4 +--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/codegen.cpp b/src/codegen.cpp index 134569374e2b70abe9b3d644d6079872e2523cf6..3066d8b1c5f8ec7fd4e2a1bb7b57124430e3a948 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -8774,6 +8774,11 @@ void add_cc_args(CodeGen *g, ZigList &args, const char *out_dep_pa } } + for (size_t i = 0; i < g->framework_dirs.length; i += 1) { + args.append("-iframework"); + args.append(g->framework_dirs.at(i)); + } + //note(dimenus): appending libc headers before c_headers breaks intrinsics //and other compiler specific items // According to Rich Felker libc headers are supposed to go before C language headers. diff --git a/src/main.cpp b/src/main.cpp index 2f1fb4f5e11c19b089fd5c9a98d3356ba2e854ae..9e8f2b7d4f38ff1f108ffb855dc33e58ccb0e1e6 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -784,9 +784,7 @@ int main(int argc, char **argv) { } else if (strcmp(arg, "--library-path") == 0 || strcmp(arg, "-L") == 0) { lib_dirs.append(argv[i]); } else if (strcmp(arg, "-F") == 0) { - framework_dirs.append(argv[i]); // embedded linker - clang_argv.append("-iframework"); // embedded clang - clang_argv.append(argv[i]); + framework_dirs.append(argv[i]); } else if (strcmp(arg, "--library") == 0 || strcmp(arg, "-l") == 0) { if (strcmp(argv[i], "c") == 0) have_libc = true; -- 2.54.0 From 0d9a78a852f5ecd0dd94a906eab300130983320e Mon Sep 17 00:00:00 2001 From: Michael Dusan Date: Sat, 7 Sep 2019 23:04:01 -0400 Subject: [PATCH 63/80] test-stack-traces: add FreeBSD --- test/stack_traces.zig | 143 +++++++++++++++++++++++++++++++++--------- 1 file changed, 112 insertions(+), 31 deletions(-) diff --git a/test/stack_traces.zig b/test/stack_traces.zig index 1a014f07cc221dde90bdd7734d47ebce3d433f70..ab00f749122af07551f0376d2b20edb1d528cd50 100644 --- a/test/stack_traces.zig +++ b/test/stack_traces.zig @@ -41,28 +41,108 @@ pub fn addCases(cases: *tests.StackTracesContext) void { \\ try foo(); \\} ; + // zig fmt: off switch (builtin.os) { + .freebsd => { + cases.addCase( + "return", + source_return, + [_][]const u8{ + // debug + \\error: TheSkyIsFalling + \\source.zig:4:5: [address] in main (test) + \\ + , + // release-safe + \\error: TheSkyIsFalling + \\source.zig:4:5: [address] in std.special.main (test) + \\ + , + // release-fast + \\error: TheSkyIsFalling + \\ + , + // release-small + \\error: TheSkyIsFalling + \\ + }, + ); + cases.addCase( + "try return", + source_try_return, + [_][]const u8{ + // debug + \\error: TheSkyIsFalling + \\source.zig:4:5: [address] in foo (test) + \\source.zig:8:5: [address] in main (test) + \\ + , + // release-safe + \\error: TheSkyIsFalling + \\source.zig:4:5: [address] in std.special.main (test) + \\source.zig:8:5: [address] in std.special.main (test) + \\ + , + // release-fast + \\error: TheSkyIsFalling + \\ + , + // release-small + \\error: TheSkyIsFalling + \\ + }, + ); + cases.addCase( + "try try return return", + source_try_try_return_return, + [_][]const u8{ + // debug + \\error: TheSkyIsFalling + \\source.zig:12:5: [address] in make_error (test) + \\source.zig:8:5: [address] in bar (test) + \\source.zig:4:5: [address] in foo (test) + \\source.zig:16:5: [address] in main (test) + \\ + , + // release-safe + \\error: TheSkyIsFalling + \\source.zig:12:5: [address] in std.special.main (test) + \\source.zig:8:5: [address] in std.special.main (test) + \\source.zig:4:5: [address] in std.special.main (test) + \\source.zig:16:5: [address] in std.special.main (test) + \\ + , + // release-fast + \\error: TheSkyIsFalling + \\ + , + // release-small + \\error: TheSkyIsFalling + \\ + }, + ); + }, .linux => { cases.addCase( "return", source_return, [_][]const u8{ // debug - \\error: TheSkyIsFalling + \\error: TheSkyIsFalling \\source.zig:4:5: [address] in main (test) \\ , // release-safe - \\error: TheSkyIsFalling + \\error: TheSkyIsFalling \\source.zig:4:5: [address] in std.special.posixCallMainAndExit (test) \\ , // release-fast - \\error: TheSkyIsFalling + \\error: TheSkyIsFalling \\ , // release-small - \\error: TheSkyIsFalling + \\error: TheSkyIsFalling \\ }, ); @@ -71,23 +151,23 @@ pub fn addCases(cases: *tests.StackTracesContext) void { source_try_return, [_][]const u8{ // debug - \\error: TheSkyIsFalling + \\error: TheSkyIsFalling \\source.zig:4:5: [address] in foo (test) \\source.zig:8:5: [address] in main (test) \\ , // release-safe - \\error: TheSkyIsFalling + \\error: TheSkyIsFalling \\source.zig:4:5: [address] in std.special.posixCallMainAndExit (test) \\source.zig:8:5: [address] in std.special.posixCallMainAndExit (test) \\ , // release-fast - \\error: TheSkyIsFalling + \\error: TheSkyIsFalling \\ , // release-small - \\error: TheSkyIsFalling + \\error: TheSkyIsFalling \\ }, ); @@ -96,7 +176,7 @@ pub fn addCases(cases: *tests.StackTracesContext) void { source_try_try_return_return, [_][]const u8{ // debug - \\error: TheSkyIsFalling + \\error: TheSkyIsFalling \\source.zig:12:5: [address] in make_error (test) \\source.zig:8:5: [address] in bar (test) \\source.zig:4:5: [address] in foo (test) @@ -104,7 +184,7 @@ pub fn addCases(cases: *tests.StackTracesContext) void { \\ , // release-safe - \\error: TheSkyIsFalling + \\error: TheSkyIsFalling \\source.zig:12:5: [address] in std.special.posixCallMainAndExit (test) \\source.zig:8:5: [address] in std.special.posixCallMainAndExit (test) \\source.zig:4:5: [address] in std.special.posixCallMainAndExit (test) @@ -112,11 +192,11 @@ pub fn addCases(cases: *tests.StackTracesContext) void { \\ , // release-fast - \\error: TheSkyIsFalling + \\error: TheSkyIsFalling \\ , // release-small - \\error: TheSkyIsFalling + \\error: TheSkyIsFalling \\ }, ); @@ -127,21 +207,21 @@ pub fn addCases(cases: *tests.StackTracesContext) void { source_return, [_][]const u8{ // debug - \\error: TheSkyIsFalling + \\error: TheSkyIsFalling \\source.zig:4:5: [address] in _main.0 (test.o) \\ , // release-safe - \\error: TheSkyIsFalling + \\error: TheSkyIsFalling \\source.zig:4:5: [address] in _main (test.o) \\ , // release-fast - \\error: TheSkyIsFalling + \\error: TheSkyIsFalling \\ , // release-small - \\error: TheSkyIsFalling + \\error: TheSkyIsFalling \\ }, ); @@ -150,23 +230,23 @@ pub fn addCases(cases: *tests.StackTracesContext) void { source_try_return, [_][]const u8{ // debug - \\error: TheSkyIsFalling + \\error: TheSkyIsFalling \\source.zig:4:5: [address] in _foo (test.o) \\source.zig:8:5: [address] in _main.0 (test.o) \\ , // release-safe - \\error: TheSkyIsFalling + \\error: TheSkyIsFalling \\source.zig:4:5: [address] in _main (test.o) \\source.zig:8:5: [address] in _main (test.o) \\ , // release-fast - \\error: TheSkyIsFalling + \\error: TheSkyIsFalling \\ , // release-small - \\error: TheSkyIsFalling + \\error: TheSkyIsFalling \\ }, ); @@ -175,7 +255,7 @@ pub fn addCases(cases: *tests.StackTracesContext) void { source_try_try_return_return, [_][]const u8{ // debug - \\error: TheSkyIsFalling + \\error: TheSkyIsFalling \\source.zig:12:5: [address] in _make_error (test.o) \\source.zig:8:5: [address] in _bar (test.o) \\source.zig:4:5: [address] in _foo (test.o) @@ -183,7 +263,7 @@ pub fn addCases(cases: *tests.StackTracesContext) void { \\ , // release-safe - \\error: TheSkyIsFalling + \\error: TheSkyIsFalling \\source.zig:12:5: [address] in _main (test.o) \\source.zig:8:5: [address] in _main (test.o) \\source.zig:4:5: [address] in _main (test.o) @@ -191,11 +271,11 @@ pub fn addCases(cases: *tests.StackTracesContext) void { \\ , // release-fast - \\error: TheSkyIsFalling + \\error: TheSkyIsFalling \\ , // release-small - \\error: TheSkyIsFalling + \\error: TheSkyIsFalling \\ }, ); @@ -206,7 +286,7 @@ pub fn addCases(cases: *tests.StackTracesContext) void { source_return, [_][]const u8{ // debug - \\error: TheSkyIsFalling + \\error: TheSkyIsFalling \\source.zig:4:5: [address] in main (test.obj) \\ , @@ -214,11 +294,11 @@ pub fn addCases(cases: *tests.StackTracesContext) void { // --disabled-- results in segmenetation fault "", // release-fast - \\error: TheSkyIsFalling + \\error: TheSkyIsFalling \\ , // release-small - \\error: TheSkyIsFalling + \\error: TheSkyIsFalling \\ }, ); @@ -236,11 +316,11 @@ pub fn addCases(cases: *tests.StackTracesContext) void { // --disabled-- results in segmenetation fault "", // release-fast - \\error: TheSkyIsFalling + \\error: TheSkyIsFalling \\ , // release-small - \\error: TheSkyIsFalling + \\error: TheSkyIsFalling \\ }, ); @@ -260,15 +340,16 @@ pub fn addCases(cases: *tests.StackTracesContext) void { // --disabled-- results in segmenetation fault "", // release-fast - \\error: TheSkyIsFalling + \\error: TheSkyIsFalling \\ , // release-small - \\error: TheSkyIsFalling + \\error: TheSkyIsFalling \\ }, ); }, else => {}, } + // zig fmt: off } -- 2.54.0 From 19cf9bd06283d020fa013333b04504133a2e26cb Mon Sep 17 00:00:00 2001 From: Sahnvour Date: Sun, 8 Sep 2019 12:07:23 +0200 Subject: [PATCH 64/80] use /debug:fastlink when building with msvc and debug info --- CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index d44cf5890f57d121484c97f017f7b4716232ba00..05f603f12cc56b27389bfb5639cb482d2b6dfcc8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -516,6 +516,9 @@ set(OPTIMIZED_C_FLAGS "-std=c99 -O3") set(EXE_LDFLAGS " ") if(MSVC) set(EXE_LDFLAGS "${EXE_LDFLAGS} /STACK:16777216") + if(NOT "${CMAKE_BUILD_TYPE}" STREQUAL "Release" AND NOT "${CMAKE_BUILD_TYPE}" STREQUAL "MinSizeRel") + set(EXE_LDFLAGS "${EXE_LDFLAGS} /debug:fastlink") + endif() elseif(MINGW) set(EXE_LDFLAGS "${EXE_LDFLAGS} -Wl,--stack,16777216") endif() -- 2.54.0 From 2482bdf22b77bdee718167da5390157cc792dced Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 9 Sep 2019 09:33:33 -0400 Subject: [PATCH 65/80] release builds of stage1 have llvm ir verification the stage2 zig code however gets compiled in release mode, and stripped. --- CMakeLists.txt | 6 ++++++ build.zig | 8 ++++++-- src/codegen.cpp | 2 -- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 05f603f12cc56b27389bfb5639cb482d2b6dfcc8..b43d31b58e19dad47fac05747450601d71f0d541 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -590,12 +590,18 @@ if(MSVC) else() set(LIBUSERLAND "${CMAKE_BINARY_DIR}/libuserland.a") endif() +if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug") + set(LIBUSERLAND_RELEASE_MODE "false") +else() + set(LIBUSERLAND_RELEASE_MODE "true") +endif() add_custom_target(zig_build_libuserland ALL COMMAND zig0 build --override-std-dir std --override-lib-dir "${CMAKE_SOURCE_DIR}" libuserland install "-Doutput-dir=${CMAKE_BINARY_DIR}" + "-Drelease=${LIBUSERLAND_RELEASE_MODE}" "-Dlib-files-only" --prefix "${CMAKE_INSTALL_PREFIX}" DEPENDS zig0 diff --git a/build.zig b/build.zig index 21fa79e863c78cb2796ef6b210aefd2b8d028d07..457314b42a6d77e1bca4ebb01519c700f59832b5 100644 --- a/build.zig +++ b/build.zig @@ -63,7 +63,7 @@ pub fn build(b: *Builder) !void { try configureStage2(b, test_stage2, ctx); try configureStage2(b, exe, ctx); - addLibUserlandStep(b); + addLibUserlandStep(b, mode); const skip_release = b.option(bool, "skip-release", "Main test suite skips release builds") orelse false; const skip_release_small = b.option(bool, "skip-release-small", "Main test suite skips release-small builds") orelse skip_release; @@ -370,11 +370,15 @@ const Context = struct { llvm: LibraryDep, }; -fn addLibUserlandStep(b: *Builder) void { +fn addLibUserlandStep(b: *Builder, mode: builtin.Mode) void { const artifact = b.addStaticLibrary("userland", "src-self-hosted/stage1.zig"); artifact.disable_gen_h = true; artifact.bundle_compiler_rt = true; artifact.setTarget(builtin.arch, builtin.os, builtin.abi); + artifact.setBuildMode(mode); + if (mode != .Debug) { + artifact.strip = true; + } artifact.linkSystemLibrary("c"); if (builtin.os == .windows) { artifact.linkSystemLibrary("ntdll"); diff --git a/src/codegen.cpp b/src/codegen.cpp index 3066d8b1c5f8ec7fd4e2a1bb7b57124430e3a948..b590995c92b46c4ad54ededc0cc9129e4c15528f 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -7381,10 +7381,8 @@ static void do_code_gen(CodeGen *g) { LLVMDumpModule(g->module); } -#ifndef NDEBUG char *error = nullptr; LLVMVerifyModule(g->module, LLVMAbortProcessAction, &error); -#endif } static void zig_llvm_emit_output(CodeGen *g) { -- 2.54.0 From f7721ac37cbb38c2f27d51f91eab776c5aca9767 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 9 Sep 2019 12:15:39 -0400 Subject: [PATCH 66/80] implement spilling when returning error union async function call closes #3190 --- src/codegen.cpp | 10 ++++++++-- test/stage1/behavior/async_fn.zig | 23 +++++++++++++++++++++++ 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/src/codegen.cpp b/src/codegen.cpp index b590995c92b46c4ad54ededc0cc9129e4c15528f..0533cc85b5829be4f3ff29519ee8d2b5319a1a76 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -4122,8 +4122,14 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr if (!type_has_bits(src_return_type)) return nullptr; - if (result_loc != nullptr) - return get_handle_value(g, result_loc, src_return_type, ptr_result_type); + if (result_loc != nullptr) { + if (instruction->result_loc->id == IrInstructionIdReturnPtr) { + instruction->base.spill = nullptr; + return g->cur_ret_ptr; + } else { + return get_handle_value(g, result_loc, src_return_type, ptr_result_type); + } + } LLVMValueRef result_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, frame_ret_start + 2, ""); return LLVMBuildLoad(g->builder, result_ptr, ""); diff --git a/test/stage1/behavior/async_fn.zig b/test/stage1/behavior/async_fn.zig index b8a7196ed69cf659312aafb154624dfe56d8a35c..3ee728f8a57ade19a946f6a988a7dc873dcb57fd 100644 --- a/test/stage1/behavior/async_fn.zig +++ b/test/stage1/behavior/async_fn.zig @@ -1178,3 +1178,26 @@ test "suspend in for loop" { S.doTheTest(); } +test "correctly spill when returning the error union result of another async fn" { + const S = struct { + var global_frame: anyframe = undefined; + + fn doTheTest() void { + expect((atest() catch unreachable) == 1234); + } + + fn atest() !i32 { + return fallible1(); + } + + fn fallible1() anyerror!i32 { + suspend { + global_frame = @frame(); + } + return 1234; + } + }; + _ = async S.doTheTest(); + resume S.global_frame; +} + -- 2.54.0 From cc6376058784aa7a910e93c31ac8bd819de4e187 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Mon, 9 Sep 2019 18:51:13 +0200 Subject: [PATCH 67/80] Allow comparison between union tag and enum literal Closes #2810 --- src/ir.cpp | 25 +++++++++++++++++++++++++ test/stage1/behavior/union.zig | 10 ++++++++++ 2 files changed, 35 insertions(+) diff --git a/src/ir.cpp b/src/ir.cpp index 6b71fa8d17f8710f57a8d7e047aacbb4f5777a49..bbea993162e44cd8b355e3827db7a726b5757ca5 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -13228,6 +13228,31 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp * ir_add_error_node(ira, source_node, buf_sprintf("comparison of '%s' with null", buf_ptr(&non_null_type->name))); return ira->codegen->invalid_instruction; + } else if (is_equality_cmp && ( + (op1->value.type->id == ZigTypeIdEnumLiteral && op2->value.type->id == ZigTypeIdUnion) || + (op2->value.type->id == ZigTypeIdEnumLiteral && op1->value.type->id == ZigTypeIdUnion))) + { + // Support equality comparison between a union's tag value and a enum literal + IrInstruction *union_val = op1->value.type->id == ZigTypeIdUnion ? op1 : op2; + IrInstruction *enum_val = op1->value.type->id == ZigTypeIdUnion ? op2 : op1; + + ZigType *tag_type = union_val->value.type->data.unionation.tag_type; + assert(tag_type != nullptr); + + IrInstruction *casted_union = ir_implicit_cast(ira, union_val, tag_type); + if (type_is_invalid(casted_union->value.type)) + return ira->codegen->invalid_instruction; + + IrInstruction *casted_val = ir_implicit_cast(ira, enum_val, tag_type); + if (type_is_invalid(casted_val->value.type)) + return ira->codegen->invalid_instruction; + + IrInstruction *result = ir_build_bin_op(&ira->new_irb, + bin_op_instruction->base.scope, bin_op_instruction->base.source_node, + op_id, casted_union, casted_val, bin_op_instruction->safety_check_on); + result->value.type = ira->codegen->builtin_types.entry_bool; + + return result; } if (op1->value.type->id == ZigTypeIdErrorSet && op2->value.type->id == ZigTypeIdErrorSet) { diff --git a/test/stage1/behavior/union.zig b/test/stage1/behavior/union.zig index d28a0f8ea47760e0e8793bdd769ba75c08c0bfa1..1f8ca82958f4f0c94dd3adcdae39280575896e7a 100644 --- a/test/stage1/behavior/union.zig +++ b/test/stage1/behavior/union.zig @@ -467,3 +467,13 @@ test "union no tag with struct member" { var u = Union{ .s = Struct{} }; u.foo(); } + +test "comparison between union and enum literal" { + var x = Payload{.A = 42}; + expect(x == .A); + expect(x != .B); + expect(x != .C); + expect((x == .B) == false); + expect((x == .C) == false); + expect((x != .A) == false); +} -- 2.54.0 From 4b1cd45472cab5569438fef018990fbe8043c6c3 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Mon, 9 Sep 2019 19:09:56 +0200 Subject: [PATCH 68/80] Comptime folding of enum/union comparisons --- src/ir.cpp | 15 +++++++++++++++ test/stage1/behavior/union.zig | 7 ++++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/ir.cpp b/src/ir.cpp index bbea993162e44cd8b355e3827db7a726b5757ca5..196e84eead4246ff1705a124c7ef3e689cd01181 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -13247,6 +13247,21 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp * if (type_is_invalid(casted_val->value.type)) return ira->codegen->invalid_instruction; + if (instr_is_comptime(casted_union)) { + ConstExprValue *const_union_val = ir_resolve_const(ira, casted_union, UndefBad); + if (!const_union_val) + return ira->codegen->invalid_instruction; + + ConstExprValue *const_enum_val = ir_resolve_const(ira, casted_val, UndefBad); + if (!const_enum_val) + return ira->codegen->invalid_instruction; + + Cmp cmp_result = bigint_cmp(&const_union_val->data.x_union.tag, &const_enum_val->data.x_enum_tag); + bool bool_result = (op_id == IrBinOpCmpEq) ? cmp_result == CmpEQ : cmp_result != CmpEQ; + + return ir_const_bool(ira, &bin_op_instruction->base, bool_result); + } + IrInstruction *result = ir_build_bin_op(&ira->new_irb, bin_op_instruction->base.scope, bin_op_instruction->base.source_node, op_id, casted_union, casted_val, bin_op_instruction->safety_check_on); diff --git a/test/stage1/behavior/union.zig b/test/stage1/behavior/union.zig index 1f8ca82958f4f0c94dd3adcdae39280575896e7a..7c5c6532755b1fb7edc4d1663bb183ebdf106cc7 100644 --- a/test/stage1/behavior/union.zig +++ b/test/stage1/behavior/union.zig @@ -468,7 +468,7 @@ test "union no tag with struct member" { u.foo(); } -test "comparison between union and enum literal" { +fn testComparison() void { var x = Payload{.A = 42}; expect(x == .A); expect(x != .B); @@ -477,3 +477,8 @@ test "comparison between union and enum literal" { expect((x == .C) == false); expect((x != .A) == false); } + +test "comparison between union and enum literal" { + testComparison(); + comptime testComparison(); +} -- 2.54.0 From e4c3067617f4be4563a293d58b173742e5b5d0fd Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Mon, 9 Sep 2019 19:50:46 +0200 Subject: [PATCH 69/80] Fix typo in TLS initialization code --- std/os/linux/tls.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/std/os/linux/tls.zig b/std/os/linux/tls.zig index ea1075e77ae2562ba25552cd76c41ea66446c5d1..62df8709447004b4c2a6c2052938d951049ae498 100644 --- a/std/os/linux/tls.zig +++ b/std/os/linux/tls.zig @@ -141,7 +141,7 @@ pub fn initTLS() void { elf.AT_PHENT => at_phent = auxv[i].a_un.a_val, elf.AT_PHNUM => at_phnum = auxv[i].a_un.a_val, elf.AT_PHDR => at_phdr = auxv[i].a_un.a_val, - elf.AT_HWCAP => at_phdr = auxv[i].a_un.a_val, + elf.AT_HWCAP => at_hwcap = auxv[i].a_un.a_val, else => continue, } } -- 2.54.0 From f50bfb94b52424f2145b9a18b731a47b3faf9648 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 9 Sep 2019 15:54:03 -0400 Subject: [PATCH 70/80] fix bad LLVM IR when for target expr needs to be spilled Also reduce the size of ZigVar in memory by making the name a `const char *` rather than a `Buf`. --- src/all_types.hpp | 4 +- src/analyze.cpp | 24 ++++---- src/analyze.hpp | 4 +- src/buffer.hpp | 5 ++ src/codegen.cpp | 92 +++++++++++++++++-------------- src/ir.cpp | 28 ++++++---- src/ir_print.cpp | 6 +- test/stage1/behavior/async_fn.zig | 32 +++++++++++ 8 files changed, 122 insertions(+), 73 deletions(-) diff --git a/src/all_types.hpp b/src/all_types.hpp index a9c2409c1961d95a08bc81219cb698a179c5f00f..2f3f56f0edad707a36e3e1afab605be3a9691734 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -2070,7 +2070,7 @@ struct CodeGen { }; struct ZigVar { - Buf name; + const char *name; ConstExprValue *const_value; ZigType *var_type; LLVMValueRef value_ref; @@ -2085,7 +2085,6 @@ struct ZigVar { LLVMValueRef param_value_ref; size_t mem_slot_index; IrExecutable *owner_exec; - size_t ref_count; // In an inline loop, multiple variables may be created, // In this case, a reference to a variable should follow @@ -2095,6 +2094,7 @@ struct ZigVar { ZigList export_list; uint32_t align_bytes; + uint32_t ref_count; bool shadowable; bool src_is_const; diff --git a/src/analyze.cpp b/src/analyze.cpp index 7a91d6b82107b9d4e7061982094b079ce86be11e..32cb3c0624ad42e420e094ef1bc1688c8aff6fac 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -3148,26 +3148,26 @@ ZigType *get_test_fn_type(CodeGen *g) { return g->test_fn_type; } -void add_var_export(CodeGen *g, ZigVar *var, Buf *symbol_name, GlobalLinkageId linkage) { +void add_var_export(CodeGen *g, ZigVar *var, const char *symbol_name, GlobalLinkageId linkage) { GlobalExport *global_export = var->export_list.add_one(); memset(global_export, 0, sizeof(GlobalExport)); - buf_init_from_buf(&global_export->name, symbol_name); + buf_init_from_str(&global_export->name, symbol_name); global_export->linkage = linkage; } -void add_fn_export(CodeGen *g, ZigFn *fn_table_entry, Buf *symbol_name, GlobalLinkageId linkage, bool ccc) { +void add_fn_export(CodeGen *g, ZigFn *fn_table_entry, const char *symbol_name, GlobalLinkageId linkage, bool ccc) { if (ccc) { - if (buf_eql_str(symbol_name, "main") && g->libc_link_lib != nullptr) { + if (strcmp(symbol_name, "main") == 0 && g->libc_link_lib != nullptr) { g->have_c_main = true; - } else if (buf_eql_str(symbol_name, "WinMain") && + } else if (strcmp(symbol_name, "WinMain") == 0 && g->zig_target->os == OsWindows) { g->have_winmain = true; - } else if (buf_eql_str(symbol_name, "WinMainCRTStartup") && + } else if (strcmp(symbol_name, "WinMainCRTStartup") == 0 && g->zig_target->os == OsWindows) { g->have_winmain_crt_startup = true; - } else if (buf_eql_str(symbol_name, "DllMainCRTStartup") && + } else if (strcmp(symbol_name, "DllMainCRTStartup") == 0 && g->zig_target->os == OsWindows) { g->have_dllmain_crt_startup = true; @@ -3176,7 +3176,7 @@ void add_fn_export(CodeGen *g, ZigFn *fn_table_entry, Buf *symbol_name, GlobalLi GlobalExport *fn_export = fn_table_entry->export_list.add_one(); memset(fn_export, 0, sizeof(GlobalExport)); - buf_init_from_buf(&fn_export->name, symbol_name); + buf_init_from_str(&fn_export->name, symbol_name); fn_export->linkage = linkage; } @@ -3200,7 +3200,7 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) { if (fn_proto->is_export) { bool ccc = (fn_proto->cc == CallingConventionUnspecified || fn_proto->cc == CallingConventionC); - add_fn_export(g, fn_table_entry, &fn_table_entry->symbol_name, GlobalLinkageIdStrong, ccc); + add_fn_export(g, fn_table_entry, buf_ptr(&fn_table_entry->symbol_name), GlobalLinkageIdStrong, ccc); } if (!is_extern) { @@ -3559,7 +3559,7 @@ ZigVar *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf variable_entry->src_arg_index = SIZE_MAX; assert(name); - buf_init_from_buf(&variable_entry->name, name); + variable_entry->name = strdup(buf_ptr(name)); if ((err = type_resolve(g, var_type, ResolveStatusAlignmentKnown))) { variable_entry->var_type = g->builtin_types.entry_invalid; @@ -3707,7 +3707,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var, bool allow_lazy) { } if (is_export) { - add_var_export(g, tld_var->var, &tld_var->var->name, GlobalLinkageIdStrong); + add_var_export(g, tld_var->var, tld_var->var->name, GlobalLinkageIdStrong); } g->global_vars.append(tld_var); @@ -3916,7 +3916,7 @@ ZigVar *find_variable(CodeGen *g, Scope *scope, Buf *name, ScopeFnDef **crossed_ while (scope) { if (scope->id == ScopeIdVarDecl) { ScopeVarDecl *var_scope = (ScopeVarDecl *)scope; - if (buf_eql_buf(name, &var_scope->var->name)) { + if (buf_eql_str(name, var_scope->var->name)) { if (crossed_fndef_scope != nullptr) *crossed_fndef_scope = my_crossed_fndef_scope; return var_scope->var; diff --git a/src/analyze.hpp b/src/analyze.hpp index 78eac4491aad9838e0c69283af191baeec8626d6..842125dcabfc2a139625ef3a930d508fb16d15bb 100644 --- a/src/analyze.hpp +++ b/src/analyze.hpp @@ -189,8 +189,8 @@ ZigType *get_align_amt_type(CodeGen *g); ZigPackage *new_anonymous_package(void); Buf *const_value_to_buffer(ConstExprValue *const_val); -void add_fn_export(CodeGen *g, ZigFn *fn_table_entry, Buf *symbol_name, GlobalLinkageId linkage, bool ccc); -void add_var_export(CodeGen *g, ZigVar *fn_table_entry, Buf *symbol_name, GlobalLinkageId linkage); +void add_fn_export(CodeGen *g, ZigFn *fn_table_entry, const char *symbol_name, GlobalLinkageId linkage, bool ccc); +void add_var_export(CodeGen *g, ZigVar *fn_table_entry, const char *symbol_name, GlobalLinkageId linkage); ConstExprValue *get_builtin_value(CodeGen *codegen, const char *name); diff --git a/src/buffer.hpp b/src/buffer.hpp index d7254c18a7ea401923e422a56128c44021bd86a5..251b5c2f273f00514e704ebd511bed87643f7275 100644 --- a/src/buffer.hpp +++ b/src/buffer.hpp @@ -57,6 +57,11 @@ static inline void buf_deinit(Buf *buf) { buf->list.deinit(); } +static inline void buf_destroy(Buf *buf) { + buf_deinit(buf); + free(buf); +} + static inline void buf_init_from_mem(Buf *buf, const char *ptr, size_t len) { assert(len != SIZE_MAX); buf->list.resize(len + 1); diff --git a/src/codegen.cpp b/src/codegen.cpp index 0533cc85b5829be4f3ff29519ee8d2b5319a1a76..a4ceae57d95b87036cec2faee4c7642796eb1683 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -234,18 +234,23 @@ static void addLLVMArgAttrInt(LLVMValueRef fn_val, unsigned param_index, const c return addLLVMAttrInt(fn_val, param_index + 1, attr_name, attr_val); } -static bool is_symbol_available(CodeGen *g, Buf *name) { - return g->exported_symbol_names.maybe_get(name) == nullptr && g->external_prototypes.maybe_get(name) == nullptr; +static bool is_symbol_available(CodeGen *g, const char *name) { + Buf *buf_name = buf_create_from_str(name); + bool result = + g->exported_symbol_names.maybe_get(buf_name) == nullptr && + g->external_prototypes.maybe_get(buf_name) == nullptr; + buf_destroy(buf_name); + return result; } -static Buf *get_mangled_name(CodeGen *g, Buf *original_name, bool external_linkage) { +static const char *get_mangled_name(CodeGen *g, const char *original_name, bool external_linkage) { if (external_linkage || is_symbol_available(g, original_name)) { return original_name; } int n = 0; for (;; n += 1) { - Buf *new_name = buf_sprintf("%s.%d", buf_ptr(original_name), n); + const char *new_name = buf_ptr(buf_sprintf("%s.%d", original_name, n)); if (is_symbol_available(g, new_name)) { return new_name; } @@ -387,8 +392,8 @@ static bool codegen_have_frame_pointer(CodeGen *g) { } static LLVMValueRef make_fn_llvm_value(CodeGen *g, ZigFn *fn) { - Buf *unmangled_name = &fn->symbol_name; - Buf *symbol_name; + const char *unmangled_name = buf_ptr(&fn->symbol_name); + const char *symbol_name; GlobalLinkageId linkage; if (fn->body_node == nullptr) { symbol_name = unmangled_name; @@ -398,7 +403,7 @@ static LLVMValueRef make_fn_llvm_value(CodeGen *g, ZigFn *fn) { linkage = GlobalLinkageIdInternal; } else { GlobalExport *fn_export = &fn->export_list.items[0]; - symbol_name = &fn_export->name; + symbol_name = buf_ptr(&fn_export->name); linkage = fn_export->linkage; } @@ -408,7 +413,7 @@ static LLVMValueRef make_fn_llvm_value(CodeGen *g, ZigFn *fn) { g->zig_target->arch == ZigLLVM_x86) { // prevent llvm name mangling - symbol_name = buf_sprintf("\x01_%s", buf_ptr(symbol_name)); + symbol_name = buf_ptr(buf_sprintf("\x01_%s", symbol_name)); } bool is_async = fn_is_async(fn); @@ -420,13 +425,16 @@ static LLVMValueRef make_fn_llvm_value(CodeGen *g, ZigFn *fn) { LLVMTypeRef fn_llvm_type = fn->raw_type_ref; LLVMValueRef llvm_fn = nullptr; if (fn->body_node == nullptr) { - LLVMValueRef existing_llvm_fn = LLVMGetNamedFunction(g->module, buf_ptr(symbol_name)); + LLVMValueRef existing_llvm_fn = LLVMGetNamedFunction(g->module, symbol_name); if (existing_llvm_fn) { return LLVMConstBitCast(existing_llvm_fn, LLVMPointerType(fn_llvm_type, 0)); } else { - auto entry = g->exported_symbol_names.maybe_get(symbol_name); + Buf *buf_symbol_name = buf_create_from_str(symbol_name); + auto entry = g->exported_symbol_names.maybe_get(buf_symbol_name); + buf_destroy(buf_symbol_name); + if (entry == nullptr) { - llvm_fn = LLVMAddFunction(g->module, buf_ptr(symbol_name), fn_llvm_type); + llvm_fn = LLVMAddFunction(g->module, symbol_name, fn_llvm_type); if (target_is_wasm(g->zig_target)) { assert(fn->proto_node->type == NodeTypeFnProto); @@ -440,7 +448,7 @@ static LLVMValueRef make_fn_llvm_value(CodeGen *g, ZigFn *fn) { TldFn *tld_fn = reinterpret_cast(entry->value); // Make the raw_type_ref populated resolve_llvm_types_fn(g, tld_fn->fn_entry); - tld_fn->fn_entry->llvm_value = LLVMAddFunction(g->module, buf_ptr(symbol_name), + tld_fn->fn_entry->llvm_value = LLVMAddFunction(g->module, symbol_name, tld_fn->fn_entry->raw_type_ref); llvm_fn = LLVMConstBitCast(tld_fn->fn_entry->llvm_value, LLVMPointerType(fn_llvm_type, 0)); return llvm_fn; @@ -448,7 +456,7 @@ static LLVMValueRef make_fn_llvm_value(CodeGen *g, ZigFn *fn) { } } else { if (llvm_fn == nullptr) { - llvm_fn = LLVMAddFunction(g->module, buf_ptr(symbol_name), fn_llvm_type); + llvm_fn = LLVMAddFunction(g->module, symbol_name, fn_llvm_type); } for (size_t i = 1; i < fn->export_list.length; i += 1) { @@ -1058,8 +1066,8 @@ static LLVMValueRef get_add_error_return_trace_addr_fn(CodeGen *g) { }; LLVMTypeRef fn_type_ref = LLVMFunctionType(LLVMVoidType(), arg_types, 2, false); - Buf *fn_name = get_mangled_name(g, buf_create_from_str("__zig_add_err_ret_trace_addr"), false); - LLVMValueRef fn_val = LLVMAddFunction(g->module, buf_ptr(fn_name), fn_type_ref); + const char *fn_name = get_mangled_name(g, "__zig_add_err_ret_trace_addr", false); + LLVMValueRef fn_val = LLVMAddFunction(g->module, fn_name, fn_type_ref); addLLVMFnAttr(fn_val, "alwaysinline"); LLVMSetLinkage(fn_val, LLVMInternalLinkage); LLVMSetFunctionCallConv(fn_val, get_llvm_cc(g, CallingConventionUnspecified)); @@ -1138,8 +1146,8 @@ static LLVMValueRef get_return_err_fn(CodeGen *g) { }; LLVMTypeRef fn_type_ref = LLVMFunctionType(LLVMVoidType(), arg_types, 1, false); - Buf *fn_name = get_mangled_name(g, buf_create_from_str("__zig_return_error"), false); - LLVMValueRef fn_val = LLVMAddFunction(g->module, buf_ptr(fn_name), fn_type_ref); + const char *fn_name = get_mangled_name(g, "__zig_return_error", false); + LLVMValueRef fn_val = LLVMAddFunction(g->module, fn_name, fn_type_ref); addLLVMFnAttr(fn_val, "noinline"); // so that we can look at return address addLLVMFnAttr(fn_val, "cold"); LLVMSetLinkage(fn_val, LLVMInternalLinkage); @@ -1208,7 +1216,7 @@ static LLVMValueRef get_safety_crash_err_fn(CodeGen *g) { LLVMSetLinkage(msg_prefix, LLVMInternalLinkage); LLVMSetGlobalConstant(msg_prefix, true); - Buf *fn_name = get_mangled_name(g, buf_create_from_str("__zig_fail_unwrap"), false); + const char *fn_name = get_mangled_name(g, "__zig_fail_unwrap", false); LLVMTypeRef fn_type_ref; if (g->have_err_ret_tracing) { LLVMTypeRef arg_types[] = { @@ -1222,7 +1230,7 @@ static LLVMValueRef get_safety_crash_err_fn(CodeGen *g) { }; fn_type_ref = LLVMFunctionType(LLVMVoidType(), arg_types, 1, false); } - LLVMValueRef fn_val = LLVMAddFunction(g->module, buf_ptr(fn_name), fn_type_ref); + LLVMValueRef fn_val = LLVMAddFunction(g->module, fn_name, fn_type_ref); addLLVMFnAttr(fn_val, "noreturn"); addLLVMFnAttr(fn_val, "cold"); LLVMSetLinkage(fn_val, LLVMInternalLinkage); @@ -1805,7 +1813,7 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_ fn_walk->data.types.param_di_types->append(get_llvm_di_type(g, ty)); break; case FnWalkIdVars: { - var->value_ref = build_alloca(g, ty, buf_ptr(&var->name), var->align_bytes); + var->value_ref = build_alloca(g, ty, var->name, var->align_bytes); di_arg_index = fn_walk->data.vars.gen_i; fn_walk->data.vars.gen_i += 1; dest_ty = ty; @@ -1916,7 +1924,7 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_ } case FnWalkIdVars: { di_arg_index = fn_walk->data.vars.gen_i; - var->value_ref = build_alloca(g, ty, buf_ptr(&var->name), var->align_bytes); + var->value_ref = build_alloca(g, ty, var->name, var->align_bytes); fn_walk->data.vars.gen_i += 1; dest_ty = ty; goto var_ok; @@ -1949,7 +1957,7 @@ var_ok: if (dest_ty != nullptr && var->decl_node) { // arg index + 1 because the 0 index is return value var->di_loc_var = ZigLLVMCreateParameterVariable(g->dbuilder, get_di_scope(g, var->parent_scope), - buf_ptr(&var->name), fn_walk->data.vars.import->data.structure.root_struct->di_file, + var->name, fn_walk->data.vars.import->data.structure.root_struct->di_file, (unsigned)(var->decl_node->line + 1), get_llvm_di_type(g, dest_ty), !g->strip_debug_symbols, 0, di_arg_index + 1); } @@ -2060,8 +2068,8 @@ static LLVMValueRef get_merge_err_ret_traces_fn_val(CodeGen *g) { }; LLVMTypeRef fn_type_ref = LLVMFunctionType(LLVMVoidType(), param_types, 2, false); - Buf *fn_name = get_mangled_name(g, buf_create_from_str("__zig_merge_error_return_traces"), false); - LLVMValueRef fn_val = LLVMAddFunction(g->module, buf_ptr(fn_name), fn_type_ref); + const char *fn_name = get_mangled_name(g, "__zig_merge_error_return_traces", false); + LLVMValueRef fn_val = LLVMAddFunction(g->module, fn_name, fn_type_ref); LLVMSetLinkage(fn_val, LLVMInternalLinkage); LLVMSetFunctionCallConv(fn_val, get_llvm_cc(g, CallingConventionUnspecified)); addLLVMFnAttr(fn_val, "nounwind"); @@ -3743,12 +3751,11 @@ static void render_async_spills(CodeGen *g) { continue; } - var->value_ref = LLVMBuildStructGEP(g->builder, g->cur_frame_ptr, async_var_index, - buf_ptr(&var->name)); + var->value_ref = LLVMBuildStructGEP(g->builder, g->cur_frame_ptr, async_var_index, var->name); async_var_index += 1; if (var->decl_node) { var->di_loc_var = ZigLLVMCreateAutoVariable(g->dbuilder, get_di_scope(g, var->parent_scope), - buf_ptr(&var->name), import->data.structure.root_struct->di_file, + var->name, import->data.structure.root_struct->di_file, (unsigned)(var->decl_node->line + 1), get_llvm_di_type(g, var->var_type), !g->strip_debug_symbols, 0); gen_var_debug_decl(g, var); @@ -4653,8 +4660,9 @@ static LLVMValueRef get_enum_tag_name_function(CodeGen *g, ZigType *enum_type) { LLVMTypeRef fn_type_ref = LLVMFunctionType(LLVMPointerType(get_llvm_type(g, u8_slice_type), 0), &tag_int_llvm_type, 1, false); - Buf *fn_name = get_mangled_name(g, buf_sprintf("__zig_tag_name_%s", buf_ptr(&enum_type->name)), false); - LLVMValueRef fn_val = LLVMAddFunction(g->module, buf_ptr(fn_name), fn_type_ref); + const char *fn_name = get_mangled_name(g, + buf_ptr(buf_sprintf("__zig_tag_name_%s", buf_ptr(&enum_type->name))), false); + LLVMValueRef fn_val = LLVMAddFunction(g->module, fn_name, fn_type_ref); LLVMSetLinkage(fn_val, LLVMInternalLinkage); LLVMSetFunctionCallConv(fn_val, get_llvm_cc(g, CallingConventionUnspecified)); addLLVMFnAttr(fn_val, "nounwind"); @@ -6919,7 +6927,7 @@ static void generate_error_name_table(CodeGen *g) { LLVMValueRef err_name_table_init = LLVMConstArray(get_llvm_type(g, str_type), values, (unsigned)g->errors_by_index.length); g->err_name_table = LLVMAddGlobal(g->module, LLVMTypeOf(err_name_table_init), - buf_ptr(get_mangled_name(g, buf_create_from_str("__zig_err_name_table"), false))); + get_mangled_name(g, buf_ptr(buf_create_from_str("__zig_err_name_table")), false)); LLVMSetInitializer(g->err_name_table, err_name_table_init); LLVMSetLinkage(g->err_name_table, LLVMPrivateLinkage); LLVMSetGlobalConstant(g->err_name_table, true); @@ -6960,8 +6968,8 @@ static void gen_global_var(CodeGen *g, ZigVar *var, LLVMValueRef init_val, assert(import); bool is_local_to_unit = true; - ZigLLVMCreateGlobalVariable(g->dbuilder, get_di_scope(g, var->parent_scope), buf_ptr(&var->name), - buf_ptr(&var->name), import->data.structure.root_struct->di_file, + ZigLLVMCreateGlobalVariable(g->dbuilder, get_di_scope(g, var->parent_scope), var->name, + var->name, import->data.structure.root_struct->di_file, (unsigned)(var->decl_node->line + 1), get_llvm_di_type(g, type_entry), is_local_to_unit); @@ -7043,8 +7051,8 @@ static void do_code_gen(CodeGen *g) { assert(var->decl_node); GlobalLinkageId linkage; - Buf *unmangled_name = &var->name; - Buf *symbol_name; + const char *unmangled_name = var->name; + const char *symbol_name; if (var->export_list.length == 0) { if (var->decl_node->data.variable_declaration.is_extern) { symbol_name = unmangled_name; @@ -7055,19 +7063,19 @@ static void do_code_gen(CodeGen *g) { } } else { GlobalExport *global_export = &var->export_list.items[0]; - symbol_name = &global_export->name; + symbol_name = buf_ptr(&global_export->name); linkage = global_export->linkage; } LLVMValueRef global_value; bool externally_initialized = var->decl_node->data.variable_declaration.expr == nullptr; if (externally_initialized) { - LLVMValueRef existing_llvm_var = LLVMGetNamedGlobal(g->module, buf_ptr(symbol_name)); + LLVMValueRef existing_llvm_var = LLVMGetNamedGlobal(g->module, symbol_name); if (existing_llvm_var) { global_value = LLVMConstBitCast(existing_llvm_var, LLVMPointerType(get_llvm_type(g, var->var_type), 0)); } else { - global_value = LLVMAddGlobal(g->module, get_llvm_type(g, var->var_type), buf_ptr(symbol_name)); + global_value = LLVMAddGlobal(g->module, get_llvm_type(g, var->var_type), symbol_name); // TODO debug info for the extern variable LLVMSetLinkage(global_value, to_llvm_linkage(linkage)); @@ -7078,8 +7086,8 @@ static void do_code_gen(CodeGen *g) { } } else { bool exported = (linkage != GlobalLinkageIdInternal); - render_const_val(g, var->const_value, buf_ptr(symbol_name)); - render_const_val_global(g, var->const_value, buf_ptr(symbol_name)); + render_const_val(g, var->const_value, symbol_name); + render_const_val_global(g, var->const_value, symbol_name); global_value = var->const_value->global_refs->llvm_global; if (exported) { @@ -7234,7 +7242,7 @@ static void do_code_gen(CodeGen *g) { if (var->src_arg_index == SIZE_MAX) { var->di_loc_var = ZigLLVMCreateAutoVariable(g->dbuilder, get_di_scope(g, var->parent_scope), - buf_ptr(&var->name), import->data.structure.root_struct->di_file, (unsigned)(var->decl_node->line + 1), + var->name, import->data.structure.root_struct->di_file, (unsigned)(var->decl_node->line + 1), get_llvm_di_type(g, var->var_type), !g->strip_debug_symbols, 0); } else if (is_c_abi) { @@ -7254,11 +7262,11 @@ static void do_code_gen(CodeGen *g) { var->value_ref = LLVMGetParam(fn, gen_info->gen_index); } else { gen_type = var->var_type; - var->value_ref = build_alloca(g, var->var_type, buf_ptr(&var->name), var->align_bytes); + var->value_ref = build_alloca(g, var->var_type, var->name, var->align_bytes); } if (var->decl_node) { var->di_loc_var = ZigLLVMCreateParameterVariable(g->dbuilder, get_di_scope(g, var->parent_scope), - buf_ptr(&var->name), import->data.structure.root_struct->di_file, + var->name, import->data.structure.root_struct->di_file, (unsigned)(var->decl_node->line + 1), get_llvm_di_type(g, gen_type), !g->strip_debug_symbols, 0, (unsigned)(gen_info->gen_index+1)); } diff --git a/src/ir.cpp b/src/ir.cpp index 6b71fa8d17f8710f57a8d7e047aacbb4f5777a49..ca2c59e34281fdb43bc9315a29649444feefcb6c 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -3628,7 +3628,7 @@ static ZigVar *create_local_var(CodeGen *codegen, AstNode *node, Scope *parent_s } if (name) { - buf_init_from_buf(&variable_entry->name, name); + variable_entry->name = strdup(buf_ptr(name)); if (!skip_name_check) { ZigVar *existing_var = find_variable(codegen, parent_scope, name, nullptr); @@ -3661,7 +3661,7 @@ static ZigVar *create_local_var(CodeGen *codegen, AstNode *node, Scope *parent_s // TODO make this name not actually be in scope. user should be able to make a variable called "_anon" // might already be solved, let's just make sure it has test coverage // maybe we put a prefix on this so the debug info doesn't clobber user debug info for same named variables - buf_init_from_str(&variable_entry->name, "_anon"); + variable_entry->name = "_anon"; } variable_entry->src_is_const = src_is_const; @@ -6467,15 +6467,15 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo } assert(elem_node->type == NodeTypeSymbol); - IrInstruction *array_val_ptr = ir_gen_node_extra(irb, array_node, parent_scope, LValPtr, nullptr); + ScopeExpr *spill_scope = create_expr_scope(irb->codegen, node, parent_scope); + + IrInstruction *array_val_ptr = ir_gen_node_extra(irb, array_node, &spill_scope->base, LValPtr, nullptr); if (array_val_ptr == irb->codegen->invalid_instruction) return array_val_ptr; IrInstruction *is_comptime = ir_build_const_bool(irb, parent_scope, node, ir_should_inline(irb->exec, parent_scope) || node->data.for_expr.is_inline); - ScopeExpr *spill_scope = create_expr_scope(irb->codegen, node, parent_scope); - AstNode *index_var_source_node; ZigVar *index_var; const char *index_var_name; @@ -14559,7 +14559,8 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, // We make a new variable so that it can hold a different type, and so the debug info can // be distinct. ZigVar *new_var = create_local_var(ira->codegen, var->decl_node, var->child_scope, - &var->name, var->src_is_const, var->gen_is_const, var->shadowable, var->is_comptime, true); + buf_create_from_str(var->name), var->src_is_const, var->gen_is_const, + var->shadowable, var->is_comptime, true); new_var->owner_exec = var->owner_exec; new_var->align_bytes = var->align_bytes; if (var->mem_slot_index != SIZE_MAX) { @@ -14702,7 +14703,8 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio case CallingConventionNaked: case CallingConventionCold: case CallingConventionStdcall: - add_fn_export(ira->codegen, fn_entry, symbol_name, global_linkage_id, cc == CallingConventionC); + add_fn_export(ira->codegen, fn_entry, buf_ptr(symbol_name), global_linkage_id, + cc == CallingConventionC); break; } } break; @@ -14840,7 +14842,7 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio if (load_ptr->ptr->id == IrInstructionIdVarPtr) { IrInstructionVarPtr *var_ptr = reinterpret_cast(load_ptr->ptr); ZigVar *var = var_ptr->var; - add_var_export(ira->codegen, var, symbol_name, global_linkage_id); + add_var_export(ira->codegen, var, buf_ptr(symbol_name), global_linkage_id); } } @@ -17023,7 +17025,7 @@ static IrInstruction *ir_analyze_instruction_var_ptr(IrAnalyze *ira, IrInstructi IrInstruction *result = ir_get_var_ptr(ira, &instruction->base, var); if (instruction->crossed_fndef_scope != nullptr && !instr_is_comptime(result)) { ErrorMsg *msg = ir_add_error(ira, &instruction->base, - buf_sprintf("'%s' not accessible from inner function", buf_ptr(&var->name))); + buf_sprintf("'%s' not accessible from inner function", var->name)); add_error_note(ira->codegen, msg, instruction->crossed_fndef_scope->base.source_node, buf_sprintf("crossed function definition here")); add_error_note(ira->codegen, msg, var->decl_node, @@ -17735,7 +17737,8 @@ static IrInstruction *ir_analyze_decl_ref(IrAnalyze *ira, IrInstruction *source_ return ir_error_dependency_loop(ira, source_instruction); } if (tld_var->extern_lib_name != nullptr) { - add_link_lib_symbol(ira, tld_var->extern_lib_name, &var->name, source_instruction->source_node); + add_link_lib_symbol(ira, tld_var->extern_lib_name, buf_create_from_str(var->name), + source_instruction->source_node); } return ir_get_var_ptr(ira, source_instruction, var); @@ -20189,8 +20192,9 @@ static Error ir_make_type_info_decls(IrAnalyze *ira, IrInstruction *source_instr for (size_t fn_arg_index = 0; fn_arg_index < fn_arg_count; fn_arg_index++) { ZigVar *arg_var = fn_entry->variable_list.at(fn_arg_index); ConstExprValue *fn_arg_name_val = &fn_arg_name_array->data.x_array.data.s_none.elements[fn_arg_index]; - ConstExprValue *arg_name = create_const_str_lit(ira->codegen, &arg_var->name); - init_const_slice(ira->codegen, fn_arg_name_val, arg_name, 0, buf_len(&arg_var->name), true); + ConstExprValue *arg_name = create_const_str_lit(ira->codegen, + buf_create_from_str(arg_var->name)); + init_const_slice(ira->codegen, fn_arg_name_val, arg_name, 0, strlen(arg_var->name), true); fn_arg_name_val->parent.id = ConstParentIdArray; fn_arg_name_val->parent.data.p_array.array_val = fn_arg_name_array; fn_arg_name_val->parent.data.p_array.elem_index = fn_arg_index; diff --git a/src/ir_print.cpp b/src/ir_print.cpp index 30b87352444ef394a35ea211d16cad9984c25aab..f2877b46e63cd4386e98db0fa69933a50680e61e 100644 --- a/src/ir_print.cpp +++ b/src/ir_print.cpp @@ -531,7 +531,7 @@ static void ir_print_bin_op(IrPrint *irp, IrInstructionBinOp *bin_op_instruction static void ir_print_decl_var_src(IrPrint *irp, IrInstructionDeclVarSrc *decl_var_instruction) { const char *var_or_const = decl_var_instruction->var->gen_is_const ? "const" : "var"; - const char *name = buf_ptr(&decl_var_instruction->var->name); + const char *name = decl_var_instruction->var->name; if (decl_var_instruction->var_type) { fprintf(irp->f, "%s %s: ", var_or_const, name); ir_print_other_instruction(irp, decl_var_instruction->var_type); @@ -747,7 +747,7 @@ static void ir_print_elem_ptr(IrPrint *irp, IrInstructionElemPtr *instruction) { } static void ir_print_var_ptr(IrPrint *irp, IrInstructionVarPtr *instruction) { - fprintf(irp->f, "&%s", buf_ptr(&instruction->var->name)); + fprintf(irp->f, "&%s", instruction->var->name); } static void ir_print_return_ptr(IrPrint *irp, IrInstructionReturnPtr *instruction) { @@ -1852,7 +1852,7 @@ static void ir_print_mul_add(IrPrint *irp, IrInstructionMulAdd *instruction) { static void ir_print_decl_var_gen(IrPrint *irp, IrInstructionDeclVarGen *decl_var_instruction) { ZigVar *var = decl_var_instruction->var; const char *var_or_const = decl_var_instruction->var->gen_is_const ? "const" : "var"; - const char *name = buf_ptr(&decl_var_instruction->var->name); + const char *name = decl_var_instruction->var->name; fprintf(irp->f, "%s %s: %s align(%u) = ", var_or_const, name, buf_ptr(&var->var_type->name), var->align_bytes); diff --git a/test/stage1/behavior/async_fn.zig b/test/stage1/behavior/async_fn.zig index 3ee728f8a57ade19a946f6a988a7dc873dcb57fd..86a0b659a8b51b502ff2bb8e7d62f2ee4cc1ed00 100644 --- a/test/stage1/behavior/async_fn.zig +++ b/test/stage1/behavior/async_fn.zig @@ -1201,3 +1201,35 @@ test "correctly spill when returning the error union result of another async fn" resume S.global_frame; } + +test "spill target expr in a for loop" { + const S = struct { + var global_frame: anyframe = undefined; + + fn doTheTest() void { + var foo = Foo{ + .slice = [_]i32{1, 2}, + }; + expect(atest(&foo) == 3); + } + + const Foo = struct { + slice: []i32, + }; + + fn atest(foo: *Foo) i32 { + var sum: i32 = 0; + for (foo.slice) |x| { + suspend { + global_frame = @frame(); + } + sum += x; + } + return sum; + } + }; + _ = async S.doTheTest(); + resume S.global_frame; + resume S.global_frame; +} + -- 2.54.0 From fec795cd29909f0e43ba9de303b93309db8858b5 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Mon, 9 Sep 2019 21:57:35 +0200 Subject: [PATCH 71/80] Adjust the stdlib to be 32bit compatible --- std/hash/cityhash.zig | 8 ++++---- std/hash/murmur.zig | 6 +++--- std/os/bits/linux/arm-eabi.zig | 2 ++ 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/std/hash/cityhash.zig b/std/hash/cityhash.zig index a4d7fc8218196ff7a28bd2acef023e6761fe4648..43e5b7a385cc30e657ded4b253fa3c2a99a85a8f 100644 --- a/std/hash/cityhash.zig +++ b/std/hash/cityhash.zig @@ -214,7 +214,7 @@ pub const CityHash64 = struct { } fn hashLen0To16(str: []const u8) u64 { - const len: u64 = @truncate(u64, str.len); + const len: u64 = u64(str.len); if (len >= 8) { const mul: u64 = k2 +% len *% 2; const a: u64 = fetch64(str.ptr) +% k2; @@ -240,7 +240,7 @@ pub const CityHash64 = struct { } fn hashLen17To32(str: []const u8) u64 { - const len: u64 = @truncate(u64, str.len); + const len: u64 = u64(str.len); const mul: u64 = k2 +% len *% 2; const a: u64 = fetch64(str.ptr) *% k1; const b: u64 = fetch64(str.ptr + 8); @@ -251,7 +251,7 @@ pub const CityHash64 = struct { } fn hashLen33To64(str: []const u8) u64 { - const len: u64 = @truncate(u64, str.len); + const len: u64 = u64(str.len); const mul: u64 = k2 +% len *% 2; const a: u64 = fetch64(str.ptr) *% k2; const b: u64 = fetch64(str.ptr + 8); @@ -305,7 +305,7 @@ pub const CityHash64 = struct { return hashLen33To64(str); } - var len: u64 = @truncate(u64, str.len); + var len: u64 = u64(str.len); var x: u64 = fetch64(str.ptr + str.len - 40); var y: u64 = fetch64(str.ptr + str.len - 16) +% fetch64(str.ptr + str.len - 56); diff --git a/std/hash/murmur.zig b/std/hash/murmur.zig index 79d05bf462a169df6a3336b3f19f8120c7f6adfc..a0c8f91338ce4ad29b5204dd80ae00664de209f6 100644 --- a/std/hash/murmur.zig +++ b/std/hash/murmur.zig @@ -98,9 +98,9 @@ pub const Murmur2_64 = struct { pub fn hashWithSeed(str: []const u8, seed: u64) u64 { const m: u64 = 0xc6a4a7935bd1e995; - const len = @truncate(u64, str.len); + const len = u64(str.len); var h1: u64 = seed ^ (len *% m); - for (@ptrCast([*]allowzero align(1) const u64, str.ptr)[0..(len >> 3)]) |v| { + for (@ptrCast([*]allowzero align(1) const u64, str.ptr)[0..@intCast(usize, len >> 3)]) |v| { var k1: u64 = v; if (builtin.endian == builtin.Endian.Big) k1 = @byteSwap(u64, k1); @@ -114,7 +114,7 @@ pub const Murmur2_64 = struct { const offset = len - rest; if (rest > 0) { var k1: u64 = 0; - @memcpy(@ptrCast([*]u8, &k1), @ptrCast([*]const u8, &str[offset]), rest); + @memcpy(@ptrCast([*]u8, &k1), @ptrCast([*]const u8, &str[@intCast(usize, offset)]), @intCast(usize, rest)); if (builtin.endian == builtin.Endian.Big) k1 = @byteSwap(u64, k1); h1 ^= k1; diff --git a/std/os/bits/linux/arm-eabi.zig b/std/os/bits/linux/arm-eabi.zig index ca80b67fe19adcea75b2da4eb55dacdc7d2fb14b..806a065059adf4f2835cd34b5c47d19810266c81 100644 --- a/std/os/bits/linux/arm-eabi.zig +++ b/std/os/bits/linux/arm-eabi.zig @@ -569,3 +569,5 @@ pub const timezone = extern struct { tz_minuteswest: i32, tz_dsttime: i32, }; + +pub const Elf_Symndx = u32; -- 2.54.0 From 852679c3695af19f218fdc9eab22c6fdf8d09622 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 9 Sep 2019 16:44:23 -0400 Subject: [PATCH 72/80] fix a var decl in scope preventing for loop spills --- src/analyze.cpp | 11 ++++++++-- test/stage1/behavior/async_fn.zig | 35 +++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 2 deletions(-) diff --git a/src/analyze.cpp b/src/analyze.cpp index 32cb3c0624ad42e420e094ef1bc1688c8aff6fac..2dfb540801e0e6624f09063e36002d52bc5bb7f1 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -5701,23 +5701,30 @@ static ZigType *get_async_fn_type(CodeGen *g, ZigType *orig_fn_type) { // (await y) + x static void mark_suspension_point(Scope *scope) { ScopeExpr *child_expr_scope = (scope->id == ScopeIdExpr) ? reinterpret_cast(scope) : nullptr; + bool looking_for_exprs = true; for (;;) { scope = scope->parent; switch (scope->id) { - case ScopeIdDefer: case ScopeIdDeferExpr: case ScopeIdDecls: case ScopeIdFnDef: case ScopeIdCompTime: - case ScopeIdVarDecl: case ScopeIdCImport: case ScopeIdSuspend: case ScopeIdTypeOf: return; + case ScopeIdVarDecl: + case ScopeIdDefer: + looking_for_exprs = false; + continue; case ScopeIdLoop: case ScopeIdRuntime: continue; case ScopeIdExpr: { + if (!looking_for_exprs) { + // Now we're only looking for a block, to see if it's in a loop (see the case ScopeIdBlock) + continue; + } ScopeExpr *parent_expr_scope = reinterpret_cast(scope); if (child_expr_scope != nullptr) { for (size_t i = 0; parent_expr_scope->children_ptr[i] != child_expr_scope; i += 1) { diff --git a/test/stage1/behavior/async_fn.zig b/test/stage1/behavior/async_fn.zig index 86a0b659a8b51b502ff2bb8e7d62f2ee4cc1ed00..8445bcb5b25b8b84ba08030d4ef86e5494aa47d3 100644 --- a/test/stage1/behavior/async_fn.zig +++ b/test/stage1/behavior/async_fn.zig @@ -1233,3 +1233,38 @@ test "spill target expr in a for loop" { resume S.global_frame; } +test "spill target expr in a for loop, with a var decl in the loop body" { + const S = struct { + var global_frame: anyframe = undefined; + + fn doTheTest() void { + var foo = Foo{ + .slice = [_]i32{1, 2}, + }; + expect(atest(&foo) == 3); + } + + const Foo = struct { + slice: []i32, + }; + + fn atest(foo: *Foo) i32 { + var sum: i32 = 0; + for (foo.slice) |x| { + // Previously this var decl would prevent spills. This test makes sure + // the for loop spills still happen even though there is a VarDecl in scope + // before the suspend. + var anything = true; + _ = anything; + suspend { + global_frame = @frame(); + } + sum += x; + } + return sum; + } + }; + _ = async S.doTheTest(); + resume S.global_frame; + resume S.global_frame; +} -- 2.54.0 From 8bd5681651f64c7ebe059e6d7b288ddc60658cd5 Mon Sep 17 00:00:00 2001 From: Michael Dusan Date: Mon, 9 Sep 2019 17:57:32 -0400 Subject: [PATCH 73/80] fix tests.addPkgTests to always run native target MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - include native-target when native-target ∉ cross_targets old behavior: - do nothing when `-Dskip-non-native` - never execute pkg tests for non-members of cross_targets --- test/tests.zig | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/test/tests.zig b/test/tests.zig index 99ee5949c3546a66a52fe344ccfa21864ec163b8..bbaf62ac94dfb2a9fec54a7443d9314e2582d41a 100644 --- a/test/tests.zig +++ b/test/tests.zig @@ -23,7 +23,7 @@ const runtime_safety = @import("runtime_safety.zig"); const translate_c = @import("translate_c.zig"); const gen_h = @import("gen_h.zig"); -const test_targets = [_]CrossTarget{ +const cross_targets = [_]CrossTarget{ CrossTarget{ .os = .linux, .arch = .x86_64, @@ -186,7 +186,17 @@ pub fn addPkgTests( skip_non_native: bool, ) *build.Step { const step = b.step(b.fmt("test-{}", name), desc); - for (test_targets) |test_target| { + + var targets = std.ArrayList(*const CrossTarget).init(b.allocator); + defer targets.deinit(); + const host = CrossTarget{ .os = builtin.os, .arch = builtin.arch, .abi = builtin.abi }; + targets.append(&host) catch unreachable; + for (cross_targets) |*t| { + if (t.os == builtin.os and t.arch == builtin.arch and t.abi == builtin.abi) continue; + targets.append(t) catch unreachable; + } + + for (targets.toSliceConst()) |test_target| { const is_native = (test_target.os == builtin.os and test_target.arch == builtin.arch); if (skip_non_native and !is_native) continue; -- 2.54.0 From a06f84fcc62396dc4216d5c9f8da1f0463d17f50 Mon Sep 17 00:00:00 2001 From: Sahnvour Date: Sat, 7 Sep 2019 13:22:33 +0200 Subject: [PATCH 74/80] forbid opaque types in function return types --- src/analyze.cpp | 32 +++++++++++++++++++++++++++----- test/compile_errors.zig | 11 +++++++++++ 2 files changed, 38 insertions(+), 5 deletions(-) diff --git a/src/analyze.cpp b/src/analyze.cpp index 2dfb540801e0e6624f09063e36002d52bc5bb7f1..e06faba7a9f78b5ee04f3eb486d54f73136bee33 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -1757,6 +1757,32 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc return g->builtin_types.entry_invalid; } + switch (specified_return_type->id) { + case ZigTypeIdInvalid: + zig_unreachable(); + + case ZigTypeIdUndefined: + case ZigTypeIdNull: + case ZigTypeIdArgTuple: + add_node_error(g, fn_proto->return_type, + buf_sprintf("return type '%s' not allowed", buf_ptr(&specified_return_type->name))); + return g->builtin_types.entry_invalid; + + case ZigTypeIdOpaque: + { + ErrorMsg* msg = add_node_error(g, fn_proto->return_type, + buf_sprintf("opaque return type '%s' not allowed", buf_ptr(&specified_return_type->name))); + Tld *tld = find_decl(g, &fn_entry->fndef_scope->base, &specified_return_type->name); + if (tld != nullptr) { + add_error_note(g, msg, tld->source_node, buf_sprintf("declared here")); + } + return g->builtin_types.entry_invalid; + } + + default: + break; + } + if (fn_proto->auto_err_set) { ZigType *inferred_err_set_type = get_auto_err_set_type(g, fn_entry); if ((err = type_resolve(g, specified_return_type, ResolveStatusSizeKnown))) @@ -1782,15 +1808,11 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc switch (fn_type_id.return_type->id) { case ZigTypeIdInvalid: - zig_unreachable(); - case ZigTypeIdUndefined: case ZigTypeIdNull: case ZigTypeIdArgTuple: case ZigTypeIdOpaque: - add_node_error(g, fn_proto->return_type, - buf_sprintf("return type '%s' not allowed", buf_ptr(&fn_type_id.return_type->name))); - return g->builtin_types.entry_invalid; + zig_unreachable(); case ZigTypeIdComptimeFloat: case ZigTypeIdComptimeInt: diff --git a/test/compile_errors.zig b/test/compile_errors.zig index d9ad5b7f82a10ff1917fa3d63ee16c0741ad77bc..6365ca64cbddc843d3639022be8d1fc10c7ab1f5 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -6556,4 +6556,15 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { , "tmp.zig:2:5: error: variable 's' of zero-bit type 'struct:2:12' has no in-memory representation, it cannot be aligned", ); + + cases.add( + "function returning opaque type", + \\const FooType = @OpaqueType(); + \\export fn bar() !FooType { + \\ return error.InvalidValue; + \\} + , + "tmp.zig:2:18: error: opaque return type 'FooType' not allowed", + "tmp.zig:1:1: note: declared here", + ); } -- 2.54.0 From 8fbae77770a77ccd645054e06baab45b03c8befd Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Sat, 7 Sep 2019 11:17:12 +0200 Subject: [PATCH 75/80] Force LLVM to generate byte-aligned packed unions Sometimes the frontend and LLVM would disagree on the ABI alignment of a packed union. Solve the problem by telling LLVM we're gonna manage the struct layout by ourselves. Closes #3184 --- src/analyze.cpp | 8 +++++--- test/stage1/behavior/union.zig | 12 ++++++++++++ 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/analyze.cpp b/src/analyze.cpp index e06faba7a9f78b5ee04f3eb486d54f73136bee33..b845dc8388e0a2ada41e23fc95123962e8f113b1 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -7905,6 +7905,8 @@ static void resolve_llvm_types_enum(CodeGen *g, ZigType *enum_type, ResolveStatu static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveStatus wanted_resolve_status) { if (union_type->data.unionation.resolve_status >= wanted_resolve_status) return; + bool packed = (union_type->data.unionation.layout == ContainerLayoutPacked); + TypeUnionField *most_aligned_union_member = union_type->data.unionation.most_aligned_union_member; ZigType *tag_type = union_type->data.unionation.tag_type; uint32_t gen_field_count = union_type->data.unionation.gen_field_count; @@ -7971,9 +7973,9 @@ static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveSta most_aligned_union_member->type_entry->llvm_type, get_llvm_type(g, padding_array), }; - LLVMStructSetBody(union_type->llvm_type, union_element_types, 2, false); + LLVMStructSetBody(union_type->llvm_type, union_element_types, 2, packed); } else { - LLVMStructSetBody(union_type->llvm_type, &most_aligned_union_member->type_entry->llvm_type, 1, false); + LLVMStructSetBody(union_type->llvm_type, &most_aligned_union_member->type_entry->llvm_type, 1, packed); } union_type->data.unionation.union_llvm_type = union_type->llvm_type; union_type->data.unionation.gen_tag_index = SIZE_MAX; @@ -8012,7 +8014,7 @@ static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveSta LLVMTypeRef root_struct_element_types[2]; root_struct_element_types[union_type->data.unionation.gen_tag_index] = get_llvm_type(g, tag_type); root_struct_element_types[union_type->data.unionation.gen_union_index] = union_type_ref; - LLVMStructSetBody(union_type->llvm_type, root_struct_element_types, 2, false); + LLVMStructSetBody(union_type->llvm_type, root_struct_element_types, 2, packed); // create debug type for union ZigLLVMDIType *union_di_type = ZigLLVMCreateDebugUnionType(g->dbuilder, diff --git a/test/stage1/behavior/union.zig b/test/stage1/behavior/union.zig index 7c5c6532755b1fb7edc4d1663bb183ebdf106cc7..21308b0ea25f9e489627c28952cb34da953e77e2 100644 --- a/test/stage1/behavior/union.zig +++ b/test/stage1/behavior/union.zig @@ -482,3 +482,15 @@ test "comparison between union and enum literal" { testComparison(); comptime testComparison(); } + +test "packed union generates correctly aligned LLVM type" { + const U = packed union { + f1: fn () void, + f2: u32, + }; + var foo = [_]U{ + U{ .f1 = doTest }, + U{ .f2 = 0 }, + }; + foo[0].f1(); +} -- 2.54.0 From a29ce78651c05029dbd72064752a099885edfd0c Mon Sep 17 00:00:00 2001 From: daurnimator Date: Mon, 8 Jul 2019 01:09:54 +1000 Subject: [PATCH 76/80] std: add BloomFilter data structure --- std/bloom_filter.zig | 253 +++++++++++++++++++++++++++++++++++++++++++ std/meta.zig | 3 +- std/std.zig | 3 + 3 files changed, 258 insertions(+), 1 deletion(-) create mode 100644 std/bloom_filter.zig diff --git a/std/bloom_filter.zig b/std/bloom_filter.zig new file mode 100644 index 0000000000000000000000000000000000000000..3e167a4115f819abb3cad9728c53a13c5ab78789 --- /dev/null +++ b/std/bloom_filter.zig @@ -0,0 +1,253 @@ +const builtin = @import("builtin"); +const std = @import("std.zig"); +const math = std.math; +const debug = std.debug; +const assert = std.debug.assert; +const testing = std.testing; + +/// There is a trade off of how quickly to fill a bloom filter; +/// the number of items is: +/// n_items / K * ln(2) +/// the rate of false positives is: +/// (1-e^(-K*N/n_items))^K +/// where N is the number of items +pub fn BloomFilter( + /// Size of bloom filter in cells, must be a power of two. + comptime n_items: usize, + /// Number of cells to set per item + comptime K: usize, + /// Cell type, should be: + /// - `bool` for a standard bloom filter + /// - an unsigned integer type for a counting bloom filter + comptime Cell: type, + /// endianess of the Cell + comptime endian: builtin.Endian, + /// Hash function to use + comptime hash: fn (out: []u8, Ki: usize, in: []const u8) void, +) type { + assert(n_items > 0); + assert(math.isPowerOfTwo(n_items)); + assert(K > 0); + const cellEmpty = if (Cell == bool) false else Cell(0); + const cellMax = if (Cell == bool) true else math.maxInt(Cell); + const n_bytes = (n_items * comptime std.meta.bitCount(Cell)) / 8; + assert(n_bytes > 0); + const Io = std.packed_int_array.PackedIntIo(Cell, endian); + + return struct { + const Self = @This(); + pub const items = n_items; + pub const Index = math.IntFittingRange(0, n_items - 1); + + data: [n_bytes]u8 = [_]u8{0} ** n_bytes, + + pub fn reset(self: *Self) void { + std.mem.set(u8, self.data[0..], 0); + } + + pub fn @"union"(x: Self, y: Self) Self { + var r = Self{ .data = undefined }; + inline for (x.data) |v, i| { + r.data[i] = v | y.data[i]; + } + return r; + } + + pub fn intersection(x: Self, y: Self) Self { + var r = Self{ .data = undefined }; + inline for (x.data) |v, i| { + r.data[i] = v & y.data[i]; + } + return r; + } + + pub fn getCell(self: Self, cell: Index) Cell { + return Io.get(self.data, cell, 0); + } + + pub fn incrementCell(self: *Self, cell: Index) void { + if (Cell == bool or Cell == u1) { + // skip the 'get' operation + Io.set(&self.data, cell, 0, cellMax); + } else { + const old = Io.get(self.data, cell, 0); + if (old != cellMax) { + Io.set(&self.data, cell, 0, old + 1); + } + } + } + + pub fn clearCell(self: *Self, cell: Index) void { + Io.set(&self.data, cell, 0, cellEmpty); + } + + pub fn add(self: *Self, item: []const u8) void { + comptime var i = 0; + inline while (i < K) : (i += 1) { + var K_th_bit: packed struct { x: Index } = undefined; + hash(std.mem.asBytes(&K_th_bit), i, item); + incrementCell(self, K_th_bit.x); + } + } + + pub fn contains(self: Self, item: []const u8) bool { + comptime var i = 0; + inline while (i < K) : (i += 1) { + var K_th_bit: packed struct { x: Index } = undefined; + hash(std.mem.asBytes(&K_th_bit), i, item); + if (getCell(self, K_th_bit.x) == cellEmpty) + return false; + } + return true; + } + + pub fn resize(self: Self, comptime newsize: usize) BloomFilter(newsize, K, Cell, endian, hash) { + var r: BloomFilter(newsize, K, Cell, endian, hash) = undefined; + if (newsize < n_items) { + std.mem.copy(u8, r.data[0..], self.data[0..r.data.len]); + var copied: usize = r.data.len; + while (copied < self.data.len) : (copied += r.data.len) { + for (self.data[copied .. copied + r.data.len]) |s, i| { + r.data[i] |= s; + } + } + } else if (newsize == n_items) { + r = self; + } else if (newsize > n_items) { + var copied: usize = 0; + while (copied < r.data.len) : (copied += self.data.len) { + std.mem.copy(u8, r.data[copied .. copied + self.data.len], self.data); + } + } + return r; + } + + /// Returns number of non-zero cells + pub fn popCount(self: Self) Index { + var n: Index = 0; + if (Cell == bool or Cell == u1) { + for (self.data) |b, i| { + n += @popCount(u8, b); + } + } else { + var i: usize = 0; + while (i < n_items) : (i += 1) { + const cell = self.getCell(@intCast(Index, i)); + n += if (if (Cell == bool) cell else cell > 0) Index(1) else Index(0); + } + } + return n; + } + + pub fn estimateItems(self: Self) f64 { + const m = comptime @intToFloat(f64, n_items); + const k = comptime @intToFloat(f64, K); + const X = @intToFloat(f64, self.popCount()); + return (comptime (-m / k)) * math.log1p(X * comptime (-1 / m)); + } + }; +} + +fn hashFunc(out: []u8, Ki: usize, in: []const u8) void { + var st = std.crypto.gimli.Hash.init(); + st.update(std.mem.asBytes(&Ki)); + st.update(in); + st.final(out); +} + +test "std.BloomFilter" { + inline for ([_]type{ bool, u1, u2, u3, u4 }) |Cell| { + const emptyCell = if (Cell == bool) false else Cell(0); + const BF = BloomFilter(128 * 8, 8, Cell, builtin.endian, hashFunc); + var bf = BF{}; + var i: usize = undefined; + // confirm that it is initialised to the empty filter + i = 0; + while (i < BF.items) : (i += 1) { + testing.expectEqual(emptyCell, bf.getCell(@intCast(BF.Index, i))); + } + testing.expectEqual(BF.Index(0), bf.popCount()); + testing.expectEqual(f64(0), bf.estimateItems()); + // fill in a few items + bf.incrementCell(42); + bf.incrementCell(255); + bf.incrementCell(256); + bf.incrementCell(257); + // check that they were set + testing.expectEqual(true, bf.getCell(42) != emptyCell); + testing.expectEqual(true, bf.getCell(255) != emptyCell); + testing.expectEqual(true, bf.getCell(256) != emptyCell); + testing.expectEqual(true, bf.getCell(257) != emptyCell); + // clear just one of them; make sure the rest are still set + bf.clearCell(256); + testing.expectEqual(true, bf.getCell(42) != emptyCell); + testing.expectEqual(true, bf.getCell(255) != emptyCell); + testing.expectEqual(false, bf.getCell(256) != emptyCell); + testing.expectEqual(true, bf.getCell(257) != emptyCell); + // reset any of the ones we've set and confirm we're back to the empty filter + bf.clearCell(42); + bf.clearCell(255); + bf.clearCell(257); + i = 0; + while (i < BF.items) : (i += 1) { + testing.expectEqual(emptyCell, bf.getCell(@intCast(BF.Index, i))); + } + testing.expectEqual(BF.Index(0), bf.popCount()); + testing.expectEqual(f64(0), bf.estimateItems()); + + // Lets add a string + bf.add("foo"); + testing.expectEqual(true, bf.contains("foo")); + { + // try adding same string again. make sure popcount is the same + const old_popcount = bf.popCount(); + testing.expect(old_popcount > 0); + bf.add("foo"); + testing.expectEqual(true, bf.contains("foo")); + testing.expectEqual(old_popcount, bf.popCount()); + } + + // Get back to empty filter via .reset + bf.reset(); + // Double check that .reset worked + i = 0; + while (i < BF.items) : (i += 1) { + testing.expectEqual(emptyCell, bf.getCell(@intCast(BF.Index, i))); + } + testing.expectEqual(BF.Index(0), bf.popCount()); + testing.expectEqual(f64(0), bf.estimateItems()); + + comptime var teststrings = [_][]const u8{ + "foo", + "bar", + "a longer string", + "some more", + "the quick brown fox", + "unique string", + }; + inline for (teststrings) |str| { + bf.add(str); + } + inline for (teststrings) |str| { + testing.expectEqual(true, bf.contains(str)); + } + + { // estimate should be close for low packing + const est = bf.estimateItems(); + testing.expect(est > @intToFloat(f64, teststrings.len) - 1); + testing.expect(est < @intToFloat(f64, teststrings.len) + 1); + } + + const larger_bf = bf.resize(4096); + inline for (teststrings) |str| { + testing.expectEqual(true, larger_bf.contains(str)); + } + testing.expectEqual(u12(bf.popCount()) * (4096 / 1024), larger_bf.popCount()); + + const smaller_bf = bf.resize(64); + inline for (teststrings) |str| { + testing.expectEqual(true, smaller_bf.contains(str)); + } + testing.expect(bf.popCount() <= u10(smaller_bf.popCount()) * (1024 / 64)); + } +} diff --git a/std/meta.zig b/std/meta.zig index 6b90727737e7cb63596e5f4887e91dc95941dc1a..52d8b54ecca540ec0e8ca44f1d7ffd583ddcd8cc 100644 --- a/std/meta.zig +++ b/std/meta.zig @@ -74,9 +74,10 @@ test "std.meta.stringToEnum" { pub fn bitCount(comptime T: type) comptime_int { return switch (@typeInfo(T)) { + TypeId.Bool => 1, TypeId.Int => |info| info.bits, TypeId.Float => |info| info.bits, - else => @compileError("Expected int or float type, found '" ++ @typeName(T) ++ "'"), + else => @compileError("Expected bool, int or float type, found '" ++ @typeName(T) ++ "'"), }; } diff --git a/std/std.zig b/std/std.zig index 18bd550eb5ee9cc3338913d7e05779f7c5eb253e..1c64242c4b36e6151660ee35ed95c92af6c56796 100644 --- a/std/std.zig +++ b/std/std.zig @@ -1,6 +1,7 @@ pub const AlignedArrayList = @import("array_list.zig").AlignedArrayList; pub const ArrayList = @import("array_list.zig").ArrayList; pub const AutoHashMap = @import("hash_map.zig").AutoHashMap; +pub const BloomFilter = @import("bloom_filter.zig").BloomFilter; pub const BufMap = @import("buf_map.zig").BufMap; pub const BufSet = @import("buf_set.zig").BufSet; pub const Buffer = @import("buffer.zig").Buffer; @@ -48,6 +49,7 @@ pub const mem = @import("mem.zig"); pub const meta = @import("meta.zig"); pub const net = @import("net.zig"); pub const os = @import("os.zig"); +pub const packed_int_array = @import("packed_int_array.zig"); pub const pdb = @import("pdb.zig"); pub const process = @import("process.zig"); pub const rand = @import("rand.zig"); @@ -64,6 +66,7 @@ test "std" { // run tests from these _ = @import("array_list.zig"); _ = @import("atomic.zig"); + _ = @import("bloom_filter.zig"); _ = @import("buf_map.zig"); _ = @import("buf_set.zig"); _ = @import("buffer.zig"); -- 2.54.0 From 0489d06c249d16457d66523b5c407fc7ddeca45a Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 10 Sep 2019 00:25:37 -0400 Subject: [PATCH 77/80] make the std lib support event-based I/O also add -fstack-report --- CMakeLists.txt | 1 + src/all_types.hpp | 3 + src/analyze.cpp | 23 +++-- src/main.cpp | 12 +++ src/stack_report.cpp | 78 +++++++++++++++++ src/stack_report.hpp | 16 ++++ std/c.zig | 1 + std/debug.zig | 43 +++++++--- std/event.zig | 2 - std/event/io.zig | 76 ---------------- std/event/loop.zig | 14 ++- std/io.zig | 188 +++------------------------------------- std/io/in_stream.zig | 200 +++++++++++++++++++++++++++++++++++++++++++ std/os.zig | 42 ++++----- 14 files changed, 392 insertions(+), 307 deletions(-) create mode 100644 src/stack_report.cpp create mode 100644 src/stack_report.hpp delete mode 100644 std/event/io.zig create mode 100644 std/io/in_stream.zig diff --git a/CMakeLists.txt b/CMakeLists.txt index b43d31b58e19dad47fac05747450601d71f0d541..a836ae23208ea0ae6f5a6cc6de1c962f4ac897d6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -449,6 +449,7 @@ set(ZIG_SOURCES "${CMAKE_SOURCE_DIR}/src/os.cpp" "${CMAKE_SOURCE_DIR}/src/parser.cpp" "${CMAKE_SOURCE_DIR}/src/range_set.cpp" + "${CMAKE_SOURCE_DIR}/src/stack_report.cpp" "${CMAKE_SOURCE_DIR}/src/target.cpp" "${CMAKE_SOURCE_DIR}/src/tokenizer.cpp" "${CMAKE_SOURCE_DIR}/src/translate_c.cpp" diff --git a/src/all_types.hpp b/src/all_types.hpp index 2f3f56f0edad707a36e3e1afab605be3a9691734..60b292662d1780ea8856afe05f9f25c7ec8abd78 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -1972,6 +1972,8 @@ struct CodeGen { ZigFn *panic_fn; TldFn *panic_tld_fn; + ZigFn *largest_frame_fn; + WantPIC want_pic; WantStackCheck want_stack_check; CacheHash cache_hash; @@ -2004,6 +2006,7 @@ struct CodeGen { bool generate_error_name_table; bool enable_cache; // mutually exclusive with output_dir bool enable_time_report; + bool enable_stack_report; bool system_linker_hack; bool reported_bad_link_libc_error; bool is_dynamic; // shared library rather than static library. dynamic musl rather than static musl. diff --git a/src/analyze.cpp b/src/analyze.cpp index b845dc8388e0a2ada41e23fc95123962e8f113b1..4347f06699d6e89b1684e52430bb036297d6fde2 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -5737,11 +5737,19 @@ static void mark_suspension_point(Scope *scope) { return; case ScopeIdVarDecl: case ScopeIdDefer: + case ScopeIdBlock: looking_for_exprs = false; continue; - case ScopeIdLoop: case ScopeIdRuntime: continue; + case ScopeIdLoop: { + ScopeLoop *loop_scope = reinterpret_cast(scope); + if (loop_scope->spill_scope != nullptr) { + loop_scope->spill_scope->need_spill = MemoizedBoolTrue; + } + looking_for_exprs = false; + continue; + } case ScopeIdExpr: { if (!looking_for_exprs) { // Now we're only looking for a block, to see if it's in a loop (see the case ScopeIdBlock) @@ -5758,14 +5766,6 @@ static void mark_suspension_point(Scope *scope) { child_expr_scope = parent_expr_scope; continue; } - case ScopeIdBlock: - if (scope->parent->parent->id == ScopeIdLoop) { - ScopeLoop *loop_scope = reinterpret_cast(scope->parent->parent); - if (loop_scope->spill_scope != nullptr) { - loop_scope->spill_scope->need_spill = MemoizedBoolTrue; - } - } - return; } } } @@ -6082,6 +6082,11 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) { frame_type->abi_size = frame_type->data.frame.locals_struct->abi_size; frame_type->abi_align = frame_type->data.frame.locals_struct->abi_align; frame_type->size_in_bits = frame_type->data.frame.locals_struct->size_in_bits; + + if (g->largest_frame_fn == nullptr || frame_type->abi_size > g->largest_frame_fn->frame_type->abi_size) { + g->largest_frame_fn = fn; + } + return ErrorNone; } diff --git a/src/main.cpp b/src/main.cpp index 9e8f2b7d4f38ff1f108ffb855dc33e58ccb0e1e6..006d62dfa99d5567c7bf561b718b3d9d0b684af6 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -16,6 +16,7 @@ #include "libc_installation.hpp" #include "userland.h" #include "glibc.hpp" +#include "stack_report.hpp" #include @@ -62,6 +63,7 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) { " -fPIC enable Position Independent Code\n" " -fno-PIC disable Position Independent Code\n" " -ftime-report print timing diagnostics\n" + " -fstack-report print stack size diagnostics\n" " --libc [file] Provide a file which specifies libc paths\n" " --name [name] override output name\n" " --output-dir [dir] override output directory (defaults to cwd)\n" @@ -476,6 +478,7 @@ int main(int argc, char **argv) { size_t ver_minor = 0; size_t ver_patch = 0; bool timing_info = false; + bool stack_report = false; const char *cache_dir = nullptr; CliPkg *cur_pkg = allocate(1); BuildMode build_mode = BuildModeDebug; @@ -664,6 +667,8 @@ int main(int argc, char **argv) { each_lib_rpath = true; } else if (strcmp(arg, "-ftime-report") == 0) { timing_info = true; + } else if (strcmp(arg, "-fstack-report") == 0) { + stack_report = true; } else if (strcmp(arg, "--enable-valgrind") == 0) { valgrind_support = ValgrindSupportEnabled; } else if (strcmp(arg, "--disable-valgrind") == 0) { @@ -1136,6 +1141,7 @@ int main(int argc, char **argv) { g->subsystem = subsystem; g->enable_time_report = timing_info; + g->enable_stack_report = stack_report; codegen_set_out_name(g, buf_out_name); codegen_set_lib_version(g, ver_major, ver_minor, ver_patch); g->want_single_threaded = want_single_threaded; @@ -1223,6 +1229,8 @@ int main(int argc, char **argv) { codegen_build_and_link(g); if (timing_info) codegen_print_timing_report(g, stdout); + if (stack_report) + zig_print_stack_report(g, stdout); if (cmd == CmdRun) { const char *exec_path = buf_ptr(&g->output_file_path); @@ -1272,6 +1280,10 @@ int main(int argc, char **argv) { codegen_print_timing_report(g, stdout); } + if (stack_report) { + zig_print_stack_report(g, stdout); + } + Buf *test_exe_path_unresolved = &g->output_file_path; Buf *test_exe_path = buf_alloc(); *test_exe_path = os_path_resolve(&test_exe_path_unresolved, 1); diff --git a/src/stack_report.cpp b/src/stack_report.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e9d9d8fbbbb35abd194e3d9a3fdde7af54aceb54 --- /dev/null +++ b/src/stack_report.cpp @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2019 Andrew Kelley + * + * This file is part of zig, which is MIT licensed. + * See http://opensource.org/licenses/MIT + */ + +#include "stack_report.hpp" + +static void tree_print(FILE *f, ZigType *ty, size_t indent); + +static void pretty_print_bytes(FILE *f, double n) { + if (n > 1024.0 * 1024.0 * 1024.0) { + fprintf(f, "%.02f GiB", n / 1024.0 / 1024.0 / 1024.0); + return; + } + if (n > 1024.0 * 1024.0) { + fprintf(f, "%.02f MiB", n / 1024.0 / 1024.0); + return; + } + if (n > 1024.0) { + fprintf(f, "%.02f KiB", n / 1024.0); + return; + } + fprintf(f, "%.02f bytes", n ); + return; +} + +static int compare_type_abi_sizes_desc(const void *a, const void *b) { + uint64_t size_a = (*(ZigType * const*)(a))->abi_size; + uint64_t size_b = (*(ZigType * const*)(b))->abi_size; + if (size_a > size_b) + return -1; + if (size_a < size_b) + return 1; + return 0; +} + +static void tree_print_struct(FILE *f, ZigType *struct_type, size_t indent) { + ZigList children = {}; + uint64_t sum_from_fields = 0; + for (size_t i = 0; i < struct_type->data.structure.src_field_count; i += 1) { + TypeStructField *field = &struct_type->data.structure.fields[i]; + children.append(field->type_entry); + sum_from_fields += field->type_entry->abi_size; + } + qsort(children.items, children.length, sizeof(ZigType *), compare_type_abi_sizes_desc); + fprintf(f, " (padding = %" ZIG_PRI_u64 ")\n", struct_type->abi_size - sum_from_fields); + for (size_t i = 0; i < children.length; i += 1) { + ZigType *child_type = children.at(i); + tree_print(f, child_type, indent + 1); + } +} + +static void tree_print(FILE *f, ZigType *ty, size_t indent) { + for (size_t i = 0; i < indent; i += 1) { + fprintf(f, " "); + } + fprintf(f, "%s: ", buf_ptr(&ty->name)); + pretty_print_bytes(f, ty->abi_size); + switch (ty->id) { + case ZigTypeIdFnFrame: + return tree_print_struct(f, ty->data.frame.locals_struct, indent); + case ZigTypeIdStruct: + return tree_print_struct(f, ty, indent); + default: + fprintf(f, "\n"); + return; + } +} + +void zig_print_stack_report(CodeGen *g, FILE *f) { + if (g->largest_frame_fn == nullptr) { + fprintf(f, "No async function frames in entire compilation.\n"); + return; + } + tree_print(f, g->largest_frame_fn->frame_type, 0); +} diff --git a/src/stack_report.hpp b/src/stack_report.hpp new file mode 100644 index 0000000000000000000000000000000000000000..8a644466f94e9dea3e523f914c8bda180c0e8dd7 --- /dev/null +++ b/src/stack_report.hpp @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2019 Andrew Kelley + * + * This file is part of zig, which is MIT licensed. + * See http://opensource.org/licenses/MIT + */ + +#ifndef ZIG_STACK_REPORT_HPP +#define ZIG_STACK_REPORT_HPP + +#include "all_types.hpp" +#include + +void zig_print_stack_report(CodeGen *g, FILE *f); + +#endif diff --git a/std/c.zig b/std/c.zig index e7b98107ab72bca8f82c9bd8311a69bc7a8c107e..45d93bfd9f635abd231409dfd09073a9bad97a93 100644 --- a/std/c.zig +++ b/std/c.zig @@ -68,6 +68,7 @@ pub extern "c" fn open(path: [*]const u8, oflag: c_uint, ...) c_int; pub extern "c" fn openat(fd: c_int, path: [*]const u8, oflag: c_uint, ...) c_int; pub extern "c" fn raise(sig: c_int) c_int; pub extern "c" fn read(fd: fd_t, buf: [*]u8, nbyte: usize) isize; +pub extern "c" fn readv(fd: c_int, iov: [*]const iovec, iovcnt: c_uint) isize; pub extern "c" fn pread(fd: fd_t, buf: [*]u8, nbyte: usize, offset: u64) isize; pub extern "c" fn preadv(fd: c_int, iov: [*]const iovec, iovcnt: c_uint, offset: usize) isize; pub extern "c" fn writev(fd: c_int, iov: [*]const iovec_const, iovcnt: c_uint) isize; diff --git a/std/debug.zig b/std/debug.zig index 68e6220a72156ebee04c5b31b98e4e359e68b590..344396efa7d184430300a5dd76d7a7b903dfc92c 100644 --- a/std/debug.zig +++ b/std/debug.zig @@ -330,14 +330,16 @@ pub fn writeCurrentStackTraceWindows( } } +/// TODO once https://github.com/ziglang/zig/issues/3157 is fully implemented, +/// make this `noasync fn` and remove the individual noasync calls. pub fn printSourceAtAddress(debug_info: *DebugInfo, out_stream: var, address: usize, tty_color: bool) !void { if (windows.is_the_target) { - return printSourceAtAddressWindows(debug_info, out_stream, address, tty_color); + return noasync printSourceAtAddressWindows(debug_info, out_stream, address, tty_color); } if (os.darwin.is_the_target) { - return printSourceAtAddressMacOs(debug_info, out_stream, address, tty_color); + return noasync printSourceAtAddressMacOs(debug_info, out_stream, address, tty_color); } - return printSourceAtAddressPosix(debug_info, out_stream, address, tty_color); + return noasync printSourceAtAddressPosix(debug_info, out_stream, address, tty_color); } fn printSourceAtAddressWindows(di: *DebugInfo, out_stream: var, relocated_address: usize, tty_color: bool) !void { @@ -793,7 +795,7 @@ fn printLineInfo( try out_stream.write(GREEN ++ "^" ++ RESET ++ "\n"); } } else |err| switch (err) { - error.EndOfFile, error.FileNotFound => {}, + error.EndOfFile, error.FileNotFound => {}, else => return err, } } else { @@ -816,16 +818,18 @@ pub const OpenSelfDebugInfoError = error{ UnsupportedOperatingSystem, }; +/// TODO once https://github.com/ziglang/zig/issues/3157 is fully implemented, +/// make this `noasync fn` and remove the individual noasync calls. pub fn openSelfDebugInfo(allocator: *mem.Allocator) !DebugInfo { if (builtin.strip_debug_info) return error.MissingDebugInfo; if (windows.is_the_target) { - return openSelfDebugInfoWindows(allocator); + return noasync openSelfDebugInfoWindows(allocator); } if (os.darwin.is_the_target) { - return openSelfDebugInfoMacOs(allocator); + return noasync openSelfDebugInfoMacOs(allocator); } - return openSelfDebugInfoPosix(allocator); + return noasync openSelfDebugInfoPosix(allocator); } fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo { @@ -1508,15 +1512,25 @@ fn parseFormValueBlock(allocator: *mem.Allocator, in_stream: var, size: usize) ! } fn parseFormValueConstant(allocator: *mem.Allocator, in_stream: var, signed: bool, comptime size: i32) !FormValue { + // TODO: Please forgive me, I've worked around zig not properly spilling some intermediate values here. + // `noasync` should be removed from all the function calls once it is fixed. return FormValue{ .Const = Constant{ .signed = signed, .payload = switch (size) { - 1 => try in_stream.readIntLittle(u8), - 2 => try in_stream.readIntLittle(u16), - 4 => try in_stream.readIntLittle(u32), - 8 => try in_stream.readIntLittle(u64), - -1 => if (signed) @bitCast(u64, try leb.readILEB128(i64, in_stream)) else try leb.readULEB128(u64, in_stream), + 1 => try noasync in_stream.readIntLittle(u8), + 2 => try noasync in_stream.readIntLittle(u16), + 4 => try noasync in_stream.readIntLittle(u32), + 8 => try noasync in_stream.readIntLittle(u64), + -1 => blk: { + if (signed) { + const x = try noasync leb.readILEB128(i64, in_stream); + break :blk @bitCast(u64, x); + } else { + const x = try noasync leb.readULEB128(u64, in_stream); + break :blk x; + } + }, else => @compileError("Invalid size"), }, }, @@ -1584,7 +1598,10 @@ fn parseFormValue(allocator: *mem.Allocator, in_stream: var, form_id: u64, is_64 DW.FORM_strp => FormValue{ .StrPtr = try parseFormValueDwarfOffsetSize(in_stream, is_64) }, DW.FORM_indirect => { const child_form_id = try leb.readULEB128(u64, in_stream); - return parseFormValue(allocator, in_stream, child_form_id, is_64); + const F = @typeOf(async parseFormValue(allocator, in_stream, child_form_id, is_64)); + var frame = try allocator.create(F); + defer allocator.destroy(frame); + return await @asyncCall(frame, {}, parseFormValue, allocator, in_stream, child_form_id, is_64); }, else => error.InvalidDebugInfo, }; diff --git a/std/event.zig b/std/event.zig index 8409cc5c00024cdf1963b7203743c51d3a47a98b..56c5223ba3e5f03be549efb3c8400e2e55cb063a 100644 --- a/std/event.zig +++ b/std/event.zig @@ -6,7 +6,6 @@ pub const Locked = @import("event/locked.zig").Locked; pub const RwLock = @import("event/rwlock.zig").RwLock; pub const RwLocked = @import("event/rwlocked.zig").RwLocked; pub const Loop = @import("event/loop.zig").Loop; -pub const io = @import("event/io.zig"); pub const fs = @import("event/fs.zig"); pub const net = @import("event/net.zig"); @@ -15,7 +14,6 @@ test "import event tests" { _ = @import("event/fs.zig"); _ = @import("event/future.zig"); _ = @import("event/group.zig"); - _ = @import("event/io.zig"); _ = @import("event/lock.zig"); _ = @import("event/locked.zig"); _ = @import("event/rwlock.zig"); diff --git a/std/event/io.zig b/std/event/io.zig deleted file mode 100644 index 4b54822e68a44ac36b7cc07479c0f6bf5653513c..0000000000000000000000000000000000000000 --- a/std/event/io.zig +++ /dev/null @@ -1,76 +0,0 @@ -const std = @import("../std.zig"); -const builtin = @import("builtin"); -const assert = std.debug.assert; -const mem = std.mem; - -pub fn InStream(comptime ReadError: type) type { - return struct { - const Self = @This(); - pub const Error = ReadError; - - /// Return the number of bytes read. It may be less than buffer.len. - /// If the number of bytes read is 0, it means end of stream. - /// End of stream is not an error condition. - readFn: async fn (self: *Self, buffer: []u8) Error!usize, - - /// Return the number of bytes read. It may be less than buffer.len. - /// If the number of bytes read is 0, it means end of stream. - /// End of stream is not an error condition. - pub async fn read(self: *Self, buffer: []u8) !usize { - return self.readFn(self, buffer); - } - - /// Return the number of bytes read. If it is less than buffer.len - /// it means end of stream. - pub async fn readFull(self: *Self, buffer: []u8) !usize { - var index: usize = 0; - while (index != buf.len) { - const amt_read = try self.read(buf[index..]); - if (amt_read == 0) return index; - index += amt_read; - } - return index; - } - - /// Same as `readFull` but end of stream returns `error.EndOfStream`. - pub async fn readNoEof(self: *Self, buf: []u8) !void { - const amt_read = try self.readFull(buf[index..]); - if (amt_read < buf.len) return error.EndOfStream; - } - - pub async fn readIntLittle(self: *Self, comptime T: type) !T { - var bytes: [@sizeOf(T)]u8 = undefined; - try self.readNoEof(bytes[0..]); - return mem.readIntLittle(T, &bytes); - } - - pub async fn readIntBe(self: *Self, comptime T: type) !T { - var bytes: [@sizeOf(T)]u8 = undefined; - try self.readNoEof(bytes[0..]); - return mem.readIntBig(T, &bytes); - } - - pub async fn readInt(self: *Self, comptime T: type, endian: builtin.Endian) !T { - var bytes: [@sizeOf(T)]u8 = undefined; - try self.readNoEof(bytes[0..]); - return mem.readInt(T, &bytes, endian); - } - - pub async fn readStruct(self: *Self, comptime T: type) !T { - // Only extern and packed structs have defined in-memory layout. - comptime assert(@typeInfo(T).Struct.layout != builtin.TypeInfo.ContainerLayout.Auto); - var res: [1]T = undefined; - try self.readNoEof(@sliceToBytes(res[0..])); - return res[0]; - } - }; -} - -pub fn OutStream(comptime WriteError: type) type { - return struct { - const Self = @This(); - pub const Error = WriteError; - - writeFn: async fn (self: *Self, buffer: []u8) Error!void, - }; -} diff --git a/std/event/loop.zig b/std/event/loop.zig index 242452237e25d41ef1d5af3a7281008dbcc330de..d0d36abc0c21a3a2e8fa34ce527d433a2eafbb9c 100644 --- a/std/event/loop.zig +++ b/std/event/loop.zig @@ -86,18 +86,10 @@ pub const Loop = struct { }; }; - pub const IoMode = enum { - blocking, - evented, - mixed, - }; - pub const io_mode: IoMode = if (@hasDecl(root, "io_mode")) root.io_mode else IoMode.blocking; var global_instance_state: Loop = undefined; - threadlocal var per_thread_instance: ?*Loop = null; - const default_instance: ?*Loop = switch (io_mode) { + const default_instance: ?*Loop = switch (std.io.mode) { .blocking => null, .evented => &global_instance_state, - .mixed => per_thread_instance, }; pub const instance: ?*Loop = if (@hasDecl(root, "event_loop")) root.event_loop else default_instance; @@ -470,6 +462,10 @@ pub const Loop = struct { } } + pub fn waitUntilFdReadable(self: *Loop, fd: os.fd_t) !void { + return self.linuxWaitFd(fd, os.EPOLLET | os.EPOLLIN); + } + pub async fn bsdWaitKev(self: *Loop, ident: usize, filter: i16, fflags: u32) !os.Kevent { var resume_node = ResumeNode.Basic{ .base = ResumeNode{ diff --git a/std/io.zig b/std/io.zig index dcf2ec5f611d857806d4e047591aafb908341a51..25106e24be55f7f04be2d7d0a2b17d6c6af14710 100644 --- a/std/io.zig +++ b/std/io.zig @@ -1,5 +1,6 @@ const std = @import("std.zig"); const builtin = @import("builtin"); +const root = @import("root"); const c = std.c; const math = std.math; @@ -15,6 +16,18 @@ const fmt = std.fmt; const File = std.fs.File; const testing = std.testing; +pub const Mode = enum { + blocking, + evented, +}; +pub const mode: Mode = if (@hasDecl(root, "io_mode")) + root.io_mode +else if (@hasDecl(root, "event_loop")) + Mode.evented +else + Mode.blocking; +pub const is_async = mode != .blocking; + pub const GetStdIoError = os.windows.GetStdHandleError; pub fn getStdOut() GetStdIoError!File { @@ -44,180 +57,7 @@ pub fn getStdIn() GetStdIoError!File { pub const SeekableStream = @import("io/seekable_stream.zig").SeekableStream; pub const SliceSeekableInStream = @import("io/seekable_stream.zig").SliceSeekableInStream; pub const COutStream = @import("io/c_out_stream.zig").COutStream; - -pub fn InStream(comptime ReadError: type) type { - return struct { - const Self = @This(); - pub const Error = ReadError; - - /// Return the number of bytes read. If the number read is smaller than buf.len, it - /// means the stream reached the end. Reaching the end of a stream is not an error - /// condition. - readFn: fn (self: *Self, buffer: []u8) Error!usize, - - /// Replaces `buffer` contents by reading from the stream until it is finished. - /// If `buffer.len()` would exceed `max_size`, `error.StreamTooLong` is returned and - /// the contents read from the stream are lost. - pub fn readAllBuffer(self: *Self, buffer: *Buffer, max_size: usize) !void { - try buffer.resize(0); - - var actual_buf_len: usize = 0; - while (true) { - const dest_slice = buffer.toSlice()[actual_buf_len..]; - const bytes_read = try self.readFull(dest_slice); - actual_buf_len += bytes_read; - - if (bytes_read != dest_slice.len) { - buffer.shrink(actual_buf_len); - return; - } - - const new_buf_size = math.min(max_size, actual_buf_len + mem.page_size); - if (new_buf_size == actual_buf_len) return error.StreamTooLong; - try buffer.resize(new_buf_size); - } - } - - /// Allocates enough memory to hold all the contents of the stream. If the allocated - /// memory would be greater than `max_size`, returns `error.StreamTooLong`. - /// Caller owns returned memory. - /// If this function returns an error, the contents from the stream read so far are lost. - pub fn readAllAlloc(self: *Self, allocator: *mem.Allocator, max_size: usize) ![]u8 { - var buf = Buffer.initNull(allocator); - defer buf.deinit(); - - try self.readAllBuffer(&buf, max_size); - return buf.toOwnedSlice(); - } - - /// Replaces `buffer` contents by reading from the stream until `delimiter` is found. - /// Does not include the delimiter in the result. - /// If `buffer.len()` would exceed `max_size`, `error.StreamTooLong` is returned and the contents - /// read from the stream so far are lost. - pub fn readUntilDelimiterBuffer(self: *Self, buffer: *Buffer, delimiter: u8, max_size: usize) !void { - try buffer.resize(0); - - while (true) { - var byte: u8 = try self.readByte(); - - if (byte == delimiter) { - return; - } - - if (buffer.len() == max_size) { - return error.StreamTooLong; - } - - try buffer.appendByte(byte); - } - } - - /// Allocates enough memory to read until `delimiter`. If the allocated - /// memory would be greater than `max_size`, returns `error.StreamTooLong`. - /// Caller owns returned memory. - /// If this function returns an error, the contents from the stream read so far are lost. - pub fn readUntilDelimiterAlloc(self: *Self, allocator: *mem.Allocator, delimiter: u8, max_size: usize) ![]u8 { - var buf = Buffer.initNull(allocator); - defer buf.deinit(); - - try self.readUntilDelimiterBuffer(&buf, delimiter, max_size); - return buf.toOwnedSlice(); - } - - /// Returns the number of bytes read. It may be less than buffer.len. - /// If the number of bytes read is 0, it means end of stream. - /// End of stream is not an error condition. - pub fn read(self: *Self, buffer: []u8) Error!usize { - return self.readFn(self, buffer); - } - - /// Returns the number of bytes read. If the number read is smaller than buf.len, it - /// means the stream reached the end. Reaching the end of a stream is not an error - /// condition. - pub fn readFull(self: *Self, buffer: []u8) Error!usize { - var index: usize = 0; - while (index != buffer.len) { - const amt = try self.read(buffer[index..]); - if (amt == 0) return index; - index += amt; - } - return index; - } - - /// Same as `readFull` but end of stream returns `error.EndOfStream`. - pub fn readNoEof(self: *Self, buf: []u8) !void { - const amt_read = try self.readFull(buf); - if (amt_read < buf.len) return error.EndOfStream; - } - - /// Reads 1 byte from the stream or returns `error.EndOfStream`. - pub fn readByte(self: *Self) !u8 { - var result: [1]u8 = undefined; - try self.readNoEof(result[0..]); - return result[0]; - } - - /// Same as `readByte` except the returned byte is signed. - pub fn readByteSigned(self: *Self) !i8 { - return @bitCast(i8, try self.readByte()); - } - - /// Reads a native-endian integer - pub fn readIntNative(self: *Self, comptime T: type) !T { - var bytes: [(T.bit_count + 7) / 8]u8 = undefined; - try self.readNoEof(bytes[0..]); - return mem.readIntNative(T, &bytes); - } - - /// Reads a foreign-endian integer - pub fn readIntForeign(self: *Self, comptime T: type) !T { - var bytes: [(T.bit_count + 7) / 8]u8 = undefined; - try self.readNoEof(bytes[0..]); - return mem.readIntForeign(T, &bytes); - } - - pub fn readIntLittle(self: *Self, comptime T: type) !T { - var bytes: [(T.bit_count + 7) / 8]u8 = undefined; - try self.readNoEof(bytes[0..]); - return mem.readIntLittle(T, &bytes); - } - - pub fn readIntBig(self: *Self, comptime T: type) !T { - var bytes: [(T.bit_count + 7) / 8]u8 = undefined; - try self.readNoEof(bytes[0..]); - return mem.readIntBig(T, &bytes); - } - - pub fn readInt(self: *Self, comptime T: type, endian: builtin.Endian) !T { - var bytes: [(T.bit_count + 7) / 8]u8 = undefined; - try self.readNoEof(bytes[0..]); - return mem.readInt(T, &bytes, endian); - } - - pub fn readVarInt(self: *Self, comptime ReturnType: type, endian: builtin.Endian, size: usize) !ReturnType { - assert(size <= @sizeOf(ReturnType)); - var bytes_buf: [@sizeOf(ReturnType)]u8 = undefined; - const bytes = bytes_buf[0..size]; - try self.readNoEof(bytes); - return mem.readVarInt(ReturnType, bytes, endian); - } - - pub fn skipBytes(self: *Self, num_bytes: u64) !void { - var i: u64 = 0; - while (i < num_bytes) : (i += 1) { - _ = try self.readByte(); - } - } - - pub fn readStruct(self: *Self, comptime T: type) !T { - // Only extern and packed structs have defined in-memory layout. - comptime assert(@typeInfo(T).Struct.layout != builtin.TypeInfo.ContainerLayout.Auto); - var res: [1]T = undefined; - try self.readNoEof(@sliceToBytes(res[0..])); - return res[0]; - } - }; -} +pub const InStream = @import("io/in_stream.zig").InStream; pub fn OutStream(comptime WriteError: type) type { return struct { diff --git a/std/io/in_stream.zig b/std/io/in_stream.zig new file mode 100644 index 0000000000000000000000000000000000000000..850f8dcb067abe8893ee1ef683f8329b7d45040e --- /dev/null +++ b/std/io/in_stream.zig @@ -0,0 +1,200 @@ +const std = @import("../std.zig"); +const builtin = @import("builtin"); +const root = @import("root"); +const math = std.math; +const assert = std.debug.assert; +const mem = std.mem; +const Buffer = std.Buffer; + +pub const default_stack_size = 4 * 1024 * 1024; +pub const stack_size: usize = if (@hasDecl(root, "stack_size_std_io_InStream")) + root.stack_size_std_io_InStream +else + default_stack_size; +pub const stack_align = 16; + +pub fn InStream(comptime ReadError: type) type { + return struct { + const Self = @This(); + pub const Error = ReadError; + pub const ReadFn = if (std.io.is_async) + async fn (self: *Self, buffer: []u8) Error!usize + else + fn (self: *Self, buffer: []u8) Error!usize; + + /// Returns the number of bytes read. It may be less than buffer.len. + /// If the number of bytes read is 0, it means end of stream. + /// End of stream is not an error condition. + readFn: ReadFn, + + /// Returns the number of bytes read. It may be less than buffer.len. + /// If the number of bytes read is 0, it means end of stream. + /// End of stream is not an error condition. + pub fn read(self: *Self, buffer: []u8) Error!usize { + if (std.io.is_async) { + var stack_frame: [stack_size]u8 align(stack_align) = undefined; + // TODO https://github.com/ziglang/zig/issues/3068 + var result: Error!usize = undefined; + return await @asyncCall(&stack_frame, &result, self.readFn, self, buffer); + } else { + return self.readFn(self, buffer); + } + } + + /// Returns the number of bytes read. If the number read is smaller than buf.len, it + /// means the stream reached the end. Reaching the end of a stream is not an error + /// condition. + pub fn readFull(self: *Self, buffer: []u8) Error!usize { + var index: usize = 0; + while (index != buffer.len) { + const amt = try self.read(buffer[index..]); + if (amt == 0) return index; + index += amt; + } + return index; + } + + /// Returns the number of bytes read. If the number read would be smaller than buf.len, + /// error.EndOfStream is returned instead. + pub fn readNoEof(self: *Self, buf: []u8) !void { + const amt_read = try self.readFull(buf); + if (amt_read < buf.len) return error.EndOfStream; + } + + /// Replaces `buffer` contents by reading from the stream until it is finished. + /// If `buffer.len()` would exceed `max_size`, `error.StreamTooLong` is returned and + /// the contents read from the stream are lost. + pub fn readAllBuffer(self: *Self, buffer: *Buffer, max_size: usize) !void { + try buffer.resize(0); + + var actual_buf_len: usize = 0; + while (true) { + const dest_slice = buffer.toSlice()[actual_buf_len..]; + const bytes_read = try self.readFull(dest_slice); + actual_buf_len += bytes_read; + + if (bytes_read != dest_slice.len) { + buffer.shrink(actual_buf_len); + return; + } + + const new_buf_size = math.min(max_size, actual_buf_len + mem.page_size); + if (new_buf_size == actual_buf_len) return error.StreamTooLong; + try buffer.resize(new_buf_size); + } + } + + /// Allocates enough memory to hold all the contents of the stream. If the allocated + /// memory would be greater than `max_size`, returns `error.StreamTooLong`. + /// Caller owns returned memory. + /// If this function returns an error, the contents from the stream read so far are lost. + pub fn readAllAlloc(self: *Self, allocator: *mem.Allocator, max_size: usize) ![]u8 { + var buf = Buffer.initNull(allocator); + defer buf.deinit(); + + try self.readAllBuffer(&buf, max_size); + return buf.toOwnedSlice(); + } + + /// Replaces `buffer` contents by reading from the stream until `delimiter` is found. + /// Does not include the delimiter in the result. + /// If `buffer.len()` would exceed `max_size`, `error.StreamTooLong` is returned and the contents + /// read from the stream so far are lost. + pub fn readUntilDelimiterBuffer(self: *Self, buffer: *Buffer, delimiter: u8, max_size: usize) !void { + try buffer.resize(0); + + while (true) { + var byte: u8 = try self.readByte(); + + if (byte == delimiter) { + return; + } + + if (buffer.len() == max_size) { + return error.StreamTooLong; + } + + try buffer.appendByte(byte); + } + } + + /// Allocates enough memory to read until `delimiter`. If the allocated + /// memory would be greater than `max_size`, returns `error.StreamTooLong`. + /// Caller owns returned memory. + /// If this function returns an error, the contents from the stream read so far are lost. + pub fn readUntilDelimiterAlloc(self: *Self, allocator: *mem.Allocator, delimiter: u8, max_size: usize) ![]u8 { + var buf = Buffer.initNull(allocator); + defer buf.deinit(); + + try self.readUntilDelimiterBuffer(&buf, delimiter, max_size); + return buf.toOwnedSlice(); + } + + /// Reads 1 byte from the stream or returns `error.EndOfStream`. + pub fn readByte(self: *Self) !u8 { + var result: [1]u8 = undefined; + try self.readNoEof(result[0..]); + return result[0]; + } + + /// Same as `readByte` except the returned byte is signed. + pub fn readByteSigned(self: *Self) !i8 { + return @bitCast(i8, try self.readByte()); + } + + /// Reads a native-endian integer + pub fn readIntNative(self: *Self, comptime T: type) !T { + var bytes: [(T.bit_count + 7) / 8]u8 = undefined; + try self.readNoEof(bytes[0..]); + return mem.readIntNative(T, &bytes); + } + + /// Reads a foreign-endian integer + pub fn readIntForeign(self: *Self, comptime T: type) !T { + var bytes: [(T.bit_count + 7) / 8]u8 = undefined; + try self.readNoEof(bytes[0..]); + return mem.readIntForeign(T, &bytes); + } + + pub fn readIntLittle(self: *Self, comptime T: type) !T { + var bytes: [(T.bit_count + 7) / 8]u8 = undefined; + try self.readNoEof(bytes[0..]); + return mem.readIntLittle(T, &bytes); + } + + pub fn readIntBig(self: *Self, comptime T: type) !T { + var bytes: [(T.bit_count + 7) / 8]u8 = undefined; + try self.readNoEof(bytes[0..]); + return mem.readIntBig(T, &bytes); + } + + pub fn readInt(self: *Self, comptime T: type, endian: builtin.Endian) !T { + var bytes: [(T.bit_count + 7) / 8]u8 = undefined; + try self.readNoEof(bytes[0..]); + return mem.readInt(T, &bytes, endian); + } + + pub fn readVarInt(self: *Self, comptime ReturnType: type, endian: builtin.Endian, size: usize) !ReturnType { + assert(size <= @sizeOf(ReturnType)); + var bytes_buf: [@sizeOf(ReturnType)]u8 = undefined; + const bytes = bytes_buf[0..size]; + try self.readNoEof(bytes); + return mem.readVarInt(ReturnType, bytes, endian); + } + + pub fn skipBytes(self: *Self, num_bytes: u64) !void { + var i: u64 = 0; + while (i < num_bytes) : (i += 1) { + _ = try self.readByte(); + } + } + + pub fn readStruct(self: *Self, comptime T: type) !T { + // Only extern and packed structs have defined in-memory layout. + comptime assert(@typeInfo(T).Struct.layout != builtin.TypeInfo.ContainerLayout.Auto); + var res: [1]T = undefined; + try self.readNoEof(@sliceToBytes(res[0..])); + return res[0]; + } + }; +} diff --git a/std/os.zig b/std/os.zig index 0291282a7794997275612dd6c608beb4c45bf242..cfde3775bec06cf4623172aef7125b1d92bf0acc 100644 --- a/std/os.zig +++ b/std/os.zig @@ -254,13 +254,18 @@ pub const ReadError = error{ IsDir, OperationAborted, BrokenPipe, + + /// This error occurs when no global event loop is configured, + /// and reading from the file descriptor would block. + WouldBlock, + Unexpected, }; /// Returns the number of bytes that were read, which can be less than /// buf.len. If 0 bytes were read, that means EOF. -/// This function is for blocking file descriptors only. For non-blocking, see -/// `readAsync`. +/// If the application has a global event loop enabled, EAGAIN is handled +/// via the event loop. Otherwise EAGAIN results in error.WouldBlock. pub fn read(fd: fd_t, buf: []u8) ReadError!usize { if (windows.is_the_target) { return windows.ReadFile(fd, buf); @@ -279,28 +284,19 @@ pub fn read(fd: fd_t, buf: []u8) ReadError!usize { } } - // Linux can return EINVAL when read amount is > 0x7ffff000 - // See https://github.com/ziglang/zig/pull/743#issuecomment-363158274 - // TODO audit this. Shawn Landden says that this is not actually true. - // if this logic should stay, move it to std.os.linux - const max_buf_len = 0x7ffff000; - - var index: usize = 0; - while (index < buf.len) { - const want_to_read = math.min(buf.len - index, usize(max_buf_len)); - const rc = system.read(fd, buf.ptr + index, want_to_read); + while (true) { + const rc = system.read(fd, buf.ptr, buf.len); switch (errno(rc)) { - 0 => { - const amt_read = @intCast(usize, rc); - index += amt_read; - if (amt_read == want_to_read) continue; - // Read returned less than buf.len. - return index; - }, + 0 => return @intCast(usize, rc), EINTR => continue, EINVAL => unreachable, EFAULT => unreachable, - EAGAIN => unreachable, // This function is for blocking reads. + EAGAIN => if (std.event.Loop.instance) |loop| { + loop.waitUntilFdReadable(fd) catch return error.WouldBlock; + continue; + } else { + return error.WouldBlock; + }, EBADF => unreachable, // Always a race condition. EIO => return error.InputOutput, EISDIR => return error.IsDir, @@ -313,8 +309,7 @@ pub fn read(fd: fd_t, buf: []u8) ReadError!usize { } /// Number of bytes read is returned. Upon reading end-of-file, zero is returned. -/// This function is for blocking file descriptors only. For non-blocking, see -/// `preadvAsync`. +/// This function is for blocking file descriptors only. pub fn preadv(fd: fd_t, iov: []const iovec, offset: u64) ReadError!usize { if (darwin.is_the_target) { // Darwin does not have preadv but it does have pread. @@ -386,8 +381,7 @@ pub const WriteError = error{ }; /// Write to a file descriptor. Keeps trying if it gets interrupted. -/// This function is for blocking file descriptors only. For non-blocking, see -/// `writeAsync`. +/// This function is for blocking file descriptors only. pub fn write(fd: fd_t, bytes: []const u8) WriteError!void { if (windows.is_the_target) { return windows.WriteFile(fd, bytes); -- 2.54.0 From ff051f8f5de47f4c5033c61fb70a5c5260f34dff Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 10 Sep 2019 01:00:50 -0400 Subject: [PATCH 78/80] -fstack-report outputs JSON See #3069 --- src/stack_report.cpp | 61 +++++++++++++++++++++++++++++++++++++------- 1 file changed, 52 insertions(+), 9 deletions(-) diff --git a/src/stack_report.cpp b/src/stack_report.cpp index e9d9d8fbbbb35abd194e3d9a3fdde7af54aceb54..3a0abd6cef5371580ba7ad8f8bbcfda5c5d7fb28 100644 --- a/src/stack_report.cpp +++ b/src/stack_report.cpp @@ -36,6 +36,20 @@ static int compare_type_abi_sizes_desc(const void *a, const void *b) { return 0; } +static void start_child(FILE *f, size_t indent) { + fprintf(f, "\n"); + for (size_t i = 0; i < indent; i += 1) { + fprintf(f, " "); + } +} + +static void start_peer(FILE *f, size_t indent) { + fprintf(f, ",\n"); + for (size_t i = 0; i < indent; i += 1) { + fprintf(f, " "); + } +} + static void tree_print_struct(FILE *f, ZigType *struct_type, size_t indent) { ZigList children = {}; uint64_t sum_from_fields = 0; @@ -45,34 +59,63 @@ static void tree_print_struct(FILE *f, ZigType *struct_type, size_t indent) { sum_from_fields += field->type_entry->abi_size; } qsort(children.items, children.length, sizeof(ZigType *), compare_type_abi_sizes_desc); - fprintf(f, " (padding = %" ZIG_PRI_u64 ")\n", struct_type->abi_size - sum_from_fields); + + start_peer(f, indent); + fprintf(f, "\"padding\": \"%" ZIG_PRI_u64 "\"", struct_type->abi_size - sum_from_fields); + + start_peer(f, indent); + fprintf(f, "\"fields\": ["); + for (size_t i = 0; i < children.length; i += 1) { + if (i == 0) { + start_child(f, indent + 1); + } else { + start_peer(f, indent + 1); + } + fprintf(f, "{"); + ZigType *child_type = children.at(i); - tree_print(f, child_type, indent + 1); + tree_print(f, child_type, indent + 2); + + start_child(f, indent + 1); + fprintf(f, "}"); } + + start_child(f, indent); + fprintf(f, "]"); } static void tree_print(FILE *f, ZigType *ty, size_t indent) { - for (size_t i = 0; i < indent; i += 1) { - fprintf(f, " "); - } - fprintf(f, "%s: ", buf_ptr(&ty->name)); + start_child(f, indent); + fprintf(f, "\"type\": \"%s\"", buf_ptr(&ty->name)); + + start_peer(f, indent); + fprintf(f, "\"sizef\": \""); pretty_print_bytes(f, ty->abi_size); + fprintf(f, "\""); + + start_peer(f, indent); + fprintf(f, "\"size\": \"%" ZIG_PRI_u64 "\"", ty->abi_size); + switch (ty->id) { case ZigTypeIdFnFrame: return tree_print_struct(f, ty->data.frame.locals_struct, indent); case ZigTypeIdStruct: return tree_print_struct(f, ty, indent); default: - fprintf(f, "\n"); + start_child(f, indent); return; } } void zig_print_stack_report(CodeGen *g, FILE *f) { if (g->largest_frame_fn == nullptr) { - fprintf(f, "No async function frames in entire compilation.\n"); + fprintf(f, "{\"error\": \"No async function frames in entire compilation.\"}\n"); return; } - tree_print(f, g->largest_frame_fn->frame_type, 0); + fprintf(f, "{"); + tree_print(f, g->largest_frame_fn->frame_type, 1); + + start_child(f, 0); + fprintf(f, "}\n"); } -- 2.54.0 From e2c68fce89d7d308b445ed26025a674aff938151 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Tue, 10 Sep 2019 16:19:31 +0200 Subject: [PATCH 79/80] Accept void argument for @cDefine value Closes #2612 --- src/ir.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/ir.cpp b/src/ir.cpp index 3e699b50eb1ab9abb99787f3bb19b36cb9e64f16..56a12d243832ff075fd759db18158b4d22fba21f 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -21383,15 +21383,20 @@ static IrInstruction *ir_analyze_instruction_c_define(IrAnalyze *ira, IrInstruct if (type_is_invalid(value->value.type)) return ira->codegen->invalid_instruction; - Buf *define_value = ir_resolve_str(ira, value); - if (!define_value) - return ira->codegen->invalid_instruction; + Buf *define_value = nullptr; + // The second parameter is either a string or void (equivalent to "") + if (value->value.type->id != ZigTypeIdVoid) { + define_value = ir_resolve_str(ira, value); + if (!define_value) + return ira->codegen->invalid_instruction; + } Buf *c_import_buf = exec_c_import_buf(ira->new_irb.exec); // We check for this error in pass1 assert(c_import_buf); - buf_appendf(c_import_buf, "#define %s %s\n", buf_ptr(define_name), buf_ptr(define_value)); + buf_appendf(c_import_buf, "#define %s %s\n", buf_ptr(define_name), + define_value ? buf_ptr(define_value) : ""); return ir_const_void(ira, &instruction->base); } -- 2.54.0 From ba4d83af3e58ce2a34ccb945a297211333fd904c Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Tue, 10 Sep 2019 17:20:48 +0200 Subject: [PATCH 80/80] Resolve lazy arguments passed to @compileLog Closes #3193 --- src/ir.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/ir.cpp b/src/ir.cpp index 56a12d243832ff075fd759db18158b4d22fba21f..f29afdcf7bb5784fe1e2c9837628e86e65ec9987 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -19735,6 +19735,11 @@ static IrInstruction *ir_analyze_instruction_compile_log(IrAnalyze *ira, IrInstr if (type_is_invalid(msg->value.type)) return ira->codegen->invalid_instruction; buf_resize(&buf, 0); + if (msg->value.special == ConstValSpecialLazy) { + // Resolve any lazy value that's passed, we need its value + if (ir_resolve_lazy(ira->codegen, msg->source_node, &msg->value)) + return ira->codegen->invalid_instruction; + } render_const_value(ira->codegen, &buf, &msg->value); const char *comma_str = (i != 0) ? ", " : ""; fprintf(stderr, "%s%s", comma_str, buf_ptr(&buf)); -- 2.54.0