| author | |
| committer | |
| log | ee3f7e20f64d715ff22eeff0b7b355bca1981ea1 |
| tree | a277698e9df0e1aaede8fa57a0e6b860ae4b3b49 |
| parent | b9c033ae1ac9c21a5729407b9a6ede88854654aa |
| signature |
4 files changed, 41 insertions(+), 29 deletions(-)
src/all_types.hpp+6-6| ... | ... | @@ -2862,26 +2862,26 @@ struct IrInstructionEmbedFile { |
| 2862 | 2862 | struct IrInstructionCmpxchgSrc { |
| 2863 | 2863 | IrInstruction base; |
| 2864 | 2864 | |
| 2865 | bool is_weak; | |
| 2865 | 2866 | IrInstruction *type_value; |
| 2866 | 2867 | IrInstruction *ptr; |
| 2867 | 2868 | IrInstruction *cmp_value; |
| 2868 | 2869 | IrInstruction *new_value; |
| 2869 | 2870 | IrInstruction *success_order_value; |
| 2870 | 2871 | IrInstruction *failure_order_value; |
| 2871 | ||
| 2872 | bool is_weak; | |
| 2872 | ResultLoc *result_loc; | |
| 2873 | 2873 | }; |
| 2874 | 2874 | |
| 2875 | 2875 | struct IrInstructionCmpxchgGen { |
| 2876 | 2876 | IrInstruction base; |
| 2877 | 2877 | |
| 2878 | bool is_weak; | |
| 2879 | AtomicOrder success_order; | |
| 2880 | AtomicOrder failure_order; | |
| 2878 | 2881 | IrInstruction *ptr; |
| 2879 | 2882 | IrInstruction *cmp_value; |
| 2880 | 2883 | IrInstruction *new_value; |
| 2881 | LLVMValueRef tmp_ptr; | |
| 2882 | AtomicOrder success_order; | |
| 2883 | AtomicOrder failure_order; | |
| 2884 | bool is_weak; | |
| 2884 | IrInstruction *result_loc; | |
| 2885 | 2885 | }; |
| 2886 | 2886 | |
| 2887 | 2887 | struct IrInstructionFence { |
src/codegen.cpp+8-11| ... | ... | @@ -4516,28 +4516,28 @@ static LLVMValueRef ir_render_cmpxchg(CodeGen *g, IrExecutable *executable, IrIn |
| 4516 | 4516 | LLVMValueRef result_val = ZigLLVMBuildCmpXchg(g->builder, ptr_val, cmp_val, new_val, |
| 4517 | 4517 | success_order, failure_order, instruction->is_weak); |
| 4518 | 4518 | |
| 4519 | ZigType *maybe_type = instruction->base.value.type; | |
| 4520 | assert(maybe_type->id == ZigTypeIdOptional); | |
| 4521 | ZigType *child_type = maybe_type->data.maybe.child_type; | |
| 4519 | ZigType *optional_type = instruction->base.value.type; | |
| 4520 | assert(optional_type->id == ZigTypeIdOptional); | |
| 4521 | ZigType *child_type = optional_type->data.maybe.child_type; | |
| 4522 | 4522 | |
| 4523 | if (!handle_is_ptr(maybe_type)) { | |
| 4523 | if (!handle_is_ptr(optional_type)) { | |
| 4524 | 4524 | LLVMValueRef payload_val = LLVMBuildExtractValue(g->builder, result_val, 0, ""); |
| 4525 | 4525 | LLVMValueRef success_bit = LLVMBuildExtractValue(g->builder, result_val, 1, ""); |
| 4526 | 4526 | return LLVMBuildSelect(g->builder, success_bit, LLVMConstNull(get_llvm_type(g, child_type)), payload_val, ""); |
| 4527 | 4527 | } |
| 4528 | 4528 | |
| 4529 | assert(instruction->tmp_ptr != nullptr); | |
| 4529 | LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc); | |
| 4530 | 4530 | assert(type_has_bits(child_type)); |
| 4531 | 4531 | |
| 4532 | 4532 | LLVMValueRef payload_val = LLVMBuildExtractValue(g->builder, result_val, 0, ""); |
| 4533 | LLVMValueRef val_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, maybe_child_index, ""); | |
| 4533 | LLVMValueRef val_ptr = LLVMBuildStructGEP(g->builder, result_loc, maybe_child_index, ""); | |
| 4534 | 4534 | gen_assign_raw(g, val_ptr, get_pointer_to_type(g, child_type, false), payload_val); |
| 4535 | 4535 | |
| 4536 | 4536 | LLVMValueRef success_bit = LLVMBuildExtractValue(g->builder, result_val, 1, ""); |
| 4537 | 4537 | LLVMValueRef nonnull_bit = LLVMBuildNot(g->builder, success_bit, ""); |
| 4538 | LLVMValueRef maybe_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, maybe_null_index, ""); | |
| 4538 | LLVMValueRef maybe_ptr = LLVMBuildStructGEP(g->builder, result_loc, maybe_null_index, ""); | |
| 4539 | 4539 | gen_store_untyped(g, nonnull_bit, maybe_ptr, 0, false); |
| 4540 | return instruction->tmp_ptr; | |
| 4540 | return result_loc; | |
| 4541 | 4541 | } |
| 4542 | 4542 | |
| 4543 | 4543 | static LLVMValueRef ir_render_fence(CodeGen *g, IrExecutable *executable, IrInstructionFence *instruction) { |
| ... | ... | @@ -6840,9 +6840,6 @@ static void do_code_gen(CodeGen *g) { |
| 6840 | 6840 | slot = &ref_instruction->tmp_ptr; |
| 6841 | 6841 | assert(instruction->value.type->id == ZigTypeIdPointer); |
| 6842 | 6842 | slot_type = instruction->value.type->data.pointer.child_type; |
| 6843 | } else if (instruction->id == IrInstructionIdCmpxchgGen) { | |
| 6844 | IrInstructionCmpxchgGen *cmpxchg_instruction = (IrInstructionCmpxchgGen *)instruction; | |
| 6845 | slot = &cmpxchg_instruction->tmp_ptr; | |
| 6846 | 6843 | } else if (instruction->id == IrInstructionIdResizeSlice) { |
| 6847 | 6844 | IrInstructionResizeSlice *resize_slice_instruction = (IrInstructionResizeSlice *)instruction; |
| 6848 | 6845 | slot = &resize_slice_instruction->tmp_ptr; |
src/ir.cpp+23-10| ... | ... | @@ -2032,8 +2032,7 @@ static IrInstruction *ir_build_embed_file(IrBuilder *irb, Scope *scope, AstNode |
| 2032 | 2032 | |
| 2033 | 2033 | static IrInstruction *ir_build_cmpxchg_src(IrBuilder *irb, Scope *scope, AstNode *source_node, |
| 2034 | 2034 | IrInstruction *type_value, IrInstruction *ptr, IrInstruction *cmp_value, IrInstruction *new_value, |
| 2035 | IrInstruction *success_order_value, IrInstruction *failure_order_value, | |
| 2036 | bool is_weak) | |
| 2035 | IrInstruction *success_order_value, IrInstruction *failure_order_value, bool is_weak, ResultLoc *result_loc) | |
| 2037 | 2036 | { |
| 2038 | 2037 | IrInstructionCmpxchgSrc *instruction = ir_build_instruction<IrInstructionCmpxchgSrc>(irb, scope, source_node); |
| 2039 | 2038 | instruction->type_value = type_value; |
| ... | ... | @@ -2043,6 +2042,7 @@ static IrInstruction *ir_build_cmpxchg_src(IrBuilder *irb, Scope *scope, AstNode |
| 2043 | 2042 | instruction->success_order_value = success_order_value; |
| 2044 | 2043 | instruction->failure_order_value = failure_order_value; |
| 2045 | 2044 | instruction->is_weak = is_weak; |
| 2045 | instruction->result_loc = result_loc; | |
| 2046 | 2046 | |
| 2047 | 2047 | ir_ref_instruction(type_value, irb->current_basic_block); |
| 2048 | 2048 | ir_ref_instruction(ptr, irb->current_basic_block); |
| ... | ... | @@ -2054,22 +2054,25 @@ static IrInstruction *ir_build_cmpxchg_src(IrBuilder *irb, Scope *scope, AstNode |
| 2054 | 2054 | return &instruction->base; |
| 2055 | 2055 | } |
| 2056 | 2056 | |
| 2057 | static IrInstruction *ir_build_cmpxchg_gen(IrAnalyze *ira, IrInstruction *source_instruction, | |
| 2057 | static IrInstruction *ir_build_cmpxchg_gen(IrAnalyze *ira, IrInstruction *source_instruction, ZigType *result_type, | |
| 2058 | 2058 | IrInstruction *ptr, IrInstruction *cmp_value, IrInstruction *new_value, |
| 2059 | AtomicOrder success_order, AtomicOrder failure_order, bool is_weak) | |
| 2059 | AtomicOrder success_order, AtomicOrder failure_order, bool is_weak, IrInstruction *result_loc) | |
| 2060 | 2060 | { |
| 2061 | 2061 | IrInstructionCmpxchgGen *instruction = ir_build_instruction<IrInstructionCmpxchgGen>(&ira->new_irb, |
| 2062 | 2062 | source_instruction->scope, source_instruction->source_node); |
| 2063 | instruction->base.value.type = result_type; | |
| 2063 | 2064 | instruction->ptr = ptr; |
| 2064 | 2065 | instruction->cmp_value = cmp_value; |
| 2065 | 2066 | instruction->new_value = new_value; |
| 2066 | 2067 | instruction->success_order = success_order; |
| 2067 | 2068 | instruction->failure_order = failure_order; |
| 2068 | 2069 | instruction->is_weak = is_weak; |
| 2070 | instruction->result_loc = result_loc; | |
| 2069 | 2071 | |
| 2070 | 2072 | ir_ref_instruction(ptr, ira->new_irb.current_basic_block); |
| 2071 | 2073 | ir_ref_instruction(cmp_value, ira->new_irb.current_basic_block); |
| 2072 | 2074 | ir_ref_instruction(new_value, ira->new_irb.current_basic_block); |
| 2075 | if (result_loc != nullptr) ir_ref_instruction(result_loc, ira->new_irb.current_basic_block); | |
| 2073 | 2076 | |
| 2074 | 2077 | return &instruction->base; |
| 2075 | 2078 | } |
| ... | ... | @@ -4420,7 +4423,8 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo |
| 4420 | 4423 | return arg5_value; |
| 4421 | 4424 | |
| 4422 | 4425 | IrInstruction *cmpxchg = ir_build_cmpxchg_src(irb, scope, node, arg0_value, arg1_value, |
| 4423 | arg2_value, arg3_value, arg4_value, arg5_value, (builtin_fn->id == BuiltinFnIdCmpxchgWeak)); | |
| 4426 | arg2_value, arg3_value, arg4_value, arg5_value, (builtin_fn->id == BuiltinFnIdCmpxchgWeak), | |
| 4427 | result_loc); | |
| 4424 | 4428 | return ir_lval_wrap(irb, scope, cmpxchg, lval, result_loc); |
| 4425 | 4429 | } |
| 4426 | 4430 | case BuiltinFnIdFence: |
| ... | ... | @@ -20439,6 +20443,18 @@ static IrInstruction *ir_analyze_instruction_cmpxchg(IrAnalyze *ira, IrInstructi |
| 20439 | 20443 | if (type_is_invalid(ptr->value.type)) |
| 20440 | 20444 | return ira->codegen->invalid_instruction; |
| 20441 | 20445 | |
| 20446 | ZigType *result_type = get_optional_type(ira->codegen, operand_type); | |
| 20447 | IrInstruction *result_loc; | |
| 20448 | if (handle_is_ptr(result_type)) { | |
| 20449 | result_loc = ir_resolve_result(ira, &instruction->base, instruction->result_loc, | |
| 20450 | result_type, nullptr); | |
| 20451 | if (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc)) { | |
| 20452 | return result_loc; | |
| 20453 | } | |
| 20454 | } else { | |
| 20455 | result_loc = nullptr; | |
| 20456 | } | |
| 20457 | ||
| 20442 | 20458 | // TODO let this be volatile |
| 20443 | 20459 | ZigType *ptr_type = get_pointer_to_type(ira->codegen, operand_type, false); |
| 20444 | 20460 | IrInstruction *casted_ptr = ir_implicit_cast(ira, ptr, ptr_type); |
| ... | ... | @@ -20502,12 +20518,9 @@ static IrInstruction *ir_analyze_instruction_cmpxchg(IrAnalyze *ira, IrInstructi |
| 20502 | 20518 | zig_panic("TODO compile-time execution of cmpxchg"); |
| 20503 | 20519 | } |
| 20504 | 20520 | |
| 20505 | IrInstruction *result = ir_build_cmpxchg_gen(ira, &instruction->base, | |
| 20521 | return ir_build_cmpxchg_gen(ira, &instruction->base, result_type, | |
| 20506 | 20522 | casted_ptr, casted_cmp_value, casted_new_value, |
| 20507 | success_order, failure_order, instruction->is_weak); | |
| 20508 | result->value.type = get_optional_type(ira->codegen, operand_type); | |
| 20509 | ir_add_alloca(ira, result, result->value.type); | |
| 20510 | return result; | |
| 20523 | success_order, failure_order, instruction->is_weak, result_loc); | |
| 20511 | 20524 | } |
| 20512 | 20525 | |
| 20513 | 20526 | static IrInstruction *ir_analyze_instruction_fence(IrAnalyze *ira, IrInstructionFence *instruction) { |
src/ir_print.cpp+4-2| ... | ... | @@ -730,7 +730,8 @@ static void ir_print_cmpxchg_src(IrPrint *irp, IrInstructionCmpxchgSrc *instruct |
| 730 | 730 | ir_print_other_instruction(irp, instruction->success_order_value); |
| 731 | 731 | fprintf(irp->f, ", "); |
| 732 | 732 | ir_print_other_instruction(irp, instruction->failure_order_value); |
| 733 | fprintf(irp->f, ")"); | |
| 733 | fprintf(irp->f, ")result="); | |
| 734 | ir_print_result_loc(irp, instruction->result_loc); | |
| 734 | 735 | } |
| 735 | 736 | |
| 736 | 737 | static void ir_print_cmpxchg_gen(IrPrint *irp, IrInstructionCmpxchgGen *instruction) { |
| ... | ... | @@ -740,7 +741,8 @@ static void ir_print_cmpxchg_gen(IrPrint *irp, IrInstructionCmpxchgGen *instruct |
| 740 | 741 | ir_print_other_instruction(irp, instruction->cmp_value); |
| 741 | 742 | fprintf(irp->f, ", "); |
| 742 | 743 | ir_print_other_instruction(irp, instruction->new_value); |
| 743 | fprintf(irp->f, ", TODO print atomic orders)"); | |
| 744 | fprintf(irp->f, ", TODO print atomic orders)result="); | |
| 745 | ir_print_other_instruction(irp, instruction->result_loc); | |
| 744 | 746 | } |
| 745 | 747 | |
| 746 | 748 | static void ir_print_fence(IrPrint *irp, IrInstructionFence *instruction) { |