result location semantics for cmpxchg
This commit is contained in:
parent
b9c033ae1a
commit
ee3f7e20f6
|
@ -2862,26 +2862,26 @@ struct IrInstructionEmbedFile {
|
|||
struct IrInstructionCmpxchgSrc {
|
||||
IrInstruction base;
|
||||
|
||||
bool is_weak;
|
||||
IrInstruction *type_value;
|
||||
IrInstruction *ptr;
|
||||
IrInstruction *cmp_value;
|
||||
IrInstruction *new_value;
|
||||
IrInstruction *success_order_value;
|
||||
IrInstruction *failure_order_value;
|
||||
|
||||
bool is_weak;
|
||||
ResultLoc *result_loc;
|
||||
};
|
||||
|
||||
struct IrInstructionCmpxchgGen {
|
||||
IrInstruction base;
|
||||
|
||||
bool is_weak;
|
||||
AtomicOrder success_order;
|
||||
AtomicOrder failure_order;
|
||||
IrInstruction *ptr;
|
||||
IrInstruction *cmp_value;
|
||||
IrInstruction *new_value;
|
||||
LLVMValueRef tmp_ptr;
|
||||
AtomicOrder success_order;
|
||||
AtomicOrder failure_order;
|
||||
bool is_weak;
|
||||
IrInstruction *result_loc;
|
||||
};
|
||||
|
||||
struct IrInstructionFence {
|
||||
|
|
|
@ -4516,28 +4516,28 @@ static LLVMValueRef ir_render_cmpxchg(CodeGen *g, IrExecutable *executable, IrIn
|
|||
LLVMValueRef result_val = ZigLLVMBuildCmpXchg(g->builder, ptr_val, cmp_val, new_val,
|
||||
success_order, failure_order, instruction->is_weak);
|
||||
|
||||
ZigType *maybe_type = instruction->base.value.type;
|
||||
assert(maybe_type->id == ZigTypeIdOptional);
|
||||
ZigType *child_type = maybe_type->data.maybe.child_type;
|
||||
ZigType *optional_type = instruction->base.value.type;
|
||||
assert(optional_type->id == ZigTypeIdOptional);
|
||||
ZigType *child_type = optional_type->data.maybe.child_type;
|
||||
|
||||
if (!handle_is_ptr(maybe_type)) {
|
||||
if (!handle_is_ptr(optional_type)) {
|
||||
LLVMValueRef payload_val = LLVMBuildExtractValue(g->builder, result_val, 0, "");
|
||||
LLVMValueRef success_bit = LLVMBuildExtractValue(g->builder, result_val, 1, "");
|
||||
return LLVMBuildSelect(g->builder, success_bit, LLVMConstNull(get_llvm_type(g, child_type)), payload_val, "");
|
||||
}
|
||||
|
||||
assert(instruction->tmp_ptr != nullptr);
|
||||
LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc);
|
||||
assert(type_has_bits(child_type));
|
||||
|
||||
LLVMValueRef payload_val = LLVMBuildExtractValue(g->builder, result_val, 0, "");
|
||||
LLVMValueRef val_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, maybe_child_index, "");
|
||||
LLVMValueRef val_ptr = LLVMBuildStructGEP(g->builder, result_loc, maybe_child_index, "");
|
||||
gen_assign_raw(g, val_ptr, get_pointer_to_type(g, child_type, false), payload_val);
|
||||
|
||||
LLVMValueRef success_bit = LLVMBuildExtractValue(g->builder, result_val, 1, "");
|
||||
LLVMValueRef nonnull_bit = LLVMBuildNot(g->builder, success_bit, "");
|
||||
LLVMValueRef maybe_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, maybe_null_index, "");
|
||||
LLVMValueRef maybe_ptr = LLVMBuildStructGEP(g->builder, result_loc, maybe_null_index, "");
|
||||
gen_store_untyped(g, nonnull_bit, maybe_ptr, 0, false);
|
||||
return instruction->tmp_ptr;
|
||||
return result_loc;
|
||||
}
|
||||
|
||||
static LLVMValueRef ir_render_fence(CodeGen *g, IrExecutable *executable, IrInstructionFence *instruction) {
|
||||
|
@ -6840,9 +6840,6 @@ static void do_code_gen(CodeGen *g) {
|
|||
slot = &ref_instruction->tmp_ptr;
|
||||
assert(instruction->value.type->id == ZigTypeIdPointer);
|
||||
slot_type = instruction->value.type->data.pointer.child_type;
|
||||
} else if (instruction->id == IrInstructionIdCmpxchgGen) {
|
||||
IrInstructionCmpxchgGen *cmpxchg_instruction = (IrInstructionCmpxchgGen *)instruction;
|
||||
slot = &cmpxchg_instruction->tmp_ptr;
|
||||
} else if (instruction->id == IrInstructionIdResizeSlice) {
|
||||
IrInstructionResizeSlice *resize_slice_instruction = (IrInstructionResizeSlice *)instruction;
|
||||
slot = &resize_slice_instruction->tmp_ptr;
|
||||
|
|
33
src/ir.cpp
33
src/ir.cpp
|
@ -2032,8 +2032,7 @@ static IrInstruction *ir_build_embed_file(IrBuilder *irb, Scope *scope, AstNode
|
|||
|
||||
static IrInstruction *ir_build_cmpxchg_src(IrBuilder *irb, Scope *scope, AstNode *source_node,
|
||||
IrInstruction *type_value, IrInstruction *ptr, IrInstruction *cmp_value, IrInstruction *new_value,
|
||||
IrInstruction *success_order_value, IrInstruction *failure_order_value,
|
||||
bool is_weak)
|
||||
IrInstruction *success_order_value, IrInstruction *failure_order_value, bool is_weak, ResultLoc *result_loc)
|
||||
{
|
||||
IrInstructionCmpxchgSrc *instruction = ir_build_instruction<IrInstructionCmpxchgSrc>(irb, scope, source_node);
|
||||
instruction->type_value = type_value;
|
||||
|
@ -2043,6 +2042,7 @@ static IrInstruction *ir_build_cmpxchg_src(IrBuilder *irb, Scope *scope, AstNode
|
|||
instruction->success_order_value = success_order_value;
|
||||
instruction->failure_order_value = failure_order_value;
|
||||
instruction->is_weak = is_weak;
|
||||
instruction->result_loc = result_loc;
|
||||
|
||||
ir_ref_instruction(type_value, irb->current_basic_block);
|
||||
ir_ref_instruction(ptr, irb->current_basic_block);
|
||||
|
@ -2054,22 +2054,25 @@ static IrInstruction *ir_build_cmpxchg_src(IrBuilder *irb, Scope *scope, AstNode
|
|||
return &instruction->base;
|
||||
}
|
||||
|
||||
static IrInstruction *ir_build_cmpxchg_gen(IrAnalyze *ira, IrInstruction *source_instruction,
|
||||
static IrInstruction *ir_build_cmpxchg_gen(IrAnalyze *ira, IrInstruction *source_instruction, ZigType *result_type,
|
||||
IrInstruction *ptr, IrInstruction *cmp_value, IrInstruction *new_value,
|
||||
AtomicOrder success_order, AtomicOrder failure_order, bool is_weak)
|
||||
AtomicOrder success_order, AtomicOrder failure_order, bool is_weak, IrInstruction *result_loc)
|
||||
{
|
||||
IrInstructionCmpxchgGen *instruction = ir_build_instruction<IrInstructionCmpxchgGen>(&ira->new_irb,
|
||||
source_instruction->scope, source_instruction->source_node);
|
||||
instruction->base.value.type = result_type;
|
||||
instruction->ptr = ptr;
|
||||
instruction->cmp_value = cmp_value;
|
||||
instruction->new_value = new_value;
|
||||
instruction->success_order = success_order;
|
||||
instruction->failure_order = failure_order;
|
||||
instruction->is_weak = is_weak;
|
||||
instruction->result_loc = result_loc;
|
||||
|
||||
ir_ref_instruction(ptr, ira->new_irb.current_basic_block);
|
||||
ir_ref_instruction(cmp_value, ira->new_irb.current_basic_block);
|
||||
ir_ref_instruction(new_value, ira->new_irb.current_basic_block);
|
||||
if (result_loc != nullptr) ir_ref_instruction(result_loc, ira->new_irb.current_basic_block);
|
||||
|
||||
return &instruction->base;
|
||||
}
|
||||
|
@ -4420,7 +4423,8 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
|
|||
return arg5_value;
|
||||
|
||||
IrInstruction *cmpxchg = ir_build_cmpxchg_src(irb, scope, node, arg0_value, arg1_value,
|
||||
arg2_value, arg3_value, arg4_value, arg5_value, (builtin_fn->id == BuiltinFnIdCmpxchgWeak));
|
||||
arg2_value, arg3_value, arg4_value, arg5_value, (builtin_fn->id == BuiltinFnIdCmpxchgWeak),
|
||||
result_loc);
|
||||
return ir_lval_wrap(irb, scope, cmpxchg, lval, result_loc);
|
||||
}
|
||||
case BuiltinFnIdFence:
|
||||
|
@ -20439,6 +20443,18 @@ static IrInstruction *ir_analyze_instruction_cmpxchg(IrAnalyze *ira, IrInstructi
|
|||
if (type_is_invalid(ptr->value.type))
|
||||
return ira->codegen->invalid_instruction;
|
||||
|
||||
ZigType *result_type = get_optional_type(ira->codegen, operand_type);
|
||||
IrInstruction *result_loc;
|
||||
if (handle_is_ptr(result_type)) {
|
||||
result_loc = ir_resolve_result(ira, &instruction->base, instruction->result_loc,
|
||||
result_type, nullptr);
|
||||
if (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc)) {
|
||||
return result_loc;
|
||||
}
|
||||
} else {
|
||||
result_loc = nullptr;
|
||||
}
|
||||
|
||||
// TODO let this be volatile
|
||||
ZigType *ptr_type = get_pointer_to_type(ira->codegen, operand_type, false);
|
||||
IrInstruction *casted_ptr = ir_implicit_cast(ira, ptr, ptr_type);
|
||||
|
@ -20502,12 +20518,9 @@ static IrInstruction *ir_analyze_instruction_cmpxchg(IrAnalyze *ira, IrInstructi
|
|||
zig_panic("TODO compile-time execution of cmpxchg");
|
||||
}
|
||||
|
||||
IrInstruction *result = ir_build_cmpxchg_gen(ira, &instruction->base,
|
||||
return ir_build_cmpxchg_gen(ira, &instruction->base, result_type,
|
||||
casted_ptr, casted_cmp_value, casted_new_value,
|
||||
success_order, failure_order, instruction->is_weak);
|
||||
result->value.type = get_optional_type(ira->codegen, operand_type);
|
||||
ir_add_alloca(ira, result, result->value.type);
|
||||
return result;
|
||||
success_order, failure_order, instruction->is_weak, result_loc);
|
||||
}
|
||||
|
||||
static IrInstruction *ir_analyze_instruction_fence(IrAnalyze *ira, IrInstructionFence *instruction) {
|
||||
|
|
|
@ -730,7 +730,8 @@ static void ir_print_cmpxchg_src(IrPrint *irp, IrInstructionCmpxchgSrc *instruct
|
|||
ir_print_other_instruction(irp, instruction->success_order_value);
|
||||
fprintf(irp->f, ", ");
|
||||
ir_print_other_instruction(irp, instruction->failure_order_value);
|
||||
fprintf(irp->f, ")");
|
||||
fprintf(irp->f, ")result=");
|
||||
ir_print_result_loc(irp, instruction->result_loc);
|
||||
}
|
||||
|
||||
static void ir_print_cmpxchg_gen(IrPrint *irp, IrInstructionCmpxchgGen *instruction) {
|
||||
|
@ -740,7 +741,8 @@ static void ir_print_cmpxchg_gen(IrPrint *irp, IrInstructionCmpxchgGen *instruct
|
|||
ir_print_other_instruction(irp, instruction->cmp_value);
|
||||
fprintf(irp->f, ", ");
|
||||
ir_print_other_instruction(irp, instruction->new_value);
|
||||
fprintf(irp->f, ", TODO print atomic orders)");
|
||||
fprintf(irp->f, ", TODO print atomic orders)result=");
|
||||
ir_print_other_instruction(irp, instruction->result_loc);
|
||||
}
|
||||
|
||||
static void ir_print_fence(IrPrint *irp, IrInstructionFence *instruction) {
|
||||
|
|
Loading…
Reference in New Issue
Block a user