| ... | @@ -65,6 +65,11 @@ void codegen_set_libc_path(CodeGen *g, Buf *libc_path) { | ... | @@ -65,6 +65,11 @@ void codegen_set_libc_path(CodeGen *g, Buf *libc_path) { |
| 65 | static LLVMValueRef gen_expr(CodeGen *g, AstNode *expr_node); | 65 | static LLVMValueRef gen_expr(CodeGen *g, AstNode *expr_node); |
| 66 | static LLVMValueRef gen_lvalue(CodeGen *g, AstNode *expr_node, AstNode *node, TypeTableEntry **out_type_entry); | 66 | static LLVMValueRef gen_lvalue(CodeGen *g, AstNode *expr_node, AstNode *node, TypeTableEntry **out_type_entry); |
| 67 | static LLVMValueRef gen_field_access_expr(CodeGen *g, AstNode *node, bool is_lvalue); | 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 | static TypeTableEntry *get_type_for_type_node(CodeGen *g, AstNode *type_node) { | 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,7 +137,7 @@ static LLVMValueRef find_or_create_string(CodeGen *g, Buf *str, bool c) { |
| 132 | } | 137 | } |
| 133 | | 138 | |
| 134 | static TypeTableEntry *get_expr_type(AstNode *node) { | 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 | return cast_type ? cast_type : node->codegen_node->expr_node.type_entry; | 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,6 +372,22 @@ static LLVMValueRef gen_bare_cast(CodeGen *g, AstNode *node, LLVMValueRef expr_v |
| 367 | switch (cast_node->op) { | 372 | switch (cast_node->op) { |
| 368 | case CastOpNothing: | 373 | case CastOpNothing: |
| 369 | return expr_val; | 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 | case CastOpPtrToInt: | 391 | case CastOpPtrToInt: |
| 371 | return LLVMBuildPtrToInt(g->builder, expr_val, wanted_type->type_ref, ""); | 392 | return LLVMBuildPtrToInt(g->builder, expr_val, wanted_type->type_ref, ""); |
| 372 | case CastOpIntWidenOrShorten: | 393 | case CastOpIntWidenOrShorten: |
| ... | @@ -423,34 +444,33 @@ static LLVMValueRef gen_cast_expr(CodeGen *g, AstNode *node) { | ... | @@ -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 | LLVMValueRef val1, LLVMValueRef val2, | 448 | LLVMValueRef val1, LLVMValueRef val2, |
| 428 | TypeTableEntry *op1_type, TypeTableEntry *op2_type, | 449 | TypeTableEntry *op1_type, TypeTableEntry *op2_type, |
| 429 | AstNode *node) | 450 | BinOpType bin_op) |
| 430 | { | 451 | { |
| 431 | assert(node->type == NodeTypeBinOpExpr); | | |
| 432 | assert(op1_type == op2_type); | 452 | assert(op1_type == op2_type); |
| 433 | | 453 | |
| 434 | switch (node->data.bin_op_expr.bin_op) { | 454 | switch (bin_op) { |
| 435 | case BinOpTypeBinOr: | 455 | case BinOpTypeBinOr: |
| 436 | case BinOpTypeAssignBitOr: | 456 | case BinOpTypeAssignBitOr: |
| 437 | add_debug_source_node(g, node); | 457 | add_debug_source_node(g, source_node); |
| 438 | return LLVMBuildOr(g->builder, val1, val2, ""); | 458 | return LLVMBuildOr(g->builder, val1, val2, ""); |
| 439 | case BinOpTypeBinXor: | 459 | case BinOpTypeBinXor: |
| 440 | case BinOpTypeAssignBitXor: | 460 | case BinOpTypeAssignBitXor: |
| 441 | add_debug_source_node(g, node); | 461 | add_debug_source_node(g, source_node); |
| 442 | return LLVMBuildXor(g->builder, val1, val2, ""); | 462 | return LLVMBuildXor(g->builder, val1, val2, ""); |
| 443 | case BinOpTypeBinAnd: | 463 | case BinOpTypeBinAnd: |
| 444 | case BinOpTypeAssignBitAnd: | 464 | case BinOpTypeAssignBitAnd: |
| 445 | add_debug_source_node(g, node); | 465 | add_debug_source_node(g, source_node); |
| 446 | return LLVMBuildAnd(g->builder, val1, val2, ""); | 466 | return LLVMBuildAnd(g->builder, val1, val2, ""); |
| 447 | case BinOpTypeBitShiftLeft: | 467 | case BinOpTypeBitShiftLeft: |
| 448 | case BinOpTypeAssignBitShiftLeft: | 468 | case BinOpTypeAssignBitShiftLeft: |
| 449 | add_debug_source_node(g, node); | 469 | add_debug_source_node(g, source_node); |
| 450 | return LLVMBuildShl(g->builder, val1, val2, ""); | 470 | return LLVMBuildShl(g->builder, val1, val2, ""); |
| 451 | case BinOpTypeBitShiftRight: | 471 | case BinOpTypeBitShiftRight: |
| 452 | case BinOpTypeAssignBitShiftRight: | 472 | case BinOpTypeAssignBitShiftRight: |
| 453 | add_debug_source_node(g, node); | 473 | add_debug_source_node(g, source_node); |
| 454 | if (op1_type->id == TypeTableEntryIdInt) { | 474 | if (op1_type->id == TypeTableEntryIdInt) { |
| 455 | return LLVMBuildAShr(g->builder, val1, val2, ""); | 475 | return LLVMBuildAShr(g->builder, val1, val2, ""); |
| 456 | } else { | 476 | } else { |
| ... | @@ -458,7 +478,7 @@ static LLVMValueRef gen_arithmetic_bin_op(CodeGen *g, | ... | @@ -458,7 +478,7 @@ static LLVMValueRef gen_arithmetic_bin_op(CodeGen *g, |
| 458 | } | 478 | } |
| 459 | case BinOpTypeAdd: | 479 | case BinOpTypeAdd: |
| 460 | case BinOpTypeAssignPlus: | 480 | case BinOpTypeAssignPlus: |
| 461 | add_debug_source_node(g, node); | 481 | add_debug_source_node(g, source_node); |
| 462 | if (op1_type->id == TypeTableEntryIdFloat) { | 482 | if (op1_type->id == TypeTableEntryIdFloat) { |
| 463 | return LLVMBuildFAdd(g->builder, val1, val2, ""); | 483 | return LLVMBuildFAdd(g->builder, val1, val2, ""); |
| 464 | } else { | 484 | } else { |
| ... | @@ -466,7 +486,7 @@ static LLVMValueRef gen_arithmetic_bin_op(CodeGen *g, | ... | @@ -466,7 +486,7 @@ static LLVMValueRef gen_arithmetic_bin_op(CodeGen *g, |
| 466 | } | 486 | } |
| 467 | case BinOpTypeSub: | 487 | case BinOpTypeSub: |
| 468 | case BinOpTypeAssignMinus: | 488 | case BinOpTypeAssignMinus: |
| 469 | add_debug_source_node(g, node); | 489 | add_debug_source_node(g, source_node); |
| 470 | if (op1_type->id == TypeTableEntryIdFloat) { | 490 | if (op1_type->id == TypeTableEntryIdFloat) { |
| 471 | return LLVMBuildFSub(g->builder, val1, val2, ""); | 491 | return LLVMBuildFSub(g->builder, val1, val2, ""); |
| 472 | } else { | 492 | } else { |
| ... | @@ -474,7 +494,7 @@ static LLVMValueRef gen_arithmetic_bin_op(CodeGen *g, | ... | @@ -474,7 +494,7 @@ static LLVMValueRef gen_arithmetic_bin_op(CodeGen *g, |
| 474 | } | 494 | } |
| 475 | case BinOpTypeMult: | 495 | case BinOpTypeMult: |
| 476 | case BinOpTypeAssignTimes: | 496 | case BinOpTypeAssignTimes: |
| 477 | add_debug_source_node(g, node); | 497 | add_debug_source_node(g, source_node); |
| 478 | if (op1_type->id == TypeTableEntryIdFloat) { | 498 | if (op1_type->id == TypeTableEntryIdFloat) { |
| 479 | return LLVMBuildFMul(g->builder, val1, val2, ""); | 499 | return LLVMBuildFMul(g->builder, val1, val2, ""); |
| 480 | } else { | 500 | } else { |
| ... | @@ -482,7 +502,7 @@ static LLVMValueRef gen_arithmetic_bin_op(CodeGen *g, | ... | @@ -482,7 +502,7 @@ static LLVMValueRef gen_arithmetic_bin_op(CodeGen *g, |
| 482 | } | 502 | } |
| 483 | case BinOpTypeDiv: | 503 | case BinOpTypeDiv: |
| 484 | case BinOpTypeAssignDiv: | 504 | case BinOpTypeAssignDiv: |
| 485 | add_debug_source_node(g, node); | 505 | add_debug_source_node(g, source_node); |
| 486 | if (op1_type->id == TypeTableEntryIdFloat) { | 506 | if (op1_type->id == TypeTableEntryIdFloat) { |
| 487 | return LLVMBuildFDiv(g->builder, val1, val2, ""); | 507 | return LLVMBuildFDiv(g->builder, val1, val2, ""); |
| 488 | } else { | 508 | } else { |
| ... | @@ -495,7 +515,7 @@ static LLVMValueRef gen_arithmetic_bin_op(CodeGen *g, | ... | @@ -495,7 +515,7 @@ static LLVMValueRef gen_arithmetic_bin_op(CodeGen *g, |
| 495 | } | 515 | } |
| 496 | case BinOpTypeMod: | 516 | case BinOpTypeMod: |
| 497 | case BinOpTypeAssignMod: | 517 | case BinOpTypeAssignMod: |
| 498 | add_debug_source_node(g, node); | 518 | add_debug_source_node(g, source_node); |
| 499 | if (op1_type->id == TypeTableEntryIdFloat) { | 519 | if (op1_type->id == TypeTableEntryIdFloat) { |
| 500 | return LLVMBuildFRem(g->builder, val1, val2, ""); | 520 | return LLVMBuildFRem(g->builder, val1, val2, ""); |
| 501 | } else { | 521 | } else { |
| ... | @@ -530,7 +550,7 @@ static LLVMValueRef gen_arithmetic_bin_op_expr(CodeGen *g, AstNode *node) { | ... | @@ -530,7 +550,7 @@ static LLVMValueRef gen_arithmetic_bin_op_expr(CodeGen *g, AstNode *node) { |
| 530 | | 550 | |
| 531 | TypeTableEntry *op1_type = get_expr_type(node->data.bin_op_expr.op1); | 551 | TypeTableEntry *op1_type = get_expr_type(node->data.bin_op_expr.op1); |
| 532 | TypeTableEntry *op2_type = get_expr_type(node->data.bin_op_expr.op2); | 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,7 +680,7 @@ static LLVMValueRef gen_bool_or_expr(CodeGen *g, AstNode *expr_node) { |
| 660 | static LLVMValueRef gen_struct_memcpy(CodeGen *g, AstNode *source_node, LLVMValueRef src, LLVMValueRef dest, | 680 | static LLVMValueRef gen_struct_memcpy(CodeGen *g, AstNode *source_node, LLVMValueRef src, LLVMValueRef dest, |
| 661 | TypeTableEntry *type_entry) | 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 | LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0); | 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,6 +699,30 @@ static LLVMValueRef gen_struct_memcpy(CodeGen *g, AstNode *source_node, LLVMValu |
| 679 | return LLVMBuildCall(g->builder, g->memcpy_fn_val, params, 5, ""); | 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 | static LLVMValueRef gen_assign_expr(CodeGen *g, AstNode *node) { | 726 | static LLVMValueRef gen_assign_expr(CodeGen *g, AstNode *node) { |
| 683 | assert(node->type == NodeTypeBinOpExpr); | 727 | assert(node->type == NodeTypeBinOpExpr); |
| 684 | | 728 | |
| ... | @@ -692,23 +736,7 @@ static LLVMValueRef gen_assign_expr(CodeGen *g, AstNode *node) { | ... | @@ -692,23 +736,7 @@ static LLVMValueRef gen_assign_expr(CodeGen *g, AstNode *node) { |
| 692 | | 736 | |
| 693 | LLVMValueRef value = gen_expr(g, node->data.bin_op_expr.op2); | 737 | LLVMValueRef value = gen_expr(g, node->data.bin_op_expr.op2); |
| 694 | | 738 | |
| 695 | if (op1_type->id == TypeTableEntryIdStruct) { | 739 | return gen_assign_raw(g, node, node->data.bin_op_expr.bin_op, target_ref, value, op1_type, op2_type); |
| 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); | | |
| 712 | } | 740 | } |
| 713 | | 741 | |
| 714 | static LLVMValueRef gen_bin_op_expr(CodeGen *g, AstNode *node) { | 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,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) { | 800 | static LLVMValueRef gen_if_bool_expr_raw(CodeGen *g, AstNode *source_node, LLVMValueRef cond_value, |
| 773 | assert(node->type == NodeTypeIfBoolExpr); | 801 | AstNode *then_node, AstNode *else_node) |
| 774 | assert(node->data.if_bool_expr.condition); | 802 | { |
| 775 | assert(node->data.if_bool_expr.then_block); | 803 | TypeTableEntry *then_type = get_expr_type(then_node); |
| 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); | | |
| 780 | bool use_expr_value = (then_type->id != TypeTableEntryIdUnreachable && | 804 | bool use_expr_value = (then_type->id != TypeTableEntryIdUnreachable && |
| 781 | then_type->id != TypeTableEntryIdVoid); | 805 | then_type->id != TypeTableEntryIdVoid); |
| 782 | | 806 | |
| 783 | if (node->data.if_bool_expr.else_node) { | 807 | if (else_node) { |
| 784 | LLVMBasicBlockRef then_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "Then"); | 808 | LLVMBasicBlockRef then_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "Then"); |
| 785 | LLVMBasicBlockRef else_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "Else"); | 809 | LLVMBasicBlockRef else_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "Else"); |
| 786 | LLVMBasicBlockRef endif_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "EndIf"); | 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,13 +812,13 @@ static LLVMValueRef gen_if_bool_expr(CodeGen *g, AstNode *node) { |
| 788 | LLVMBuildCondBr(g->builder, cond_value, then_block, else_block); | 812 | LLVMBuildCondBr(g->builder, cond_value, then_block, else_block); |
| 789 | | 813 | |
| 790 | LLVMPositionBuilderAtEnd(g->builder, then_block); | 814 | LLVMPositionBuilderAtEnd(g->builder, then_block); |
| 791 | LLVMValueRef then_expr_result = gen_expr(g, node->data.if_bool_expr.then_block); | 815 | LLVMValueRef then_expr_result = gen_expr(g, then_node); |
| 792 | if (get_expr_type(node->data.if_bool_expr.then_block)->id != TypeTableEntryIdUnreachable) | 816 | if (get_expr_type(then_node)->id != TypeTableEntryIdUnreachable) |
| 793 | LLVMBuildBr(g->builder, endif_block); | 817 | LLVMBuildBr(g->builder, endif_block); |
| 794 | | 818 | |
| 795 | LLVMPositionBuilderAtEnd(g->builder, else_block); | 819 | LLVMPositionBuilderAtEnd(g->builder, else_block); |
| 796 | LLVMValueRef else_expr_result = gen_expr(g, node->data.if_bool_expr.else_node); | 820 | LLVMValueRef else_expr_result = gen_expr(g, else_node); |
| 797 | if (get_expr_type(node->data.if_bool_expr.else_node)->id != TypeTableEntryIdUnreachable) | 821 | if (get_expr_type(else_node)->id != TypeTableEntryIdUnreachable) |
| 798 | LLVMBuildBr(g->builder, endif_block); | 822 | LLVMBuildBr(g->builder, endif_block); |
| 799 | | 823 | |
| 800 | LLVMPositionBuilderAtEnd(g->builder, endif_block); | 824 | LLVMPositionBuilderAtEnd(g->builder, endif_block); |
| ... | @@ -818,17 +842,49 @@ static LLVMValueRef gen_if_bool_expr(CodeGen *g, AstNode *node) { | ... | @@ -818,17 +842,49 @@ static LLVMValueRef gen_if_bool_expr(CodeGen *g, AstNode *node) { |
| 818 | LLVMBuildCondBr(g->builder, cond_value, then_block, endif_block); | 842 | LLVMBuildCondBr(g->builder, cond_value, then_block, endif_block); |
| 819 | | 843 | |
| 820 | LLVMPositionBuilderAtEnd(g->builder, then_block); | 844 | LLVMPositionBuilderAtEnd(g->builder, then_block); |
| 821 | gen_expr(g, node->data.if_bool_expr.then_block); | 845 | gen_expr(g, then_node); |
| 822 | if (get_expr_type(node->data.if_bool_expr.then_block)->id != TypeTableEntryIdUnreachable) | 846 | if (get_expr_type(then_node)->id != TypeTableEntryIdUnreachable) |
| 823 | LLVMBuildBr(g->builder, endif_block); | 847 | LLVMBuildBr(g->builder, endif_block); |
| 824 | | 848 | |
| 825 | LLVMPositionBuilderAtEnd(g->builder, endif_block); | 849 | LLVMPositionBuilderAtEnd(g->builder, endif_block); |
| 826 | return nullptr; | 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 | static LLVMValueRef gen_if_var_expr(CodeGen *g, AstNode *node) { | 865 | static LLVMValueRef gen_if_var_expr(CodeGen *g, AstNode *node) { |
| 830 | assert(node->type == NodeTypeIfVarExpr); | 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 | static LLVMValueRef gen_block(CodeGen *g, AstNode *block_node, TypeTableEntry *implicit_return_type) { | 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,6 +1114,55 @@ static LLVMValueRef gen_continue(CodeGen *g, AstNode *node) { |
| 1058 | return LLVMBuildBr(g->builder, dest_block); | 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 | static LLVMValueRef gen_expr_no_cast(CodeGen *g, AstNode *node) { | 1166 | static LLVMValueRef gen_expr_no_cast(CodeGen *g, AstNode *node) { |
| 1062 | switch (node->type) { | 1167 | switch (node->type) { |
| 1063 | case NodeTypeBinOpExpr: | 1168 | case NodeTypeBinOpExpr: |
| ... | @@ -1065,38 +1170,7 @@ static LLVMValueRef gen_expr_no_cast(CodeGen *g, AstNode *node) { | ... | @@ -1065,38 +1170,7 @@ static LLVMValueRef gen_expr_no_cast(CodeGen *g, AstNode *node) { |
| 1065 | case NodeTypeReturnExpr: | 1170 | case NodeTypeReturnExpr: |
| 1066 | return gen_return_expr(g, node); | 1171 | return gen_return_expr(g, node); |
| 1067 | case NodeTypeVariableDeclaration: | 1172 | case NodeTypeVariableDeclaration: |
| 1068 | { | 1173 | return gen_var_decl_expr(g, node); |
| 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 | } | | |
| 1100 | case NodeTypeCastExpr: | 1174 | case NodeTypeCastExpr: |
| 1101 | return gen_cast_expr(g, node); | 1175 | return gen_cast_expr(g, node); |
| 1102 | case NodeTypePrefixOpExpr: | 1176 | case NodeTypePrefixOpExpr: |
| ... | @@ -1174,7 +1248,9 @@ static LLVMValueRef gen_expr_no_cast(CodeGen *g, AstNode *node) { | ... | @@ -1174,7 +1248,9 @@ static LLVMValueRef gen_expr_no_cast(CodeGen *g, AstNode *node) { |
| 1174 | assert(variable->value_ref); | 1248 | assert(variable->value_ref); |
| 1175 | if (variable->type->id == TypeTableEntryIdArray) { | 1249 | if (variable->type->id == TypeTableEntryIdArray) { |
| 1176 | return variable->value_ref; | 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 | return variable->value_ref; | 1254 | return variable->value_ref; |
| 1179 | } else { | 1255 | } else { |
| 1180 | add_debug_source_node(g, node); | 1256 | add_debug_source_node(g, node); |
| ... | @@ -1225,6 +1301,12 @@ static LLVMValueRef gen_expr_no_cast(CodeGen *g, AstNode *node) { | ... | @@ -1225,6 +1301,12 @@ static LLVMValueRef gen_expr_no_cast(CodeGen *g, AstNode *node) { |
| 1225 | zig_unreachable(); | 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 | static LLVMValueRef gen_expr(CodeGen *g, AstNode *node) { | 1310 | static LLVMValueRef gen_expr(CodeGen *g, AstNode *node) { |
| 1229 | LLVMValueRef val = gen_expr_no_cast(g, node); | 1311 | LLVMValueRef val = gen_expr_no_cast(g, node); |
| 1230 | | 1312 | |
| ... | @@ -1234,11 +1316,17 @@ static LLVMValueRef gen_expr(CodeGen *g, AstNode *node) { | ... | @@ -1234,11 +1316,17 @@ static LLVMValueRef gen_expr(CodeGen *g, AstNode *node) { |
| 1234 | | 1316 | |
| 1235 | assert(node->codegen_node); | 1317 | assert(node->codegen_node); |
| 1236 | | 1318 | |
| 1237 | TypeTableEntry *actual_type = node->codegen_node->expr_node.type_entry; | 1319 | { |
| 1238 | TypeTableEntry *cast_type = node->codegen_node->expr_node.implicit_cast.type; | 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, | 1329 | return val; |
| 1241 | &node->codegen_node->expr_node.implicit_cast) : val; | | |
| 1242 | } | 1330 | } |
| 1243 | | 1331 | |
| 1244 | static void build_label_blocks(CodeGen *g, AstNode *block_node) { | 1332 | static void build_label_blocks(CodeGen *g, AstNode *block_node) { |
| ... | @@ -1460,7 +1548,7 @@ static void do_code_gen(CodeGen *g) { | ... | @@ -1460,7 +1548,7 @@ static void do_code_gen(CodeGen *g) { |
| 1460 | for (int cea_i = 0; cea_i < block_context->cast_expr_alloca_list.length; cea_i += 1) { | 1548 | for (int cea_i = 0; cea_i < block_context->cast_expr_alloca_list.length; cea_i += 1) { |
| 1461 | CastNode *cast_node = block_context->cast_expr_alloca_list.at(cea_i); | 1549 | CastNode *cast_node = block_context->cast_expr_alloca_list.at(cea_i); |
| 1462 | add_debug_source_node(g, cast_node->source_node); | 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 | // allocate structs which are struct value expressions | 1554 | // allocate structs which are struct value expressions |