| author | |
| committer | |
| log | ec906a97712b329694e8f2e1a35b50b75d052642 |
| tree | e0b5234faa2cbc58bd7a54d8d77f797fa47c5bc1 |
| parent | 1f66435a6b0c5ccf6e4e96df0ed96732480ab4db |
| signature |
3 files changed, 17 insertions(+), 43 deletions(-)
doc/langref.html.in+10-35| ... | ... | @@ -6728,17 +6728,8 @@ async fn func(y: *i32) void { |
| 6728 | 6728 | This builtin function atomically dereferences a pointer and returns the value. |
| 6729 | 6729 | </p> |
| 6730 | 6730 | <p> |
| 6731 | {#syntax#}T{#endsyntax#} must be a pointer type, a {#syntax#}bool{#endsyntax#}, a float, | |
| 6732 | an integer whose bit count meets these requirements: | |
| 6733 | </p> | |
| 6734 | <ul> | |
| 6735 | <li>At least 8</li> | |
| 6736 | <li>At most the same as usize</li> | |
| 6737 | <li>Power of 2</li> | |
| 6738 | </ul> or an enum with a valid integer tag type. | |
| 6739 | <p> | |
| 6740 | TODO right now bool is not accepted. Also I think we could make non powers of 2 work fine, maybe | |
| 6741 | we can remove this restriction | |
| 6731 | {#syntax#}T{#endsyntax#} must be a {#syntax#}bool{#endsyntax#}, a float, | |
| 6732 | an integer or an enum. | |
| 6742 | 6733 | </p> |
| 6743 | 6734 | {#header_close#} |
| 6744 | 6735 | {#header_open|@atomicRmw#} |
| ... | ... | @@ -6747,17 +6738,8 @@ async fn func(y: *i32) void { |
| 6747 | 6738 | This builtin function atomically modifies memory and then returns the previous value. |
| 6748 | 6739 | </p> |
| 6749 | 6740 | <p> |
| 6750 | {#syntax#}T{#endsyntax#} must be a pointer type, a {#syntax#}bool{#endsyntax#}, | |
| 6751 | or an integer whose bit count meets these requirements: | |
| 6752 | </p> | |
| 6753 | <ul> | |
| 6754 | <li>At least 8</li> | |
| 6755 | <li>At most the same as usize</li> | |
| 6756 | <li>Power of 2</li> | |
| 6757 | </ul> | |
| 6758 | <p> | |
| 6759 | TODO right now bool is not accepted. Also I think we could make non powers of 2 work fine, maybe | |
| 6760 | we can remove this restriction | |
| 6741 | {#syntax#}T{#endsyntax#} must be a {#syntax#}bool{#endsyntax#}, a float, | |
| 6742 | an integer or an enum. | |
| 6761 | 6743 | </p> |
| 6762 | 6744 | <p> |
| 6763 | 6745 | Supported operations: |
| ... | ... | @@ -6782,17 +6764,8 @@ async fn func(y: *i32) void { |
| 6782 | 6764 | This builtin function atomically stores a value. |
| 6783 | 6765 | </p> |
| 6784 | 6766 | <p> |
| 6785 | {#syntax#}T{#endsyntax#} must be a pointer type, a {#syntax#}bool{#endsyntax#}, a float, | |
| 6786 | an integer whose bit count meets these requirements: | |
| 6787 | </p> | |
| 6788 | <ul> | |
| 6789 | <li>At least 8</li> | |
| 6790 | <li>At most the same as usize</li> | |
| 6791 | <li>Power of 2</li> | |
| 6792 | </ul> or an enum with a valid integer tag type. | |
| 6793 | <p> | |
| 6794 | TODO right now bool is not accepted. Also I think we could make non powers of 2 work fine, maybe | |
| 6795 | we can remove this restriction | |
| 6767 | {#syntax#}T{#endsyntax#} must be a {#syntax#}bool{#endsyntax#}, a float, | |
| 6768 | an integer or an enum. | |
| 6796 | 6769 | </p> |
| 6797 | 6770 | {#header_close#} |
| 6798 | 6771 | {#header_open|@bitCast#} |
| ... | ... | @@ -7108,7 +7081,8 @@ fn cmpxchgStrongButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_v |
| 7108 | 7081 | more efficiently in machine instructions. |
| 7109 | 7082 | </p> |
| 7110 | 7083 | <p> |
| 7111 | {#syntax#}AtomicOrder{#endsyntax#} can be found with {#syntax#}@import("builtin").AtomicOrder{#endsyntax#}. | |
| 7084 | {#syntax#}T{#endsyntax#} must be a {#syntax#}bool{#endsyntax#}, a float, | |
| 7085 | an integer or an enum. | |
| 7112 | 7086 | </p> |
| 7113 | 7087 | <p>{#syntax#}@TypeOf(ptr).alignment{#endsyntax#} must be {#syntax#}>= @sizeOf(T).{#endsyntax#}</p> |
| 7114 | 7088 | {#see_also|Compile Variables|cmpxchgWeak#} |
| ... | ... | @@ -7136,7 +7110,8 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val |
| 7136 | 7110 | However if you need a stronger guarantee, use {#link|@cmpxchgStrong#}. |
| 7137 | 7111 | </p> |
| 7138 | 7112 | <p> |
| 7139 | {#syntax#}AtomicOrder{#endsyntax#} can be found with {#syntax#}@import("builtin").AtomicOrder{#endsyntax#}. | |
| 7113 | {#syntax#}T{#endsyntax#} must be a {#syntax#}bool{#endsyntax#}, a float, | |
| 7114 | an integer or an enum. | |
| 7140 | 7115 | </p> |
| 7141 | 7116 | <p>{#syntax#}@TypeOf(ptr).alignment{#endsyntax#} must be {#syntax#}>= @sizeOf(T).{#endsyntax#}</p> |
| 7142 | 7117 | {#see_also|Compile Variables|cmpxchgStrong#} |
src/codegen.cpp+5-5| ... | ... | @@ -5229,8 +5229,8 @@ static LLVMValueRef ir_render_cmpxchg(CodeGen *g, IrExecutableGen *executable, I |
| 5229 | 5229 | // operand needs widening and truncating |
| 5230 | 5230 | ptr_val = LLVMBuildBitCast(g->builder, ptr_val, |
| 5231 | 5231 | LLVMPointerType(get_llvm_type(g, instruction->actual_type), 0), ""); |
| 5232 | cmp_val = LLVMConstZExt(cmp_val, get_llvm_type(g, instruction->actual_type)); | |
| 5233 | new_val = LLVMConstZExt(new_val, get_llvm_type(g, instruction->actual_type)); | |
| 5232 | cmp_val = LLVMBuildZExt(g->builder, cmp_val, get_llvm_type(g, instruction->actual_type), ""); | |
| 5233 | new_val = LLVMBuildZExt(g->builder, new_val, get_llvm_type(g, instruction->actual_type), ""); | |
| 5234 | 5234 | } |
| 5235 | 5235 | |
| 5236 | 5236 | LLVMAtomicOrdering success_order = to_LLVMAtomicOrdering(instruction->success_order); |
| ... | ... | @@ -5846,7 +5846,7 @@ static LLVMValueRef ir_render_atomic_rmw(CodeGen *g, IrExecutableGen *executable |
| 5846 | 5846 | // operand needs widening and truncating |
| 5847 | 5847 | LLVMValueRef casted_ptr = LLVMBuildBitCast(g->builder, ptr, |
| 5848 | 5848 | LLVMPointerType(get_llvm_type(g, instruction->actual_type), 0), ""); |
| 5849 | LLVMValueRef casted_operand = LLVMBuildPtrToInt(g->builder, operand, get_llvm_type(g, instruction->actual_type), ""); | |
| 5849 | LLVMValueRef casted_operand = LLVMBuildZExt(g->builder, operand, get_llvm_type(g, instruction->actual_type), ""); | |
| 5850 | 5850 | LLVMValueRef uncasted_result = ZigLLVMBuildAtomicRMW(g->builder, op, casted_ptr, casted_operand, ordering, |
| 5851 | 5851 | g->is_single_threaded); |
| 5852 | 5852 | return LLVMBuildTrunc(g->builder, uncasted_result, get_llvm_type(g, operand_type), ""); |
| ... | ... | @@ -5893,10 +5893,10 @@ static LLVMValueRef ir_render_atomic_store(CodeGen *g, IrExecutableGen *executab |
| 5893 | 5893 | LLVMValueRef value = ir_llvm_value(g, instruction->value); |
| 5894 | 5894 | |
| 5895 | 5895 | if (instruction->actual_type != nullptr) { |
| 5896 | // operand needs widening and truncating | |
| 5896 | // operand needs widening | |
| 5897 | 5897 | ptr = LLVMBuildBitCast(g->builder, ptr, |
| 5898 | 5898 | LLVMPointerType(get_llvm_type(g, instruction->actual_type), 0), ""); |
| 5899 | value = LLVMConstZExt(value, get_llvm_type(g, instruction->actual_type)); | |
| 5899 | value = LLVMBuildZExt(g->builder, value, get_llvm_type(g, instruction->actual_type), ""); | |
| 5900 | 5900 | } |
| 5901 | 5901 | LLVMValueRef store_inst = gen_store(g, value, ptr, instruction->ptr->value->type); |
| 5902 | 5902 | LLVMSetOrdering(store_inst, ordering); |
test/stage1/behavior/atomics.zig+2-3| ... | ... | @@ -167,7 +167,7 @@ fn testAtomicRmwFloat() void { |
| 167 | 167 | |
| 168 | 168 | test "atomics with different types" { |
| 169 | 169 | testAtomicsWithType(bool, true, false); |
| 170 | inline for (.{ u1, i5, u33 }) |T| { | |
| 170 | inline for (.{ u1, i5, u15 }) |T| { | |
| 171 | 171 | var x: T = 0; |
| 172 | 172 | testAtomicsWithType(T, 0, 1); |
| 173 | 173 | } |
| ... | ... | @@ -175,8 +175,7 @@ test "atomics with different types" { |
| 175 | 175 | testAtomicsWithType(i0, 0, 0); |
| 176 | 176 | } |
| 177 | 177 | |
| 178 | // a and b souldn't need to be comptime | |
| 179 | fn testAtomicsWithType(comptime T: type, comptime a: T, comptime b: T) void { | |
| 178 | fn testAtomicsWithType(comptime T: type, a: T, b: T) void { | |
| 180 | 179 | var x: T = b; |
| 181 | 180 | @atomicStore(T, &x, a, .SeqCst); |
| 182 | 181 | expect(x == a); |