authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-04-15 18:12:00-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-04-15 18:12:00-04:00
logb9360640cefd1aa30dedf71a0c6b7bddc51a6ae3
tree89c751d93d98bee02e77fd7ac015845f398d8afd
parent859b10d8bfcca3c4a30798b4522fd88ec6c66de6

add @atomicLoad builtin

See #174

7 files changed, 183 insertions(+), 11 deletions(-)

doc/langref.html.in+20-1
...@@ -3880,6 +3880,25 @@ pub fn main() void {...@@ -3880,6 +3880,25 @@ pub fn main() void {
3880 {#header_open|@ArgType#}3880 {#header_open|@ArgType#}
3881 <p>TODO</p>3881 <p>TODO</p>
3882 {#header_close#}3882 {#header_close#}
3883 {#header_open|@atomicLoad#}
3884 <pre><code class="zig">@atomicLoad(comptime T: type, ptr: &amp;const T, comptime ordering: builtin.AtomicOrder) -&gt; T</code></pre>
3885 <p>
3886 This builtin function atomically dereferences a pointer and returns the value.
3887 </p>
3888 <p>
3889 <code>T</code> must be a pointer type, a <code>bool</code>,
3890 or an integer whose bit count meets these requirements:
3891 </p>
3892 <ul>
3893 <li>At least 8</li>
3894 <li>At most the same as usize</li>
3895 <li>Power of 2</li>
3896 </ul>
3897 <p>
3898 TODO right now bool is not accepted. Also I think we could make non powers of 2 work fine, maybe
3899 we can remove this restriction
3900 </p>
3901 {#header_close#}
3883 {#header_open|@atomicRmw#}3902 {#header_open|@atomicRmw#}
3884 <pre><code class="zig">@atomicRmw(comptime T: type, ptr: &amp;T, comptime op: builtin.AtomicRmwOp, operand: T, comptime ordering: builtin.AtomicOrder) -&gt; T</code></pre>3903 <pre><code class="zig">@atomicRmw(comptime T: type, ptr: &amp;T, comptime op: builtin.AtomicRmwOp, operand: T, comptime ordering: builtin.AtomicOrder) -&gt; T</code></pre>
3885 <p>3904 <p>
...@@ -6001,7 +6020,7 @@ hljs.registerLanguage("zig", function(t) {...@@ -6001,7 +6020,7 @@ hljs.registerLanguage("zig", function(t) {
6001 a = t.IR + "\\s*\\(",6020 a = t.IR + "\\s*\\(",
6002 c = {6021 c = {
6003 keyword: "const align var extern stdcallcc nakedcc volatile export pub noalias inline struct packed enum union break return try catch test continue unreachable comptime and or asm defer errdefer if else switch while for fn use bool f32 f64 void type noreturn error i8 u8 i16 u16 i32 u32 i64 u64 isize usize i8w u8w i16w i32w u32w i64w u64w isizew usizew c_short c_ushort c_int c_uint c_long c_ulong c_longlong c_ulonglong",6022 keyword: "const align var extern stdcallcc nakedcc volatile export pub noalias inline struct packed enum union break return try catch test continue unreachable comptime and or asm defer errdefer if else switch while for fn use bool f32 f64 void type noreturn error i8 u8 i16 u16 i32 u32 i64 u64 isize usize i8w u8w i16w i32w u32w i64w u64w isizew usizew c_short c_ushort c_int c_uint c_long c_ulong c_longlong c_ulonglong",
6004 built_in: "breakpoint returnAddress frameAddress fieldParentPtr setFloatMode IntType OpaqueType compileError compileLog setCold setRuntimeSafety setEvalBranchQuota offsetOf memcpy inlineCall setGlobalLinkage setGlobalSection divTrunc divFloor enumTagName intToPtr ptrToInt panic canImplicitCast ptrCast bitCast rem mod memset sizeOf alignOf alignCast maxValue minValue memberCount memberName memberType typeOf addWithOverflow subWithOverflow mulWithOverflow shlWithOverflow shlExact shrExact cInclude cDefine cUndef ctz clz import cImport errorName embedFile cmpxchg fence divExact truncate atomicRmw sqrt",6023 built_in: "atomicLoad breakpoint returnAddress frameAddress fieldParentPtr setFloatMode IntType OpaqueType compileError compileLog setCold setRuntimeSafety setEvalBranchQuota offsetOf memcpy inlineCall setGlobalLinkage setGlobalSection divTrunc divFloor enumTagName intToPtr ptrToInt panic canImplicitCast ptrCast bitCast rem mod memset sizeOf alignOf alignCast maxValue minValue memberCount memberName memberType typeOf addWithOverflow subWithOverflow mulWithOverflow shlWithOverflow shlExact shrExact cInclude cDefine cUndef ctz clz import cImport errorName embedFile cmpxchg fence divExact truncate atomicRmw sqrt",
6005 literal: "true false null undefined"6024 literal: "true false null undefined"
6006 },6025 },
6007 n = [e, t.CLCM, t.CBCM, s, r];6026 n = [e, t.CLCM, t.CBCM, s, r];
src/all_types.hpp+11
...@@ -1347,6 +1347,7 @@ enum BuiltinFnId {...@@ -1347,6 +1347,7 @@ enum BuiltinFnId {
1347 BuiltinFnIdExport,1347 BuiltinFnIdExport,
1348 BuiltinFnIdErrorReturnTrace,1348 BuiltinFnIdErrorReturnTrace,
1349 BuiltinFnIdAtomicRmw,1349 BuiltinFnIdAtomicRmw,
1350 BuiltinFnIdAtomicLoad,
1350};1351};
13511352
1352struct BuiltinFnEntry {1353struct BuiltinFnEntry {
...@@ -2043,6 +2044,7 @@ enum IrInstructionId {...@@ -2043,6 +2044,7 @@ enum IrInstructionId {
2043 IrInstructionIdCoroPromise,2044 IrInstructionIdCoroPromise,
2044 IrInstructionIdCoroAllocHelper,2045 IrInstructionIdCoroAllocHelper,
2045 IrInstructionIdAtomicRmw,2046 IrInstructionIdAtomicRmw,
2047 IrInstructionIdAtomicLoad,
2046 IrInstructionIdPromiseResultType,2048 IrInstructionIdPromiseResultType,
2047 IrInstructionIdAwaitBookkeeping,2049 IrInstructionIdAwaitBookkeeping,
2048 IrInstructionIdSaveErrRetAddr,2050 IrInstructionIdSaveErrRetAddr,
...@@ -3003,6 +3005,15 @@ struct IrInstructionAtomicRmw {...@@ -3003,6 +3005,15 @@ struct IrInstructionAtomicRmw {
3003 AtomicOrder resolved_ordering;3005 AtomicOrder resolved_ordering;
3004};3006};
30053007
3008struct IrInstructionAtomicLoad {
3009 IrInstruction base;
3010
3011 IrInstruction *operand_type;
3012 IrInstruction *ptr;
3013 IrInstruction *ordering;
3014 AtomicOrder resolved_ordering;
3015};
3016
3006struct IrInstructionPromiseResultType {3017struct IrInstructionPromiseResultType {
3007 IrInstruction base;3018 IrInstruction base;
30083019
src/codegen.cpp+13
...@@ -4385,6 +4385,16 @@ static LLVMValueRef ir_render_atomic_rmw(CodeGen *g, IrExecutable *executable,...@@ -4385,6 +4385,16 @@ static LLVMValueRef ir_render_atomic_rmw(CodeGen *g, IrExecutable *executable,
4385 return LLVMBuildIntToPtr(g->builder, uncasted_result, operand_type->type_ref, "");4385 return LLVMBuildIntToPtr(g->builder, uncasted_result, operand_type->type_ref, "");
4386}4386}
43874387
4388static LLVMValueRef ir_render_atomic_load(CodeGen *g, IrExecutable *executable,
4389 IrInstructionAtomicLoad *instruction)
4390{
4391 LLVMAtomicOrdering ordering = to_LLVMAtomicOrdering(instruction->resolved_ordering);
4392 LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr);
4393 LLVMValueRef load_inst = gen_load(g, ptr, instruction->ptr->value.type, "");
4394 LLVMSetOrdering(load_inst, ordering);
4395 return load_inst;
4396}
4397
4388static LLVMValueRef ir_render_merge_err_ret_traces(CodeGen *g, IrExecutable *executable,4398static LLVMValueRef ir_render_merge_err_ret_traces(CodeGen *g, IrExecutable *executable,
4389 IrInstructionMergeErrRetTraces *instruction)4399 IrInstructionMergeErrRetTraces *instruction)
4390{4400{
...@@ -4628,6 +4638,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -4628,6 +4638,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
4628 return ir_render_coro_alloc_helper(g, executable, (IrInstructionCoroAllocHelper *)instruction);4638 return ir_render_coro_alloc_helper(g, executable, (IrInstructionCoroAllocHelper *)instruction);
4629 case IrInstructionIdAtomicRmw:4639 case IrInstructionIdAtomicRmw:
4630 return ir_render_atomic_rmw(g, executable, (IrInstructionAtomicRmw *)instruction);4640 return ir_render_atomic_rmw(g, executable, (IrInstructionAtomicRmw *)instruction);
4641 case IrInstructionIdAtomicLoad:
4642 return ir_render_atomic_load(g, executable, (IrInstructionAtomicLoad *)instruction);
4631 case IrInstructionIdSaveErrRetAddr:4643 case IrInstructionIdSaveErrRetAddr:
4632 return ir_render_save_err_ret_addr(g, executable, (IrInstructionSaveErrRetAddr *)instruction);4644 return ir_render_save_err_ret_addr(g, executable, (IrInstructionSaveErrRetAddr *)instruction);
4633 case IrInstructionIdMergeErrRetTraces:4645 case IrInstructionIdMergeErrRetTraces:
...@@ -6136,6 +6148,7 @@ static void define_builtin_fns(CodeGen *g) {...@@ -6136,6 +6148,7 @@ static void define_builtin_fns(CodeGen *g) {
6136 create_builtin_fn(g, BuiltinFnIdExport, "export", 3);6148 create_builtin_fn(g, BuiltinFnIdExport, "export", 3);
6137 create_builtin_fn(g, BuiltinFnIdErrorReturnTrace, "errorReturnTrace", 0);6149 create_builtin_fn(g, BuiltinFnIdErrorReturnTrace, "errorReturnTrace", 0);
6138 create_builtin_fn(g, BuiltinFnIdAtomicRmw, "atomicRmw", 5);6150 create_builtin_fn(g, BuiltinFnIdAtomicRmw, "atomicRmw", 5);
6151 create_builtin_fn(g, BuiltinFnIdAtomicLoad, "atomicLoad", 3);
6139}6152}
61406153
6141static const char *bool_to_str(bool b) {6154static const char *bool_to_str(bool b) {
src/ir.cpp+104-8
...@@ -709,6 +709,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionAtomicRmw *) {...@@ -709,6 +709,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionAtomicRmw *) {
709 return IrInstructionIdAtomicRmw;709 return IrInstructionIdAtomicRmw;
710}710}
711711
712static constexpr IrInstructionId ir_instruction_id(IrInstructionAtomicLoad *) {
713 return IrInstructionIdAtomicLoad;
714}
715
712static constexpr IrInstructionId ir_instruction_id(IrInstructionPromiseResultType *) {716static constexpr IrInstructionId ir_instruction_id(IrInstructionPromiseResultType *) {
713 return IrInstructionIdPromiseResultType;717 return IrInstructionIdPromiseResultType;
714}718}
...@@ -2673,6 +2677,23 @@ static IrInstruction *ir_build_atomic_rmw(IrBuilder *irb, Scope *scope, AstNode...@@ -2673,6 +2677,23 @@ static IrInstruction *ir_build_atomic_rmw(IrBuilder *irb, Scope *scope, AstNode
2673 return &instruction->base;2677 return &instruction->base;
2674}2678}
26752679
2680static IrInstruction *ir_build_atomic_load(IrBuilder *irb, Scope *scope, AstNode *source_node,
2681 IrInstruction *operand_type, IrInstruction *ptr,
2682 IrInstruction *ordering, AtomicOrder resolved_ordering)
2683{
2684 IrInstructionAtomicLoad *instruction = ir_build_instruction<IrInstructionAtomicLoad>(irb, scope, source_node);
2685 instruction->operand_type = operand_type;
2686 instruction->ptr = ptr;
2687 instruction->ordering = ordering;
2688 instruction->resolved_ordering = resolved_ordering;
2689
2690 if (operand_type != nullptr) ir_ref_instruction(operand_type, irb->current_basic_block);
2691 ir_ref_instruction(ptr, irb->current_basic_block);
2692 if (ordering != nullptr) ir_ref_instruction(ordering, irb->current_basic_block);
2693
2694 return &instruction->base;
2695}
2696
2676static IrInstruction *ir_build_promise_result_type(IrBuilder *irb, Scope *scope, AstNode *source_node,2697static IrInstruction *ir_build_promise_result_type(IrBuilder *irb, Scope *scope, AstNode *source_node,
2677 IrInstruction *promise_type)2698 IrInstruction *promise_type)
2678{2699{
...@@ -4303,6 +4324,27 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -4303,6 +4324,27 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
4303 // these 2 values don't mean anything since we passed non-null values for other args4324 // these 2 values don't mean anything since we passed non-null values for other args
4304 AtomicRmwOp_xchg, AtomicOrderMonotonic);4325 AtomicRmwOp_xchg, AtomicOrderMonotonic);
4305 }4326 }
4327 case BuiltinFnIdAtomicLoad:
4328 {
4329 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
4330 IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope);
4331 if (arg0_value == irb->codegen->invalid_instruction)
4332 return arg0_value;
4333
4334 AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
4335 IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope);
4336 if (arg1_value == irb->codegen->invalid_instruction)
4337 return arg1_value;
4338
4339 AstNode *arg2_node = node->data.fn_call_expr.params.at(2);
4340 IrInstruction *arg2_value = ir_gen_node(irb, arg2_node, scope);
4341 if (arg2_value == irb->codegen->invalid_instruction)
4342 return arg2_value;
4343
4344 return ir_build_atomic_load(irb, scope, node, arg0_value, arg1_value, arg2_value,
4345 // this value does not mean anything since we passed non-null values for other arg
4346 AtomicOrderMonotonic);
4347 }
4306 }4348 }
4307 zig_unreachable();4349 zig_unreachable();
4308}4350}
...@@ -17898,35 +17940,43 @@ static TypeTableEntry *ir_analyze_instruction_coro_alloc_helper(IrAnalyze *ira,...@@ -17898,35 +17940,43 @@ static TypeTableEntry *ir_analyze_instruction_coro_alloc_helper(IrAnalyze *ira,
17898 return result->value.type;17940 return result->value.type;
17899}17941}
1790017942
17901static TypeTableEntry *ir_analyze_instruction_atomic_rmw(IrAnalyze *ira, IrInstructionAtomicRmw *instruction) {17943static TypeTableEntry *ir_resolve_atomic_operand_type(IrAnalyze *ira, IrInstruction *op) {
17902 TypeTableEntry *operand_type = ir_resolve_type(ira, instruction->operand_type->other);17944 TypeTableEntry *operand_type = ir_resolve_type(ira, op);
17903 if (type_is_invalid(operand_type)) {17945 if (type_is_invalid(operand_type))
17904 return ira->codegen->builtin_types.entry_invalid;17946 return ira->codegen->builtin_types.entry_invalid;
17905 }17947
17906 if (operand_type->id == TypeTableEntryIdInt) {17948 if (operand_type->id == TypeTableEntryIdInt) {
17907 if (operand_type->data.integral.bit_count < 8) {17949 if (operand_type->data.integral.bit_count < 8) {
17908 ir_add_error(ira, &instruction->base,17950 ir_add_error(ira, op,
17909 buf_sprintf("expected integer type 8 bits or larger, found %" PRIu32 "-bit integer type",17951 buf_sprintf("expected integer type 8 bits or larger, found %" PRIu32 "-bit integer type",
17910 operand_type->data.integral.bit_count));17952 operand_type->data.integral.bit_count));
17911 return ira->codegen->builtin_types.entry_invalid;17953 return ira->codegen->builtin_types.entry_invalid;
17912 }17954 }
17913 if (operand_type->data.integral.bit_count > ira->codegen->pointer_size_bytes * 8) {17955 if (operand_type->data.integral.bit_count > ira->codegen->pointer_size_bytes * 8) {
17914 ir_add_error(ira, &instruction->base,17956 ir_add_error(ira, op,
17915 buf_sprintf("expected integer type pointer size or smaller, found %" PRIu32 "-bit integer type",17957 buf_sprintf("expected integer type pointer size or smaller, found %" PRIu32 "-bit integer type",
17916 operand_type->data.integral.bit_count));17958 operand_type->data.integral.bit_count));
17917 return ira->codegen->builtin_types.entry_invalid;17959 return ira->codegen->builtin_types.entry_invalid;
17918 }17960 }
17919 if (!is_power_of_2(operand_type->data.integral.bit_count)) {17961 if (!is_power_of_2(operand_type->data.integral.bit_count)) {
17920 ir_add_error(ira, &instruction->base,17962 ir_add_error(ira, op,
17921 buf_sprintf("%" PRIu32 "-bit integer type is not a power of 2", operand_type->data.integral.bit_count));17963 buf_sprintf("%" PRIu32 "-bit integer type is not a power of 2", operand_type->data.integral.bit_count));
17922 return ira->codegen->builtin_types.entry_invalid;17964 return ira->codegen->builtin_types.entry_invalid;
17923 }17965 }
17924 } else if (get_codegen_ptr_type(operand_type) == nullptr) {17966 } else if (get_codegen_ptr_type(operand_type) == nullptr) {
17925 ir_add_error(ira, &instruction->base,17967 ir_add_error(ira, op,
17926 buf_sprintf("expected integer or pointer type, found '%s'", buf_ptr(&operand_type->name)));17968 buf_sprintf("expected integer or pointer type, found '%s'", buf_ptr(&operand_type->name)));
17927 return ira->codegen->builtin_types.entry_invalid;17969 return ira->codegen->builtin_types.entry_invalid;
17928 }17970 }
1792917971
17972 return operand_type;
17973}
17974
17975static TypeTableEntry *ir_analyze_instruction_atomic_rmw(IrAnalyze *ira, IrInstructionAtomicRmw *instruction) {
17976 TypeTableEntry *operand_type = ir_resolve_atomic_operand_type(ira, instruction->operand_type->other);
17977 if (type_is_invalid(operand_type))
17978 return ira->codegen->builtin_types.entry_invalid;
17979
17930 IrInstruction *ptr_inst = instruction->ptr->other;17980 IrInstruction *ptr_inst = instruction->ptr->other;
17931 if (type_is_invalid(ptr_inst->value.type))17981 if (type_is_invalid(ptr_inst->value.type))
17932 return ira->codegen->builtin_types.entry_invalid;17982 return ira->codegen->builtin_types.entry_invalid;
...@@ -17974,6 +18024,49 @@ static TypeTableEntry *ir_analyze_instruction_atomic_rmw(IrAnalyze *ira, IrInstr...@@ -17974,6 +18024,49 @@ static TypeTableEntry *ir_analyze_instruction_atomic_rmw(IrAnalyze *ira, IrInstr
17974 return result->value.type;18024 return result->value.type;
17975}18025}
1797618026
18027static TypeTableEntry *ir_analyze_instruction_atomic_load(IrAnalyze *ira, IrInstructionAtomicLoad *instruction) {
18028 TypeTableEntry *operand_type = ir_resolve_atomic_operand_type(ira, instruction->operand_type->other);
18029 if (type_is_invalid(operand_type))
18030 return ira->codegen->builtin_types.entry_invalid;
18031
18032 IrInstruction *ptr_inst = instruction->ptr->other;
18033 if (type_is_invalid(ptr_inst->value.type))
18034 return ira->codegen->builtin_types.entry_invalid;
18035
18036 TypeTableEntry *ptr_type = get_pointer_to_type(ira->codegen, operand_type, true);
18037 IrInstruction *casted_ptr = ir_implicit_cast(ira, ptr_inst, ptr_type);
18038 if (type_is_invalid(casted_ptr->value.type))
18039 return ira->codegen->builtin_types.entry_invalid;
18040
18041 AtomicOrder ordering;
18042 if (instruction->ordering == nullptr) {
18043 ordering = instruction->resolved_ordering;
18044 } else {
18045 if (!ir_resolve_atomic_order(ira, instruction->ordering->other, &ordering))
18046 return ira->codegen->builtin_types.entry_invalid;
18047 }
18048
18049 if (ordering == AtomicOrderRelease || ordering == AtomicOrderAcqRel) {
18050 assert(instruction->ordering != nullptr);
18051 ir_add_error(ira, instruction->ordering,
18052 buf_sprintf("@atomicLoad atomic ordering must not be Release or AcqRel"));
18053 return ira->codegen->builtin_types.entry_invalid;
18054 }
18055
18056 if (instr_is_comptime(casted_ptr)) {
18057 IrInstruction *result = ir_get_deref(ira, &instruction->base, casted_ptr);
18058 ir_link_new_instruction(result, &instruction->base);
18059 assert(result->value.type != nullptr);
18060 return result->value.type;
18061 }
18062
18063 IrInstruction *result = ir_build_atomic_load(&ira->new_irb, instruction->base.scope,
18064 instruction->base.source_node, nullptr, casted_ptr, nullptr, ordering);
18065 ir_link_new_instruction(result, &instruction->base);
18066 result->value.type = operand_type;
18067 return result->value.type;
18068}
18069
17977static TypeTableEntry *ir_analyze_instruction_promise_result_type(IrAnalyze *ira, IrInstructionPromiseResultType *instruction) {18070static TypeTableEntry *ir_analyze_instruction_promise_result_type(IrAnalyze *ira, IrInstructionPromiseResultType *instruction) {
17978 TypeTableEntry *promise_type = ir_resolve_type(ira, instruction->promise_type->other);18071 TypeTableEntry *promise_type = ir_resolve_type(ira, instruction->promise_type->other);
17979 if (type_is_invalid(promise_type))18072 if (type_is_invalid(promise_type))
...@@ -18357,6 +18450,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi...@@ -18357,6 +18450,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
18357 return ir_analyze_instruction_coro_alloc_helper(ira, (IrInstructionCoroAllocHelper *)instruction);18450 return ir_analyze_instruction_coro_alloc_helper(ira, (IrInstructionCoroAllocHelper *)instruction);
18358 case IrInstructionIdAtomicRmw:18451 case IrInstructionIdAtomicRmw:
18359 return ir_analyze_instruction_atomic_rmw(ira, (IrInstructionAtomicRmw *)instruction);18452 return ir_analyze_instruction_atomic_rmw(ira, (IrInstructionAtomicRmw *)instruction);
18453 case IrInstructionIdAtomicLoad:
18454 return ir_analyze_instruction_atomic_load(ira, (IrInstructionAtomicLoad *)instruction);
18360 case IrInstructionIdPromiseResultType:18455 case IrInstructionIdPromiseResultType:
18361 return ir_analyze_instruction_promise_result_type(ira, (IrInstructionPromiseResultType *)instruction);18456 return ir_analyze_instruction_promise_result_type(ira, (IrInstructionPromiseResultType *)instruction);
18362 case IrInstructionIdAwaitBookkeeping:18457 case IrInstructionIdAwaitBookkeeping:
...@@ -18584,6 +18679,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -18584,6 +18679,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
18584 case IrInstructionIdCoroPromise:18679 case IrInstructionIdCoroPromise:
18585 case IrInstructionIdPromiseResultType:18680 case IrInstructionIdPromiseResultType:
18586 case IrInstructionIdSqrt:18681 case IrInstructionIdSqrt:
18682 case IrInstructionIdAtomicLoad:
18587 return false;18683 return false;
1858818684
18589 case IrInstructionIdAsm:18685 case IrInstructionIdAsm:
src/ir_print.cpp+21
...@@ -1172,6 +1172,24 @@ static void ir_print_atomic_rmw(IrPrint *irp, IrInstructionAtomicRmw *instructio...@@ -1172,6 +1172,24 @@ static void ir_print_atomic_rmw(IrPrint *irp, IrInstructionAtomicRmw *instructio
1172 fprintf(irp->f, ")");1172 fprintf(irp->f, ")");
1173}1173}
11741174
1175static void ir_print_atomic_load(IrPrint *irp, IrInstructionAtomicLoad *instruction) {
1176 fprintf(irp->f, "@atomicLoad(");
1177 if (instruction->operand_type != nullptr) {
1178 ir_print_other_instruction(irp, instruction->operand_type);
1179 } else {
1180 fprintf(irp->f, "[TODO print]");
1181 }
1182 fprintf(irp->f, ",");
1183 ir_print_other_instruction(irp, instruction->ptr);
1184 fprintf(irp->f, ",");
1185 if (instruction->ordering != nullptr) {
1186 ir_print_other_instruction(irp, instruction->ordering);
1187 } else {
1188 fprintf(irp->f, "[TODO print]");
1189 }
1190 fprintf(irp->f, ")");
1191}
1192
1175static void ir_print_await_bookkeeping(IrPrint *irp, IrInstructionAwaitBookkeeping *instruction) {1193static void ir_print_await_bookkeeping(IrPrint *irp, IrInstructionAwaitBookkeeping *instruction) {
1176 fprintf(irp->f, "@awaitBookkeeping(");1194 fprintf(irp->f, "@awaitBookkeeping(");
1177 ir_print_other_instruction(irp, instruction->promise_result_type);1195 ir_print_other_instruction(irp, instruction->promise_result_type);
...@@ -1605,6 +1623,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {...@@ -1605,6 +1623,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
1605 case IrInstructionIdSqrt:1623 case IrInstructionIdSqrt:
1606 ir_print_sqrt(irp, (IrInstructionSqrt *)instruction);1624 ir_print_sqrt(irp, (IrInstructionSqrt *)instruction);
1607 break;1625 break;
1626 case IrInstructionIdAtomicLoad:
1627 ir_print_atomic_load(irp, (IrInstructionAtomicLoad *)instruction);
1628 break;
1608 }1629 }
1609 fprintf(irp->f, "\n");1630 fprintf(irp->f, "\n");
1610}1631}
std/os/index.zig+1-1
...@@ -2392,7 +2392,7 @@ pub const Thread = struct {...@@ -2392,7 +2392,7 @@ pub const Thread = struct {
23922392
2393 pub fn wait(self: &const Thread) void {2393 pub fn wait(self: &const Thread) void {
2394 while (true) {2394 while (true) {
2395 const pid_value = self.pid; // TODO atomic load2395 const pid_value = @atomicLoad(i32, &self.pid, builtin.AtomicOrder.SeqCst);
2396 if (pid_value == 0) break;2396 if (pid_value == 0) break;
2397 const rc = linux.futex_wait(@ptrToInt(&self.pid), linux.FUTEX_WAIT, pid_value, null);2397 const rc = linux.futex_wait(@ptrToInt(&self.pid), linux.FUTEX_WAIT, pid_value, null);
2398 switch (linux.getErrno(rc)) {2398 switch (linux.getErrno(rc)) {
test/cases/atomics.zig+13-1
...@@ -15,13 +15,25 @@ test "fence" {...@@ -15,13 +15,25 @@ test "fence" {
15 x = 5678;15 x = 5678;
16}16}
1717
18test "atomicrmw" {18test "atomicrmw and atomicload" {
19 var data: u8 = 200;19 var data: u8 = 200;
20 testAtomicRmw(&data);20 testAtomicRmw(&data);
21 assert(data == 42);21 assert(data == 42);
22 testAtomicLoad(&data);
22}23}
2324
24fn testAtomicRmw(ptr: &u8) void {25fn testAtomicRmw(ptr: &u8) void {
25 const prev_value = @atomicRmw(u8, ptr, AtomicRmwOp.Xchg, 42, AtomicOrder.SeqCst);26 const prev_value = @atomicRmw(u8, ptr, AtomicRmwOp.Xchg, 42, AtomicOrder.SeqCst);
26 assert(prev_value == 200);27 assert(prev_value == 200);
28 comptime {
29 var x: i32 = 1234;
30 const y: i32 = 12345;
31 assert(@atomicLoad(i32, &x, AtomicOrder.SeqCst) == 1234);
32 assert(@atomicLoad(i32, &y, AtomicOrder.SeqCst) == 12345);
33 }
34}
35
36fn testAtomicLoad(ptr: &u8) void {
37 const x = @atomicLoad(u8, ptr, AtomicOrder.SeqCst);
38 assert(x == 42);
27}39}