| ... | ... | @@ -65,6 +65,11 @@ void codegen_set_libc_path(CodeGen *g, Buf *libc_path) { |
| 65 | 65 | static LLVMValueRef gen_expr(CodeGen *g, AstNode *expr_node); |
| 66 | 66 | static LLVMValueRef gen_lvalue(CodeGen *g, AstNode *expr_node, AstNode *node, TypeTableEntry **out_type_entry); |
| 67 | 67 | static LLVMValueRef gen_field_access_expr(CodeGen *g, AstNode *node, bool is_lvalue); |
| 68 | static LLVMValueRef gen_var_decl_raw(CodeGen *g, AstNode *source_node, AstNodeVariableDeclaration *var_decl, |
| 69 | BlockContext *block_context, bool unwrap_maybe, LLVMValueRef *init_val); |
| 70 | static LLVMValueRef gen_assign_raw(CodeGen *g, AstNode *source_node, BinOpType bin_op, |
| 71 | LLVMValueRef target_ref, LLVMValueRef value, |
| 72 | TypeTableEntry *op1_type, TypeTableEntry *op2_type); |
| 68 | 73 | |
| 69 | 74 | |
| 70 | 75 | static TypeTableEntry *get_type_for_type_node(CodeGen *g, AstNode *type_node) { |
| ... | ... | @@ -132,7 +137,7 @@ static LLVMValueRef find_or_create_string(CodeGen *g, Buf *str, bool c) { |
| 132 | 137 | } |
| 133 | 138 | |
| 134 | 139 | static TypeTableEntry *get_expr_type(AstNode *node) { |
| 135 | | TypeTableEntry *cast_type = node->codegen_node->expr_node.implicit_cast.type; |
| 140 | TypeTableEntry *cast_type = node->codegen_node->expr_node.implicit_cast.after_type; |
| 136 | 141 | return cast_type ? cast_type : node->codegen_node->expr_node.type_entry; |
| 137 | 142 | } |
| 138 | 143 | |
| ... | ... | @@ -367,6 +372,22 @@ static LLVMValueRef gen_bare_cast(CodeGen *g, AstNode *node, LLVMValueRef expr_v |
| 367 | 372 | switch (cast_node->op) { |
| 368 | 373 | case CastOpNothing: |
| 369 | 374 | return expr_val; |
| 375 | case CastOpMaybeWrap: |
| 376 | { |
| 377 | assert(cast_node->ptr); |
| 378 | assert(wanted_type->id == TypeTableEntryIdMaybe); |
| 379 | |
| 380 | add_debug_source_node(g, node); |
| 381 | LLVMValueRef val_ptr = LLVMBuildStructGEP(g->builder, cast_node->ptr, 0, ""); |
| 382 | gen_assign_raw(g, node, BinOpTypeAssign, |
| 383 | val_ptr, expr_val, wanted_type->data.maybe.child_type, actual_type); |
| 384 | |
| 385 | add_debug_source_node(g, node); |
| 386 | LLVMValueRef maybe_ptr = LLVMBuildStructGEP(g->builder, cast_node->ptr, 1, ""); |
| 387 | LLVMBuildStore(g->builder, LLVMConstAllOnes(LLVMInt1Type()), maybe_ptr); |
| 388 | |
| 389 | return cast_node->ptr; |
| 390 | } |
| 370 | 391 | case CastOpPtrToInt: |
| 371 | 392 | return LLVMBuildPtrToInt(g->builder, expr_val, wanted_type->type_ref, ""); |
| 372 | 393 | case CastOpIntWidenOrShorten: |
| ... | ... | @@ -423,34 +444,33 @@ static LLVMValueRef gen_cast_expr(CodeGen *g, AstNode *node) { |
| 423 | 444 | |
| 424 | 445 | } |
| 425 | 446 | |
| 426 | | static LLVMValueRef gen_arithmetic_bin_op(CodeGen *g, |
| 447 | static LLVMValueRef gen_arithmetic_bin_op(CodeGen *g, AstNode *source_node, |
| 427 | 448 | LLVMValueRef val1, LLVMValueRef val2, |
| 428 | 449 | TypeTableEntry *op1_type, TypeTableEntry *op2_type, |
| 429 | | AstNode *node) |
| 450 | BinOpType bin_op) |
| 430 | 451 | { |
| 431 | | assert(node->type == NodeTypeBinOpExpr); |
| 432 | 452 | assert(op1_type == op2_type); |
| 433 | 453 | |
| 434 | | switch (node->data.bin_op_expr.bin_op) { |
| 454 | switch (bin_op) { |
| 435 | 455 | case BinOpTypeBinOr: |
| 436 | 456 | case BinOpTypeAssignBitOr: |
| 437 | | add_debug_source_node(g, node); |
| 457 | add_debug_source_node(g, source_node); |
| 438 | 458 | return LLVMBuildOr(g->builder, val1, val2, ""); |
| 439 | 459 | case BinOpTypeBinXor: |
| 440 | 460 | case BinOpTypeAssignBitXor: |
| 441 | | add_debug_source_node(g, node); |
| 461 | add_debug_source_node(g, source_node); |
| 442 | 462 | return LLVMBuildXor(g->builder, val1, val2, ""); |
| 443 | 463 | case BinOpTypeBinAnd: |
| 444 | 464 | case BinOpTypeAssignBitAnd: |
| 445 | | add_debug_source_node(g, node); |
| 465 | add_debug_source_node(g, source_node); |
| 446 | 466 | return LLVMBuildAnd(g->builder, val1, val2, ""); |
| 447 | 467 | case BinOpTypeBitShiftLeft: |
| 448 | 468 | case BinOpTypeAssignBitShiftLeft: |
| 449 | | add_debug_source_node(g, node); |
| 469 | add_debug_source_node(g, source_node); |
| 450 | 470 | return LLVMBuildShl(g->builder, val1, val2, ""); |
| 451 | 471 | case BinOpTypeBitShiftRight: |
| 452 | 472 | case BinOpTypeAssignBitShiftRight: |
| 453 | | add_debug_source_node(g, node); |
| 473 | add_debug_source_node(g, source_node); |
| 454 | 474 | if (op1_type->id == TypeTableEntryIdInt) { |
| 455 | 475 | return LLVMBuildAShr(g->builder, val1, val2, ""); |
| 456 | 476 | } else { |
| ... | ... | @@ -458,7 +478,7 @@ static LLVMValueRef gen_arithmetic_bin_op(CodeGen *g, |
| 458 | 478 | } |
| 459 | 479 | case BinOpTypeAdd: |
| 460 | 480 | case BinOpTypeAssignPlus: |
| 461 | | add_debug_source_node(g, node); |
| 481 | add_debug_source_node(g, source_node); |
| 462 | 482 | if (op1_type->id == TypeTableEntryIdFloat) { |
| 463 | 483 | return LLVMBuildFAdd(g->builder, val1, val2, ""); |
| 464 | 484 | } else { |
| ... | ... | @@ -466,7 +486,7 @@ static LLVMValueRef gen_arithmetic_bin_op(CodeGen *g, |
| 466 | 486 | } |
| 467 | 487 | case BinOpTypeSub: |
| 468 | 488 | case BinOpTypeAssignMinus: |
| 469 | | add_debug_source_node(g, node); |
| 489 | add_debug_source_node(g, source_node); |
| 470 | 490 | if (op1_type->id == TypeTableEntryIdFloat) { |
| 471 | 491 | return LLVMBuildFSub(g->builder, val1, val2, ""); |
| 472 | 492 | } else { |
| ... | ... | @@ -474,7 +494,7 @@ static LLVMValueRef gen_arithmetic_bin_op(CodeGen *g, |
| 474 | 494 | } |
| 475 | 495 | case BinOpTypeMult: |
| 476 | 496 | case BinOpTypeAssignTimes: |
| 477 | | add_debug_source_node(g, node); |
| 497 | add_debug_source_node(g, source_node); |
| 478 | 498 | if (op1_type->id == TypeTableEntryIdFloat) { |
| 479 | 499 | return LLVMBuildFMul(g->builder, val1, val2, ""); |
| 480 | 500 | } else { |
| ... | ... | @@ -482,7 +502,7 @@ static LLVMValueRef gen_arithmetic_bin_op(CodeGen *g, |
| 482 | 502 | } |
| 483 | 503 | case BinOpTypeDiv: |
| 484 | 504 | case BinOpTypeAssignDiv: |
| 485 | | add_debug_source_node(g, node); |
| 505 | add_debug_source_node(g, source_node); |
| 486 | 506 | if (op1_type->id == TypeTableEntryIdFloat) { |
| 487 | 507 | return LLVMBuildFDiv(g->builder, val1, val2, ""); |
| 488 | 508 | } else { |
| ... | ... | @@ -495,7 +515,7 @@ static LLVMValueRef gen_arithmetic_bin_op(CodeGen *g, |
| 495 | 515 | } |
| 496 | 516 | case BinOpTypeMod: |
| 497 | 517 | case BinOpTypeAssignMod: |
| 498 | | add_debug_source_node(g, node); |
| 518 | add_debug_source_node(g, source_node); |
| 499 | 519 | if (op1_type->id == TypeTableEntryIdFloat) { |
| 500 | 520 | return LLVMBuildFRem(g->builder, val1, val2, ""); |
| 501 | 521 | } else { |
| ... | ... | @@ -530,7 +550,7 @@ static LLVMValueRef gen_arithmetic_bin_op_expr(CodeGen *g, AstNode *node) { |
| 530 | 550 | |
| 531 | 551 | TypeTableEntry *op1_type = get_expr_type(node->data.bin_op_expr.op1); |
| 532 | 552 | TypeTableEntry *op2_type = get_expr_type(node->data.bin_op_expr.op2); |
| 533 | | return gen_arithmetic_bin_op(g, val1, val2, op1_type, op2_type, node); |
| 553 | return gen_arithmetic_bin_op(g, node, val1, val2, op1_type, op2_type, node->data.bin_op_expr.bin_op); |
| 534 | 554 | |
| 535 | 555 | } |
| 536 | 556 | |
| ... | ... | @@ -660,7 +680,7 @@ static LLVMValueRef gen_bool_or_expr(CodeGen *g, AstNode *expr_node) { |
| 660 | 680 | static LLVMValueRef gen_struct_memcpy(CodeGen *g, AstNode *source_node, LLVMValueRef src, LLVMValueRef dest, |
| 661 | 681 | TypeTableEntry *type_entry) |
| 662 | 682 | { |
| 663 | | assert(type_entry->id == TypeTableEntryIdStruct); |
| 683 | assert(type_entry->id == TypeTableEntryIdStruct || type_entry->id == TypeTableEntryIdMaybe); |
| 664 | 684 | |
| 665 | 685 | LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0); |
| 666 | 686 | |
| ... | ... | @@ -679,6 +699,30 @@ static LLVMValueRef gen_struct_memcpy(CodeGen *g, AstNode *source_node, LLVMValu |
| 679 | 699 | return LLVMBuildCall(g->builder, g->memcpy_fn_val, params, 5, ""); |
| 680 | 700 | } |
| 681 | 701 | |
| 702 | static LLVMValueRef gen_assign_raw(CodeGen *g, AstNode *source_node, BinOpType bin_op, |
| 703 | LLVMValueRef target_ref, LLVMValueRef value, |
| 704 | TypeTableEntry *op1_type, TypeTableEntry *op2_type) |
| 705 | { |
| 706 | if (op1_type->id == TypeTableEntryIdStruct) { |
| 707 | assert(op2_type->id == TypeTableEntryIdStruct); |
| 708 | assert(op1_type == op2_type); |
| 709 | assert(bin_op == BinOpTypeAssign); |
| 710 | |
| 711 | return gen_struct_memcpy(g, source_node, value, target_ref, op1_type); |
| 712 | } |
| 713 | |
| 714 | if (bin_op != BinOpTypeAssign) { |
| 715 | assert(source_node->type == NodeTypeBinOpExpr); |
| 716 | add_debug_source_node(g, source_node->data.bin_op_expr.op1); |
| 717 | LLVMValueRef left_value = LLVMBuildLoad(g->builder, target_ref, ""); |
| 718 | |
| 719 | value = gen_arithmetic_bin_op(g, source_node, left_value, value, op1_type, op2_type, bin_op); |
| 720 | } |
| 721 | |
| 722 | add_debug_source_node(g, source_node); |
| 723 | return LLVMBuildStore(g->builder, value, target_ref); |
| 724 | } |
| 725 | |
| 682 | 726 | static LLVMValueRef gen_assign_expr(CodeGen *g, AstNode *node) { |
| 683 | 727 | assert(node->type == NodeTypeBinOpExpr); |
| 684 | 728 | |
| ... | ... | @@ -692,23 +736,7 @@ static LLVMValueRef gen_assign_expr(CodeGen *g, AstNode *node) { |
| 692 | 736 | |
| 693 | 737 | LLVMValueRef value = gen_expr(g, node->data.bin_op_expr.op2); |
| 694 | 738 | |
| 695 | | if (op1_type->id == TypeTableEntryIdStruct) { |
| 696 | | assert(op2_type->id == TypeTableEntryIdStruct); |
| 697 | | assert(op1_type == op2_type); |
| 698 | | assert(node->data.bin_op_expr.bin_op == BinOpTypeAssign); |
| 699 | | |
| 700 | | return gen_struct_memcpy(g, node, value, target_ref, op1_type); |
| 701 | | } |
| 702 | | |
| 703 | | if (node->data.bin_op_expr.bin_op != BinOpTypeAssign) { |
| 704 | | add_debug_source_node(g, node->data.bin_op_expr.op1); |
| 705 | | LLVMValueRef left_value = LLVMBuildLoad(g->builder, target_ref, ""); |
| 706 | | |
| 707 | | value = gen_arithmetic_bin_op(g, left_value, value, op1_type, op2_type, node); |
| 708 | | } |
| 709 | | |
| 710 | | add_debug_source_node(g, node); |
| 711 | | return LLVMBuildStore(g->builder, value, target_ref); |
| 739 | return gen_assign_raw(g, node, node->data.bin_op_expr.bin_op, target_ref, value, op1_type, op2_type); |
| 712 | 740 | } |
| 713 | 741 | |
| 714 | 742 | static LLVMValueRef gen_bin_op_expr(CodeGen *g, AstNode *node) { |
| ... | ... | @@ -769,18 +797,14 @@ static LLVMValueRef gen_return_expr(CodeGen *g, AstNode *node) { |
| 769 | 797 | } |
| 770 | 798 | } |
| 771 | 799 | |
| 772 | | static LLVMValueRef gen_if_bool_expr(CodeGen *g, AstNode *node) { |
| 773 | | assert(node->type == NodeTypeIfBoolExpr); |
| 774 | | assert(node->data.if_bool_expr.condition); |
| 775 | | assert(node->data.if_bool_expr.then_block); |
| 776 | | |
| 777 | | LLVMValueRef cond_value = gen_expr(g, node->data.if_bool_expr.condition); |
| 778 | | |
| 779 | | TypeTableEntry *then_type = get_expr_type(node->data.if_bool_expr.then_block); |
| 800 | static LLVMValueRef gen_if_bool_expr_raw(CodeGen *g, AstNode *source_node, LLVMValueRef cond_value, |
| 801 | AstNode *then_node, AstNode *else_node) |
| 802 | { |
| 803 | TypeTableEntry *then_type = get_expr_type(then_node); |
| 780 | 804 | bool use_expr_value = (then_type->id != TypeTableEntryIdUnreachable && |
| 781 | 805 | then_type->id != TypeTableEntryIdVoid); |
| 782 | 806 | |
| 783 | | if (node->data.if_bool_expr.else_node) { |
| 807 | if (else_node) { |
| 784 | 808 | LLVMBasicBlockRef then_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "Then"); |
| 785 | 809 | LLVMBasicBlockRef else_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "Else"); |
| 786 | 810 | LLVMBasicBlockRef endif_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "EndIf"); |
| ... | ... | @@ -788,13 +812,13 @@ static LLVMValueRef gen_if_bool_expr(CodeGen *g, AstNode *node) { |
| 788 | 812 | LLVMBuildCondBr(g->builder, cond_value, then_block, else_block); |
| 789 | 813 | |
| 790 | 814 | LLVMPositionBuilderAtEnd(g->builder, then_block); |
| 791 | | LLVMValueRef then_expr_result = gen_expr(g, node->data.if_bool_expr.then_block); |
| 792 | | if (get_expr_type(node->data.if_bool_expr.then_block)->id != TypeTableEntryIdUnreachable) |
| 815 | LLVMValueRef then_expr_result = gen_expr(g, then_node); |
| 816 | if (get_expr_type(then_node)->id != TypeTableEntryIdUnreachable) |
| 793 | 817 | LLVMBuildBr(g->builder, endif_block); |
| 794 | 818 | |
| 795 | 819 | LLVMPositionBuilderAtEnd(g->builder, else_block); |
| 796 | | LLVMValueRef else_expr_result = gen_expr(g, node->data.if_bool_expr.else_node); |
| 797 | | if (get_expr_type(node->data.if_bool_expr.else_node)->id != TypeTableEntryIdUnreachable) |
| 820 | LLVMValueRef else_expr_result = gen_expr(g, else_node); |
| 821 | if (get_expr_type(else_node)->id != TypeTableEntryIdUnreachable) |
| 798 | 822 | LLVMBuildBr(g->builder, endif_block); |
| 799 | 823 | |
| 800 | 824 | LLVMPositionBuilderAtEnd(g->builder, endif_block); |
| ... | ... | @@ -818,17 +842,49 @@ static LLVMValueRef gen_if_bool_expr(CodeGen *g, AstNode *node) { |
| 818 | 842 | LLVMBuildCondBr(g->builder, cond_value, then_block, endif_block); |
| 819 | 843 | |
| 820 | 844 | LLVMPositionBuilderAtEnd(g->builder, then_block); |
| 821 | | gen_expr(g, node->data.if_bool_expr.then_block); |
| 822 | | if (get_expr_type(node->data.if_bool_expr.then_block)->id != TypeTableEntryIdUnreachable) |
| 845 | gen_expr(g, then_node); |
| 846 | if (get_expr_type(then_node)->id != TypeTableEntryIdUnreachable) |
| 823 | 847 | LLVMBuildBr(g->builder, endif_block); |
| 824 | 848 | |
| 825 | 849 | LLVMPositionBuilderAtEnd(g->builder, endif_block); |
| 826 | 850 | return nullptr; |
| 827 | 851 | } |
| 828 | 852 | |
| 853 | static LLVMValueRef gen_if_bool_expr(CodeGen *g, AstNode *node) { |
| 854 | assert(node->type == NodeTypeIfBoolExpr); |
| 855 | assert(node->data.if_bool_expr.condition); |
| 856 | assert(node->data.if_bool_expr.then_block); |
| 857 | |
| 858 | LLVMValueRef cond_value = gen_expr(g, node->data.if_bool_expr.condition); |
| 859 | |
| 860 | return gen_if_bool_expr_raw(g, node, cond_value, |
| 861 | node->data.if_bool_expr.then_block, |
| 862 | node->data.if_bool_expr.else_node); |
| 863 | } |
| 864 | |
| 829 | 865 | static LLVMValueRef gen_if_var_expr(CodeGen *g, AstNode *node) { |
| 830 | 866 | assert(node->type == NodeTypeIfVarExpr); |
| 831 | | zig_panic("TODO gen_if_var_expr"); |
| 867 | assert(node->data.if_var_expr.var_decl.expr); |
| 868 | |
| 869 | BlockContext *old_block_context = g->cur_block_context; |
| 870 | BlockContext *new_block_context = node->codegen_node->data.if_var_node.block_context; |
| 871 | |
| 872 | LLVMValueRef init_val; |
| 873 | gen_var_decl_raw(g, node, &node->data.if_var_expr.var_decl, new_block_context, true, &init_val); |
| 874 | |
| 875 | // test if value is the maybe state |
| 876 | add_debug_source_node(g, node); |
| 877 | LLVMValueRef maybe_field_ptr = LLVMBuildStructGEP(g->builder, init_val, 1, ""); |
| 878 | LLVMValueRef cond_value = LLVMBuildLoad(g->builder, maybe_field_ptr, ""); |
| 879 | |
| 880 | g->cur_block_context = new_block_context; |
| 881 | |
| 882 | LLVMValueRef return_value = gen_if_bool_expr_raw(g, node, cond_value, |
| 883 | node->data.if_var_expr.then_block, |
| 884 | node->data.if_var_expr.else_node); |
| 885 | |
| 886 | g->cur_block_context = old_block_context; |
| 887 | return return_value; |
| 832 | 888 | } |
| 833 | 889 | |
| 834 | 890 | static LLVMValueRef gen_block(CodeGen *g, AstNode *block_node, TypeTableEntry *implicit_return_type) { |
| ... | ... | @@ -1058,6 +1114,55 @@ static LLVMValueRef gen_continue(CodeGen *g, AstNode *node) { |
| 1058 | 1114 | return LLVMBuildBr(g->builder, dest_block); |
| 1059 | 1115 | } |
| 1060 | 1116 | |
| 1117 | static LLVMValueRef gen_var_decl_raw(CodeGen *g, AstNode *source_node, AstNodeVariableDeclaration *var_decl, |
| 1118 | BlockContext *block_context, bool unwrap_maybe, LLVMValueRef *init_value) |
| 1119 | { |
| 1120 | VariableTableEntry *variable = find_variable(block_context, &var_decl->symbol); |
| 1121 | |
| 1122 | assert(variable); |
| 1123 | assert(variable->is_ptr); |
| 1124 | |
| 1125 | if (var_decl->expr) { |
| 1126 | *init_value = gen_expr(g, var_decl->expr); |
| 1127 | } else { |
| 1128 | *init_value = LLVMConstNull(variable->type->type_ref); |
| 1129 | } |
| 1130 | if (variable->type->id == TypeTableEntryIdVoid) { |
| 1131 | return nullptr; |
| 1132 | } else { |
| 1133 | LLVMValueRef store_instr; |
| 1134 | LLVMValueRef value; |
| 1135 | if (unwrap_maybe) { |
| 1136 | assert(var_decl->expr); |
| 1137 | add_debug_source_node(g, source_node); |
| 1138 | LLVMValueRef maybe_field_ptr = LLVMBuildStructGEP(g->builder, *init_value, 0, ""); |
| 1139 | // TODO if it's a struct we might not want to load the pointer |
| 1140 | value = LLVMBuildLoad(g->builder, maybe_field_ptr, ""); |
| 1141 | } else { |
| 1142 | value = *init_value; |
| 1143 | } |
| 1144 | if ((variable->type->id == TypeTableEntryIdStruct || variable->type->id == TypeTableEntryIdMaybe) && |
| 1145 | var_decl->expr) |
| 1146 | { |
| 1147 | store_instr = gen_struct_memcpy(g, source_node, value, variable->value_ref, variable->type); |
| 1148 | } else { |
| 1149 | add_debug_source_node(g, source_node); |
| 1150 | store_instr = LLVMBuildStore(g->builder, value, variable->value_ref); |
| 1151 | } |
| 1152 | |
| 1153 | LLVMZigDILocation *debug_loc = LLVMZigGetDebugLoc(source_node->line + 1, source_node->column + 1, |
| 1154 | g->cur_block_context->di_scope); |
| 1155 | LLVMZigInsertDeclare(g->dbuilder, variable->value_ref, variable->di_loc_var, debug_loc, store_instr); |
| 1156 | return nullptr; |
| 1157 | } |
| 1158 | } |
| 1159 | |
| 1160 | static LLVMValueRef gen_var_decl_expr(CodeGen *g, AstNode *node) { |
| 1161 | LLVMValueRef init_val; |
| 1162 | return gen_var_decl_raw(g, node, &node->data.variable_declaration, |
| 1163 | node->codegen_node->expr_node.block_context, false, &init_val); |
| 1164 | } |
| 1165 | |
| 1061 | 1166 | static LLVMValueRef gen_expr_no_cast(CodeGen *g, AstNode *node) { |
| 1062 | 1167 | switch (node->type) { |
| 1063 | 1168 | case NodeTypeBinOpExpr: |
| ... | ... | @@ -1065,38 +1170,7 @@ static LLVMValueRef gen_expr_no_cast(CodeGen *g, AstNode *node) { |
| 1065 | 1170 | case NodeTypeReturnExpr: |
| 1066 | 1171 | return gen_return_expr(g, node); |
| 1067 | 1172 | case NodeTypeVariableDeclaration: |
| 1068 | | { |
| 1069 | | VariableTableEntry *variable = find_variable( |
| 1070 | | node->codegen_node->expr_node.block_context, |
| 1071 | | &node->data.variable_declaration.symbol); |
| 1072 | | |
| 1073 | | assert(variable); |
| 1074 | | assert(variable->is_ptr); |
| 1075 | | |
| 1076 | | LLVMValueRef value; |
| 1077 | | if (node->data.variable_declaration.expr) { |
| 1078 | | value = gen_expr(g, node->data.variable_declaration.expr); |
| 1079 | | } else { |
| 1080 | | value = LLVMConstNull(variable->type->type_ref); |
| 1081 | | } |
| 1082 | | if (variable->type->id == TypeTableEntryIdVoid) { |
| 1083 | | return nullptr; |
| 1084 | | } else { |
| 1085 | | LLVMValueRef store_instr; |
| 1086 | | if (variable->type->id == TypeTableEntryIdStruct && node->data.variable_declaration.expr) { |
| 1087 | | store_instr = gen_struct_memcpy(g, node, value, variable->value_ref, variable->type); |
| 1088 | | } else { |
| 1089 | | add_debug_source_node(g, node); |
| 1090 | | store_instr = LLVMBuildStore(g->builder, value, variable->value_ref); |
| 1091 | | } |
| 1092 | | |
| 1093 | | LLVMZigDILocation *debug_loc = LLVMZigGetDebugLoc(node->line + 1, node->column + 1, |
| 1094 | | g->cur_block_context->di_scope); |
| 1095 | | LLVMZigInsertDeclare(g->dbuilder, variable->value_ref, variable->di_loc_var, |
| 1096 | | debug_loc, store_instr); |
| 1097 | | return nullptr; |
| 1098 | | } |
| 1099 | | } |
| 1173 | return gen_var_decl_expr(g, node); |
| 1100 | 1174 | case NodeTypeCastExpr: |
| 1101 | 1175 | return gen_cast_expr(g, node); |
| 1102 | 1176 | case NodeTypePrefixOpExpr: |
| ... | ... | @@ -1174,7 +1248,9 @@ static LLVMValueRef gen_expr_no_cast(CodeGen *g, AstNode *node) { |
| 1174 | 1248 | assert(variable->value_ref); |
| 1175 | 1249 | if (variable->type->id == TypeTableEntryIdArray) { |
| 1176 | 1250 | return variable->value_ref; |
| 1177 | | } else if (variable->type->id == TypeTableEntryIdStruct) { |
| 1251 | } else if (variable->type->id == TypeTableEntryIdStruct || |
| 1252 | variable->type->id == TypeTableEntryIdMaybe) |
| 1253 | { |
| 1178 | 1254 | return variable->value_ref; |
| 1179 | 1255 | } else { |
| 1180 | 1256 | add_debug_source_node(g, node); |
| ... | ... | @@ -1225,6 +1301,12 @@ static LLVMValueRef gen_expr_no_cast(CodeGen *g, AstNode *node) { |
| 1225 | 1301 | zig_unreachable(); |
| 1226 | 1302 | } |
| 1227 | 1303 | |
| 1304 | static LLVMValueRef gen_cast_node(CodeGen *g, AstNode *node, LLVMValueRef val, TypeTableEntry *before_type, |
| 1305 | CastNode *cast_node) |
| 1306 | { |
| 1307 | return cast_node->after_type ? gen_bare_cast(g, node, val, before_type, cast_node->after_type, cast_node) : val; |
| 1308 | } |
| 1309 | |
| 1228 | 1310 | static LLVMValueRef gen_expr(CodeGen *g, AstNode *node) { |
| 1229 | 1311 | LLVMValueRef val = gen_expr_no_cast(g, node); |
| 1230 | 1312 | |
| ... | ... | @@ -1234,11 +1316,17 @@ static LLVMValueRef gen_expr(CodeGen *g, AstNode *node) { |
| 1234 | 1316 | |
| 1235 | 1317 | assert(node->codegen_node); |
| 1236 | 1318 | |
| 1237 | | TypeTableEntry *actual_type = node->codegen_node->expr_node.type_entry; |
| 1238 | | TypeTableEntry *cast_type = node->codegen_node->expr_node.implicit_cast.type; |
| 1319 | { |
| 1320 | TypeTableEntry *before_type = node->codegen_node->expr_node.type_entry; |
| 1321 | val = gen_cast_node(g, node, val, before_type, &node->codegen_node->expr_node.implicit_cast); |
| 1322 | } |
| 1323 | |
| 1324 | { |
| 1325 | TypeTableEntry *before_type = node->codegen_node->expr_node.implicit_cast.after_type; |
| 1326 | val = gen_cast_node(g, node, val, before_type, &node->codegen_node->expr_node.implicit_maybe_cast); |
| 1327 | } |
| 1239 | 1328 | |
| 1240 | | return cast_type ? gen_bare_cast(g, node, val, actual_type, cast_type, |
| 1241 | | &node->codegen_node->expr_node.implicit_cast) : val; |
| 1329 | return val; |
| 1242 | 1330 | } |
| 1243 | 1331 | |
| 1244 | 1332 | static void build_label_blocks(CodeGen *g, AstNode *block_node) { |
| ... | ... | @@ -1460,7 +1548,7 @@ static void do_code_gen(CodeGen *g) { |
| 1460 | 1548 | for (int cea_i = 0; cea_i < block_context->cast_expr_alloca_list.length; cea_i += 1) { |
| 1461 | 1549 | CastNode *cast_node = block_context->cast_expr_alloca_list.at(cea_i); |
| 1462 | 1550 | add_debug_source_node(g, cast_node->source_node); |
| 1463 | | cast_node->ptr = LLVMBuildAlloca(g->builder, cast_node->type->type_ref, ""); |
| 1551 | cast_node->ptr = LLVMBuildAlloca(g->builder, cast_node->after_type->type_ref, ""); |
| 1464 | 1552 | } |
| 1465 | 1553 | |
| 1466 | 1554 | // allocate structs which are struct value expressions |