| ... | ... | @@ -344,11 +344,10 @@ static LLVMValueRef get_int_builtin_fn(CodeGen *g, TypeTableEntry *int_type, Bui |
| 344 | 344 | return *fn; |
| 345 | 345 | } |
| 346 | 346 | |
| 347 | | static LLVMValueRef get_handle_value(CodeGen *g, AstNode *source_node, LLVMValueRef ptr, TypeTableEntry *type) { |
| 347 | static LLVMValueRef get_handle_value(CodeGen *g, LLVMValueRef ptr, TypeTableEntry *type) { |
| 348 | 348 | if (handle_is_ptr(type)) { |
| 349 | 349 | return ptr; |
| 350 | 350 | } else { |
| 351 | | set_debug_source_node(g, source_node); |
| 352 | 351 | return LLVMBuildLoad(g->builder, ptr, ""); |
| 353 | 352 | } |
| 354 | 353 | } |
| ... | ... | @@ -378,7 +377,7 @@ static void gen_debug_safety_crash(CodeGen *g) { |
| 378 | 377 | LLVMBuildUnreachable(g->builder); |
| 379 | 378 | } |
| 380 | 379 | |
| 381 | | static void add_bounds_check(CodeGen *g, AstNode *source_node, LLVMValueRef target_val, |
| 380 | static void add_bounds_check(CodeGen *g, LLVMValueRef target_val, |
| 382 | 381 | LLVMIntPredicate lower_pred, LLVMValueRef lower_value, |
| 383 | 382 | LLVMIntPredicate upper_pred, LLVMValueRef upper_value) |
| 384 | 383 | { |
| ... | ... | @@ -391,8 +390,6 @@ static void add_bounds_check(CodeGen *g, AstNode *source_node, LLVMValueRef targ |
| 391 | 390 | upper_value = nullptr; |
| 392 | 391 | } |
| 393 | 392 | |
| 394 | | set_debug_source_node(g, source_node); |
| 395 | | |
| 396 | 393 | LLVMBasicBlockRef bounds_check_fail_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "BoundsCheckFail"); |
| 397 | 394 | LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "BoundsCheckOk"); |
| 398 | 395 | LLVMBasicBlockRef lower_ok_block = upper_value ? |
| ... | ... | @@ -425,12 +422,11 @@ static LLVMValueRef gen_err_name(CodeGen *g, AstNode *node) { |
| 425 | 422 | |
| 426 | 423 | AstNode *err_val_node = node->data.fn_call_expr.params.at(0); |
| 427 | 424 | LLVMValueRef err_val = gen_expr(g, err_val_node); |
| 428 | | set_debug_source_node(g, node); |
| 429 | 425 | |
| 430 | 426 | if (want_debug_safety(g, node)) { |
| 431 | 427 | LLVMValueRef zero = LLVMConstNull(LLVMTypeOf(err_val)); |
| 432 | 428 | LLVMValueRef end_val = LLVMConstInt(LLVMTypeOf(err_val), g->error_decls.length, false); |
| 433 | | add_bounds_check(g, node, err_val, LLVMIntNE, zero, LLVMIntULT, end_val); |
| 429 | add_bounds_check(g, err_val, LLVMIntNE, zero, LLVMIntULT, end_val); |
| 434 | 430 | } |
| 435 | 431 | |
| 436 | 432 | LLVMValueRef indices[] = { |
| ... | ... | @@ -514,15 +510,12 @@ static LLVMValueRef gen_truncate(CodeGen *g, AstNode *node) { |
| 514 | 510 | |
| 515 | 511 | LLVMValueRef src_val = gen_expr(g, src_node); |
| 516 | 512 | |
| 517 | | set_debug_source_node(g, node); |
| 518 | 513 | return LLVMBuildTrunc(g->builder, src_val, dest_type->type_ref, ""); |
| 519 | 514 | } |
| 520 | 515 | |
| 521 | 516 | static LLVMValueRef gen_unreachable(CodeGen *g, AstNode *node) { |
| 522 | 517 | assert(node->type == NodeTypeFnCallExpr); |
| 523 | 518 | |
| 524 | | set_debug_source_node(g, node); |
| 525 | | |
| 526 | 519 | if (want_debug_safety(g, node) || g->is_test_build) { |
| 527 | 520 | gen_debug_safety_crash(g); |
| 528 | 521 | } else { |
| ... | ... | @@ -545,7 +538,6 @@ static LLVMValueRef gen_shl_with_overflow(CodeGen *g, AstNode *node) { |
| 545 | 538 | LLVMValueRef val2 = gen_expr(g, node->data.fn_call_expr.params.at(2)); |
| 546 | 539 | LLVMValueRef ptr_result = gen_expr(g, node->data.fn_call_expr.params.at(3)); |
| 547 | 540 | |
| 548 | | set_debug_source_node(g, node); |
| 549 | 541 | LLVMValueRef result = LLVMBuildShl(g->builder, val1, val2, ""); |
| 550 | 542 | LLVMValueRef orig_val; |
| 551 | 543 | if (int_type->data.integral.is_signed) { |
| ... | ... | @@ -590,7 +582,6 @@ static LLVMValueRef gen_builtin_fn_call_expr(CodeGen *g, AstNode *node) { |
| 590 | 582 | operand, |
| 591 | 583 | LLVMConstNull(LLVMInt1Type()), |
| 592 | 584 | }; |
| 593 | | set_debug_source_node(g, node); |
| 594 | 585 | return LLVMBuildCall(g->builder, fn_val, params, 2, ""); |
| 595 | 586 | } |
| 596 | 587 | case BuiltinFnIdAddWithOverflow: |
| ... | ... | @@ -622,7 +613,6 @@ static LLVMValueRef gen_builtin_fn_call_expr(CodeGen *g, AstNode *node) { |
| 622 | 613 | op2, |
| 623 | 614 | }; |
| 624 | 615 | |
| 625 | | set_debug_source_node(g, node); |
| 626 | 616 | LLVMValueRef result_struct = LLVMBuildCall(g->builder, fn_val, params, 2, ""); |
| 627 | 617 | LLVMValueRef result = LLVMBuildExtractValue(g->builder, result_struct, 0, ""); |
| 628 | 618 | LLVMValueRef overflow_bit = LLVMBuildExtractValue(g->builder, result_struct, 1, ""); |
| ... | ... | @@ -646,7 +636,6 @@ static LLVMValueRef gen_builtin_fn_call_expr(CodeGen *g, AstNode *node) { |
| 646 | 636 | |
| 647 | 637 | LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0); |
| 648 | 638 | |
| 649 | | set_debug_source_node(g, node); |
| 650 | 639 | LLVMValueRef dest_ptr_casted = LLVMBuildBitCast(g->builder, dest_ptr, ptr_u8, ""); |
| 651 | 640 | LLVMValueRef src_ptr_casted = LLVMBuildBitCast(g->builder, src_ptr, ptr_u8, ""); |
| 652 | 641 | |
| ... | ... | @@ -677,7 +666,6 @@ static LLVMValueRef gen_builtin_fn_call_expr(CodeGen *g, AstNode *node) { |
| 677 | 666 | |
| 678 | 667 | LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0); |
| 679 | 668 | |
| 680 | | set_debug_source_node(g, node); |
| 681 | 669 | LLVMValueRef dest_ptr_casted = LLVMBuildBitCast(g->builder, dest_ptr, ptr_u8, ""); |
| 682 | 670 | |
| 683 | 671 | uint64_t align_in_bytes = get_memcpy_align(g, dest_type->data.pointer.child_type); |
| ... | ... | @@ -707,13 +695,11 @@ static LLVMValueRef gen_builtin_fn_call_expr(CodeGen *g, AstNode *node) { |
| 707 | 695 | case BuiltinFnIdErrName: |
| 708 | 696 | return gen_err_name(g, node); |
| 709 | 697 | case BuiltinFnIdBreakpoint: |
| 710 | | set_debug_source_node(g, node); |
| 711 | 698 | return LLVMBuildCall(g->builder, g->trap_fn_val, nullptr, 0, ""); |
| 712 | 699 | case BuiltinFnIdFrameAddress: |
| 713 | 700 | case BuiltinFnIdReturnAddress: |
| 714 | 701 | { |
| 715 | 702 | LLVMValueRef zero = LLVMConstNull(g->builtin_types.entry_i32->type_ref); |
| 716 | | set_debug_source_node(g, node); |
| 717 | 703 | return LLVMBuildCall(g->builder, builtin_fn->fn_val, &zero, 1, ""); |
| 718 | 704 | } |
| 719 | 705 | case BuiltinFnIdCmpExchange: |
| ... | ... | @@ -760,7 +746,6 @@ static LLVMValueRef gen_enum_value_expr(CodeGen *g, AstNode *node, TypeTableEntr |
| 760 | 746 | LLVMValueRef tmp_struct_ptr = node->data.field_access_expr.resolved_struct_val_expr.ptr; |
| 761 | 747 | |
| 762 | 748 | // populate the new tag value |
| 763 | | set_debug_source_node(g, node); |
| 764 | 749 | LLVMValueRef tag_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, 0, ""); |
| 765 | 750 | LLVMBuildStore(g->builder, tag_value, tag_field_ptr); |
| 766 | 751 | |
| ... | ... | @@ -804,7 +789,6 @@ static LLVMValueRef gen_widen_or_shorten(CodeGen *g, AstNode *source_node, TypeT |
| 804 | 789 | !wanted_type->data.integral.is_signed && actual_type->data.integral.is_signed && |
| 805 | 790 | want_debug_safety(g, source_node)) |
| 806 | 791 | { |
| 807 | | set_debug_source_node(g, source_node); |
| 808 | 792 | LLVMValueRef zero = LLVMConstNull(actual_type->type_ref); |
| 809 | 793 | LLVMValueRef ok_bit = LLVMBuildICmp(g->builder, LLVMIntSGE, expr_val, zero, ""); |
| 810 | 794 | |
| ... | ... | @@ -822,14 +806,11 @@ static LLVMValueRef gen_widen_or_shorten(CodeGen *g, AstNode *source_node, TypeT |
| 822 | 806 | return expr_val; |
| 823 | 807 | } else if (actual_bits < wanted_bits) { |
| 824 | 808 | if (actual_type->id == TypeTableEntryIdFloat) { |
| 825 | | set_debug_source_node(g, source_node); |
| 826 | 809 | return LLVMBuildFPExt(g->builder, expr_val, wanted_type->type_ref, ""); |
| 827 | 810 | } else if (actual_type->id == TypeTableEntryIdInt) { |
| 828 | 811 | if (actual_type->data.integral.is_signed) { |
| 829 | | set_debug_source_node(g, source_node); |
| 830 | 812 | return LLVMBuildSExt(g->builder, expr_val, wanted_type->type_ref, ""); |
| 831 | 813 | } else { |
| 832 | | set_debug_source_node(g, source_node); |
| 833 | 814 | return LLVMBuildZExt(g->builder, expr_val, wanted_type->type_ref, ""); |
| 834 | 815 | } |
| 835 | 816 | } else { |
| ... | ... | @@ -837,10 +818,8 @@ static LLVMValueRef gen_widen_or_shorten(CodeGen *g, AstNode *source_node, TypeT |
| 837 | 818 | } |
| 838 | 819 | } else if (actual_bits > wanted_bits) { |
| 839 | 820 | if (actual_type->id == TypeTableEntryIdFloat) { |
| 840 | | set_debug_source_node(g, source_node); |
| 841 | 821 | return LLVMBuildFPTrunc(g->builder, expr_val, wanted_type->type_ref, ""); |
| 842 | 822 | } else if (actual_type->id == TypeTableEntryIdInt) { |
| 843 | | set_debug_source_node(g, source_node); |
| 844 | 823 | LLVMValueRef trunc_val = LLVMBuildTrunc(g->builder, expr_val, wanted_type->type_ref, ""); |
| 845 | 824 | if (!want_debug_safety(g, source_node)) { |
| 846 | 825 | return trunc_val; |
| ... | ... | @@ -869,256 +848,11 @@ static LLVMValueRef gen_widen_or_shorten(CodeGen *g, AstNode *source_node, TypeT |
| 869 | 848 | } |
| 870 | 849 | } |
| 871 | 850 | |
| 872 | | static LLVMValueRef gen_cast_expr(CodeGen *g, AstNode *node) { |
| 873 | | assert(node->type == NodeTypeFnCallExpr); |
| 874 | | |
| 875 | | AstNode *expr_node = node->data.fn_call_expr.params.at(0); |
| 876 | | |
| 877 | | LLVMValueRef expr_val = gen_expr(g, expr_node); |
| 878 | | |
| 879 | | TypeTableEntry *actual_type = get_expr_type(expr_node); |
| 880 | | TypeTableEntry *wanted_type = get_expr_type(node); |
| 881 | | |
| 882 | | AstNodeFnCallExpr *cast_expr = &node->data.fn_call_expr; |
| 883 | | |
| 884 | | switch (cast_expr->cast_op) { |
| 885 | | case CastOpNoCast: |
| 886 | | zig_unreachable(); |
| 887 | | case CastOpNoop: |
| 888 | | return expr_val; |
| 889 | | case CastOpErrToInt: |
| 890 | | assert(actual_type->id == TypeTableEntryIdErrorUnion); |
| 891 | | if (!type_has_bits(actual_type->data.error.child_type)) { |
| 892 | | return gen_widen_or_shorten(g, node, g->err_tag_type, wanted_type, expr_val); |
| 893 | | } else { |
| 894 | | zig_panic("TODO"); |
| 895 | | } |
| 896 | | case CastOpMaybeWrap: |
| 897 | | { |
| 898 | | assert(cast_expr->tmp_ptr); |
| 899 | | assert(wanted_type->id == TypeTableEntryIdMaybe); |
| 900 | | assert(actual_type); |
| 901 | | |
| 902 | | TypeTableEntry *child_type = wanted_type->data.maybe.child_type; |
| 903 | | |
| 904 | | if (child_type->id == TypeTableEntryIdPointer || |
| 905 | | child_type->id == TypeTableEntryIdFn) |
| 906 | | { |
| 907 | | return expr_val; |
| 908 | | } else { |
| 909 | | set_debug_source_node(g, node); |
| 910 | | LLVMValueRef val_ptr = LLVMBuildStructGEP(g->builder, cast_expr->tmp_ptr, 0, ""); |
| 911 | | gen_assign_raw(g, node, BinOpTypeAssign, |
| 912 | | val_ptr, expr_val, child_type, actual_type); |
| 913 | | |
| 914 | | set_debug_source_node(g, node); |
| 915 | | LLVMValueRef maybe_ptr = LLVMBuildStructGEP(g->builder, cast_expr->tmp_ptr, 1, ""); |
| 916 | | LLVMBuildStore(g->builder, LLVMConstAllOnes(LLVMInt1Type()), maybe_ptr); |
| 917 | | } |
| 918 | | |
| 919 | | return cast_expr->tmp_ptr; |
| 920 | | } |
| 921 | | case CastOpNullToMaybe: |
| 922 | | // handled by constant expression evaluator |
| 923 | | zig_unreachable(); |
| 924 | | case CastOpErrorWrap: |
| 925 | | { |
| 926 | | assert(wanted_type->id == TypeTableEntryIdErrorUnion); |
| 927 | | TypeTableEntry *child_type = wanted_type->data.error.child_type; |
| 928 | | LLVMValueRef ok_err_val = LLVMConstNull(g->err_tag_type->type_ref); |
| 929 | | |
| 930 | | if (!type_has_bits(child_type)) { |
| 931 | | return ok_err_val; |
| 932 | | } else { |
| 933 | | assert(cast_expr->tmp_ptr); |
| 934 | | assert(wanted_type->id == TypeTableEntryIdErrorUnion); |
| 935 | | assert(actual_type); |
| 936 | | |
| 937 | | set_debug_source_node(g, node); |
| 938 | | LLVMValueRef err_tag_ptr = LLVMBuildStructGEP(g->builder, cast_expr->tmp_ptr, 0, ""); |
| 939 | | LLVMBuildStore(g->builder, ok_err_val, err_tag_ptr); |
| 940 | | |
| 941 | | LLVMValueRef payload_ptr = LLVMBuildStructGEP(g->builder, cast_expr->tmp_ptr, 1, ""); |
| 942 | | gen_assign_raw(g, node, BinOpTypeAssign, |
| 943 | | payload_ptr, expr_val, child_type, actual_type); |
| 944 | | |
| 945 | | return cast_expr->tmp_ptr; |
| 946 | | } |
| 947 | | } |
| 948 | | case CastOpPureErrorWrap: |
| 949 | | assert(wanted_type->id == TypeTableEntryIdErrorUnion); |
| 950 | | |
| 951 | | if (!type_has_bits(wanted_type->data.error.child_type)) { |
| 952 | | return expr_val; |
| 953 | | } else { |
| 954 | | zig_panic("TODO"); |
| 955 | | } |
| 956 | | case CastOpPtrToInt: |
| 957 | | set_debug_source_node(g, node); |
| 958 | | return LLVMBuildPtrToInt(g->builder, expr_val, wanted_type->type_ref, ""); |
| 959 | | case CastOpIntToPtr: |
| 960 | | set_debug_source_node(g, node); |
| 961 | | return LLVMBuildIntToPtr(g->builder, expr_val, wanted_type->type_ref, ""); |
| 962 | | case CastOpPointerReinterpret: |
| 963 | | set_debug_source_node(g, node); |
| 964 | | return LLVMBuildBitCast(g->builder, expr_val, wanted_type->type_ref, ""); |
| 965 | | case CastOpWidenOrShorten: |
| 966 | | return gen_widen_or_shorten(g, node, actual_type, wanted_type, expr_val); |
| 967 | | case CastOpToUnknownSizeArray: |
| 968 | | { |
| 969 | | assert(cast_expr->tmp_ptr); |
| 970 | | assert(wanted_type->id == TypeTableEntryIdStruct); |
| 971 | | assert(wanted_type->data.structure.is_slice); |
| 972 | | |
| 973 | | TypeTableEntry *pointer_type = wanted_type->data.structure.fields[0].type_entry; |
| 974 | | |
| 975 | | set_debug_source_node(g, node); |
| 976 | | |
| 977 | | size_t ptr_index = wanted_type->data.structure.fields[0].gen_index; |
| 978 | | if (ptr_index != SIZE_MAX) { |
| 979 | | LLVMValueRef ptr_ptr = LLVMBuildStructGEP(g->builder, cast_expr->tmp_ptr, ptr_index, ""); |
| 980 | | LLVMValueRef expr_bitcast = LLVMBuildBitCast(g->builder, expr_val, pointer_type->type_ref, ""); |
| 981 | | LLVMBuildStore(g->builder, expr_bitcast, ptr_ptr); |
| 982 | | } |
| 983 | | |
| 984 | | size_t len_index = wanted_type->data.structure.fields[1].gen_index; |
| 985 | | LLVMValueRef len_ptr = LLVMBuildStructGEP(g->builder, cast_expr->tmp_ptr, len_index, ""); |
| 986 | | LLVMValueRef len_val = LLVMConstInt(g->builtin_types.entry_usize->type_ref, |
| 987 | | actual_type->data.array.len, false); |
| 988 | | LLVMBuildStore(g->builder, len_val, len_ptr); |
| 989 | | |
| 990 | | return cast_expr->tmp_ptr; |
| 991 | | } |
| 992 | | case CastOpResizeSlice: |
| 993 | | { |
| 994 | | assert(cast_expr->tmp_ptr); |
| 995 | | assert(wanted_type->id == TypeTableEntryIdStruct); |
| 996 | | assert(wanted_type->data.structure.is_slice); |
| 997 | | assert(actual_type->id == TypeTableEntryIdStruct); |
| 998 | | assert(actual_type->data.structure.is_slice); |
| 999 | | |
| 1000 | | TypeTableEntry *actual_pointer_type = actual_type->data.structure.fields[0].type_entry; |
| 1001 | | TypeTableEntry *actual_child_type = actual_pointer_type->data.pointer.child_type; |
| 1002 | | TypeTableEntry *wanted_pointer_type = wanted_type->data.structure.fields[0].type_entry; |
| 1003 | | TypeTableEntry *wanted_child_type = wanted_pointer_type->data.pointer.child_type; |
| 1004 | | |
| 1005 | | set_debug_source_node(g, node); |
| 1006 | | |
| 1007 | | size_t actual_ptr_index = actual_type->data.structure.fields[0].gen_index; |
| 1008 | | size_t actual_len_index = actual_type->data.structure.fields[1].gen_index; |
| 1009 | | size_t wanted_ptr_index = wanted_type->data.structure.fields[0].gen_index; |
| 1010 | | size_t wanted_len_index = wanted_type->data.structure.fields[1].gen_index; |
| 1011 | | |
| 1012 | | LLVMValueRef src_ptr_ptr = LLVMBuildStructGEP(g->builder, expr_val, actual_ptr_index, ""); |
| 1013 | | LLVMValueRef src_ptr = LLVMBuildLoad(g->builder, src_ptr_ptr, ""); |
| 1014 | | LLVMValueRef src_ptr_casted = LLVMBuildBitCast(g->builder, src_ptr, |
| 1015 | | wanted_type->data.structure.fields[0].type_entry->type_ref, ""); |
| 1016 | | LLVMValueRef dest_ptr_ptr = LLVMBuildStructGEP(g->builder, cast_expr->tmp_ptr, |
| 1017 | | wanted_ptr_index, ""); |
| 1018 | | LLVMBuildStore(g->builder, src_ptr_casted, dest_ptr_ptr); |
| 1019 | | |
| 1020 | | LLVMValueRef src_len_ptr = LLVMBuildStructGEP(g->builder, expr_val, actual_len_index, ""); |
| 1021 | | LLVMValueRef src_len = LLVMBuildLoad(g->builder, src_len_ptr, ""); |
| 1022 | | uint64_t src_size = type_size(g, actual_child_type); |
| 1023 | | uint64_t dest_size = type_size(g, wanted_child_type); |
| 1024 | | |
| 1025 | | LLVMValueRef new_len; |
| 1026 | | if (dest_size == 1) { |
| 1027 | | LLVMValueRef src_size_val = LLVMConstInt(g->builtin_types.entry_usize->type_ref, src_size, false); |
| 1028 | | new_len = LLVMBuildMul(g->builder, src_len, src_size_val, ""); |
| 1029 | | } else if (src_size == 1) { |
| 1030 | | LLVMValueRef dest_size_val = LLVMConstInt(g->builtin_types.entry_usize->type_ref, dest_size, false); |
| 1031 | | if (want_debug_safety(g, node)) { |
| 1032 | | LLVMValueRef remainder_val = LLVMBuildURem(g->builder, src_len, dest_size_val, ""); |
| 1033 | | LLVMValueRef zero = LLVMConstNull(g->builtin_types.entry_usize->type_ref); |
| 1034 | | LLVMValueRef ok_bit = LLVMBuildICmp(g->builder, LLVMIntEQ, remainder_val, zero, ""); |
| 1035 | | LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "SliceWidenOk"); |
| 1036 | | LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "SliceWidenFail"); |
| 1037 | | LLVMBuildCondBr(g->builder, ok_bit, ok_block, fail_block); |
| 1038 | | |
| 1039 | | LLVMPositionBuilderAtEnd(g->builder, fail_block); |
| 1040 | | gen_debug_safety_crash(g); |
| 1041 | | |
| 1042 | | LLVMPositionBuilderAtEnd(g->builder, ok_block); |
| 1043 | | } |
| 1044 | | new_len = ZigLLVMBuildExactUDiv(g->builder, src_len, dest_size_val, ""); |
| 1045 | | } else { |
| 1046 | | zig_unreachable(); |
| 1047 | | } |
| 1048 | | |
| 1049 | | LLVMValueRef dest_len_ptr = LLVMBuildStructGEP(g->builder, cast_expr->tmp_ptr, |
| 1050 | | wanted_len_index, ""); |
| 1051 | | LLVMBuildStore(g->builder, new_len, dest_len_ptr); |
| 1052 | | |
| 1053 | | |
| 1054 | | return cast_expr->tmp_ptr; |
| 1055 | | } |
| 1056 | | case CastOpBytesToSlice: |
| 1057 | | { |
| 1058 | | assert(cast_expr->tmp_ptr); |
| 1059 | | assert(wanted_type->id == TypeTableEntryIdStruct); |
| 1060 | | assert(wanted_type->data.structure.is_slice); |
| 1061 | | assert(actual_type->id == TypeTableEntryIdArray); |
| 1062 | | |
| 1063 | | TypeTableEntry *wanted_pointer_type = wanted_type->data.structure.fields[0].type_entry; |
| 1064 | | TypeTableEntry *wanted_child_type = wanted_pointer_type->data.pointer.child_type; |
| 1065 | | |
| 1066 | | set_debug_source_node(g, node); |
| 1067 | | |
| 1068 | | size_t wanted_ptr_index = wanted_type->data.structure.fields[0].gen_index; |
| 1069 | | LLVMValueRef dest_ptr_ptr = LLVMBuildStructGEP(g->builder, cast_expr->tmp_ptr, wanted_ptr_index, ""); |
| 1070 | | LLVMValueRef src_ptr_casted = LLVMBuildBitCast(g->builder, expr_val, wanted_pointer_type->type_ref, ""); |
| 1071 | | LLVMBuildStore(g->builder, src_ptr_casted, dest_ptr_ptr); |
| 1072 | | |
| 1073 | | size_t wanted_len_index = wanted_type->data.structure.fields[1].gen_index; |
| 1074 | | LLVMValueRef len_ptr = LLVMBuildStructGEP(g->builder, cast_expr->tmp_ptr, wanted_len_index, ""); |
| 1075 | | LLVMValueRef len_val = LLVMConstInt(g->builtin_types.entry_usize->type_ref, |
| 1076 | | actual_type->data.array.len / type_size(g, wanted_child_type), false); |
| 1077 | | LLVMBuildStore(g->builder, len_val, len_ptr); |
| 1078 | | |
| 1079 | | return cast_expr->tmp_ptr; |
| 1080 | | } |
| 1081 | | case CastOpIntToFloat: |
| 1082 | | assert(actual_type->id == TypeTableEntryIdInt); |
| 1083 | | if (actual_type->data.integral.is_signed) { |
| 1084 | | set_debug_source_node(g, node); |
| 1085 | | return LLVMBuildSIToFP(g->builder, expr_val, wanted_type->type_ref, ""); |
| 1086 | | } else { |
| 1087 | | set_debug_source_node(g, node); |
| 1088 | | return LLVMBuildUIToFP(g->builder, expr_val, wanted_type->type_ref, ""); |
| 1089 | | } |
| 1090 | | case CastOpFloatToInt: |
| 1091 | | assert(wanted_type->id == TypeTableEntryIdInt); |
| 1092 | | if (wanted_type->data.integral.is_signed) { |
| 1093 | | set_debug_source_node(g, node); |
| 1094 | | return LLVMBuildFPToSI(g->builder, expr_val, wanted_type->type_ref, ""); |
| 1095 | | } else { |
| 1096 | | set_debug_source_node(g, node); |
| 1097 | | return LLVMBuildFPToUI(g->builder, expr_val, wanted_type->type_ref, ""); |
| 1098 | | } |
| 1099 | | |
| 1100 | | case CastOpBoolToInt: |
| 1101 | | assert(wanted_type->id == TypeTableEntryIdInt); |
| 1102 | | assert(actual_type->id == TypeTableEntryIdBool); |
| 1103 | | set_debug_source_node(g, node); |
| 1104 | | return LLVMBuildZExt(g->builder, expr_val, wanted_type->type_ref, ""); |
| 1105 | | |
| 1106 | | case CastOpIntToEnum: |
| 1107 | | return gen_widen_or_shorten(g, node, actual_type, wanted_type->data.enumeration.tag_type, expr_val); |
| 1108 | | case CastOpEnumToInt: |
| 1109 | | return gen_widen_or_shorten(g, node, actual_type->data.enumeration.tag_type, wanted_type, expr_val); |
| 1110 | | } |
| 1111 | | zig_unreachable(); |
| 1112 | | } |
| 1113 | | |
| 1114 | | |
| 1115 | 851 | static LLVMValueRef gen_fn_call_expr(CodeGen *g, AstNode *node) { |
| 1116 | 852 | assert(node->type == NodeTypeFnCallExpr); |
| 1117 | 853 | |
| 1118 | 854 | if (node->data.fn_call_expr.is_builtin) { |
| 1119 | 855 | return gen_builtin_fn_call_expr(g, node); |
| 1120 | | } else if (node->data.fn_call_expr.cast_op != CastOpNoCast) { |
| 1121 | | return gen_cast_expr(g, node); |
| 1122 | 856 | } |
| 1123 | 857 | |
| 1124 | 858 | FnTableEntry *fn_table_entry = node->data.fn_call_expr.fn_entry; |
| ... | ... | @@ -1186,7 +920,6 @@ static LLVMValueRef gen_fn_call_expr(CodeGen *g, AstNode *node) { |
| 1186 | 920 | } |
| 1187 | 921 | } |
| 1188 | 922 | |
| 1189 | | set_debug_source_node(g, node); |
| 1190 | 923 | LLVMValueRef result = ZigLLVMBuildCall(g->builder, fn_val, |
| 1191 | 924 | gen_param_values, gen_param_index, fn_type->data.fn.calling_convention, ""); |
| 1192 | 925 | |
| ... | ... | @@ -1209,7 +942,6 @@ static LLVMValueRef gen_array_base_ptr(CodeGen *g, AstNode *node) { |
| 1209 | 942 | array_ptr = gen_field_access_expr(g, node, true); |
| 1210 | 943 | if (type_entry->id == TypeTableEntryIdPointer) { |
| 1211 | 944 | // we have a double pointer so we must dereference it once |
| 1212 | | set_debug_source_node(g, node); |
| 1213 | 945 | array_ptr = LLVMBuildLoad(g->builder, array_ptr, ""); |
| 1214 | 946 | } |
| 1215 | 947 | } else { |
| ... | ... | @@ -1234,20 +966,18 @@ static LLVMValueRef gen_array_elem_ptr(CodeGen *g, AstNode *source_node, LLVMVal |
| 1234 | 966 | if (want_debug_safety(g, source_node)) { |
| 1235 | 967 | LLVMValueRef end = LLVMConstInt(g->builtin_types.entry_usize->type_ref, |
| 1236 | 968 | array_type->data.array.len, false); |
| 1237 | | add_bounds_check(g, source_node, subscript_value, LLVMIntEQ, nullptr, LLVMIntULT, end); |
| 969 | add_bounds_check(g, subscript_value, LLVMIntEQ, nullptr, LLVMIntULT, end); |
| 1238 | 970 | } |
| 1239 | 971 | LLVMValueRef indices[] = { |
| 1240 | 972 | LLVMConstNull(g->builtin_types.entry_usize->type_ref), |
| 1241 | 973 | subscript_value |
| 1242 | 974 | }; |
| 1243 | | set_debug_source_node(g, source_node); |
| 1244 | 975 | return LLVMBuildInBoundsGEP(g->builder, array_ptr, indices, 2, ""); |
| 1245 | 976 | } else if (array_type->id == TypeTableEntryIdPointer) { |
| 1246 | 977 | assert(LLVMGetTypeKind(LLVMTypeOf(array_ptr)) == LLVMPointerTypeKind); |
| 1247 | 978 | LLVMValueRef indices[] = { |
| 1248 | 979 | subscript_value |
| 1249 | 980 | }; |
| 1250 | | set_debug_source_node(g, source_node); |
| 1251 | 981 | return LLVMBuildInBoundsGEP(g->builder, array_ptr, indices, 1, ""); |
| 1252 | 982 | } else if (array_type->id == TypeTableEntryIdStruct) { |
| 1253 | 983 | assert(array_type->data.structure.is_slice); |
| ... | ... | @@ -1255,15 +985,13 @@ static LLVMValueRef gen_array_elem_ptr(CodeGen *g, AstNode *source_node, LLVMVal |
| 1255 | 985 | assert(LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(array_ptr))) == LLVMStructTypeKind); |
| 1256 | 986 | |
| 1257 | 987 | if (want_debug_safety(g, source_node)) { |
| 1258 | | set_debug_source_node(g, source_node); |
| 1259 | 988 | size_t len_index = array_type->data.structure.fields[1].gen_index; |
| 1260 | 989 | assert(len_index != SIZE_MAX); |
| 1261 | 990 | LLVMValueRef len_ptr = LLVMBuildStructGEP(g->builder, array_ptr, len_index, ""); |
| 1262 | 991 | LLVMValueRef len = LLVMBuildLoad(g->builder, len_ptr, ""); |
| 1263 | | add_bounds_check(g, source_node, subscript_value, LLVMIntEQ, nullptr, LLVMIntULT, len); |
| 992 | add_bounds_check(g, subscript_value, LLVMIntEQ, nullptr, LLVMIntULT, len); |
| 1264 | 993 | } |
| 1265 | 994 | |
| 1266 | | set_debug_source_node(g, source_node); |
| 1267 | 995 | size_t ptr_index = array_type->data.structure.fields[0].gen_index; |
| 1268 | 996 | assert(ptr_index != SIZE_MAX); |
| 1269 | 997 | LLVMValueRef ptr_ptr = LLVMBuildStructGEP(g->builder, array_ptr, ptr_index, ""); |
| ... | ... | @@ -1302,7 +1030,6 @@ static LLVMValueRef gen_field_ptr(CodeGen *g, AstNode *node, TypeTableEntry **ou |
| 1302 | 1030 | assert(var); |
| 1303 | 1031 | |
| 1304 | 1032 | if (var->type->id == TypeTableEntryIdPointer) { |
| 1305 | | set_debug_source_node(g, node); |
| 1306 | 1033 | struct_ptr = LLVMBuildLoad(g->builder, var->value_ref, ""); |
| 1307 | 1034 | } else { |
| 1308 | 1035 | struct_ptr = var->value_ref; |
| ... | ... | @@ -1312,7 +1039,6 @@ static LLVMValueRef gen_field_ptr(CodeGen *g, AstNode *node, TypeTableEntry **ou |
| 1312 | 1039 | TypeTableEntry *field_type = get_expr_type(struct_expr_node); |
| 1313 | 1040 | if (field_type->id == TypeTableEntryIdPointer) { |
| 1314 | 1041 | // we have a double pointer so we must dereference it once |
| 1315 | | set_debug_source_node(g, node); |
| 1316 | 1042 | struct_ptr = LLVMBuildLoad(g->builder, struct_ptr, ""); |
| 1317 | 1043 | } |
| 1318 | 1044 | } else { |
| ... | ... | @@ -1325,7 +1051,6 @@ static LLVMValueRef gen_field_ptr(CodeGen *g, AstNode *node, TypeTableEntry **ou |
| 1325 | 1051 | size_t gen_field_index = node->data.field_access_expr.type_struct_field->gen_index; |
| 1326 | 1052 | assert(gen_field_index != SIZE_MAX); |
| 1327 | 1053 | |
| 1328 | | set_debug_source_node(g, node); |
| 1329 | 1054 | return LLVMBuildStructGEP(g->builder, struct_ptr, gen_field_index, ""); |
| 1330 | 1055 | } |
| 1331 | 1056 | |
| ... | ... | @@ -1348,15 +1073,14 @@ static LLVMValueRef gen_slice_expr(CodeGen *g, AstNode *node) { |
| 1348 | 1073 | } |
| 1349 | 1074 | |
| 1350 | 1075 | if (want_debug_safety(g, node)) { |
| 1351 | | add_bounds_check(g, node, start_val, LLVMIntEQ, nullptr, LLVMIntULE, end_val); |
| 1076 | add_bounds_check(g, start_val, LLVMIntEQ, nullptr, LLVMIntULE, end_val); |
| 1352 | 1077 | if (node->data.slice_expr.end) { |
| 1353 | 1078 | LLVMValueRef array_end = LLVMConstInt(g->builtin_types.entry_usize->type_ref, |
| 1354 | 1079 | array_type->data.array.len, false); |
| 1355 | | add_bounds_check(g, node, end_val, LLVMIntEQ, nullptr, LLVMIntULE, array_end); |
| 1080 | add_bounds_check(g, end_val, LLVMIntEQ, nullptr, LLVMIntULE, array_end); |
| 1356 | 1081 | } |
| 1357 | 1082 | } |
| 1358 | 1083 | |
| 1359 | | set_debug_source_node(g, node); |
| 1360 | 1084 | LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, 0, ""); |
| 1361 | 1085 | LLVMValueRef indices[] = { |
| 1362 | 1086 | LLVMConstNull(g->builtin_types.entry_usize->type_ref), |
| ... | ... | @@ -1375,10 +1099,9 @@ static LLVMValueRef gen_slice_expr(CodeGen *g, AstNode *node) { |
| 1375 | 1099 | LLVMValueRef end_val = gen_expr(g, node->data.slice_expr.end); |
| 1376 | 1100 | |
| 1377 | 1101 | if (want_debug_safety(g, node)) { |
| 1378 | | add_bounds_check(g, node, start_val, LLVMIntEQ, nullptr, LLVMIntULE, end_val); |
| 1102 | add_bounds_check(g, start_val, LLVMIntEQ, nullptr, LLVMIntULE, end_val); |
| 1379 | 1103 | } |
| 1380 | 1104 | |
| 1381 | | set_debug_source_node(g, node); |
| 1382 | 1105 | LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, 0, ""); |
| 1383 | 1106 | LLVMValueRef slice_start_ptr = LLVMBuildInBoundsGEP(g->builder, array_ptr, &start_val, 1, ""); |
| 1384 | 1107 | LLVMBuildStore(g->builder, slice_start_ptr, ptr_field_ptr); |
| ... | ... | @@ -1400,7 +1123,6 @@ static LLVMValueRef gen_slice_expr(CodeGen *g, AstNode *node) { |
| 1400 | 1123 | |
| 1401 | 1124 | LLVMValueRef prev_end = nullptr; |
| 1402 | 1125 | if (!node->data.slice_expr.end || want_debug_safety(g, node)) { |
| 1403 | | set_debug_source_node(g, node); |
| 1404 | 1126 | LLVMValueRef src_len_ptr = LLVMBuildStructGEP(g->builder, array_ptr, len_index, ""); |
| 1405 | 1127 | prev_end = LLVMBuildLoad(g->builder, src_len_ptr, ""); |
| 1406 | 1128 | } |
| ... | ... | @@ -1415,13 +1137,12 @@ static LLVMValueRef gen_slice_expr(CodeGen *g, AstNode *node) { |
| 1415 | 1137 | |
| 1416 | 1138 | if (want_debug_safety(g, node)) { |
| 1417 | 1139 | assert(prev_end); |
| 1418 | | add_bounds_check(g, node, start_val, LLVMIntEQ, nullptr, LLVMIntULE, end_val); |
| 1140 | add_bounds_check(g, start_val, LLVMIntEQ, nullptr, LLVMIntULE, end_val); |
| 1419 | 1141 | if (node->data.slice_expr.end) { |
| 1420 | | add_bounds_check(g, node, end_val, LLVMIntEQ, nullptr, LLVMIntULE, prev_end); |
| 1142 | add_bounds_check(g, end_val, LLVMIntEQ, nullptr, LLVMIntULE, prev_end); |
| 1421 | 1143 | } |
| 1422 | 1144 | } |
| 1423 | 1145 | |
| 1424 | | set_debug_source_node(g, node); |
| 1425 | 1146 | LLVMValueRef src_ptr_ptr = LLVMBuildStructGEP(g->builder, array_ptr, ptr_index, ""); |
| 1426 | 1147 | LLVMValueRef src_ptr = LLVMBuildLoad(g->builder, src_ptr_ptr, ""); |
| 1427 | 1148 | LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, ptr_index, ""); |
| ... | ... | @@ -1461,7 +1182,6 @@ static LLVMValueRef gen_array_access_expr(CodeGen *g, AstNode *node, bool is_lva |
| 1461 | 1182 | if (is_lvalue || !ptr || handle_is_ptr(child_type)) { |
| 1462 | 1183 | return ptr; |
| 1463 | 1184 | } else { |
| 1464 | | set_debug_source_node(g, node); |
| 1465 | 1185 | return LLVMBuildLoad(g->builder, ptr, ""); |
| 1466 | 1186 | } |
| 1467 | 1187 | } |
| ... | ... | @@ -1471,7 +1191,7 @@ static LLVMValueRef gen_variable(CodeGen *g, AstNode *source_node, VariableTable |
| 1471 | 1191 | return nullptr; |
| 1472 | 1192 | } else { |
| 1473 | 1193 | assert(variable->value_ref); |
| 1474 | | return get_handle_value(g, source_node, variable->value_ref, variable->type); |
| 1194 | return get_handle_value(g, variable->value_ref, variable->type); |
| 1475 | 1195 | } |
| 1476 | 1196 | } |
| 1477 | 1197 | |
| ... | ... | @@ -1494,7 +1214,6 @@ static LLVMValueRef gen_field_access_expr(CodeGen *g, AstNode *node, bool is_lva |
| 1494 | 1214 | if (is_lvalue || handle_is_ptr(type_entry)) { |
| 1495 | 1215 | return ptr; |
| 1496 | 1216 | } else { |
| 1497 | | set_debug_source_node(g, node); |
| 1498 | 1217 | return LLVMBuildLoad(g->builder, ptr, ""); |
| 1499 | 1218 | } |
| 1500 | 1219 | } else if (struct_type->id == TypeTableEntryIdMetaType) { |
| ... | ... | @@ -1631,7 +1350,6 @@ static LLVMValueRef gen_prefix_op_expr(CodeGen *g, AstNode *node) { |
| 1631 | 1350 | case PrefixOpNegationWrap: |
| 1632 | 1351 | { |
| 1633 | 1352 | LLVMValueRef expr = gen_expr(g, expr_node); |
| 1634 | | set_debug_source_node(g, node); |
| 1635 | 1353 | if (expr_type->id == TypeTableEntryIdFloat) { |
| 1636 | 1354 | return LLVMBuildFNeg(g->builder, expr, ""); |
| 1637 | 1355 | } else if (expr_type->id == TypeTableEntryIdInt) { |
| ... | ... | @@ -1653,13 +1371,11 @@ static LLVMValueRef gen_prefix_op_expr(CodeGen *g, AstNode *node) { |
| 1653 | 1371 | { |
| 1654 | 1372 | LLVMValueRef expr = gen_expr(g, expr_node); |
| 1655 | 1373 | LLVMValueRef zero = LLVMConstNull(LLVMTypeOf(expr)); |
| 1656 | | set_debug_source_node(g, node); |
| 1657 | 1374 | return LLVMBuildICmp(g->builder, LLVMIntEQ, expr, zero, ""); |
| 1658 | 1375 | } |
| 1659 | 1376 | case PrefixOpBinNot: |
| 1660 | 1377 | { |
| 1661 | 1378 | LLVMValueRef expr = gen_expr(g, expr_node); |
| 1662 | | set_debug_source_node(g, node); |
| 1663 | 1379 | return LLVMBuildNot(g->builder, expr, ""); |
| 1664 | 1380 | } |
| 1665 | 1381 | case PrefixOpAddressOf: |
| ... | ... | @@ -1677,7 +1393,7 @@ static LLVMValueRef gen_prefix_op_expr(CodeGen *g, AstNode *node) { |
| 1677 | 1393 | return nullptr; |
| 1678 | 1394 | } else { |
| 1679 | 1395 | TypeTableEntry *child_type = expr_type->data.pointer.child_type; |
| 1680 | | return get_handle_value(g, node, expr, child_type); |
| 1396 | return get_handle_value(g, expr, child_type); |
| 1681 | 1397 | } |
| 1682 | 1398 | } |
| 1683 | 1399 | case PrefixOpMaybe: |
| ... | ... | @@ -1698,13 +1414,11 @@ static LLVMValueRef gen_prefix_op_expr(CodeGen *g, AstNode *node) { |
| 1698 | 1414 | if (want_debug_safety(g, node)) { |
| 1699 | 1415 | LLVMValueRef err_val; |
| 1700 | 1416 | if (type_has_bits(child_type)) { |
| 1701 | | set_debug_source_node(g, node); |
| 1702 | 1417 | LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, expr_val, 0, ""); |
| 1703 | 1418 | err_val = LLVMBuildLoad(g->builder, err_val_ptr, ""); |
| 1704 | 1419 | } else { |
| 1705 | 1420 | err_val = expr_val; |
| 1706 | 1421 | } |
| 1707 | | set_debug_source_node(g, node); |
| 1708 | 1422 | LLVMValueRef zero = LLVMConstNull(g->err_tag_type->type_ref); |
| 1709 | 1423 | LLVMValueRef cond_val = LLVMBuildICmp(g->builder, LLVMIntEQ, err_val, zero, ""); |
| 1710 | 1424 | LLVMBasicBlockRef err_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "UnwrapErrError"); |
| ... | ... | @@ -1719,7 +1433,7 @@ static LLVMValueRef gen_prefix_op_expr(CodeGen *g, AstNode *node) { |
| 1719 | 1433 | |
| 1720 | 1434 | if (type_has_bits(child_type)) { |
| 1721 | 1435 | LLVMValueRef child_val_ptr = LLVMBuildStructGEP(g->builder, expr_val, 1, ""); |
| 1722 | | return get_handle_value(g, expr_node, child_val_ptr, child_type); |
| 1436 | return get_handle_value(g, child_val_ptr, child_type); |
| 1723 | 1437 | } else { |
| 1724 | 1438 | return nullptr; |
| 1725 | 1439 | } |
| ... | ... | @@ -1733,7 +1447,6 @@ static LLVMValueRef gen_prefix_op_expr(CodeGen *g, AstNode *node) { |
| 1733 | 1447 | TypeTableEntry *child_type = expr_type->data.maybe.child_type; |
| 1734 | 1448 | |
| 1735 | 1449 | if (want_debug_safety(g, node)) { |
| 1736 | | set_debug_source_node(g, node); |
| 1737 | 1450 | LLVMValueRef cond_val; |
| 1738 | 1451 | if (child_type->id == TypeTableEntryIdPointer || |
| 1739 | 1452 | child_type->id == TypeTableEntryIdFn) |
| ... | ... | @@ -1761,9 +1474,8 @@ static LLVMValueRef gen_prefix_op_expr(CodeGen *g, AstNode *node) { |
| 1761 | 1474 | { |
| 1762 | 1475 | return expr_val; |
| 1763 | 1476 | } else { |
| 1764 | | set_debug_source_node(g, node); |
| 1765 | 1477 | LLVMValueRef maybe_field_ptr = LLVMBuildStructGEP(g->builder, expr_val, 0, ""); |
| 1766 | | return get_handle_value(g, node, maybe_field_ptr, child_type); |
| 1478 | return get_handle_value(g, maybe_field_ptr, child_type); |
| 1767 | 1479 | } |
| 1768 | 1480 | } |
| 1769 | 1481 | } |
| ... | ... | @@ -1773,7 +1485,6 @@ static LLVMValueRef gen_prefix_op_expr(CodeGen *g, AstNode *node) { |
| 1773 | 1485 | static LLVMValueRef gen_div(CodeGen *g, AstNode *source_node, LLVMValueRef val1, LLVMValueRef val2, |
| 1774 | 1486 | TypeTableEntry *type_entry, bool exact) |
| 1775 | 1487 | { |
| 1776 | | set_debug_source_node(g, source_node); |
| 1777 | 1488 | |
| 1778 | 1489 | if (want_debug_safety(g, source_node)) { |
| 1779 | 1490 | LLVMValueRef zero = LLVMConstNull(type_entry->type_ref); |
| ... | ... | @@ -1846,22 +1557,18 @@ static LLVMValueRef gen_arithmetic_bin_op(CodeGen *g, AstNode *source_node, |
| 1846 | 1557 | switch (bin_op) { |
| 1847 | 1558 | case BinOpTypeBinOr: |
| 1848 | 1559 | case BinOpTypeAssignBitOr: |
| 1849 | | set_debug_source_node(g, source_node); |
| 1850 | 1560 | return LLVMBuildOr(g->builder, val1, val2, ""); |
| 1851 | 1561 | case BinOpTypeBinXor: |
| 1852 | 1562 | case BinOpTypeAssignBitXor: |
| 1853 | | set_debug_source_node(g, source_node); |
| 1854 | 1563 | return LLVMBuildXor(g->builder, val1, val2, ""); |
| 1855 | 1564 | case BinOpTypeBinAnd: |
| 1856 | 1565 | case BinOpTypeAssignBitAnd: |
| 1857 | | set_debug_source_node(g, source_node); |
| 1858 | 1566 | return LLVMBuildAnd(g->builder, val1, val2, ""); |
| 1859 | 1567 | case BinOpTypeBitShiftLeft: |
| 1860 | 1568 | case BinOpTypeBitShiftLeftWrap: |
| 1861 | 1569 | case BinOpTypeAssignBitShiftLeft: |
| 1862 | 1570 | case BinOpTypeAssignBitShiftLeftWrap: |
| 1863 | 1571 | { |
| 1864 | | set_debug_source_node(g, source_node); |
| 1865 | 1572 | assert(op1_type->id == TypeTableEntryIdInt); |
| 1866 | 1573 | bool is_wrapping = (bin_op == BinOpTypeBitShiftLeftWrap) || |
| 1867 | 1574 | (bin_op == BinOpTypeAssignBitShiftLeftWrap); |
| ... | ... | @@ -1880,7 +1587,6 @@ static LLVMValueRef gen_arithmetic_bin_op(CodeGen *g, AstNode *source_node, |
| 1880 | 1587 | assert(op1_type->id == TypeTableEntryIdInt); |
| 1881 | 1588 | assert(op2_type->id == TypeTableEntryIdInt); |
| 1882 | 1589 | |
| 1883 | | set_debug_source_node(g, source_node); |
| 1884 | 1590 | if (op1_type->data.integral.is_signed) { |
| 1885 | 1591 | return LLVMBuildAShr(g->builder, val1, val2, ""); |
| 1886 | 1592 | } else { |
| ... | ... | @@ -1890,7 +1596,6 @@ static LLVMValueRef gen_arithmetic_bin_op(CodeGen *g, AstNode *source_node, |
| 1890 | 1596 | case BinOpTypeAddWrap: |
| 1891 | 1597 | case BinOpTypeAssignPlus: |
| 1892 | 1598 | case BinOpTypeAssignPlusWrap: |
| 1893 | | set_debug_source_node(g, source_node); |
| 1894 | 1599 | if (op1_type->id == TypeTableEntryIdFloat) { |
| 1895 | 1600 | return LLVMBuildFAdd(g->builder, val1, val2, ""); |
| 1896 | 1601 | } else if (op1_type->id == TypeTableEntryIdInt) { |
| ... | ... | @@ -1911,7 +1616,6 @@ static LLVMValueRef gen_arithmetic_bin_op(CodeGen *g, AstNode *source_node, |
| 1911 | 1616 | case BinOpTypeSubWrap: |
| 1912 | 1617 | case BinOpTypeAssignMinus: |
| 1913 | 1618 | case BinOpTypeAssignMinusWrap: |
| 1914 | | set_debug_source_node(g, source_node); |
| 1915 | 1619 | if (op1_type->id == TypeTableEntryIdFloat) { |
| 1916 | 1620 | return LLVMBuildFSub(g->builder, val1, val2, ""); |
| 1917 | 1621 | } else if (op1_type->id == TypeTableEntryIdInt) { |
| ... | ... | @@ -1932,7 +1636,6 @@ static LLVMValueRef gen_arithmetic_bin_op(CodeGen *g, AstNode *source_node, |
| 1932 | 1636 | case BinOpTypeMultWrap: |
| 1933 | 1637 | case BinOpTypeAssignTimes: |
| 1934 | 1638 | case BinOpTypeAssignTimesWrap: |
| 1935 | | set_debug_source_node(g, source_node); |
| 1936 | 1639 | if (op1_type->id == TypeTableEntryIdFloat) { |
| 1937 | 1640 | return LLVMBuildFMul(g->builder, val1, val2, ""); |
| 1938 | 1641 | } else if (op1_type->id == TypeTableEntryIdInt) { |
| ... | ... | @@ -1954,7 +1657,6 @@ static LLVMValueRef gen_arithmetic_bin_op(CodeGen *g, AstNode *source_node, |
| 1954 | 1657 | return gen_div(g, source_node, val1, val2, op1_type, false); |
| 1955 | 1658 | case BinOpTypeMod: |
| 1956 | 1659 | case BinOpTypeAssignMod: |
| 1957 | | set_debug_source_node(g, source_node); |
| 1958 | 1660 | if (op1_type->id == TypeTableEntryIdFloat) { |
| 1959 | 1661 | return LLVMBuildFRem(g->builder, val1, val2, ""); |
| 1960 | 1662 | } else { |
| ... | ... | @@ -2044,7 +1746,6 @@ static LLVMValueRef gen_cmp_expr(CodeGen *g, AstNode *node) { |
| 2044 | 1746 | TypeTableEntry *op2_type = get_expr_type(node->data.bin_op_expr.op2); |
| 2045 | 1747 | assert(op1_type == op2_type); |
| 2046 | 1748 | |
| 2047 | | set_debug_source_node(g, node); |
| 2048 | 1749 | if (op1_type->id == TypeTableEntryIdFloat) { |
| 2049 | 1750 | LLVMRealPredicate pred = cmp_op_to_real_predicate(node->data.bin_op_expr.bin_op); |
| 2050 | 1751 | return LLVMBuildFCmp(g->builder, pred, val1, val2, ""); |
| ... | ... | @@ -2081,18 +1782,15 @@ static LLVMValueRef gen_bool_and_expr(CodeGen *g, AstNode *node) { |
| 2081 | 1782 | // block for when val1 == false (don't even evaluate the second part) |
| 2082 | 1783 | LLVMBasicBlockRef false_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "BoolAndFalse"); |
| 2083 | 1784 | |
| 2084 | | set_debug_source_node(g, node); |
| 2085 | 1785 | LLVMBuildCondBr(g->builder, val1, true_block, false_block); |
| 2086 | 1786 | |
| 2087 | 1787 | LLVMPositionBuilderAtEnd(g->builder, true_block); |
| 2088 | 1788 | LLVMValueRef val2 = gen_expr(g, node->data.bin_op_expr.op2); |
| 2089 | 1789 | LLVMBasicBlockRef post_val2_block = LLVMGetInsertBlock(g->builder); |
| 2090 | 1790 | |
| 2091 | | set_debug_source_node(g, node); |
| 2092 | 1791 | LLVMBuildBr(g->builder, false_block); |
| 2093 | 1792 | |
| 2094 | 1793 | LLVMPositionBuilderAtEnd(g->builder, false_block); |
| 2095 | | set_debug_source_node(g, node); |
| 2096 | 1794 | LLVMValueRef phi = LLVMBuildPhi(g->builder, LLVMInt1Type(), ""); |
| 2097 | 1795 | LLVMValueRef incoming_values[2] = {val1, val2}; |
| 2098 | 1796 | LLVMBasicBlockRef incoming_blocks[2] = {post_val1_block, post_val2_block}; |
| ... | ... | @@ -2112,7 +1810,6 @@ static LLVMValueRef gen_bool_or_expr(CodeGen *g, AstNode *expr_node) { |
| 2112 | 1810 | // block for when val1 == true (don't even evaluate the second part) |
| 2113 | 1811 | LLVMBasicBlockRef true_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "BoolOrTrue"); |
| 2114 | 1812 | |
| 2115 | | set_debug_source_node(g, expr_node); |
| 2116 | 1813 | LLVMBuildCondBr(g->builder, val1, true_block, false_block); |
| 2117 | 1814 | |
| 2118 | 1815 | LLVMPositionBuilderAtEnd(g->builder, false_block); |
| ... | ... | @@ -2120,11 +1817,9 @@ static LLVMValueRef gen_bool_or_expr(CodeGen *g, AstNode *expr_node) { |
| 2120 | 1817 | |
| 2121 | 1818 | LLVMBasicBlockRef post_val2_block = LLVMGetInsertBlock(g->builder); |
| 2122 | 1819 | |
| 2123 | | set_debug_source_node(g, expr_node); |
| 2124 | 1820 | LLVMBuildBr(g->builder, true_block); |
| 2125 | 1821 | |
| 2126 | 1822 | LLVMPositionBuilderAtEnd(g->builder, true_block); |
| 2127 | | set_debug_source_node(g, expr_node); |
| 2128 | 1823 | LLVMValueRef phi = LLVMBuildPhi(g->builder, LLVMInt1Type(), ""); |
| 2129 | 1824 | LLVMValueRef incoming_values[2] = {val1, val2}; |
| 2130 | 1825 | LLVMBasicBlockRef incoming_blocks[2] = {post_val1_block, post_val2_block}; |
| ... | ... | @@ -2133,14 +1828,13 @@ static LLVMValueRef gen_bool_or_expr(CodeGen *g, AstNode *expr_node) { |
| 2133 | 1828 | return phi; |
| 2134 | 1829 | } |
| 2135 | 1830 | |
| 2136 | | static LLVMValueRef gen_struct_memcpy(CodeGen *g, AstNode *source_node, LLVMValueRef src, LLVMValueRef dest, |
| 1831 | static LLVMValueRef gen_struct_memcpy(CodeGen *g, LLVMValueRef src, LLVMValueRef dest, |
| 2137 | 1832 | TypeTableEntry *type_entry) |
| 2138 | 1833 | { |
| 2139 | 1834 | assert(handle_is_ptr(type_entry)); |
| 2140 | 1835 | |
| 2141 | 1836 | LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0); |
| 2142 | 1837 | |
| 2143 | | set_debug_source_node(g, source_node); |
| 2144 | 1838 | LLVMValueRef src_ptr = LLVMBuildBitCast(g->builder, src, ptr_u8, ""); |
| 2145 | 1839 | LLVMValueRef dest_ptr = LLVMBuildBitCast(g->builder, dest, ptr_u8, ""); |
| 2146 | 1840 | |
| ... | ... | @@ -2172,18 +1866,16 @@ static LLVMValueRef gen_assign_raw(CodeGen *g, AstNode *source_node, BinOpType b |
| 2172 | 1866 | assert(op1_type == op2_type); |
| 2173 | 1867 | assert(bin_op == BinOpTypeAssign); |
| 2174 | 1868 | |
| 2175 | | return gen_struct_memcpy(g, source_node, value, target_ref, op1_type); |
| 1869 | return gen_struct_memcpy(g, value, target_ref, op1_type); |
| 2176 | 1870 | } |
| 2177 | 1871 | |
| 2178 | 1872 | if (bin_op != BinOpTypeAssign) { |
| 2179 | 1873 | assert(source_node->type == NodeTypeBinOpExpr); |
| 2180 | | set_debug_source_node(g, source_node->data.bin_op_expr.op1); |
| 2181 | 1874 | LLVMValueRef left_value = LLVMBuildLoad(g->builder, target_ref, ""); |
| 2182 | 1875 | |
| 2183 | 1876 | value = gen_arithmetic_bin_op(g, source_node, left_value, value, op1_type, op2_type, bin_op); |
| 2184 | 1877 | } |
| 2185 | 1878 | |
| 2186 | | set_debug_source_node(g, source_node); |
| 2187 | 1879 | LLVMBuildStore(g->builder, value, target_ref); |
| 2188 | 1880 | return nullptr; |
| 2189 | 1881 | } |
| ... | ... | @@ -2214,9 +1906,8 @@ static LLVMValueRef gen_unwrap_maybe(CodeGen *g, AstNode *node, LLVMValueRef may |
| 2214 | 1906 | { |
| 2215 | 1907 | return maybe_struct_ref; |
| 2216 | 1908 | } else { |
| 2217 | | set_debug_source_node(g, node); |
| 2218 | 1909 | LLVMValueRef maybe_field_ptr = LLVMBuildStructGEP(g->builder, maybe_struct_ref, 0, ""); |
| 2219 | | return get_handle_value(g, node, maybe_field_ptr, child_type); |
| 1910 | return get_handle_value(g, maybe_field_ptr, child_type); |
| 2220 | 1911 | } |
| 2221 | 1912 | } |
| 2222 | 1913 | |
| ... | ... | @@ -2240,7 +1931,6 @@ static LLVMValueRef gen_unwrap_maybe_expr(CodeGen *g, AstNode *node) { |
| 2240 | 1931 | cond_value = LLVMBuildICmp(g->builder, LLVMIntNE, maybe_struct_ref, |
| 2241 | 1932 | LLVMConstNull(child_type->type_ref), ""); |
| 2242 | 1933 | } else { |
| 2243 | | set_debug_source_node(g, node); |
| 2244 | 1934 | LLVMValueRef maybe_field_ptr = LLVMBuildStructGEP(g->builder, maybe_struct_ref, 1, ""); |
| 2245 | 1935 | cond_value = LLVMBuildLoad(g->builder, maybe_field_ptr, ""); |
| 2246 | 1936 | } |
| ... | ... | @@ -2255,21 +1945,18 @@ static LLVMValueRef gen_unwrap_maybe_expr(CodeGen *g, AstNode *node) { |
| 2255 | 1945 | |
| 2256 | 1946 | LLVMPositionBuilderAtEnd(g->builder, non_null_block); |
| 2257 | 1947 | LLVMValueRef non_null_result = gen_unwrap_maybe(g, op1_node, maybe_struct_ref); |
| 2258 | | set_debug_source_node(g, node); |
| 2259 | 1948 | LLVMBuildBr(g->builder, end_block); |
| 2260 | 1949 | LLVMBasicBlockRef post_non_null_result_block = LLVMGetInsertBlock(g->builder); |
| 2261 | 1950 | |
| 2262 | 1951 | LLVMPositionBuilderAtEnd(g->builder, null_block); |
| 2263 | 1952 | LLVMValueRef null_result = gen_expr(g, op2_node); |
| 2264 | 1953 | if (null_reachable) { |
| 2265 | | set_debug_source_node(g, node); |
| 2266 | 1954 | LLVMBuildBr(g->builder, end_block); |
| 2267 | 1955 | } |
| 2268 | 1956 | LLVMBasicBlockRef post_null_result_block = LLVMGetInsertBlock(g->builder); |
| 2269 | 1957 | |
| 2270 | 1958 | LLVMPositionBuilderAtEnd(g->builder, end_block); |
| 2271 | 1959 | if (null_reachable) { |
| 2272 | | set_debug_source_node(g, node); |
| 2273 | 1960 | LLVMValueRef phi = LLVMBuildPhi(g->builder, LLVMTypeOf(non_null_result), ""); |
| 2274 | 1961 | LLVMValueRef incoming_values[2] = {non_null_result, null_result}; |
| 2275 | 1962 | LLVMBasicBlockRef incoming_blocks[2] = {post_non_null_result_block, post_null_result_block}; |
| ... | ... | @@ -2351,7 +2038,6 @@ static LLVMValueRef gen_unwrap_err_expr(CodeGen *g, AstNode *node) { |
| 2351 | 2038 | assert(expr_type->id == TypeTableEntryIdErrorUnion); |
| 2352 | 2039 | TypeTableEntry *child_type = expr_type->data.error.child_type; |
| 2353 | 2040 | LLVMValueRef err_val; |
| 2354 | | set_debug_source_node(g, node); |
| 2355 | 2041 | if (handle_is_ptr(expr_type)) { |
| 2356 | 2042 | LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, expr_val, 0, ""); |
| 2357 | 2043 | err_val = LLVMBuildLoad(g->builder, err_val_ptr, ""); |
| ... | ... | @@ -2377,7 +2063,6 @@ static LLVMValueRef gen_unwrap_err_expr(CodeGen *g, AstNode *node) { |
| 2377 | 2063 | LLVMBuildStore(g->builder, err_val, var->value_ref); |
| 2378 | 2064 | } |
| 2379 | 2065 | LLVMValueRef err_result = gen_expr(g, op2); |
| 2380 | | set_debug_source_node(g, node); |
| 2381 | 2066 | if (have_end_block) { |
| 2382 | 2067 | LLVMBuildBr(g->builder, end_block); |
| 2383 | 2068 | } else if (err_reachable) { |
| ... | ... | @@ -2389,7 +2074,7 @@ static LLVMValueRef gen_unwrap_err_expr(CodeGen *g, AstNode *node) { |
| 2389 | 2074 | return nullptr; |
| 2390 | 2075 | } |
| 2391 | 2076 | LLVMValueRef child_val_ptr = LLVMBuildStructGEP(g->builder, expr_val, 1, ""); |
| 2392 | | LLVMValueRef child_val = get_handle_value(g, node, child_val_ptr, child_type); |
| 2077 | LLVMValueRef child_val = get_handle_value(g, child_val_ptr, child_type); |
| 2393 | 2078 | |
| 2394 | 2079 | if (!have_end_block) { |
| 2395 | 2080 | return child_val; |
| ... | ... | @@ -2452,17 +2137,14 @@ static LLVMValueRef gen_return(CodeGen *g, AstNode *source_node, LLVMValueRef va |
| 2452 | 2137 | bool is_extern = g->cur_fn->type_entry->data.fn.fn_type_id.is_extern; |
| 2453 | 2138 | if (handle_is_ptr(return_type)) { |
| 2454 | 2139 | if (is_extern) { |
| 2455 | | set_debug_source_node(g, source_node); |
| 2456 | 2140 | LLVMValueRef by_val_value = LLVMBuildLoad(g->builder, value, ""); |
| 2457 | 2141 | LLVMBuildRet(g->builder, by_val_value); |
| 2458 | 2142 | } else { |
| 2459 | 2143 | assert(g->cur_ret_ptr); |
| 2460 | 2144 | gen_assign_raw(g, source_node, BinOpTypeAssign, g->cur_ret_ptr, value, return_type, return_type); |
| 2461 | | set_debug_source_node(g, source_node); |
| 2462 | 2145 | LLVMBuildRetVoid(g->builder); |
| 2463 | 2146 | } |
| 2464 | 2147 | } else { |
| 2465 | | set_debug_source_node(g, source_node); |
| 2466 | 2148 | LLVMBuildRet(g->builder, value); |
| 2467 | 2149 | } |
| 2468 | 2150 | return nullptr; |
| ... | ... | @@ -2504,7 +2186,6 @@ static LLVMValueRef gen_return_expr(CodeGen *g, AstNode *node) { |
| 2504 | 2186 | LLVMBasicBlockRef return_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "ErrRetReturn"); |
| 2505 | 2187 | LLVMBasicBlockRef continue_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "ErrRetContinue"); |
| 2506 | 2188 | |
| 2507 | | set_debug_source_node(g, node); |
| 2508 | 2189 | LLVMValueRef err_val; |
| 2509 | 2190 | if (type_has_bits(child_type)) { |
| 2510 | 2191 | LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, value, 0, ""); |
| ... | ... | @@ -2524,7 +2205,6 @@ static LLVMValueRef gen_return_expr(CodeGen *g, AstNode *node) { |
| 2524 | 2205 | if (type_has_bits(return_type->data.error.child_type)) { |
| 2525 | 2206 | assert(g->cur_ret_ptr); |
| 2526 | 2207 | |
| 2527 | | set_debug_source_node(g, node); |
| 2528 | 2208 | LLVMValueRef tag_ptr = LLVMBuildStructGEP(g->builder, g->cur_ret_ptr, 0, ""); |
| 2529 | 2209 | LLVMBuildStore(g->builder, err_val, tag_ptr); |
| 2530 | 2210 | LLVMBuildRetVoid(g->builder); |
| ... | ... | @@ -2537,9 +2217,8 @@ static LLVMValueRef gen_return_expr(CodeGen *g, AstNode *node) { |
| 2537 | 2217 | |
| 2538 | 2218 | LLVMPositionBuilderAtEnd(g->builder, continue_block); |
| 2539 | 2219 | if (type_has_bits(child_type)) { |
| 2540 | | set_debug_source_node(g, node); |
| 2541 | 2220 | LLVMValueRef val_ptr = LLVMBuildStructGEP(g->builder, value, 1, ""); |
| 2542 | | return get_handle_value(g, node, val_ptr, child_type); |
| 2221 | return get_handle_value(g, val_ptr, child_type); |
| 2543 | 2222 | } else { |
| 2544 | 2223 | return nullptr; |
| 2545 | 2224 | } |
| ... | ... | @@ -2552,7 +2231,6 @@ static LLVMValueRef gen_return_expr(CodeGen *g, AstNode *node) { |
| 2552 | 2231 | LLVMBasicBlockRef return_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "MaybeRetReturn"); |
| 2553 | 2232 | LLVMBasicBlockRef continue_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "MaybeRetContinue"); |
| 2554 | 2233 | |
| 2555 | | set_debug_source_node(g, node); |
| 2556 | 2234 | LLVMValueRef maybe_val_ptr = LLVMBuildStructGEP(g->builder, value, 1, ""); |
| 2557 | 2235 | LLVMValueRef is_non_null = LLVMBuildLoad(g->builder, maybe_val_ptr, ""); |
| 2558 | 2236 | |
| ... | ... | @@ -2566,7 +2244,6 @@ static LLVMValueRef gen_return_expr(CodeGen *g, AstNode *node) { |
| 2566 | 2244 | if (handle_is_ptr(return_type)) { |
| 2567 | 2245 | assert(g->cur_ret_ptr); |
| 2568 | 2246 | |
| 2569 | | set_debug_source_node(g, node); |
| 2570 | 2247 | LLVMValueRef maybe_bit_ptr = LLVMBuildStructGEP(g->builder, g->cur_ret_ptr, 1, ""); |
| 2571 | 2248 | LLVMBuildStore(g->builder, zero, maybe_bit_ptr); |
| 2572 | 2249 | LLVMBuildRetVoid(g->builder); |
| ... | ... | @@ -2577,9 +2254,8 @@ static LLVMValueRef gen_return_expr(CodeGen *g, AstNode *node) { |
| 2577 | 2254 | |
| 2578 | 2255 | LLVMPositionBuilderAtEnd(g->builder, continue_block); |
| 2579 | 2256 | if (type_has_bits(child_type)) { |
| 2580 | | set_debug_source_node(g, node); |
| 2581 | 2257 | LLVMValueRef val_ptr = LLVMBuildStructGEP(g->builder, value, 0, ""); |
| 2582 | | return get_handle_value(g, node, val_ptr, child_type); |
| 2258 | return get_handle_value(g, val_ptr, child_type); |
| 2583 | 2259 | } else { |
| 2584 | 2260 | return nullptr; |
| 2585 | 2261 | } |
| ... | ... | @@ -2610,7 +2286,6 @@ static LLVMValueRef gen_if_bool_expr_raw(CodeGen *g, AstNode *source_node, LLVMV |
| 2610 | 2286 | endif_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "EndIf"); |
| 2611 | 2287 | } |
| 2612 | 2288 | |
| 2613 | | set_debug_source_node(g, source_node); |
| 2614 | 2289 | LLVMBuildCondBr(g->builder, cond_value, then_block, else_block); |
| 2615 | 2290 | |
| 2616 | 2291 | LLVMPositionBuilderAtEnd(g->builder, then_block); |
| ... | ... | @@ -2632,7 +2307,6 @@ static LLVMValueRef gen_if_bool_expr_raw(CodeGen *g, AstNode *source_node, LLVMV |
| 2632 | 2307 | if (then_endif_reachable || else_endif_reachable) { |
| 2633 | 2308 | LLVMPositionBuilderAtEnd(g->builder, endif_block); |
| 2634 | 2309 | if (use_then_value && use_else_value) { |
| 2635 | | set_debug_source_node(g, source_node); |
| 2636 | 2310 | LLVMValueRef phi = LLVMBuildPhi(g->builder, LLVMTypeOf(then_expr_result), ""); |
| 2637 | 2311 | LLVMValueRef incoming_values[2] = {then_expr_result, else_expr_result}; |
| 2638 | 2312 | LLVMBasicBlockRef incoming_blocks[2] = {after_then_block, after_else_block}; |
| ... | ... | @@ -2697,7 +2371,7 @@ static LLVMValueRef gen_if_var_then_block(CodeGen *g, AstNode *node, VariableTab |
| 2697 | 2371 | payload_val = init_val; |
| 2698 | 2372 | } else { |
| 2699 | 2373 | LLVMValueRef payload_ptr = LLVMBuildStructGEP(g->builder, init_val, 0, ""); |
| 2700 | | payload_val = get_handle_value(g, node, payload_ptr, child_type); |
| 2374 | payload_val = get_handle_value(g, payload_ptr, child_type); |
| 2701 | 2375 | } |
| 2702 | 2376 | gen_assign_raw(g, node, BinOpTypeAssign, variable->value_ref, payload_val, |
| 2703 | 2377 | variable->type, child_type); |
| ... | ... | @@ -2736,10 +2410,8 @@ static LLVMValueRef gen_if_var_expr(CodeGen *g, AstNode *node) { |
| 2736 | 2410 | |
| 2737 | 2411 | LLVMValueRef cond_value; |
| 2738 | 2412 | if (maybe_is_ptr) { |
| 2739 | | set_debug_source_node(g, node); |
| 2740 | 2413 | cond_value = LLVMBuildICmp(g->builder, LLVMIntNE, init_val, LLVMConstNull(child_type->type_ref), ""); |
| 2741 | 2414 | } else { |
| 2742 | | set_debug_source_node(g, node); |
| 2743 | 2415 | LLVMValueRef maybe_field_ptr = LLVMBuildStructGEP(g->builder, init_val, 1, ""); |
| 2744 | 2416 | cond_value = LLVMBuildLoad(g->builder, maybe_field_ptr, ""); |
| 2745 | 2417 | } |
| ... | ... | @@ -2760,7 +2432,6 @@ static LLVMValueRef gen_if_var_expr(CodeGen *g, AstNode *node) { |
| 2760 | 2432 | endif_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "MaybeEndIf"); |
| 2761 | 2433 | } |
| 2762 | 2434 | |
| 2763 | | set_debug_source_node(g, node); |
| 2764 | 2435 | LLVMBuildCondBr(g->builder, cond_value, then_block, else_block); |
| 2765 | 2436 | |
| 2766 | 2437 | LLVMPositionBuilderAtEnd(g->builder, then_block); |
| ... | ... | @@ -2810,7 +2481,7 @@ static LLVMValueRef ir_render_load_var(CodeGen *g, IrExecutable *executable, |
| 2810 | 2481 | return nullptr; |
| 2811 | 2482 | |
| 2812 | 2483 | assert(var->value_ref); |
| 2813 | | return get_handle_value(g, load_var_instruction->base.source_node, var->value_ref, var->type); |
| 2484 | return get_handle_value(g, var->value_ref, var->type); |
| 2814 | 2485 | } |
| 2815 | 2486 | |
| 2816 | 2487 | static LLVMValueRef ir_render_bin_op_bool(CodeGen *g, IrExecutable *executable, |
| ... | ... | @@ -2894,6 +2565,233 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable, |
| 2894 | 2565 | zig_unreachable(); |
| 2895 | 2566 | } |
| 2896 | 2567 | |
| 2568 | static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable, |
| 2569 | IrInstructionCast *cast_instruction) |
| 2570 | { |
| 2571 | TypeTableEntry *actual_type = cast_instruction->value->type_entry; |
| 2572 | TypeTableEntry *wanted_type = cast_instruction->base.type_entry; |
| 2573 | LLVMValueRef expr_val = cast_instruction->value->llvm_value; |
| 2574 | assert(expr_val); |
| 2575 | |
| 2576 | switch (cast_instruction->cast_op) { |
| 2577 | case CastOpNoCast: |
| 2578 | zig_unreachable(); |
| 2579 | case CastOpNoop: |
| 2580 | return expr_val; |
| 2581 | case CastOpErrToInt: |
| 2582 | assert(actual_type->id == TypeTableEntryIdErrorUnion); |
| 2583 | if (!type_has_bits(actual_type->data.error.child_type)) { |
| 2584 | return gen_widen_or_shorten(g, cast_instruction->base.source_node, |
| 2585 | g->err_tag_type, wanted_type, expr_val); |
| 2586 | } else { |
| 2587 | zig_panic("TODO"); |
| 2588 | } |
| 2589 | case CastOpMaybeWrap: |
| 2590 | { |
| 2591 | assert(cast_instruction->tmp_ptr); |
| 2592 | assert(wanted_type->id == TypeTableEntryIdMaybe); |
| 2593 | assert(actual_type); |
| 2594 | |
| 2595 | TypeTableEntry *child_type = wanted_type->data.maybe.child_type; |
| 2596 | |
| 2597 | if (child_type->id == TypeTableEntryIdPointer || |
| 2598 | child_type->id == TypeTableEntryIdFn) |
| 2599 | { |
| 2600 | return expr_val; |
| 2601 | } else { |
| 2602 | LLVMValueRef val_ptr = LLVMBuildStructGEP(g->builder, cast_instruction->tmp_ptr, 0, ""); |
| 2603 | gen_assign_raw(g, cast_instruction->base.source_node, BinOpTypeAssign, |
| 2604 | val_ptr, expr_val, child_type, actual_type); |
| 2605 | |
| 2606 | LLVMValueRef maybe_ptr = LLVMBuildStructGEP(g->builder, cast_instruction->tmp_ptr, 1, ""); |
| 2607 | LLVMBuildStore(g->builder, LLVMConstAllOnes(LLVMInt1Type()), maybe_ptr); |
| 2608 | } |
| 2609 | |
| 2610 | return cast_instruction->tmp_ptr; |
| 2611 | } |
| 2612 | case CastOpNullToMaybe: |
| 2613 | // handled by constant expression evaluator |
| 2614 | zig_unreachable(); |
| 2615 | case CastOpErrorWrap: |
| 2616 | { |
| 2617 | assert(wanted_type->id == TypeTableEntryIdErrorUnion); |
| 2618 | TypeTableEntry *child_type = wanted_type->data.error.child_type; |
| 2619 | LLVMValueRef ok_err_val = LLVMConstNull(g->err_tag_type->type_ref); |
| 2620 | |
| 2621 | if (!type_has_bits(child_type)) { |
| 2622 | return ok_err_val; |
| 2623 | } else { |
| 2624 | assert(cast_instruction->tmp_ptr); |
| 2625 | assert(wanted_type->id == TypeTableEntryIdErrorUnion); |
| 2626 | assert(actual_type); |
| 2627 | |
| 2628 | LLVMValueRef err_tag_ptr = LLVMBuildStructGEP(g->builder, cast_instruction->tmp_ptr, 0, ""); |
| 2629 | LLVMBuildStore(g->builder, ok_err_val, err_tag_ptr); |
| 2630 | |
| 2631 | LLVMValueRef payload_ptr = LLVMBuildStructGEP(g->builder, cast_instruction->tmp_ptr, 1, ""); |
| 2632 | gen_assign_raw(g, cast_instruction->base.source_node, BinOpTypeAssign, |
| 2633 | payload_ptr, expr_val, child_type, actual_type); |
| 2634 | |
| 2635 | return cast_instruction->tmp_ptr; |
| 2636 | } |
| 2637 | } |
| 2638 | case CastOpPureErrorWrap: |
| 2639 | assert(wanted_type->id == TypeTableEntryIdErrorUnion); |
| 2640 | |
| 2641 | if (!type_has_bits(wanted_type->data.error.child_type)) { |
| 2642 | return expr_val; |
| 2643 | } else { |
| 2644 | zig_panic("TODO"); |
| 2645 | } |
| 2646 | case CastOpPtrToInt: |
| 2647 | return LLVMBuildPtrToInt(g->builder, expr_val, wanted_type->type_ref, ""); |
| 2648 | case CastOpIntToPtr: |
| 2649 | return LLVMBuildIntToPtr(g->builder, expr_val, wanted_type->type_ref, ""); |
| 2650 | case CastOpPointerReinterpret: |
| 2651 | return LLVMBuildBitCast(g->builder, expr_val, wanted_type->type_ref, ""); |
| 2652 | case CastOpWidenOrShorten: |
| 2653 | return gen_widen_or_shorten(g, cast_instruction->base.source_node, actual_type, wanted_type, expr_val); |
| 2654 | case CastOpToUnknownSizeArray: |
| 2655 | { |
| 2656 | assert(cast_instruction->tmp_ptr); |
| 2657 | assert(wanted_type->id == TypeTableEntryIdStruct); |
| 2658 | assert(wanted_type->data.structure.is_slice); |
| 2659 | |
| 2660 | TypeTableEntry *pointer_type = wanted_type->data.structure.fields[0].type_entry; |
| 2661 | |
| 2662 | |
| 2663 | size_t ptr_index = wanted_type->data.structure.fields[0].gen_index; |
| 2664 | if (ptr_index != SIZE_MAX) { |
| 2665 | LLVMValueRef ptr_ptr = LLVMBuildStructGEP(g->builder, cast_instruction->tmp_ptr, ptr_index, ""); |
| 2666 | LLVMValueRef expr_bitcast = LLVMBuildBitCast(g->builder, expr_val, pointer_type->type_ref, ""); |
| 2667 | LLVMBuildStore(g->builder, expr_bitcast, ptr_ptr); |
| 2668 | } |
| 2669 | |
| 2670 | size_t len_index = wanted_type->data.structure.fields[1].gen_index; |
| 2671 | LLVMValueRef len_ptr = LLVMBuildStructGEP(g->builder, cast_instruction->tmp_ptr, len_index, ""); |
| 2672 | LLVMValueRef len_val = LLVMConstInt(g->builtin_types.entry_usize->type_ref, |
| 2673 | actual_type->data.array.len, false); |
| 2674 | LLVMBuildStore(g->builder, len_val, len_ptr); |
| 2675 | |
| 2676 | return cast_instruction->tmp_ptr; |
| 2677 | } |
| 2678 | case CastOpResizeSlice: |
| 2679 | { |
| 2680 | assert(cast_instruction->tmp_ptr); |
| 2681 | assert(wanted_type->id == TypeTableEntryIdStruct); |
| 2682 | assert(wanted_type->data.structure.is_slice); |
| 2683 | assert(actual_type->id == TypeTableEntryIdStruct); |
| 2684 | assert(actual_type->data.structure.is_slice); |
| 2685 | |
| 2686 | TypeTableEntry *actual_pointer_type = actual_type->data.structure.fields[0].type_entry; |
| 2687 | TypeTableEntry *actual_child_type = actual_pointer_type->data.pointer.child_type; |
| 2688 | TypeTableEntry *wanted_pointer_type = wanted_type->data.structure.fields[0].type_entry; |
| 2689 | TypeTableEntry *wanted_child_type = wanted_pointer_type->data.pointer.child_type; |
| 2690 | |
| 2691 | |
| 2692 | size_t actual_ptr_index = actual_type->data.structure.fields[0].gen_index; |
| 2693 | size_t actual_len_index = actual_type->data.structure.fields[1].gen_index; |
| 2694 | size_t wanted_ptr_index = wanted_type->data.structure.fields[0].gen_index; |
| 2695 | size_t wanted_len_index = wanted_type->data.structure.fields[1].gen_index; |
| 2696 | |
| 2697 | LLVMValueRef src_ptr_ptr = LLVMBuildStructGEP(g->builder, expr_val, actual_ptr_index, ""); |
| 2698 | LLVMValueRef src_ptr = LLVMBuildLoad(g->builder, src_ptr_ptr, ""); |
| 2699 | LLVMValueRef src_ptr_casted = LLVMBuildBitCast(g->builder, src_ptr, |
| 2700 | wanted_type->data.structure.fields[0].type_entry->type_ref, ""); |
| 2701 | LLVMValueRef dest_ptr_ptr = LLVMBuildStructGEP(g->builder, cast_instruction->tmp_ptr, |
| 2702 | wanted_ptr_index, ""); |
| 2703 | LLVMBuildStore(g->builder, src_ptr_casted, dest_ptr_ptr); |
| 2704 | |
| 2705 | LLVMValueRef src_len_ptr = LLVMBuildStructGEP(g->builder, expr_val, actual_len_index, ""); |
| 2706 | LLVMValueRef src_len = LLVMBuildLoad(g->builder, src_len_ptr, ""); |
| 2707 | uint64_t src_size = type_size(g, actual_child_type); |
| 2708 | uint64_t dest_size = type_size(g, wanted_child_type); |
| 2709 | |
| 2710 | LLVMValueRef new_len; |
| 2711 | if (dest_size == 1) { |
| 2712 | LLVMValueRef src_size_val = LLVMConstInt(g->builtin_types.entry_usize->type_ref, src_size, false); |
| 2713 | new_len = LLVMBuildMul(g->builder, src_len, src_size_val, ""); |
| 2714 | } else if (src_size == 1) { |
| 2715 | LLVMValueRef dest_size_val = LLVMConstInt(g->builtin_types.entry_usize->type_ref, dest_size, false); |
| 2716 | if (ir_want_debug_safety(g, &cast_instruction->base)) { |
| 2717 | LLVMValueRef remainder_val = LLVMBuildURem(g->builder, src_len, dest_size_val, ""); |
| 2718 | LLVMValueRef zero = LLVMConstNull(g->builtin_types.entry_usize->type_ref); |
| 2719 | LLVMValueRef ok_bit = LLVMBuildICmp(g->builder, LLVMIntEQ, remainder_val, zero, ""); |
| 2720 | LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "SliceWidenOk"); |
| 2721 | LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "SliceWidenFail"); |
| 2722 | LLVMBuildCondBr(g->builder, ok_bit, ok_block, fail_block); |
| 2723 | |
| 2724 | LLVMPositionBuilderAtEnd(g->builder, fail_block); |
| 2725 | gen_debug_safety_crash(g); |
| 2726 | |
| 2727 | LLVMPositionBuilderAtEnd(g->builder, ok_block); |
| 2728 | } |
| 2729 | new_len = ZigLLVMBuildExactUDiv(g->builder, src_len, dest_size_val, ""); |
| 2730 | } else { |
| 2731 | zig_unreachable(); |
| 2732 | } |
| 2733 | |
| 2734 | LLVMValueRef dest_len_ptr = LLVMBuildStructGEP(g->builder, cast_instruction->tmp_ptr, |
| 2735 | wanted_len_index, ""); |
| 2736 | LLVMBuildStore(g->builder, new_len, dest_len_ptr); |
| 2737 | |
| 2738 | |
| 2739 | return cast_instruction->tmp_ptr; |
| 2740 | } |
| 2741 | case CastOpBytesToSlice: |
| 2742 | { |
| 2743 | assert(cast_instruction->tmp_ptr); |
| 2744 | assert(wanted_type->id == TypeTableEntryIdStruct); |
| 2745 | assert(wanted_type->data.structure.is_slice); |
| 2746 | assert(actual_type->id == TypeTableEntryIdArray); |
| 2747 | |
| 2748 | TypeTableEntry *wanted_pointer_type = wanted_type->data.structure.fields[0].type_entry; |
| 2749 | TypeTableEntry *wanted_child_type = wanted_pointer_type->data.pointer.child_type; |
| 2750 | |
| 2751 | |
| 2752 | size_t wanted_ptr_index = wanted_type->data.structure.fields[0].gen_index; |
| 2753 | LLVMValueRef dest_ptr_ptr = LLVMBuildStructGEP(g->builder, cast_instruction->tmp_ptr, wanted_ptr_index, ""); |
| 2754 | LLVMValueRef src_ptr_casted = LLVMBuildBitCast(g->builder, expr_val, wanted_pointer_type->type_ref, ""); |
| 2755 | LLVMBuildStore(g->builder, src_ptr_casted, dest_ptr_ptr); |
| 2756 | |
| 2757 | size_t wanted_len_index = wanted_type->data.structure.fields[1].gen_index; |
| 2758 | LLVMValueRef len_ptr = LLVMBuildStructGEP(g->builder, cast_instruction->tmp_ptr, wanted_len_index, ""); |
| 2759 | LLVMValueRef len_val = LLVMConstInt(g->builtin_types.entry_usize->type_ref, |
| 2760 | actual_type->data.array.len / type_size(g, wanted_child_type), false); |
| 2761 | LLVMBuildStore(g->builder, len_val, len_ptr); |
| 2762 | |
| 2763 | return cast_instruction->tmp_ptr; |
| 2764 | } |
| 2765 | case CastOpIntToFloat: |
| 2766 | assert(actual_type->id == TypeTableEntryIdInt); |
| 2767 | if (actual_type->data.integral.is_signed) { |
| 2768 | return LLVMBuildSIToFP(g->builder, expr_val, wanted_type->type_ref, ""); |
| 2769 | } else { |
| 2770 | return LLVMBuildUIToFP(g->builder, expr_val, wanted_type->type_ref, ""); |
| 2771 | } |
| 2772 | case CastOpFloatToInt: |
| 2773 | assert(wanted_type->id == TypeTableEntryIdInt); |
| 2774 | if (wanted_type->data.integral.is_signed) { |
| 2775 | return LLVMBuildFPToSI(g->builder, expr_val, wanted_type->type_ref, ""); |
| 2776 | } else { |
| 2777 | return LLVMBuildFPToUI(g->builder, expr_val, wanted_type->type_ref, ""); |
| 2778 | } |
| 2779 | |
| 2780 | case CastOpBoolToInt: |
| 2781 | assert(wanted_type->id == TypeTableEntryIdInt); |
| 2782 | assert(actual_type->id == TypeTableEntryIdBool); |
| 2783 | return LLVMBuildZExt(g->builder, expr_val, wanted_type->type_ref, ""); |
| 2784 | |
| 2785 | case CastOpIntToEnum: |
| 2786 | return gen_widen_or_shorten(g, cast_instruction->base.source_node, |
| 2787 | actual_type, wanted_type->data.enumeration.tag_type, expr_val); |
| 2788 | case CastOpEnumToInt: |
| 2789 | return gen_widen_or_shorten(g, cast_instruction->base.source_node, |
| 2790 | actual_type->data.enumeration.tag_type, wanted_type, expr_val); |
| 2791 | } |
| 2792 | zig_unreachable(); |
| 2793 | } |
| 2794 | |
| 2897 | 2795 | static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, IrInstruction *instruction) { |
| 2898 | 2796 | set_debug_source_node(g, instruction->source_node); |
| 2899 | 2797 | switch (instruction->id) { |
| ... | ... | @@ -2907,13 +2805,14 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, |
| 2907 | 2805 | return ir_render_load_var(g, executable, (IrInstructionLoadVar *)instruction); |
| 2908 | 2806 | case IrInstructionIdBinOp: |
| 2909 | 2807 | return ir_render_bin_op(g, executable, (IrInstructionBinOp *)instruction); |
| 2808 | case IrInstructionIdCast: |
| 2809 | return ir_render_cast(g, executable, (IrInstructionCast *)instruction); |
| 2910 | 2810 | case IrInstructionIdCondBr: |
| 2911 | 2811 | case IrInstructionIdSwitchBr: |
| 2912 | 2812 | case IrInstructionIdPhi: |
| 2913 | 2813 | case IrInstructionIdStoreVar: |
| 2914 | 2814 | case IrInstructionIdCall: |
| 2915 | 2815 | case IrInstructionIdBuiltinCall: |
| 2916 | | case IrInstructionIdCast: |
| 2917 | 2816 | zig_panic("TODO render more IR instructions to LLVM"); |
| 2918 | 2817 | } |
| 2919 | 2818 | zig_unreachable(); |
| ... | ... | @@ -3592,7 +3491,7 @@ static LLVMValueRef gen_switch_expr(CodeGen *g, AstNode *node) { |
| 3592 | 3491 | 1, ""); |
| 3593 | 3492 | LLVMValueRef bitcasted_union_field_ptr = LLVMBuildBitCast(g->builder, union_field_ptr, |
| 3594 | 3493 | LLVMPointerType(enum_field->type_entry->type_ref, 0), ""); |
| 3595 | | LLVMValueRef handle_val = get_handle_value(g, var_node, bitcasted_union_field_ptr, |
| 3494 | LLVMValueRef handle_val = get_handle_value(g, bitcasted_union_field_ptr, |
| 3596 | 3495 | enum_field->type_entry); |
| 3597 | 3496 | |
| 3598 | 3497 | gen_assign_raw(g, var_node, BinOpTypeAssign, |
| ... | ... | @@ -3602,8 +3501,7 @@ static LLVMValueRef gen_switch_expr(CodeGen *g, AstNode *node) { |
| 3602 | 3501 | // variable is the payload |
| 3603 | 3502 | LLVMValueRef err_payload_ptr = LLVMBuildStructGEP(g->builder, |
| 3604 | 3503 | target_value_handle, 1, ""); |
| 3605 | | LLVMValueRef handle_val = get_handle_value(g, var_node, |
| 3606 | | err_payload_ptr, prong_var->type); |
| 3504 | LLVMValueRef handle_val = get_handle_value(g, err_payload_ptr, prong_var->type); |
| 3607 | 3505 | gen_assign_raw(g, var_node, BinOpTypeAssign, |
| 3608 | 3506 | prong_var->value_ref, handle_val, prong_var->type, prong_var->type); |
| 3609 | 3507 | } else { |
| ... | ... | @@ -4375,10 +4273,8 @@ static void do_code_gen(CodeGen *g) { |
| 4375 | 4273 | |
| 4376 | 4274 | // allocate structs which are the result of casts |
| 4377 | 4275 | for (size_t cea_i = 0; cea_i < fn_table_entry->cast_alloca_list.length; cea_i += 1) { |
| 4378 | | AstNode *fn_call_node = fn_table_entry->cast_alloca_list.at(cea_i); |
| 4379 | | Expr *expr = &fn_call_node->data.fn_call_expr.resolved_expr; |
| 4380 | | fn_call_node->data.fn_call_expr.tmp_ptr = LLVMBuildAlloca(g->builder, |
| 4381 | | expr->type_entry->type_ref, ""); |
| 4276 | IrInstructionCast *cast_instruction = fn_table_entry->cast_alloca_list.at(cea_i); |
| 4277 | cast_instruction->tmp_ptr = LLVMBuildAlloca(g->builder, cast_instruction->base.type_entry->type_ref, ""); |
| 4382 | 4278 | } |
| 4383 | 4279 | |
| 4384 | 4280 | // allocate structs which are struct value expressions |