| author | |
| committer | |
| log | 264acfdf3caef663cddc39c2bf83818abb0e0073 |
| tree | 26f3019c76b210d3c501745298991d2c8cea18f2 |
| parent | 97d69e3352ab50f88580c383b5f375b0edadacfd |
8 files changed, 256 insertions(+), 251 deletions(-)
src/AstGen.zig+8-8| ... | ... | @@ -7322,7 +7322,7 @@ fn builtinCall( |
| 7322 | 7322 | }, |
| 7323 | 7323 | } }); |
| 7324 | 7324 | const ptr = try expr(gz, scope, .{ .ty = ptr_type }, params[1]); |
| 7325 | const ordering = try expr(gz, scope, .{ .ty = .atomic_ordering_type }, params[2]); | |
| 7325 | const ordering = try expr(gz, scope, .{ .ty = .atomic_order_type }, params[2]); | |
| 7326 | 7326 | const result = try gz.addPlNode(.atomic_load, node, Zir.Inst.Bin{ |
| 7327 | 7327 | .lhs = ptr, |
| 7328 | 7328 | .rhs = ordering, |
| ... | ... | @@ -7343,7 +7343,7 @@ fn builtinCall( |
| 7343 | 7343 | const ptr = try expr(gz, scope, .{ .ty = ptr_type }, params[1]); |
| 7344 | 7344 | const operation = try expr(gz, scope, .{ .ty = .atomic_rmw_op_type }, params[2]); |
| 7345 | 7345 | const operand = try expr(gz, scope, .{ .ty = int_type }, params[3]); |
| 7346 | const ordering = try expr(gz, scope, .{ .ty = .atomic_ordering_type }, params[4]); | |
| 7346 | const ordering = try expr(gz, scope, .{ .ty = .atomic_order_type }, params[4]); | |
| 7347 | 7347 | const result = try gz.addPlNode(.atomic_rmw, node, Zir.Inst.AtomicRmw{ |
| 7348 | 7348 | .ptr = ptr, |
| 7349 | 7349 | .operation = operation, |
| ... | ... | @@ -7365,7 +7365,7 @@ fn builtinCall( |
| 7365 | 7365 | } }); |
| 7366 | 7366 | const ptr = try expr(gz, scope, .{ .ty = ptr_type }, params[1]); |
| 7367 | 7367 | const operand = try expr(gz, scope, .{ .ty = int_type }, params[2]); |
| 7368 | const ordering = try expr(gz, scope, .{ .ty = .atomic_ordering_type }, params[3]); | |
| 7368 | const ordering = try expr(gz, scope, .{ .ty = .atomic_order_type }, params[3]); | |
| 7369 | 7369 | const result = try gz.addPlNode(.atomic_store, node, Zir.Inst.AtomicStore{ |
| 7370 | 7370 | .ptr = ptr, |
| 7371 | 7371 | .operand = operand, |
| ... | ... | @@ -7553,11 +7553,11 @@ fn cmpxchg( |
| 7553 | 7553 | } }); |
| 7554 | 7554 | const result = try gz.addPlNode(tag, node, Zir.Inst.Cmpxchg{ |
| 7555 | 7555 | // zig fmt: off |
| 7556 | .ptr = try expr(gz, scope, .{ .ty = ptr_type }, params[1]), | |
| 7557 | .expected_value = try expr(gz, scope, .{ .ty = int_type }, params[2]), | |
| 7558 | .new_value = try expr(gz, scope, .{ .ty = int_type }, params[3]), | |
| 7559 | .success_order = try expr(gz, scope, .{ .ty = .atomic_ordering_type }, params[4]), | |
| 7560 | .fail_order = try expr(gz, scope, .{ .ty = .atomic_ordering_type }, params[5]), | |
| 7556 | .ptr = try expr(gz, scope, .{ .ty = ptr_type }, params[1]), | |
| 7557 | .expected_value = try expr(gz, scope, .{ .ty = int_type }, params[2]), | |
| 7558 | .new_value = try expr(gz, scope, .{ .ty = int_type }, params[3]), | |
| 7559 | .success_order = try expr(gz, scope, .{ .ty = .atomic_order_type }, params[4]), | |
| 7560 | .fail_order = try expr(gz, scope, .{ .ty = .atomic_order_type }, params[5]), | |
| 7561 | 7561 | // zig fmt: on |
| 7562 | 7562 | }); |
| 7563 | 7563 | return rvalue(gz, rl, result, node); |
src/Sema.zig+3-3| ... | ... | @@ -9702,7 +9702,7 @@ fn resolveTypeFields(sema: *Sema, block: *Scope.Block, src: LazySrcLoc, ty: Type |
| 9702 | 9702 | .type_info => return sema.resolveBuiltinTypeFields(block, src, "TypeInfo"), |
| 9703 | 9703 | .extern_options => return sema.resolveBuiltinTypeFields(block, src, "ExternOptions"), |
| 9704 | 9704 | .export_options => return sema.resolveBuiltinTypeFields(block, src, "ExportOptions"), |
| 9705 | .atomic_ordering => return sema.resolveBuiltinTypeFields(block, src, "AtomicOrdering"), | |
| 9705 | .atomic_order => return sema.resolveBuiltinTypeFields(block, src, "AtomicOrder"), | |
| 9706 | 9706 | .atomic_rmw_op => return sema.resolveBuiltinTypeFields(block, src, "AtomicRmwOp"), |
| 9707 | 9707 | .calling_convention => return sema.resolveBuiltinTypeFields(block, src, "CallingConvention"), |
| 9708 | 9708 | .float_mode => return sema.resolveBuiltinTypeFields(block, src, "FloatMode"), |
| ... | ... | @@ -10096,7 +10096,7 @@ fn typeHasOnePossibleValue( |
| 10096 | 10096 | .var_args_param, |
| 10097 | 10097 | .manyptr_u8, |
| 10098 | 10098 | .manyptr_const_u8, |
| 10099 | .atomic_ordering, | |
| 10099 | .atomic_order, | |
| 10100 | 10100 | .atomic_rmw_op, |
| 10101 | 10101 | .calling_convention, |
| 10102 | 10102 | .float_mode, |
| ... | ... | @@ -10281,7 +10281,7 @@ pub fn addType(sema: *Sema, ty: Type) !Air.Inst.Ref { |
| 10281 | 10281 | .@"null" => return .null_type, |
| 10282 | 10282 | .@"undefined" => return .undefined_type, |
| 10283 | 10283 | .enum_literal => return .enum_literal_type, |
| 10284 | .atomic_ordering => return .atomic_ordering_type, | |
| 10284 | .atomic_order => return .atomic_order_type, | |
| 10285 | 10285 | .atomic_rmw_op => return .atomic_rmw_op_type, |
| 10286 | 10286 | .calling_convention => return .calling_convention_type, |
| 10287 | 10287 | .float_mode => return .float_mode_type, |
src/Zir.zig+3-3| ... | ... | @@ -1714,7 +1714,7 @@ pub const Inst = struct { |
| 1714 | 1714 | null_type, |
| 1715 | 1715 | undefined_type, |
| 1716 | 1716 | enum_literal_type, |
| 1717 | atomic_ordering_type, | |
| 1717 | atomic_order_type, | |
| 1718 | 1718 | atomic_rmw_op_type, |
| 1719 | 1719 | calling_convention_type, |
| 1720 | 1720 | float_mode_type, |
| ... | ... | @@ -1961,9 +1961,9 @@ pub const Inst = struct { |
| 1961 | 1961 | .ty = Type.initTag(.type), |
| 1962 | 1962 | .val = Value.initTag(.manyptr_const_u8_type), |
| 1963 | 1963 | }, |
| 1964 | .atomic_ordering_type = .{ | |
| 1964 | .atomic_order_type = .{ | |
| 1965 | 1965 | .ty = Type.initTag(.type), |
| 1966 | .val = Value.initTag(.atomic_ordering_type), | |
| 1966 | .val = Value.initTag(.atomic_order_type), | |
| 1967 | 1967 | }, |
| 1968 | 1968 | .atomic_rmw_op_type = .{ |
| 1969 | 1969 | .ty = Type.initTag(.type), |
src/type.zig+19-19| ... | ... | @@ -124,7 +124,7 @@ pub const Type = extern union { |
| 124 | 124 | .enum_full, |
| 125 | 125 | .enum_nonexhaustive, |
| 126 | 126 | .enum_simple, |
| 127 | .atomic_ordering, | |
| 127 | .atomic_order, | |
| 128 | 128 | .atomic_rmw_op, |
| 129 | 129 | .calling_convention, |
| 130 | 130 | .float_mode, |
| ... | ... | @@ -743,7 +743,7 @@ pub const Type = extern union { |
| 743 | 743 | .empty_struct_literal, |
| 744 | 744 | .manyptr_u8, |
| 745 | 745 | .manyptr_const_u8, |
| 746 | .atomic_ordering, | |
| 746 | .atomic_order, | |
| 747 | 747 | .atomic_rmw_op, |
| 748 | 748 | .calling_convention, |
| 749 | 749 | .float_mode, |
| ... | ... | @@ -955,7 +955,7 @@ pub const Type = extern union { |
| 955 | 955 | .single_const_pointer_to_comptime_int => return writer.writeAll("*const comptime_int"), |
| 956 | 956 | .manyptr_u8 => return writer.writeAll("[*]u8"), |
| 957 | 957 | .manyptr_const_u8 => return writer.writeAll("[*]const u8"), |
| 958 | .atomic_ordering => return writer.writeAll("std.builtin.AtomicOrdering"), | |
| 958 | .atomic_order => return writer.writeAll("std.builtin.AtomicOrder"), | |
| 959 | 959 | .atomic_rmw_op => return writer.writeAll("std.builtin.AtomicRmwOp"), |
| 960 | 960 | .calling_convention => return writer.writeAll("std.builtin.CallingConvention"), |
| 961 | 961 | .float_mode => return writer.writeAll("std.builtin.FloatMode"), |
| ... | ... | @@ -1183,7 +1183,7 @@ pub const Type = extern union { |
| 1183 | 1183 | .@"anyframe", |
| 1184 | 1184 | .@"null", |
| 1185 | 1185 | .@"undefined", |
| 1186 | .atomic_ordering, | |
| 1186 | .atomic_order, | |
| 1187 | 1187 | .atomic_rmw_op, |
| 1188 | 1188 | .calling_convention, |
| 1189 | 1189 | .float_mode, |
| ... | ... | @@ -1298,7 +1298,7 @@ pub const Type = extern union { |
| 1298 | 1298 | .enum_literal => return Value.initTag(.enum_literal_type), |
| 1299 | 1299 | .manyptr_u8 => return Value.initTag(.manyptr_u8_type), |
| 1300 | 1300 | .manyptr_const_u8 => return Value.initTag(.manyptr_const_u8_type), |
| 1301 | .atomic_ordering => return Value.initTag(.atomic_ordering_type), | |
| 1301 | .atomic_order => return Value.initTag(.atomic_order_type), | |
| 1302 | 1302 | .atomic_rmw_op => return Value.initTag(.atomic_rmw_op_type), |
| 1303 | 1303 | .calling_convention => return Value.initTag(.calling_convention_type), |
| 1304 | 1304 | .float_mode => return Value.initTag(.float_mode_type), |
| ... | ... | @@ -1359,7 +1359,7 @@ pub const Type = extern union { |
| 1359 | 1359 | .error_set_inferred, |
| 1360 | 1360 | .manyptr_u8, |
| 1361 | 1361 | .manyptr_const_u8, |
| 1362 | .atomic_ordering, | |
| 1362 | .atomic_order, | |
| 1363 | 1363 | .atomic_rmw_op, |
| 1364 | 1364 | .calling_convention, |
| 1365 | 1365 | .float_mode, |
| ... | ... | @@ -1505,7 +1505,7 @@ pub const Type = extern union { |
| 1505 | 1505 | .bool, |
| 1506 | 1506 | .array_u8_sentinel_0, |
| 1507 | 1507 | .array_u8, |
| 1508 | .atomic_ordering, | |
| 1508 | .atomic_order, | |
| 1509 | 1509 | .atomic_rmw_op, |
| 1510 | 1510 | .calling_convention, |
| 1511 | 1511 | .float_mode, |
| ... | ... | @@ -1727,7 +1727,7 @@ pub const Type = extern union { |
| 1727 | 1727 | .u8, |
| 1728 | 1728 | .i8, |
| 1729 | 1729 | .bool, |
| 1730 | .atomic_ordering, | |
| 1730 | .atomic_order, | |
| 1731 | 1731 | .atomic_rmw_op, |
| 1732 | 1732 | .calling_convention, |
| 1733 | 1733 | .float_mode, |
| ... | ... | @@ -2011,7 +2011,7 @@ pub const Type = extern union { |
| 2011 | 2011 | @panic("TODO bitSize error union"); |
| 2012 | 2012 | }, |
| 2013 | 2013 | |
| 2014 | .atomic_ordering, | |
| 2014 | .atomic_order, | |
| 2015 | 2015 | .atomic_rmw_op, |
| 2016 | 2016 | .calling_convention, |
| 2017 | 2017 | .float_mode, |
| ... | ... | @@ -2725,7 +2725,7 @@ pub const Type = extern union { |
| 2725 | 2725 | .var_args_param, |
| 2726 | 2726 | .manyptr_u8, |
| 2727 | 2727 | .manyptr_const_u8, |
| 2728 | .atomic_ordering, | |
| 2728 | .atomic_order, | |
| 2729 | 2729 | .atomic_rmw_op, |
| 2730 | 2730 | .calling_convention, |
| 2731 | 2731 | .float_mode, |
| ... | ... | @@ -2903,7 +2903,7 @@ pub const Type = extern union { |
| 2903 | 2903 | const enum_simple = ty.castTag(.enum_simple).?.data; |
| 2904 | 2904 | return enum_simple.fields.count(); |
| 2905 | 2905 | }, |
| 2906 | .atomic_ordering, | |
| 2906 | .atomic_order, | |
| 2907 | 2907 | .atomic_rmw_op, |
| 2908 | 2908 | .calling_convention, |
| 2909 | 2909 | .float_mode, |
| ... | ... | @@ -2927,7 +2927,7 @@ pub const Type = extern union { |
| 2927 | 2927 | const enum_simple = ty.castTag(.enum_simple).?.data; |
| 2928 | 2928 | return enum_simple.fields.keys()[field_index]; |
| 2929 | 2929 | }, |
| 2930 | .atomic_ordering, | |
| 2930 | .atomic_order, | |
| 2931 | 2931 | .atomic_rmw_op, |
| 2932 | 2932 | .calling_convention, |
| 2933 | 2933 | .float_mode, |
| ... | ... | @@ -2950,7 +2950,7 @@ pub const Type = extern union { |
| 2950 | 2950 | const enum_simple = ty.castTag(.enum_simple).?.data; |
| 2951 | 2951 | return enum_simple.fields.getIndex(field_name); |
| 2952 | 2952 | }, |
| 2953 | .atomic_ordering, | |
| 2953 | .atomic_order, | |
| 2954 | 2954 | .atomic_rmw_op, |
| 2955 | 2955 | .calling_convention, |
| 2956 | 2956 | .float_mode, |
| ... | ... | @@ -3003,7 +3003,7 @@ pub const Type = extern union { |
| 3003 | 3003 | const tag_ty = Type.initPayload(&buffer.base); |
| 3004 | 3004 | return S.fieldWithRange(tag_ty, enum_tag, fields_len); |
| 3005 | 3005 | }, |
| 3006 | .atomic_ordering, | |
| 3006 | .atomic_order, | |
| 3007 | 3007 | .atomic_rmw_op, |
| 3008 | 3008 | .calling_convention, |
| 3009 | 3009 | .float_mode, |
| ... | ... | @@ -3058,7 +3058,7 @@ pub const Type = extern union { |
| 3058 | 3058 | const union_obj = ty.cast(Payload.Union).?.data; |
| 3059 | 3059 | return union_obj.srcLoc(); |
| 3060 | 3060 | }, |
| 3061 | .atomic_ordering, | |
| 3061 | .atomic_order, | |
| 3062 | 3062 | .atomic_rmw_op, |
| 3063 | 3063 | .calling_convention, |
| 3064 | 3064 | .float_mode, |
| ... | ... | @@ -3095,7 +3095,7 @@ pub const Type = extern union { |
| 3095 | 3095 | return union_obj.owner_decl; |
| 3096 | 3096 | }, |
| 3097 | 3097 | .@"opaque" => @panic("TODO"), |
| 3098 | .atomic_ordering, | |
| 3098 | .atomic_order, | |
| 3099 | 3099 | .atomic_rmw_op, |
| 3100 | 3100 | .calling_convention, |
| 3101 | 3101 | .float_mode, |
| ... | ... | @@ -3145,7 +3145,7 @@ pub const Type = extern union { |
| 3145 | 3145 | const tag_ty = Type.initPayload(&buffer.base); |
| 3146 | 3146 | return S.intInRange(tag_ty, int, fields_len); |
| 3147 | 3147 | }, |
| 3148 | .atomic_ordering, | |
| 3148 | .atomic_order, | |
| 3149 | 3149 | .atomic_rmw_op, |
| 3150 | 3150 | .calling_convention, |
| 3151 | 3151 | .float_mode, |
| ... | ... | @@ -3205,7 +3205,7 @@ pub const Type = extern union { |
| 3205 | 3205 | @"null", |
| 3206 | 3206 | @"undefined", |
| 3207 | 3207 | enum_literal, |
| 3208 | atomic_ordering, | |
| 3208 | atomic_order, | |
| 3209 | 3209 | atomic_rmw_op, |
| 3210 | 3210 | calling_convention, |
| 3211 | 3211 | float_mode, |
| ... | ... | @@ -3328,7 +3328,7 @@ pub const Type = extern union { |
| 3328 | 3328 | .empty_struct_literal, |
| 3329 | 3329 | .manyptr_u8, |
| 3330 | 3330 | .manyptr_const_u8, |
| 3331 | .atomic_ordering, | |
| 3331 | .atomic_order, | |
| 3332 | 3332 | .atomic_rmw_op, |
| 3333 | 3333 | .calling_convention, |
| 3334 | 3334 | .float_mode, |
src/value.zig+5-5| ... | ... | @@ -60,7 +60,7 @@ pub const Value = extern union { |
| 60 | 60 | null_type, |
| 61 | 61 | undefined_type, |
| 62 | 62 | enum_literal_type, |
| 63 | atomic_ordering_type, | |
| 63 | atomic_order_type, | |
| 64 | 64 | atomic_rmw_op_type, |
| 65 | 65 | calling_convention_type, |
| 66 | 66 | float_mode_type, |
| ... | ... | @@ -223,7 +223,7 @@ pub const Value = extern union { |
| 223 | 223 | .abi_align_default, |
| 224 | 224 | .manyptr_u8_type, |
| 225 | 225 | .manyptr_const_u8_type, |
| 226 | .atomic_ordering_type, | |
| 226 | .atomic_order_type, | |
| 227 | 227 | .atomic_rmw_op_type, |
| 228 | 228 | .calling_convention_type, |
| 229 | 229 | .float_mode_type, |
| ... | ... | @@ -409,7 +409,7 @@ pub const Value = extern union { |
| 409 | 409 | .abi_align_default, |
| 410 | 410 | .manyptr_u8_type, |
| 411 | 411 | .manyptr_const_u8_type, |
| 412 | .atomic_ordering_type, | |
| 412 | .atomic_order_type, | |
| 413 | 413 | .atomic_rmw_op_type, |
| 414 | 414 | .calling_convention_type, |
| 415 | 415 | .float_mode_type, |
| ... | ... | @@ -622,7 +622,7 @@ pub const Value = extern union { |
| 622 | 622 | .enum_literal_type => return out_stream.writeAll("@Type(.EnumLiteral)"), |
| 623 | 623 | .manyptr_u8_type => return out_stream.writeAll("[*]u8"), |
| 624 | 624 | .manyptr_const_u8_type => return out_stream.writeAll("[*]const u8"), |
| 625 | .atomic_ordering_type => return out_stream.writeAll("std.builtin.AtomicOrdering"), | |
| 625 | .atomic_order_type => return out_stream.writeAll("std.builtin.AtomicOrder"), | |
| 626 | 626 | .atomic_rmw_op_type => return out_stream.writeAll("std.builtin.AtomicRmwOp"), |
| 627 | 627 | .calling_convention_type => return out_stream.writeAll("std.builtin.CallingConvention"), |
| 628 | 628 | .float_mode_type => return out_stream.writeAll("std.builtin.FloatMode"), |
| ... | ... | @@ -789,7 +789,7 @@ pub const Value = extern union { |
| 789 | 789 | .enum_literal_type => Type.initTag(.enum_literal), |
| 790 | 790 | .manyptr_u8_type => Type.initTag(.manyptr_u8), |
| 791 | 791 | .manyptr_const_u8_type => Type.initTag(.manyptr_const_u8), |
| 792 | .atomic_ordering_type => Type.initTag(.atomic_ordering), | |
| 792 | .atomic_order_type => Type.initTag(.atomic_order), | |
| 793 | 793 | .atomic_rmw_op_type => Type.initTag(.atomic_rmw_op), |
| 794 | 794 | .calling_convention_type => Type.initTag(.calling_convention), |
| 795 | 795 | .float_mode_type => Type.initTag(.float_mode), |
test/behavior.zig+2-1| ... | ... | @@ -11,6 +11,7 @@ test { |
| 11 | 11 | _ = @import("behavior/cast.zig"); |
| 12 | 12 | _ = @import("behavior/array.zig"); |
| 13 | 13 | _ = @import("behavior/usingnamespace.zig"); |
| 14 | _ = @import("behavior/atomics.zig"); | |
| 14 | 15 | |
| 15 | 16 | if (!builtin.zig_is_stage2) { |
| 16 | 17 | // Tests that only pass for stage1. |
| ... | ... | @@ -21,7 +22,7 @@ test { |
| 21 | 22 | _ = @import("behavior/asm.zig"); |
| 22 | 23 | _ = @import("behavior/async_fn.zig"); |
| 23 | 24 | } |
| 24 | _ = @import("behavior/atomics.zig"); | |
| 25 | _ = @import("behavior/atomics_stage1.zig"); | |
| 25 | 26 | _ = @import("behavior/await_struct.zig"); |
| 26 | 27 | _ = @import("behavior/bit_shifting.zig"); |
| 27 | 28 | _ = @import("behavior/bitcast.zig"); |
test/behavior/atomics.zig-212| ... | ... | @@ -2,215 +2,3 @@ const std = @import("std"); |
| 2 | 2 | const expect = std.testing.expect; |
| 3 | 3 | const expectEqual = std.testing.expectEqual; |
| 4 | 4 | const builtin = @import("builtin"); |
| 5 | ||
| 6 | test "cmpxchg" { | |
| 7 | try testCmpxchg(); | |
| 8 | comptime try testCmpxchg(); | |
| 9 | } | |
| 10 | ||
| 11 | fn testCmpxchg() !void { | |
| 12 | var x: i32 = 1234; | |
| 13 | if (@cmpxchgWeak(i32, &x, 99, 5678, .SeqCst, .SeqCst)) |x1| { | |
| 14 | try expect(x1 == 1234); | |
| 15 | } else { | |
| 16 | @panic("cmpxchg should have failed"); | |
| 17 | } | |
| 18 | ||
| 19 | while (@cmpxchgWeak(i32, &x, 1234, 5678, .SeqCst, .SeqCst)) |x1| { | |
| 20 | try expect(x1 == 1234); | |
| 21 | } | |
| 22 | try expect(x == 5678); | |
| 23 | ||
| 24 | try expect(@cmpxchgStrong(i32, &x, 5678, 42, .SeqCst, .SeqCst) == null); | |
| 25 | try expect(x == 42); | |
| 26 | } | |
| 27 | ||
| 28 | test "fence" { | |
| 29 | var x: i32 = 1234; | |
| 30 | @fence(.SeqCst); | |
| 31 | x = 5678; | |
| 32 | } | |
| 33 | ||
| 34 | test "atomicrmw and atomicload" { | |
| 35 | var data: u8 = 200; | |
| 36 | try testAtomicRmw(&data); | |
| 37 | try expect(data == 42); | |
| 38 | try testAtomicLoad(&data); | |
| 39 | } | |
| 40 | ||
| 41 | fn testAtomicRmw(ptr: *u8) !void { | |
| 42 | const prev_value = @atomicRmw(u8, ptr, .Xchg, 42, .SeqCst); | |
| 43 | try expect(prev_value == 200); | |
| 44 | comptime { | |
| 45 | var x: i32 = 1234; | |
| 46 | const y: i32 = 12345; | |
| 47 | try expect(@atomicLoad(i32, &x, .SeqCst) == 1234); | |
| 48 | try expect(@atomicLoad(i32, &y, .SeqCst) == 12345); | |
| 49 | } | |
| 50 | } | |
| 51 | ||
| 52 | fn testAtomicLoad(ptr: *u8) !void { | |
| 53 | const x = @atomicLoad(u8, ptr, .SeqCst); | |
| 54 | try expect(x == 42); | |
| 55 | } | |
| 56 | ||
| 57 | test "cmpxchg with ptr" { | |
| 58 | var data1: i32 = 1234; | |
| 59 | var data2: i32 = 5678; | |
| 60 | var data3: i32 = 9101; | |
| 61 | var x: *i32 = &data1; | |
| 62 | if (@cmpxchgWeak(*i32, &x, &data2, &data3, .SeqCst, .SeqCst)) |x1| { | |
| 63 | try expect(x1 == &data1); | |
| 64 | } else { | |
| 65 | @panic("cmpxchg should have failed"); | |
| 66 | } | |
| 67 | ||
| 68 | while (@cmpxchgWeak(*i32, &x, &data1, &data3, .SeqCst, .SeqCst)) |x1| { | |
| 69 | try expect(x1 == &data1); | |
| 70 | } | |
| 71 | try expect(x == &data3); | |
| 72 | ||
| 73 | try expect(@cmpxchgStrong(*i32, &x, &data3, &data2, .SeqCst, .SeqCst) == null); | |
| 74 | try expect(x == &data2); | |
| 75 | } | |
| 76 | ||
| 77 | test "128-bit cmpxchg" { | |
| 78 | try test_u128_cmpxchg(); | |
| 79 | comptime try test_u128_cmpxchg(); | |
| 80 | } | |
| 81 | ||
| 82 | fn test_u128_cmpxchg() !void { | |
| 83 | if (std.Target.current.cpu.arch != .x86_64) return error.SkipZigTest; | |
| 84 | if (comptime !std.Target.x86.featureSetHas(std.Target.current.cpu.features, .cx16)) return error.SkipZigTest; | |
| 85 | ||
| 86 | var x: u128 = 1234; | |
| 87 | if (@cmpxchgWeak(u128, &x, 99, 5678, .SeqCst, .SeqCst)) |x1| { | |
| 88 | try expect(x1 == 1234); | |
| 89 | } else { | |
| 90 | @panic("cmpxchg should have failed"); | |
| 91 | } | |
| 92 | ||
| 93 | while (@cmpxchgWeak(u128, &x, 1234, 5678, .SeqCst, .SeqCst)) |x1| { | |
| 94 | try expect(x1 == 1234); | |
| 95 | } | |
| 96 | try expect(x == 5678); | |
| 97 | ||
| 98 | try expect(@cmpxchgStrong(u128, &x, 5678, 42, .SeqCst, .SeqCst) == null); | |
| 99 | try expect(x == 42); | |
| 100 | } | |
| 101 | ||
| 102 | test "cmpxchg with ignored result" { | |
| 103 | var x: i32 = 1234; | |
| 104 | ||
| 105 | _ = @cmpxchgStrong(i32, &x, 1234, 5678, .Monotonic, .Monotonic); | |
| 106 | ||
| 107 | try expectEqual(@as(i32, 5678), x); | |
| 108 | } | |
| 109 | ||
| 110 | var a_global_variable = @as(u32, 1234); | |
| 111 | ||
| 112 | test "cmpxchg on a global variable" { | |
| 113 | _ = @cmpxchgWeak(u32, &a_global_variable, 1234, 42, .Acquire, .Monotonic); | |
| 114 | try expectEqual(@as(u32, 42), a_global_variable); | |
| 115 | } | |
| 116 | ||
| 117 | test "atomic load and rmw with enum" { | |
| 118 | const Value = enum(u8) { | |
| 119 | a, | |
| 120 | b, | |
| 121 | c, | |
| 122 | }; | |
| 123 | var x = Value.a; | |
| 124 | ||
| 125 | try expect(@atomicLoad(Value, &x, .SeqCst) != .b); | |
| 126 | ||
| 127 | _ = @atomicRmw(Value, &x, .Xchg, .c, .SeqCst); | |
| 128 | try expect(@atomicLoad(Value, &x, .SeqCst) == .c); | |
| 129 | try expect(@atomicLoad(Value, &x, .SeqCst) != .a); | |
| 130 | try expect(@atomicLoad(Value, &x, .SeqCst) != .b); | |
| 131 | } | |
| 132 | ||
| 133 | test "atomic store" { | |
| 134 | var x: u32 = 0; | |
| 135 | @atomicStore(u32, &x, 1, .SeqCst); | |
| 136 | try expect(@atomicLoad(u32, &x, .SeqCst) == 1); | |
| 137 | @atomicStore(u32, &x, 12345678, .SeqCst); | |
| 138 | try expect(@atomicLoad(u32, &x, .SeqCst) == 12345678); | |
| 139 | } | |
| 140 | ||
| 141 | test "atomic store comptime" { | |
| 142 | comptime try testAtomicStore(); | |
| 143 | try testAtomicStore(); | |
| 144 | } | |
| 145 | ||
| 146 | fn testAtomicStore() !void { | |
| 147 | var x: u32 = 0; | |
| 148 | @atomicStore(u32, &x, 1, .SeqCst); | |
| 149 | try expect(@atomicLoad(u32, &x, .SeqCst) == 1); | |
| 150 | @atomicStore(u32, &x, 12345678, .SeqCst); | |
| 151 | try expect(@atomicLoad(u32, &x, .SeqCst) == 12345678); | |
| 152 | } | |
| 153 | ||
| 154 | test "atomicrmw with floats" { | |
| 155 | try testAtomicRmwFloat(); | |
| 156 | comptime try testAtomicRmwFloat(); | |
| 157 | } | |
| 158 | ||
| 159 | fn testAtomicRmwFloat() !void { | |
| 160 | var x: f32 = 0; | |
| 161 | try expect(x == 0); | |
| 162 | _ = @atomicRmw(f32, &x, .Xchg, 1, .SeqCst); | |
| 163 | try expect(x == 1); | |
| 164 | _ = @atomicRmw(f32, &x, .Add, 5, .SeqCst); | |
| 165 | try expect(x == 6); | |
| 166 | _ = @atomicRmw(f32, &x, .Sub, 2, .SeqCst); | |
| 167 | try expect(x == 4); | |
| 168 | } | |
| 169 | ||
| 170 | test "atomicrmw with ints" { | |
| 171 | try testAtomicRmwInt(); | |
| 172 | comptime try testAtomicRmwInt(); | |
| 173 | } | |
| 174 | ||
| 175 | fn testAtomicRmwInt() !void { | |
| 176 | var x: u8 = 1; | |
| 177 | var res = @atomicRmw(u8, &x, .Xchg, 3, .SeqCst); | |
| 178 | try expect(x == 3 and res == 1); | |
| 179 | _ = @atomicRmw(u8, &x, .Add, 3, .SeqCst); | |
| 180 | try expect(x == 6); | |
| 181 | _ = @atomicRmw(u8, &x, .Sub, 1, .SeqCst); | |
| 182 | try expect(x == 5); | |
| 183 | _ = @atomicRmw(u8, &x, .And, 4, .SeqCst); | |
| 184 | try expect(x == 4); | |
| 185 | _ = @atomicRmw(u8, &x, .Nand, 4, .SeqCst); | |
| 186 | try expect(x == 0xfb); | |
| 187 | _ = @atomicRmw(u8, &x, .Or, 6, .SeqCst); | |
| 188 | try expect(x == 0xff); | |
| 189 | _ = @atomicRmw(u8, &x, .Xor, 2, .SeqCst); | |
| 190 | try expect(x == 0xfd); | |
| 191 | ||
| 192 | _ = @atomicRmw(u8, &x, .Max, 1, .SeqCst); | |
| 193 | try expect(x == 0xfd); | |
| 194 | _ = @atomicRmw(u8, &x, .Min, 1, .SeqCst); | |
| 195 | try expect(x == 1); | |
| 196 | } | |
| 197 | ||
| 198 | test "atomics with different types" { | |
| 199 | try testAtomicsWithType(bool, true, false); | |
| 200 | inline for (.{ u1, i4, u5, i15, u24 }) |T| { | |
| 201 | try testAtomicsWithType(T, 0, 1); | |
| 202 | } | |
| 203 | try testAtomicsWithType(u0, 0, 0); | |
| 204 | try testAtomicsWithType(i0, 0, 0); | |
| 205 | } | |
| 206 | ||
| 207 | fn testAtomicsWithType(comptime T: type, a: T, b: T) !void { | |
| 208 | var x: T = b; | |
| 209 | @atomicStore(T, &x, a, .SeqCst); | |
| 210 | try expect(x == a); | |
| 211 | try expect(@atomicLoad(T, &x, .SeqCst) == a); | |
| 212 | try expect(@atomicRmw(T, &x, .Xchg, b, .SeqCst) == a); | |
| 213 | try expect(@cmpxchgStrong(T, &x, b, a, .SeqCst, .SeqCst) == null); | |
| 214 | if (@sizeOf(T) != 0) | |
| 215 | try expect(@cmpxchgStrong(T, &x, b, a, .SeqCst, .SeqCst).? == a); | |
| 216 | } |
test/behavior/atomics_stage1.zig created+216| ... | ... | @@ -0,0 +1,216 @@ |
| 1 | const std = @import("std"); | |
| 2 | const expect = std.testing.expect; | |
| 3 | const expectEqual = std.testing.expectEqual; | |
| 4 | const builtin = @import("builtin"); | |
| 5 | ||
| 6 | test "cmpxchg" { | |
| 7 | try testCmpxchg(); | |
| 8 | comptime try testCmpxchg(); | |
| 9 | } | |
| 10 | ||
| 11 | fn testCmpxchg() !void { | |
| 12 | var x: i32 = 1234; | |
| 13 | if (@cmpxchgWeak(i32, &x, 99, 5678, .SeqCst, .SeqCst)) |x1| { | |
| 14 | try expect(x1 == 1234); | |
| 15 | } else { | |
| 16 | @panic("cmpxchg should have failed"); | |
| 17 | } | |
| 18 | ||
| 19 | while (@cmpxchgWeak(i32, &x, 1234, 5678, .SeqCst, .SeqCst)) |x1| { | |
| 20 | try expect(x1 == 1234); | |
| 21 | } | |
| 22 | try expect(x == 5678); | |
| 23 | ||
| 24 | try expect(@cmpxchgStrong(i32, &x, 5678, 42, .SeqCst, .SeqCst) == null); | |
| 25 | try expect(x == 42); | |
| 26 | } | |
| 27 | ||
| 28 | test "fence" { | |
| 29 | var x: i32 = 1234; | |
| 30 | @fence(.SeqCst); | |
| 31 | x = 5678; | |
| 32 | } | |
| 33 | ||
| 34 | test "atomicrmw and atomicload" { | |
| 35 | var data: u8 = 200; | |
| 36 | try testAtomicRmw(&data); | |
| 37 | try expect(data == 42); | |
| 38 | try testAtomicLoad(&data); | |
| 39 | } | |
| 40 | ||
| 41 | fn testAtomicRmw(ptr: *u8) !void { | |
| 42 | const prev_value = @atomicRmw(u8, ptr, .Xchg, 42, .SeqCst); | |
| 43 | try expect(prev_value == 200); | |
| 44 | comptime { | |
| 45 | var x: i32 = 1234; | |
| 46 | const y: i32 = 12345; | |
| 47 | try expect(@atomicLoad(i32, &x, .SeqCst) == 1234); | |
| 48 | try expect(@atomicLoad(i32, &y, .SeqCst) == 12345); | |
| 49 | } | |
| 50 | } | |
| 51 | ||
| 52 | fn testAtomicLoad(ptr: *u8) !void { | |
| 53 | const x = @atomicLoad(u8, ptr, .SeqCst); | |
| 54 | try expect(x == 42); | |
| 55 | } | |
| 56 | ||
| 57 | test "cmpxchg with ptr" { | |
| 58 | var data1: i32 = 1234; | |
| 59 | var data2: i32 = 5678; | |
| 60 | var data3: i32 = 9101; | |
| 61 | var x: *i32 = &data1; | |
| 62 | if (@cmpxchgWeak(*i32, &x, &data2, &data3, .SeqCst, .SeqCst)) |x1| { | |
| 63 | try expect(x1 == &data1); | |
| 64 | } else { | |
| 65 | @panic("cmpxchg should have failed"); | |
| 66 | } | |
| 67 | ||
| 68 | while (@cmpxchgWeak(*i32, &x, &data1, &data3, .SeqCst, .SeqCst)) |x1| { | |
| 69 | try expect(x1 == &data1); | |
| 70 | } | |
| 71 | try expect(x == &data3); | |
| 72 | ||
| 73 | try expect(@cmpxchgStrong(*i32, &x, &data3, &data2, .SeqCst, .SeqCst) == null); | |
| 74 | try expect(x == &data2); | |
| 75 | } | |
| 76 | ||
| 77 | test "128-bit cmpxchg" { | |
| 78 | try test_u128_cmpxchg(); | |
| 79 | comptime try test_u128_cmpxchg(); | |
| 80 | } | |
| 81 | ||
| 82 | fn test_u128_cmpxchg() !void { | |
| 83 | if (std.Target.current.cpu.arch != .x86_64) return error.SkipZigTest; | |
| 84 | if (comptime !std.Target.x86.featureSetHas(std.Target.current.cpu.features, .cx16)) return error.SkipZigTest; | |
| 85 | ||
| 86 | var x: u128 = 1234; | |
| 87 | if (@cmpxchgWeak(u128, &x, 99, 5678, .SeqCst, .SeqCst)) |x1| { | |
| 88 | try expect(x1 == 1234); | |
| 89 | } else { | |
| 90 | @panic("cmpxchg should have failed"); | |
| 91 | } | |
| 92 | ||
| 93 | while (@cmpxchgWeak(u128, &x, 1234, 5678, .SeqCst, .SeqCst)) |x1| { | |
| 94 | try expect(x1 == 1234); | |
| 95 | } | |
| 96 | try expect(x == 5678); | |
| 97 | ||
| 98 | try expect(@cmpxchgStrong(u128, &x, 5678, 42, .SeqCst, .SeqCst) == null); | |
| 99 | try expect(x == 42); | |
| 100 | } | |
| 101 | ||
| 102 | test "cmpxchg with ignored result" { | |
| 103 | var x: i32 = 1234; | |
| 104 | ||
| 105 | _ = @cmpxchgStrong(i32, &x, 1234, 5678, .Monotonic, .Monotonic); | |
| 106 | ||
| 107 | try expectEqual(@as(i32, 5678), x); | |
| 108 | } | |
| 109 | ||
| 110 | var a_global_variable = @as(u32, 1234); | |
| 111 | ||
| 112 | test "cmpxchg on a global variable" { | |
| 113 | _ = @cmpxchgWeak(u32, &a_global_variable, 1234, 42, .Acquire, .Monotonic); | |
| 114 | try expectEqual(@as(u32, 42), a_global_variable); | |
| 115 | } | |
| 116 | ||
| 117 | test "atomic load and rmw with enum" { | |
| 118 | const Value = enum(u8) { | |
| 119 | a, | |
| 120 | b, | |
| 121 | c, | |
| 122 | }; | |
| 123 | var x = Value.a; | |
| 124 | ||
| 125 | try expect(@atomicLoad(Value, &x, .SeqCst) != .b); | |
| 126 | ||
| 127 | _ = @atomicRmw(Value, &x, .Xchg, .c, .SeqCst); | |
| 128 | try expect(@atomicLoad(Value, &x, .SeqCst) == .c); | |
| 129 | try expect(@atomicLoad(Value, &x, .SeqCst) != .a); | |
| 130 | try expect(@atomicLoad(Value, &x, .SeqCst) != .b); | |
| 131 | } | |
| 132 | ||
| 133 | test "atomic store" { | |
| 134 | var x: u32 = 0; | |
| 135 | @atomicStore(u32, &x, 1, .SeqCst); | |
| 136 | try expect(@atomicLoad(u32, &x, .SeqCst) == 1); | |
| 137 | @atomicStore(u32, &x, 12345678, .SeqCst); | |
| 138 | try expect(@atomicLoad(u32, &x, .SeqCst) == 12345678); | |
| 139 | } | |
| 140 | ||
| 141 | test "atomic store comptime" { | |
| 142 | comptime try testAtomicStore(); | |
| 143 | try testAtomicStore(); | |
| 144 | } | |
| 145 | ||
| 146 | fn testAtomicStore() !void { | |
| 147 | var x: u32 = 0; | |
| 148 | @atomicStore(u32, &x, 1, .SeqCst); | |
| 149 | try expect(@atomicLoad(u32, &x, .SeqCst) == 1); | |
| 150 | @atomicStore(u32, &x, 12345678, .SeqCst); | |
| 151 | try expect(@atomicLoad(u32, &x, .SeqCst) == 12345678); | |
| 152 | } | |
| 153 | ||
| 154 | test "atomicrmw with floats" { | |
| 155 | try testAtomicRmwFloat(); | |
| 156 | comptime try testAtomicRmwFloat(); | |
| 157 | } | |
| 158 | ||
| 159 | fn testAtomicRmwFloat() !void { | |
| 160 | var x: f32 = 0; | |
| 161 | try expect(x == 0); | |
| 162 | _ = @atomicRmw(f32, &x, .Xchg, 1, .SeqCst); | |
| 163 | try expect(x == 1); | |
| 164 | _ = @atomicRmw(f32, &x, .Add, 5, .SeqCst); | |
| 165 | try expect(x == 6); | |
| 166 | _ = @atomicRmw(f32, &x, .Sub, 2, .SeqCst); | |
| 167 | try expect(x == 4); | |
| 168 | } | |
| 169 | ||
| 170 | test "atomicrmw with ints" { | |
| 171 | try testAtomicRmwInt(); | |
| 172 | comptime try testAtomicRmwInt(); | |
| 173 | } | |
| 174 | ||
| 175 | fn testAtomicRmwInt() !void { | |
| 176 | var x: u8 = 1; | |
| 177 | var res = @atomicRmw(u8, &x, .Xchg, 3, .SeqCst); | |
| 178 | try expect(x == 3 and res == 1); | |
| 179 | _ = @atomicRmw(u8, &x, .Add, 3, .SeqCst); | |
| 180 | try expect(x == 6); | |
| 181 | _ = @atomicRmw(u8, &x, .Sub, 1, .SeqCst); | |
| 182 | try expect(x == 5); | |
| 183 | _ = @atomicRmw(u8, &x, .And, 4, .SeqCst); | |
| 184 | try expect(x == 4); | |
| 185 | _ = @atomicRmw(u8, &x, .Nand, 4, .SeqCst); | |
| 186 | try expect(x == 0xfb); | |
| 187 | _ = @atomicRmw(u8, &x, .Or, 6, .SeqCst); | |
| 188 | try expect(x == 0xff); | |
| 189 | _ = @atomicRmw(u8, &x, .Xor, 2, .SeqCst); | |
| 190 | try expect(x == 0xfd); | |
| 191 | ||
| 192 | _ = @atomicRmw(u8, &x, .Max, 1, .SeqCst); | |
| 193 | try expect(x == 0xfd); | |
| 194 | _ = @atomicRmw(u8, &x, .Min, 1, .SeqCst); | |
| 195 | try expect(x == 1); | |
| 196 | } | |
| 197 | ||
| 198 | test "atomics with different types" { | |
| 199 | try testAtomicsWithType(bool, true, false); | |
| 200 | inline for (.{ u1, i4, u5, i15, u24 }) |T| { | |
| 201 | try testAtomicsWithType(T, 0, 1); | |
| 202 | } | |
| 203 | try testAtomicsWithType(u0, 0, 0); | |
| 204 | try testAtomicsWithType(i0, 0, 0); | |
| 205 | } | |
| 206 | ||
| 207 | fn testAtomicsWithType(comptime T: type, a: T, b: T) !void { | |
| 208 | var x: T = b; | |
| 209 | @atomicStore(T, &x, a, .SeqCst); | |
| 210 | try expect(x == a); | |
| 211 | try expect(@atomicLoad(T, &x, .SeqCst) == a); | |
| 212 | try expect(@atomicRmw(T, &x, .Xchg, b, .SeqCst) == a); | |
| 213 | try expect(@cmpxchgStrong(T, &x, b, a, .SeqCst, .SeqCst) == null); | |
| 214 | if (@sizeOf(T) != 0) | |
| 215 | try expect(@cmpxchgStrong(T, &x, b, a, .SeqCst, .SeqCst).? == a); | |
| 216 | } |