| ... | ... | @@ -888,6 +888,8 @@ static LLVMValueRef gen_cast_expr(CodeGen *g, AstNode *node) { |
| 888 | 888 | |
| 889 | 889 | TypeTableEntry *actual_pointer_type = actual_type->data.structure.fields[0].type_entry; |
| 890 | 890 | TypeTableEntry *actual_child_type = actual_pointer_type->data.pointer.child_type; |
| 891 | TypeTableEntry *wanted_pointer_type = wanted_type->data.structure.fields[0].type_entry; |
| 892 | TypeTableEntry *wanted_child_type = wanted_pointer_type->data.pointer.child_type; |
| 891 | 893 | |
| 892 | 894 | set_debug_source_node(g, node); |
| 893 | 895 | |
| ... | ... | @@ -896,15 +898,6 @@ static LLVMValueRef gen_cast_expr(CodeGen *g, AstNode *node) { |
| 896 | 898 | int wanted_ptr_index = wanted_type->data.structure.fields[0].gen_index; |
| 897 | 899 | int wanted_len_index = wanted_type->data.structure.fields[1].gen_index; |
| 898 | 900 | |
| 899 | | LLVMValueRef src_len_ptr = LLVMBuildStructGEP(g->builder, expr_val, actual_len_index, ""); |
| 900 | | LLVMValueRef src_len = LLVMBuildLoad(g->builder, src_len_ptr, ""); |
| 901 | | LLVMValueRef src_size = LLVMConstInt(g->builtin_types.entry_isize->type_ref, |
| 902 | | type_size(g, actual_child_type), false); |
| 903 | | LLVMValueRef new_len = LLVMBuildMul(g->builder, src_len, src_size, ""); |
| 904 | | LLVMValueRef dest_len_ptr = LLVMBuildStructGEP(g->builder, cast_expr->tmp_ptr, |
| 905 | | wanted_len_index, ""); |
| 906 | | LLVMBuildStore(g->builder, new_len, dest_len_ptr); |
| 907 | | |
| 908 | 901 | LLVMValueRef src_ptr_ptr = LLVMBuildStructGEP(g->builder, expr_val, actual_ptr_index, ""); |
| 909 | 902 | LLVMValueRef src_ptr = LLVMBuildLoad(g->builder, src_ptr_ptr, ""); |
| 910 | 903 | LLVMValueRef src_ptr_casted = LLVMBuildBitCast(g->builder, src_ptr, |
| ... | ... | @@ -913,6 +906,40 @@ static LLVMValueRef gen_cast_expr(CodeGen *g, AstNode *node) { |
| 913 | 906 | wanted_ptr_index, ""); |
| 914 | 907 | LLVMBuildStore(g->builder, src_ptr_casted, dest_ptr_ptr); |
| 915 | 908 | |
| 909 | LLVMValueRef src_len_ptr = LLVMBuildStructGEP(g->builder, expr_val, actual_len_index, ""); |
| 910 | LLVMValueRef src_len = LLVMBuildLoad(g->builder, src_len_ptr, ""); |
| 911 | uint64_t src_size = type_size(g, actual_child_type); |
| 912 | uint64_t dest_size = type_size(g, wanted_child_type); |
| 913 | |
| 914 | LLVMValueRef new_len; |
| 915 | if (dest_size == 1) { |
| 916 | LLVMValueRef src_size_val = LLVMConstInt(g->builtin_types.entry_isize->type_ref, src_size, false); |
| 917 | new_len = LLVMBuildMul(g->builder, src_len, src_size_val, ""); |
| 918 | } else if (src_size == 1) { |
| 919 | LLVMValueRef dest_size_val = LLVMConstInt(g->builtin_types.entry_isize->type_ref, dest_size, false); |
| 920 | if (want_debug_safety(g, node)) { |
| 921 | LLVMValueRef remainder_val = LLVMBuildURem(g->builder, src_len, dest_size_val, ""); |
| 922 | LLVMValueRef zero = LLVMConstNull(g->builtin_types.entry_isize->type_ref); |
| 923 | LLVMValueRef ok_bit = LLVMBuildICmp(g->builder, LLVMIntEQ, remainder_val, zero, ""); |
| 924 | LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "SliceWidenOk"); |
| 925 | LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "SliceWidenFail"); |
| 926 | LLVMBuildCondBr(g->builder, ok_bit, ok_block, fail_block); |
| 927 | |
| 928 | LLVMPositionBuilderAtEnd(g->builder, fail_block); |
| 929 | gen_debug_safety_crash(g); |
| 930 | |
| 931 | LLVMPositionBuilderAtEnd(g->builder, ok_block); |
| 932 | } |
| 933 | new_len = ZigLLVMBuildExactUDiv(g->builder, src_len, dest_size_val, ""); |
| 934 | } else { |
| 935 | zig_unreachable(); |
| 936 | } |
| 937 | |
| 938 | LLVMValueRef dest_len_ptr = LLVMBuildStructGEP(g->builder, cast_expr->tmp_ptr, |
| 939 | wanted_len_index, ""); |
| 940 | LLVMBuildStore(g->builder, new_len, dest_len_ptr); |
| 941 | |
| 942 | |
| 916 | 943 | return cast_expr->tmp_ptr; |
| 917 | 944 | } |
| 918 | 945 | case CastOpIntToFloat: |