| author | |
| committer | |
| log | 110ef2e52825656fc048cba020f0fc36a1e58d13 |
| tree | cae3ae95a6ce44f85650c44b90365f7cc5cb4045 |
| parent | 956ba8b0e7ada08f2f85cd41ee73af6453db0c16 |
| signature |
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, maybe | 6624 | 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 restriction | 6625 | 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 | }; |
| 3715 | 3717 | ||
| 3718 | struct IrInstructionAtomicStore { | ||
| 3719 | IrInstruction base; | ||
| 3720 | |||
| 3721 | IrInstruction *operand_type; | ||
| 3722 | IrInstruction *ptr; | ||
| 3723 | IrInstruction *value; | ||
| 3724 | IrInstruction *ordering; | ||
| 3725 | AtomicOrder resolved_ordering; | ||
| 3726 | }; | ||
| 3727 | |||
| 3716 | struct IrInstructionSaveErrRetAddr { | 3728 | struct 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 | } |
| 5652 | 5652 | ||
| 5653 | static 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 | |||
| 5653 | static LLVMValueRef ir_render_float_op(CodeGen *g, IrExecutable *executable, IrInstructionFloatOp *instruction) { | 5664 | static 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 | } |
| 1011 | 1011 | ||
| 1012 | static constexpr IrInstructionId ir_instruction_id(IrInstructionAtomicStore *) { | ||
| 1013 | return IrInstructionIdAtomicStore; | ||
| 1014 | } | ||
| 1015 | |||
| 1012 | static constexpr IrInstructionId ir_instruction_id(IrInstructionSaveErrRetAddr *) { | 1016 | static 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 | } |
| 3188 | 3192 | ||
| 3193 | static 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 | |||
| 3189 | static IrInstruction *ir_build_save_err_ret_addr(IrBuilder *irb, Scope *scope, AstNode *source_node) { | 3212 | static 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 | } |
| 25750 | 25800 | ||
| 25801 | static 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 | |||
| 25751 | static IrInstruction *ir_analyze_instruction_save_err_ret_addr(IrAnalyze *ira, IrInstructionSaveErrRetAddr *instruction) { | 25851 | static 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 | } |
| 1873 | 1875 | ||
| 1876 | static 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 | |||
| 1874 | static void ir_print_save_err_ret_addr(IrPrint *irp, IrInstructionSaveErrRetAddr *instruction) { | 1897 | static 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 | |||
| 127 | test "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 | |||