authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2019-11-13 00:25:44+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2019-11-13 00:25:44+02:00
log110ef2e52825656fc048cba020f0fc36a1e58d13
treecae3ae95a6ce44f85650c44b90365f7cc5cb4045
parent956ba8b0e7ada08f2f85cd41ee73af6453db0c16
signaturelock-open Commit is signed but in an unrecognized format.

add @atomicStore builtin


6 files changed, 185 insertions(+), 3 deletions(-)

doc/langref.html.in+22-3
...@@ -6612,14 +6612,14 @@ async fn func(y: *i32) void {...@@ -6612,14 +6612,14 @@ async fn func(y: *i32) void {
6612 This builtin function atomically dereferences a pointer and returns the value.6612 This builtin function atomically dereferences a pointer and returns the value.
6613 </p>6613 </p>
6614 <p>6614 <p>
6615 {#syntax#}T{#endsyntax#} must be a pointer type, a {#syntax#}bool{#endsyntax#},6615 {#syntax#}T{#endsyntax#} must be a pointer type, a {#syntax#}bool{#endsyntax#}
6616 or an integer whose bit count meets these requirements:6616 an integer whose bit count meets these requirements:
6617 </p>6617 </p>
6618 <ul>6618 <ul>
6619 <li>At least 8</li>6619 <li>At least 8</li>
6620 <li>At most the same as usize</li>6620 <li>At most the same as usize</li>
6621 <li>Power of 2</li>6621 <li>Power of 2</li>
6622 </ul>6622 </ul> or an enum with a valid integer tag type.
6623 <p>6623 <p>
6624 TODO right now bool is not accepted. Also I think we could make non powers of 2 work fine, maybe6624 TODO right now bool is not accepted. Also I think we could make non powers of 2 work fine, maybe
6625 we can remove this restriction6625 we can remove this restriction
...@@ -6660,6 +6660,25 @@ async fn func(y: *i32) void {...@@ -6660,6 +6660,25 @@ async fn func(y: *i32) void {
6660 <li>{#syntax#}.Min{#endsyntax#} - stores the operand if it is smaller. Supports integers and floats.</li>6660 <li>{#syntax#}.Min{#endsyntax#} - stores the operand if it is smaller. Supports integers and floats.</li>
6661 </ul>6661 </ul>
6662 {#header_close#}6662 {#header_close#}
6663 {#header_open|@atomicStore#}
6664 <pre>{#syntax#}@atomicStore(comptime T: type, ptr: *T, value: T, comptime ordering: builtin.AtomicOrder) void{#endsyntax#}</pre>
6665 <p>
6666 This builtin function atomically stores a value.
6667 </p>
6668 <p>
6669 {#syntax#}T{#endsyntax#} must be a pointer type, a {#syntax#}bool{#endsyntax#}
6670 an integer whose bit count meets these requirements:
6671 </p>
6672 <ul>
6673 <li>At least 8</li>
6674 <li>At most the same as usize</li>
6675 <li>Power of 2</li>
6676 </ul> or an enum with a valid integer tag type.
6677 <p>
6678 TODO right now bool is not accepted. Also I think we could make non powers of 2 work fine, maybe
6679 we can remove this restriction
6680 </p>
6681 {#header_close#}
6663 {#header_open|@bitCast#}6682 {#header_open|@bitCast#}
6664 <pre>{#syntax#}@bitCast(comptime DestType: type, value: var) DestType{#endsyntax#}</pre>6683 <pre>{#syntax#}@bitCast(comptime DestType: type, value: var) DestType{#endsyntax#}</pre>
6665 <p>6684 <p>
src/all_types.hpp+12
...@@ -1700,6 +1700,7 @@ enum BuiltinFnId {...@@ -1700,6 +1700,7 @@ enum BuiltinFnId {
1700 BuiltinFnIdErrorReturnTrace,1700 BuiltinFnIdErrorReturnTrace,
1701 BuiltinFnIdAtomicRmw,1701 BuiltinFnIdAtomicRmw,
1702 BuiltinFnIdAtomicLoad,1702 BuiltinFnIdAtomicLoad,
1703 BuiltinFnIdAtomicStore,
1703 BuiltinFnIdHasDecl,1704 BuiltinFnIdHasDecl,
1704 BuiltinFnIdUnionInit,1705 BuiltinFnIdUnionInit,
1705 BuiltinFnIdFrameAddress,1706 BuiltinFnIdFrameAddress,
...@@ -2569,6 +2570,7 @@ enum IrInstructionId {...@@ -2569,6 +2570,7 @@ enum IrInstructionId {
2569 IrInstructionIdErrorUnion,2570 IrInstructionIdErrorUnion,
2570 IrInstructionIdAtomicRmw,2571 IrInstructionIdAtomicRmw,
2571 IrInstructionIdAtomicLoad,2572 IrInstructionIdAtomicLoad,
2573 IrInstructionIdAtomicStore,
2572 IrInstructionIdSaveErrRetAddr,2574 IrInstructionIdSaveErrRetAddr,
2573 IrInstructionIdAddImplicitReturnType,2575 IrInstructionIdAddImplicitReturnType,
2574 IrInstructionIdErrSetCast,2576 IrInstructionIdErrSetCast,
...@@ -3713,6 +3715,16 @@ struct IrInstructionAtomicLoad {...@@ -3713,6 +3715,16 @@ struct IrInstructionAtomicLoad {
3713 AtomicOrder resolved_ordering;3715 AtomicOrder resolved_ordering;
3714};3716};
37153717
3718struct IrInstructionAtomicStore {
3719 IrInstruction base;
3720
3721 IrInstruction *operand_type;
3722 IrInstruction *ptr;
3723 IrInstruction *value;
3724 IrInstruction *ordering;
3725 AtomicOrder resolved_ordering;
3726};
3727
3716struct IrInstructionSaveErrRetAddr {3728struct IrInstructionSaveErrRetAddr {
3717 IrInstruction base;3729 IrInstruction base;
3718};3730};
src/codegen.cpp+14
...@@ -5650,6 +5650,17 @@ static LLVMValueRef ir_render_atomic_load(CodeGen *g, IrExecutable *executable,...@@ -5650,6 +5650,17 @@ static LLVMValueRef ir_render_atomic_load(CodeGen *g, IrExecutable *executable,
5650 return load_inst;5650 return load_inst;
5651}5651}
56525652
5653static LLVMValueRef ir_render_atomic_store(CodeGen *g, IrExecutable *executable,
5654 IrInstructionAtomicStore *instruction)
5655{
5656 LLVMAtomicOrdering ordering = to_LLVMAtomicOrdering(instruction->resolved_ordering);
5657 LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr);
5658 LLVMValueRef value = ir_llvm_value(g, instruction->value);
5659 LLVMValueRef store_inst = gen_store(g, value, ptr, instruction->ptr->value.type);
5660 LLVMSetOrdering(store_inst, ordering);
5661 return nullptr;
5662}
5663
5653static LLVMValueRef ir_render_float_op(CodeGen *g, IrExecutable *executable, IrInstructionFloatOp *instruction) {5664static LLVMValueRef ir_render_float_op(CodeGen *g, IrExecutable *executable, IrInstructionFloatOp *instruction) {
5654 LLVMValueRef op = ir_llvm_value(g, instruction->op1);5665 LLVMValueRef op = ir_llvm_value(g, instruction->op1);
5655 assert(instruction->base.value.type->id == ZigTypeIdFloat);5666 assert(instruction->base.value.type->id == ZigTypeIdFloat);
...@@ -6253,6 +6264,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -6253,6 +6264,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
6253 return ir_render_atomic_rmw(g, executable, (IrInstructionAtomicRmw *)instruction);6264 return ir_render_atomic_rmw(g, executable, (IrInstructionAtomicRmw *)instruction);
6254 case IrInstructionIdAtomicLoad:6265 case IrInstructionIdAtomicLoad:
6255 return ir_render_atomic_load(g, executable, (IrInstructionAtomicLoad *)instruction);6266 return ir_render_atomic_load(g, executable, (IrInstructionAtomicLoad *)instruction);
6267 case IrInstructionIdAtomicStore:
6268 return ir_render_atomic_store(g, executable, (IrInstructionAtomicStore *)instruction);
6256 case IrInstructionIdSaveErrRetAddr:6269 case IrInstructionIdSaveErrRetAddr:
6257 return ir_render_save_err_ret_addr(g, executable, (IrInstructionSaveErrRetAddr *)instruction);6270 return ir_render_save_err_ret_addr(g, executable, (IrInstructionSaveErrRetAddr *)instruction);
6258 case IrInstructionIdFloatOp:6271 case IrInstructionIdFloatOp:
...@@ -8064,6 +8077,7 @@ static void define_builtin_fns(CodeGen *g) {...@@ -8064,6 +8077,7 @@ static void define_builtin_fns(CodeGen *g) {
8064 create_builtin_fn(g, BuiltinFnIdErrorReturnTrace, "errorReturnTrace", 0);8077 create_builtin_fn(g, BuiltinFnIdErrorReturnTrace, "errorReturnTrace", 0);
8065 create_builtin_fn(g, BuiltinFnIdAtomicRmw, "atomicRmw", 5);8078 create_builtin_fn(g, BuiltinFnIdAtomicRmw, "atomicRmw", 5);
8066 create_builtin_fn(g, BuiltinFnIdAtomicLoad, "atomicLoad", 3);8079 create_builtin_fn(g, BuiltinFnIdAtomicLoad, "atomicLoad", 3);
8080 create_builtin_fn(g, BuiltinFnIdAtomicStore, "atomicStore", 4);
8067 create_builtin_fn(g, BuiltinFnIdErrSetCast, "errSetCast", 2);8081 create_builtin_fn(g, BuiltinFnIdErrSetCast, "errSetCast", 2);
8068 create_builtin_fn(g, BuiltinFnIdToBytes, "sliceToBytes", 1);8082 create_builtin_fn(g, BuiltinFnIdToBytes, "sliceToBytes", 1);
8069 create_builtin_fn(g, BuiltinFnIdFromBytes, "bytesToSlice", 2);8083 create_builtin_fn(g, BuiltinFnIdFromBytes, "bytesToSlice", 2);
src/ir.cpp+103
...@@ -1009,6 +1009,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionAtomicLoad *) {...@@ -1009,6 +1009,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionAtomicLoad *) {
1009 return IrInstructionIdAtomicLoad;1009 return IrInstructionIdAtomicLoad;
1010}1010}
10111011
1012static constexpr IrInstructionId ir_instruction_id(IrInstructionAtomicStore *) {
1013 return IrInstructionIdAtomicStore;
1014}
1015
1012static constexpr IrInstructionId ir_instruction_id(IrInstructionSaveErrRetAddr *) {1016static constexpr IrInstructionId ir_instruction_id(IrInstructionSaveErrRetAddr *) {
1013 return IrInstructionIdSaveErrRetAddr;1017 return IrInstructionIdSaveErrRetAddr;
1014}1018}
...@@ -3186,6 +3190,25 @@ static IrInstruction *ir_build_atomic_load(IrBuilder *irb, Scope *scope, AstNode...@@ -3186,6 +3190,25 @@ static IrInstruction *ir_build_atomic_load(IrBuilder *irb, Scope *scope, AstNode
3186 return &instruction->base;3190 return &instruction->base;
3187}3191}
31883192
3193static IrInstruction *ir_build_atomic_store(IrBuilder *irb, Scope *scope, AstNode *source_node,
3194 IrInstruction *operand_type, IrInstruction *ptr, IrInstruction *value,
3195 IrInstruction *ordering, AtomicOrder resolved_ordering)
3196{
3197 IrInstructionAtomicStore *instruction = ir_build_instruction<IrInstructionAtomicStore>(irb, scope, source_node);
3198 instruction->operand_type = operand_type;
3199 instruction->ptr = ptr;
3200 instruction->value = value;
3201 instruction->ordering = ordering;
3202 instruction->resolved_ordering = resolved_ordering;
3203
3204 if (operand_type != nullptr) ir_ref_instruction(operand_type, irb->current_basic_block);
3205 ir_ref_instruction(ptr, irb->current_basic_block);
3206 ir_ref_instruction(value, irb->current_basic_block);
3207 if (ordering != nullptr) ir_ref_instruction(ordering, irb->current_basic_block);
3208
3209 return &instruction->base;
3210}
3211
3189static IrInstruction *ir_build_save_err_ret_addr(IrBuilder *irb, Scope *scope, AstNode *source_node) {3212static IrInstruction *ir_build_save_err_ret_addr(IrBuilder *irb, Scope *scope, AstNode *source_node) {
3190 IrInstructionSaveErrRetAddr *instruction = ir_build_instruction<IrInstructionSaveErrRetAddr>(irb, scope, source_node);3213 IrInstructionSaveErrRetAddr *instruction = ir_build_instruction<IrInstructionSaveErrRetAddr>(irb, scope, source_node);
3191 return &instruction->base;3214 return &instruction->base;
...@@ -5730,6 +5753,33 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -5730,6 +5753,33 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
5730 AtomicOrderMonotonic);5753 AtomicOrderMonotonic);
5731 return ir_lval_wrap(irb, scope, inst, lval, result_loc);5754 return ir_lval_wrap(irb, scope, inst, lval, result_loc);
5732 }5755 }
5756 case BuiltinFnIdAtomicStore:
5757 {
5758 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
5759 IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope);
5760 if (arg0_value == irb->codegen->invalid_instruction)
5761 return arg0_value;
5762
5763 AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
5764 IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope);
5765 if (arg1_value == irb->codegen->invalid_instruction)
5766 return arg1_value;
5767
5768 AstNode *arg2_node = node->data.fn_call_expr.params.at(2);
5769 IrInstruction *arg2_value = ir_gen_node(irb, arg2_node, scope);
5770 if (arg2_value == irb->codegen->invalid_instruction)
5771 return arg2_value;
5772
5773 AstNode *arg3_node = node->data.fn_call_expr.params.at(3);
5774 IrInstruction *arg3_value = ir_gen_node(irb, arg3_node, scope);
5775 if (arg3_value == irb->codegen->invalid_instruction)
5776 return arg3_value;
5777
5778 IrInstruction *inst = ir_build_atomic_store(irb, scope, node, arg0_value, arg1_value, arg2_value, arg3_value,
5779 // this value does not mean anything since we passed non-null values for other arg
5780 AtomicOrderMonotonic);
5781 return ir_lval_wrap(irb, scope, inst, lval, result_loc);
5782 }
5733 case BuiltinFnIdIntToEnum:5783 case BuiltinFnIdIntToEnum:
5734 {5784 {
5735 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);5785 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
...@@ -25748,6 +25798,56 @@ static IrInstruction *ir_analyze_instruction_atomic_load(IrAnalyze *ira, IrInstr...@@ -25748,6 +25798,56 @@ static IrInstruction *ir_analyze_instruction_atomic_load(IrAnalyze *ira, IrInstr
25748 return result;25798 return result;
25749}25799}
2575025800
25801static IrInstruction *ir_analyze_instruction_atomic_store(IrAnalyze *ira, IrInstructionAtomicStore *instruction) {
25802 ZigType *operand_type = ir_resolve_atomic_operand_type(ira, instruction->operand_type->child);
25803 if (type_is_invalid(operand_type))
25804 return ira->codegen->invalid_instruction;
25805
25806 IrInstruction *ptr_inst = instruction->ptr->child;
25807 if (type_is_invalid(ptr_inst->value.type))
25808 return ira->codegen->invalid_instruction;
25809
25810 ZigType *ptr_type = get_pointer_to_type(ira->codegen, operand_type, true);
25811 IrInstruction *casted_ptr = ir_implicit_cast(ira, ptr_inst, ptr_type);
25812 if (type_is_invalid(casted_ptr->value.type))
25813 return ira->codegen->invalid_instruction;
25814
25815 IrInstruction *value = instruction->value->child;
25816 if (type_is_invalid(value->value.type))
25817 return ira->codegen->invalid_instruction;
25818
25819 IrInstruction *casted_value = ir_implicit_cast(ira, value, operand_type);
25820 if (type_is_invalid(casted_value->value.type))
25821 return ira->codegen->invalid_instruction;
25822
25823
25824 AtomicOrder ordering;
25825 if (instruction->ordering == nullptr) {
25826 ordering = instruction->resolved_ordering;
25827 } else {
25828 if (!ir_resolve_atomic_order(ira, instruction->ordering->child, &ordering))
25829 return ira->codegen->invalid_instruction;
25830 }
25831
25832 if (ordering == AtomicOrderAcquire || ordering == AtomicOrderAcqRel) {
25833 ir_assert(instruction->ordering != nullptr, &instruction->base);
25834 ir_add_error(ira, instruction->ordering,
25835 buf_sprintf("@atomicStore atomic ordering must not be Acquire or AcqRel"));
25836 return ira->codegen->invalid_instruction;
25837 }
25838
25839 if (instr_is_comptime(casted_value) && instr_is_comptime(casted_ptr)) {
25840 IrInstruction *result = ir_get_deref(ira, &instruction->base, casted_ptr, nullptr);
25841 ir_assert(result->value.type != nullptr, &instruction->base);
25842 return result;
25843 }
25844
25845 IrInstruction *result = ir_build_atomic_store(&ira->new_irb, instruction->base.scope,
25846 instruction->base.source_node, nullptr, casted_ptr, casted_value, nullptr, ordering);
25847 result->value.type = ira->codegen->builtin_types.entry_void;
25848 return result;
25849}
25850
25751static IrInstruction *ir_analyze_instruction_save_err_ret_addr(IrAnalyze *ira, IrInstructionSaveErrRetAddr *instruction) {25851static IrInstruction *ir_analyze_instruction_save_err_ret_addr(IrAnalyze *ira, IrInstructionSaveErrRetAddr *instruction) {
25752 IrInstruction *result = ir_build_save_err_ret_addr(&ira->new_irb, instruction->base.scope,25852 IrInstruction *result = ir_build_save_err_ret_addr(&ira->new_irb, instruction->base.scope,
25753 instruction->base.source_node);25853 instruction->base.source_node);
...@@ -26782,6 +26882,8 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction...@@ -26782,6 +26882,8 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction
26782 return ir_analyze_instruction_atomic_rmw(ira, (IrInstructionAtomicRmw *)instruction);26882 return ir_analyze_instruction_atomic_rmw(ira, (IrInstructionAtomicRmw *)instruction);
26783 case IrInstructionIdAtomicLoad:26883 case IrInstructionIdAtomicLoad:
26784 return ir_analyze_instruction_atomic_load(ira, (IrInstructionAtomicLoad *)instruction);26884 return ir_analyze_instruction_atomic_load(ira, (IrInstructionAtomicLoad *)instruction);
26885 case IrInstructionIdAtomicStore:
26886 return ir_analyze_instruction_atomic_store(ira, (IrInstructionAtomicStore *)instruction);
26785 case IrInstructionIdSaveErrRetAddr:26887 case IrInstructionIdSaveErrRetAddr:
26786 return ir_analyze_instruction_save_err_ret_addr(ira, (IrInstructionSaveErrRetAddr *)instruction);26888 return ir_analyze_instruction_save_err_ret_addr(ira, (IrInstructionSaveErrRetAddr *)instruction);
26787 case IrInstructionIdAddImplicitReturnType:26889 case IrInstructionIdAddImplicitReturnType:
...@@ -26962,6 +27064,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -26962,6 +27064,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
26962 case IrInstructionIdSaveErrRetAddr:27064 case IrInstructionIdSaveErrRetAddr:
26963 case IrInstructionIdAddImplicitReturnType:27065 case IrInstructionIdAddImplicitReturnType:
26964 case IrInstructionIdAtomicRmw:27066 case IrInstructionIdAtomicRmw:
27067 case IrInstructionIdAtomicStore:
26965 case IrInstructionIdCmpxchgGen:27068 case IrInstructionIdCmpxchgGen:
26966 case IrInstructionIdCmpxchgSrc:27069 case IrInstructionIdCmpxchgSrc:
26967 case IrInstructionIdAssertZero:27070 case IrInstructionIdAssertZero:
src/ir_print.cpp+26
...@@ -324,6 +324,8 @@ const char* ir_instruction_type_str(IrInstructionId id) {...@@ -324,6 +324,8 @@ const char* ir_instruction_type_str(IrInstructionId id) {
324 return "AtomicRmw";324 return "AtomicRmw";
325 case IrInstructionIdAtomicLoad:325 case IrInstructionIdAtomicLoad:
326 return "AtomicLoad";326 return "AtomicLoad";
327 case IrInstructionIdAtomicStore:
328 return "AtomicStore";
327 case IrInstructionIdSaveErrRetAddr:329 case IrInstructionIdSaveErrRetAddr:
328 return "SaveErrRetAddr";330 return "SaveErrRetAddr";
329 case IrInstructionIdAddImplicitReturnType:331 case IrInstructionIdAddImplicitReturnType:
...@@ -1871,6 +1873,27 @@ static void ir_print_atomic_load(IrPrint *irp, IrInstructionAtomicLoad *instruct...@@ -1871,6 +1873,27 @@ static void ir_print_atomic_load(IrPrint *irp, IrInstructionAtomicLoad *instruct
1871 fprintf(irp->f, ")");1873 fprintf(irp->f, ")");
1872}1874}
18731875
1876static void ir_print_atomic_store(IrPrint *irp, IrInstructionAtomicStore *instruction) {
1877 fprintf(irp->f, "@atomicStore(");
1878 if (instruction->operand_type != nullptr) {
1879 ir_print_other_instruction(irp, instruction->operand_type);
1880 } else {
1881 fprintf(irp->f, "[TODO print]");
1882 }
1883 fprintf(irp->f, ",");
1884 ir_print_other_instruction(irp, instruction->ptr);
1885 fprintf(irp->f, ",");
1886 ir_print_other_instruction(irp, instruction->value);
1887 fprintf(irp->f, ",");
1888 if (instruction->ordering != nullptr) {
1889 ir_print_other_instruction(irp, instruction->ordering);
1890 } else {
1891 fprintf(irp->f, "[TODO print]");
1892 }
1893 fprintf(irp->f, ")");
1894}
1895
1896
1874static void ir_print_save_err_ret_addr(IrPrint *irp, IrInstructionSaveErrRetAddr *instruction) {1897static void ir_print_save_err_ret_addr(IrPrint *irp, IrInstructionSaveErrRetAddr *instruction) {
1875 fprintf(irp->f, "@saveErrRetAddr()");1898 fprintf(irp->f, "@saveErrRetAddr()");
1876}1899}
...@@ -2431,6 +2454,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction, bool...@@ -2431,6 +2454,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction, bool
2431 case IrInstructionIdAtomicLoad:2454 case IrInstructionIdAtomicLoad:
2432 ir_print_atomic_load(irp, (IrInstructionAtomicLoad *)instruction);2455 ir_print_atomic_load(irp, (IrInstructionAtomicLoad *)instruction);
2433 break;2456 break;
2457 case IrInstructionIdAtomicStore:
2458 ir_print_atomic_store(irp, (IrInstructionAtomicStore *)instruction);
2459 break;
2434 case IrInstructionIdEnumToInt:2460 case IrInstructionIdEnumToInt:
2435 ir_print_enum_to_int(irp, (IrInstructionEnumToInt *)instruction);2461 ir_print_enum_to_int(irp, (IrInstructionEnumToInt *)instruction);
2436 break;2462 break;
test/stage1/behavior/atomics.zig+8
...@@ -123,3 +123,11 @@ test "atomic load and rmw with enum" {...@@ -123,3 +123,11 @@ test "atomic load and rmw with enum" {
123 expect(@atomicLoad(Value, &x, .SeqCst) != .a);123 expect(@atomicLoad(Value, &x, .SeqCst) != .a);
124 expect(@atomicLoad(Value, &x, .SeqCst) != .b);124 expect(@atomicLoad(Value, &x, .SeqCst) != .b);
125}125}
126
127test "atomic store" {
128 var x: u32 = 0;
129 @atomicStore(u32, &x, 1, .SeqCst);
130 expect(@atomicLoad(u32, &x, .SeqCst) == 1);
131 @atomicStore(u32, &x, 12345678, .SeqCst);
132 expect(@atomicLoad(u32, &x, .SeqCst) == 12345678);
133}
\ No newline at end of file