@@ -709,6 +709,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionAtomicRmw *) {
709
709
return IrInstructionIdAtomicRmw;
710
710
}
711
711
712
+ static constexpr IrInstructionId ir_instruction_id(IrInstructionAtomicLoad *) {
713
+ return IrInstructionIdAtomicLoad;
714
+ }
715
+
712
716
static constexpr IrInstructionId ir_instruction_id(IrInstructionPromiseResultType *) {
713
717
return IrInstructionIdPromiseResultType;
714
718
}
@@ -2673,6 +2677,23 @@ static IrInstruction *ir_build_atomic_rmw(IrBuilder *irb, Scope *scope, AstNode
2673
2677
return &instruction->base;
2674
2678
}
2675
2679
2680
+ static 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
+
2676
2697
static IrInstruction *ir_build_promise_result_type(IrBuilder *irb, Scope *scope, AstNode *source_node,
2677
2698
IrInstruction *promise_type)
2678
2699
{
@@ -4303,6 +4324,27 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
4303
4324
// these 2 values don't mean anything since we passed non-null values for other args
4304
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
4349
zig_unreachable();
4308
4350
}
@@ -17898,35 +17940,43 @@ static TypeTableEntry *ir_analyze_instruction_coro_alloc_helper(IrAnalyze *ira,
17898
17940
return result->value.type;
17899
17941
}
17900
17942
17901
- static TypeTableEntry *ir_analyze_instruction_atomic_rmw (IrAnalyze *ira, IrInstructionAtomicRmw *instruction ) {
17902
- TypeTableEntry *operand_type = ir_resolve_type(ira, instruction->operand_type->other );
17903
- if (type_is_invalid(operand_type)) {
17943
+ static TypeTableEntry *ir_resolve_atomic_operand_type (IrAnalyze *ira, IrInstruction *op ) {
17944
+ TypeTableEntry *operand_type = ir_resolve_type(ira, op );
17945
+ if (type_is_invalid(operand_type))
17904
17946
return ira->codegen->builtin_types.entry_invalid;
17905
- }
17947
+
17906
17948
if (operand_type->id == TypeTableEntryIdInt) {
17907
17949
if (operand_type->data.integral.bit_count < 8) {
17908
- ir_add_error(ira, &instruction->base ,
17950
+ ir_add_error(ira, op ,
17909
17951
buf_sprintf("expected integer type 8 bits or larger, found %" PRIu32 "-bit integer type",
17910
17952
operand_type->data.integral.bit_count));
17911
17953
return ira->codegen->builtin_types.entry_invalid;
17912
17954
}
17913
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
17957
buf_sprintf("expected integer type pointer size or smaller, found %" PRIu32 "-bit integer type",
17916
17958
operand_type->data.integral.bit_count));
17917
17959
return ira->codegen->builtin_types.entry_invalid;
17918
17960
}
17919
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
17963
buf_sprintf("%" PRIu32 "-bit integer type is not a power of 2", operand_type->data.integral.bit_count));
17922
17964
return ira->codegen->builtin_types.entry_invalid;
17923
17965
}
17924
17966
} else if (get_codegen_ptr_type(operand_type) == nullptr) {
17925
- ir_add_error(ira, &instruction->base ,
17967
+ ir_add_error(ira, op ,
17926
17968
buf_sprintf("expected integer or pointer type, found '%s'", buf_ptr(&operand_type->name)));
17927
17969
return ira->codegen->builtin_types.entry_invalid;
17928
17970
}
17929
17971
17972
+ return operand_type;
17973
+ }
17974
+
17975
+ static 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
17980
IrInstruction *ptr_inst = instruction->ptr->other;
17931
17981
if (type_is_invalid(ptr_inst->value.type))
17932
17982
return ira->codegen->builtin_types.entry_invalid;
@@ -17974,6 +18024,49 @@ static TypeTableEntry *ir_analyze_instruction_atomic_rmw(IrAnalyze *ira, IrInstr
17974
18024
return result->value.type;
17975
18025
}
17976
18026
18027
+ static 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
+
17977
18070
static TypeTableEntry *ir_analyze_instruction_promise_result_type(IrAnalyze *ira, IrInstructionPromiseResultType *instruction) {
17978
18071
TypeTableEntry *promise_type = ir_resolve_type(ira, instruction->promise_type->other);
17979
18072
if (type_is_invalid(promise_type))
@@ -18357,6 +18450,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
18357
18450
return ir_analyze_instruction_coro_alloc_helper(ira, (IrInstructionCoroAllocHelper *)instruction);
18358
18451
case IrInstructionIdAtomicRmw:
18359
18452
return ir_analyze_instruction_atomic_rmw(ira, (IrInstructionAtomicRmw *)instruction);
18453
+ case IrInstructionIdAtomicLoad:
18454
+ return ir_analyze_instruction_atomic_load(ira, (IrInstructionAtomicLoad *)instruction);
18360
18455
case IrInstructionIdPromiseResultType:
18361
18456
return ir_analyze_instruction_promise_result_type(ira, (IrInstructionPromiseResultType *)instruction);
18362
18457
case IrInstructionIdAwaitBookkeeping:
@@ -18584,6 +18679,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
18584
18679
case IrInstructionIdCoroPromise:
18585
18680
case IrInstructionIdPromiseResultType:
18586
18681
case IrInstructionIdSqrt:
18682
+ case IrInstructionIdAtomicLoad:
18587
18683
return false;
18588
18684
18589
18685
case IrInstructionIdAsm:
0 commit comments