Commit ee3f7e20f6

Andrew Kelley <andrew@ziglang.org>
2019-06-10 23:49:36
result location semantics for cmpxchg
1 parent b9c033a
src/all_types.hpp
@@ -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 {
src/codegen.cpp
@@ -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;
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) {
src/ir_print.cpp
@@ -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) {