stage2: fix incorrect spelling of AtomicOrder
This commit is contained in:
@@ -7322,7 +7322,7 @@ fn builtinCall(
|
||||
},
|
||||
} });
|
||||
const ptr = try expr(gz, scope, .{ .ty = ptr_type }, params[1]);
|
||||
const ordering = try expr(gz, scope, .{ .ty = .atomic_ordering_type }, params[2]);
|
||||
const ordering = try expr(gz, scope, .{ .ty = .atomic_order_type }, params[2]);
|
||||
const result = try gz.addPlNode(.atomic_load, node, Zir.Inst.Bin{
|
||||
.lhs = ptr,
|
||||
.rhs = ordering,
|
||||
@@ -7343,7 +7343,7 @@ fn builtinCall(
|
||||
const ptr = try expr(gz, scope, .{ .ty = ptr_type }, params[1]);
|
||||
const operation = try expr(gz, scope, .{ .ty = .atomic_rmw_op_type }, params[2]);
|
||||
const operand = try expr(gz, scope, .{ .ty = int_type }, params[3]);
|
||||
const ordering = try expr(gz, scope, .{ .ty = .atomic_ordering_type }, params[4]);
|
||||
const ordering = try expr(gz, scope, .{ .ty = .atomic_order_type }, params[4]);
|
||||
const result = try gz.addPlNode(.atomic_rmw, node, Zir.Inst.AtomicRmw{
|
||||
.ptr = ptr,
|
||||
.operation = operation,
|
||||
@@ -7365,7 +7365,7 @@ fn builtinCall(
|
||||
} });
|
||||
const ptr = try expr(gz, scope, .{ .ty = ptr_type }, params[1]);
|
||||
const operand = try expr(gz, scope, .{ .ty = int_type }, params[2]);
|
||||
const ordering = try expr(gz, scope, .{ .ty = .atomic_ordering_type }, params[3]);
|
||||
const ordering = try expr(gz, scope, .{ .ty = .atomic_order_type }, params[3]);
|
||||
const result = try gz.addPlNode(.atomic_store, node, Zir.Inst.AtomicStore{
|
||||
.ptr = ptr,
|
||||
.operand = operand,
|
||||
@@ -7553,11 +7553,11 @@ fn cmpxchg(
|
||||
} });
|
||||
const result = try gz.addPlNode(tag, node, Zir.Inst.Cmpxchg{
|
||||
// zig fmt: off
|
||||
.ptr = try expr(gz, scope, .{ .ty = ptr_type }, params[1]),
|
||||
.expected_value = try expr(gz, scope, .{ .ty = int_type }, params[2]),
|
||||
.new_value = try expr(gz, scope, .{ .ty = int_type }, params[3]),
|
||||
.success_order = try expr(gz, scope, .{ .ty = .atomic_ordering_type }, params[4]),
|
||||
.fail_order = try expr(gz, scope, .{ .ty = .atomic_ordering_type }, params[5]),
|
||||
.ptr = try expr(gz, scope, .{ .ty = ptr_type }, params[1]),
|
||||
.expected_value = try expr(gz, scope, .{ .ty = int_type }, params[2]),
|
||||
.new_value = try expr(gz, scope, .{ .ty = int_type }, params[3]),
|
||||
.success_order = try expr(gz, scope, .{ .ty = .atomic_order_type }, params[4]),
|
||||
.fail_order = try expr(gz, scope, .{ .ty = .atomic_order_type }, params[5]),
|
||||
// zig fmt: on
|
||||
});
|
||||
return rvalue(gz, rl, result, node);
|
||||
|
||||
@@ -9702,7 +9702,7 @@ fn resolveTypeFields(sema: *Sema, block: *Scope.Block, src: LazySrcLoc, ty: Type
|
||||
.type_info => return sema.resolveBuiltinTypeFields(block, src, "TypeInfo"),
|
||||
.extern_options => return sema.resolveBuiltinTypeFields(block, src, "ExternOptions"),
|
||||
.export_options => return sema.resolveBuiltinTypeFields(block, src, "ExportOptions"),
|
||||
.atomic_ordering => return sema.resolveBuiltinTypeFields(block, src, "AtomicOrdering"),
|
||||
.atomic_order => return sema.resolveBuiltinTypeFields(block, src, "AtomicOrder"),
|
||||
.atomic_rmw_op => return sema.resolveBuiltinTypeFields(block, src, "AtomicRmwOp"),
|
||||
.calling_convention => return sema.resolveBuiltinTypeFields(block, src, "CallingConvention"),
|
||||
.float_mode => return sema.resolveBuiltinTypeFields(block, src, "FloatMode"),
|
||||
@@ -10096,7 +10096,7 @@ fn typeHasOnePossibleValue(
|
||||
.var_args_param,
|
||||
.manyptr_u8,
|
||||
.manyptr_const_u8,
|
||||
.atomic_ordering,
|
||||
.atomic_order,
|
||||
.atomic_rmw_op,
|
||||
.calling_convention,
|
||||
.float_mode,
|
||||
@@ -10281,7 +10281,7 @@ pub fn addType(sema: *Sema, ty: Type) !Air.Inst.Ref {
|
||||
.@"null" => return .null_type,
|
||||
.@"undefined" => return .undefined_type,
|
||||
.enum_literal => return .enum_literal_type,
|
||||
.atomic_ordering => return .atomic_ordering_type,
|
||||
.atomic_order => return .atomic_order_type,
|
||||
.atomic_rmw_op => return .atomic_rmw_op_type,
|
||||
.calling_convention => return .calling_convention_type,
|
||||
.float_mode => return .float_mode_type,
|
||||
|
||||
@@ -1714,7 +1714,7 @@ pub const Inst = struct {
|
||||
null_type,
|
||||
undefined_type,
|
||||
enum_literal_type,
|
||||
atomic_ordering_type,
|
||||
atomic_order_type,
|
||||
atomic_rmw_op_type,
|
||||
calling_convention_type,
|
||||
float_mode_type,
|
||||
@@ -1961,9 +1961,9 @@ pub const Inst = struct {
|
||||
.ty = Type.initTag(.type),
|
||||
.val = Value.initTag(.manyptr_const_u8_type),
|
||||
},
|
||||
.atomic_ordering_type = .{
|
||||
.atomic_order_type = .{
|
||||
.ty = Type.initTag(.type),
|
||||
.val = Value.initTag(.atomic_ordering_type),
|
||||
.val = Value.initTag(.atomic_order_type),
|
||||
},
|
||||
.atomic_rmw_op_type = .{
|
||||
.ty = Type.initTag(.type),
|
||||
|
||||
38
src/type.zig
38
src/type.zig
@@ -124,7 +124,7 @@ pub const Type = extern union {
|
||||
.enum_full,
|
||||
.enum_nonexhaustive,
|
||||
.enum_simple,
|
||||
.atomic_ordering,
|
||||
.atomic_order,
|
||||
.atomic_rmw_op,
|
||||
.calling_convention,
|
||||
.float_mode,
|
||||
@@ -743,7 +743,7 @@ pub const Type = extern union {
|
||||
.empty_struct_literal,
|
||||
.manyptr_u8,
|
||||
.manyptr_const_u8,
|
||||
.atomic_ordering,
|
||||
.atomic_order,
|
||||
.atomic_rmw_op,
|
||||
.calling_convention,
|
||||
.float_mode,
|
||||
@@ -955,7 +955,7 @@ pub const Type = extern union {
|
||||
.single_const_pointer_to_comptime_int => return writer.writeAll("*const comptime_int"),
|
||||
.manyptr_u8 => return writer.writeAll("[*]u8"),
|
||||
.manyptr_const_u8 => return writer.writeAll("[*]const u8"),
|
||||
.atomic_ordering => return writer.writeAll("std.builtin.AtomicOrdering"),
|
||||
.atomic_order => return writer.writeAll("std.builtin.AtomicOrder"),
|
||||
.atomic_rmw_op => return writer.writeAll("std.builtin.AtomicRmwOp"),
|
||||
.calling_convention => return writer.writeAll("std.builtin.CallingConvention"),
|
||||
.float_mode => return writer.writeAll("std.builtin.FloatMode"),
|
||||
@@ -1183,7 +1183,7 @@ pub const Type = extern union {
|
||||
.@"anyframe",
|
||||
.@"null",
|
||||
.@"undefined",
|
||||
.atomic_ordering,
|
||||
.atomic_order,
|
||||
.atomic_rmw_op,
|
||||
.calling_convention,
|
||||
.float_mode,
|
||||
@@ -1298,7 +1298,7 @@ pub const Type = extern union {
|
||||
.enum_literal => return Value.initTag(.enum_literal_type),
|
||||
.manyptr_u8 => return Value.initTag(.manyptr_u8_type),
|
||||
.manyptr_const_u8 => return Value.initTag(.manyptr_const_u8_type),
|
||||
.atomic_ordering => return Value.initTag(.atomic_ordering_type),
|
||||
.atomic_order => return Value.initTag(.atomic_order_type),
|
||||
.atomic_rmw_op => return Value.initTag(.atomic_rmw_op_type),
|
||||
.calling_convention => return Value.initTag(.calling_convention_type),
|
||||
.float_mode => return Value.initTag(.float_mode_type),
|
||||
@@ -1359,7 +1359,7 @@ pub const Type = extern union {
|
||||
.error_set_inferred,
|
||||
.manyptr_u8,
|
||||
.manyptr_const_u8,
|
||||
.atomic_ordering,
|
||||
.atomic_order,
|
||||
.atomic_rmw_op,
|
||||
.calling_convention,
|
||||
.float_mode,
|
||||
@@ -1505,7 +1505,7 @@ pub const Type = extern union {
|
||||
.bool,
|
||||
.array_u8_sentinel_0,
|
||||
.array_u8,
|
||||
.atomic_ordering,
|
||||
.atomic_order,
|
||||
.atomic_rmw_op,
|
||||
.calling_convention,
|
||||
.float_mode,
|
||||
@@ -1727,7 +1727,7 @@ pub const Type = extern union {
|
||||
.u8,
|
||||
.i8,
|
||||
.bool,
|
||||
.atomic_ordering,
|
||||
.atomic_order,
|
||||
.atomic_rmw_op,
|
||||
.calling_convention,
|
||||
.float_mode,
|
||||
@@ -2011,7 +2011,7 @@ pub const Type = extern union {
|
||||
@panic("TODO bitSize error union");
|
||||
},
|
||||
|
||||
.atomic_ordering,
|
||||
.atomic_order,
|
||||
.atomic_rmw_op,
|
||||
.calling_convention,
|
||||
.float_mode,
|
||||
@@ -2725,7 +2725,7 @@ pub const Type = extern union {
|
||||
.var_args_param,
|
||||
.manyptr_u8,
|
||||
.manyptr_const_u8,
|
||||
.atomic_ordering,
|
||||
.atomic_order,
|
||||
.atomic_rmw_op,
|
||||
.calling_convention,
|
||||
.float_mode,
|
||||
@@ -2903,7 +2903,7 @@ pub const Type = extern union {
|
||||
const enum_simple = ty.castTag(.enum_simple).?.data;
|
||||
return enum_simple.fields.count();
|
||||
},
|
||||
.atomic_ordering,
|
||||
.atomic_order,
|
||||
.atomic_rmw_op,
|
||||
.calling_convention,
|
||||
.float_mode,
|
||||
@@ -2927,7 +2927,7 @@ pub const Type = extern union {
|
||||
const enum_simple = ty.castTag(.enum_simple).?.data;
|
||||
return enum_simple.fields.keys()[field_index];
|
||||
},
|
||||
.atomic_ordering,
|
||||
.atomic_order,
|
||||
.atomic_rmw_op,
|
||||
.calling_convention,
|
||||
.float_mode,
|
||||
@@ -2950,7 +2950,7 @@ pub const Type = extern union {
|
||||
const enum_simple = ty.castTag(.enum_simple).?.data;
|
||||
return enum_simple.fields.getIndex(field_name);
|
||||
},
|
||||
.atomic_ordering,
|
||||
.atomic_order,
|
||||
.atomic_rmw_op,
|
||||
.calling_convention,
|
||||
.float_mode,
|
||||
@@ -3003,7 +3003,7 @@ pub const Type = extern union {
|
||||
const tag_ty = Type.initPayload(&buffer.base);
|
||||
return S.fieldWithRange(tag_ty, enum_tag, fields_len);
|
||||
},
|
||||
.atomic_ordering,
|
||||
.atomic_order,
|
||||
.atomic_rmw_op,
|
||||
.calling_convention,
|
||||
.float_mode,
|
||||
@@ -3058,7 +3058,7 @@ pub const Type = extern union {
|
||||
const union_obj = ty.cast(Payload.Union).?.data;
|
||||
return union_obj.srcLoc();
|
||||
},
|
||||
.atomic_ordering,
|
||||
.atomic_order,
|
||||
.atomic_rmw_op,
|
||||
.calling_convention,
|
||||
.float_mode,
|
||||
@@ -3095,7 +3095,7 @@ pub const Type = extern union {
|
||||
return union_obj.owner_decl;
|
||||
},
|
||||
.@"opaque" => @panic("TODO"),
|
||||
.atomic_ordering,
|
||||
.atomic_order,
|
||||
.atomic_rmw_op,
|
||||
.calling_convention,
|
||||
.float_mode,
|
||||
@@ -3145,7 +3145,7 @@ pub const Type = extern union {
|
||||
const tag_ty = Type.initPayload(&buffer.base);
|
||||
return S.intInRange(tag_ty, int, fields_len);
|
||||
},
|
||||
.atomic_ordering,
|
||||
.atomic_order,
|
||||
.atomic_rmw_op,
|
||||
.calling_convention,
|
||||
.float_mode,
|
||||
@@ -3205,7 +3205,7 @@ pub const Type = extern union {
|
||||
@"null",
|
||||
@"undefined",
|
||||
enum_literal,
|
||||
atomic_ordering,
|
||||
atomic_order,
|
||||
atomic_rmw_op,
|
||||
calling_convention,
|
||||
float_mode,
|
||||
@@ -3328,7 +3328,7 @@ pub const Type = extern union {
|
||||
.empty_struct_literal,
|
||||
.manyptr_u8,
|
||||
.manyptr_const_u8,
|
||||
.atomic_ordering,
|
||||
.atomic_order,
|
||||
.atomic_rmw_op,
|
||||
.calling_convention,
|
||||
.float_mode,
|
||||
|
||||
@@ -60,7 +60,7 @@ pub const Value = extern union {
|
||||
null_type,
|
||||
undefined_type,
|
||||
enum_literal_type,
|
||||
atomic_ordering_type,
|
||||
atomic_order_type,
|
||||
atomic_rmw_op_type,
|
||||
calling_convention_type,
|
||||
float_mode_type,
|
||||
@@ -223,7 +223,7 @@ pub const Value = extern union {
|
||||
.abi_align_default,
|
||||
.manyptr_u8_type,
|
||||
.manyptr_const_u8_type,
|
||||
.atomic_ordering_type,
|
||||
.atomic_order_type,
|
||||
.atomic_rmw_op_type,
|
||||
.calling_convention_type,
|
||||
.float_mode_type,
|
||||
@@ -409,7 +409,7 @@ pub const Value = extern union {
|
||||
.abi_align_default,
|
||||
.manyptr_u8_type,
|
||||
.manyptr_const_u8_type,
|
||||
.atomic_ordering_type,
|
||||
.atomic_order_type,
|
||||
.atomic_rmw_op_type,
|
||||
.calling_convention_type,
|
||||
.float_mode_type,
|
||||
@@ -622,7 +622,7 @@ pub const Value = extern union {
|
||||
.enum_literal_type => return out_stream.writeAll("@Type(.EnumLiteral)"),
|
||||
.manyptr_u8_type => return out_stream.writeAll("[*]u8"),
|
||||
.manyptr_const_u8_type => return out_stream.writeAll("[*]const u8"),
|
||||
.atomic_ordering_type => return out_stream.writeAll("std.builtin.AtomicOrdering"),
|
||||
.atomic_order_type => return out_stream.writeAll("std.builtin.AtomicOrder"),
|
||||
.atomic_rmw_op_type => return out_stream.writeAll("std.builtin.AtomicRmwOp"),
|
||||
.calling_convention_type => return out_stream.writeAll("std.builtin.CallingConvention"),
|
||||
.float_mode_type => return out_stream.writeAll("std.builtin.FloatMode"),
|
||||
@@ -789,7 +789,7 @@ pub const Value = extern union {
|
||||
.enum_literal_type => Type.initTag(.enum_literal),
|
||||
.manyptr_u8_type => Type.initTag(.manyptr_u8),
|
||||
.manyptr_const_u8_type => Type.initTag(.manyptr_const_u8),
|
||||
.atomic_ordering_type => Type.initTag(.atomic_ordering),
|
||||
.atomic_order_type => Type.initTag(.atomic_order),
|
||||
.atomic_rmw_op_type => Type.initTag(.atomic_rmw_op),
|
||||
.calling_convention_type => Type.initTag(.calling_convention),
|
||||
.float_mode_type => Type.initTag(.float_mode),
|
||||
|
||||
@@ -11,6 +11,7 @@ test {
|
||||
_ = @import("behavior/cast.zig");
|
||||
_ = @import("behavior/array.zig");
|
||||
_ = @import("behavior/usingnamespace.zig");
|
||||
_ = @import("behavior/atomics.zig");
|
||||
|
||||
if (!builtin.zig_is_stage2) {
|
||||
// Tests that only pass for stage1.
|
||||
@@ -21,7 +22,7 @@ test {
|
||||
_ = @import("behavior/asm.zig");
|
||||
_ = @import("behavior/async_fn.zig");
|
||||
}
|
||||
_ = @import("behavior/atomics.zig");
|
||||
_ = @import("behavior/atomics_stage1.zig");
|
||||
_ = @import("behavior/await_struct.zig");
|
||||
_ = @import("behavior/bit_shifting.zig");
|
||||
_ = @import("behavior/bitcast.zig");
|
||||
|
||||
@@ -2,215 +2,3 @@ const std = @import("std");
|
||||
const expect = std.testing.expect;
|
||||
const expectEqual = std.testing.expectEqual;
|
||||
const builtin = @import("builtin");
|
||||
|
||||
test "cmpxchg" {
|
||||
try testCmpxchg();
|
||||
comptime try testCmpxchg();
|
||||
}
|
||||
|
||||
fn testCmpxchg() !void {
|
||||
var x: i32 = 1234;
|
||||
if (@cmpxchgWeak(i32, &x, 99, 5678, .SeqCst, .SeqCst)) |x1| {
|
||||
try expect(x1 == 1234);
|
||||
} else {
|
||||
@panic("cmpxchg should have failed");
|
||||
}
|
||||
|
||||
while (@cmpxchgWeak(i32, &x, 1234, 5678, .SeqCst, .SeqCst)) |x1| {
|
||||
try expect(x1 == 1234);
|
||||
}
|
||||
try expect(x == 5678);
|
||||
|
||||
try expect(@cmpxchgStrong(i32, &x, 5678, 42, .SeqCst, .SeqCst) == null);
|
||||
try expect(x == 42);
|
||||
}
|
||||
|
||||
test "fence" {
|
||||
var x: i32 = 1234;
|
||||
@fence(.SeqCst);
|
||||
x = 5678;
|
||||
}
|
||||
|
||||
test "atomicrmw and atomicload" {
|
||||
var data: u8 = 200;
|
||||
try testAtomicRmw(&data);
|
||||
try expect(data == 42);
|
||||
try testAtomicLoad(&data);
|
||||
}
|
||||
|
||||
fn testAtomicRmw(ptr: *u8) !void {
|
||||
const prev_value = @atomicRmw(u8, ptr, .Xchg, 42, .SeqCst);
|
||||
try expect(prev_value == 200);
|
||||
comptime {
|
||||
var x: i32 = 1234;
|
||||
const y: i32 = 12345;
|
||||
try expect(@atomicLoad(i32, &x, .SeqCst) == 1234);
|
||||
try expect(@atomicLoad(i32, &y, .SeqCst) == 12345);
|
||||
}
|
||||
}
|
||||
|
||||
fn testAtomicLoad(ptr: *u8) !void {
|
||||
const x = @atomicLoad(u8, ptr, .SeqCst);
|
||||
try expect(x == 42);
|
||||
}
|
||||
|
||||
test "cmpxchg with ptr" {
|
||||
var data1: i32 = 1234;
|
||||
var data2: i32 = 5678;
|
||||
var data3: i32 = 9101;
|
||||
var x: *i32 = &data1;
|
||||
if (@cmpxchgWeak(*i32, &x, &data2, &data3, .SeqCst, .SeqCst)) |x1| {
|
||||
try expect(x1 == &data1);
|
||||
} else {
|
||||
@panic("cmpxchg should have failed");
|
||||
}
|
||||
|
||||
while (@cmpxchgWeak(*i32, &x, &data1, &data3, .SeqCst, .SeqCst)) |x1| {
|
||||
try expect(x1 == &data1);
|
||||
}
|
||||
try expect(x == &data3);
|
||||
|
||||
try expect(@cmpxchgStrong(*i32, &x, &data3, &data2, .SeqCst, .SeqCst) == null);
|
||||
try expect(x == &data2);
|
||||
}
|
||||
|
||||
test "128-bit cmpxchg" {
|
||||
try test_u128_cmpxchg();
|
||||
comptime try test_u128_cmpxchg();
|
||||
}
|
||||
|
||||
fn test_u128_cmpxchg() !void {
|
||||
if (std.Target.current.cpu.arch != .x86_64) return error.SkipZigTest;
|
||||
if (comptime !std.Target.x86.featureSetHas(std.Target.current.cpu.features, .cx16)) return error.SkipZigTest;
|
||||
|
||||
var x: u128 = 1234;
|
||||
if (@cmpxchgWeak(u128, &x, 99, 5678, .SeqCst, .SeqCst)) |x1| {
|
||||
try expect(x1 == 1234);
|
||||
} else {
|
||||
@panic("cmpxchg should have failed");
|
||||
}
|
||||
|
||||
while (@cmpxchgWeak(u128, &x, 1234, 5678, .SeqCst, .SeqCst)) |x1| {
|
||||
try expect(x1 == 1234);
|
||||
}
|
||||
try expect(x == 5678);
|
||||
|
||||
try expect(@cmpxchgStrong(u128, &x, 5678, 42, .SeqCst, .SeqCst) == null);
|
||||
try expect(x == 42);
|
||||
}
|
||||
|
||||
test "cmpxchg with ignored result" {
|
||||
var x: i32 = 1234;
|
||||
|
||||
_ = @cmpxchgStrong(i32, &x, 1234, 5678, .Monotonic, .Monotonic);
|
||||
|
||||
try expectEqual(@as(i32, 5678), x);
|
||||
}
|
||||
|
||||
var a_global_variable = @as(u32, 1234);
|
||||
|
||||
test "cmpxchg on a global variable" {
|
||||
_ = @cmpxchgWeak(u32, &a_global_variable, 1234, 42, .Acquire, .Monotonic);
|
||||
try expectEqual(@as(u32, 42), a_global_variable);
|
||||
}
|
||||
|
||||
test "atomic load and rmw with enum" {
|
||||
const Value = enum(u8) {
|
||||
a,
|
||||
b,
|
||||
c,
|
||||
};
|
||||
var x = Value.a;
|
||||
|
||||
try expect(@atomicLoad(Value, &x, .SeqCst) != .b);
|
||||
|
||||
_ = @atomicRmw(Value, &x, .Xchg, .c, .SeqCst);
|
||||
try expect(@atomicLoad(Value, &x, .SeqCst) == .c);
|
||||
try expect(@atomicLoad(Value, &x, .SeqCst) != .a);
|
||||
try expect(@atomicLoad(Value, &x, .SeqCst) != .b);
|
||||
}
|
||||
|
||||
test "atomic store" {
|
||||
var x: u32 = 0;
|
||||
@atomicStore(u32, &x, 1, .SeqCst);
|
||||
try expect(@atomicLoad(u32, &x, .SeqCst) == 1);
|
||||
@atomicStore(u32, &x, 12345678, .SeqCst);
|
||||
try expect(@atomicLoad(u32, &x, .SeqCst) == 12345678);
|
||||
}
|
||||
|
||||
test "atomic store comptime" {
|
||||
comptime try testAtomicStore();
|
||||
try testAtomicStore();
|
||||
}
|
||||
|
||||
fn testAtomicStore() !void {
|
||||
var x: u32 = 0;
|
||||
@atomicStore(u32, &x, 1, .SeqCst);
|
||||
try expect(@atomicLoad(u32, &x, .SeqCst) == 1);
|
||||
@atomicStore(u32, &x, 12345678, .SeqCst);
|
||||
try expect(@atomicLoad(u32, &x, .SeqCst) == 12345678);
|
||||
}
|
||||
|
||||
test "atomicrmw with floats" {
|
||||
try testAtomicRmwFloat();
|
||||
comptime try testAtomicRmwFloat();
|
||||
}
|
||||
|
||||
fn testAtomicRmwFloat() !void {
|
||||
var x: f32 = 0;
|
||||
try expect(x == 0);
|
||||
_ = @atomicRmw(f32, &x, .Xchg, 1, .SeqCst);
|
||||
try expect(x == 1);
|
||||
_ = @atomicRmw(f32, &x, .Add, 5, .SeqCst);
|
||||
try expect(x == 6);
|
||||
_ = @atomicRmw(f32, &x, .Sub, 2, .SeqCst);
|
||||
try expect(x == 4);
|
||||
}
|
||||
|
||||
test "atomicrmw with ints" {
|
||||
try testAtomicRmwInt();
|
||||
comptime try testAtomicRmwInt();
|
||||
}
|
||||
|
||||
fn testAtomicRmwInt() !void {
|
||||
var x: u8 = 1;
|
||||
var res = @atomicRmw(u8, &x, .Xchg, 3, .SeqCst);
|
||||
try expect(x == 3 and res == 1);
|
||||
_ = @atomicRmw(u8, &x, .Add, 3, .SeqCst);
|
||||
try expect(x == 6);
|
||||
_ = @atomicRmw(u8, &x, .Sub, 1, .SeqCst);
|
||||
try expect(x == 5);
|
||||
_ = @atomicRmw(u8, &x, .And, 4, .SeqCst);
|
||||
try expect(x == 4);
|
||||
_ = @atomicRmw(u8, &x, .Nand, 4, .SeqCst);
|
||||
try expect(x == 0xfb);
|
||||
_ = @atomicRmw(u8, &x, .Or, 6, .SeqCst);
|
||||
try expect(x == 0xff);
|
||||
_ = @atomicRmw(u8, &x, .Xor, 2, .SeqCst);
|
||||
try expect(x == 0xfd);
|
||||
|
||||
_ = @atomicRmw(u8, &x, .Max, 1, .SeqCst);
|
||||
try expect(x == 0xfd);
|
||||
_ = @atomicRmw(u8, &x, .Min, 1, .SeqCst);
|
||||
try expect(x == 1);
|
||||
}
|
||||
|
||||
test "atomics with different types" {
|
||||
try testAtomicsWithType(bool, true, false);
|
||||
inline for (.{ u1, i4, u5, i15, u24 }) |T| {
|
||||
try testAtomicsWithType(T, 0, 1);
|
||||
}
|
||||
try testAtomicsWithType(u0, 0, 0);
|
||||
try testAtomicsWithType(i0, 0, 0);
|
||||
}
|
||||
|
||||
fn testAtomicsWithType(comptime T: type, a: T, b: T) !void {
|
||||
var x: T = b;
|
||||
@atomicStore(T, &x, a, .SeqCst);
|
||||
try expect(x == a);
|
||||
try expect(@atomicLoad(T, &x, .SeqCst) == a);
|
||||
try expect(@atomicRmw(T, &x, .Xchg, b, .SeqCst) == a);
|
||||
try expect(@cmpxchgStrong(T, &x, b, a, .SeqCst, .SeqCst) == null);
|
||||
if (@sizeOf(T) != 0)
|
||||
try expect(@cmpxchgStrong(T, &x, b, a, .SeqCst, .SeqCst).? == a);
|
||||
}
|
||||
|
||||
216
test/behavior/atomics_stage1.zig
Normal file
216
test/behavior/atomics_stage1.zig
Normal file
@@ -0,0 +1,216 @@
|
||||
const std = @import("std");
|
||||
const expect = std.testing.expect;
|
||||
const expectEqual = std.testing.expectEqual;
|
||||
const builtin = @import("builtin");
|
||||
|
||||
test "cmpxchg" {
|
||||
try testCmpxchg();
|
||||
comptime try testCmpxchg();
|
||||
}
|
||||
|
||||
fn testCmpxchg() !void {
|
||||
var x: i32 = 1234;
|
||||
if (@cmpxchgWeak(i32, &x, 99, 5678, .SeqCst, .SeqCst)) |x1| {
|
||||
try expect(x1 == 1234);
|
||||
} else {
|
||||
@panic("cmpxchg should have failed");
|
||||
}
|
||||
|
||||
while (@cmpxchgWeak(i32, &x, 1234, 5678, .SeqCst, .SeqCst)) |x1| {
|
||||
try expect(x1 == 1234);
|
||||
}
|
||||
try expect(x == 5678);
|
||||
|
||||
try expect(@cmpxchgStrong(i32, &x, 5678, 42, .SeqCst, .SeqCst) == null);
|
||||
try expect(x == 42);
|
||||
}
|
||||
|
||||
test "fence" {
|
||||
var x: i32 = 1234;
|
||||
@fence(.SeqCst);
|
||||
x = 5678;
|
||||
}
|
||||
|
||||
test "atomicrmw and atomicload" {
|
||||
var data: u8 = 200;
|
||||
try testAtomicRmw(&data);
|
||||
try expect(data == 42);
|
||||
try testAtomicLoad(&data);
|
||||
}
|
||||
|
||||
fn testAtomicRmw(ptr: *u8) !void {
|
||||
const prev_value = @atomicRmw(u8, ptr, .Xchg, 42, .SeqCst);
|
||||
try expect(prev_value == 200);
|
||||
comptime {
|
||||
var x: i32 = 1234;
|
||||
const y: i32 = 12345;
|
||||
try expect(@atomicLoad(i32, &x, .SeqCst) == 1234);
|
||||
try expect(@atomicLoad(i32, &y, .SeqCst) == 12345);
|
||||
}
|
||||
}
|
||||
|
||||
fn testAtomicLoad(ptr: *u8) !void {
|
||||
const x = @atomicLoad(u8, ptr, .SeqCst);
|
||||
try expect(x == 42);
|
||||
}
|
||||
|
||||
test "cmpxchg with ptr" {
|
||||
var data1: i32 = 1234;
|
||||
var data2: i32 = 5678;
|
||||
var data3: i32 = 9101;
|
||||
var x: *i32 = &data1;
|
||||
if (@cmpxchgWeak(*i32, &x, &data2, &data3, .SeqCst, .SeqCst)) |x1| {
|
||||
try expect(x1 == &data1);
|
||||
} else {
|
||||
@panic("cmpxchg should have failed");
|
||||
}
|
||||
|
||||
while (@cmpxchgWeak(*i32, &x, &data1, &data3, .SeqCst, .SeqCst)) |x1| {
|
||||
try expect(x1 == &data1);
|
||||
}
|
||||
try expect(x == &data3);
|
||||
|
||||
try expect(@cmpxchgStrong(*i32, &x, &data3, &data2, .SeqCst, .SeqCst) == null);
|
||||
try expect(x == &data2);
|
||||
}
|
||||
|
||||
test "128-bit cmpxchg" {
|
||||
try test_u128_cmpxchg();
|
||||
comptime try test_u128_cmpxchg();
|
||||
}
|
||||
|
||||
fn test_u128_cmpxchg() !void {
|
||||
if (std.Target.current.cpu.arch != .x86_64) return error.SkipZigTest;
|
||||
if (comptime !std.Target.x86.featureSetHas(std.Target.current.cpu.features, .cx16)) return error.SkipZigTest;
|
||||
|
||||
var x: u128 = 1234;
|
||||
if (@cmpxchgWeak(u128, &x, 99, 5678, .SeqCst, .SeqCst)) |x1| {
|
||||
try expect(x1 == 1234);
|
||||
} else {
|
||||
@panic("cmpxchg should have failed");
|
||||
}
|
||||
|
||||
while (@cmpxchgWeak(u128, &x, 1234, 5678, .SeqCst, .SeqCst)) |x1| {
|
||||
try expect(x1 == 1234);
|
||||
}
|
||||
try expect(x == 5678);
|
||||
|
||||
try expect(@cmpxchgStrong(u128, &x, 5678, 42, .SeqCst, .SeqCst) == null);
|
||||
try expect(x == 42);
|
||||
}
|
||||
|
||||
test "cmpxchg with ignored result" {
|
||||
var x: i32 = 1234;
|
||||
|
||||
_ = @cmpxchgStrong(i32, &x, 1234, 5678, .Monotonic, .Monotonic);
|
||||
|
||||
try expectEqual(@as(i32, 5678), x);
|
||||
}
|
||||
|
||||
var a_global_variable = @as(u32, 1234);
|
||||
|
||||
test "cmpxchg on a global variable" {
|
||||
_ = @cmpxchgWeak(u32, &a_global_variable, 1234, 42, .Acquire, .Monotonic);
|
||||
try expectEqual(@as(u32, 42), a_global_variable);
|
||||
}
|
||||
|
||||
test "atomic load and rmw with enum" {
|
||||
const Value = enum(u8) {
|
||||
a,
|
||||
b,
|
||||
c,
|
||||
};
|
||||
var x = Value.a;
|
||||
|
||||
try expect(@atomicLoad(Value, &x, .SeqCst) != .b);
|
||||
|
||||
_ = @atomicRmw(Value, &x, .Xchg, .c, .SeqCst);
|
||||
try expect(@atomicLoad(Value, &x, .SeqCst) == .c);
|
||||
try expect(@atomicLoad(Value, &x, .SeqCst) != .a);
|
||||
try expect(@atomicLoad(Value, &x, .SeqCst) != .b);
|
||||
}
|
||||
|
||||
test "atomic store" {
|
||||
var x: u32 = 0;
|
||||
@atomicStore(u32, &x, 1, .SeqCst);
|
||||
try expect(@atomicLoad(u32, &x, .SeqCst) == 1);
|
||||
@atomicStore(u32, &x, 12345678, .SeqCst);
|
||||
try expect(@atomicLoad(u32, &x, .SeqCst) == 12345678);
|
||||
}
|
||||
|
||||
test "atomic store comptime" {
|
||||
comptime try testAtomicStore();
|
||||
try testAtomicStore();
|
||||
}
|
||||
|
||||
fn testAtomicStore() !void {
|
||||
var x: u32 = 0;
|
||||
@atomicStore(u32, &x, 1, .SeqCst);
|
||||
try expect(@atomicLoad(u32, &x, .SeqCst) == 1);
|
||||
@atomicStore(u32, &x, 12345678, .SeqCst);
|
||||
try expect(@atomicLoad(u32, &x, .SeqCst) == 12345678);
|
||||
}
|
||||
|
||||
test "atomicrmw with floats" {
|
||||
try testAtomicRmwFloat();
|
||||
comptime try testAtomicRmwFloat();
|
||||
}
|
||||
|
||||
fn testAtomicRmwFloat() !void {
|
||||
var x: f32 = 0;
|
||||
try expect(x == 0);
|
||||
_ = @atomicRmw(f32, &x, .Xchg, 1, .SeqCst);
|
||||
try expect(x == 1);
|
||||
_ = @atomicRmw(f32, &x, .Add, 5, .SeqCst);
|
||||
try expect(x == 6);
|
||||
_ = @atomicRmw(f32, &x, .Sub, 2, .SeqCst);
|
||||
try expect(x == 4);
|
||||
}
|
||||
|
||||
test "atomicrmw with ints" {
|
||||
try testAtomicRmwInt();
|
||||
comptime try testAtomicRmwInt();
|
||||
}
|
||||
|
||||
fn testAtomicRmwInt() !void {
|
||||
var x: u8 = 1;
|
||||
var res = @atomicRmw(u8, &x, .Xchg, 3, .SeqCst);
|
||||
try expect(x == 3 and res == 1);
|
||||
_ = @atomicRmw(u8, &x, .Add, 3, .SeqCst);
|
||||
try expect(x == 6);
|
||||
_ = @atomicRmw(u8, &x, .Sub, 1, .SeqCst);
|
||||
try expect(x == 5);
|
||||
_ = @atomicRmw(u8, &x, .And, 4, .SeqCst);
|
||||
try expect(x == 4);
|
||||
_ = @atomicRmw(u8, &x, .Nand, 4, .SeqCst);
|
||||
try expect(x == 0xfb);
|
||||
_ = @atomicRmw(u8, &x, .Or, 6, .SeqCst);
|
||||
try expect(x == 0xff);
|
||||
_ = @atomicRmw(u8, &x, .Xor, 2, .SeqCst);
|
||||
try expect(x == 0xfd);
|
||||
|
||||
_ = @atomicRmw(u8, &x, .Max, 1, .SeqCst);
|
||||
try expect(x == 0xfd);
|
||||
_ = @atomicRmw(u8, &x, .Min, 1, .SeqCst);
|
||||
try expect(x == 1);
|
||||
}
|
||||
|
||||
test "atomics with different types" {
|
||||
try testAtomicsWithType(bool, true, false);
|
||||
inline for (.{ u1, i4, u5, i15, u24 }) |T| {
|
||||
try testAtomicsWithType(T, 0, 1);
|
||||
}
|
||||
try testAtomicsWithType(u0, 0, 0);
|
||||
try testAtomicsWithType(i0, 0, 0);
|
||||
}
|
||||
|
||||
fn testAtomicsWithType(comptime T: type, a: T, b: T) !void {
|
||||
var x: T = b;
|
||||
@atomicStore(T, &x, a, .SeqCst);
|
||||
try expect(x == a);
|
||||
try expect(@atomicLoad(T, &x, .SeqCst) == a);
|
||||
try expect(@atomicRmw(T, &x, .Xchg, b, .SeqCst) == a);
|
||||
try expect(@cmpxchgStrong(T, &x, b, a, .SeqCst, .SeqCst) == null);
|
||||
if (@sizeOf(T) != 0)
|
||||
try expect(@cmpxchgStrong(T, &x, b, a, .SeqCst, .SeqCst).? == a);
|
||||
}
|
||||
Reference in New Issue
Block a user