| author | |
| committer | |
| log | 2bb795dc455823e76ef3e0c9b3fcee6bcb15fddb |
| tree | 995e0a82e2d47d0b6701716372808ae7a40a406f |
| parent | db31c2524df4352593128aaceaa0b085ef8bb674 |
| signature |
closes #2626 files changed, 185 insertions(+), 84 deletions(-)
src/all_types.hpp+20-13| ... | @@ -630,19 +630,6 @@ struct AstNodeUnwrapOptional { | ... | @@ -630,19 +630,6 @@ struct AstNodeUnwrapOptional { |
| 630 | AstNode *expr; | 630 | AstNode *expr; |
| 631 | }; | 631 | }; |
| 632 | 632 | ||
| 633 | enum CastOp { | ||
| 634 | CastOpNoCast, // signifies the function call expression is not a cast | ||
| 635 | CastOpNoop, // fn call expr is a cast, but does nothing | ||
| 636 | CastOpIntToFloat, | ||
| 637 | CastOpFloatToInt, | ||
| 638 | CastOpBoolToInt, | ||
| 639 | CastOpResizeSlice, | ||
| 640 | CastOpNumLitToConcrete, | ||
| 641 | CastOpErrSet, | ||
| 642 | CastOpBitCast, | ||
| 643 | CastOpPtrOfArrayToSlice, | ||
| 644 | }; | ||
| 645 | |||
| 646 | struct AstNodeFnCallExpr { | 633 | struct AstNodeFnCallExpr { |
| 647 | AstNode *fn_ref_expr; | 634 | AstNode *fn_ref_expr; |
| 648 | ZigList<AstNode *> params; | 635 | ZigList<AstNode *> params; |
| ... | @@ -2142,6 +2129,7 @@ enum IrInstructionId { | ... | @@ -2142,6 +2129,7 @@ enum IrInstructionId { |
| 2142 | IrInstructionIdConst, | 2129 | IrInstructionIdConst, |
| 2143 | IrInstructionIdReturn, | 2130 | IrInstructionIdReturn, |
| 2144 | IrInstructionIdCast, | 2131 | IrInstructionIdCast, |
| 2132 | IrInstructionIdResizeSlice, | ||
| 2145 | IrInstructionIdContainerInitList, | 2133 | IrInstructionIdContainerInitList, |
| 2146 | IrInstructionIdContainerInitFields, | 2134 | IrInstructionIdContainerInitFields, |
| 2147 | IrInstructionIdStructInit, | 2135 | IrInstructionIdStructInit, |
| ... | @@ -2503,6 +2491,18 @@ struct IrInstructionReturn { | ... | @@ -2503,6 +2491,18 @@ struct IrInstructionReturn { |
| 2503 | IrInstruction *value; | 2491 | IrInstruction *value; |
| 2504 | }; | 2492 | }; |
| 2505 | 2493 | ||
| 2494 | enum CastOp { | ||
| 2495 | CastOpNoCast, // signifies the function call expression is not a cast | ||
| 2496 | CastOpNoop, // fn call expr is a cast, but does nothing | ||
| 2497 | CastOpIntToFloat, | ||
| 2498 | CastOpFloatToInt, | ||
| 2499 | CastOpBoolToInt, | ||
| 2500 | CastOpNumLitToConcrete, | ||
| 2501 | CastOpErrSet, | ||
| 2502 | CastOpBitCast, | ||
| 2503 | CastOpPtrOfArrayToSlice, | ||
| 2504 | }; | ||
| 2505 | |||
| 2506 | // TODO get rid of this instruction, replace with instructions for each op code | 2506 | // TODO get rid of this instruction, replace with instructions for each op code |
| 2507 | struct IrInstructionCast { | 2507 | struct IrInstructionCast { |
| 2508 | IrInstruction base; | 2508 | IrInstruction base; |
| ... | @@ -2513,6 +2513,13 @@ struct IrInstructionCast { | ... | @@ -2513,6 +2513,13 @@ struct IrInstructionCast { |
| 2513 | LLVMValueRef tmp_ptr; | 2513 | LLVMValueRef tmp_ptr; |
| 2514 | }; | 2514 | }; |
| 2515 | 2515 | ||
| 2516 | struct IrInstructionResizeSlice { | ||
| 2517 | IrInstruction base; | ||
| 2518 | |||
| 2519 | IrInstruction *operand; | ||
| 2520 | LLVMValueRef tmp_ptr; | ||
| 2521 | }; | ||
| 2522 | |||
| 2516 | struct IrInstructionContainerInitList { | 2523 | struct IrInstructionContainerInitList { |
| 2517 | IrInstruction base; | 2524 | IrInstruction base; |
| 2518 | 2525 |
src/codegen.cpp+75-63| ... | @@ -2882,6 +2882,76 @@ static void add_error_range_check(CodeGen *g, ZigType *err_set_type, ZigType *in | ... | @@ -2882,6 +2882,76 @@ static void add_error_range_check(CodeGen *g, ZigType *err_set_type, ZigType *in |
| 2882 | } | 2882 | } |
| 2883 | } | 2883 | } |
| 2884 | 2884 | ||
| 2885 | static LLVMValueRef ir_render_resize_slice(CodeGen *g, IrExecutable *executable, | ||
| 2886 | IrInstructionResizeSlice *instruction) | ||
| 2887 | { | ||
| 2888 | ZigType *actual_type = instruction->operand->value.type; | ||
| 2889 | ZigType *wanted_type = instruction->base.value.type; | ||
| 2890 | LLVMValueRef expr_val = ir_llvm_value(g, instruction->operand); | ||
| 2891 | assert(expr_val); | ||
| 2892 | |||
| 2893 | assert(instruction->tmp_ptr); | ||
| 2894 | assert(wanted_type->id == ZigTypeIdStruct); | ||
| 2895 | assert(wanted_type->data.structure.is_slice); | ||
| 2896 | assert(actual_type->id == ZigTypeIdStruct); | ||
| 2897 | assert(actual_type->data.structure.is_slice); | ||
| 2898 | |||
| 2899 | ZigType *actual_pointer_type = actual_type->data.structure.fields[0].type_entry; | ||
| 2900 | ZigType *actual_child_type = actual_pointer_type->data.pointer.child_type; | ||
| 2901 | ZigType *wanted_pointer_type = wanted_type->data.structure.fields[0].type_entry; | ||
| 2902 | ZigType *wanted_child_type = wanted_pointer_type->data.pointer.child_type; | ||
| 2903 | |||
| 2904 | |||
| 2905 | size_t actual_ptr_index = actual_type->data.structure.fields[slice_ptr_index].gen_index; | ||
| 2906 | size_t actual_len_index = actual_type->data.structure.fields[slice_len_index].gen_index; | ||
| 2907 | size_t wanted_ptr_index = wanted_type->data.structure.fields[slice_ptr_index].gen_index; | ||
| 2908 | size_t wanted_len_index = wanted_type->data.structure.fields[slice_len_index].gen_index; | ||
| 2909 | |||
| 2910 | LLVMValueRef src_ptr_ptr = LLVMBuildStructGEP(g->builder, expr_val, (unsigned)actual_ptr_index, ""); | ||
| 2911 | LLVMValueRef src_ptr = gen_load_untyped(g, src_ptr_ptr, 0, false, ""); | ||
| 2912 | LLVMValueRef src_ptr_casted = LLVMBuildBitCast(g->builder, src_ptr, | ||
| 2913 | wanted_type->data.structure.fields[0].type_entry->type_ref, ""); | ||
| 2914 | LLVMValueRef dest_ptr_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, | ||
| 2915 | (unsigned)wanted_ptr_index, ""); | ||
| 2916 | gen_store_untyped(g, src_ptr_casted, dest_ptr_ptr, 0, false); | ||
| 2917 | |||
| 2918 | LLVMValueRef src_len_ptr = LLVMBuildStructGEP(g->builder, expr_val, (unsigned)actual_len_index, ""); | ||
| 2919 | LLVMValueRef src_len = gen_load_untyped(g, src_len_ptr, 0, false, ""); | ||
| 2920 | uint64_t src_size = type_size(g, actual_child_type); | ||
| 2921 | uint64_t dest_size = type_size(g, wanted_child_type); | ||
| 2922 | |||
| 2923 | LLVMValueRef new_len; | ||
| 2924 | if (dest_size == 1) { | ||
| 2925 | LLVMValueRef src_size_val = LLVMConstInt(g->builtin_types.entry_usize->type_ref, src_size, false); | ||
| 2926 | new_len = LLVMBuildMul(g->builder, src_len, src_size_val, ""); | ||
| 2927 | } else if (src_size == 1) { | ||
| 2928 | LLVMValueRef dest_size_val = LLVMConstInt(g->builtin_types.entry_usize->type_ref, dest_size, false); | ||
| 2929 | if (ir_want_runtime_safety(g, &instruction->base)) { | ||
| 2930 | LLVMValueRef remainder_val = LLVMBuildURem(g->builder, src_len, dest_size_val, ""); | ||
| 2931 | LLVMValueRef zero = LLVMConstNull(g->builtin_types.entry_usize->type_ref); | ||
| 2932 | LLVMValueRef ok_bit = LLVMBuildICmp(g->builder, LLVMIntEQ, remainder_val, zero, ""); | ||
| 2933 | LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "SliceWidenOk"); | ||
| 2934 | LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "SliceWidenFail"); | ||
| 2935 | LLVMBuildCondBr(g->builder, ok_bit, ok_block, fail_block); | ||
| 2936 | |||
| 2937 | LLVMPositionBuilderAtEnd(g->builder, fail_block); | ||
| 2938 | gen_safety_crash(g, PanicMsgIdSliceWidenRemainder); | ||
| 2939 | |||
| 2940 | LLVMPositionBuilderAtEnd(g->builder, ok_block); | ||
| 2941 | } | ||
| 2942 | new_len = LLVMBuildExactUDiv(g->builder, src_len, dest_size_val, ""); | ||
| 2943 | } else { | ||
| 2944 | zig_unreachable(); | ||
| 2945 | } | ||
| 2946 | |||
| 2947 | LLVMValueRef dest_len_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, | ||
| 2948 | (unsigned)wanted_len_index, ""); | ||
| 2949 | gen_store_untyped(g, new_len, dest_len_ptr, 0, false); | ||
| 2950 | |||
| 2951 | |||
| 2952 | return instruction->tmp_ptr; | ||
| 2953 | } | ||
| 2954 | |||
| 2885 | static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable, | 2955 | static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable, |
| 2886 | IrInstructionCast *cast_instruction) | 2956 | IrInstructionCast *cast_instruction) |
| 2887 | { | 2957 | { |
| ... | @@ -2896,69 +2966,6 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable, | ... | @@ -2896,69 +2966,6 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable, |
| 2896 | zig_unreachable(); | 2966 | zig_unreachable(); |
| 2897 | case CastOpNoop: | 2967 | case CastOpNoop: |
| 2898 | return expr_val; | 2968 | return expr_val; |
| 2899 | case CastOpResizeSlice: | ||
| 2900 | { | ||
| 2901 | assert(cast_instruction->tmp_ptr); | ||
| 2902 | assert(wanted_type->id == ZigTypeIdStruct); | ||
| 2903 | assert(wanted_type->data.structure.is_slice); | ||
| 2904 | assert(actual_type->id == ZigTypeIdStruct); | ||
| 2905 | assert(actual_type->data.structure.is_slice); | ||
| 2906 | |||
| 2907 | ZigType *actual_pointer_type = actual_type->data.structure.fields[0].type_entry; | ||
| 2908 | ZigType *actual_child_type = actual_pointer_type->data.pointer.child_type; | ||
| 2909 | ZigType *wanted_pointer_type = wanted_type->data.structure.fields[0].type_entry; | ||
| 2910 | ZigType *wanted_child_type = wanted_pointer_type->data.pointer.child_type; | ||
| 2911 | |||
| 2912 | |||
| 2913 | size_t actual_ptr_index = actual_type->data.structure.fields[slice_ptr_index].gen_index; | ||
| 2914 | size_t actual_len_index = actual_type->data.structure.fields[slice_len_index].gen_index; | ||
| 2915 | size_t wanted_ptr_index = wanted_type->data.structure.fields[slice_ptr_index].gen_index; | ||
| 2916 | size_t wanted_len_index = wanted_type->data.structure.fields[slice_len_index].gen_index; | ||
| 2917 | |||
| 2918 | LLVMValueRef src_ptr_ptr = LLVMBuildStructGEP(g->builder, expr_val, (unsigned)actual_ptr_index, ""); | ||
| 2919 | LLVMValueRef src_ptr = gen_load_untyped(g, src_ptr_ptr, 0, false, ""); | ||
| 2920 | LLVMValueRef src_ptr_casted = LLVMBuildBitCast(g->builder, src_ptr, | ||
| 2921 | wanted_type->data.structure.fields[0].type_entry->type_ref, ""); | ||
| 2922 | LLVMValueRef dest_ptr_ptr = LLVMBuildStructGEP(g->builder, cast_instruction->tmp_ptr, | ||
| 2923 | (unsigned)wanted_ptr_index, ""); | ||
| 2924 | gen_store_untyped(g, src_ptr_casted, dest_ptr_ptr, 0, false); | ||
| 2925 | |||
| 2926 | LLVMValueRef src_len_ptr = LLVMBuildStructGEP(g->builder, expr_val, (unsigned)actual_len_index, ""); | ||
| 2927 | LLVMValueRef src_len = gen_load_untyped(g, src_len_ptr, 0, false, ""); | ||
| 2928 | uint64_t src_size = type_size(g, actual_child_type); | ||
| 2929 | uint64_t dest_size = type_size(g, wanted_child_type); | ||
| 2930 | |||
| 2931 | LLVMValueRef new_len; | ||
| 2932 | if (dest_size == 1) { | ||
| 2933 | LLVMValueRef src_size_val = LLVMConstInt(g->builtin_types.entry_usize->type_ref, src_size, false); | ||
| 2934 | new_len = LLVMBuildMul(g->builder, src_len, src_size_val, ""); | ||
| 2935 | } else if (src_size == 1) { | ||
| 2936 | LLVMValueRef dest_size_val = LLVMConstInt(g->builtin_types.entry_usize->type_ref, dest_size, false); | ||
| 2937 | if (ir_want_runtime_safety(g, &cast_instruction->base)) { | ||
| 2938 | LLVMValueRef remainder_val = LLVMBuildURem(g->builder, src_len, dest_size_val, ""); | ||
| 2939 | LLVMValueRef zero = LLVMConstNull(g->builtin_types.entry_usize->type_ref); | ||
| 2940 | LLVMValueRef ok_bit = LLVMBuildICmp(g->builder, LLVMIntEQ, remainder_val, zero, ""); | ||
| 2941 | LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "SliceWidenOk"); | ||
| 2942 | LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "SliceWidenFail"); | ||
| 2943 | LLVMBuildCondBr(g->builder, ok_bit, ok_block, fail_block); | ||
| 2944 | |||
| 2945 | LLVMPositionBuilderAtEnd(g->builder, fail_block); | ||
| 2946 | gen_safety_crash(g, PanicMsgIdSliceWidenRemainder); | ||
| 2947 | |||
| 2948 | LLVMPositionBuilderAtEnd(g->builder, ok_block); | ||
| 2949 | } | ||
| 2950 | new_len = LLVMBuildExactUDiv(g->builder, src_len, dest_size_val, ""); | ||
| 2951 | } else { | ||
| 2952 | zig_unreachable(); | ||
| 2953 | } | ||
| 2954 | |||
| 2955 | LLVMValueRef dest_len_ptr = LLVMBuildStructGEP(g->builder, cast_instruction->tmp_ptr, | ||
| 2956 | (unsigned)wanted_len_index, ""); | ||
| 2957 | gen_store_untyped(g, new_len, dest_len_ptr, 0, false); | ||
| 2958 | |||
| 2959 | |||
| 2960 | return cast_instruction->tmp_ptr; | ||
| 2961 | } | ||
| 2962 | case CastOpIntToFloat: | 2969 | case CastOpIntToFloat: |
| 2963 | assert(actual_type->id == ZigTypeIdInt); | 2970 | assert(actual_type->id == ZigTypeIdInt); |
| 2964 | if (actual_type->data.integral.is_signed) { | 2971 | if (actual_type->data.integral.is_signed) { |
| ... | @@ -5625,6 +5632,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, | ... | @@ -5625,6 +5632,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, |
| 5625 | return ir_render_vector_to_array(g, executable, (IrInstructionVectorToArray *)instruction); | 5632 | return ir_render_vector_to_array(g, executable, (IrInstructionVectorToArray *)instruction); |
| 5626 | case IrInstructionIdAssertZero: | 5633 | case IrInstructionIdAssertZero: |
| 5627 | return ir_render_assert_zero(g, executable, (IrInstructionAssertZero *)instruction); | 5634 | return ir_render_assert_zero(g, executable, (IrInstructionAssertZero *)instruction); |
| 5635 | case IrInstructionIdResizeSlice: | ||
| 5636 | return ir_render_resize_slice(g, executable, (IrInstructionResizeSlice *)instruction); | ||
| 5628 | } | 5637 | } |
| 5629 | zig_unreachable(); | 5638 | zig_unreachable(); |
| 5630 | } | 5639 | } |
| ... | @@ -6716,6 +6725,9 @@ static void do_code_gen(CodeGen *g) { | ... | @@ -6716,6 +6725,9 @@ static void do_code_gen(CodeGen *g) { |
| 6716 | } else if (instruction->id == IrInstructionIdCmpxchgGen) { | 6725 | } else if (instruction->id == IrInstructionIdCmpxchgGen) { |
| 6717 | IrInstructionCmpxchgGen *cmpxchg_instruction = (IrInstructionCmpxchgGen *)instruction; | 6726 | IrInstructionCmpxchgGen *cmpxchg_instruction = (IrInstructionCmpxchgGen *)instruction; |
| 6718 | slot = &cmpxchg_instruction->tmp_ptr; | 6727 | slot = &cmpxchg_instruction->tmp_ptr; |
| 6728 | } else if (instruction->id == IrInstructionIdResizeSlice) { | ||
| 6729 | IrInstructionResizeSlice *resize_slice_instruction = (IrInstructionResizeSlice *)instruction; | ||
| 6730 | slot = &resize_slice_instruction->tmp_ptr; | ||
| 6719 | } else if (instruction->id == IrInstructionIdVectorToArray) { | 6731 | } else if (instruction->id == IrInstructionIdVectorToArray) { |
| 6720 | IrInstructionVectorToArray *vector_to_array_instruction = (IrInstructionVectorToArray *)instruction; | 6732 | IrInstructionVectorToArray *vector_to_array_instruction = (IrInstructionVectorToArray *)instruction; |
| 6721 | alignment_bytes = get_abi_alignment(g, vector_to_array_instruction->vector->value.type); | 6733 | alignment_bytes = get_abi_alignment(g, vector_to_array_instruction->vector->value.type); |
src/ir.cpp+51-8| ... | @@ -456,6 +456,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionCast *) { | ... | @@ -456,6 +456,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionCast *) { |
| 456 | return IrInstructionIdCast; | 456 | return IrInstructionIdCast; |
| 457 | } | 457 | } |
| 458 | 458 | ||
| 459 | static constexpr IrInstructionId ir_instruction_id(IrInstructionResizeSlice *) { | ||
| 460 | return IrInstructionIdResizeSlice; | ||
| 461 | } | ||
| 462 | |||
| 459 | static constexpr IrInstructionId ir_instruction_id(IrInstructionContainerInitList *) { | 463 | static constexpr IrInstructionId ir_instruction_id(IrInstructionContainerInitList *) { |
| 460 | return IrInstructionIdContainerInitList; | 464 | return IrInstructionIdContainerInitList; |
| 461 | } | 465 | } |
| ... | @@ -1475,6 +1479,19 @@ static IrInstruction *ir_build_var_decl_gen(IrAnalyze *ira, IrInstruction *sourc | ... | @@ -1475,6 +1479,19 @@ static IrInstruction *ir_build_var_decl_gen(IrAnalyze *ira, IrInstruction *sourc |
| 1475 | return &decl_var_instruction->base; | 1479 | return &decl_var_instruction->base; |
| 1476 | } | 1480 | } |
| 1477 | 1481 | ||
| 1482 | static IrInstruction *ir_build_resize_slice(IrAnalyze *ira, IrInstruction *source_instruction, | ||
| 1483 | IrInstruction *operand, ZigType *ty) | ||
| 1484 | { | ||
| 1485 | IrInstructionResizeSlice *instruction = ir_build_instruction<IrInstructionResizeSlice>(&ira->new_irb, | ||
| 1486 | source_instruction->scope, source_instruction->source_node); | ||
| 1487 | instruction->base.value.type = ty; | ||
| 1488 | instruction->operand = operand; | ||
| 1489 | |||
| 1490 | ir_ref_instruction(operand, ira->new_irb.current_basic_block); | ||
| 1491 | |||
| 1492 | return &instruction->base; | ||
| 1493 | } | ||
| 1494 | |||
| 1478 | static IrInstruction *ir_build_export(IrBuilder *irb, Scope *scope, AstNode *source_node, | 1495 | static IrInstruction *ir_build_export(IrBuilder *irb, Scope *scope, AstNode *source_node, |
| 1479 | IrInstruction *name, IrInstruction *target, IrInstruction *linkage) | 1496 | IrInstruction *name, IrInstruction *target, IrInstruction *linkage) |
| 1480 | { | 1497 | { |
| ... | @@ -9674,9 +9691,6 @@ static bool eval_const_expr_implicit_cast(IrAnalyze *ira, IrInstruction *source_ | ... | @@ -9674,9 +9691,6 @@ static bool eval_const_expr_implicit_cast(IrAnalyze *ira, IrInstruction *source_ |
| 9674 | } | 9691 | } |
| 9675 | const_val->type = new_type; | 9692 | const_val->type = new_type; |
| 9676 | break; | 9693 | break; |
| 9677 | case CastOpResizeSlice: | ||
| 9678 | // can't do it | ||
| 9679 | zig_unreachable(); | ||
| 9680 | case CastOpIntToFloat: | 9694 | case CastOpIntToFloat: |
| 9681 | { | 9695 | { |
| 9682 | assert(new_type->id == ZigTypeIdFloat); | 9696 | assert(new_type->id == ZigTypeIdFloat); |
| ... | @@ -9740,9 +9754,7 @@ static IrInstruction *ir_const(IrAnalyze *ira, IrInstruction *old_instruction, Z | ... | @@ -9740,9 +9754,7 @@ static IrInstruction *ir_const(IrAnalyze *ira, IrInstruction *old_instruction, Z |
| 9740 | static IrInstruction *ir_resolve_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value, | 9754 | static IrInstruction *ir_resolve_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value, |
| 9741 | ZigType *wanted_type, CastOp cast_op, bool need_alloca) | 9755 | ZigType *wanted_type, CastOp cast_op, bool need_alloca) |
| 9742 | { | 9756 | { |
| 9743 | if ((instr_is_comptime(value) || !type_has_bits(wanted_type)) && | 9757 | if (instr_is_comptime(value) || !type_has_bits(wanted_type)) { |
| 9744 | cast_op != CastOpResizeSlice) | ||
| 9745 | { | ||
| 9746 | IrInstruction *result = ir_const(ira, source_instr, wanted_type); | 9758 | IrInstruction *result = ir_const(ira, source_instr, wanted_type); |
| 9747 | if (!eval_const_expr_implicit_cast(ira, source_instr, cast_op, &value->value, value->value.type, | 9759 | if (!eval_const_expr_implicit_cast(ira, source_instr, cast_op, &value->value, value->value.type, |
| 9748 | &result->value, wanted_type)) | 9760 | &result->value, wanted_type)) |
| ... | @@ -19082,7 +19094,9 @@ static IrInstruction *ir_analyze_instruction_from_bytes(IrAnalyze *ira, IrInstru | ... | @@ -19082,7 +19094,9 @@ static IrInstruction *ir_analyze_instruction_from_bytes(IrAnalyze *ira, IrInstru |
| 19082 | } | 19094 | } |
| 19083 | } | 19095 | } |
| 19084 | 19096 | ||
| 19085 | return ir_resolve_cast(ira, &instruction->base, casted_value, dest_slice_type, CastOpResizeSlice, true); | 19097 | IrInstruction *result = ir_build_resize_slice(ira, &instruction->base, casted_value, dest_slice_type); |
| 19098 | ir_add_alloca(ira, result, dest_slice_type); | ||
| 19099 | return result; | ||
| 19086 | } | 19100 | } |
| 19087 | 19101 | ||
| 19088 | static IrInstruction *ir_analyze_instruction_to_bytes(IrAnalyze *ira, IrInstructionToBytes *instruction) { | 19102 | static IrInstruction *ir_analyze_instruction_to_bytes(IrAnalyze *ira, IrInstructionToBytes *instruction) { |
| ... | @@ -19109,7 +19123,34 @@ static IrInstruction *ir_analyze_instruction_to_bytes(IrAnalyze *ira, IrInstruct | ... | @@ -19109,7 +19123,34 @@ static IrInstruction *ir_analyze_instruction_to_bytes(IrAnalyze *ira, IrInstruct |
| 19109 | alignment, 0, 0); | 19123 | alignment, 0, 0); |
| 19110 | ZigType *dest_slice_type = get_slice_type(ira->codegen, dest_ptr_type); | 19124 | ZigType *dest_slice_type = get_slice_type(ira->codegen, dest_ptr_type); |
| 19111 | 19125 | ||
| 19112 | return ir_resolve_cast(ira, &instruction->base, target, dest_slice_type, CastOpResizeSlice, true); | 19126 | if (instr_is_comptime(target)) { |
| 19127 | ConstExprValue *target_val = ir_resolve_const(ira, target, UndefBad); | ||
| 19128 | if (target_val == nullptr) | ||
| 19129 | return ira->codegen->invalid_instruction; | ||
| 19130 | |||
| 19131 | IrInstruction *result = ir_const(ira, &instruction->base, dest_slice_type); | ||
| 19132 | result->value.data.x_struct.fields = create_const_vals(2); | ||
| 19133 | |||
| 19134 | ConstExprValue *ptr_val = &result->value.data.x_struct.fields[slice_ptr_index]; | ||
| 19135 | ConstExprValue *target_ptr_val = &target_val->data.x_struct.fields[slice_ptr_index]; | ||
| 19136 | copy_const_val(ptr_val, target_ptr_val, false); | ||
| 19137 | ptr_val->type = dest_ptr_type; | ||
| 19138 | |||
| 19139 | ConstExprValue *len_val = &result->value.data.x_struct.fields[slice_len_index]; | ||
| 19140 | len_val->special = ConstValSpecialStatic; | ||
| 19141 | len_val->type = ira->codegen->builtin_types.entry_usize; | ||
| 19142 | ConstExprValue *target_len_val = &target_val->data.x_struct.fields[slice_len_index]; | ||
| 19143 | ZigType *elem_type = src_ptr_type->data.pointer.child_type; | ||
| 19144 | BigInt elem_size_bigint; | ||
| 19145 | bigint_init_unsigned(&elem_size_bigint, type_size(ira->codegen, elem_type)); | ||
| 19146 | bigint_mul(&len_val->data.x_bigint, &target_len_val->data.x_bigint, &elem_size_bigint); | ||
| 19147 | |||
| 19148 | return result; | ||
| 19149 | } | ||
| 19150 | |||
| 19151 | IrInstruction *result = ir_build_resize_slice(ira, &instruction->base, target, dest_slice_type); | ||
| 19152 | ir_add_alloca(ira, result, dest_slice_type); | ||
| 19153 | return result; | ||
| 19113 | } | 19154 | } |
| 19114 | 19155 | ||
| 19115 | static Error resolve_ptr_align(IrAnalyze *ira, ZigType *ty, uint32_t *result_align) { | 19156 | static Error resolve_ptr_align(IrAnalyze *ira, ZigType *ty, uint32_t *result_align) { |
| ... | @@ -22274,6 +22315,7 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio | ... | @@ -22274,6 +22315,7 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio |
| 22274 | case IrInstructionIdArrayToVector: | 22315 | case IrInstructionIdArrayToVector: |
| 22275 | case IrInstructionIdVectorToArray: | 22316 | case IrInstructionIdVectorToArray: |
| 22276 | case IrInstructionIdAssertZero: | 22317 | case IrInstructionIdAssertZero: |
| 22318 | case IrInstructionIdResizeSlice: | ||
| 22277 | zig_unreachable(); | 22319 | zig_unreachable(); |
| 22278 | 22320 | ||
| 22279 | case IrInstructionIdReturn: | 22321 | case IrInstructionIdReturn: |
| ... | @@ -22673,6 +22715,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { | ... | @@ -22673,6 +22715,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 22673 | case IrInstructionIdCmpxchgGen: | 22715 | case IrInstructionIdCmpxchgGen: |
| 22674 | case IrInstructionIdCmpxchgSrc: | 22716 | case IrInstructionIdCmpxchgSrc: |
| 22675 | case IrInstructionIdAssertZero: | 22717 | case IrInstructionIdAssertZero: |
| 22718 | case IrInstructionIdResizeSlice: | ||
| 22676 | return true; | 22719 | return true; |
| 22677 | 22720 | ||
| 22678 | case IrInstructionIdPhi: | 22721 | case IrInstructionIdPhi: |
src/ir_print.cpp+9| ... | @@ -990,6 +990,12 @@ static void ir_print_assert_zero(IrPrint *irp, IrInstructionAssertZero *instruct | ... | @@ -990,6 +990,12 @@ static void ir_print_assert_zero(IrPrint *irp, IrInstructionAssertZero *instruct |
| 990 | fprintf(irp->f, ")"); | 990 | fprintf(irp->f, ")"); |
| 991 | } | 991 | } |
| 992 | 992 | ||
| 993 | static void ir_print_resize_slice(IrPrint *irp, IrInstructionResizeSlice *instruction) { | ||
| 994 | fprintf(irp->f, "@resizeSlice("); | ||
| 995 | ir_print_other_instruction(irp, instruction->operand); | ||
| 996 | fprintf(irp->f, ")"); | ||
| 997 | } | ||
| 998 | |||
| 993 | static void ir_print_int_to_err(IrPrint *irp, IrInstructionIntToErr *instruction) { | 999 | static void ir_print_int_to_err(IrPrint *irp, IrInstructionIntToErr *instruction) { |
| 994 | fprintf(irp->f, "inttoerr "); | 1000 | fprintf(irp->f, "inttoerr "); |
| 995 | ir_print_other_instruction(irp, instruction->target); | 1001 | ir_print_other_instruction(irp, instruction->target); |
| ... | @@ -1852,6 +1858,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { | ... | @@ -1852,6 +1858,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { |
| 1852 | case IrInstructionIdAssertZero: | 1858 | case IrInstructionIdAssertZero: |
| 1853 | ir_print_assert_zero(irp, (IrInstructionAssertZero *)instruction); | 1859 | ir_print_assert_zero(irp, (IrInstructionAssertZero *)instruction); |
| 1854 | break; | 1860 | break; |
| 1861 | case IrInstructionIdResizeSlice: | ||
| 1862 | ir_print_resize_slice(irp, (IrInstructionResizeSlice *)instruction); | ||
| 1863 | break; | ||
| 1855 | } | 1864 | } |
| 1856 | fprintf(irp->f, "\n"); | 1865 | fprintf(irp->f, "\n"); |
| 1857 | } | 1866 | } |
test/stage1/behavior.zig+1| ... | @@ -61,6 +61,7 @@ comptime { | ... | @@ -61,6 +61,7 @@ comptime { |
| 61 | _ = @import("behavior/reflection.zig"); | 61 | _ = @import("behavior/reflection.zig"); |
| 62 | _ = @import("behavior/sizeof_and_typeof.zig"); | 62 | _ = @import("behavior/sizeof_and_typeof.zig"); |
| 63 | _ = @import("behavior/slice.zig"); | 63 | _ = @import("behavior/slice.zig"); |
| 64 | _ = @import("behavior/slicetobytes.zig"); | ||
| 64 | _ = @import("behavior/struct.zig"); | 65 | _ = @import("behavior/struct.zig"); |
| 65 | _ = @import("behavior/struct_contains_null_ptr_itself.zig"); | 66 | _ = @import("behavior/struct_contains_null_ptr_itself.zig"); |
| 66 | _ = @import("behavior/struct_contains_slice_of_itself.zig"); | 67 | _ = @import("behavior/struct_contains_slice_of_itself.zig"); |
test/stage1/behavior/slicetobytes.zig created+29| ... | @@ -0,0 +1,29 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const builtin = @import("builtin"); | ||
| 3 | const expect = std.testing.expect; | ||
| 4 | |||
| 5 | test "@sliceToBytes packed struct at runtime and comptime" { | ||
| 6 | const Foo = packed struct { | ||
| 7 | a: u4, | ||
| 8 | b: u4, | ||
| 9 | }; | ||
| 10 | const S = struct { | ||
| 11 | fn doTheTest() void { | ||
| 12 | var foo: Foo = undefined; | ||
| 13 | var slice = @sliceToBytes(((*[1]Foo)(&foo))[0..1]); | ||
| 14 | slice[0] = 0x13; | ||
| 15 | switch (builtin.endian) { | ||
| 16 | builtin.Endian.Big => { | ||
| 17 | expect(foo.a == 0x1); | ||
| 18 | expect(foo.b == 0x3); | ||
| 19 | }, | ||
| 20 | builtin.Endian.Little => { | ||
| 21 | expect(foo.a == 0x3); | ||
| 22 | expect(foo.b == 0x1); | ||
| 23 | }, | ||
| 24 | } | ||
| 25 | } | ||
| 26 | }; | ||
| 27 | S.doTheTest(); | ||
| 28 | comptime S.doTheTest(); | ||
| 29 | } | ||