authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2024-03-16 16:46:45+01:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2024-03-17 03:06:17+01:00
logd10c52c194a093f58df40bc6122f24380f0cc097
tree98909ac98dabdf19d082ce94dddf11a54cc11926
parentf88a971e4ff211b78695609b4482fb886f30a1af

AstGen: disallow alignment on function types

A pointer type already has an alignment, so this information does not need to be duplicated on the function type. This already has precedence with addrspace which is already disallowed on function types for this reason. Also fixes `@TypeOf(&func)` to have the correct addrspace and alignment.

30 files changed, 257 insertions(+), 310 deletions(-)

doc/langref.html.in+8-2
...@@ -2780,10 +2780,16 @@ fn noop4() align(4) void {}...@@ -2780,10 +2780,16 @@ fn noop4() align(4) void {}
27802780
2781test "function alignment" {2781test "function alignment" {
2782 try expect(derp() == 1234);2782 try expect(derp() == 1234);
2783 try expect(@TypeOf(noop1) == fn () align(1) void);2783 try expect(@TypeOf(derp) == fn () i32);
2784 try expect(@TypeOf(noop4) == fn () align(4) void);2784 try expect(@TypeOf(&derp) == *align(@sizeOf(usize) * 2) const fn () i32);
2785
2785 noop1();2786 noop1();
2787 try expect(@TypeOf(noop1) == fn () void);
2788 try expect(@TypeOf(&noop1) == *align(1) const fn () void);
2789
2786 noop4();2790 noop4();
2791 try expect(@TypeOf(noop4) == fn () void);
2792 try expect(@TypeOf(&noop4) == *align(4) const fn () void);
2787}2793}
2788 {#code_end#}2794 {#code_end#}
2789 <p>2795 <p>
lib/std/builtin.zig-1
...@@ -420,7 +420,6 @@ pub const Type = union(enum) {...@@ -420,7 +420,6 @@ pub const Type = union(enum) {
420 /// therefore must be kept in sync with the compiler implementation.420 /// therefore must be kept in sync with the compiler implementation.
421 pub const Fn = struct {421 pub const Fn = struct {
422 calling_convention: CallingConvention,422 calling_convention: CallingConvention,
423 alignment: comptime_int,
424 is_generic: bool,423 is_generic: bool,
425 is_var_args: bool,424 is_var_args: bool,
426 /// TODO change the language spec to make this not optional.425 /// TODO change the language spec to make this not optional.
lib/std/c/darwin.zig+5-5
...@@ -1053,10 +1053,10 @@ pub const sigset_t = u32;...@@ -1053,10 +1053,10 @@ pub const sigset_t = u32;
1053pub const empty_sigset: sigset_t = 0;1053pub const empty_sigset: sigset_t = 0;
10541054
1055pub const SIG = struct {1055pub const SIG = struct {
1056 pub const ERR = @as(?Sigaction.handler_fn, @ptrFromInt(maxInt(usize)));1056 pub const ERR: ?Sigaction.handler_fn = @ptrFromInt(maxInt(usize));
1057 pub const DFL = @as(?Sigaction.handler_fn, @ptrFromInt(0));1057 pub const DFL: ?Sigaction.handler_fn = @ptrFromInt(0);
1058 pub const IGN = @as(?Sigaction.handler_fn, @ptrFromInt(1));1058 pub const IGN: ?Sigaction.handler_fn = @ptrFromInt(1);
1059 pub const HOLD = @as(?Sigaction.handler_fn, @ptrFromInt(5));1059 pub const HOLD: ?Sigaction.handler_fn = @ptrFromInt(5);
10601060
1061 /// block specified signal set1061 /// block specified signal set
1062 pub const BLOCK = 1;1062 pub const BLOCK = 1;
...@@ -1150,7 +1150,7 @@ pub const siginfo_t = extern struct {...@@ -1150,7 +1150,7 @@ pub const siginfo_t = extern struct {
11501150
1151/// Renamed from `sigaction` to `Sigaction` to avoid conflict with function name.1151/// Renamed from `sigaction` to `Sigaction` to avoid conflict with function name.
1152pub const Sigaction = extern struct {1152pub const Sigaction = extern struct {
1153 pub const handler_fn = *const fn (c_int) align(1) callconv(.C) void;1153 pub const handler_fn = *align(1) const fn (c_int) callconv(.C) void;
1154 pub const sigaction_fn = *const fn (c_int, *const siginfo_t, ?*const anyopaque) callconv(.C) void;1154 pub const sigaction_fn = *const fn (c_int, *const siginfo_t, ?*const anyopaque) callconv(.C) void;
11551155
1156 handler: extern union {1156 handler: extern union {
lib/std/c/dragonfly.zig+4-4
...@@ -616,9 +616,9 @@ pub const S = struct {...@@ -616,9 +616,9 @@ pub const S = struct {
616pub const BADSIG = SIG.ERR;616pub const BADSIG = SIG.ERR;
617617
618pub const SIG = struct {618pub const SIG = struct {
619 pub const DFL = @as(?Sigaction.handler_fn, @ptrFromInt(0));619 pub const DFL: ?Sigaction.handler_fn = @ptrFromInt(0);
620 pub const IGN = @as(?Sigaction.handler_fn, @ptrFromInt(1));620 pub const IGN: ?Sigaction.handler_fn = @ptrFromInt(1);
621 pub const ERR = @as(?Sigaction.handler_fn, @ptrFromInt(maxInt(usize)));621 pub const ERR: ?Sigaction.handler_fn = @ptrFromInt(maxInt(usize));
622622
623 pub const BLOCK = 1;623 pub const BLOCK = 1;
624 pub const UNBLOCK = 2;624 pub const UNBLOCK = 2;
...@@ -690,7 +690,7 @@ pub const empty_sigset = sigset_t{ .__bits = [_]c_uint{0} ** _SIG_WORDS };...@@ -690,7 +690,7 @@ pub const empty_sigset = sigset_t{ .__bits = [_]c_uint{0} ** _SIG_WORDS };
690pub const sig_atomic_t = c_int;690pub const sig_atomic_t = c_int;
691691
692pub const Sigaction = extern struct {692pub const Sigaction = extern struct {
693 pub const handler_fn = *const fn (c_int) align(1) callconv(.C) void;693 pub const handler_fn = *align(1) const fn (c_int) callconv(.C) void;
694 pub const sigaction_fn = *const fn (c_int, *const siginfo_t, ?*const anyopaque) callconv(.C) void;694 pub const sigaction_fn = *const fn (c_int, *const siginfo_t, ?*const anyopaque) callconv(.C) void;
695695
696 /// signal handler696 /// signal handler
lib/std/c/freebsd.zig+4-4
...@@ -695,9 +695,9 @@ pub const SIG = struct {...@@ -695,9 +695,9 @@ pub const SIG = struct {
695 pub const UNBLOCK = 2;695 pub const UNBLOCK = 2;
696 pub const SETMASK = 3;696 pub const SETMASK = 3;
697697
698 pub const DFL = @as(?Sigaction.handler_fn, @ptrFromInt(0));698 pub const DFL: ?Sigaction.handler_fn = @ptrFromInt(0);
699 pub const IGN = @as(?Sigaction.handler_fn, @ptrFromInt(1));699 pub const IGN: ?Sigaction.handler_fn = @ptrFromInt(1);
700 pub const ERR = @as(?Sigaction.handler_fn, @ptrFromInt(maxInt(usize)));700 pub const ERR: ?Sigaction.handler_fn = @ptrFromInt(maxInt(usize));
701701
702 pub const WORDS = 4;702 pub const WORDS = 4;
703 pub const MAXSIG = 128;703 pub const MAXSIG = 128;
...@@ -1171,7 +1171,7 @@ const NSIG = 32;...@@ -1171,7 +1171,7 @@ const NSIG = 32;
11711171
1172/// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall.1172/// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall.
1173pub const Sigaction = extern struct {1173pub const Sigaction = extern struct {
1174 pub const handler_fn = *const fn (c_int) align(1) callconv(.C) void;1174 pub const handler_fn = *align(1) const fn (c_int) callconv(.C) void;
1175 pub const sigaction_fn = *const fn (c_int, *const siginfo_t, ?*const anyopaque) callconv(.C) void;1175 pub const sigaction_fn = *const fn (c_int, *const siginfo_t, ?*const anyopaque) callconv(.C) void;
11761176
1177 /// signal handler1177 /// signal handler
lib/std/c/haiku.zig+4-4
...@@ -441,9 +441,9 @@ pub const SA = struct {...@@ -441,9 +441,9 @@ pub const SA = struct {
441};441};
442442
443pub const SIG = struct {443pub const SIG = struct {
444 pub const ERR = @as(?Sigaction.handler_fn, @ptrFromInt(maxInt(usize)));444 pub const ERR: ?Sigaction.handler_fn = @ptrFromInt(maxInt(usize));
445 pub const DFL = @as(?Sigaction.handler_fn, @ptrFromInt(0));445 pub const DFL: ?Sigaction.handler_fn = @ptrFromInt(0);
446 pub const IGN = @as(?Sigaction.handler_fn, @ptrFromInt(1));446 pub const IGN: ?Sigaction.handler_fn = @ptrFromInt(1);
447447
448 pub const HUP = 1;448 pub const HUP = 1;
449 pub const INT = 2;449 pub const INT = 2;
...@@ -690,7 +690,7 @@ const NSIG = 32;...@@ -690,7 +690,7 @@ const NSIG = 32;
690690
691/// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall.691/// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall.
692pub const Sigaction = extern struct {692pub const Sigaction = extern struct {
693 pub const handler_fn = *const fn (i32) align(1) callconv(.C) void;693 pub const handler_fn = *align(1) const fn (i32) callconv(.C) void;
694694
695 /// signal handler695 /// signal handler
696 __sigaction_u: extern union {696 __sigaction_u: extern union {
lib/std/c/netbsd.zig+4-4
...@@ -800,9 +800,9 @@ pub const winsize = extern struct {...@@ -800,9 +800,9 @@ pub const winsize = extern struct {
800const NSIG = 32;800const NSIG = 32;
801801
802pub const SIG = struct {802pub const SIG = struct {
803 pub const DFL = @as(?Sigaction.handler_fn, @ptrFromInt(0));803 pub const DFL: ?Sigaction.handler_fn = @ptrFromInt(0);
804 pub const IGN = @as(?Sigaction.handler_fn, @ptrFromInt(1));804 pub const IGN: ?Sigaction.handler_fn = @ptrFromInt(1);
805 pub const ERR = @as(?Sigaction.handler_fn, @ptrFromInt(maxInt(usize)));805 pub const ERR: ?Sigaction.handler_fn = @ptrFromInt(maxInt(usize));
806806
807 pub const WORDS = 4;807 pub const WORDS = 4;
808 pub const MAXSIG = 128;808 pub const MAXSIG = 128;
...@@ -864,7 +864,7 @@ pub const SIG = struct {...@@ -864,7 +864,7 @@ pub const SIG = struct {
864864
865/// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall.865/// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall.
866pub const Sigaction = extern struct {866pub const Sigaction = extern struct {
867 pub const handler_fn = *const fn (c_int) align(1) callconv(.C) void;867 pub const handler_fn = *align(1) const fn (c_int) callconv(.C) void;
868 pub const sigaction_fn = *const fn (c_int, *const siginfo_t, ?*const anyopaque) callconv(.C) void;868 pub const sigaction_fn = *const fn (c_int, *const siginfo_t, ?*const anyopaque) callconv(.C) void;
869869
870 /// signal handler870 /// signal handler
lib/std/c/openbsd.zig+6-6
...@@ -795,11 +795,11 @@ pub const winsize = extern struct {...@@ -795,11 +795,11 @@ pub const winsize = extern struct {
795const NSIG = 33;795const NSIG = 33;
796796
797pub const SIG = struct {797pub const SIG = struct {
798 pub const DFL = @as(?Sigaction.handler_fn, @ptrFromInt(0));798 pub const DFL: ?Sigaction.handler_fn = @ptrFromInt(0);
799 pub const IGN = @as(?Sigaction.handler_fn, @ptrFromInt(1));799 pub const IGN: ?Sigaction.handler_fn = @ptrFromInt(1);
800 pub const ERR = @as(?Sigaction.handler_fn, @ptrFromInt(maxInt(usize)));800 pub const ERR: ?Sigaction.handler_fn = @ptrFromInt(maxInt(usize));
801 pub const CATCH = @as(?Sigaction.handler_fn, @ptrFromInt(2));801 pub const CATCH: ?Sigaction.handler_fn = @ptrFromInt(2);
802 pub const HOLD = @as(?Sigaction.handler_fn, @ptrFromInt(3));802 pub const HOLD: ?Sigaction.handler_fn = @ptrFromInt(3);
803803
804 pub const HUP = 1;804 pub const HUP = 1;
805 pub const INT = 2;805 pub const INT = 2;
...@@ -842,7 +842,7 @@ pub const SIG = struct {...@@ -842,7 +842,7 @@ pub const SIG = struct {
842842
843/// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall.843/// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall.
844pub const Sigaction = extern struct {844pub const Sigaction = extern struct {
845 pub const handler_fn = *const fn (c_int) align(1) callconv(.C) void;845 pub const handler_fn = *align(1) const fn (c_int) callconv(.C) void;
846 pub const sigaction_fn = *const fn (c_int, *const siginfo_t, ?*const anyopaque) callconv(.C) void;846 pub const sigaction_fn = *const fn (c_int, *const siginfo_t, ?*const anyopaque) callconv(.C) void;
847847
848 /// signal handler848 /// signal handler
lib/std/c/solaris.zig+5-5
...@@ -798,10 +798,10 @@ pub const winsize = extern struct {...@@ -798,10 +798,10 @@ pub const winsize = extern struct {
798const NSIG = 75;798const NSIG = 75;
799799
800pub const SIG = struct {800pub const SIG = struct {
801 pub const DFL = @as(?Sigaction.handler_fn, @ptrFromInt(0));801 pub const DFL: ?Sigaction.handler_fn = @ptrFromInt(0);
802 pub const ERR = @as(?Sigaction.handler_fn, @ptrFromInt(maxInt(usize)));802 pub const ERR: ?Sigaction.handler_fn = @ptrFromInt(maxInt(usize));
803 pub const IGN = @as(?Sigaction.handler_fn, @ptrFromInt(1));803 pub const IGN: ?Sigaction.handler_fn = @ptrFromInt(1);
804 pub const HOLD = @as(?Sigaction.handler_fn, @ptrFromInt(2));804 pub const HOLD: ?Sigaction.handler_fn = @ptrFromInt(2);
805805
806 pub const WORDS = 4;806 pub const WORDS = 4;
807 pub const MAXSIG = 75;807 pub const MAXSIG = 75;
...@@ -874,7 +874,7 @@ pub const SIG = struct {...@@ -874,7 +874,7 @@ pub const SIG = struct {
874874
875/// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall.875/// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall.
876pub const Sigaction = extern struct {876pub const Sigaction = extern struct {
877 pub const handler_fn = *const fn (c_int) align(1) callconv(.C) void;877 pub const handler_fn = *align(1) const fn (c_int) callconv(.C) void;
878 pub const sigaction_fn = *const fn (c_int, *const siginfo_t, ?*const anyopaque) callconv(.C) void;878 pub const sigaction_fn = *const fn (c_int, *const siginfo_t, ?*const anyopaque) callconv(.C) void;
879879
880 /// signal options880 /// signal options
lib/std/meta.zig+4-5
...@@ -57,10 +57,9 @@ test stringToEnum {...@@ -57,10 +57,9 @@ test stringToEnum {
57}57}
5858
59/// Returns the alignment of type T.59/// Returns the alignment of type T.
60/// Note that if T is a pointer or function type the result is different than60/// Note that if T is a pointer type the result is different than the one
61/// the one returned by @alignOf(T).61/// returned by @alignOf(T).
62/// If T is a pointer type the alignment of the type it points to is returned.62/// If T is a pointer type the alignment of the type it points to is returned.
63/// If T is a function type the alignment a target-dependent value is returned.
64pub fn alignment(comptime T: type) comptime_int {63pub fn alignment(comptime T: type) comptime_int {
65 return switch (@typeInfo(T)) {64 return switch (@typeInfo(T)) {
66 .Optional => |info| switch (@typeInfo(info.child)) {65 .Optional => |info| switch (@typeInfo(info.child)) {
...@@ -68,7 +67,6 @@ pub fn alignment(comptime T: type) comptime_int {...@@ -68,7 +67,6 @@ pub fn alignment(comptime T: type) comptime_int {
68 else => @alignOf(T),67 else => @alignOf(T),
69 },68 },
70 .Pointer => |info| info.alignment,69 .Pointer => |info| info.alignment,
71 .Fn => |info| info.alignment,
72 else => @alignOf(T),70 else => @alignOf(T),
73 };71 };
74}72}
...@@ -80,7 +78,8 @@ test alignment {...@@ -80,7 +78,8 @@ test alignment {
80 try testing.expect(alignment([]align(1) u8) == 1);78 try testing.expect(alignment([]align(1) u8) == 1);
81 try testing.expect(alignment([]align(2) u8) == 2);79 try testing.expect(alignment([]align(2) u8) == 2);
82 try testing.expect(alignment(fn () void) > 0);80 try testing.expect(alignment(fn () void) > 0);
83 try testing.expect(alignment(fn () align(128) void) == 128);81 try testing.expect(alignment(*const fn () void) > 0);
82 try testing.expect(alignment(*align(128) const fn () void) == 128);
84}83}
8584
86/// Given a parameterized type (array, vector, pointer, optional), returns the "child type".85/// Given a parameterized type (array, vector, pointer, optional), returns the "child type".
lib/std/os/emscripten.zig+4-4
...@@ -689,13 +689,13 @@ pub const SIG = struct {...@@ -689,13 +689,13 @@ pub const SIG = struct {
689 pub const SYS = 31;689 pub const SYS = 31;
690 pub const UNUSED = SIG.SYS;690 pub const UNUSED = SIG.SYS;
691691
692 pub const ERR = @as(?Sigaction.handler_fn, @ptrFromInt(std.math.maxInt(usize)));692 pub const ERR: ?Sigaction.handler_fn = @ptrFromInt(std.math.maxInt(usize));
693 pub const DFL = @as(?Sigaction.handler_fn, @ptrFromInt(0));693 pub const DFL: ?Sigaction.handler_fn = @ptrFromInt(0);
694 pub const IGN = @as(?Sigaction.handler_fn, @ptrFromInt(1));694 pub const IGN: ?Sigaction.handler_fn = @ptrFromInt(1);
695};695};
696696
697pub const Sigaction = extern struct {697pub const Sigaction = extern struct {
698 pub const handler_fn = *const fn (c_int) align(1) callconv(.C) void;698 pub const handler_fn = *align(1) const fn (c_int) callconv(.C) void;
699 pub const sigaction_fn = *const fn (c_int, *const siginfo_t, ?*const anyopaque) callconv(.C) void;699 pub const sigaction_fn = *const fn (c_int, *const siginfo_t, ?*const anyopaque) callconv(.C) void;
700700
701 handler: extern union {701 handler: extern union {
lib/std/os/linux.zig+18-23
...@@ -1327,16 +1327,14 @@ pub fn flock(fd: fd_t, operation: i32) usize {...@@ -1327,16 +1327,14 @@ pub fn flock(fd: fd_t, operation: i32) usize {
1327 return syscall2(.flock, @as(usize, @bitCast(@as(isize, fd))), @as(usize, @bitCast(@as(isize, operation))));1327 return syscall2(.flock, @as(usize, @bitCast(@as(isize, fd))), @as(usize, @bitCast(@as(isize, operation))));
1328}1328}
13291329
1330var vdso_clock_gettime = @as(?*const anyopaque, @ptrCast(&init_vdso_clock_gettime));
1331
1332// We must follow the C calling convention when we call into the VDSO1330// We must follow the C calling convention when we call into the VDSO
1333const vdso_clock_gettime_ty = *align(1) const fn (i32, *timespec) callconv(.C) usize;1331const VdsoClockGettime = *align(1) const fn (i32, *timespec) callconv(.C) usize;
1332var vdso_clock_gettime: ?VdsoClockGettime = &init_vdso_clock_gettime;
13341333
1335pub fn clock_gettime(clk_id: i32, tp: *timespec) usize {1334pub fn clock_gettime(clk_id: i32, tp: *timespec) usize {
1336 if (@hasDecl(VDSO, "CGT_SYM")) {1335 if (@hasDecl(VDSO, "CGT_SYM")) {
1337 const ptr = @atomicLoad(?*const anyopaque, &vdso_clock_gettime, .unordered);1336 const ptr = @atomicLoad(?VdsoClockGettime, &vdso_clock_gettime, .unordered);
1338 if (ptr) |fn_ptr| {1337 if (ptr) |f| {
1339 const f = @as(vdso_clock_gettime_ty, @ptrCast(fn_ptr));
1340 const rc = f(clk_id, tp);1338 const rc = f(clk_id, tp);
1341 switch (rc) {1339 switch (rc) {
1342 0, @as(usize, @bitCast(-@as(isize, @intFromEnum(E.INVAL)))) => return rc,1340 0, @as(usize, @bitCast(-@as(isize, @intFromEnum(E.INVAL)))) => return rc,
...@@ -1348,15 +1346,12 @@ pub fn clock_gettime(clk_id: i32, tp: *timespec) usize {...@@ -1348,15 +1346,12 @@ pub fn clock_gettime(clk_id: i32, tp: *timespec) usize {
1348}1346}
13491347
1350fn init_vdso_clock_gettime(clk: i32, ts: *timespec) callconv(.C) usize {1348fn init_vdso_clock_gettime(clk: i32, ts: *timespec) callconv(.C) usize {
1351 const ptr = @as(?*const anyopaque, @ptrFromInt(vdso.lookup(VDSO.CGT_VER, VDSO.CGT_SYM)));1349 const ptr: ?VdsoClockGettime = @ptrFromInt(vdso.lookup(VDSO.CGT_VER, VDSO.CGT_SYM));
1352 // Note that we may not have a VDSO at all, update the stub address anyway1350 // Note that we may not have a VDSO at all, update the stub address anyway
1353 // so that clock_gettime will fall back on the good old (and slow) syscall1351 // so that clock_gettime will fall back on the good old (and slow) syscall
1354 @atomicStore(?*const anyopaque, &vdso_clock_gettime, ptr, .monotonic);1352 @atomicStore(?VdsoClockGettime, &vdso_clock_gettime, ptr, .monotonic);
1355 // Call into the VDSO if available1353 // Call into the VDSO if available
1356 if (ptr) |fn_ptr| {1354 if (ptr) |f| return f(clk, ts);
1357 const f = @as(vdso_clock_gettime_ty, @ptrCast(fn_ptr));
1358 return f(clk, ts);
1359 }
1360 return @as(usize, @bitCast(-@as(isize, @intFromEnum(E.NOSYS))));1355 return @as(usize, @bitCast(-@as(isize, @intFromEnum(E.NOSYS))));
1361}1356}
13621357
...@@ -2516,9 +2511,9 @@ pub const SIG = if (is_mips) struct {...@@ -2516,9 +2511,9 @@ pub const SIG = if (is_mips) struct {
2516 pub const SYS = 31;2511 pub const SYS = 31;
2517 pub const UNUSED = SIG.SYS;2512 pub const UNUSED = SIG.SYS;
25182513
2519 pub const ERR = @as(?Sigaction.handler_fn, @ptrFromInt(maxInt(usize)));2514 pub const ERR: ?Sigaction.handler_fn = @ptrFromInt(maxInt(usize));
2520 pub const DFL = @as(?Sigaction.handler_fn, @ptrFromInt(0));2515 pub const DFL: ?Sigaction.handler_fn = @ptrFromInt(0);
2521 pub const IGN = @as(?Sigaction.handler_fn, @ptrFromInt(1));2516 pub const IGN: ?Sigaction.handler_fn = @ptrFromInt(1);
2522} else if (is_sparc) struct {2517} else if (is_sparc) struct {
2523 pub const BLOCK = 1;2518 pub const BLOCK = 1;
2524 pub const UNBLOCK = 2;2519 pub const UNBLOCK = 2;
...@@ -2560,9 +2555,9 @@ pub const SIG = if (is_mips) struct {...@@ -2560,9 +2555,9 @@ pub const SIG = if (is_mips) struct {
2560 pub const PWR = LOST;2555 pub const PWR = LOST;
2561 pub const IO = SIG.POLL;2556 pub const IO = SIG.POLL;
25622557
2563 pub const ERR = @as(?Sigaction.handler_fn, @ptrFromInt(maxInt(usize)));2558 pub const ERR: ?Sigaction.handler_fn = @ptrFromInt(maxInt(usize));
2564 pub const DFL = @as(?Sigaction.handler_fn, @ptrFromInt(0));2559 pub const DFL: ?Sigaction.handler_fn = @ptrFromInt(0);
2565 pub const IGN = @as(?Sigaction.handler_fn, @ptrFromInt(1));2560 pub const IGN: ?Sigaction.handler_fn = @ptrFromInt(1);
2566} else struct {2561} else struct {
2567 pub const BLOCK = 0;2562 pub const BLOCK = 0;
2568 pub const UNBLOCK = 1;2563 pub const UNBLOCK = 1;
...@@ -2603,9 +2598,9 @@ pub const SIG = if (is_mips) struct {...@@ -2603,9 +2598,9 @@ pub const SIG = if (is_mips) struct {
2603 pub const SYS = 31;2598 pub const SYS = 31;
2604 pub const UNUSED = SIG.SYS;2599 pub const UNUSED = SIG.SYS;
26052600
2606 pub const ERR = @as(?Sigaction.handler_fn, @ptrFromInt(maxInt(usize)));2601 pub const ERR: ?Sigaction.handler_fn = @ptrFromInt(maxInt(usize));
2607 pub const DFL = @as(?Sigaction.handler_fn, @ptrFromInt(0));2602 pub const DFL: ?Sigaction.handler_fn = @ptrFromInt(0);
2608 pub const IGN = @as(?Sigaction.handler_fn, @ptrFromInt(1));2603 pub const IGN: ?Sigaction.handler_fn = @ptrFromInt(1);
2609};2604};
26102605
2611pub const kernel_rwf = u32;2606pub const kernel_rwf = u32;
...@@ -3709,7 +3704,7 @@ pub const all_mask: sigset_t = [_]u32{0xffffffff} ** @typeInfo(sigset_t).Array.l...@@ -3709,7 +3704,7 @@ pub const all_mask: sigset_t = [_]u32{0xffffffff} ** @typeInfo(sigset_t).Array.l
3709pub const app_mask: sigset_t = [2]u32{ 0xfffffffc, 0x7fffffff } ++ [_]u32{0xffffffff} ** 30;3704pub const app_mask: sigset_t = [2]u32{ 0xfffffffc, 0x7fffffff } ++ [_]u32{0xffffffff} ** 30;
37103705
3711const k_sigaction_funcs = struct {3706const k_sigaction_funcs = struct {
3712 const handler = ?*const fn (c_int) align(1) callconv(.C) void;3707 const handler = ?*align(1) const fn (c_int) callconv(.C) void;
3713 const restorer = *const fn () callconv(.C) void;3708 const restorer = *const fn () callconv(.C) void;
3714};3709};
37153710
...@@ -3736,7 +3731,7 @@ pub const k_sigaction = switch (native_arch) {...@@ -3736,7 +3731,7 @@ pub const k_sigaction = switch (native_arch) {
37363731
3737/// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall.3732/// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall.
3738pub const Sigaction = extern struct {3733pub const Sigaction = extern struct {
3739 pub const handler_fn = *const fn (c_int) align(1) callconv(.C) void;3734 pub const handler_fn = *align(1) const fn (c_int) callconv(.C) void;
3740 pub const sigaction_fn = *const fn (c_int, *const siginfo_t, ?*const anyopaque) callconv(.C) void;3735 pub const sigaction_fn = *const fn (c_int, *const siginfo_t, ?*const anyopaque) callconv(.C) void;
37413736
3742 handler: extern union {3737 handler: extern union {
lib/std/zig/AstGen.zig+7-7
...@@ -1369,16 +1369,16 @@ fn fnProtoExpr(...@@ -1369,16 +1369,16 @@ fn fnProtoExpr(
1369 break :is_var_args false;1369 break :is_var_args false;
1370 };1370 };
13711371
1372 const align_ref: Zir.Inst.Ref = if (fn_proto.ast.align_expr == 0) .none else inst: {1372 if (fn_proto.ast.align_expr != 0) {
1373 break :inst try expr(&block_scope, scope, coerced_align_ri, fn_proto.ast.align_expr);1373 return astgen.failNode(fn_proto.ast.align_expr, "function type cannot have an alignment", .{});
1374 };1374 }
13751375
1376 if (fn_proto.ast.addrspace_expr != 0) {1376 if (fn_proto.ast.addrspace_expr != 0) {
1377 return astgen.failNode(fn_proto.ast.addrspace_expr, "addrspace not allowed on function prototypes", .{});1377 return astgen.failNode(fn_proto.ast.addrspace_expr, "function type cannot have an addrspace", .{});
1378 }1378 }
13791379
1380 if (fn_proto.ast.section_expr != 0) {1380 if (fn_proto.ast.section_expr != 0) {
1381 return astgen.failNode(fn_proto.ast.section_expr, "linksection not allowed on function prototypes", .{});1381 return astgen.failNode(fn_proto.ast.section_expr, "function type cannot have a linksection", .{});
1382 }1382 }
13831383
1384 const cc: Zir.Inst.Ref = if (fn_proto.ast.callconv_expr != 0)1384 const cc: Zir.Inst.Ref = if (fn_proto.ast.callconv_expr != 0)
...@@ -1394,7 +1394,7 @@ fn fnProtoExpr(...@@ -1394,7 +1394,7 @@ fn fnProtoExpr(
1394 const maybe_bang = tree.firstToken(fn_proto.ast.return_type) - 1;1394 const maybe_bang = tree.firstToken(fn_proto.ast.return_type) - 1;
1395 const is_inferred_error = token_tags[maybe_bang] == .bang;1395 const is_inferred_error = token_tags[maybe_bang] == .bang;
1396 if (is_inferred_error) {1396 if (is_inferred_error) {
1397 return astgen.failTok(maybe_bang, "function prototype may not have inferred error set", .{});1397 return astgen.failTok(maybe_bang, "function type cannot have an inferred error set", .{});
1398 }1398 }
1399 const ret_ty = try expr(&block_scope, scope, coerced_type_ri, fn_proto.ast.return_type);1399 const ret_ty = try expr(&block_scope, scope, coerced_type_ri, fn_proto.ast.return_type);
14001400
...@@ -1403,7 +1403,7 @@ fn fnProtoExpr(...@@ -1403,7 +1403,7 @@ fn fnProtoExpr(
14031403
1404 .cc_ref = cc,1404 .cc_ref = cc,
1405 .cc_gz = null,1405 .cc_gz = null,
1406 .align_ref = align_ref,1406 .align_ref = .none,
1407 .align_gz = null,1407 .align_gz = null,
1408 .ret_ref = ret_ty,1408 .ret_ref = ret_ty,
1409 .ret_gz = null,1409 .ret_gz = null,
src/InternPool.zig+5-23
...@@ -765,16 +765,10 @@ pub const Key = union(enum) {...@@ -765,16 +765,10 @@ pub const Key = union(enum) {
765 /// Tells whether a parameter is noalias. See `paramIsNoalias` helper765 /// Tells whether a parameter is noalias. See `paramIsNoalias` helper
766 /// method for accessing this.766 /// method for accessing this.
767 noalias_bits: u32,767 noalias_bits: u32,
768 /// `none` indicates the function has the default alignment for
769 /// function code on the target. In this case, this field *must* be set
770 /// to `none`, otherwise the `InternPool` equality and hashing
771 /// functions will return incorrect results.
772 alignment: Alignment,
773 cc: std.builtin.CallingConvention,768 cc: std.builtin.CallingConvention,
774 is_var_args: bool,769 is_var_args: bool,
775 is_generic: bool,770 is_generic: bool,
776 is_noinline: bool,771 is_noinline: bool,
777 align_is_generic: bool,
778 cc_is_generic: bool,772 cc_is_generic: bool,
779 section_is_generic: bool,773 section_is_generic: bool,
780 addrspace_is_generic: bool,774 addrspace_is_generic: bool,
...@@ -794,7 +788,6 @@ pub const Key = union(enum) {...@@ -794,7 +788,6 @@ pub const Key = union(enum) {
794 a.return_type == b.return_type and788 a.return_type == b.return_type and
795 a.comptime_bits == b.comptime_bits and789 a.comptime_bits == b.comptime_bits and
796 a.noalias_bits == b.noalias_bits and790 a.noalias_bits == b.noalias_bits and
797 a.alignment == b.alignment and
798 a.cc == b.cc and791 a.cc == b.cc and
799 a.is_var_args == b.is_var_args and792 a.is_var_args == b.is_var_args and
800 a.is_generic == b.is_generic and793 a.is_generic == b.is_generic and
...@@ -808,7 +801,6 @@ pub const Key = union(enum) {...@@ -808,7 +801,6 @@ pub const Key = union(enum) {
808 std.hash.autoHash(hasher, self.return_type);801 std.hash.autoHash(hasher, self.return_type);
809 std.hash.autoHash(hasher, self.comptime_bits);802 std.hash.autoHash(hasher, self.comptime_bits);
810 std.hash.autoHash(hasher, self.noalias_bits);803 std.hash.autoHash(hasher, self.noalias_bits);
811 std.hash.autoHash(hasher, self.alignment);
812 std.hash.autoHash(hasher, self.cc);804 std.hash.autoHash(hasher, self.cc);
813 std.hash.autoHash(hasher, self.is_var_args);805 std.hash.autoHash(hasher, self.is_var_args);
814 std.hash.autoHash(hasher, self.is_generic);806 std.hash.autoHash(hasher, self.is_generic);
...@@ -3587,18 +3579,16 @@ pub const Tag = enum(u8) {...@@ -3587,18 +3579,16 @@ pub const Tag = enum(u8) {
3587 flags: Flags,3579 flags: Flags,
35883580
3589 pub const Flags = packed struct(u32) {3581 pub const Flags = packed struct(u32) {
3590 alignment: Alignment,
3591 cc: std.builtin.CallingConvention,3582 cc: std.builtin.CallingConvention,
3592 is_var_args: bool,3583 is_var_args: bool,
3593 is_generic: bool,3584 is_generic: bool,
3594 has_comptime_bits: bool,3585 has_comptime_bits: bool,
3595 has_noalias_bits: bool,3586 has_noalias_bits: bool,
3596 is_noinline: bool,3587 is_noinline: bool,
3597 align_is_generic: bool,
3598 cc_is_generic: bool,3588 cc_is_generic: bool,
3599 section_is_generic: bool,3589 section_is_generic: bool,
3600 addrspace_is_generic: bool,3590 addrspace_is_generic: bool,
3601 _: u9 = 0,3591 _: u16 = 0,
3602 };3592 };
3603 };3593 };
36043594
...@@ -4918,11 +4908,9 @@ fn extraFuncType(ip: *const InternPool, extra_index: u32) Key.FuncType {...@@ -4918,11 +4908,9 @@ fn extraFuncType(ip: *const InternPool, extra_index: u32) Key.FuncType {
4918 .return_type = type_function.data.return_type,4908 .return_type = type_function.data.return_type,
4919 .comptime_bits = comptime_bits,4909 .comptime_bits = comptime_bits,
4920 .noalias_bits = noalias_bits,4910 .noalias_bits = noalias_bits,
4921 .alignment = type_function.data.flags.alignment,
4922 .cc = type_function.data.flags.cc,4911 .cc = type_function.data.flags.cc,
4923 .is_var_args = type_function.data.flags.is_var_args,4912 .is_var_args = type_function.data.flags.is_var_args,
4924 .is_noinline = type_function.data.flags.is_noinline,4913 .is_noinline = type_function.data.flags.is_noinline,
4925 .align_is_generic = type_function.data.flags.align_is_generic,
4926 .cc_is_generic = type_function.data.flags.cc_is_generic,4914 .cc_is_generic = type_function.data.flags.cc_is_generic,
4927 .section_is_generic = type_function.data.flags.section_is_generic,4915 .section_is_generic = type_function.data.flags.section_is_generic,
4928 .addrspace_is_generic = type_function.data.flags.addrspace_is_generic,4916 .addrspace_is_generic = type_function.data.flags.addrspace_is_generic,
...@@ -6211,8 +6199,6 @@ pub const GetFuncTypeKey = struct {...@@ -6211,8 +6199,6 @@ pub const GetFuncTypeKey = struct {
6211 comptime_bits: u32 = 0,6199 comptime_bits: u32 = 0,
6212 noalias_bits: u32 = 0,6200 noalias_bits: u32 = 0,
6213 /// `null` means generic.6201 /// `null` means generic.
6214 alignment: ?Alignment = .none,
6215 /// `null` means generic.
6216 cc: ?std.builtin.CallingConvention = .Unspecified,6202 cc: ?std.builtin.CallingConvention = .Unspecified,
6217 is_var_args: bool = false,6203 is_var_args: bool = false,
6218 is_generic: bool = false,6204 is_generic: bool = false,
...@@ -6242,14 +6228,12 @@ pub fn getFuncType(ip: *InternPool, gpa: Allocator, key: GetFuncTypeKey) Allocat...@@ -6242,14 +6228,12 @@ pub fn getFuncType(ip: *InternPool, gpa: Allocator, key: GetFuncTypeKey) Allocat
6242 .params_len = params_len,6228 .params_len = params_len,
6243 .return_type = key.return_type,6229 .return_type = key.return_type,
6244 .flags = .{6230 .flags = .{
6245 .alignment = key.alignment orelse .none,
6246 .cc = key.cc orelse .Unspecified,6231 .cc = key.cc orelse .Unspecified,
6247 .is_var_args = key.is_var_args,6232 .is_var_args = key.is_var_args,
6248 .has_comptime_bits = key.comptime_bits != 0,6233 .has_comptime_bits = key.comptime_bits != 0,
6249 .has_noalias_bits = key.noalias_bits != 0,6234 .has_noalias_bits = key.noalias_bits != 0,
6250 .is_generic = key.is_generic,6235 .is_generic = key.is_generic,
6251 .is_noinline = key.is_noinline,6236 .is_noinline = key.is_noinline,
6252 .align_is_generic = key.alignment == null,
6253 .cc_is_generic = key.cc == null,6237 .cc_is_generic = key.cc == null,
6254 .section_is_generic = key.section_is_generic,6238 .section_is_generic = key.section_is_generic,
6255 .addrspace_is_generic = key.addrspace_is_generic,6239 .addrspace_is_generic = key.addrspace_is_generic,
...@@ -6433,14 +6417,12 @@ pub fn getFuncDeclIes(ip: *InternPool, gpa: Allocator, key: GetFuncDeclIesKey) A...@@ -6433,14 +6417,12 @@ pub fn getFuncDeclIes(ip: *InternPool, gpa: Allocator, key: GetFuncDeclIesKey) A
6433 .params_len = params_len,6417 .params_len = params_len,
6434 .return_type = @enumFromInt(ip.items.len - 2),6418 .return_type = @enumFromInt(ip.items.len - 2),
6435 .flags = .{6419 .flags = .{
6436 .alignment = key.alignment orelse .none,
6437 .cc = key.cc orelse .Unspecified,6420 .cc = key.cc orelse .Unspecified,
6438 .is_var_args = key.is_var_args,6421 .is_var_args = key.is_var_args,
6439 .has_comptime_bits = key.comptime_bits != 0,6422 .has_comptime_bits = key.comptime_bits != 0,
6440 .has_noalias_bits = key.noalias_bits != 0,6423 .has_noalias_bits = key.noalias_bits != 0,
6441 .is_generic = key.is_generic,6424 .is_generic = key.is_generic,
6442 .is_noinline = key.is_noinline,6425 .is_noinline = key.is_noinline,
6443 .align_is_generic = key.alignment == null,
6444 .cc_is_generic = key.cc == null,6426 .cc_is_generic = key.cc == null,
6445 .section_is_generic = key.section_is_generic,6427 .section_is_generic = key.section_is_generic,
6446 .addrspace_is_generic = key.addrspace_is_generic,6428 .addrspace_is_generic = key.addrspace_is_generic,
...@@ -6553,7 +6535,6 @@ pub fn getFuncInstance(ip: *InternPool, gpa: Allocator, arg: GetFuncInstanceKey)...@@ -6553,7 +6535,6 @@ pub fn getFuncInstance(ip: *InternPool, gpa: Allocator, arg: GetFuncInstanceKey)
6553 .param_types = arg.param_types,6535 .param_types = arg.param_types,
6554 .return_type = arg.bare_return_type,6536 .return_type = arg.bare_return_type,
6555 .noalias_bits = arg.noalias_bits,6537 .noalias_bits = arg.noalias_bits,
6556 .alignment = arg.alignment,
6557 .cc = arg.cc,6538 .cc = arg.cc,
6558 .is_noinline = arg.is_noinline,6539 .is_noinline = arg.is_noinline,
6559 });6540 });
...@@ -6610,6 +6591,7 @@ pub fn getFuncInstance(ip: *InternPool, gpa: Allocator, arg: GetFuncInstanceKey)...@@ -6610,6 +6591,7 @@ pub fn getFuncInstance(ip: *InternPool, gpa: Allocator, arg: GetFuncInstanceKey)
6610 func_index,6591 func_index,
6611 func_extra_index,6592 func_extra_index,
6612 func_ty,6593 func_ty,
6594 arg.alignment,
6613 arg.section,6595 arg.section,
6614 );6596 );
6615}6597}
...@@ -6673,14 +6655,12 @@ pub fn getFuncInstanceIes(...@@ -6673,14 +6655,12 @@ pub fn getFuncInstanceIes(
6673 .params_len = params_len,6655 .params_len = params_len,
6674 .return_type = error_union_type,6656 .return_type = error_union_type,
6675 .flags = .{6657 .flags = .{
6676 .alignment = arg.alignment,
6677 .cc = arg.cc,6658 .cc = arg.cc,
6678 .is_var_args = false,6659 .is_var_args = false,
6679 .has_comptime_bits = false,6660 .has_comptime_bits = false,
6680 .has_noalias_bits = arg.noalias_bits != 0,6661 .has_noalias_bits = arg.noalias_bits != 0,
6681 .is_generic = false,6662 .is_generic = false,
6682 .is_noinline = arg.is_noinline,6663 .is_noinline = arg.is_noinline,
6683 .align_is_generic = false,
6684 .cc_is_generic = false,6664 .cc_is_generic = false,
6685 .section_is_generic = false,6665 .section_is_generic = false,
6686 .addrspace_is_generic = false,6666 .addrspace_is_generic = false,
...@@ -6741,6 +6721,7 @@ pub fn getFuncInstanceIes(...@@ -6741,6 +6721,7 @@ pub fn getFuncInstanceIes(
6741 func_index,6721 func_index,
6742 func_extra_index,6722 func_extra_index,
6743 func_ty,6723 func_ty,
6724 arg.alignment,
6744 arg.section,6725 arg.section,
6745 );6726 );
6746}6727}
...@@ -6752,6 +6733,7 @@ fn finishFuncInstance(...@@ -6752,6 +6733,7 @@ fn finishFuncInstance(
6752 func_index: Index,6733 func_index: Index,
6753 func_extra_index: u32,6734 func_extra_index: u32,
6754 func_ty: Index,6735 func_ty: Index,
6736 alignment: Alignment,
6755 section: OptionalNullTerminatedString,6737 section: OptionalNullTerminatedString,
6756) Allocator.Error!Index {6738) Allocator.Error!Index {
6757 const fn_owner_decl = ip.declPtr(ip.funcDeclOwner(generic_owner));6739 const fn_owner_decl = ip.declPtr(ip.funcDeclOwner(generic_owner));
...@@ -6764,7 +6746,7 @@ fn finishFuncInstance(...@@ -6764,7 +6746,7 @@ fn finishFuncInstance(
6764 .owns_tv = true,6746 .owns_tv = true,
6765 .ty = @import("type.zig").Type.fromInterned(func_ty),6747 .ty = @import("type.zig").Type.fromInterned(func_ty),
6766 .val = @import("Value.zig").fromInterned(func_index),6748 .val = @import("Value.zig").fromInterned(func_index),
6767 .alignment = .none,6749 .alignment = alignment,
6768 .@"linksection" = section,6750 .@"linksection" = section,
6769 .@"addrspace" = fn_owner_decl.@"addrspace",6751 .@"addrspace" = fn_owner_decl.@"addrspace",
6770 .analysis = .complete,6752 .analysis = .complete,
src/Module.zig+72-104
...@@ -3596,6 +3596,18 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult {...@@ -3596,6 +3596,18 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult {
35963596
3597 log.debug("semaDecl '{d}'", .{@intFromEnum(decl_index)});3597 log.debug("semaDecl '{d}'", .{@intFromEnum(decl_index)});
35983598
3599 const old_has_tv = decl.has_tv;
3600 // The following values are ignored if `!old_has_tv`
3601 const old_ty = decl.ty;
3602 const old_val = decl.val;
3603 const old_align = decl.alignment;
3604 const old_linksection = decl.@"linksection";
3605 const old_addrspace = decl.@"addrspace";
3606 const old_is_inline = if (decl.getOwnedFunction(mod)) |prev_func|
3607 prev_func.analysis(ip).state == .inline_only
3608 else
3609 false;
3610
3599 const decl_inst = decl.zir_decl_index.unwrap().?.resolve(ip);3611 const decl_inst = decl.zir_decl_index.unwrap().?.resolve(ip);
36003612
3601 const gpa = mod.gpa;3613 const gpa = mod.gpa;
...@@ -3733,141 +3745,96 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult {...@@ -3733,141 +3745,96 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult {
3733 };3745 };
3734 }3746 }
37353747
3736 switch (ip.indexToKey(decl_tv.val.toIntern())) {3748 var queue_linker_work = true;
3737 .func => |func| {3749 var is_func = false;
3738 const owns_tv = func.owner_decl == decl_index;3750 var is_inline = false;
3739 if (owns_tv) {
3740 var prev_type_has_bits = false;
3741 var prev_is_inline = false;
3742 var type_changed = true;
3743
3744 if (decl.has_tv) {
3745 prev_type_has_bits = decl.ty.isFnOrHasRuntimeBits(mod);
3746 type_changed = !decl.ty.eql(decl_tv.ty, mod);
3747 if (decl.getOwnedFunction(mod)) |prev_func| {
3748 prev_is_inline = prev_func.analysis(ip).state == .inline_only;
3749 }
3750 }
3751
3752 decl.ty = decl_tv.ty;
3753 decl.val = Value.fromInterned((try decl_tv.val.intern(decl_tv.ty, mod)));
3754 // linksection, align, and addrspace were already set by Sema
3755 decl.has_tv = true;
3756 decl.owns_tv = owns_tv;
3757 decl.analysis = .complete;
3758
3759 const is_inline = decl.ty.fnCallingConvention(mod) == .Inline;
3760 if (decl.is_exported) {
3761 const export_src: LazySrcLoc = .{ .token_offset = @intFromBool(decl.is_pub) };
3762 if (is_inline) {
3763 return sema.fail(&block_scope, export_src, "export of inline function", .{});
3764 }
3765 // The scope needs to have the decl in it.
3766 try sema.analyzeExport(&block_scope, export_src, .{ .name = decl.name }, decl_index);
3767 }
3768 // TODO: align, linksection, addrspace?
3769 const changed = type_changed or is_inline != prev_is_inline;
3770 return .{
3771 .invalidate_decl_val = changed,
3772 .invalidate_decl_ref = changed,
3773 };
3774 }
3775 },
3776 else => {},
3777 }
3778
3779 decl.owns_tv = false;
3780 var queue_linker_work = false;
3781 var is_extern = false;
3782 switch (decl_tv.val.toIntern()) {3751 switch (decl_tv.val.toIntern()) {
3783 .generic_poison => unreachable,3752 .generic_poison => unreachable,
3784 .unreachable_value => unreachable,3753 .unreachable_value => unreachable,
3785 else => switch (ip.indexToKey(decl_tv.val.toIntern())) {3754 else => switch (ip.indexToKey(decl_tv.val.toIntern())) {
3786 .variable => |variable| if (variable.decl == decl_index) {3755 .variable => |variable| {
3787 decl.owns_tv = true;3756 decl.owns_tv = variable.decl == decl_index;
3788 queue_linker_work = true;3757 queue_linker_work = decl.owns_tv;
3789 },3758 },
37903759
3791 .extern_func => |extern_fn| if (extern_fn.decl == decl_index) {3760 .extern_func => |extern_func| {
3792 decl.owns_tv = true;3761 decl.owns_tv = extern_func.decl == decl_index;
3793 queue_linker_work = true;3762 queue_linker_work = decl.owns_tv;
3794 is_extern = true;3763 is_func = decl.owns_tv;
3795 },3764 },
37963765
3797 .func => {},3766 .func => |func| {
37983767 decl.owns_tv = func.owner_decl == decl_index;
3799 else => {3768 queue_linker_work = false;
3800 queue_linker_work = true;3769 is_inline = decl.owns_tv and decl_tv.ty.fnCallingConvention(mod) == .Inline;
3770 is_func = decl.owns_tv;
3801 },3771 },
3772
3773 else => {},
3802 },3774 },
3803 }3775 }
38043776
3805 const old_has_tv = decl.has_tv;
3806 // The following values are ignored if `!old_has_tv`
3807 const old_ty = decl.ty;
3808 const old_val = decl.val;
3809 const old_align = decl.alignment;
3810 const old_linksection = decl.@"linksection";
3811 const old_addrspace = decl.@"addrspace";
3812
3813 decl.ty = decl_tv.ty;3777 decl.ty = decl_tv.ty;
3814 decl.val = Value.fromInterned((try decl_tv.val.intern(decl_tv.ty, mod)));3778 decl.val = Value.fromInterned((try decl_tv.val.intern(decl_tv.ty, mod)));
3815 decl.alignment = blk: {3779 // Function linksection, align, and addrspace were already set by Sema
3816 const align_body = decl_bodies.align_body orelse break :blk .none;3780 if (!is_func) {
3817 const align_ref = try sema.resolveInlineBody(&block_scope, align_body, decl_inst);3781 decl.alignment = blk: {
3818 break :blk try sema.analyzeAsAlign(&block_scope, align_src, align_ref);3782 const align_body = decl_bodies.align_body orelse break :blk .none;
3819 };3783 const align_ref = try sema.resolveInlineBody(&block_scope, align_body, decl_inst);
3820 decl.@"linksection" = blk: {3784 break :blk try sema.analyzeAsAlign(&block_scope, align_src, align_ref);
3821 const linksection_body = decl_bodies.linksection_body orelse break :blk .none;
3822 const linksection_ref = try sema.resolveInlineBody(&block_scope, linksection_body, decl_inst);
3823 const bytes = try sema.toConstString(&block_scope, section_src, linksection_ref, .{
3824 .needed_comptime_reason = "linksection must be comptime-known",
3825 });
3826 if (mem.indexOfScalar(u8, bytes, 0) != null) {
3827 return sema.fail(&block_scope, section_src, "linksection cannot contain null bytes", .{});
3828 } else if (bytes.len == 0) {
3829 return sema.fail(&block_scope, section_src, "linksection cannot be empty", .{});
3830 }
3831 const section = try ip.getOrPutString(gpa, bytes);
3832 break :blk section.toOptional();
3833 };
3834 decl.@"addrspace" = blk: {
3835 const addrspace_ctx: Sema.AddressSpaceContext = switch (ip.indexToKey(decl_tv.val.toIntern())) {
3836 .variable => .variable,
3837 .extern_func, .func => .function,
3838 else => .constant,
3839 };3785 };
3786 decl.@"linksection" = blk: {
3787 const linksection_body = decl_bodies.linksection_body orelse break :blk .none;
3788 const linksection_ref = try sema.resolveInlineBody(&block_scope, linksection_body, decl_inst);
3789 const bytes = try sema.toConstString(&block_scope, section_src, linksection_ref, .{
3790 .needed_comptime_reason = "linksection must be comptime-known",
3791 });
3792 if (mem.indexOfScalar(u8, bytes, 0) != null) {
3793 return sema.fail(&block_scope, section_src, "linksection cannot contain null bytes", .{});
3794 } else if (bytes.len == 0) {
3795 return sema.fail(&block_scope, section_src, "linksection cannot be empty", .{});
3796 }
3797 const section = try ip.getOrPutString(gpa, bytes);
3798 break :blk section.toOptional();
3799 };
3800 decl.@"addrspace" = blk: {
3801 const addrspace_ctx: Sema.AddressSpaceContext = switch (ip.indexToKey(decl_tv.val.toIntern())) {
3802 .variable => .variable,
3803 .extern_func, .func => .function,
3804 else => .constant,
3805 };
38403806
3841 const target = sema.mod.getTarget();3807 const target = sema.mod.getTarget();
38423808
3843 const addrspace_body = decl_bodies.addrspace_body orelse break :blk switch (addrspace_ctx) {3809 const addrspace_body = decl_bodies.addrspace_body orelse break :blk switch (addrspace_ctx) {
3844 .function => target_util.defaultAddressSpace(target, .function),3810 .function => target_util.defaultAddressSpace(target, .function),
3845 .variable => target_util.defaultAddressSpace(target, .global_mutable),3811 .variable => target_util.defaultAddressSpace(target, .global_mutable),
3846 .constant => target_util.defaultAddressSpace(target, .global_constant),3812 .constant => target_util.defaultAddressSpace(target, .global_constant),
3847 else => unreachable,3813 else => unreachable,
3814 };
3815 const addrspace_ref = try sema.resolveInlineBody(&block_scope, addrspace_body, decl_inst);
3816 break :blk try sema.analyzeAsAddressSpace(&block_scope, address_space_src, addrspace_ref, addrspace_ctx);
3848 };3817 };
3849 const addrspace_ref = try sema.resolveInlineBody(&block_scope, addrspace_body, decl_inst);3818 }
3850 break :blk try sema.analyzeAsAddressSpace(&block_scope, address_space_src, addrspace_ref, addrspace_ctx);
3851 };
3852 decl.has_tv = true;3819 decl.has_tv = true;
3853 decl.analysis = .complete;3820 decl.analysis = .complete;
38543821
3855 const result: SemaDeclResult = if (old_has_tv) .{3822 const result: SemaDeclResult = if (old_has_tv) .{
3856 .invalidate_decl_val = !decl.ty.eql(old_ty, mod) or !decl.val.eql(old_val, decl.ty, mod),3823 .invalidate_decl_val = !decl.ty.eql(old_ty, mod) or
3824 !decl.val.eql(old_val, decl.ty, mod) or
3825 is_inline != old_is_inline,
3857 .invalidate_decl_ref = !decl.ty.eql(old_ty, mod) or3826 .invalidate_decl_ref = !decl.ty.eql(old_ty, mod) or
3858 decl.alignment != old_align or3827 decl.alignment != old_align or
3859 decl.@"linksection" != old_linksection or3828 decl.@"linksection" != old_linksection or
3860 decl.@"addrspace" != old_addrspace,3829 decl.@"addrspace" != old_addrspace or
3830 is_inline != old_is_inline,
3861 } else .{3831 } else .{
3862 .invalidate_decl_val = true,3832 .invalidate_decl_val = true,
3863 .invalidate_decl_ref = true,3833 .invalidate_decl_ref = true,
3864 };3834 };
38653835
3866 const has_runtime_bits = is_extern or3836 const has_runtime_bits = queue_linker_work and (is_func or try sema.typeHasRuntimeBits(decl.ty));
3867 (queue_linker_work and try sema.typeHasRuntimeBits(decl.ty));
3868
3869 if (has_runtime_bits) {3837 if (has_runtime_bits) {
3870
3871 // Needed for codegen_decl which will call updateDecl and then the3838 // Needed for codegen_decl which will call updateDecl and then the
3872 // codegen backend wants full access to the Decl Type.3839 // codegen backend wants full access to the Decl Type.
3873 try sema.resolveTypeFully(decl.ty);3840 try sema.resolveTypeFully(decl.ty);
...@@ -3881,6 +3848,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult {...@@ -3881,6 +3848,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult {
38813848
3882 if (decl.is_exported) {3849 if (decl.is_exported) {
3883 const export_src: LazySrcLoc = .{ .token_offset = @intFromBool(decl.is_pub) };3850 const export_src: LazySrcLoc = .{ .token_offset = @intFromBool(decl.is_pub) };
3851 if (is_inline) return sema.fail(&block_scope, export_src, "export of inline function", .{});
3884 // The scope needs to have the decl in it.3852 // The scope needs to have the decl in it.
3885 try sema.analyzeExport(&block_scope, export_src, .{ .name = decl.name }, decl_index);3853 try sema.analyzeExport(&block_scope, export_src, .{ .name = decl.name }, decl_index);
3886 }3854 }
src/Sema.zig+11-32
...@@ -7605,7 +7605,6 @@ fn analyzeCall(...@@ -7605,7 +7605,6 @@ fn analyzeCall(
7605 .param_types = new_param_types,7605 .param_types = new_param_types,
7606 .return_type = owner_info.return_type,7606 .return_type = owner_info.return_type,
7607 .noalias_bits = owner_info.noalias_bits,7607 .noalias_bits = owner_info.noalias_bits,
7608 .alignment = if (owner_info.align_is_generic) null else owner_info.alignment,
7609 .cc = if (owner_info.cc_is_generic) null else owner_info.cc,7608 .cc = if (owner_info.cc_is_generic) null else owner_info.cc,
7610 .is_var_args = owner_info.is_var_args,7609 .is_var_args = owner_info.is_var_args,
7611 .is_noinline = owner_info.is_noinline,7610 .is_noinline = owner_info.is_noinline,
...@@ -9629,7 +9628,6 @@ fn funcCommon(...@@ -9629,7 +9628,6 @@ fn funcCommon(
9629 .comptime_bits = comptime_bits,9628 .comptime_bits = comptime_bits,
9630 .return_type = bare_return_type.toIntern(),9629 .return_type = bare_return_type.toIntern(),
9631 .cc = cc,9630 .cc = cc,
9632 .alignment = alignment,
9633 .section_is_generic = section == .generic,9631 .section_is_generic = section == .generic,
9634 .addrspace_is_generic = address_space == null,9632 .addrspace_is_generic = address_space == null,
9635 .is_var_args = var_args,9633 .is_var_args = var_args,
...@@ -9640,6 +9638,7 @@ fn funcCommon(...@@ -9640,6 +9638,7 @@ fn funcCommon(
9640 if (is_extern) {9638 if (is_extern) {
9641 assert(comptime_bits == 0);9639 assert(comptime_bits == 0);
9642 assert(cc != null);9640 assert(cc != null);
9641 assert(alignment != null);
9643 assert(section != .generic);9642 assert(section != .generic);
9644 assert(address_space != null);9643 assert(address_space != null);
9645 assert(!is_generic);9644 assert(!is_generic);
...@@ -17623,8 +17622,6 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -17623,8 +17622,6 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
17623 const field_values = .{17622 const field_values = .{
17624 // calling_convention: CallingConvention,17623 // calling_convention: CallingConvention,
17625 (try mod.enumValueFieldIndex(callconv_ty, @intFromEnum(func_ty_info.cc))).toIntern(),17624 (try mod.enumValueFieldIndex(callconv_ty, @intFromEnum(func_ty_info.cc))).toIntern(),
17626 // alignment: comptime_int,
17627 (try mod.intValue(Type.comptime_int, ty.abiAlignment(mod).toByteUnits(0))).toIntern(),
17628 // is_generic: bool,17625 // is_generic: bool,
17629 Value.makeBool(func_ty_info.is_generic).toIntern(),17626 Value.makeBool(func_ty_info.is_generic).toIntern(),
17630 // is_var_args: bool,17627 // is_var_args: bool,
...@@ -19701,12 +19698,6 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -19701,12 +19698,6 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
19701 if (inst_data.size != .One) {19698 if (inst_data.size != .One) {
19702 return sema.fail(block, elem_ty_src, "function pointers must be single pointers", .{});19699 return sema.fail(block, elem_ty_src, "function pointers must be single pointers", .{});
19703 }19700 }
19704 const fn_align = mod.typeToFunc(elem_ty).?.alignment;
19705 if (inst_data.flags.has_align and abi_align != .none and fn_align != .none and
19706 abi_align != fn_align)
19707 {
19708 return sema.fail(block, align_src, "function pointer alignment disagrees with function alignment", .{});
19709 }
19710 } else if (inst_data.size == .Many and elem_ty.zigTypeTag(mod) == .Opaque) {19701 } else if (inst_data.size == .Many and elem_ty.zigTypeTag(mod) == .Opaque) {
19711 return sema.fail(block, elem_ty_src, "unknown-length pointer to opaque not allowed", .{});19702 return sema.fail(block, elem_ty_src, "unknown-length pointer to opaque not allowed", .{});
19712 } else if (inst_data.size == .C) {19703 } else if (inst_data.size == .C) {
...@@ -21030,7 +21021,6 @@ fn zirReify(...@@ -21030,7 +21021,6 @@ fn zirReify(
21030 .needed_comptime_reason = "operand to @Type must be comptime-known",21021 .needed_comptime_reason = "operand to @Type must be comptime-known",
21031 });21022 });
21032 const union_val = ip.indexToKey(val.toIntern()).un;21023 const union_val = ip.indexToKey(val.toIntern()).un;
21033 const target = mod.getTarget();
21034 if (try Value.fromInterned(union_val.val).anyUndef(mod)) return sema.failWithUseOfUndef(block, src);21024 if (try Value.fromInterned(union_val.val).anyUndef(mod)) return sema.failWithUseOfUndef(block, src);
21035 const tag_index = type_info_ty.unionTagFieldIndex(Value.fromInterned(union_val.tag), mod).?;21025 const tag_index = type_info_ty.unionTagFieldIndex(Value.fromInterned(union_val.tag), mod).?;
21036 switch (@as(std.builtin.TypeId, @enumFromInt(tag_index))) {21026 switch (@as(std.builtin.TypeId, @enumFromInt(tag_index))) {
...@@ -21171,12 +21161,6 @@ fn zirReify(...@@ -21171,12 +21161,6 @@ fn zirReify(
21171 if (ptr_size != .One) {21161 if (ptr_size != .One) {
21172 return sema.fail(block, src, "function pointers must be single pointers", .{});21162 return sema.fail(block, src, "function pointers must be single pointers", .{});
21173 }21163 }
21174 const fn_align = mod.typeToFunc(elem_ty).?.alignment;
21175 if (abi_align != .none and fn_align != .none and
21176 abi_align != fn_align)
21177 {
21178 return sema.fail(block, src, "function pointer alignment disagrees with function alignment", .{});
21179 }
21180 } else if (ptr_size == .Many and elem_ty.zigTypeTag(mod) == .Opaque) {21164 } else if (ptr_size == .Many and elem_ty.zigTypeTag(mod) == .Opaque) {
21181 return sema.fail(block, src, "unknown-length pointer to opaque not allowed", .{});21165 return sema.fail(block, src, "unknown-length pointer to opaque not allowed", .{});
21182 } else if (ptr_size == .C) {21166 } else if (ptr_size == .C) {
...@@ -21429,10 +21413,6 @@ fn zirReify(...@@ -21429,10 +21413,6 @@ fn zirReify(
21429 ip,21413 ip,
21430 try ip.getOrPutString(gpa, "calling_convention"),21414 try ip.getOrPutString(gpa, "calling_convention"),
21431 ).?);21415 ).?);
21432 const alignment_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex(
21433 ip,
21434 try ip.getOrPutString(gpa, "alignment"),
21435 ).?);
21436 const is_generic_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex(21416 const is_generic_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex(
21437 ip,21417 ip,
21438 try ip.getOrPutString(gpa, "is_generic"),21418 try ip.getOrPutString(gpa, "is_generic"),
...@@ -21461,11 +21441,6 @@ fn zirReify(...@@ -21461,11 +21441,6 @@ fn zirReify(
21461 try sema.checkCallConvSupportsVarArgs(block, src, cc);21441 try sema.checkCallConvSupportsVarArgs(block, src, cc);
21462 }21442 }
2146321443
21464 const alignment = alignment: {
21465 const alignment = try sema.validateAlignAllowZero(block, src, try alignment_val.toUnsignedIntAdvanced(sema));
21466 const default = target_util.defaultFunctionAlignment(target);
21467 break :alignment if (alignment == default) .none else alignment;
21468 };
21469 const return_type = return_type_val.optionalValue(mod) orelse21444 const return_type = return_type_val.optionalValue(mod) orelse
21470 return sema.fail(block, src, "Type.Fn.return_type must be non-null for @Type", .{});21445 return sema.fail(block, src, "Type.Fn.return_type must be non-null for @Type", .{});
2147121446
...@@ -21510,7 +21485,6 @@ fn zirReify(...@@ -21510,7 +21485,6 @@ fn zirReify(
21510 .param_types = param_types,21485 .param_types = param_types,
21511 .noalias_bits = noalias_bits,21486 .noalias_bits = noalias_bits,
21512 .return_type = return_type.toIntern(),21487 .return_type = return_type.toIntern(),
21513 .alignment = alignment,
21514 .cc = cc,21488 .cc = cc,
21515 .is_var_args = is_var_args,21489 .is_var_args = is_var_args,
21516 });21490 });
...@@ -32536,16 +32510,21 @@ fn analyzeDeclRefInner(sema: *Sema, decl_index: InternPool.DeclIndex, analyze_fn...@@ -32536,16 +32510,21 @@ fn analyzeDeclRefInner(sema: *Sema, decl_index: InternPool.DeclIndex, analyze_fn
32536 const mod = sema.mod;32510 const mod = sema.mod;
32537 try sema.ensureDeclAnalyzed(decl_index);32511 try sema.ensureDeclAnalyzed(decl_index);
3253832512
32539 const decl = mod.declPtr(decl_index);32513 const decl_tv = try mod.declPtr(decl_index).typedValue();
32540 const decl_tv = try decl.typedValue();32514 const owner_decl = mod.declPtr(switch (mod.intern_pool.indexToKey(decl_tv.val.toIntern())) {
32515 .variable => |variable| variable.decl,
32516 .extern_func => |extern_func| extern_func.decl,
32517 .func => |func| func.owner_decl,
32518 else => decl_index,
32519 });
32541 // TODO: if this is a `decl_ref` of a non-variable decl, only depend on decl type32520 // TODO: if this is a `decl_ref` of a non-variable decl, only depend on decl type
32542 try sema.declareDependency(.{ .decl_val = decl_index });32521 try sema.declareDependency(.{ .decl_val = decl_index });
32543 const ptr_ty = try sema.ptrType(.{32522 const ptr_ty = try sema.ptrType(.{
32544 .child = decl_tv.ty.toIntern(),32523 .child = decl_tv.ty.toIntern(),
32545 .flags = .{32524 .flags = .{
32546 .alignment = decl.alignment,32525 .alignment = owner_decl.alignment,
32547 .is_const = if (decl.val.getVariable(mod)) |variable| variable.is_const else true,32526 .is_const = if (decl_tv.val.getVariable(mod)) |variable| variable.is_const else true,
32548 .address_space = decl.@"addrspace",32527 .address_space = owner_decl.@"addrspace",
32549 },32528 },
32550 });32529 });
32551 if (analyze_fn_body) {32530 if (analyze_fn_body) {
src/codegen/c.zig+2-2
...@@ -1635,7 +1635,7 @@ pub const DeclGen = struct {...@@ -1635,7 +1635,7 @@ pub const DeclGen = struct {
16351635
1636 switch (kind) {1636 switch (kind) {
1637 .forward => {},1637 .forward => {},
1638 .complete => if (fn_info.alignment.toByteUnitsOptional()) |a| {1638 .complete => if (fn_decl.alignment.toByteUnitsOptional()) |a| {
1639 try w.print("{}zig_align_fn({})", .{ trailing, a });1639 try w.print("{}zig_align_fn({})", .{ trailing, a });
1640 trailing = .maybe_space;1640 trailing = .maybe_space;
1641 },1641 },
...@@ -1666,7 +1666,7 @@ pub const DeclGen = struct {...@@ -1666,7 +1666,7 @@ pub const DeclGen = struct {
16661666
1667 switch (kind) {1667 switch (kind) {
1668 .forward => {1668 .forward => {
1669 if (fn_info.alignment.toByteUnitsOptional()) |a| {1669 if (fn_decl.alignment.toByteUnitsOptional()) |a| {
1670 try w.print(" zig_align_fn({})", .{a});1670 try w.print(" zig_align_fn({})", .{a});
1671 }1671 }
1672 switch (name) {1672 switch (name) {
src/codegen/llvm.zig+2-2
...@@ -2949,8 +2949,8 @@ pub const Object = struct {...@@ -2949,8 +2949,8 @@ pub const Object = struct {
2949 else => function_index.setCallConv(toLlvmCallConv(fn_info.cc, target), &o.builder),2949 else => function_index.setCallConv(toLlvmCallConv(fn_info.cc, target), &o.builder),
2950 }2950 }
29512951
2952 if (fn_info.alignment != .none)2952 if (decl.alignment != .none)
2953 function_index.setAlignment(fn_info.alignment.toLlvm(), &o.builder);2953 function_index.setAlignment(decl.alignment.toLlvm(), &o.builder);
29542954
2955 // Function attributes that are independent of analysis results of the function body.2955 // Function attributes that are independent of analysis results of the function body.
2956 try o.addCommonFnAttributes(&attributes, owner_mod);2956 try o.addCommonFnAttributes(&attributes, owner_mod);
src/type.zig+1-9
...@@ -396,9 +396,6 @@ pub const Type = struct {...@@ -396,9 +396,6 @@ pub const Type = struct {
396 try writer.writeAll("...");396 try writer.writeAll("...");
397 }397 }
398 try writer.writeAll(") ");398 try writer.writeAll(") ");
399 if (fn_info.alignment.toByteUnitsOptional()) |a| {
400 try writer.print("align({d}) ", .{a});
401 }
402 if (fn_info.cc != .Unspecified) {399 if (fn_info.cc != .Unspecified) {
403 try writer.writeAll("callconv(.");400 try writer.writeAll("callconv(.");
404 try writer.writeAll(@tagName(fn_info.cc));401 try writer.writeAll(@tagName(fn_info.cc));
...@@ -949,12 +946,7 @@ pub const Type = struct {...@@ -949,12 +946,7 @@ pub const Type = struct {
949 },946 },
950947
951 // represents machine code; not a pointer948 // represents machine code; not a pointer
952 .func_type => |func_type| return .{949 .func_type => return .{ .scalar = target_util.defaultFunctionAlignment(target) },
953 .scalar = if (func_type.alignment != .none)
954 func_type.alignment
955 else
956 target_util.defaultFunctionAlignment(target),
957 },
958950
959 .simple_type => |t| switch (t) {951 .simple_type => |t| switch (t) {
960 .bool,952 .bool,
test/behavior/align.zig+22-14
...@@ -311,12 +311,6 @@ test "page aligned array on stack" {...@@ -311,12 +311,6 @@ test "page aligned array on stack" {
311 try expect(number2 == 43);311 try expect(number2 == 43);
312}312}
313313
314fn derp() align(@sizeOf(usize) * 2) i32 {
315 return 1234;
316}
317fn noop1() align(1) void {}
318fn noop4() align(4) void {}
319
320test "function alignment" {314test "function alignment" {
321 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;315 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
322 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;316 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
...@@ -325,11 +319,25 @@ test "function alignment" {...@@ -325,11 +319,25 @@ test "function alignment" {
325 // function alignment is a compile error on wasm32/wasm64319 // function alignment is a compile error on wasm32/wasm64
326 if (native_arch == .wasm32 or native_arch == .wasm64) return error.SkipZigTest;320 if (native_arch == .wasm32 or native_arch == .wasm64) return error.SkipZigTest;
327321
328 try expect(derp() == 1234);322 const S = struct {
329 try expect(@TypeOf(noop1) == fn () align(1) void);323 fn alignExpr() align(@sizeOf(usize) * 2) i32 {
330 try expect(@TypeOf(noop4) == fn () align(4) void);324 return 1234;
331 noop1();325 }
332 noop4();326 fn align1() align(1) void {}
327 fn align4() align(4) void {}
328 };
329
330 try expect(S.alignExpr() == 1234);
331 try expect(@TypeOf(S.alignExpr) == fn () i32);
332 try expect(@TypeOf(&S.alignExpr) == *align(@sizeOf(usize) * 2) const fn () i32);
333
334 S.align1();
335 try expect(@TypeOf(S.align1) == fn () void);
336 try expect(@TypeOf(&S.align1) == *align(1) const fn () void);
337
338 S.align4();
339 try expect(@TypeOf(S.align4) == fn () void);
340 try expect(@TypeOf(&S.align4) == *align(4) const fn () void);
333}341}
334342
335test "implicitly decreasing fn alignment" {343test "implicitly decreasing fn alignment" {
...@@ -345,7 +353,7 @@ test "implicitly decreasing fn alignment" {...@@ -345,7 +353,7 @@ test "implicitly decreasing fn alignment" {
345 try testImplicitlyDecreaseFnAlign(alignedBig, 5678);353 try testImplicitlyDecreaseFnAlign(alignedBig, 5678);
346}354}
347355
348fn testImplicitlyDecreaseFnAlign(ptr: *const fn () align(1) i32, answer: i32) !void {356fn testImplicitlyDecreaseFnAlign(ptr: *align(1) const fn () i32, answer: i32) !void {
349 try expect(ptr() == answer);357 try expect(ptr() == answer);
350}358}
351359
...@@ -368,10 +376,10 @@ test "@alignCast functions" {...@@ -368,10 +376,10 @@ test "@alignCast functions" {
368376
369 try expect(fnExpectsOnly1(simple4) == 0x19);377 try expect(fnExpectsOnly1(simple4) == 0x19);
370}378}
371fn fnExpectsOnly1(ptr: *const fn () align(1) i32) i32 {379fn fnExpectsOnly1(ptr: *align(1) const fn () i32) i32 {
372 return fnExpects4(@alignCast(ptr));380 return fnExpects4(@alignCast(ptr));
373}381}
374fn fnExpects4(ptr: *const fn () align(4) i32) i32 {382fn fnExpects4(ptr: *align(4) const fn () i32) i32 {
375 return ptr();383 return ptr();
376}384}
377fn simple4() align(4) i32 {385fn simple4() align(4) i32 {
test/behavior/type.zig-2
...@@ -527,7 +527,6 @@ test "Type.Fn" {...@@ -527,7 +527,6 @@ test "Type.Fn" {
527 {527 {
528 const fn_info = std.builtin.Type{ .Fn = .{528 const fn_info = std.builtin.Type{ .Fn = .{
529 .calling_convention = .C,529 .calling_convention = .C,
530 .alignment = 0,
531 .is_generic = false,530 .is_generic = false,
532 .is_var_args = false,531 .is_var_args = false,
533 .return_type = void,532 .return_type = void,
...@@ -643,7 +642,6 @@ test "reified function type params initialized with field pointer" {...@@ -643,7 +642,6 @@ test "reified function type params initialized with field pointer" {
643 const Bar = @Type(.{642 const Bar = @Type(.{
644 .Fn = .{643 .Fn = .{
645 .calling_convention = .Unspecified,644 .calling_convention = .Unspecified,
646 .alignment = 0,
647 .is_generic = false,645 .is_generic = false,
648 .is_var_args = false,646 .is_var_args = false,
649 .return_type = void,647 .return_type = void,
test/behavior/type_info.zig+32-10
...@@ -356,16 +356,38 @@ test "type info: function type info" {...@@ -356,16 +356,38 @@ test "type info: function type info" {
356}356}
357357
358fn testFunction() !void {358fn testFunction() !void {
359 const fn_info = @typeInfo(@TypeOf(typeInfoFoo));359 const foo_fn_type = @TypeOf(typeInfoFoo);
360 try expect(fn_info == .Fn);360 const foo_fn_info = @typeInfo(foo_fn_type);
361 try expect(fn_info.Fn.alignment > 0);361 try expect(foo_fn_info.Fn.calling_convention == .C);
362 try expect(fn_info.Fn.calling_convention == .C);362 try expect(!foo_fn_info.Fn.is_generic);
363 try expect(!fn_info.Fn.is_generic);363 try expect(foo_fn_info.Fn.params.len == 2);
364 try expect(fn_info.Fn.params.len == 2);364 try expect(foo_fn_info.Fn.is_var_args);
365 try expect(fn_info.Fn.is_var_args);365 try expect(foo_fn_info.Fn.return_type.? == usize);
366 try expect(fn_info.Fn.return_type.? == usize);366 const foo_ptr_fn_info = @typeInfo(@TypeOf(&typeInfoFoo));
367 const fn_aligned_info = @typeInfo(@TypeOf(typeInfoFooAligned));367 try expect(foo_ptr_fn_info.Pointer.size == .One);
368 try expect(fn_aligned_info.Fn.alignment == 4);368 try expect(foo_ptr_fn_info.Pointer.is_const);
369 try expect(!foo_ptr_fn_info.Pointer.is_volatile);
370 try expect(foo_ptr_fn_info.Pointer.address_space == .generic);
371 try expect(foo_ptr_fn_info.Pointer.child == foo_fn_type);
372 try expect(!foo_ptr_fn_info.Pointer.is_allowzero);
373 try expect(foo_ptr_fn_info.Pointer.sentinel == null);
374
375 const aligned_foo_fn_type = @TypeOf(typeInfoFooAligned);
376 const aligned_foo_fn_info = @typeInfo(aligned_foo_fn_type);
377 try expect(aligned_foo_fn_info.Fn.calling_convention == .C);
378 try expect(!aligned_foo_fn_info.Fn.is_generic);
379 try expect(aligned_foo_fn_info.Fn.params.len == 2);
380 try expect(aligned_foo_fn_info.Fn.is_var_args);
381 try expect(aligned_foo_fn_info.Fn.return_type.? == usize);
382 const aligned_foo_ptr_fn_info = @typeInfo(@TypeOf(&typeInfoFooAligned));
383 try expect(aligned_foo_ptr_fn_info.Pointer.size == .One);
384 try expect(aligned_foo_ptr_fn_info.Pointer.is_const);
385 try expect(!aligned_foo_ptr_fn_info.Pointer.is_volatile);
386 try expect(aligned_foo_ptr_fn_info.Pointer.alignment == 4);
387 try expect(aligned_foo_ptr_fn_info.Pointer.address_space == .generic);
388 try expect(aligned_foo_ptr_fn_info.Pointer.child == aligned_foo_fn_type);
389 try expect(!aligned_foo_ptr_fn_info.Pointer.is_allowzero);
390 try expect(aligned_foo_ptr_fn_info.Pointer.sentinel == null);
369}391}
370392
371extern fn typeInfoFoo(a: usize, b: bool, ...) callconv(.C) usize;393extern fn typeInfoFoo(a: usize, b: bool, ...) callconv(.C) usize;
test/behavior/typename.zig+2-4
...@@ -78,11 +78,9 @@ test "basic" {...@@ -78,11 +78,9 @@ test "basic" {
78 try expectEqualStrings("fn (comptime u32) void", @typeName(fn (comptime u32) void));78 try expectEqualStrings("fn (comptime u32) void", @typeName(fn (comptime u32) void));
79 try expectEqualStrings("fn (noalias []u8) void", @typeName(fn (noalias []u8) void));79 try expectEqualStrings("fn (noalias []u8) void", @typeName(fn (noalias []u8) void));
8080
81 try expectEqualStrings("fn () align(32) void", @typeName(fn () align(32) void));
82 try expectEqualStrings("fn () callconv(.C) void", @typeName(fn () callconv(.C) void));81 try expectEqualStrings("fn () callconv(.C) void", @typeName(fn () callconv(.C) void));
83 try expectEqualStrings("fn () align(32) callconv(.C) void", @typeName(fn () align(32) callconv(.C) void));82 try expectEqualStrings("fn (...) callconv(.C) void", @typeName(fn (...) callconv(.C) void));
84 try expectEqualStrings("fn (...) align(32) callconv(.C) void", @typeName(fn (...) align(32) callconv(.C) void));83 try expectEqualStrings("fn (u32, ...) callconv(.C) void", @typeName(fn (u32, ...) callconv(.C) void));
85 try expectEqualStrings("fn (u32, ...) align(32) callconv(.C) void", @typeName(fn (u32, ...) align(32) callconv(.C) void));
86}84}
8785
88test "top level decl" {86test "top level decl" {
test/cases/compile_errors/function_ptr_alignment.zig+8-20
...@@ -1,28 +1,16 @@...@@ -1,28 +1,16 @@
1comptime {1fn align1() align(1) void {}
2 var a: *align(2) @TypeOf(foo) = undefined;2fn align2() align(2) void {}
3 _ = &a;
4}
5fn foo() void {}
63
7comptime {4comptime {
8 var a: *align(1) fn () void = undefined;5 _ = @as(*align(1) const fn () void, &align2);
9 _ = &a;6 _ = @as(*align(1) const fn () void, &align1);
10}7 _ = @as(*align(2) const fn () void, &align2);
11comptime {8 _ = @as(*align(2) const fn () void, &align1);
12 var a: *align(2) fn () align(2) void = undefined;
13 _ = &a;
14}
15comptime {
16 var a: *align(2) fn () void = undefined;
17 _ = &a;
18}
19comptime {
20 var a: *align(1) fn () align(2) void = undefined;
21 _ = &a;
22}9}
2310
24// error11// error
25// backend=stage212// backend=stage2
26// target=native13// target=native
27//14//
28// :20:19: error: function pointer alignment disagrees with function alignment15// :8:41: error: expected type '*align(2) const fn () void', found '*const fn () void'
16// :8:41: note: pointer alignment '1' cannot cast into pointer alignment '2'
test/cases/compile_errors/inferring_error_set_of_function_pointer.zig deleted-9
...@@ -1,9 +0,0 @@
1comptime {
2 const z: ?fn () !void = null;
3}
4
5// error
6// backend=stage2
7// target=native
8//
9// :2:21: error: function prototype may not have inferred error set
test/cases/compile_errors/invalid_function_types.zig created+25
...@@ -0,0 +1,25 @@
1comptime {
2 _ = fn name() void;
3}
4comptime {
5 _ = fn () align(128) void;
6}
7comptime {
8 _ = fn () addrspace(.generic) void;
9}
10comptime {
11 _ = fn () linksection("section") void;
12}
13comptime {
14 _ = fn () !void;
15}
16
17// error
18// backend=stage2
19// target=native
20//
21// :2:12: error: function type cannot have a name
22// :5:21: error: function type cannot have an alignment
23// :8:26: error: function type cannot have an addrspace
24// :11:27: error: function type cannot have a linksection
25// :14:15: error: function type cannot have an inferred error set
test/cases/compile_errors/passing_an_under-aligned_function_pointer.zig+2-2
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1export fn entry() void {1export fn entry() void {
2 testImplicitlyDecreaseFnAlign(alignedSmall, 1234);2 testImplicitlyDecreaseFnAlign(alignedSmall, 1234);
3}3}
4fn testImplicitlyDecreaseFnAlign(ptr: *const fn () align(8) i32, answer: i32) void {4fn testImplicitlyDecreaseFnAlign(ptr: *align(8) const fn () i32, answer: i32) void {
5 if (ptr() != answer) unreachable;5 if (ptr() != answer) unreachable;
6}6}
7fn alignedSmall() align(4) i32 {7fn alignedSmall() align(4) i32 {
...@@ -12,5 +12,5 @@ fn alignedSmall() align(4) i32 {...@@ -12,5 +12,5 @@ fn alignedSmall() align(4) i32 {
12// backend=stage212// backend=stage2
13// target=x86_64-linux13// target=x86_64-linux
14//14//
15// :2:35: error: expected type '*const fn () align(8) i32', found '*const fn () align(4) i32'15// :2:35: error: expected type '*align(8) const fn () i32', found '*align(4) const fn () i32'
16// :2:35: note: pointer alignment '4' cannot cast into pointer alignment '8'16// :2:35: note: pointer alignment '4' cannot cast into pointer alignment '8'
test/cases/compile_errors/reify_type.Fn_with_is_generic_true.zig-1
...@@ -1,7 +1,6 @@...@@ -1,7 +1,6 @@
1const Foo = @Type(.{1const Foo = @Type(.{
2 .Fn = .{2 .Fn = .{
3 .calling_convention = .Unspecified,3 .calling_convention = .Unspecified,
4 .alignment = 0,
5 .is_generic = true,4 .is_generic = true,
6 .is_var_args = false,5 .is_var_args = false,
7 .return_type = u0,6 .return_type = u0,
test/cases/compile_errors/reify_type.Fn_with_is_var_args_true_and_non-C_callconv.zig-1
...@@ -1,7 +1,6 @@...@@ -1,7 +1,6 @@
1const Foo = @Type(.{1const Foo = @Type(.{
2 .Fn = .{2 .Fn = .{
3 .calling_convention = .Unspecified,3 .calling_convention = .Unspecified,
4 .alignment = 0,
5 .is_generic = false,4 .is_generic = false,
6 .is_var_args = true,5 .is_var_args = true,
7 .return_type = u0,6 .return_type = u0,
test/cases/compile_errors/reify_type.Fn_with_return_type_null.zig-1
...@@ -1,7 +1,6 @@...@@ -1,7 +1,6 @@
1const Foo = @Type(.{1const Foo = @Type(.{
2 .Fn = .{2 .Fn = .{
3 .calling_convention = .Unspecified,3 .calling_convention = .Unspecified,
4 .alignment = 0,
5 .is_generic = false,4 .is_generic = false,
6 .is_var_args = false,5 .is_var_args = false,
7 .return_type = null,6 .return_type = null,