mirror of
https://github.com/ziglang/zig.git
synced 2026-02-13 04:48:20 +00:00
Merge pull request #19323 from jacobly0/rm-fn-type-align
AstGen: disallow alignment on function types
This commit is contained in:
commit
d981549d65
@ -2780,10 +2780,16 @@ fn noop4() align(4) void {}
|
||||
|
||||
test "function alignment" {
|
||||
try expect(derp() == 1234);
|
||||
try expect(@TypeOf(noop1) == fn () align(1) void);
|
||||
try expect(@TypeOf(noop4) == fn () align(4) void);
|
||||
try expect(@TypeOf(derp) == fn () i32);
|
||||
try expect(@TypeOf(&derp) == *align(@sizeOf(usize) * 2) const fn () i32);
|
||||
|
||||
noop1();
|
||||
try expect(@TypeOf(noop1) == fn () void);
|
||||
try expect(@TypeOf(&noop1) == *align(1) const fn () void);
|
||||
|
||||
noop4();
|
||||
try expect(@TypeOf(noop4) == fn () void);
|
||||
try expect(@TypeOf(&noop4) == *align(4) const fn () void);
|
||||
}
|
||||
{#code_end#}
|
||||
<p>
|
||||
|
||||
@ -420,7 +420,6 @@ pub const Type = union(enum) {
|
||||
/// therefore must be kept in sync with the compiler implementation.
|
||||
pub const Fn = struct {
|
||||
calling_convention: CallingConvention,
|
||||
alignment: comptime_int,
|
||||
is_generic: bool,
|
||||
is_var_args: bool,
|
||||
/// TODO change the language spec to make this not optional.
|
||||
|
||||
@ -1053,10 +1053,10 @@ pub const sigset_t = u32;
|
||||
pub const empty_sigset: sigset_t = 0;
|
||||
|
||||
pub const SIG = struct {
|
||||
pub const ERR = @as(?Sigaction.handler_fn, @ptrFromInt(maxInt(usize)));
|
||||
pub const DFL = @as(?Sigaction.handler_fn, @ptrFromInt(0));
|
||||
pub const IGN = @as(?Sigaction.handler_fn, @ptrFromInt(1));
|
||||
pub const HOLD = @as(?Sigaction.handler_fn, @ptrFromInt(5));
|
||||
pub const ERR: ?Sigaction.handler_fn = @ptrFromInt(maxInt(usize));
|
||||
pub const DFL: ?Sigaction.handler_fn = @ptrFromInt(0);
|
||||
pub const IGN: ?Sigaction.handler_fn = @ptrFromInt(1);
|
||||
pub const HOLD: ?Sigaction.handler_fn = @ptrFromInt(5);
|
||||
|
||||
/// block specified signal set
|
||||
pub const BLOCK = 1;
|
||||
@ -1150,7 +1150,7 @@ pub const siginfo_t = extern struct {
|
||||
|
||||
/// Renamed from `sigaction` to `Sigaction` to avoid conflict with function name.
|
||||
pub const Sigaction = extern struct {
|
||||
pub const handler_fn = *const fn (c_int) align(1) callconv(.C) void;
|
||||
pub const handler_fn = *align(1) const fn (c_int) callconv(.C) void;
|
||||
pub const sigaction_fn = *const fn (c_int, *const siginfo_t, ?*const anyopaque) callconv(.C) void;
|
||||
|
||||
handler: extern union {
|
||||
|
||||
@ -616,9 +616,9 @@ pub const S = struct {
|
||||
pub const BADSIG = SIG.ERR;
|
||||
|
||||
pub const SIG = struct {
|
||||
pub const DFL = @as(?Sigaction.handler_fn, @ptrFromInt(0));
|
||||
pub const IGN = @as(?Sigaction.handler_fn, @ptrFromInt(1));
|
||||
pub const ERR = @as(?Sigaction.handler_fn, @ptrFromInt(maxInt(usize)));
|
||||
pub const DFL: ?Sigaction.handler_fn = @ptrFromInt(0);
|
||||
pub const IGN: ?Sigaction.handler_fn = @ptrFromInt(1);
|
||||
pub const ERR: ?Sigaction.handler_fn = @ptrFromInt(maxInt(usize));
|
||||
|
||||
pub const BLOCK = 1;
|
||||
pub const UNBLOCK = 2;
|
||||
@ -690,7 +690,7 @@ pub const empty_sigset = sigset_t{ .__bits = [_]c_uint{0} ** _SIG_WORDS };
|
||||
pub const sig_atomic_t = c_int;
|
||||
|
||||
pub const Sigaction = extern struct {
|
||||
pub const handler_fn = *const fn (c_int) align(1) callconv(.C) void;
|
||||
pub const handler_fn = *align(1) const fn (c_int) callconv(.C) void;
|
||||
pub const sigaction_fn = *const fn (c_int, *const siginfo_t, ?*const anyopaque) callconv(.C) void;
|
||||
|
||||
/// signal handler
|
||||
|
||||
@ -695,9 +695,9 @@ pub const SIG = struct {
|
||||
pub const UNBLOCK = 2;
|
||||
pub const SETMASK = 3;
|
||||
|
||||
pub const DFL = @as(?Sigaction.handler_fn, @ptrFromInt(0));
|
||||
pub const IGN = @as(?Sigaction.handler_fn, @ptrFromInt(1));
|
||||
pub const ERR = @as(?Sigaction.handler_fn, @ptrFromInt(maxInt(usize)));
|
||||
pub const DFL: ?Sigaction.handler_fn = @ptrFromInt(0);
|
||||
pub const IGN: ?Sigaction.handler_fn = @ptrFromInt(1);
|
||||
pub const ERR: ?Sigaction.handler_fn = @ptrFromInt(maxInt(usize));
|
||||
|
||||
pub const WORDS = 4;
|
||||
pub const MAXSIG = 128;
|
||||
@ -1171,7 +1171,7 @@ const NSIG = 32;
|
||||
|
||||
/// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall.
|
||||
pub const Sigaction = extern struct {
|
||||
pub const handler_fn = *const fn (c_int) align(1) callconv(.C) void;
|
||||
pub const handler_fn = *align(1) const fn (c_int) callconv(.C) void;
|
||||
pub const sigaction_fn = *const fn (c_int, *const siginfo_t, ?*const anyopaque) callconv(.C) void;
|
||||
|
||||
/// signal handler
|
||||
|
||||
@ -441,9 +441,9 @@ pub const SA = struct {
|
||||
};
|
||||
|
||||
pub const SIG = struct {
|
||||
pub const ERR = @as(?Sigaction.handler_fn, @ptrFromInt(maxInt(usize)));
|
||||
pub const DFL = @as(?Sigaction.handler_fn, @ptrFromInt(0));
|
||||
pub const IGN = @as(?Sigaction.handler_fn, @ptrFromInt(1));
|
||||
pub const ERR: ?Sigaction.handler_fn = @ptrFromInt(maxInt(usize));
|
||||
pub const DFL: ?Sigaction.handler_fn = @ptrFromInt(0);
|
||||
pub const IGN: ?Sigaction.handler_fn = @ptrFromInt(1);
|
||||
|
||||
pub const HUP = 1;
|
||||
pub const INT = 2;
|
||||
@ -690,7 +690,7 @@ const NSIG = 32;
|
||||
|
||||
/// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall.
|
||||
pub const Sigaction = extern struct {
|
||||
pub const handler_fn = *const fn (i32) align(1) callconv(.C) void;
|
||||
pub const handler_fn = *align(1) const fn (i32) callconv(.C) void;
|
||||
|
||||
/// signal handler
|
||||
__sigaction_u: extern union {
|
||||
|
||||
@ -800,9 +800,9 @@ pub const winsize = extern struct {
|
||||
const NSIG = 32;
|
||||
|
||||
pub const SIG = struct {
|
||||
pub const DFL = @as(?Sigaction.handler_fn, @ptrFromInt(0));
|
||||
pub const IGN = @as(?Sigaction.handler_fn, @ptrFromInt(1));
|
||||
pub const ERR = @as(?Sigaction.handler_fn, @ptrFromInt(maxInt(usize)));
|
||||
pub const DFL: ?Sigaction.handler_fn = @ptrFromInt(0);
|
||||
pub const IGN: ?Sigaction.handler_fn = @ptrFromInt(1);
|
||||
pub const ERR: ?Sigaction.handler_fn = @ptrFromInt(maxInt(usize));
|
||||
|
||||
pub const WORDS = 4;
|
||||
pub const MAXSIG = 128;
|
||||
@ -864,7 +864,7 @@ pub const SIG = struct {
|
||||
|
||||
/// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall.
|
||||
pub const Sigaction = extern struct {
|
||||
pub const handler_fn = *const fn (c_int) align(1) callconv(.C) void;
|
||||
pub const handler_fn = *align(1) const fn (c_int) callconv(.C) void;
|
||||
pub const sigaction_fn = *const fn (c_int, *const siginfo_t, ?*const anyopaque) callconv(.C) void;
|
||||
|
||||
/// signal handler
|
||||
|
||||
@ -795,11 +795,11 @@ pub const winsize = extern struct {
|
||||
const NSIG = 33;
|
||||
|
||||
pub const SIG = struct {
|
||||
pub const DFL = @as(?Sigaction.handler_fn, @ptrFromInt(0));
|
||||
pub const IGN = @as(?Sigaction.handler_fn, @ptrFromInt(1));
|
||||
pub const ERR = @as(?Sigaction.handler_fn, @ptrFromInt(maxInt(usize)));
|
||||
pub const CATCH = @as(?Sigaction.handler_fn, @ptrFromInt(2));
|
||||
pub const HOLD = @as(?Sigaction.handler_fn, @ptrFromInt(3));
|
||||
pub const DFL: ?Sigaction.handler_fn = @ptrFromInt(0);
|
||||
pub const IGN: ?Sigaction.handler_fn = @ptrFromInt(1);
|
||||
pub const ERR: ?Sigaction.handler_fn = @ptrFromInt(maxInt(usize));
|
||||
pub const CATCH: ?Sigaction.handler_fn = @ptrFromInt(2);
|
||||
pub const HOLD: ?Sigaction.handler_fn = @ptrFromInt(3);
|
||||
|
||||
pub const HUP = 1;
|
||||
pub const INT = 2;
|
||||
@ -842,7 +842,7 @@ pub const SIG = struct {
|
||||
|
||||
/// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall.
|
||||
pub const Sigaction = extern struct {
|
||||
pub const handler_fn = *const fn (c_int) align(1) callconv(.C) void;
|
||||
pub const handler_fn = *align(1) const fn (c_int) callconv(.C) void;
|
||||
pub const sigaction_fn = *const fn (c_int, *const siginfo_t, ?*const anyopaque) callconv(.C) void;
|
||||
|
||||
/// signal handler
|
||||
|
||||
@ -798,10 +798,10 @@ pub const winsize = extern struct {
|
||||
const NSIG = 75;
|
||||
|
||||
pub const SIG = struct {
|
||||
pub const DFL = @as(?Sigaction.handler_fn, @ptrFromInt(0));
|
||||
pub const ERR = @as(?Sigaction.handler_fn, @ptrFromInt(maxInt(usize)));
|
||||
pub const IGN = @as(?Sigaction.handler_fn, @ptrFromInt(1));
|
||||
pub const HOLD = @as(?Sigaction.handler_fn, @ptrFromInt(2));
|
||||
pub const DFL: ?Sigaction.handler_fn = @ptrFromInt(0);
|
||||
pub const ERR: ?Sigaction.handler_fn = @ptrFromInt(maxInt(usize));
|
||||
pub const IGN: ?Sigaction.handler_fn = @ptrFromInt(1);
|
||||
pub const HOLD: ?Sigaction.handler_fn = @ptrFromInt(2);
|
||||
|
||||
pub const WORDS = 4;
|
||||
pub const MAXSIG = 75;
|
||||
@ -874,7 +874,7 @@ pub const SIG = struct {
|
||||
|
||||
/// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall.
|
||||
pub const Sigaction = extern struct {
|
||||
pub const handler_fn = *const fn (c_int) align(1) callconv(.C) void;
|
||||
pub const handler_fn = *align(1) const fn (c_int) callconv(.C) void;
|
||||
pub const sigaction_fn = *const fn (c_int, *const siginfo_t, ?*const anyopaque) callconv(.C) void;
|
||||
|
||||
/// signal options
|
||||
|
||||
@ -57,10 +57,9 @@ test stringToEnum {
|
||||
}
|
||||
|
||||
/// Returns the alignment of type T.
|
||||
/// Note that if T is a pointer or function type the result is different than
|
||||
/// the one returned by @alignOf(T).
|
||||
/// Note that if T is a pointer type the result is different than the one
|
||||
/// returned by @alignOf(T).
|
||||
/// If T is a pointer type the alignment of the type it points to is returned.
|
||||
/// If T is a function type the alignment a target-dependent value is returned.
|
||||
pub fn alignment(comptime T: type) comptime_int {
|
||||
return switch (@typeInfo(T)) {
|
||||
.Optional => |info| switch (@typeInfo(info.child)) {
|
||||
@ -68,7 +67,6 @@ pub fn alignment(comptime T: type) comptime_int {
|
||||
else => @alignOf(T),
|
||||
},
|
||||
.Pointer => |info| info.alignment,
|
||||
.Fn => |info| info.alignment,
|
||||
else => @alignOf(T),
|
||||
};
|
||||
}
|
||||
@ -80,7 +78,8 @@ test alignment {
|
||||
try testing.expect(alignment([]align(1) u8) == 1);
|
||||
try testing.expect(alignment([]align(2) u8) == 2);
|
||||
try testing.expect(alignment(fn () void) > 0);
|
||||
try testing.expect(alignment(fn () align(128) void) == 128);
|
||||
try testing.expect(alignment(*const fn () void) > 0);
|
||||
try testing.expect(alignment(*align(128) const fn () void) == 128);
|
||||
}
|
||||
|
||||
/// Given a parameterized type (array, vector, pointer, optional), returns the "child type".
|
||||
|
||||
@ -689,13 +689,13 @@ pub const SIG = struct {
|
||||
pub const SYS = 31;
|
||||
pub const UNUSED = SIG.SYS;
|
||||
|
||||
pub const ERR = @as(?Sigaction.handler_fn, @ptrFromInt(std.math.maxInt(usize)));
|
||||
pub const DFL = @as(?Sigaction.handler_fn, @ptrFromInt(0));
|
||||
pub const IGN = @as(?Sigaction.handler_fn, @ptrFromInt(1));
|
||||
pub const ERR: ?Sigaction.handler_fn = @ptrFromInt(std.math.maxInt(usize));
|
||||
pub const DFL: ?Sigaction.handler_fn = @ptrFromInt(0);
|
||||
pub const IGN: ?Sigaction.handler_fn = @ptrFromInt(1);
|
||||
};
|
||||
|
||||
pub const Sigaction = extern struct {
|
||||
pub const handler_fn = *const fn (c_int) align(1) callconv(.C) void;
|
||||
pub const handler_fn = *align(1) const fn (c_int) callconv(.C) void;
|
||||
pub const sigaction_fn = *const fn (c_int, *const siginfo_t, ?*const anyopaque) callconv(.C) void;
|
||||
|
||||
handler: extern union {
|
||||
|
||||
@ -1327,16 +1327,14 @@ pub fn flock(fd: fd_t, operation: i32) usize {
|
||||
return syscall2(.flock, @as(usize, @bitCast(@as(isize, fd))), @as(usize, @bitCast(@as(isize, operation))));
|
||||
}
|
||||
|
||||
var vdso_clock_gettime = @as(?*const anyopaque, @ptrCast(&init_vdso_clock_gettime));
|
||||
|
||||
// We must follow the C calling convention when we call into the VDSO
|
||||
const vdso_clock_gettime_ty = *align(1) const fn (i32, *timespec) callconv(.C) usize;
|
||||
const VdsoClockGettime = *align(1) const fn (i32, *timespec) callconv(.C) usize;
|
||||
var vdso_clock_gettime: ?VdsoClockGettime = &init_vdso_clock_gettime;
|
||||
|
||||
pub fn clock_gettime(clk_id: i32, tp: *timespec) usize {
|
||||
if (@hasDecl(VDSO, "CGT_SYM")) {
|
||||
const ptr = @atomicLoad(?*const anyopaque, &vdso_clock_gettime, .unordered);
|
||||
if (ptr) |fn_ptr| {
|
||||
const f = @as(vdso_clock_gettime_ty, @ptrCast(fn_ptr));
|
||||
const ptr = @atomicLoad(?VdsoClockGettime, &vdso_clock_gettime, .unordered);
|
||||
if (ptr) |f| {
|
||||
const rc = f(clk_id, tp);
|
||||
switch (rc) {
|
||||
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 {
|
||||
}
|
||||
|
||||
fn init_vdso_clock_gettime(clk: i32, ts: *timespec) callconv(.C) usize {
|
||||
const ptr = @as(?*const anyopaque, @ptrFromInt(vdso.lookup(VDSO.CGT_VER, VDSO.CGT_SYM)));
|
||||
const ptr: ?VdsoClockGettime = @ptrFromInt(vdso.lookup(VDSO.CGT_VER, VDSO.CGT_SYM));
|
||||
// Note that we may not have a VDSO at all, update the stub address anyway
|
||||
// so that clock_gettime will fall back on the good old (and slow) syscall
|
||||
@atomicStore(?*const anyopaque, &vdso_clock_gettime, ptr, .monotonic);
|
||||
@atomicStore(?VdsoClockGettime, &vdso_clock_gettime, ptr, .monotonic);
|
||||
// Call into the VDSO if available
|
||||
if (ptr) |fn_ptr| {
|
||||
const f = @as(vdso_clock_gettime_ty, @ptrCast(fn_ptr));
|
||||
return f(clk, ts);
|
||||
}
|
||||
if (ptr) |f| return f(clk, ts);
|
||||
return @as(usize, @bitCast(-@as(isize, @intFromEnum(E.NOSYS))));
|
||||
}
|
||||
|
||||
@ -2516,9 +2511,9 @@ pub const SIG = if (is_mips) struct {
|
||||
pub const SYS = 31;
|
||||
pub const UNUSED = SIG.SYS;
|
||||
|
||||
pub const ERR = @as(?Sigaction.handler_fn, @ptrFromInt(maxInt(usize)));
|
||||
pub const DFL = @as(?Sigaction.handler_fn, @ptrFromInt(0));
|
||||
pub const IGN = @as(?Sigaction.handler_fn, @ptrFromInt(1));
|
||||
pub const ERR: ?Sigaction.handler_fn = @ptrFromInt(maxInt(usize));
|
||||
pub const DFL: ?Sigaction.handler_fn = @ptrFromInt(0);
|
||||
pub const IGN: ?Sigaction.handler_fn = @ptrFromInt(1);
|
||||
} else if (is_sparc) struct {
|
||||
pub const BLOCK = 1;
|
||||
pub const UNBLOCK = 2;
|
||||
@ -2560,9 +2555,9 @@ pub const SIG = if (is_mips) struct {
|
||||
pub const PWR = LOST;
|
||||
pub const IO = SIG.POLL;
|
||||
|
||||
pub const ERR = @as(?Sigaction.handler_fn, @ptrFromInt(maxInt(usize)));
|
||||
pub const DFL = @as(?Sigaction.handler_fn, @ptrFromInt(0));
|
||||
pub const IGN = @as(?Sigaction.handler_fn, @ptrFromInt(1));
|
||||
pub const ERR: ?Sigaction.handler_fn = @ptrFromInt(maxInt(usize));
|
||||
pub const DFL: ?Sigaction.handler_fn = @ptrFromInt(0);
|
||||
pub const IGN: ?Sigaction.handler_fn = @ptrFromInt(1);
|
||||
} else struct {
|
||||
pub const BLOCK = 0;
|
||||
pub const UNBLOCK = 1;
|
||||
@ -2603,9 +2598,9 @@ pub const SIG = if (is_mips) struct {
|
||||
pub const SYS = 31;
|
||||
pub const UNUSED = SIG.SYS;
|
||||
|
||||
pub const ERR = @as(?Sigaction.handler_fn, @ptrFromInt(maxInt(usize)));
|
||||
pub const DFL = @as(?Sigaction.handler_fn, @ptrFromInt(0));
|
||||
pub const IGN = @as(?Sigaction.handler_fn, @ptrFromInt(1));
|
||||
pub const ERR: ?Sigaction.handler_fn = @ptrFromInt(maxInt(usize));
|
||||
pub const DFL: ?Sigaction.handler_fn = @ptrFromInt(0);
|
||||
pub const IGN: ?Sigaction.handler_fn = @ptrFromInt(1);
|
||||
};
|
||||
|
||||
pub const kernel_rwf = u32;
|
||||
@ -3709,7 +3704,7 @@ pub const all_mask: sigset_t = [_]u32{0xffffffff} ** @typeInfo(sigset_t).Array.l
|
||||
pub const app_mask: sigset_t = [2]u32{ 0xfffffffc, 0x7fffffff } ++ [_]u32{0xffffffff} ** 30;
|
||||
|
||||
const k_sigaction_funcs = struct {
|
||||
const handler = ?*const fn (c_int) align(1) callconv(.C) void;
|
||||
const handler = ?*align(1) const fn (c_int) callconv(.C) void;
|
||||
const restorer = *const fn () callconv(.C) void;
|
||||
};
|
||||
|
||||
@ -3736,7 +3731,7 @@ pub const k_sigaction = switch (native_arch) {
|
||||
|
||||
/// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall.
|
||||
pub const Sigaction = extern struct {
|
||||
pub const handler_fn = *const fn (c_int) align(1) callconv(.C) void;
|
||||
pub const handler_fn = *align(1) const fn (c_int) callconv(.C) void;
|
||||
pub const sigaction_fn = *const fn (c_int, *const siginfo_t, ?*const anyopaque) callconv(.C) void;
|
||||
|
||||
handler: extern union {
|
||||
|
||||
@ -1369,16 +1369,16 @@ fn fnProtoExpr(
|
||||
break :is_var_args false;
|
||||
};
|
||||
|
||||
const align_ref: Zir.Inst.Ref = if (fn_proto.ast.align_expr == 0) .none else inst: {
|
||||
break :inst try expr(&block_scope, scope, coerced_align_ri, fn_proto.ast.align_expr);
|
||||
};
|
||||
if (fn_proto.ast.align_expr != 0) {
|
||||
return astgen.failNode(fn_proto.ast.align_expr, "function type cannot have an alignment", .{});
|
||||
}
|
||||
|
||||
if (fn_proto.ast.addrspace_expr != 0) {
|
||||
return astgen.failNode(fn_proto.ast.addrspace_expr, "addrspace not allowed on function prototypes", .{});
|
||||
return astgen.failNode(fn_proto.ast.addrspace_expr, "function type cannot have an addrspace", .{});
|
||||
}
|
||||
|
||||
if (fn_proto.ast.section_expr != 0) {
|
||||
return astgen.failNode(fn_proto.ast.section_expr, "linksection not allowed on function prototypes", .{});
|
||||
return astgen.failNode(fn_proto.ast.section_expr, "function type cannot have a linksection", .{});
|
||||
}
|
||||
|
||||
const cc: Zir.Inst.Ref = if (fn_proto.ast.callconv_expr != 0)
|
||||
@ -1394,7 +1394,7 @@ fn fnProtoExpr(
|
||||
const maybe_bang = tree.firstToken(fn_proto.ast.return_type) - 1;
|
||||
const is_inferred_error = token_tags[maybe_bang] == .bang;
|
||||
if (is_inferred_error) {
|
||||
return astgen.failTok(maybe_bang, "function prototype may not have inferred error set", .{});
|
||||
return astgen.failTok(maybe_bang, "function type cannot have an inferred error set", .{});
|
||||
}
|
||||
const ret_ty = try expr(&block_scope, scope, coerced_type_ri, fn_proto.ast.return_type);
|
||||
|
||||
@ -1403,7 +1403,7 @@ fn fnProtoExpr(
|
||||
|
||||
.cc_ref = cc,
|
||||
.cc_gz = null,
|
||||
.align_ref = align_ref,
|
||||
.align_ref = .none,
|
||||
.align_gz = null,
|
||||
.ret_ref = ret_ty,
|
||||
.ret_gz = null,
|
||||
|
||||
@ -765,16 +765,10 @@ pub const Key = union(enum) {
|
||||
/// Tells whether a parameter is noalias. See `paramIsNoalias` helper
|
||||
/// method for accessing this.
|
||||
noalias_bits: u32,
|
||||
/// `none` indicates the function has the default alignment for
|
||||
/// function code on the target. In this case, this field *must* be set
|
||||
/// to `none`, otherwise the `InternPool` equality and hashing
|
||||
/// functions will return incorrect results.
|
||||
alignment: Alignment,
|
||||
cc: std.builtin.CallingConvention,
|
||||
is_var_args: bool,
|
||||
is_generic: bool,
|
||||
is_noinline: bool,
|
||||
align_is_generic: bool,
|
||||
cc_is_generic: bool,
|
||||
section_is_generic: bool,
|
||||
addrspace_is_generic: bool,
|
||||
@ -794,7 +788,6 @@ pub const Key = union(enum) {
|
||||
a.return_type == b.return_type and
|
||||
a.comptime_bits == b.comptime_bits and
|
||||
a.noalias_bits == b.noalias_bits and
|
||||
a.alignment == b.alignment and
|
||||
a.cc == b.cc and
|
||||
a.is_var_args == b.is_var_args and
|
||||
a.is_generic == b.is_generic and
|
||||
@ -808,7 +801,6 @@ pub const Key = union(enum) {
|
||||
std.hash.autoHash(hasher, self.return_type);
|
||||
std.hash.autoHash(hasher, self.comptime_bits);
|
||||
std.hash.autoHash(hasher, self.noalias_bits);
|
||||
std.hash.autoHash(hasher, self.alignment);
|
||||
std.hash.autoHash(hasher, self.cc);
|
||||
std.hash.autoHash(hasher, self.is_var_args);
|
||||
std.hash.autoHash(hasher, self.is_generic);
|
||||
@ -3587,18 +3579,16 @@ pub const Tag = enum(u8) {
|
||||
flags: Flags,
|
||||
|
||||
pub const Flags = packed struct(u32) {
|
||||
alignment: Alignment,
|
||||
cc: std.builtin.CallingConvention,
|
||||
is_var_args: bool,
|
||||
is_generic: bool,
|
||||
has_comptime_bits: bool,
|
||||
has_noalias_bits: bool,
|
||||
is_noinline: bool,
|
||||
align_is_generic: bool,
|
||||
cc_is_generic: bool,
|
||||
section_is_generic: bool,
|
||||
addrspace_is_generic: bool,
|
||||
_: u9 = 0,
|
||||
_: u16 = 0,
|
||||
};
|
||||
};
|
||||
|
||||
@ -4918,11 +4908,9 @@ fn extraFuncType(ip: *const InternPool, extra_index: u32) Key.FuncType {
|
||||
.return_type = type_function.data.return_type,
|
||||
.comptime_bits = comptime_bits,
|
||||
.noalias_bits = noalias_bits,
|
||||
.alignment = type_function.data.flags.alignment,
|
||||
.cc = type_function.data.flags.cc,
|
||||
.is_var_args = type_function.data.flags.is_var_args,
|
||||
.is_noinline = type_function.data.flags.is_noinline,
|
||||
.align_is_generic = type_function.data.flags.align_is_generic,
|
||||
.cc_is_generic = type_function.data.flags.cc_is_generic,
|
||||
.section_is_generic = type_function.data.flags.section_is_generic,
|
||||
.addrspace_is_generic = type_function.data.flags.addrspace_is_generic,
|
||||
@ -6211,8 +6199,6 @@ pub const GetFuncTypeKey = struct {
|
||||
comptime_bits: u32 = 0,
|
||||
noalias_bits: u32 = 0,
|
||||
/// `null` means generic.
|
||||
alignment: ?Alignment = .none,
|
||||
/// `null` means generic.
|
||||
cc: ?std.builtin.CallingConvention = .Unspecified,
|
||||
is_var_args: bool = false,
|
||||
is_generic: bool = false,
|
||||
@ -6242,14 +6228,12 @@ pub fn getFuncType(ip: *InternPool, gpa: Allocator, key: GetFuncTypeKey) Allocat
|
||||
.params_len = params_len,
|
||||
.return_type = key.return_type,
|
||||
.flags = .{
|
||||
.alignment = key.alignment orelse .none,
|
||||
.cc = key.cc orelse .Unspecified,
|
||||
.is_var_args = key.is_var_args,
|
||||
.has_comptime_bits = key.comptime_bits != 0,
|
||||
.has_noalias_bits = key.noalias_bits != 0,
|
||||
.is_generic = key.is_generic,
|
||||
.is_noinline = key.is_noinline,
|
||||
.align_is_generic = key.alignment == null,
|
||||
.cc_is_generic = key.cc == null,
|
||||
.section_is_generic = key.section_is_generic,
|
||||
.addrspace_is_generic = key.addrspace_is_generic,
|
||||
@ -6433,14 +6417,12 @@ pub fn getFuncDeclIes(ip: *InternPool, gpa: Allocator, key: GetFuncDeclIesKey) A
|
||||
.params_len = params_len,
|
||||
.return_type = @enumFromInt(ip.items.len - 2),
|
||||
.flags = .{
|
||||
.alignment = key.alignment orelse .none,
|
||||
.cc = key.cc orelse .Unspecified,
|
||||
.is_var_args = key.is_var_args,
|
||||
.has_comptime_bits = key.comptime_bits != 0,
|
||||
.has_noalias_bits = key.noalias_bits != 0,
|
||||
.is_generic = key.is_generic,
|
||||
.is_noinline = key.is_noinline,
|
||||
.align_is_generic = key.alignment == null,
|
||||
.cc_is_generic = key.cc == null,
|
||||
.section_is_generic = key.section_is_generic,
|
||||
.addrspace_is_generic = key.addrspace_is_generic,
|
||||
@ -6553,7 +6535,6 @@ pub fn getFuncInstance(ip: *InternPool, gpa: Allocator, arg: GetFuncInstanceKey)
|
||||
.param_types = arg.param_types,
|
||||
.return_type = arg.bare_return_type,
|
||||
.noalias_bits = arg.noalias_bits,
|
||||
.alignment = arg.alignment,
|
||||
.cc = arg.cc,
|
||||
.is_noinline = arg.is_noinline,
|
||||
});
|
||||
@ -6610,6 +6591,7 @@ pub fn getFuncInstance(ip: *InternPool, gpa: Allocator, arg: GetFuncInstanceKey)
|
||||
func_index,
|
||||
func_extra_index,
|
||||
func_ty,
|
||||
arg.alignment,
|
||||
arg.section,
|
||||
);
|
||||
}
|
||||
@ -6673,14 +6655,12 @@ pub fn getFuncInstanceIes(
|
||||
.params_len = params_len,
|
||||
.return_type = error_union_type,
|
||||
.flags = .{
|
||||
.alignment = arg.alignment,
|
||||
.cc = arg.cc,
|
||||
.is_var_args = false,
|
||||
.has_comptime_bits = false,
|
||||
.has_noalias_bits = arg.noalias_bits != 0,
|
||||
.is_generic = false,
|
||||
.is_noinline = arg.is_noinline,
|
||||
.align_is_generic = false,
|
||||
.cc_is_generic = false,
|
||||
.section_is_generic = false,
|
||||
.addrspace_is_generic = false,
|
||||
@ -6741,6 +6721,7 @@ pub fn getFuncInstanceIes(
|
||||
func_index,
|
||||
func_extra_index,
|
||||
func_ty,
|
||||
arg.alignment,
|
||||
arg.section,
|
||||
);
|
||||
}
|
||||
@ -6752,6 +6733,7 @@ fn finishFuncInstance(
|
||||
func_index: Index,
|
||||
func_extra_index: u32,
|
||||
func_ty: Index,
|
||||
alignment: Alignment,
|
||||
section: OptionalNullTerminatedString,
|
||||
) Allocator.Error!Index {
|
||||
const fn_owner_decl = ip.declPtr(ip.funcDeclOwner(generic_owner));
|
||||
@ -6764,7 +6746,7 @@ fn finishFuncInstance(
|
||||
.owns_tv = true,
|
||||
.ty = @import("type.zig").Type.fromInterned(func_ty),
|
||||
.val = @import("Value.zig").fromInterned(func_index),
|
||||
.alignment = .none,
|
||||
.alignment = alignment,
|
||||
.@"linksection" = section,
|
||||
.@"addrspace" = fn_owner_decl.@"addrspace",
|
||||
.analysis = .complete,
|
||||
|
||||
180
src/Module.zig
180
src/Module.zig
@ -3596,6 +3596,18 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult {
|
||||
|
||||
log.debug("semaDecl '{d}'", .{@intFromEnum(decl_index)});
|
||||
|
||||
const old_has_tv = decl.has_tv;
|
||||
// The following values are ignored if `!old_has_tv`
|
||||
const old_ty = decl.ty;
|
||||
const old_val = decl.val;
|
||||
const old_align = decl.alignment;
|
||||
const old_linksection = decl.@"linksection";
|
||||
const old_addrspace = decl.@"addrspace";
|
||||
const old_is_inline = if (decl.getOwnedFunction(mod)) |prev_func|
|
||||
prev_func.analysis(ip).state == .inline_only
|
||||
else
|
||||
false;
|
||||
|
||||
const decl_inst = decl.zir_decl_index.unwrap().?.resolve(ip);
|
||||
|
||||
const gpa = mod.gpa;
|
||||
@ -3733,141 +3745,96 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult {
|
||||
};
|
||||
}
|
||||
|
||||
switch (ip.indexToKey(decl_tv.val.toIntern())) {
|
||||
.func => |func| {
|
||||
const owns_tv = func.owner_decl == decl_index;
|
||||
if (owns_tv) {
|
||||
var prev_type_has_bits = false;
|
||||
var prev_is_inline = false;
|
||||
var type_changed = true;
|
||||
|
||||
if (decl.has_tv) {
|
||||
prev_type_has_bits = decl.ty.isFnOrHasRuntimeBits(mod);
|
||||
type_changed = !decl.ty.eql(decl_tv.ty, mod);
|
||||
if (decl.getOwnedFunction(mod)) |prev_func| {
|
||||
prev_is_inline = prev_func.analysis(ip).state == .inline_only;
|
||||
}
|
||||
}
|
||||
|
||||
decl.ty = decl_tv.ty;
|
||||
decl.val = Value.fromInterned((try decl_tv.val.intern(decl_tv.ty, mod)));
|
||||
// linksection, align, and addrspace were already set by Sema
|
||||
decl.has_tv = true;
|
||||
decl.owns_tv = owns_tv;
|
||||
decl.analysis = .complete;
|
||||
|
||||
const is_inline = decl.ty.fnCallingConvention(mod) == .Inline;
|
||||
if (decl.is_exported) {
|
||||
const export_src: LazySrcLoc = .{ .token_offset = @intFromBool(decl.is_pub) };
|
||||
if (is_inline) {
|
||||
return sema.fail(&block_scope, export_src, "export of inline function", .{});
|
||||
}
|
||||
// The scope needs to have the decl in it.
|
||||
try sema.analyzeExport(&block_scope, export_src, .{ .name = decl.name }, decl_index);
|
||||
}
|
||||
// TODO: align, linksection, addrspace?
|
||||
const changed = type_changed or is_inline != prev_is_inline;
|
||||
return .{
|
||||
.invalidate_decl_val = changed,
|
||||
.invalidate_decl_ref = changed,
|
||||
};
|
||||
}
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
|
||||
decl.owns_tv = false;
|
||||
var queue_linker_work = false;
|
||||
var is_extern = false;
|
||||
var queue_linker_work = true;
|
||||
var is_func = false;
|
||||
var is_inline = false;
|
||||
switch (decl_tv.val.toIntern()) {
|
||||
.generic_poison => unreachable,
|
||||
.unreachable_value => unreachable,
|
||||
else => switch (ip.indexToKey(decl_tv.val.toIntern())) {
|
||||
.variable => |variable| if (variable.decl == decl_index) {
|
||||
decl.owns_tv = true;
|
||||
queue_linker_work = true;
|
||||
.variable => |variable| {
|
||||
decl.owns_tv = variable.decl == decl_index;
|
||||
queue_linker_work = decl.owns_tv;
|
||||
},
|
||||
|
||||
.extern_func => |extern_fn| if (extern_fn.decl == decl_index) {
|
||||
decl.owns_tv = true;
|
||||
queue_linker_work = true;
|
||||
is_extern = true;
|
||||
.extern_func => |extern_func| {
|
||||
decl.owns_tv = extern_func.decl == decl_index;
|
||||
queue_linker_work = decl.owns_tv;
|
||||
is_func = decl.owns_tv;
|
||||
},
|
||||
|
||||
.func => {},
|
||||
|
||||
else => {
|
||||
queue_linker_work = true;
|
||||
.func => |func| {
|
||||
decl.owns_tv = func.owner_decl == decl_index;
|
||||
queue_linker_work = false;
|
||||
is_inline = decl.owns_tv and decl_tv.ty.fnCallingConvention(mod) == .Inline;
|
||||
is_func = decl.owns_tv;
|
||||
},
|
||||
|
||||
else => {},
|
||||
},
|
||||
}
|
||||
|
||||
const old_has_tv = decl.has_tv;
|
||||
// The following values are ignored if `!old_has_tv`
|
||||
const old_ty = decl.ty;
|
||||
const old_val = decl.val;
|
||||
const old_align = decl.alignment;
|
||||
const old_linksection = decl.@"linksection";
|
||||
const old_addrspace = decl.@"addrspace";
|
||||
|
||||
decl.ty = decl_tv.ty;
|
||||
decl.val = Value.fromInterned((try decl_tv.val.intern(decl_tv.ty, mod)));
|
||||
decl.alignment = blk: {
|
||||
const align_body = decl_bodies.align_body orelse break :blk .none;
|
||||
const align_ref = try sema.resolveInlineBody(&block_scope, align_body, decl_inst);
|
||||
break :blk try sema.analyzeAsAlign(&block_scope, align_src, align_ref);
|
||||
};
|
||||
decl.@"linksection" = blk: {
|
||||
const linksection_body = decl_bodies.linksection_body orelse break :blk .none;
|
||||
const linksection_ref = try sema.resolveInlineBody(&block_scope, linksection_body, decl_inst);
|
||||
const bytes = try sema.toConstString(&block_scope, section_src, linksection_ref, .{
|
||||
.needed_comptime_reason = "linksection must be comptime-known",
|
||||
});
|
||||
if (mem.indexOfScalar(u8, bytes, 0) != null) {
|
||||
return sema.fail(&block_scope, section_src, "linksection cannot contain null bytes", .{});
|
||||
} else if (bytes.len == 0) {
|
||||
return sema.fail(&block_scope, section_src, "linksection cannot be empty", .{});
|
||||
}
|
||||
const section = try ip.getOrPutString(gpa, bytes);
|
||||
break :blk section.toOptional();
|
||||
};
|
||||
decl.@"addrspace" = blk: {
|
||||
const addrspace_ctx: Sema.AddressSpaceContext = switch (ip.indexToKey(decl_tv.val.toIntern())) {
|
||||
.variable => .variable,
|
||||
.extern_func, .func => .function,
|
||||
else => .constant,
|
||||
// Function linksection, align, and addrspace were already set by Sema
|
||||
if (!is_func) {
|
||||
decl.alignment = blk: {
|
||||
const align_body = decl_bodies.align_body orelse break :blk .none;
|
||||
const align_ref = try sema.resolveInlineBody(&block_scope, align_body, decl_inst);
|
||||
break :blk try sema.analyzeAsAlign(&block_scope, align_src, align_ref);
|
||||
};
|
||||
|
||||
const target = sema.mod.getTarget();
|
||||
|
||||
const addrspace_body = decl_bodies.addrspace_body orelse break :blk switch (addrspace_ctx) {
|
||||
.function => target_util.defaultAddressSpace(target, .function),
|
||||
.variable => target_util.defaultAddressSpace(target, .global_mutable),
|
||||
.constant => target_util.defaultAddressSpace(target, .global_constant),
|
||||
else => unreachable,
|
||||
decl.@"linksection" = blk: {
|
||||
const linksection_body = decl_bodies.linksection_body orelse break :blk .none;
|
||||
const linksection_ref = try sema.resolveInlineBody(&block_scope, linksection_body, decl_inst);
|
||||
const bytes = try sema.toConstString(&block_scope, section_src, linksection_ref, .{
|
||||
.needed_comptime_reason = "linksection must be comptime-known",
|
||||
});
|
||||
if (mem.indexOfScalar(u8, bytes, 0) != null) {
|
||||
return sema.fail(&block_scope, section_src, "linksection cannot contain null bytes", .{});
|
||||
} else if (bytes.len == 0) {
|
||||
return sema.fail(&block_scope, section_src, "linksection cannot be empty", .{});
|
||||
}
|
||||
const section = try ip.getOrPutString(gpa, bytes);
|
||||
break :blk section.toOptional();
|
||||
};
|
||||
const addrspace_ref = try sema.resolveInlineBody(&block_scope, addrspace_body, decl_inst);
|
||||
break :blk try sema.analyzeAsAddressSpace(&block_scope, address_space_src, addrspace_ref, addrspace_ctx);
|
||||
};
|
||||
decl.@"addrspace" = blk: {
|
||||
const addrspace_ctx: Sema.AddressSpaceContext = switch (ip.indexToKey(decl_tv.val.toIntern())) {
|
||||
.variable => .variable,
|
||||
.extern_func, .func => .function,
|
||||
else => .constant,
|
||||
};
|
||||
|
||||
const target = sema.mod.getTarget();
|
||||
|
||||
const addrspace_body = decl_bodies.addrspace_body orelse break :blk switch (addrspace_ctx) {
|
||||
.function => target_util.defaultAddressSpace(target, .function),
|
||||
.variable => target_util.defaultAddressSpace(target, .global_mutable),
|
||||
.constant => target_util.defaultAddressSpace(target, .global_constant),
|
||||
else => unreachable,
|
||||
};
|
||||
const addrspace_ref = try sema.resolveInlineBody(&block_scope, addrspace_body, decl_inst);
|
||||
break :blk try sema.analyzeAsAddressSpace(&block_scope, address_space_src, addrspace_ref, addrspace_ctx);
|
||||
};
|
||||
}
|
||||
decl.has_tv = true;
|
||||
decl.analysis = .complete;
|
||||
|
||||
const result: SemaDeclResult = if (old_has_tv) .{
|
||||
.invalidate_decl_val = !decl.ty.eql(old_ty, mod) or !decl.val.eql(old_val, decl.ty, mod),
|
||||
.invalidate_decl_val = !decl.ty.eql(old_ty, mod) or
|
||||
!decl.val.eql(old_val, decl.ty, mod) or
|
||||
is_inline != old_is_inline,
|
||||
.invalidate_decl_ref = !decl.ty.eql(old_ty, mod) or
|
||||
decl.alignment != old_align or
|
||||
decl.@"linksection" != old_linksection or
|
||||
decl.@"addrspace" != old_addrspace,
|
||||
decl.@"addrspace" != old_addrspace or
|
||||
is_inline != old_is_inline,
|
||||
} else .{
|
||||
.invalidate_decl_val = true,
|
||||
.invalidate_decl_ref = true,
|
||||
};
|
||||
|
||||
const has_runtime_bits = is_extern or
|
||||
(queue_linker_work and try sema.typeHasRuntimeBits(decl.ty));
|
||||
|
||||
const has_runtime_bits = queue_linker_work and (is_func or try sema.typeHasRuntimeBits(decl.ty));
|
||||
if (has_runtime_bits) {
|
||||
|
||||
// Needed for codegen_decl which will call updateDecl and then the
|
||||
// codegen backend wants full access to the Decl Type.
|
||||
try sema.resolveTypeFully(decl.ty);
|
||||
@ -3881,6 +3848,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult {
|
||||
|
||||
if (decl.is_exported) {
|
||||
const export_src: LazySrcLoc = .{ .token_offset = @intFromBool(decl.is_pub) };
|
||||
if (is_inline) return sema.fail(&block_scope, export_src, "export of inline function", .{});
|
||||
// The scope needs to have the decl in it.
|
||||
try sema.analyzeExport(&block_scope, export_src, .{ .name = decl.name }, decl_index);
|
||||
}
|
||||
|
||||
43
src/Sema.zig
43
src/Sema.zig
@ -7605,7 +7605,6 @@ fn analyzeCall(
|
||||
.param_types = new_param_types,
|
||||
.return_type = owner_info.return_type,
|
||||
.noalias_bits = owner_info.noalias_bits,
|
||||
.alignment = if (owner_info.align_is_generic) null else owner_info.alignment,
|
||||
.cc = if (owner_info.cc_is_generic) null else owner_info.cc,
|
||||
.is_var_args = owner_info.is_var_args,
|
||||
.is_noinline = owner_info.is_noinline,
|
||||
@ -9629,7 +9628,6 @@ fn funcCommon(
|
||||
.comptime_bits = comptime_bits,
|
||||
.return_type = bare_return_type.toIntern(),
|
||||
.cc = cc,
|
||||
.alignment = alignment,
|
||||
.section_is_generic = section == .generic,
|
||||
.addrspace_is_generic = address_space == null,
|
||||
.is_var_args = var_args,
|
||||
@ -9640,6 +9638,7 @@ fn funcCommon(
|
||||
if (is_extern) {
|
||||
assert(comptime_bits == 0);
|
||||
assert(cc != null);
|
||||
assert(alignment != null);
|
||||
assert(section != .generic);
|
||||
assert(address_space != null);
|
||||
assert(!is_generic);
|
||||
@ -17623,8 +17622,6 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
|
||||
const field_values = .{
|
||||
// calling_convention: CallingConvention,
|
||||
(try mod.enumValueFieldIndex(callconv_ty, @intFromEnum(func_ty_info.cc))).toIntern(),
|
||||
// alignment: comptime_int,
|
||||
(try mod.intValue(Type.comptime_int, ty.abiAlignment(mod).toByteUnits(0))).toIntern(),
|
||||
// is_generic: bool,
|
||||
Value.makeBool(func_ty_info.is_generic).toIntern(),
|
||||
// is_var_args: bool,
|
||||
@ -19701,12 +19698,6 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
|
||||
if (inst_data.size != .One) {
|
||||
return sema.fail(block, elem_ty_src, "function pointers must be single pointers", .{});
|
||||
}
|
||||
const fn_align = mod.typeToFunc(elem_ty).?.alignment;
|
||||
if (inst_data.flags.has_align and abi_align != .none and fn_align != .none and
|
||||
abi_align != fn_align)
|
||||
{
|
||||
return sema.fail(block, align_src, "function pointer alignment disagrees with function alignment", .{});
|
||||
}
|
||||
} else if (inst_data.size == .Many and elem_ty.zigTypeTag(mod) == .Opaque) {
|
||||
return sema.fail(block, elem_ty_src, "unknown-length pointer to opaque not allowed", .{});
|
||||
} else if (inst_data.size == .C) {
|
||||
@ -21030,7 +21021,6 @@ fn zirReify(
|
||||
.needed_comptime_reason = "operand to @Type must be comptime-known",
|
||||
});
|
||||
const union_val = ip.indexToKey(val.toIntern()).un;
|
||||
const target = mod.getTarget();
|
||||
if (try Value.fromInterned(union_val.val).anyUndef(mod)) return sema.failWithUseOfUndef(block, src);
|
||||
const tag_index = type_info_ty.unionTagFieldIndex(Value.fromInterned(union_val.tag), mod).?;
|
||||
switch (@as(std.builtin.TypeId, @enumFromInt(tag_index))) {
|
||||
@ -21171,12 +21161,6 @@ fn zirReify(
|
||||
if (ptr_size != .One) {
|
||||
return sema.fail(block, src, "function pointers must be single pointers", .{});
|
||||
}
|
||||
const fn_align = mod.typeToFunc(elem_ty).?.alignment;
|
||||
if (abi_align != .none and fn_align != .none and
|
||||
abi_align != fn_align)
|
||||
{
|
||||
return sema.fail(block, src, "function pointer alignment disagrees with function alignment", .{});
|
||||
}
|
||||
} else if (ptr_size == .Many and elem_ty.zigTypeTag(mod) == .Opaque) {
|
||||
return sema.fail(block, src, "unknown-length pointer to opaque not allowed", .{});
|
||||
} else if (ptr_size == .C) {
|
||||
@ -21429,10 +21413,6 @@ fn zirReify(
|
||||
ip,
|
||||
try ip.getOrPutString(gpa, "calling_convention"),
|
||||
).?);
|
||||
const alignment_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex(
|
||||
ip,
|
||||
try ip.getOrPutString(gpa, "alignment"),
|
||||
).?);
|
||||
const is_generic_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex(
|
||||
ip,
|
||||
try ip.getOrPutString(gpa, "is_generic"),
|
||||
@ -21461,11 +21441,6 @@ fn zirReify(
|
||||
try sema.checkCallConvSupportsVarArgs(block, src, cc);
|
||||
}
|
||||
|
||||
const alignment = alignment: {
|
||||
const alignment = try sema.validateAlignAllowZero(block, src, try alignment_val.toUnsignedIntAdvanced(sema));
|
||||
const default = target_util.defaultFunctionAlignment(target);
|
||||
break :alignment if (alignment == default) .none else alignment;
|
||||
};
|
||||
const return_type = return_type_val.optionalValue(mod) orelse
|
||||
return sema.fail(block, src, "Type.Fn.return_type must be non-null for @Type", .{});
|
||||
|
||||
@ -21510,7 +21485,6 @@ fn zirReify(
|
||||
.param_types = param_types,
|
||||
.noalias_bits = noalias_bits,
|
||||
.return_type = return_type.toIntern(),
|
||||
.alignment = alignment,
|
||||
.cc = cc,
|
||||
.is_var_args = is_var_args,
|
||||
});
|
||||
@ -32536,16 +32510,21 @@ fn analyzeDeclRefInner(sema: *Sema, decl_index: InternPool.DeclIndex, analyze_fn
|
||||
const mod = sema.mod;
|
||||
try sema.ensureDeclAnalyzed(decl_index);
|
||||
|
||||
const decl = mod.declPtr(decl_index);
|
||||
const decl_tv = try decl.typedValue();
|
||||
const decl_tv = try mod.declPtr(decl_index).typedValue();
|
||||
const owner_decl = mod.declPtr(switch (mod.intern_pool.indexToKey(decl_tv.val.toIntern())) {
|
||||
.variable => |variable| variable.decl,
|
||||
.extern_func => |extern_func| extern_func.decl,
|
||||
.func => |func| func.owner_decl,
|
||||
else => decl_index,
|
||||
});
|
||||
// TODO: if this is a `decl_ref` of a non-variable decl, only depend on decl type
|
||||
try sema.declareDependency(.{ .decl_val = decl_index });
|
||||
const ptr_ty = try sema.ptrType(.{
|
||||
.child = decl_tv.ty.toIntern(),
|
||||
.flags = .{
|
||||
.alignment = decl.alignment,
|
||||
.is_const = if (decl.val.getVariable(mod)) |variable| variable.is_const else true,
|
||||
.address_space = decl.@"addrspace",
|
||||
.alignment = owner_decl.alignment,
|
||||
.is_const = if (decl_tv.val.getVariable(mod)) |variable| variable.is_const else true,
|
||||
.address_space = owner_decl.@"addrspace",
|
||||
},
|
||||
});
|
||||
if (analyze_fn_body) {
|
||||
|
||||
@ -1635,7 +1635,7 @@ pub const DeclGen = struct {
|
||||
|
||||
switch (kind) {
|
||||
.forward => {},
|
||||
.complete => if (fn_info.alignment.toByteUnitsOptional()) |a| {
|
||||
.complete => if (fn_decl.alignment.toByteUnitsOptional()) |a| {
|
||||
try w.print("{}zig_align_fn({})", .{ trailing, a });
|
||||
trailing = .maybe_space;
|
||||
},
|
||||
@ -1666,7 +1666,7 @@ pub const DeclGen = struct {
|
||||
|
||||
switch (kind) {
|
||||
.forward => {
|
||||
if (fn_info.alignment.toByteUnitsOptional()) |a| {
|
||||
if (fn_decl.alignment.toByteUnitsOptional()) |a| {
|
||||
try w.print(" zig_align_fn({})", .{a});
|
||||
}
|
||||
switch (name) {
|
||||
|
||||
@ -2952,8 +2952,8 @@ pub const Object = struct {
|
||||
else => function_index.setCallConv(toLlvmCallConv(fn_info.cc, target), &o.builder),
|
||||
}
|
||||
|
||||
if (fn_info.alignment != .none)
|
||||
function_index.setAlignment(fn_info.alignment.toLlvm(), &o.builder);
|
||||
if (decl.alignment != .none)
|
||||
function_index.setAlignment(decl.alignment.toLlvm(), &o.builder);
|
||||
|
||||
// Function attributes that are independent of analysis results of the function body.
|
||||
try o.addCommonFnAttributes(&attributes, owner_mod);
|
||||
|
||||
@ -4995,6 +4995,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
|
||||
} else .{
|
||||
.root = .{
|
||||
.root_dir = zig_lib_directory,
|
||||
.sub_path = "compiler",
|
||||
},
|
||||
.root_src_path = "build_runner.zig",
|
||||
};
|
||||
|
||||
10
src/type.zig
10
src/type.zig
@ -396,9 +396,6 @@ pub const Type = struct {
|
||||
try writer.writeAll("...");
|
||||
}
|
||||
try writer.writeAll(") ");
|
||||
if (fn_info.alignment.toByteUnitsOptional()) |a| {
|
||||
try writer.print("align({d}) ", .{a});
|
||||
}
|
||||
if (fn_info.cc != .Unspecified) {
|
||||
try writer.writeAll("callconv(.");
|
||||
try writer.writeAll(@tagName(fn_info.cc));
|
||||
@ -949,12 +946,7 @@ pub const Type = struct {
|
||||
},
|
||||
|
||||
// represents machine code; not a pointer
|
||||
.func_type => |func_type| return .{
|
||||
.scalar = if (func_type.alignment != .none)
|
||||
func_type.alignment
|
||||
else
|
||||
target_util.defaultFunctionAlignment(target),
|
||||
},
|
||||
.func_type => return .{ .scalar = target_util.defaultFunctionAlignment(target) },
|
||||
|
||||
.simple_type => |t| switch (t) {
|
||||
.bool,
|
||||
|
||||
249
stage1/zig.h
249
stage1/zig.h
@ -25,11 +25,15 @@ typedef char bool;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define zig_concat(lhs, rhs) lhs##rhs
|
||||
#define zig_expand_concat(lhs, rhs) zig_concat(lhs, rhs)
|
||||
|
||||
#if defined(__has_builtin)
|
||||
#define zig_has_builtin(builtin) __has_builtin(__builtin_##builtin)
|
||||
#else
|
||||
#define zig_has_builtin(builtin) 0
|
||||
#endif
|
||||
#define zig_expand_has_builtin(b) zig_has_builtin(b)
|
||||
|
||||
#if defined(__has_attribute)
|
||||
#define zig_has_attribute(attribute) __has_attribute(attribute)
|
||||
@ -112,7 +116,7 @@ typedef char bool;
|
||||
#define zig_never_tail zig_never_tail_unavailable
|
||||
#endif
|
||||
|
||||
#if zig_has_attribute(always_inline)
|
||||
#if zig_has_attribute(musttail)
|
||||
#define zig_always_tail __attribute__((musttail))
|
||||
#else
|
||||
#define zig_always_tail zig_always_tail_unavailable
|
||||
@ -180,20 +184,58 @@ typedef char bool;
|
||||
#define zig_extern extern
|
||||
#endif
|
||||
|
||||
#if zig_has_attribute(alias)
|
||||
#define zig_export(sig, symbol, name) zig_extern sig __attribute__((alias(symbol)))
|
||||
#elif _MSC_VER
|
||||
#if _MSC_VER
|
||||
#if _M_X64
|
||||
#define zig_export(sig, symbol, name) sig;\
|
||||
__pragma(comment(linker, "/alternatename:" name "=" symbol ))
|
||||
#define zig_mangle_c(symbol) symbol
|
||||
#else /*_M_X64 */
|
||||
#define zig_export(sig, symbol, name) sig;\
|
||||
__pragma(comment(linker, "/alternatename:_" name "=_" symbol ))
|
||||
#define zig_mangle_c(symbol) "_" symbol
|
||||
#endif /*_M_X64 */
|
||||
#else /* _MSC_VER */
|
||||
#if __APPLE__
|
||||
#define zig_mangle_c(symbol) "_" symbol
|
||||
#else /* __APPLE__ */
|
||||
#define zig_mangle_c(symbol) symbol
|
||||
#endif /* __APPLE__ */
|
||||
#endif /* _MSC_VER */
|
||||
|
||||
#if zig_has_attribute(alias) && !__APPLE__
|
||||
#define zig_export(symbol, name) __attribute__((alias(symbol)))
|
||||
#elif _MSC_VER
|
||||
#define zig_export(symbol, name) ; \
|
||||
__pragma(comment(linker, "/alternatename:" zig_mangle_c(name) "=" zig_mangle_c(symbol)))
|
||||
#else
|
||||
#define zig_export(sig, symbol, name) __asm(name " = " symbol)
|
||||
#define zig_export(symbol, name) ; \
|
||||
__asm(zig_mangle_c(name) " = " zig_mangle_c(symbol))
|
||||
#endif
|
||||
|
||||
#if _MSC_VER
|
||||
#define zig_mangled_tentative(mangled, unmangled)
|
||||
#define zig_mangled_final(mangled, unmangled) ; \
|
||||
zig_export(#mangled, unmangled)
|
||||
#define zig_mangled_export(mangled, unmangled, symbol) \
|
||||
zig_export(unmangled, #mangled) \
|
||||
zig_export(symbol, unmangled)
|
||||
#else /* _MSC_VER */
|
||||
#define zig_mangled_tentative(mangled, unmangled) __asm(zig_mangle_c(unmangled))
|
||||
#define zig_mangled_final(mangled, unmangled) zig_mangled_tentative(mangled, unmangled)
|
||||
#define zig_mangled_export(mangled, unmangled, symbol) \
|
||||
zig_mangled_final(mangled, unmangled) \
|
||||
zig_export(symbol, unmangled)
|
||||
#endif /* _MSC_VER */
|
||||
|
||||
#if _MSC_VER
|
||||
#define zig_import(Type, fn_name, libc_name, sig_args, call_args) zig_extern Type fn_name sig_args;\
|
||||
__pragma(comment(linker, "/alternatename:" zig_mangle_c(#fn_name) "=" zig_mangle_c(#libc_name)));
|
||||
#define zig_import_builtin(Type, fn_name, libc_name, sig_args, call_args) zig_import(Type, fn_name, sig_args, call_args)
|
||||
#else /* _MSC_VER */
|
||||
#define zig_import(Type, fn_name, libc_name, sig_args, call_args) zig_extern Type fn_name sig_args __asm(zig_mangle_c(#libc_name));
|
||||
#define zig_import_builtin(Type, fn_name, libc_name, sig_args, call_args) zig_extern Type libc_name sig_args; \
|
||||
static inline Type fn_name sig_args { return libc_name call_args; }
|
||||
#endif
|
||||
|
||||
#define zig_expand_import_0(Type, fn_name, libc_name, sig_args, call_args) zig_import(Type, fn_name, libc_name, sig_args, call_args)
|
||||
#define zig_expand_import_1(Type, fn_name, libc_name, sig_args, call_args) zig_import_builtin(Type, fn_name, libc_name, sig_args, call_args)
|
||||
|
||||
#if zig_has_attribute(weak) || defined(zig_gnuc)
|
||||
#define zig_weak_linkage __attribute__((weak))
|
||||
#define zig_weak_linkage_fn __attribute__((weak))
|
||||
@ -267,9 +309,6 @@ typedef char bool;
|
||||
#define zig_wasm_memory_grow(index, delta) zig_unimplemented()
|
||||
#endif
|
||||
|
||||
#define zig_concat(lhs, rhs) lhs##rhs
|
||||
#define zig_expand_concat(lhs, rhs) zig_concat(lhs, rhs)
|
||||
|
||||
#if __STDC_VERSION__ >= 201112L
|
||||
#define zig_noreturn _Noreturn
|
||||
#elif zig_has_attribute(noreturn) || defined(zig_gnuc)
|
||||
@ -2163,7 +2202,7 @@ static inline bool zig_addo_big(void *res, const void *lhs, const void *rhs, boo
|
||||
const uint8_t *rhs_bytes = rhs;
|
||||
uint16_t byte_offset = 0;
|
||||
uint16_t remaining_bytes = zig_int_bytes(bits);
|
||||
uint16_t top_bits = remaining_bytes * 8 - bits;
|
||||
uint8_t top_bits = (uint8_t)(remaining_bytes * 8 - bits);
|
||||
bool overflow = false;
|
||||
|
||||
#if zig_big_endian
|
||||
@ -2171,7 +2210,7 @@ static inline bool zig_addo_big(void *res, const void *lhs, const void *rhs, boo
|
||||
#endif
|
||||
|
||||
while (remaining_bytes >= 128 / CHAR_BIT) {
|
||||
uint16_t limb_bits = 128 - (remaining_bytes == 128 / CHAR_BIT ? top_bits : 0);
|
||||
uint8_t limb_bits = 128 - (remaining_bytes == 128 / CHAR_BIT ? top_bits : 0);
|
||||
|
||||
#if zig_big_endian
|
||||
byte_offset -= 128 / CHAR_BIT;
|
||||
@ -2211,7 +2250,7 @@ static inline bool zig_addo_big(void *res, const void *lhs, const void *rhs, boo
|
||||
}
|
||||
|
||||
while (remaining_bytes >= 64 / CHAR_BIT) {
|
||||
uint16_t limb_bits = 64 - (remaining_bytes == 64 / CHAR_BIT ? top_bits : 0);
|
||||
uint8_t limb_bits = 64 - (remaining_bytes == 64 / CHAR_BIT ? top_bits : 0);
|
||||
|
||||
#if zig_big_endian
|
||||
byte_offset -= 64 / CHAR_BIT;
|
||||
@ -2251,7 +2290,7 @@ static inline bool zig_addo_big(void *res, const void *lhs, const void *rhs, boo
|
||||
}
|
||||
|
||||
while (remaining_bytes >= 32 / CHAR_BIT) {
|
||||
uint16_t limb_bits = 32 - (remaining_bytes == 32 / CHAR_BIT ? top_bits : 0);
|
||||
uint8_t limb_bits = 32 - (remaining_bytes == 32 / CHAR_BIT ? top_bits : 0);
|
||||
|
||||
#if zig_big_endian
|
||||
byte_offset -= 32 / CHAR_BIT;
|
||||
@ -2291,7 +2330,7 @@ static inline bool zig_addo_big(void *res, const void *lhs, const void *rhs, boo
|
||||
}
|
||||
|
||||
while (remaining_bytes >= 16 / CHAR_BIT) {
|
||||
uint16_t limb_bits = 16 - (remaining_bytes == 16 / CHAR_BIT ? top_bits : 0);
|
||||
uint8_t limb_bits = 16 - (remaining_bytes == 16 / CHAR_BIT ? top_bits : 0);
|
||||
|
||||
#if zig_big_endian
|
||||
byte_offset -= 16 / CHAR_BIT;
|
||||
@ -2331,7 +2370,7 @@ static inline bool zig_addo_big(void *res, const void *lhs, const void *rhs, boo
|
||||
}
|
||||
|
||||
while (remaining_bytes >= 8 / CHAR_BIT) {
|
||||
uint16_t limb_bits = 8 - (remaining_bytes == 8 / CHAR_BIT ? top_bits : 0);
|
||||
uint8_t limb_bits = 8 - (remaining_bytes == 8 / CHAR_BIT ? top_bits : 0);
|
||||
|
||||
#if zig_big_endian
|
||||
byte_offset -= 8 / CHAR_BIT;
|
||||
@ -2379,7 +2418,7 @@ static inline bool zig_subo_big(void *res, const void *lhs, const void *rhs, boo
|
||||
const uint8_t *rhs_bytes = rhs;
|
||||
uint16_t byte_offset = 0;
|
||||
uint16_t remaining_bytes = zig_int_bytes(bits);
|
||||
uint16_t top_bits = remaining_bytes * 8 - bits;
|
||||
uint8_t top_bits = (uint8_t)(remaining_bytes * 8 - bits);
|
||||
bool overflow = false;
|
||||
|
||||
#if zig_big_endian
|
||||
@ -2387,7 +2426,7 @@ static inline bool zig_subo_big(void *res, const void *lhs, const void *rhs, boo
|
||||
#endif
|
||||
|
||||
while (remaining_bytes >= 128 / CHAR_BIT) {
|
||||
uint16_t limb_bits = 128 - (remaining_bytes == 128 / CHAR_BIT ? top_bits : 0);
|
||||
uint8_t limb_bits = 128 - (remaining_bytes == 128 / CHAR_BIT ? top_bits : 0);
|
||||
|
||||
#if zig_big_endian
|
||||
byte_offset -= 128 / CHAR_BIT;
|
||||
@ -2427,7 +2466,7 @@ static inline bool zig_subo_big(void *res, const void *lhs, const void *rhs, boo
|
||||
}
|
||||
|
||||
while (remaining_bytes >= 64 / CHAR_BIT) {
|
||||
uint16_t limb_bits = 64 - (remaining_bytes == 64 / CHAR_BIT ? top_bits : 0);
|
||||
uint8_t limb_bits = 64 - (remaining_bytes == 64 / CHAR_BIT ? top_bits : 0);
|
||||
|
||||
#if zig_big_endian
|
||||
byte_offset -= 64 / CHAR_BIT;
|
||||
@ -2467,7 +2506,7 @@ static inline bool zig_subo_big(void *res, const void *lhs, const void *rhs, boo
|
||||
}
|
||||
|
||||
while (remaining_bytes >= 32 / CHAR_BIT) {
|
||||
uint16_t limb_bits = 32 - (remaining_bytes == 32 / CHAR_BIT ? top_bits : 0);
|
||||
uint8_t limb_bits = 32 - (remaining_bytes == 32 / CHAR_BIT ? top_bits : 0);
|
||||
|
||||
#if zig_big_endian
|
||||
byte_offset -= 32 / CHAR_BIT;
|
||||
@ -2507,7 +2546,7 @@ static inline bool zig_subo_big(void *res, const void *lhs, const void *rhs, boo
|
||||
}
|
||||
|
||||
while (remaining_bytes >= 16 / CHAR_BIT) {
|
||||
uint16_t limb_bits = 16 - (remaining_bytes == 16 / CHAR_BIT ? top_bits : 0);
|
||||
uint8_t limb_bits = 16 - (remaining_bytes == 16 / CHAR_BIT ? top_bits : 0);
|
||||
|
||||
#if zig_big_endian
|
||||
byte_offset -= 16 / CHAR_BIT;
|
||||
@ -2547,7 +2586,7 @@ static inline bool zig_subo_big(void *res, const void *lhs, const void *rhs, boo
|
||||
}
|
||||
|
||||
while (remaining_bytes >= 8 / CHAR_BIT) {
|
||||
uint16_t limb_bits = 8 - (remaining_bytes == 8 / CHAR_BIT ? top_bits : 0);
|
||||
uint8_t limb_bits = 8 - (remaining_bytes == 8 / CHAR_BIT ? top_bits : 0);
|
||||
|
||||
#if zig_big_endian
|
||||
byte_offset -= 8 / CHAR_BIT;
|
||||
@ -3093,6 +3132,7 @@ ypedef uint32_t zig_f32;
|
||||
|
||||
#define zig_has_f64 1
|
||||
#define zig_libc_name_f64(name) name
|
||||
|
||||
#if _MSC_VER
|
||||
#define zig_init_special_f64(sign, name, arg, repr) sign zig_make_f64(zig_msvc_flt_##name, )
|
||||
#else
|
||||
@ -3336,31 +3376,31 @@ zig_float_negate_builtin(128, zig_make_u128, (UINT64_C(1) << 63, UINT64_C(0)))
|
||||
zig_expand_concat(zig_float_binary_builtin_, zig_has_f##w)(f##w, sub, -) \
|
||||
zig_expand_concat(zig_float_binary_builtin_, zig_has_f##w)(f##w, mul, *) \
|
||||
zig_expand_concat(zig_float_binary_builtin_, zig_has_f##w)(f##w, div, /) \
|
||||
zig_extern zig_f##w zig_libc_name_f##w(sqrt)(zig_f##w); \
|
||||
zig_extern zig_f##w zig_libc_name_f##w(sin)(zig_f##w); \
|
||||
zig_extern zig_f##w zig_libc_name_f##w(cos)(zig_f##w); \
|
||||
zig_extern zig_f##w zig_libc_name_f##w(tan)(zig_f##w); \
|
||||
zig_extern zig_f##w zig_libc_name_f##w(exp)(zig_f##w); \
|
||||
zig_extern zig_f##w zig_libc_name_f##w(exp2)(zig_f##w); \
|
||||
zig_extern zig_f##w zig_libc_name_f##w(log)(zig_f##w); \
|
||||
zig_extern zig_f##w zig_libc_name_f##w(log2)(zig_f##w); \
|
||||
zig_extern zig_f##w zig_libc_name_f##w(log10)(zig_f##w); \
|
||||
zig_extern zig_f##w zig_libc_name_f##w(fabs)(zig_f##w); \
|
||||
zig_extern zig_f##w zig_libc_name_f##w(floor)(zig_f##w); \
|
||||
zig_extern zig_f##w zig_libc_name_f##w(ceil)(zig_f##w); \
|
||||
zig_extern zig_f##w zig_libc_name_f##w(round)(zig_f##w); \
|
||||
zig_extern zig_f##w zig_libc_name_f##w(trunc)(zig_f##w); \
|
||||
zig_extern zig_f##w zig_libc_name_f##w(fmod)(zig_f##w, zig_f##w); \
|
||||
zig_extern zig_f##w zig_libc_name_f##w(fmin)(zig_f##w, zig_f##w); \
|
||||
zig_extern zig_f##w zig_libc_name_f##w(fmax)(zig_f##w, zig_f##w); \
|
||||
zig_extern zig_f##w zig_libc_name_f##w(fma)(zig_f##w, zig_f##w, zig_f##w); \
|
||||
zig_expand_concat(zig_expand_import_, zig_expand_has_builtin(zig_libc_name_f##w(sqrt)))(zig_f##w, zig_float_fn_f##w##_sqrt, zig_libc_name_f##w(sqrt), (zig_f##w x), (x)) \
|
||||
zig_expand_concat(zig_expand_import_, zig_expand_has_builtin(zig_libc_name_f##w(sin)))(zig_f##w, zig_float_fn_f##w##_sin, zig_libc_name_f##w(sin), (zig_f##w x), (x)) \
|
||||
zig_expand_concat(zig_expand_import_, zig_expand_has_builtin(zig_libc_name_f##w(cos)))(zig_f##w, zig_float_fn_f##w##_cos, zig_libc_name_f##w(cos), (zig_f##w x), (x)) \
|
||||
zig_expand_concat(zig_expand_import_, zig_expand_has_builtin(zig_libc_name_f##w(tan)))(zig_f##w, zig_float_fn_f##w##_tan, zig_libc_name_f##w(tan), (zig_f##w x), (x)) \
|
||||
zig_expand_concat(zig_expand_import_, zig_expand_has_builtin(zig_libc_name_f##w(exp)))(zig_f##w, zig_float_fn_f##w##_exp, zig_libc_name_f##w(exp), (zig_f##w x), (x)) \
|
||||
zig_expand_concat(zig_expand_import_, zig_expand_has_builtin(zig_libc_name_f##w(exp2)))(zig_f##w, zig_float_fn_f##w##_exp2, zig_libc_name_f##w(exp2), (zig_f##w x), (x)) \
|
||||
zig_expand_concat(zig_expand_import_, zig_expand_has_builtin(zig_libc_name_f##w(log)))(zig_f##w, zig_float_fn_f##w##_log, zig_libc_name_f##w(log), (zig_f##w x), (x)) \
|
||||
zig_expand_concat(zig_expand_import_, zig_expand_has_builtin(zig_libc_name_f##w(log2)))(zig_f##w, zig_float_fn_f##w##_log2, zig_libc_name_f##w(log2), (zig_f##w x), (x)) \
|
||||
zig_expand_concat(zig_expand_import_, zig_expand_has_builtin(zig_libc_name_f##w(log10)))(zig_f##w, zig_float_fn_f##w##_log10, zig_libc_name_f##w(log10), (zig_f##w x), (x)) \
|
||||
zig_expand_concat(zig_expand_import_, zig_expand_has_builtin(zig_libc_name_f##w(fabs)))(zig_f##w, zig_float_fn_f##w##_fabs, zig_libc_name_f##w(fabs), (zig_f##w x), (x)) \
|
||||
zig_expand_concat(zig_expand_import_, zig_expand_has_builtin(zig_libc_name_f##w(floor)))(zig_f##w, zig_float_fn_f##w##_floor, zig_libc_name_f##w(floor), (zig_f##w x), (x)) \
|
||||
zig_expand_concat(zig_expand_import_, zig_expand_has_builtin(zig_libc_name_f##w(ceil)))(zig_f##w, zig_float_fn_f##w##_ceil, zig_libc_name_f##w(ceil), (zig_f##w x), (x)) \
|
||||
zig_expand_concat(zig_expand_import_, zig_expand_has_builtin(zig_libc_name_f##w(round)))(zig_f##w, zig_float_fn_f##w##_round, zig_libc_name_f##w(round), (zig_f##w x), (x)) \
|
||||
zig_expand_concat(zig_expand_import_, zig_expand_has_builtin(zig_libc_name_f##w(trunc)))(zig_f##w, zig_float_fn_f##w##_trunc, zig_libc_name_f##w(trunc), (zig_f##w x), (x)) \
|
||||
zig_expand_concat(zig_expand_import_, zig_expand_has_builtin(zig_libc_name_f##w(fmod)))(zig_f##w, zig_float_fn_f##w##_fmod, zig_libc_name_f##w(fmod), (zig_f##w x, zig_f##w y), (x, y)) \
|
||||
zig_expand_concat(zig_expand_import_, zig_expand_has_builtin(zig_libc_name_f##w(fmin)))(zig_f##w, zig_float_fn_f##w##_fmin, zig_libc_name_f##w(fmin), (zig_f##w x, zig_f##w y), (x, y)) \
|
||||
zig_expand_concat(zig_expand_import_, zig_expand_has_builtin(zig_libc_name_f##w(fmax)))(zig_f##w, zig_float_fn_f##w##_fmax, zig_libc_name_f##w(fmax), (zig_f##w x, zig_f##w y), (x, y)) \
|
||||
zig_expand_concat(zig_expand_import_, zig_expand_has_builtin(zig_libc_name_f##w(fma)))(zig_f##w, zig_float_fn_f##w##_fma, zig_libc_name_f##w(fma), (zig_f##w x, zig_f##w y, zig_f##w z), (x, y, z)) \
|
||||
\
|
||||
static inline zig_f##w zig_div_trunc_f##w(zig_f##w lhs, zig_f##w rhs) { \
|
||||
return zig_libc_name_f##w(trunc)(zig_div_f##w(lhs, rhs)); \
|
||||
return zig_float_fn_f##w##_trunc(zig_div_f##w(lhs, rhs)); \
|
||||
} \
|
||||
\
|
||||
static inline zig_f##w zig_div_floor_f##w(zig_f##w lhs, zig_f##w rhs) { \
|
||||
return zig_libc_name_f##w(floor)(zig_div_f##w(lhs, rhs)); \
|
||||
return zig_float_fn_f##w##_floor(zig_div_f##w(lhs, rhs)); \
|
||||
} \
|
||||
\
|
||||
static inline zig_f##w zig_mod_f##w(zig_f##w lhs, zig_f##w rhs) { \
|
||||
@ -3437,129 +3477,134 @@ zig_float_builtins(64)
|
||||
/* Note that zig_atomicrmw_expected is needed to handle aliasing between res and arg. */
|
||||
#define zig_atomicrmw_xchg_float(res, obj, arg, order, Type, ReprType) do { \
|
||||
zig_##Type zig_atomicrmw_expected; \
|
||||
zig_atomic_load(zig_atomicrmw_expected, obj, memory_order_relaxed, Type, ReprType); \
|
||||
while (!zig_cmpxchg_weak(obj, zig_atomicrmw_expected, arg, order, memory_order_relaxed, Type, ReprType)); \
|
||||
zig_atomic_load(zig_atomicrmw_expected, obj, zig_memory_order_relaxed, Type, ReprType); \
|
||||
while (!zig_cmpxchg_weak(obj, zig_atomicrmw_expected, arg, order, zig_memory_order_relaxed, Type, ReprType)); \
|
||||
res = zig_atomicrmw_expected; \
|
||||
} while (0)
|
||||
#define zig_atomicrmw_add_float(res, obj, arg, order, Type, ReprType) do { \
|
||||
zig_##Type zig_atomicrmw_expected; \
|
||||
zig_##Type zig_atomicrmw_desired; \
|
||||
zig_atomic_load(zig_atomicrmw_expected, obj, memory_order_relaxed, Type, ReprType); \
|
||||
zig_atomic_load(zig_atomicrmw_expected, obj, zig_memory_order_relaxed, Type, ReprType); \
|
||||
do { \
|
||||
zig_atomicrmw_desired = zig_add_##Type(zig_atomicrmw_expected, arg); \
|
||||
} while (!zig_cmpxchg_weak(obj, zig_atomicrmw_expected, zig_atomicrmw_desired, order, memory_order_relaxed, Type, ReprType)); \
|
||||
} while (!zig_cmpxchg_weak(obj, zig_atomicrmw_expected, zig_atomicrmw_desired, order, zig_memory_order_relaxed, Type, ReprType)); \
|
||||
res = zig_atomicrmw_expected; \
|
||||
} while (0)
|
||||
#define zig_atomicrmw_sub_float(res, obj, arg, order, Type, ReprType) do { \
|
||||
zig_##Type zig_atomicrmw_expected; \
|
||||
zig_##Type zig_atomicrmw_desired; \
|
||||
zig_atomic_load(zig_atomicrmw_expected, obj, memory_order_relaxed, Type, ReprType); \
|
||||
zig_atomic_load(zig_atomicrmw_expected, obj, zig_memory_order_relaxed, Type, ReprType); \
|
||||
do { \
|
||||
zig_atomicrmw_desired = zig_sub_##Type(zig_atomicrmw_expected, arg); \
|
||||
} while (!zig_cmpxchg_weak(obj, zig_atomicrmw_expected, zig_atomicrmw_desired, order, memory_order_relaxed, Type, ReprType)); \
|
||||
} while (!zig_cmpxchg_weak(obj, zig_atomicrmw_expected, zig_atomicrmw_desired, order, zig_memory_order_relaxed, Type, ReprType)); \
|
||||
res = zig_atomicrmw_expected; \
|
||||
} while (0)
|
||||
#define zig_atomicrmw_min_float(res, obj, arg, order, Type, ReprType) do { \
|
||||
zig_##Type zig_atomicrmw_expected; \
|
||||
zig_##Type zig_atomicrmw_desired; \
|
||||
zig_atomic_load(zig_atomicrmw_expected, obj, memory_order_relaxed, Type, ReprType); \
|
||||
zig_atomic_load(zig_atomicrmw_expected, obj, zig_memory_order_relaxed, Type, ReprType); \
|
||||
do { \
|
||||
zig_atomicrmw_desired = zig_libc_name_##Type(fmin)(zig_atomicrmw_expected, arg); \
|
||||
} while (!zig_cmpxchg_weak(obj, zig_atomicrmw_expected, zig_atomicrmw_desired, order, memory_order_relaxed, Type, ReprType)); \
|
||||
zig_atomicrmw_desired = zig_float_fn_##Type##_fmin(zig_atomicrmw_expected, arg); \
|
||||
} while (!zig_cmpxchg_weak(obj, zig_atomicrmw_expected, zig_atomicrmw_desired, order, zig_memory_order_relaxed, Type, ReprType)); \
|
||||
res = zig_atomicrmw_expected; \
|
||||
} while (0)
|
||||
#define zig_atomicrmw_max_float(res, obj, arg, order, Type, ReprType) do { \
|
||||
zig_##Type zig_atomicrmw_expected; \
|
||||
zig_##Type zig_atomicrmw_desired; \
|
||||
zig_atomic_load(zig_atomicrmw_expected, obj, memory_order_relaxed, Type, ReprType); \
|
||||
zig_atomic_load(zig_atomicrmw_expected, obj, zig_memory_order_relaxed, Type, ReprType); \
|
||||
do { \
|
||||
zig_atomicrmw_desired = zig_libc_name_##Type(fmax)(zig_atomicrmw_expected, arg); \
|
||||
} while (!zig_cmpxchg_weak(obj, zig_atomicrmw_expected, zig_atomicrmw_desired, order, memory_order_relaxed, Type, ReprType)); \
|
||||
zig_atomicrmw_desired = zig_float_fn_##Type##_fmax(zig_atomicrmw_expected, arg); \
|
||||
} while (!zig_cmpxchg_weak(obj, zig_atomicrmw_expected, zig_atomicrmw_desired, order, zig_memory_order_relaxed, Type, ReprType)); \
|
||||
res = zig_atomicrmw_expected; \
|
||||
} while (0)
|
||||
|
||||
#define zig_atomicrmw_xchg_int128(res, obj, arg, order, Type, ReprType) do { \
|
||||
zig_##Type zig_atomicrmw_expected; \
|
||||
zig_atomic_load(zig_atomicrmw_expected, obj, memory_order_relaxed, Type, ReprType); \
|
||||
while (!zig_cmpxchg_weak(obj, zig_atomicrmw_expected, arg, order, memory_order_relaxed, Type, ReprType)); \
|
||||
zig_atomic_load(zig_atomicrmw_expected, obj, zig_memory_order_relaxed, Type, ReprType); \
|
||||
while (!zig_cmpxchg_weak(obj, zig_atomicrmw_expected, arg, order, zig_memory_order_relaxed, Type, ReprType)); \
|
||||
res = zig_atomicrmw_expected; \
|
||||
} while (0)
|
||||
#define zig_atomicrmw_add_int128(res, obj, arg, order, Type, ReprType) do { \
|
||||
zig_##Type zig_atomicrmw_expected; \
|
||||
zig_##Type zig_atomicrmw_desired; \
|
||||
zig_atomic_load(zig_atomicrmw_expected, obj, memory_order_relaxed, Type, ReprType); \
|
||||
zig_atomic_load(zig_atomicrmw_expected, obj, zig_memory_order_relaxed, Type, ReprType); \
|
||||
do { \
|
||||
zig_atomicrmw_desired = zig_add_##Type(zig_atomicrmw_expected, arg); \
|
||||
} while (!zig_cmpxchg_weak(obj, zig_atomicrmw_expected, zig_atomicrmw_desired, order, memory_order_relaxed, Type, ReprType)); \
|
||||
} while (!zig_cmpxchg_weak(obj, zig_atomicrmw_expected, zig_atomicrmw_desired, order, zig_memory_order_relaxed, Type, ReprType)); \
|
||||
res = zig_atomicrmw_expected; \
|
||||
} while (0)
|
||||
#define zig_atomicrmw_sub_int128(res, obj, arg, order, Type, ReprType) do { \
|
||||
zig_##Type zig_atomicrmw_expected; \
|
||||
zig_##Type zig_atomicrmw_desired; \
|
||||
zig_atomic_load(zig_atomicrmw_expected, obj, memory_order_relaxed, Type, ReprType); \
|
||||
zig_atomic_load(zig_atomicrmw_expected, obj, zig_memory_order_relaxed, Type, ReprType); \
|
||||
do { \
|
||||
zig_atomicrmw_desired = zig_sub_##Type(zig_atomicrmw_expected, arg); \
|
||||
} while (!zig_cmpxchg_weak(obj, zig_atomicrmw_expected, zig_atomicrmw_desired, order, memory_order_relaxed, Type, ReprType)); \
|
||||
} while (!zig_cmpxchg_weak(obj, zig_atomicrmw_expected, zig_atomicrmw_desired, order, zig_memory_order_relaxed, Type, ReprType)); \
|
||||
res = zig_atomicrmw_expected; \
|
||||
} while (0)
|
||||
#define zig_atomicrmw_and_int128(res, obj, arg, order, Type, ReprType) do { \
|
||||
zig_##Type zig_atomicrmw_expected; \
|
||||
zig_##Type zig_atomicrmw_desired; \
|
||||
zig_atomic_load(zig_atomicrmw_expected, obj, memory_order_relaxed, Type, ReprType); \
|
||||
zig_atomic_load(zig_atomicrmw_expected, obj, zig_memory_order_relaxed, Type, ReprType); \
|
||||
do { \
|
||||
zig_atomicrmw_desired = zig_and_##Type(zig_atomicrmw_expected, arg); \
|
||||
} while (!zig_cmpxchg_weak(obj, zig_atomicrmw_expected, zig_atomicrmw_desired, order, memory_order_relaxed, Type, ReprType)); \
|
||||
} while (!zig_cmpxchg_weak(obj, zig_atomicrmw_expected, zig_atomicrmw_desired, order, zig_memory_order_relaxed, Type, ReprType)); \
|
||||
res = zig_atomicrmw_expected; \
|
||||
} while (0)
|
||||
#define zig_atomicrmw_nand_int128(res, obj, arg, order, Type, ReprType) do { \
|
||||
zig_##Type zig_atomicrmw_expected; \
|
||||
zig_##Type zig_atomicrmw_desired; \
|
||||
zig_atomic_load(zig_atomicrmw_expected, obj, memory_order_relaxed, Type, ReprType); \
|
||||
zig_atomic_load(zig_atomicrmw_expected, obj, zig_memory_order_relaxed, Type, ReprType); \
|
||||
do { \
|
||||
zig_atomicrmw_desired = zig_not_##Type(zig_and_##Type(zig_atomicrmw_expected, arg), 128); \
|
||||
} while (!zig_cmpxchg_weak(obj, zig_atomicrmw_expected, zig_atomicrmw_desired, order, memory_order_relaxed, Type, ReprType)); \
|
||||
} while (!zig_cmpxchg_weak(obj, zig_atomicrmw_expected, zig_atomicrmw_desired, order, zig_memory_order_relaxed, Type, ReprType)); \
|
||||
res = zig_atomicrmw_expected; \
|
||||
} while (0)
|
||||
#define zig_atomicrmw_or_int128(res, obj, arg, order, Type, ReprType) do { \
|
||||
zig_##Type zig_atomicrmw_expected; \
|
||||
zig_##Type zig_atomicrmw_desired; \
|
||||
zig_atomic_load(zig_atomicrmw_expected, obj, memory_order_relaxed, Type, ReprType); \
|
||||
zig_atomic_load(zig_atomicrmw_expected, obj, zig_memory_order_relaxed, Type, ReprType); \
|
||||
do { \
|
||||
zig_atomicrmw_desired = zig_or_##Type(zig_atomicrmw_expected, arg); \
|
||||
} while (!zig_cmpxchg_weak(obj, zig_atomicrmw_expected, zig_atomicrmw_desired, order, memory_order_relaxed, Type, ReprType)); \
|
||||
} while (!zig_cmpxchg_weak(obj, zig_atomicrmw_expected, zig_atomicrmw_desired, order, zig_memory_order_relaxed, Type, ReprType)); \
|
||||
res = zig_atomicrmw_expected; \
|
||||
} while (0)
|
||||
#define zig_atomicrmw_xor_int128(res, obj, arg, order, Type, ReprType) do { \
|
||||
zig_##Type zig_atomicrmw_expected; \
|
||||
zig_##Type zig_atomicrmw_desired; \
|
||||
zig_atomic_load(zig_atomicrmw_expected, obj, memory_order_relaxed, Type, ReprType); \
|
||||
zig_atomic_load(zig_atomicrmw_expected, obj, zig_memory_order_relaxed, Type, ReprType); \
|
||||
do { \
|
||||
zig_atomicrmw_desired = zig_xor_##Type(zig_atomicrmw_expected, arg); \
|
||||
} while (!zig_cmpxchg_weak(obj, zig_atomicrmw_expected, zig_atomicrmw_desired, order, memory_order_relaxed, Type, ReprType)); \
|
||||
} while (!zig_cmpxchg_weak(obj, zig_atomicrmw_expected, zig_atomicrmw_desired, order, zig_memory_order_relaxed, Type, ReprType)); \
|
||||
res = zig_atomicrmw_expected; \
|
||||
} while (0)
|
||||
#define zig_atomicrmw_min_int128(res, obj, arg, order, Type, ReprType) do { \
|
||||
zig_##Type zig_atomicrmw_expected; \
|
||||
zig_##Type zig_atomicrmw_desired; \
|
||||
zig_atomic_load(zig_atomicrmw_expected, obj, memory_order_relaxed, Type, ReprType); \
|
||||
zig_atomic_load(zig_atomicrmw_expected, obj, zig_memory_order_relaxed, Type, ReprType); \
|
||||
do { \
|
||||
zig_atomicrmw_desired = zig_min_##Type(zig_atomicrmw_expected, arg); \
|
||||
} while (!zig_cmpxchg_weak(obj, zig_atomicrmw_expected, zig_atomicrmw_desired, order, memory_order_relaxed, Type, ReprType)); \
|
||||
} while (!zig_cmpxchg_weak(obj, zig_atomicrmw_expected, zig_atomicrmw_desired, order, zig_memory_order_relaxed, Type, ReprType)); \
|
||||
res = zig_atomicrmw_expected; \
|
||||
} while (0)
|
||||
#define zig_atomicrmw_max_int128(res, obj, arg, order, Type, ReprType) do { \
|
||||
zig_##Type zig_atomicrmw_expected; \
|
||||
zig_##Type zig_atomicrmw_desired; \
|
||||
zig_atomic_load(zig_atomicrmw_expected, obj, memory_order_relaxed, Type, ReprType); \
|
||||
zig_atomic_load(zig_atomicrmw_expected, obj, zig_memory_order_relaxed, Type, ReprType); \
|
||||
do { \
|
||||
zig_atomicrmw_desired = zig_max_##Type(zig_atomicrmw_expected, arg); \
|
||||
} while (!zig_cmpxchg_weak(obj, zig_atomicrmw_expected, zig_atomicrmw_desired, order, memory_order_relaxed, Type, ReprType)); \
|
||||
} while (!zig_cmpxchg_weak(obj, zig_atomicrmw_expected, zig_atomicrmw_desired, order, zig_memory_order_relaxed, Type, ReprType)); \
|
||||
res = zig_atomicrmw_expected; \
|
||||
} while (0)
|
||||
|
||||
#if __STDC_VERSION__ >= 201112L && !defined(__STDC_NO_ATOMICS__)
|
||||
#include <stdatomic.h>
|
||||
typedef enum memory_order zig_memory_order;
|
||||
#define zig_memory_order_relaxed memory_order_relaxed
|
||||
#define zig_memory_order_acquire memory_order_acquire
|
||||
#define zig_memory_order_release memory_order_release
|
||||
#define zig_memory_order_acq_rel memory_order_acq_rel
|
||||
#define zig_memory_order_seq_cst memory_order_seq_cst
|
||||
#define zig_atomic(Type) _Atomic(Type)
|
||||
#define zig_cmpxchg_strong( obj, expected, desired, succ, fail, Type, ReprType) atomic_compare_exchange_strong_explicit(obj, &(expected), desired, succ, fail)
|
||||
#define zig_cmpxchg_weak( obj, expected, desired, succ, fail, Type, ReprType) atomic_compare_exchange_weak_explicit (obj, &(expected), desired, succ, fail)
|
||||
@ -3583,12 +3628,11 @@ typedef enum memory_order zig_memory_order;
|
||||
#define zig_fence(order) atomic_thread_fence(order)
|
||||
#elif defined(__GNUC__)
|
||||
typedef int zig_memory_order;
|
||||
#define memory_order_relaxed __ATOMIC_RELAXED
|
||||
#define memory_order_consume __ATOMIC_CONSUME
|
||||
#define memory_order_acquire __ATOMIC_ACQUIRE
|
||||
#define memory_order_release __ATOMIC_RELEASE
|
||||
#define memory_order_acq_rel __ATOMIC_ACQ_REL
|
||||
#define memory_order_seq_cst __ATOMIC_SEQ_CST
|
||||
#define zig_memory_order_relaxed __ATOMIC_RELAXED
|
||||
#define zig_memory_order_acquire __ATOMIC_ACQUIRE
|
||||
#define zig_memory_order_release __ATOMIC_RELEASE
|
||||
#define zig_memory_order_acq_rel __ATOMIC_ACQ_REL
|
||||
#define zig_memory_order_seq_cst __ATOMIC_SEQ_CST
|
||||
#define zig_atomic(Type) Type
|
||||
#define zig_cmpxchg_strong( obj, expected, desired, succ, fail, Type, ReprType) __atomic_compare_exchange(obj, &(expected), &(desired), false, succ, fail)
|
||||
#define zig_cmpxchg_weak( obj, expected, desired, succ, fail, Type, ReprType) __atomic_compare_exchange(obj, &(expected), &(desired), true, succ, fail)
|
||||
@ -3607,12 +3651,11 @@ typedef int zig_memory_order;
|
||||
#define zig_atomicrmw_xchg_float zig_atomicrmw_xchg
|
||||
#define zig_fence(order) __atomic_thread_fence(order)
|
||||
#elif _MSC_VER && (_M_IX86 || _M_X64)
|
||||
#define memory_order_relaxed 0
|
||||
#define memory_order_consume 1
|
||||
#define memory_order_acquire 2
|
||||
#define memory_order_release 3
|
||||
#define memory_order_acq_rel 4
|
||||
#define memory_order_seq_cst 5
|
||||
#define zig_memory_order_relaxed 0
|
||||
#define zig_memory_order_acquire 2
|
||||
#define zig_memory_order_release 3
|
||||
#define zig_memory_order_acq_rel 4
|
||||
#define zig_memory_order_seq_cst 5
|
||||
#define zig_atomic(Type) Type
|
||||
#define zig_cmpxchg_strong( obj, expected, desired, succ, fail, Type, ReprType) zig_msvc_cmpxchg_##Type(obj, &(expected), desired)
|
||||
#define zig_cmpxchg_weak( obj, expected, desired, succ, fail, Type, ReprType) zig_cmpxchg_strong(obj, expected, desired, succ, fail, Type, ReprType)
|
||||
@ -3634,12 +3677,11 @@ typedef int zig_memory_order;
|
||||
#endif
|
||||
/* TODO: _MSC_VER && (_M_ARM || _M_ARM64) */
|
||||
#else
|
||||
#define memory_order_relaxed 0
|
||||
#define memory_order_consume 1
|
||||
#define memory_order_acquire 2
|
||||
#define memory_order_release 3
|
||||
#define memory_order_acq_rel 4
|
||||
#define memory_order_seq_cst 5
|
||||
#define zig_memory_order_relaxed 0
|
||||
#define zig_memory_order_acquire 2
|
||||
#define zig_memory_order_release 3
|
||||
#define zig_memory_order_acq_rel 4
|
||||
#define zig_memory_order_seq_cst 5
|
||||
#define zig_atomic(Type) Type
|
||||
#define zig_cmpxchg_strong( obj, expected, desired, succ, fail, Type, ReprType) zig_atomics_unavailable
|
||||
#define zig_cmpxchg_weak( obj, expected, desired, succ, fail, Type, ReprType) zig_atomics_unavailable
|
||||
@ -3830,9 +3872,32 @@ static inline bool zig_msvc_cmpxchg_u128(zig_u128 volatile* obj, zig_u128* expec
|
||||
return _InterlockedCompareExchange128((__int64 volatile*)obj, (__int64)zig_hi_u128(desired), (__int64)zig_lo_u128(desired), (__int64*)expected);
|
||||
}
|
||||
|
||||
static inline zig_u128 zig_msvc_atomic_load_u128(zig_u128 volatile* obj) {
|
||||
zig_u128 expected = zig_make_u128(UINT64_C(0), UINT64_C(0));
|
||||
(void)zig_cmpxchg_strong(obj, expected, expected, zig_memory_order_seq_cst, zig_memory_order_seq_cst, u128, zig_u128);
|
||||
return expected;
|
||||
}
|
||||
|
||||
static inline void zig_msvc_atomic_store_u128(zig_u128 volatile* obj, zig_u128 arg) {
|
||||
zig_u128 expected = zig_make_u128(UINT64_C(0), UINT64_C(0));
|
||||
while (!zig_cmpxchg_weak(obj, expected, arg, zig_memory_order_seq_cst, zig_memory_order_seq_cst, u128, zig_u128));
|
||||
}
|
||||
|
||||
static inline bool zig_msvc_cmpxchg_i128(zig_i128 volatile* obj, zig_i128* expected, zig_i128 desired) {
|
||||
return _InterlockedCompareExchange128((__int64 volatile*)obj, (__int64)zig_hi_i128(desired), (__int64)zig_lo_i128(desired), (__int64*)expected);
|
||||
}
|
||||
|
||||
static inline zig_i128 zig_msvc_atomic_load_i128(zig_i128 volatile* obj) {
|
||||
zig_i128 expected = zig_make_i128(INT64_C(0), UINT64_C(0));
|
||||
(void)zig_cmpxchg_strong(obj, expected, expected, zig_memory_order_seq_cst, zig_memory_order_seq_cst, i128, zig_i128);
|
||||
return expected;
|
||||
}
|
||||
|
||||
static inline void zig_msvc_atomic_store_i128(zig_i128 volatile* obj, zig_i128 arg) {
|
||||
zig_i128 expected = zig_make_i128(INT64_C(0), UINT64_C(0));
|
||||
while (!zig_cmpxchg_weak(obj, expected, arg, zig_memory_order_seq_cst, zig_memory_order_seq_cst, i128, zig_i128));
|
||||
}
|
||||
|
||||
#endif /* _M_IX86 */
|
||||
|
||||
#endif /* _MSC_VER && (_M_IX86 || _M_X64) */
|
||||
|
||||
BIN
stage1/zig1.wasm
BIN
stage1/zig1.wasm
Binary file not shown.
@ -311,12 +311,6 @@ test "page aligned array on stack" {
|
||||
try expect(number2 == 43);
|
||||
}
|
||||
|
||||
fn derp() align(@sizeOf(usize) * 2) i32 {
|
||||
return 1234;
|
||||
}
|
||||
fn noop1() align(1) void {}
|
||||
fn noop4() align(4) void {}
|
||||
|
||||
test "function alignment" {
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
||||
@ -325,11 +319,25 @@ test "function alignment" {
|
||||
// function alignment is a compile error on wasm32/wasm64
|
||||
if (native_arch == .wasm32 or native_arch == .wasm64) return error.SkipZigTest;
|
||||
|
||||
try expect(derp() == 1234);
|
||||
try expect(@TypeOf(noop1) == fn () align(1) void);
|
||||
try expect(@TypeOf(noop4) == fn () align(4) void);
|
||||
noop1();
|
||||
noop4();
|
||||
const S = struct {
|
||||
fn alignExpr() align(@sizeOf(usize) * 2) i32 {
|
||||
return 1234;
|
||||
}
|
||||
fn align1() align(1) void {}
|
||||
fn align4() align(4) void {}
|
||||
};
|
||||
|
||||
try expect(S.alignExpr() == 1234);
|
||||
try expect(@TypeOf(S.alignExpr) == fn () i32);
|
||||
try expect(@TypeOf(&S.alignExpr) == *align(@sizeOf(usize) * 2) const fn () i32);
|
||||
|
||||
S.align1();
|
||||
try expect(@TypeOf(S.align1) == fn () void);
|
||||
try expect(@TypeOf(&S.align1) == *align(1) const fn () void);
|
||||
|
||||
S.align4();
|
||||
try expect(@TypeOf(S.align4) == fn () void);
|
||||
try expect(@TypeOf(&S.align4) == *align(4) const fn () void);
|
||||
}
|
||||
|
||||
test "implicitly decreasing fn alignment" {
|
||||
@ -345,7 +353,7 @@ test "implicitly decreasing fn alignment" {
|
||||
try testImplicitlyDecreaseFnAlign(alignedBig, 5678);
|
||||
}
|
||||
|
||||
fn testImplicitlyDecreaseFnAlign(ptr: *const fn () align(1) i32, answer: i32) !void {
|
||||
fn testImplicitlyDecreaseFnAlign(ptr: *align(1) const fn () i32, answer: i32) !void {
|
||||
try expect(ptr() == answer);
|
||||
}
|
||||
|
||||
@ -368,10 +376,10 @@ test "@alignCast functions" {
|
||||
|
||||
try expect(fnExpectsOnly1(simple4) == 0x19);
|
||||
}
|
||||
fn fnExpectsOnly1(ptr: *const fn () align(1) i32) i32 {
|
||||
fn fnExpectsOnly1(ptr: *align(1) const fn () i32) i32 {
|
||||
return fnExpects4(@alignCast(ptr));
|
||||
}
|
||||
fn fnExpects4(ptr: *const fn () align(4) i32) i32 {
|
||||
fn fnExpects4(ptr: *align(4) const fn () i32) i32 {
|
||||
return ptr();
|
||||
}
|
||||
fn simple4() align(4) i32 {
|
||||
|
||||
@ -527,7 +527,6 @@ test "Type.Fn" {
|
||||
{
|
||||
const fn_info = std.builtin.Type{ .Fn = .{
|
||||
.calling_convention = .C,
|
||||
.alignment = 0,
|
||||
.is_generic = false,
|
||||
.is_var_args = false,
|
||||
.return_type = void,
|
||||
@ -643,7 +642,6 @@ test "reified function type params initialized with field pointer" {
|
||||
const Bar = @Type(.{
|
||||
.Fn = .{
|
||||
.calling_convention = .Unspecified,
|
||||
.alignment = 0,
|
||||
.is_generic = false,
|
||||
.is_var_args = false,
|
||||
.return_type = void,
|
||||
|
||||
@ -356,16 +356,38 @@ test "type info: function type info" {
|
||||
}
|
||||
|
||||
fn testFunction() !void {
|
||||
const fn_info = @typeInfo(@TypeOf(typeInfoFoo));
|
||||
try expect(fn_info == .Fn);
|
||||
try expect(fn_info.Fn.alignment > 0);
|
||||
try expect(fn_info.Fn.calling_convention == .C);
|
||||
try expect(!fn_info.Fn.is_generic);
|
||||
try expect(fn_info.Fn.params.len == 2);
|
||||
try expect(fn_info.Fn.is_var_args);
|
||||
try expect(fn_info.Fn.return_type.? == usize);
|
||||
const fn_aligned_info = @typeInfo(@TypeOf(typeInfoFooAligned));
|
||||
try expect(fn_aligned_info.Fn.alignment == 4);
|
||||
const foo_fn_type = @TypeOf(typeInfoFoo);
|
||||
const foo_fn_info = @typeInfo(foo_fn_type);
|
||||
try expect(foo_fn_info.Fn.calling_convention == .C);
|
||||
try expect(!foo_fn_info.Fn.is_generic);
|
||||
try expect(foo_fn_info.Fn.params.len == 2);
|
||||
try expect(foo_fn_info.Fn.is_var_args);
|
||||
try expect(foo_fn_info.Fn.return_type.? == usize);
|
||||
const foo_ptr_fn_info = @typeInfo(@TypeOf(&typeInfoFoo));
|
||||
try expect(foo_ptr_fn_info.Pointer.size == .One);
|
||||
try expect(foo_ptr_fn_info.Pointer.is_const);
|
||||
try expect(!foo_ptr_fn_info.Pointer.is_volatile);
|
||||
try expect(foo_ptr_fn_info.Pointer.address_space == .generic);
|
||||
try expect(foo_ptr_fn_info.Pointer.child == foo_fn_type);
|
||||
try expect(!foo_ptr_fn_info.Pointer.is_allowzero);
|
||||
try expect(foo_ptr_fn_info.Pointer.sentinel == null);
|
||||
|
||||
const aligned_foo_fn_type = @TypeOf(typeInfoFooAligned);
|
||||
const aligned_foo_fn_info = @typeInfo(aligned_foo_fn_type);
|
||||
try expect(aligned_foo_fn_info.Fn.calling_convention == .C);
|
||||
try expect(!aligned_foo_fn_info.Fn.is_generic);
|
||||
try expect(aligned_foo_fn_info.Fn.params.len == 2);
|
||||
try expect(aligned_foo_fn_info.Fn.is_var_args);
|
||||
try expect(aligned_foo_fn_info.Fn.return_type.? == usize);
|
||||
const aligned_foo_ptr_fn_info = @typeInfo(@TypeOf(&typeInfoFooAligned));
|
||||
try expect(aligned_foo_ptr_fn_info.Pointer.size == .One);
|
||||
try expect(aligned_foo_ptr_fn_info.Pointer.is_const);
|
||||
try expect(!aligned_foo_ptr_fn_info.Pointer.is_volatile);
|
||||
try expect(aligned_foo_ptr_fn_info.Pointer.alignment == 4);
|
||||
try expect(aligned_foo_ptr_fn_info.Pointer.address_space == .generic);
|
||||
try expect(aligned_foo_ptr_fn_info.Pointer.child == aligned_foo_fn_type);
|
||||
try expect(!aligned_foo_ptr_fn_info.Pointer.is_allowzero);
|
||||
try expect(aligned_foo_ptr_fn_info.Pointer.sentinel == null);
|
||||
}
|
||||
|
||||
extern fn typeInfoFoo(a: usize, b: bool, ...) callconv(.C) usize;
|
||||
|
||||
@ -78,11 +78,9 @@ test "basic" {
|
||||
try expectEqualStrings("fn (comptime u32) void", @typeName(fn (comptime u32) void));
|
||||
try expectEqualStrings("fn (noalias []u8) void", @typeName(fn (noalias []u8) void));
|
||||
|
||||
try expectEqualStrings("fn () align(32) void", @typeName(fn () align(32) void));
|
||||
try expectEqualStrings("fn () callconv(.C) void", @typeName(fn () callconv(.C) void));
|
||||
try expectEqualStrings("fn () align(32) callconv(.C) void", @typeName(fn () align(32) callconv(.C) void));
|
||||
try expectEqualStrings("fn (...) align(32) callconv(.C) void", @typeName(fn (...) align(32) callconv(.C) void));
|
||||
try expectEqualStrings("fn (u32, ...) align(32) callconv(.C) void", @typeName(fn (u32, ...) align(32) callconv(.C) void));
|
||||
try expectEqualStrings("fn (...) callconv(.C) void", @typeName(fn (...) callconv(.C) void));
|
||||
try expectEqualStrings("fn (u32, ...) callconv(.C) void", @typeName(fn (u32, ...) callconv(.C) void));
|
||||
}
|
||||
|
||||
test "top level decl" {
|
||||
|
||||
@ -1,28 +1,16 @@
|
||||
comptime {
|
||||
var a: *align(2) @TypeOf(foo) = undefined;
|
||||
_ = &a;
|
||||
}
|
||||
fn foo() void {}
|
||||
fn align1() align(1) void {}
|
||||
fn align2() align(2) void {}
|
||||
|
||||
comptime {
|
||||
var a: *align(1) fn () void = undefined;
|
||||
_ = &a;
|
||||
}
|
||||
comptime {
|
||||
var a: *align(2) fn () align(2) void = undefined;
|
||||
_ = &a;
|
||||
}
|
||||
comptime {
|
||||
var a: *align(2) fn () void = undefined;
|
||||
_ = &a;
|
||||
}
|
||||
comptime {
|
||||
var a: *align(1) fn () align(2) void = undefined;
|
||||
_ = &a;
|
||||
_ = @as(*align(1) const fn () void, &align2);
|
||||
_ = @as(*align(1) const fn () void, &align1);
|
||||
_ = @as(*align(2) const fn () void, &align2);
|
||||
_ = @as(*align(2) const fn () void, &align1);
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :20:19: error: function pointer alignment disagrees with function alignment
|
||||
// :8:41: error: expected type '*align(2) const fn () void', found '*const fn () void'
|
||||
// :8:41: note: pointer alignment '1' cannot cast into pointer alignment '2'
|
||||
|
||||
@ -1,9 +0,0 @@
|
||||
comptime {
|
||||
const z: ?fn () !void = null;
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :2:21: error: function prototype may not have inferred error set
|
||||
25
test/cases/compile_errors/invalid_function_types.zig
Normal file
25
test/cases/compile_errors/invalid_function_types.zig
Normal file
@ -0,0 +1,25 @@
|
||||
comptime {
|
||||
_ = fn name() void;
|
||||
}
|
||||
comptime {
|
||||
_ = fn () align(128) void;
|
||||
}
|
||||
comptime {
|
||||
_ = fn () addrspace(.generic) void;
|
||||
}
|
||||
comptime {
|
||||
_ = fn () linksection("section") void;
|
||||
}
|
||||
comptime {
|
||||
_ = fn () !void;
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :2:12: error: function type cannot have a name
|
||||
// :5:21: error: function type cannot have an alignment
|
||||
// :8:26: error: function type cannot have an addrspace
|
||||
// :11:27: error: function type cannot have a linksection
|
||||
// :14:15: error: function type cannot have an inferred error set
|
||||
@ -1,7 +1,7 @@
|
||||
export fn entry() void {
|
||||
testImplicitlyDecreaseFnAlign(alignedSmall, 1234);
|
||||
}
|
||||
fn testImplicitlyDecreaseFnAlign(ptr: *const fn () align(8) i32, answer: i32) void {
|
||||
fn testImplicitlyDecreaseFnAlign(ptr: *align(8) const fn () i32, answer: i32) void {
|
||||
if (ptr() != answer) unreachable;
|
||||
}
|
||||
fn alignedSmall() align(4) i32 {
|
||||
@ -12,5 +12,5 @@ fn alignedSmall() align(4) i32 {
|
||||
// backend=stage2
|
||||
// target=x86_64-linux
|
||||
//
|
||||
// :2:35: error: expected type '*const fn () align(8) i32', found '*const fn () align(4) i32'
|
||||
// :2:35: error: expected type '*align(8) const fn () i32', found '*align(4) const fn () i32'
|
||||
// :2:35: note: pointer alignment '4' cannot cast into pointer alignment '8'
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
const Foo = @Type(.{
|
||||
.Fn = .{
|
||||
.calling_convention = .Unspecified,
|
||||
.alignment = 0,
|
||||
.is_generic = true,
|
||||
.is_var_args = false,
|
||||
.return_type = u0,
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
const Foo = @Type(.{
|
||||
.Fn = .{
|
||||
.calling_convention = .Unspecified,
|
||||
.alignment = 0,
|
||||
.is_generic = false,
|
||||
.is_var_args = true,
|
||||
.return_type = u0,
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
const Foo = @Type(.{
|
||||
.Fn = .{
|
||||
.calling_convention = .Unspecified,
|
||||
.alignment = 0,
|
||||
.is_generic = false,
|
||||
.is_var_args = false,
|
||||
.return_type = null,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user