add @atomicStore builtin
This commit is contained in:
103
src/ir.cpp
103
src/ir.cpp
@@ -1009,6 +1009,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionAtomicLoad *) {
|
||||
return IrInstructionIdAtomicLoad;
|
||||
}
|
||||
|
||||
static constexpr IrInstructionId ir_instruction_id(IrInstructionAtomicStore *) {
|
||||
return IrInstructionIdAtomicStore;
|
||||
}
|
||||
|
||||
static constexpr IrInstructionId ir_instruction_id(IrInstructionSaveErrRetAddr *) {
|
||||
return IrInstructionIdSaveErrRetAddr;
|
||||
}
|
||||
@@ -3186,6 +3190,25 @@ static IrInstruction *ir_build_atomic_load(IrBuilder *irb, Scope *scope, AstNode
|
||||
return &instruction->base;
|
||||
}
|
||||
|
||||
static IrInstruction *ir_build_atomic_store(IrBuilder *irb, Scope *scope, AstNode *source_node,
|
||||
IrInstruction *operand_type, IrInstruction *ptr, IrInstruction *value,
|
||||
IrInstruction *ordering, AtomicOrder resolved_ordering)
|
||||
{
|
||||
IrInstructionAtomicStore *instruction = ir_build_instruction<IrInstructionAtomicStore>(irb, scope, source_node);
|
||||
instruction->operand_type = operand_type;
|
||||
instruction->ptr = ptr;
|
||||
instruction->value = value;
|
||||
instruction->ordering = ordering;
|
||||
instruction->resolved_ordering = resolved_ordering;
|
||||
|
||||
if (operand_type != nullptr) ir_ref_instruction(operand_type, irb->current_basic_block);
|
||||
ir_ref_instruction(ptr, irb->current_basic_block);
|
||||
ir_ref_instruction(value, irb->current_basic_block);
|
||||
if (ordering != nullptr) ir_ref_instruction(ordering, irb->current_basic_block);
|
||||
|
||||
return &instruction->base;
|
||||
}
|
||||
|
||||
static IrInstruction *ir_build_save_err_ret_addr(IrBuilder *irb, Scope *scope, AstNode *source_node) {
|
||||
IrInstructionSaveErrRetAddr *instruction = ir_build_instruction<IrInstructionSaveErrRetAddr>(irb, scope, source_node);
|
||||
return &instruction->base;
|
||||
@@ -5730,6 +5753,33 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
|
||||
AtomicOrderMonotonic);
|
||||
return ir_lval_wrap(irb, scope, inst, lval, result_loc);
|
||||
}
|
||||
case BuiltinFnIdAtomicStore:
|
||||
{
|
||||
AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
|
||||
IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope);
|
||||
if (arg0_value == irb->codegen->invalid_instruction)
|
||||
return arg0_value;
|
||||
|
||||
AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
|
||||
IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope);
|
||||
if (arg1_value == irb->codegen->invalid_instruction)
|
||||
return arg1_value;
|
||||
|
||||
AstNode *arg2_node = node->data.fn_call_expr.params.at(2);
|
||||
IrInstruction *arg2_value = ir_gen_node(irb, arg2_node, scope);
|
||||
if (arg2_value == irb->codegen->invalid_instruction)
|
||||
return arg2_value;
|
||||
|
||||
AstNode *arg3_node = node->data.fn_call_expr.params.at(3);
|
||||
IrInstruction *arg3_value = ir_gen_node(irb, arg3_node, scope);
|
||||
if (arg3_value == irb->codegen->invalid_instruction)
|
||||
return arg3_value;
|
||||
|
||||
IrInstruction *inst = ir_build_atomic_store(irb, scope, node, arg0_value, arg1_value, arg2_value, arg3_value,
|
||||
// this value does not mean anything since we passed non-null values for other arg
|
||||
AtomicOrderMonotonic);
|
||||
return ir_lval_wrap(irb, scope, inst, lval, result_loc);
|
||||
}
|
||||
case BuiltinFnIdIntToEnum:
|
||||
{
|
||||
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
|
||||
return result;
|
||||
}
|
||||
|
||||
static IrInstruction *ir_analyze_instruction_atomic_store(IrAnalyze *ira, IrInstructionAtomicStore *instruction) {
|
||||
ZigType *operand_type = ir_resolve_atomic_operand_type(ira, instruction->operand_type->child);
|
||||
if (type_is_invalid(operand_type))
|
||||
return ira->codegen->invalid_instruction;
|
||||
|
||||
IrInstruction *ptr_inst = instruction->ptr->child;
|
||||
if (type_is_invalid(ptr_inst->value.type))
|
||||
return ira->codegen->invalid_instruction;
|
||||
|
||||
ZigType *ptr_type = get_pointer_to_type(ira->codegen, operand_type, true);
|
||||
IrInstruction *casted_ptr = ir_implicit_cast(ira, ptr_inst, ptr_type);
|
||||
if (type_is_invalid(casted_ptr->value.type))
|
||||
return ira->codegen->invalid_instruction;
|
||||
|
||||
IrInstruction *value = instruction->value->child;
|
||||
if (type_is_invalid(value->value.type))
|
||||
return ira->codegen->invalid_instruction;
|
||||
|
||||
IrInstruction *casted_value = ir_implicit_cast(ira, value, operand_type);
|
||||
if (type_is_invalid(casted_value->value.type))
|
||||
return ira->codegen->invalid_instruction;
|
||||
|
||||
|
||||
AtomicOrder ordering;
|
||||
if (instruction->ordering == nullptr) {
|
||||
ordering = instruction->resolved_ordering;
|
||||
} else {
|
||||
if (!ir_resolve_atomic_order(ira, instruction->ordering->child, &ordering))
|
||||
return ira->codegen->invalid_instruction;
|
||||
}
|
||||
|
||||
if (ordering == AtomicOrderAcquire || ordering == AtomicOrderAcqRel) {
|
||||
ir_assert(instruction->ordering != nullptr, &instruction->base);
|
||||
ir_add_error(ira, instruction->ordering,
|
||||
buf_sprintf("@atomicStore atomic ordering must not be Acquire or AcqRel"));
|
||||
return ira->codegen->invalid_instruction;
|
||||
}
|
||||
|
||||
if (instr_is_comptime(casted_value) && instr_is_comptime(casted_ptr)) {
|
||||
IrInstruction *result = ir_get_deref(ira, &instruction->base, casted_ptr, nullptr);
|
||||
ir_assert(result->value.type != nullptr, &instruction->base);
|
||||
return result;
|
||||
}
|
||||
|
||||
IrInstruction *result = ir_build_atomic_store(&ira->new_irb, instruction->base.scope,
|
||||
instruction->base.source_node, nullptr, casted_ptr, casted_value, nullptr, ordering);
|
||||
result->value.type = ira->codegen->builtin_types.entry_void;
|
||||
return result;
|
||||
}
|
||||
|
||||
static IrInstruction *ir_analyze_instruction_save_err_ret_addr(IrAnalyze *ira, IrInstructionSaveErrRetAddr *instruction) {
|
||||
IrInstruction *result = ir_build_save_err_ret_addr(&ira->new_irb, instruction->base.scope,
|
||||
instruction->base.source_node);
|
||||
@@ -26782,6 +26882,8 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction
|
||||
return ir_analyze_instruction_atomic_rmw(ira, (IrInstructionAtomicRmw *)instruction);
|
||||
case IrInstructionIdAtomicLoad:
|
||||
return ir_analyze_instruction_atomic_load(ira, (IrInstructionAtomicLoad *)instruction);
|
||||
case IrInstructionIdAtomicStore:
|
||||
return ir_analyze_instruction_atomic_store(ira, (IrInstructionAtomicStore *)instruction);
|
||||
case IrInstructionIdSaveErrRetAddr:
|
||||
return ir_analyze_instruction_save_err_ret_addr(ira, (IrInstructionSaveErrRetAddr *)instruction);
|
||||
case IrInstructionIdAddImplicitReturnType:
|
||||
@@ -26962,6 +27064,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
|
||||
case IrInstructionIdSaveErrRetAddr:
|
||||
case IrInstructionIdAddImplicitReturnType:
|
||||
case IrInstructionIdAtomicRmw:
|
||||
case IrInstructionIdAtomicStore:
|
||||
case IrInstructionIdCmpxchgGen:
|
||||
case IrInstructionIdCmpxchgSrc:
|
||||
case IrInstructionIdAssertZero:
|
||||
|
||||
Reference in New Issue
Block a user