| ... | ... | @@ -28436,14 +28436,84 @@ static IrInstGen *ir_analyze_instruction_atomic_rmw(IrAnalyze *ira, IrInstSrcAto |
| 28436 | 28436 | return ir_const_move(ira, &instruction->base.base, get_the_one_possible_value(ira->codegen, operand_type)); |
| 28437 | 28437 | } |
| 28438 | 28438 | |
| 28439 | | if (instr_is_comptime(casted_operand) && instr_is_comptime(casted_ptr) && casted_ptr->value->data.x_ptr.mut == ConstPtrMutComptimeVar) |
| 28440 | | { |
| 28441 | | ir_add_error(ira, &instruction->base.base, |
| 28442 | | buf_sprintf("compiler bug: TODO compile-time execution of @atomicRmw")); |
| 28443 | | return ira->codegen->invalid_inst_gen; |
| 28439 | IrInst *source_inst = &instruction->base.base; |
| 28440 | if (instr_is_comptime(casted_operand) && instr_is_comptime(casted_ptr) && casted_ptr->value->data.x_ptr.mut == ConstPtrMutComptimeVar) { |
| 28441 | ZigValue *ptr_val = ir_resolve_const(ira, casted_ptr, UndefBad); |
| 28442 | if (ptr_val == nullptr) |
| 28443 | return ira->codegen->invalid_inst_gen; |
| 28444 | |
| 28445 | ZigValue *op1_val = const_ptr_pointee(ira, ira->codegen, ptr_val, instruction->base.base.source_node); |
| 28446 | if (op1_val == nullptr) |
| 28447 | return ira->codegen->invalid_inst_gen; |
| 28448 | |
| 28449 | ZigValue *op2_val = ir_resolve_const(ira, casted_operand, UndefBad); |
| 28450 | if (op2_val == nullptr) |
| 28451 | return ira->codegen->invalid_inst_gen; |
| 28452 | |
| 28453 | if (op == AtomicRmwOp_xchg) { |
| 28454 | ir_analyze_store_ptr(ira, source_inst, casted_ptr, casted_operand, false); |
| 28455 | return ir_const_move(ira, source_inst, op1_val); |
| 28456 | } |
| 28457 | |
| 28458 | if (operand_type->id == ZigTypeIdPointer || operand_type->id == ZigTypeIdOptional) { |
| 28459 | ir_add_error(ira, &instruction->ordering->base, |
| 28460 | buf_sprintf("TODO comptime @atomicRmw with pointers other than .Xchg")); |
| 28461 | return ira->codegen->invalid_inst_gen; |
| 28462 | } |
| 28463 | |
| 28464 | if (op == AtomicRmwOp_min || op == AtomicRmwOp_max) { |
| 28465 | IrBinOp bin_op; |
| 28466 | if (op == AtomicRmwOp_min) |
| 28467 | // store op2 if op2 < op1 |
| 28468 | bin_op = IrBinOpCmpGreaterThan; |
| 28469 | else |
| 28470 | // store op2 if op2 > op1 |
| 28471 | bin_op = IrBinOpCmpLessThan; |
| 28472 | |
| 28473 | IrInstGen *dummy_value = ir_const(ira, source_inst, operand_type); |
| 28474 | ir_eval_bin_op_cmp_scalar(ira, source_inst, op1_val, bin_op, op2_val, dummy_value->value); |
| 28475 | if (dummy_value->value->data.x_bool) |
| 28476 | ir_analyze_store_ptr(ira, source_inst, casted_ptr, casted_operand, false); |
| 28477 | } else { |
| 28478 | IrBinOp bin_op; |
| 28479 | switch (op) { |
| 28480 | case AtomicRmwOp_xchg: |
| 28481 | case AtomicRmwOp_max: |
| 28482 | case AtomicRmwOp_min: |
| 28483 | zig_unreachable(); |
| 28484 | case AtomicRmwOp_add: |
| 28485 | if (operand_type->id == ZigTypeIdFloat) |
| 28486 | bin_op = IrBinOpAdd; |
| 28487 | else |
| 28488 | bin_op = IrBinOpAddWrap; |
| 28489 | break; |
| 28490 | case AtomicRmwOp_sub: |
| 28491 | if (operand_type->id == ZigTypeIdFloat) |
| 28492 | bin_op = IrBinOpSub; |
| 28493 | else |
| 28494 | bin_op = IrBinOpSubWrap; |
| 28495 | break; |
| 28496 | case AtomicRmwOp_and: |
| 28497 | case AtomicRmwOp_nand: |
| 28498 | bin_op = IrBinOpBinAnd; |
| 28499 | break; |
| 28500 | case AtomicRmwOp_or: |
| 28501 | bin_op = IrBinOpBinOr; |
| 28502 | break; |
| 28503 | case AtomicRmwOp_xor: |
| 28504 | bin_op = IrBinOpBinXor; |
| 28505 | break; |
| 28506 | } |
| 28507 | ir_eval_math_op_scalar(ira, source_inst, operand_type, op1_val, bin_op, op2_val, op1_val); |
| 28508 | if (op == AtomicRmwOp_nand) { |
| 28509 | bigint_not(&op1_val->data.x_bigint, &op1_val->data.x_bigint, |
| 28510 | operand_type->data.integral.bit_count, operand_type->data.integral.is_signed); |
| 28511 | } |
| 28512 | } |
| 28513 | return ir_const_move(ira, source_inst, op1_val); |
| 28444 | 28514 | } |
| 28445 | 28515 | |
| 28446 | | return ir_build_atomic_rmw_gen(ira, &instruction->base.base, casted_ptr, casted_operand, op, |
| 28516 | return ir_build_atomic_rmw_gen(ira, source_inst, casted_ptr, casted_operand, op, |
| 28447 | 28517 | ordering, operand_type); |
| 28448 | 28518 | } |
| 28449 | 28519 | |