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 {}
27802780
27812781test "function alignment" {
27822782 try expect(derp() == 1234);
2783 try expect(@TypeOf(noop1) == fn () align(1) void);
2784 try expect(@TypeOf(noop4) == fn () align(4) void);
2783 try expect(@TypeOf(derp) == fn () i32);
2784 try expect(@TypeOf(&derp) == *align(@sizeOf(usize) * 2) const fn () i32);
2785
27852786 noop1();
2787 try expect(@TypeOf(noop1) == fn () void);
2788 try expect(@TypeOf(&noop1) == *align(1) const fn () void);
2789
27862790 noop4();
2791 try expect(@TypeOf(noop4) == fn () void);
2792 try expect(@TypeOf(&noop4) == *align(4) const fn () void);
27872793}
27882794 {#code_end#}
27892795 <p>
lib/std/builtin.zig-1
......@@ -420,7 +420,6 @@ pub const Type = union(enum) {
420420 /// therefore must be kept in sync with the compiler implementation.
421421 pub const Fn = struct {
422422 calling_convention: CallingConvention,
423 alignment: comptime_int,
424423 is_generic: bool,
425424 is_var_args: bool,
426425 /// 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;
10531053pub const empty_sigset: sigset_t = 0;
10541054
10551055pub const SIG = struct {
1056 pub const ERR = @as(?Sigaction.handler_fn, @ptrFromInt(maxInt(usize)));
1057 pub const DFL = @as(?Sigaction.handler_fn, @ptrFromInt(0));
1058 pub const IGN = @as(?Sigaction.handler_fn, @ptrFromInt(1));
1059 pub const HOLD = @as(?Sigaction.handler_fn, @ptrFromInt(5));
1056 pub const ERR: ?Sigaction.handler_fn = @ptrFromInt(maxInt(usize));
1057 pub const DFL: ?Sigaction.handler_fn = @ptrFromInt(0);
1058 pub const IGN: ?Sigaction.handler_fn = @ptrFromInt(1);
1059 pub const HOLD: ?Sigaction.handler_fn = @ptrFromInt(5);
10601060
10611061 /// block specified signal set
10621062 pub const BLOCK = 1;
......@@ -1150,7 +1150,7 @@ pub const siginfo_t = extern struct {
11501150
11511151/// Renamed from `sigaction` to `Sigaction` to avoid conflict with function name.
11521152pub 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;
11541154 pub const sigaction_fn = *const fn (c_int, *const siginfo_t, ?*const anyopaque) callconv(.C) void;
11551155
11561156 handler: extern union {
lib/std/c/dragonfly.zig+4-4
......@@ -616,9 +616,9 @@ pub const S = struct {
616616pub const BADSIG = SIG.ERR;
617617
618618pub const SIG = struct {
619 pub const DFL = @as(?Sigaction.handler_fn, @ptrFromInt(0));
620 pub const IGN = @as(?Sigaction.handler_fn, @ptrFromInt(1));
621 pub const ERR = @as(?Sigaction.handler_fn, @ptrFromInt(maxInt(usize)));
619 pub const DFL: ?Sigaction.handler_fn = @ptrFromInt(0);
620 pub const IGN: ?Sigaction.handler_fn = @ptrFromInt(1);
621 pub const ERR: ?Sigaction.handler_fn = @ptrFromInt(maxInt(usize));
622622
623623 pub const BLOCK = 1;
624624 pub const UNBLOCK = 2;
......@@ -690,7 +690,7 @@ pub const empty_sigset = sigset_t{ .__bits = [_]c_uint{0} ** _SIG_WORDS };
690690pub const sig_atomic_t = c_int;
691691
692692pub 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;
694694 pub const sigaction_fn = *const fn (c_int, *const siginfo_t, ?*const anyopaque) callconv(.C) void;
695695
696696 /// signal handler
lib/std/c/freebsd.zig+4-4
......@@ -695,9 +695,9 @@ pub const SIG = struct {
695695 pub const UNBLOCK = 2;
696696 pub const SETMASK = 3;
697697
698 pub const DFL = @as(?Sigaction.handler_fn, @ptrFromInt(0));
699 pub const IGN = @as(?Sigaction.handler_fn, @ptrFromInt(1));
700 pub const ERR = @as(?Sigaction.handler_fn, @ptrFromInt(maxInt(usize)));
698 pub const DFL: ?Sigaction.handler_fn = @ptrFromInt(0);
699 pub const IGN: ?Sigaction.handler_fn = @ptrFromInt(1);
700 pub const ERR: ?Sigaction.handler_fn = @ptrFromInt(maxInt(usize));
701701
702702 pub const WORDS = 4;
703703 pub const MAXSIG = 128;
......@@ -1171,7 +1171,7 @@ const NSIG = 32;
11711171
11721172/// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall.
11731173pub 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;
11751175 pub const sigaction_fn = *const fn (c_int, *const siginfo_t, ?*const anyopaque) callconv(.C) void;
11761176
11771177 /// signal handler
lib/std/c/haiku.zig+4-4
......@@ -441,9 +441,9 @@ pub const SA = struct {
441441};
442442
443443pub const SIG = struct {
444 pub const ERR = @as(?Sigaction.handler_fn, @ptrFromInt(maxInt(usize)));
445 pub const DFL = @as(?Sigaction.handler_fn, @ptrFromInt(0));
446 pub const IGN = @as(?Sigaction.handler_fn, @ptrFromInt(1));
444 pub const ERR: ?Sigaction.handler_fn = @ptrFromInt(maxInt(usize));
445 pub const DFL: ?Sigaction.handler_fn = @ptrFromInt(0);
446 pub const IGN: ?Sigaction.handler_fn = @ptrFromInt(1);
447447
448448 pub const HUP = 1;
449449 pub const INT = 2;
......@@ -690,7 +690,7 @@ const NSIG = 32;
690690
691691/// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall.
692692pub 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
695695 /// signal handler
696696 __sigaction_u: extern union {
lib/std/c/netbsd.zig+4-4
......@@ -800,9 +800,9 @@ pub const winsize = extern struct {
800800const NSIG = 32;
801801
802802pub const SIG = struct {
803 pub const DFL = @as(?Sigaction.handler_fn, @ptrFromInt(0));
804 pub const IGN = @as(?Sigaction.handler_fn, @ptrFromInt(1));
805 pub const ERR = @as(?Sigaction.handler_fn, @ptrFromInt(maxInt(usize)));
803 pub const DFL: ?Sigaction.handler_fn = @ptrFromInt(0);
804 pub const IGN: ?Sigaction.handler_fn = @ptrFromInt(1);
805 pub const ERR: ?Sigaction.handler_fn = @ptrFromInt(maxInt(usize));
806806
807807 pub const WORDS = 4;
808808 pub const MAXSIG = 128;
......@@ -864,7 +864,7 @@ pub const SIG = struct {
864864
865865/// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall.
866866pub 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;
868868 pub const sigaction_fn = *const fn (c_int, *const siginfo_t, ?*const anyopaque) callconv(.C) void;
869869
870870 /// signal handler
lib/std/c/openbsd.zig+6-6
......@@ -795,11 +795,11 @@ pub const winsize = extern struct {
795795const NSIG = 33;
796796
797797pub const SIG = struct {
798 pub const DFL = @as(?Sigaction.handler_fn, @ptrFromInt(0));
799 pub const IGN = @as(?Sigaction.handler_fn, @ptrFromInt(1));
800 pub const ERR = @as(?Sigaction.handler_fn, @ptrFromInt(maxInt(usize)));
801 pub const CATCH = @as(?Sigaction.handler_fn, @ptrFromInt(2));
802 pub const HOLD = @as(?Sigaction.handler_fn, @ptrFromInt(3));
798 pub const DFL: ?Sigaction.handler_fn = @ptrFromInt(0);
799 pub const IGN: ?Sigaction.handler_fn = @ptrFromInt(1);
800 pub const ERR: ?Sigaction.handler_fn = @ptrFromInt(maxInt(usize));
801 pub const CATCH: ?Sigaction.handler_fn = @ptrFromInt(2);
802 pub const HOLD: ?Sigaction.handler_fn = @ptrFromInt(3);
803803
804804 pub const HUP = 1;
805805 pub const INT = 2;
......@@ -842,7 +842,7 @@ pub const SIG = struct {
842842
843843/// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall.
844844pub 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;
846846 pub const sigaction_fn = *const fn (c_int, *const siginfo_t, ?*const anyopaque) callconv(.C) void;
847847
848848 /// signal handler
lib/std/c/solaris.zig+5-5
......@@ -798,10 +798,10 @@ pub const winsize = extern struct {
798798const NSIG = 75;
799799
800800pub const SIG = struct {
801 pub const DFL = @as(?Sigaction.handler_fn, @ptrFromInt(0));
802 pub const ERR = @as(?Sigaction.handler_fn, @ptrFromInt(maxInt(usize)));
803 pub const IGN = @as(?Sigaction.handler_fn, @ptrFromInt(1));
804 pub const HOLD = @as(?Sigaction.handler_fn, @ptrFromInt(2));
801 pub const DFL: ?Sigaction.handler_fn = @ptrFromInt(0);
802 pub const ERR: ?Sigaction.handler_fn = @ptrFromInt(maxInt(usize));
803 pub const IGN: ?Sigaction.handler_fn = @ptrFromInt(1);
804 pub const HOLD: ?Sigaction.handler_fn = @ptrFromInt(2);
805805
806806 pub const WORDS = 4;
807807 pub const MAXSIG = 75;
......@@ -874,7 +874,7 @@ pub const SIG = struct {
874874
875875/// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall.
876876pub 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;
878878 pub const sigaction_fn = *const fn (c_int, *const siginfo_t, ?*const anyopaque) callconv(.C) void;
879879
880880 /// signal options
lib/std/meta.zig+4-5
......@@ -57,10 +57,9 @@ test stringToEnum {
5757}
5858
5959/// Returns the alignment of type T.
60/// Note that if T is a pointer or function type the result is different than
61/// the one returned by @alignOf(T).
60/// Note that if T is a pointer type the result is different than the one
61/// returned by @alignOf(T).
6262/// 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.
6463pub fn alignment(comptime T: type) comptime_int {
6564 return switch (@typeInfo(T)) {
6665 .Optional => |info| switch (@typeInfo(info.child)) {
......@@ -68,7 +67,6 @@ pub fn alignment(comptime T: type) comptime_int {
6867 else => @alignOf(T),
6968 },
7069 .Pointer => |info| info.alignment,
71 .Fn => |info| info.alignment,
7270 else => @alignOf(T),
7371 };
7472}
......@@ -80,7 +78,8 @@ test alignment {
8078 try testing.expect(alignment([]align(1) u8) == 1);
8179 try testing.expect(alignment([]align(2) u8) == 2);
8280 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);
8483}
8584
8685/// 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 {
689689 pub const SYS = 31;
690690 pub const UNUSED = SIG.SYS;
691691
692 pub const ERR = @as(?Sigaction.handler_fn, @ptrFromInt(std.math.maxInt(usize)));
693 pub const DFL = @as(?Sigaction.handler_fn, @ptrFromInt(0));
694 pub const IGN = @as(?Sigaction.handler_fn, @ptrFromInt(1));
692 pub const ERR: ?Sigaction.handler_fn = @ptrFromInt(std.math.maxInt(usize));
693 pub const DFL: ?Sigaction.handler_fn = @ptrFromInt(0);
694 pub const IGN: ?Sigaction.handler_fn = @ptrFromInt(1);
695695};
696696
697697pub 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;
699699 pub const sigaction_fn = *const fn (c_int, *const siginfo_t, ?*const anyopaque) callconv(.C) void;
700700
701701 handler: extern union {
lib/std/os/linux.zig+18-23
......@@ -1327,16 +1327,14 @@ pub fn flock(fd: fd_t, operation: i32) usize {
13271327 return syscall2(.flock, @as(usize, @bitCast(@as(isize, fd))), @as(usize, @bitCast(@as(isize, operation))));
13281328}
13291329
1330var vdso_clock_gettime = @as(?*const anyopaque, @ptrCast(&init_vdso_clock_gettime));
1331
13321330// 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
13351334pub fn clock_gettime(clk_id: i32, tp: *timespec) usize {
13361335 if (@hasDecl(VDSO, "CGT_SYM")) {
1337 const ptr = @atomicLoad(?*const anyopaque, &vdso_clock_gettime, .unordered);
1338 if (ptr) |fn_ptr| {
1339 const f = @as(vdso_clock_gettime_ty, @ptrCast(fn_ptr));
1336 const ptr = @atomicLoad(?VdsoClockGettime, &vdso_clock_gettime, .unordered);
1337 if (ptr) |f| {
13401338 const rc = f(clk_id, tp);
13411339 switch (rc) {
13421340 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 {
13481346}
13491347
13501348fn 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));
13521350 // Note that we may not have a VDSO at all, update the stub address anyway
13531351 // 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);
13551353 // Call into the VDSO if available
1356 if (ptr) |fn_ptr| {
1357 const f = @as(vdso_clock_gettime_ty, @ptrCast(fn_ptr));
1358 return f(clk, ts);
1359 }
1354 if (ptr) |f| return f(clk, ts);
13601355 return @as(usize, @bitCast(-@as(isize, @intFromEnum(E.NOSYS))));
13611356}
13621357
......@@ -2516,9 +2511,9 @@ pub const SIG = if (is_mips) struct {
25162511 pub const SYS = 31;
25172512 pub const UNUSED = SIG.SYS;
25182513
2519 pub const ERR = @as(?Sigaction.handler_fn, @ptrFromInt(maxInt(usize)));
2520 pub const DFL = @as(?Sigaction.handler_fn, @ptrFromInt(0));
2521 pub const IGN = @as(?Sigaction.handler_fn, @ptrFromInt(1));
2514 pub const ERR: ?Sigaction.handler_fn = @ptrFromInt(maxInt(usize));
2515 pub const DFL: ?Sigaction.handler_fn = @ptrFromInt(0);
2516 pub const IGN: ?Sigaction.handler_fn = @ptrFromInt(1);
25222517} else if (is_sparc) struct {
25232518 pub const BLOCK = 1;
25242519 pub const UNBLOCK = 2;
......@@ -2560,9 +2555,9 @@ pub const SIG = if (is_mips) struct {
25602555 pub const PWR = LOST;
25612556 pub const IO = SIG.POLL;
25622557
2563 pub const ERR = @as(?Sigaction.handler_fn, @ptrFromInt(maxInt(usize)));
2564 pub const DFL = @as(?Sigaction.handler_fn, @ptrFromInt(0));
2565 pub const IGN = @as(?Sigaction.handler_fn, @ptrFromInt(1));
2558 pub const ERR: ?Sigaction.handler_fn = @ptrFromInt(maxInt(usize));
2559 pub const DFL: ?Sigaction.handler_fn = @ptrFromInt(0);
2560 pub const IGN: ?Sigaction.handler_fn = @ptrFromInt(1);
25662561} else struct {
25672562 pub const BLOCK = 0;
25682563 pub const UNBLOCK = 1;
......@@ -2603,9 +2598,9 @@ pub const SIG = if (is_mips) struct {
26032598 pub const SYS = 31;
26042599 pub const UNUSED = SIG.SYS;
26052600
2606 pub const ERR = @as(?Sigaction.handler_fn, @ptrFromInt(maxInt(usize)));
2607 pub const DFL = @as(?Sigaction.handler_fn, @ptrFromInt(0));
2608 pub const IGN = @as(?Sigaction.handler_fn, @ptrFromInt(1));
2601 pub const ERR: ?Sigaction.handler_fn = @ptrFromInt(maxInt(usize));
2602 pub const DFL: ?Sigaction.handler_fn = @ptrFromInt(0);
2603 pub const IGN: ?Sigaction.handler_fn = @ptrFromInt(1);
26092604};
26102605
26112606pub const kernel_rwf = u32;
......@@ -3709,7 +3704,7 @@ pub const all_mask: sigset_t = [_]u32{0xffffffff} ** @typeInfo(sigset_t).Array.l
37093704pub const app_mask: sigset_t = [2]u32{ 0xfffffffc, 0x7fffffff } ++ [_]u32{0xffffffff} ** 30;
37103705
37113706const 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;
37133708 const restorer = *const fn () callconv(.C) void;
37143709};
37153710
......@@ -3736,7 +3731,7 @@ pub const k_sigaction = switch (native_arch) {
37363731
37373732/// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall.
37383733pub 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;
37403735 pub const sigaction_fn = *const fn (c_int, *const siginfo_t, ?*const anyopaque) callconv(.C) void;
37413736
37423737 handler: extern union {
lib/std/zig/AstGen.zig+7-7
......@@ -1369,16 +1369,16 @@ fn fnProtoExpr(
13691369 break :is_var_args false;
13701370 };
13711371
1372 const align_ref: Zir.Inst.Ref = if (fn_proto.ast.align_expr == 0) .none else inst: {
1373 break :inst try expr(&block_scope, scope, coerced_align_ri, fn_proto.ast.align_expr);
1374 };
1372 if (fn_proto.ast.align_expr != 0) {
1373 return astgen.failNode(fn_proto.ast.align_expr, "function type cannot have an alignment", .{});
1374 }
13751375
13761376 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", .{});
13781378 }
13791379
13801380 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", .{});
13821382 }
13831383
13841384 const cc: Zir.Inst.Ref = if (fn_proto.ast.callconv_expr != 0)
......@@ -1394,7 +1394,7 @@ fn fnProtoExpr(
13941394 const maybe_bang = tree.firstToken(fn_proto.ast.return_type) - 1;
13951395 const is_inferred_error = token_tags[maybe_bang] == .bang;
13961396 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", .{});
13981398 }
13991399 const ret_ty = try expr(&block_scope, scope, coerced_type_ri, fn_proto.ast.return_type);
14001400
......@@ -1403,7 +1403,7 @@ fn fnProtoExpr(
14031403
14041404 .cc_ref = cc,
14051405 .cc_gz = null,
1406 .align_ref = align_ref,
1406 .align_ref = .none,
14071407 .align_gz = null,
14081408 .ret_ref = ret_ty,
14091409 .ret_gz = null,
src/InternPool.zig+5-23
......@@ -765,16 +765,10 @@ pub const Key = union(enum) {
765765 /// Tells whether a parameter is noalias. See `paramIsNoalias` helper
766766 /// method for accessing this.
767767 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,
773768 cc: std.builtin.CallingConvention,
774769 is_var_args: bool,
775770 is_generic: bool,
776771 is_noinline: bool,
777 align_is_generic: bool,
778772 cc_is_generic: bool,
779773 section_is_generic: bool,
780774 addrspace_is_generic: bool,
......@@ -794,7 +788,6 @@ pub const Key = union(enum) {
794788 a.return_type == b.return_type and
795789 a.comptime_bits == b.comptime_bits and
796790 a.noalias_bits == b.noalias_bits and
797 a.alignment == b.alignment and
798791 a.cc == b.cc and
799792 a.is_var_args == b.is_var_args and
800793 a.is_generic == b.is_generic and
......@@ -808,7 +801,6 @@ pub const Key = union(enum) {
808801 std.hash.autoHash(hasher, self.return_type);
809802 std.hash.autoHash(hasher, self.comptime_bits);
810803 std.hash.autoHash(hasher, self.noalias_bits);
811 std.hash.autoHash(hasher, self.alignment);
812804 std.hash.autoHash(hasher, self.cc);
813805 std.hash.autoHash(hasher, self.is_var_args);
814806 std.hash.autoHash(hasher, self.is_generic);
......@@ -3587,18 +3579,16 @@ pub const Tag = enum(u8) {
35873579 flags: Flags,
35883580
35893581 pub const Flags = packed struct(u32) {
3590 alignment: Alignment,
35913582 cc: std.builtin.CallingConvention,
35923583 is_var_args: bool,
35933584 is_generic: bool,
35943585 has_comptime_bits: bool,
35953586 has_noalias_bits: bool,
35963587 is_noinline: bool,
3597 align_is_generic: bool,
35983588 cc_is_generic: bool,
35993589 section_is_generic: bool,
36003590 addrspace_is_generic: bool,
3601 _: u9 = 0,
3591 _: u16 = 0,
36023592 };
36033593 };
36043594
......@@ -4918,11 +4908,9 @@ fn extraFuncType(ip: *const InternPool, extra_index: u32) Key.FuncType {
49184908 .return_type = type_function.data.return_type,
49194909 .comptime_bits = comptime_bits,
49204910 .noalias_bits = noalias_bits,
4921 .alignment = type_function.data.flags.alignment,
49224911 .cc = type_function.data.flags.cc,
49234912 .is_var_args = type_function.data.flags.is_var_args,
49244913 .is_noinline = type_function.data.flags.is_noinline,
4925 .align_is_generic = type_function.data.flags.align_is_generic,
49264914 .cc_is_generic = type_function.data.flags.cc_is_generic,
49274915 .section_is_generic = type_function.data.flags.section_is_generic,
49284916 .addrspace_is_generic = type_function.data.flags.addrspace_is_generic,
......@@ -6211,8 +6199,6 @@ pub const GetFuncTypeKey = struct {
62116199 comptime_bits: u32 = 0,
62126200 noalias_bits: u32 = 0,
62136201 /// `null` means generic.
6214 alignment: ?Alignment = .none,
6215 /// `null` means generic.
62166202 cc: ?std.builtin.CallingConvention = .Unspecified,
62176203 is_var_args: bool = false,
62186204 is_generic: bool = false,
......@@ -6242,14 +6228,12 @@ pub fn getFuncType(ip: *InternPool, gpa: Allocator, key: GetFuncTypeKey) Allocat
62426228 .params_len = params_len,
62436229 .return_type = key.return_type,
62446230 .flags = .{
6245 .alignment = key.alignment orelse .none,
62466231 .cc = key.cc orelse .Unspecified,
62476232 .is_var_args = key.is_var_args,
62486233 .has_comptime_bits = key.comptime_bits != 0,
62496234 .has_noalias_bits = key.noalias_bits != 0,
62506235 .is_generic = key.is_generic,
62516236 .is_noinline = key.is_noinline,
6252 .align_is_generic = key.alignment == null,
62536237 .cc_is_generic = key.cc == null,
62546238 .section_is_generic = key.section_is_generic,
62556239 .addrspace_is_generic = key.addrspace_is_generic,
......@@ -6433,14 +6417,12 @@ pub fn getFuncDeclIes(ip: *InternPool, gpa: Allocator, key: GetFuncDeclIesKey) A
64336417 .params_len = params_len,
64346418 .return_type = @enumFromInt(ip.items.len - 2),
64356419 .flags = .{
6436 .alignment = key.alignment orelse .none,
64376420 .cc = key.cc orelse .Unspecified,
64386421 .is_var_args = key.is_var_args,
64396422 .has_comptime_bits = key.comptime_bits != 0,
64406423 .has_noalias_bits = key.noalias_bits != 0,
64416424 .is_generic = key.is_generic,
64426425 .is_noinline = key.is_noinline,
6443 .align_is_generic = key.alignment == null,
64446426 .cc_is_generic = key.cc == null,
64456427 .section_is_generic = key.section_is_generic,
64466428 .addrspace_is_generic = key.addrspace_is_generic,
......@@ -6553,7 +6535,6 @@ pub fn getFuncInstance(ip: *InternPool, gpa: Allocator, arg: GetFuncInstanceKey)
65536535 .param_types = arg.param_types,
65546536 .return_type = arg.bare_return_type,
65556537 .noalias_bits = arg.noalias_bits,
6556 .alignment = arg.alignment,
65576538 .cc = arg.cc,
65586539 .is_noinline = arg.is_noinline,
65596540 });
......@@ -6610,6 +6591,7 @@ pub fn getFuncInstance(ip: *InternPool, gpa: Allocator, arg: GetFuncInstanceKey)
66106591 func_index,
66116592 func_extra_index,
66126593 func_ty,
6594 arg.alignment,
66136595 arg.section,
66146596 );
66156597}
......@@ -6673,14 +6655,12 @@ pub fn getFuncInstanceIes(
66736655 .params_len = params_len,
66746656 .return_type = error_union_type,
66756657 .flags = .{
6676 .alignment = arg.alignment,
66776658 .cc = arg.cc,
66786659 .is_var_args = false,
66796660 .has_comptime_bits = false,
66806661 .has_noalias_bits = arg.noalias_bits != 0,
66816662 .is_generic = false,
66826663 .is_noinline = arg.is_noinline,
6683 .align_is_generic = false,
66846664 .cc_is_generic = false,
66856665 .section_is_generic = false,
66866666 .addrspace_is_generic = false,
......@@ -6741,6 +6721,7 @@ pub fn getFuncInstanceIes(
67416721 func_index,
67426722 func_extra_index,
67436723 func_ty,
6724 arg.alignment,
67446725 arg.section,
67456726 );
67466727}
......@@ -6752,6 +6733,7 @@ fn finishFuncInstance(
67526733 func_index: Index,
67536734 func_extra_index: u32,
67546735 func_ty: Index,
6736 alignment: Alignment,
67556737 section: OptionalNullTerminatedString,
67566738) Allocator.Error!Index {
67576739 const fn_owner_decl = ip.declPtr(ip.funcDeclOwner(generic_owner));
......@@ -6764,7 +6746,7 @@ fn finishFuncInstance(
67646746 .owns_tv = true,
67656747 .ty = @import("type.zig").Type.fromInterned(func_ty),
67666748 .val = @import("Value.zig").fromInterned(func_index),
6767 .alignment = .none,
6749 .alignment = alignment,
67686750 .@"linksection" = section,
67696751 .@"addrspace" = fn_owner_decl.@"addrspace",
67706752 .analysis = .complete,
src/Module.zig+72-104
......@@ -3596,6 +3596,18 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult {
35963596
35973597 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
35993611 const decl_inst = decl.zir_decl_index.unwrap().?.resolve(ip);
36003612
36013613 const gpa = mod.gpa;
......@@ -3733,141 +3745,96 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult {
37333745 };
37343746 }
37353747
3736 switch (ip.indexToKey(decl_tv.val.toIntern())) {
3737 .func => |func| {
3738 const owns_tv = func.owner_decl == decl_index;
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;
3748 var queue_linker_work = true;
3749 var is_func = false;
3750 var is_inline = false;
37823751 switch (decl_tv.val.toIntern()) {
37833752 .generic_poison => unreachable,
37843753 .unreachable_value => unreachable,
37853754 else => switch (ip.indexToKey(decl_tv.val.toIntern())) {
3786 .variable => |variable| if (variable.decl == decl_index) {
3787 decl.owns_tv = true;
3788 queue_linker_work = true;
3755 .variable => |variable| {
3756 decl.owns_tv = variable.decl == decl_index;
3757 queue_linker_work = decl.owns_tv;
37893758 },
37903759
3791 .extern_func => |extern_fn| if (extern_fn.decl == decl_index) {
3792 decl.owns_tv = true;
3793 queue_linker_work = true;
3794 is_extern = true;
3760 .extern_func => |extern_func| {
3761 decl.owns_tv = extern_func.decl == decl_index;
3762 queue_linker_work = decl.owns_tv;
3763 is_func = decl.owns_tv;
37953764 },
37963765
3797 .func => {},
3798
3799 else => {
3800 queue_linker_work = true;
3766 .func => |func| {
3767 decl.owns_tv = func.owner_decl == decl_index;
3768 queue_linker_work = false;
3769 is_inline = decl.owns_tv and decl_tv.ty.fnCallingConvention(mod) == .Inline;
3770 is_func = decl.owns_tv;
38013771 },
3772
3773 else => {},
38023774 },
38033775 }
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
38133777 decl.ty = decl_tv.ty;
38143778 decl.val = Value.fromInterned((try decl_tv.val.intern(decl_tv.ty, mod)));
3815 decl.alignment = blk: {
3816 const align_body = decl_bodies.align_body orelse break :blk .none;
3817 const align_ref = try sema.resolveInlineBody(&block_scope, align_body, decl_inst);
3818 break :blk try sema.analyzeAsAlign(&block_scope, align_src, align_ref);
3819 };
3820 decl.@"linksection" = blk: {
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,
3779 // Function linksection, align, and addrspace were already set by Sema
3780 if (!is_func) {
3781 decl.alignment = blk: {
3782 const align_body = decl_bodies.align_body orelse break :blk .none;
3783 const align_ref = try sema.resolveInlineBody(&block_scope, align_body, decl_inst);
3784 break :blk try sema.analyzeAsAlign(&block_scope, align_src, align_ref);
38393785 };
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) {
3844 .function => target_util.defaultAddressSpace(target, .function),
3845 .variable => target_util.defaultAddressSpace(target, .global_mutable),
3846 .constant => target_util.defaultAddressSpace(target, .global_constant),
3847 else => unreachable,
3809 const addrspace_body = decl_bodies.addrspace_body orelse break :blk switch (addrspace_ctx) {
3810 .function => target_util.defaultAddressSpace(target, .function),
3811 .variable => target_util.defaultAddressSpace(target, .global_mutable),
3812 .constant => target_util.defaultAddressSpace(target, .global_constant),
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);
38483817 };
3849 const addrspace_ref = try sema.resolveInlineBody(&block_scope, addrspace_body, decl_inst);
3850 break :blk try sema.analyzeAsAddressSpace(&block_scope, address_space_src, addrspace_ref, addrspace_ctx);
3851 };
3818 }
38523819 decl.has_tv = true;
38533820 decl.analysis = .complete;
38543821
38553822 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,
38573826 .invalidate_decl_ref = !decl.ty.eql(old_ty, mod) or
38583827 decl.alignment != old_align or
38593828 decl.@"linksection" != old_linksection or
3860 decl.@"addrspace" != old_addrspace,
3829 decl.@"addrspace" != old_addrspace or
3830 is_inline != old_is_inline,
38613831 } else .{
38623832 .invalidate_decl_val = true,
38633833 .invalidate_decl_ref = true,
38643834 };
38653835
3866 const has_runtime_bits = is_extern or
3867 (queue_linker_work and try sema.typeHasRuntimeBits(decl.ty));
3868
3836 const has_runtime_bits = queue_linker_work and (is_func or try sema.typeHasRuntimeBits(decl.ty));
38693837 if (has_runtime_bits) {
3870
38713838 // Needed for codegen_decl which will call updateDecl and then the
38723839 // codegen backend wants full access to the Decl Type.
38733840 try sema.resolveTypeFully(decl.ty);
......@@ -3881,6 +3848,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult {
38813848
38823849 if (decl.is_exported) {
38833850 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", .{});
38843852 // The scope needs to have the decl in it.
38853853 try sema.analyzeExport(&block_scope, export_src, .{ .name = decl.name }, decl_index);
38863854 }
src/Sema.zig+11-32
......@@ -7605,7 +7605,6 @@ fn analyzeCall(
76057605 .param_types = new_param_types,
76067606 .return_type = owner_info.return_type,
76077607 .noalias_bits = owner_info.noalias_bits,
7608 .alignment = if (owner_info.align_is_generic) null else owner_info.alignment,
76097608 .cc = if (owner_info.cc_is_generic) null else owner_info.cc,
76107609 .is_var_args = owner_info.is_var_args,
76117610 .is_noinline = owner_info.is_noinline,
......@@ -9629,7 +9628,6 @@ fn funcCommon(
96299628 .comptime_bits = comptime_bits,
96309629 .return_type = bare_return_type.toIntern(),
96319630 .cc = cc,
9632 .alignment = alignment,
96339631 .section_is_generic = section == .generic,
96349632 .addrspace_is_generic = address_space == null,
96359633 .is_var_args = var_args,
......@@ -9640,6 +9638,7 @@ fn funcCommon(
96409638 if (is_extern) {
96419639 assert(comptime_bits == 0);
96429640 assert(cc != null);
9641 assert(alignment != null);
96439642 assert(section != .generic);
96449643 assert(address_space != null);
96459644 assert(!is_generic);
......@@ -17623,8 +17622,6 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1762317622 const field_values = .{
1762417623 // calling_convention: CallingConvention,
1762517624 (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(),
1762817625 // is_generic: bool,
1762917626 Value.makeBool(func_ty_info.is_generic).toIntern(),
1763017627 // is_var_args: bool,
......@@ -19701,12 +19698,6 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
1970119698 if (inst_data.size != .One) {
1970219699 return sema.fail(block, elem_ty_src, "function pointers must be single pointers", .{});
1970319700 }
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 }
1971019701 } else if (inst_data.size == .Many and elem_ty.zigTypeTag(mod) == .Opaque) {
1971119702 return sema.fail(block, elem_ty_src, "unknown-length pointer to opaque not allowed", .{});
1971219703 } else if (inst_data.size == .C) {
......@@ -21030,7 +21021,6 @@ fn zirReify(
2103021021 .needed_comptime_reason = "operand to @Type must be comptime-known",
2103121022 });
2103221023 const union_val = ip.indexToKey(val.toIntern()).un;
21033 const target = mod.getTarget();
2103421024 if (try Value.fromInterned(union_val.val).anyUndef(mod)) return sema.failWithUseOfUndef(block, src);
2103521025 const tag_index = type_info_ty.unionTagFieldIndex(Value.fromInterned(union_val.tag), mod).?;
2103621026 switch (@as(std.builtin.TypeId, @enumFromInt(tag_index))) {
......@@ -21171,12 +21161,6 @@ fn zirReify(
2117121161 if (ptr_size != .One) {
2117221162 return sema.fail(block, src, "function pointers must be single pointers", .{});
2117321163 }
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 }
2118021164 } else if (ptr_size == .Many and elem_ty.zigTypeTag(mod) == .Opaque) {
2118121165 return sema.fail(block, src, "unknown-length pointer to opaque not allowed", .{});
2118221166 } else if (ptr_size == .C) {
......@@ -21429,10 +21413,6 @@ fn zirReify(
2142921413 ip,
2143021414 try ip.getOrPutString(gpa, "calling_convention"),
2143121415 ).?);
21432 const alignment_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex(
21433 ip,
21434 try ip.getOrPutString(gpa, "alignment"),
21435 ).?);
2143621416 const is_generic_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex(
2143721417 ip,
2143821418 try ip.getOrPutString(gpa, "is_generic"),
......@@ -21461,11 +21441,6 @@ fn zirReify(
2146121441 try sema.checkCallConvSupportsVarArgs(block, src, cc);
2146221442 }
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 };
2146921444 const return_type = return_type_val.optionalValue(mod) orelse
2147021445 return sema.fail(block, src, "Type.Fn.return_type must be non-null for @Type", .{});
2147121446
......@@ -21510,7 +21485,6 @@ fn zirReify(
2151021485 .param_types = param_types,
2151121486 .noalias_bits = noalias_bits,
2151221487 .return_type = return_type.toIntern(),
21513 .alignment = alignment,
2151421488 .cc = cc,
2151521489 .is_var_args = is_var_args,
2151621490 });
......@@ -32536,16 +32510,21 @@ fn analyzeDeclRefInner(sema: *Sema, decl_index: InternPool.DeclIndex, analyze_fn
3253632510 const mod = sema.mod;
3253732511 try sema.ensureDeclAnalyzed(decl_index);
3253832512
32539 const decl = mod.declPtr(decl_index);
32540 const decl_tv = try decl.typedValue();
32513 const decl_tv = try mod.declPtr(decl_index).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 });
3254132520 // TODO: if this is a `decl_ref` of a non-variable decl, only depend on decl type
3254232521 try sema.declareDependency(.{ .decl_val = decl_index });
3254332522 const ptr_ty = try sema.ptrType(.{
3254432523 .child = decl_tv.ty.toIntern(),
3254532524 .flags = .{
32546 .alignment = decl.alignment,
32547 .is_const = if (decl.val.getVariable(mod)) |variable| variable.is_const else true,
32548 .address_space = decl.@"addrspace",
32525 .alignment = owner_decl.alignment,
32526 .is_const = if (decl_tv.val.getVariable(mod)) |variable| variable.is_const else true,
32527 .address_space = owner_decl.@"addrspace",
3254932528 },
3255032529 });
3255132530 if (analyze_fn_body) {
src/codegen/c.zig+2-2
......@@ -1635,7 +1635,7 @@ pub const DeclGen = struct {
16351635
16361636 switch (kind) {
16371637 .forward => {},
1638 .complete => if (fn_info.alignment.toByteUnitsOptional()) |a| {
1638 .complete => if (fn_decl.alignment.toByteUnitsOptional()) |a| {
16391639 try w.print("{}zig_align_fn({})", .{ trailing, a });
16401640 trailing = .maybe_space;
16411641 },
......@@ -1666,7 +1666,7 @@ pub const DeclGen = struct {
16661666
16671667 switch (kind) {
16681668 .forward => {
1669 if (fn_info.alignment.toByteUnitsOptional()) |a| {
1669 if (fn_decl.alignment.toByteUnitsOptional()) |a| {
16701670 try w.print(" zig_align_fn({})", .{a});
16711671 }
16721672 switch (name) {
src/codegen/llvm.zig+2-2
......@@ -2949,8 +2949,8 @@ pub const Object = struct {
29492949 else => function_index.setCallConv(toLlvmCallConv(fn_info.cc, target), &o.builder),
29502950 }
29512951
2952 if (fn_info.alignment != .none)
2953 function_index.setAlignment(fn_info.alignment.toLlvm(), &o.builder);
2952 if (decl.alignment != .none)
2953 function_index.setAlignment(decl.alignment.toLlvm(), &o.builder);
29542954
29552955 // Function attributes that are independent of analysis results of the function body.
29562956 try o.addCommonFnAttributes(&attributes, owner_mod);
src/type.zig+1-9
......@@ -396,9 +396,6 @@ pub const Type = struct {
396396 try writer.writeAll("...");
397397 }
398398 try writer.writeAll(") ");
399 if (fn_info.alignment.toByteUnitsOptional()) |a| {
400 try writer.print("align({d}) ", .{a});
401 }
402399 if (fn_info.cc != .Unspecified) {
403400 try writer.writeAll("callconv(.");
404401 try writer.writeAll(@tagName(fn_info.cc));
......@@ -949,12 +946,7 @@ pub const Type = struct {
949946 },
950947
951948 // represents machine code; not a pointer
952 .func_type => |func_type| return .{
953 .scalar = if (func_type.alignment != .none)
954 func_type.alignment
955 else
956 target_util.defaultFunctionAlignment(target),
957 },
949 .func_type => return .{ .scalar = target_util.defaultFunctionAlignment(target) },
958950
959951 .simple_type => |t| switch (t) {
960952 .bool,
test/behavior/align.zig+22-14
......@@ -311,12 +311,6 @@ test "page aligned array on stack" {
311311 try expect(number2 == 43);
312312}
313313
314fn derp() align(@sizeOf(usize) * 2) i32 {
315 return 1234;
316}
317fn noop1() align(1) void {}
318fn noop4() align(4) void {}
319
320314test "function alignment" {
321315 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
322316 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
......@@ -325,11 +319,25 @@ test "function alignment" {
325319 // function alignment is a compile error on wasm32/wasm64
326320 if (native_arch == .wasm32 or native_arch == .wasm64) return error.SkipZigTest;
327321
328 try expect(derp() == 1234);
329 try expect(@TypeOf(noop1) == fn () align(1) void);
330 try expect(@TypeOf(noop4) == fn () align(4) void);
331 noop1();
332 noop4();
322 const S = struct {
323 fn alignExpr() align(@sizeOf(usize) * 2) i32 {
324 return 1234;
325 }
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);
333341}
334342
335343test "implicitly decreasing fn alignment" {
......@@ -345,7 +353,7 @@ test "implicitly decreasing fn alignment" {
345353 try testImplicitlyDecreaseFnAlign(alignedBig, 5678);
346354}
347355
348fn testImplicitlyDecreaseFnAlign(ptr: *const fn () align(1) i32, answer: i32) !void {
356fn testImplicitlyDecreaseFnAlign(ptr: *align(1) const fn () i32, answer: i32) !void {
349357 try expect(ptr() == answer);
350358}
351359
......@@ -368,10 +376,10 @@ test "@alignCast functions" {
368376
369377 try expect(fnExpectsOnly1(simple4) == 0x19);
370378}
371fn fnExpectsOnly1(ptr: *const fn () align(1) i32) i32 {
379fn fnExpectsOnly1(ptr: *align(1) const fn () i32) i32 {
372380 return fnExpects4(@alignCast(ptr));
373381}
374fn fnExpects4(ptr: *const fn () align(4) i32) i32 {
382fn fnExpects4(ptr: *align(4) const fn () i32) i32 {
375383 return ptr();
376384}
377385fn simple4() align(4) i32 {
test/behavior/type.zig-2
......@@ -527,7 +527,6 @@ test "Type.Fn" {
527527 {
528528 const fn_info = std.builtin.Type{ .Fn = .{
529529 .calling_convention = .C,
530 .alignment = 0,
531530 .is_generic = false,
532531 .is_var_args = false,
533532 .return_type = void,
......@@ -643,7 +642,6 @@ test "reified function type params initialized with field pointer" {
643642 const Bar = @Type(.{
644643 .Fn = .{
645644 .calling_convention = .Unspecified,
646 .alignment = 0,
647645 .is_generic = false,
648646 .is_var_args = false,
649647 .return_type = void,
test/behavior/type_info.zig+32-10
......@@ -356,16 +356,38 @@ test "type info: function type info" {
356356}
357357
358358fn testFunction() !void {
359 const fn_info = @typeInfo(@TypeOf(typeInfoFoo));
360 try expect(fn_info == .Fn);
361 try expect(fn_info.Fn.alignment > 0);
362 try expect(fn_info.Fn.calling_convention == .C);
363 try expect(!fn_info.Fn.is_generic);
364 try expect(fn_info.Fn.params.len == 2);
365 try expect(fn_info.Fn.is_var_args);
366 try expect(fn_info.Fn.return_type.? == usize);
367 const fn_aligned_info = @typeInfo(@TypeOf(typeInfoFooAligned));
368 try expect(fn_aligned_info.Fn.alignment == 4);
359 const foo_fn_type = @TypeOf(typeInfoFoo);
360 const foo_fn_info = @typeInfo(foo_fn_type);
361 try expect(foo_fn_info.Fn.calling_convention == .C);
362 try expect(!foo_fn_info.Fn.is_generic);
363 try expect(foo_fn_info.Fn.params.len == 2);
364 try expect(foo_fn_info.Fn.is_var_args);
365 try expect(foo_fn_info.Fn.return_type.? == usize);
366 const foo_ptr_fn_info = @typeInfo(@TypeOf(&typeInfoFoo));
367 try expect(foo_ptr_fn_info.Pointer.size == .One);
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);
369391}
370392
371393extern fn typeInfoFoo(a: usize, b: bool, ...) callconv(.C) usize;
test/behavior/typename.zig+2-4
......@@ -78,11 +78,9 @@ test "basic" {
7878 try expectEqualStrings("fn (comptime u32) void", @typeName(fn (comptime u32) void));
7979 try expectEqualStrings("fn (noalias []u8) void", @typeName(fn (noalias []u8) void));
8080
81 try expectEqualStrings("fn () align(32) void", @typeName(fn () align(32) void));
8281 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));
84 try expectEqualStrings("fn (...) align(32) callconv(.C) void", @typeName(fn (...) align(32) callconv(.C) void));
85 try expectEqualStrings("fn (u32, ...) align(32) callconv(.C) void", @typeName(fn (u32, ...) align(32) callconv(.C) void));
82 try expectEqualStrings("fn (...) callconv(.C) void", @typeName(fn (...) callconv(.C) void));
83 try expectEqualStrings("fn (u32, ...) callconv(.C) void", @typeName(fn (u32, ...) callconv(.C) void));
8684}
8785
8886test "top level decl" {
test/cases/compile_errors/function_ptr_alignment.zig+8-20
......@@ -1,28 +1,16 @@
1comptime {
2 var a: *align(2) @TypeOf(foo) = undefined;
3 _ = &a;
4}
5fn foo() void {}
1fn align1() align(1) void {}
2fn align2() align(2) void {}
63
74comptime {
8 var a: *align(1) fn () void = undefined;
9 _ = &a;
10}
11comptime {
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;
5 _ = @as(*align(1) const fn () void, &align2);
6 _ = @as(*align(1) const fn () void, &align1);
7 _ = @as(*align(2) const fn () void, &align2);
8 _ = @as(*align(2) const fn () void, &align1);
229}
2310
2411// error
2512// backend=stage2
2613// target=native
2714//
28// :20:19: error: function pointer alignment disagrees with function alignment
15// :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 @@
11export fn entry() void {
22 testImplicitlyDecreaseFnAlign(alignedSmall, 1234);
33}
4fn testImplicitlyDecreaseFnAlign(ptr: *const fn () align(8) i32, answer: i32) void {
4fn testImplicitlyDecreaseFnAlign(ptr: *align(8) const fn () i32, answer: i32) void {
55 if (ptr() != answer) unreachable;
66}
77fn alignedSmall() align(4) i32 {
......@@ -12,5 +12,5 @@ fn alignedSmall() align(4) i32 {
1212// backend=stage2
1313// target=x86_64-linux
1414//
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'
1616// :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 @@
11const Foo = @Type(.{
22 .Fn = .{
33 .calling_convention = .Unspecified,
4 .alignment = 0,
54 .is_generic = true,
65 .is_var_args = false,
76 .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 @@
11const Foo = @Type(.{
22 .Fn = .{
33 .calling_convention = .Unspecified,
4 .alignment = 0,
54 .is_generic = false,
65 .is_var_args = true,
76 .return_type = u0,
test/cases/compile_errors/reify_type.Fn_with_return_type_null.zig-1
......@@ -1,7 +1,6 @@
11const Foo = @Type(.{
22 .Fn = .{
33 .calling_convention = .Unspecified,
4 .alignment = 0,
54 .is_generic = false,
65 .is_var_args = false,
76 .return_type = null,