| ... | @@ -49,6 +49,10 @@ ConstExprValue *const_ptr_pointee(ConstExprValue *const_val) { | ... | @@ -49,6 +49,10 @@ ConstExprValue *const_ptr_pointee(ConstExprValue *const_val) { |
| 49 | } | 49 | } |
| 50 | } | 50 | } |
| 51 | | 51 | |
| | 52 | static bool ir_should_inline(IrBuilder *irb) { |
| | 53 | return irb->exec->is_inline; |
| | 54 | } |
| | 55 | |
| 52 | static void ir_instruction_append(IrBasicBlock *basic_block, IrInstruction *instruction) { | 56 | static void ir_instruction_append(IrBasicBlock *basic_block, IrInstruction *instruction) { |
| 53 | assert(basic_block); | 57 | assert(basic_block); |
| 54 | assert(instruction); | 58 | assert(instruction); |
| ... | @@ -160,6 +164,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionStructFieldPtr * | ... | @@ -160,6 +164,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionStructFieldPtr * |
| 160 | return IrInstructionIdStructFieldPtr; | 164 | return IrInstructionIdStructFieldPtr; |
| 161 | } | 165 | } |
| 162 | | 166 | |
| | 167 | static constexpr IrInstructionId ir_instruction_id(IrInstructionEnumFieldPtr *) { |
| | 168 | return IrInstructionIdEnumFieldPtr; |
| | 169 | } |
| | 170 | |
| 163 | static constexpr IrInstructionId ir_instruction_id(IrInstructionElemPtr *) { | 171 | static constexpr IrInstructionId ir_instruction_id(IrInstructionElemPtr *) { |
| 164 | return IrInstructionIdElemPtr; | 172 | return IrInstructionIdElemPtr; |
| 165 | } | 173 | } |
| ... | @@ -276,6 +284,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionRef *) { | ... | @@ -276,6 +284,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionRef *) { |
| 276 | return IrInstructionIdRef; | 284 | return IrInstructionIdRef; |
| 277 | } | 285 | } |
| 278 | | 286 | |
| | 287 | static constexpr IrInstructionId ir_instruction_id(IrInstructionStructInit *) { |
| | 288 | return IrInstructionIdStructInit; |
| | 289 | } |
| | 290 | |
| 279 | template<typename T> | 291 | template<typename T> |
| 280 | static T *ir_create_instruction(IrExecutable *exec, AstNode *source_node) { | 292 | static T *ir_create_instruction(IrExecutable *exec, AstNode *source_node) { |
| 281 | T *special_instruction = allocate<T>(1); | 293 | T *special_instruction = allocate<T>(1); |
| ... | @@ -293,15 +305,14 @@ static T *ir_build_instruction(IrBuilder *irb, AstNode *source_node) { | ... | @@ -293,15 +305,14 @@ static T *ir_build_instruction(IrBuilder *irb, AstNode *source_node) { |
| 293 | return special_instruction; | 305 | return special_instruction; |
| 294 | } | 306 | } |
| 295 | | 307 | |
| 296 | static IrInstruction *ir_build_cast(IrBuilder *irb, AstNode *source_node, IrInstruction *dest_type, | 308 | static IrInstruction *ir_build_cast(IrBuilder *irb, AstNode *source_node, TypeTableEntry *dest_type, |
| 297 | IrInstruction *value, CastOp cast_op) | 309 | IrInstruction *value, CastOp cast_op) |
| 298 | { | 310 | { |
| 299 | IrInstructionCast *cast_instruction = ir_build_instruction<IrInstructionCast>(irb, source_node); | 311 | IrInstructionCast *cast_instruction = ir_build_instruction<IrInstructionCast>(irb, source_node); |
| 300 | cast_instruction->dest_type = dest_type; | 312 | cast_instruction->dest_type = dest_type; |
| 301 | cast_instruction->value = value; | 313 | cast_instruction->value = value; |
| 302 | cast_instruction->cast_op = cast_op; | 314 | cast_instruction->cast_op = cast_op; |
| 303 | | 315 | |
| 304 | ir_ref_instruction(dest_type); | | |
| 305 | ir_ref_instruction(value); | 316 | ir_ref_instruction(value); |
| 306 | | 317 | |
| 307 | return &cast_instruction->base; | 318 | return &cast_instruction->base; |
| ... | @@ -353,10 +364,14 @@ static IrInstruction *ir_build_return_from(IrBuilder *irb, IrInstruction *old_in | ... | @@ -353,10 +364,14 @@ static IrInstruction *ir_build_return_from(IrBuilder *irb, IrInstruction *old_in |
| 353 | return new_instruction; | 364 | return new_instruction; |
| 354 | } | 365 | } |
| 355 | | 366 | |
| 356 | static IrInstruction *ir_create_const(IrBuilder *irb, AstNode *source_node, TypeTableEntry *type_entry) { | 367 | static IrInstruction *ir_create_const(IrBuilder *irb, AstNode *source_node, |
| | 368 | TypeTableEntry *type_entry, bool depends_on_compile_var) |
| | 369 | { |
| | 370 | assert(type_entry); |
| 357 | IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(irb->exec, source_node); | 371 | IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(irb->exec, source_node); |
| 358 | const_instruction->base.type_entry = type_entry; | 372 | const_instruction->base.type_entry = type_entry; |
| 359 | const_instruction->base.static_value.special = ConstValSpecialStatic; | 373 | const_instruction->base.static_value.special = ConstValSpecialStatic; |
| | 374 | const_instruction->base.static_value.depends_on_compile_var = depends_on_compile_var; |
| 360 | return &const_instruction->base; | 375 | return &const_instruction->base; |
| 361 | } | 376 | } |
| 362 | | 377 | |
| ... | @@ -452,6 +467,18 @@ static IrInstruction *ir_build_const_bool(IrBuilder *irb, AstNode *source_node, | ... | @@ -452,6 +467,18 @@ static IrInstruction *ir_build_const_bool(IrBuilder *irb, AstNode *source_node, |
| 452 | return &const_instruction->base; | 467 | return &const_instruction->base; |
| 453 | } | 468 | } |
| 454 | | 469 | |
| | 470 | static IrInstruction *ir_build_const_bound_fn(IrBuilder *irb, AstNode *source_node, |
| | 471 | FnTableEntry *fn_entry, IrInstruction *first_arg, bool depends_on_compile_var) |
| | 472 | { |
| | 473 | IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, source_node); |
| | 474 | const_instruction->base.type_entry = get_bound_fn_type(irb->codegen, fn_entry); |
| | 475 | const_instruction->base.static_value.special = ConstValSpecialStatic; |
| | 476 | const_instruction->base.static_value.depends_on_compile_var = depends_on_compile_var; |
| | 477 | const_instruction->base.static_value.data.x_bound_fn.fn = fn_entry; |
| | 478 | const_instruction->base.static_value.data.x_bound_fn.first_arg = first_arg; |
| | 479 | return &const_instruction->base; |
| | 480 | } |
| | 481 | |
| 455 | static IrInstruction *ir_build_const_str_lit(IrBuilder *irb, AstNode *source_node, Buf *str) { | 482 | static IrInstruction *ir_build_const_str_lit(IrBuilder *irb, AstNode *source_node, Buf *str) { |
| 456 | IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, source_node); | 483 | IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, source_node); |
| 457 | TypeTableEntry *u8_type = irb->codegen->builtin_types.entry_u8; | 484 | TypeTableEntry *u8_type = irb->codegen->builtin_types.entry_u8; |
| ... | @@ -595,26 +622,48 @@ static IrInstruction *ir_build_struct_field_ptr_from(IrBuilder *irb, IrInstructi | ... | @@ -595,26 +622,48 @@ static IrInstruction *ir_build_struct_field_ptr_from(IrBuilder *irb, IrInstructi |
| 595 | return new_instruction; | 622 | return new_instruction; |
| 596 | } | 623 | } |
| 597 | | 624 | |
| | 625 | static IrInstruction *ir_build_enum_field_ptr(IrBuilder *irb, AstNode *source_node, |
| | 626 | IrInstruction *enum_ptr, TypeEnumField *field) |
| | 627 | { |
| | 628 | IrInstructionEnumFieldPtr *instruction = ir_build_instruction<IrInstructionEnumFieldPtr>(irb, source_node); |
| | 629 | instruction->enum_ptr = enum_ptr; |
| | 630 | instruction->field = field; |
| | 631 | |
| | 632 | ir_ref_instruction(enum_ptr); |
| | 633 | |
| | 634 | return &instruction->base; |
| | 635 | } |
| | 636 | |
| | 637 | static IrInstruction *ir_build_enum_field_ptr_from(IrBuilder *irb, IrInstruction *old_instruction, |
| | 638 | IrInstruction *enum_ptr, TypeEnumField *type_enum_field) |
| | 639 | { |
| | 640 | IrInstruction *new_instruction = ir_build_enum_field_ptr(irb, old_instruction->source_node, |
| | 641 | enum_ptr, type_enum_field); |
| | 642 | ir_link_new_instruction(new_instruction, old_instruction); |
| | 643 | return new_instruction; |
| | 644 | } |
| | 645 | |
| 598 | static IrInstruction *ir_build_call(IrBuilder *irb, AstNode *source_node, | 646 | static IrInstruction *ir_build_call(IrBuilder *irb, AstNode *source_node, |
| 599 | IrInstruction *fn, size_t arg_count, IrInstruction **args) | 647 | FnTableEntry *fn_entry, IrInstruction *fn_ref, size_t arg_count, IrInstruction **args) |
| 600 | { | 648 | { |
| 601 | IrInstructionCall *call_instruction = ir_build_instruction<IrInstructionCall>(irb, source_node); | 649 | IrInstructionCall *call_instruction = ir_build_instruction<IrInstructionCall>(irb, source_node); |
| 602 | call_instruction->fn = fn; | 650 | call_instruction->fn_entry = fn_entry; |
| | 651 | call_instruction->fn_ref = fn_ref; |
| 603 | call_instruction->arg_count = arg_count; | 652 | call_instruction->arg_count = arg_count; |
| 604 | call_instruction->args = args; | 653 | call_instruction->args = args; |
| 605 | | 654 | |
| 606 | ir_ref_instruction(fn); | 655 | if (fn_ref) |
| 607 | for (size_t i = 0; i < arg_count; i += 1) { | 656 | ir_ref_instruction(fn_ref); |
| | 657 | for (size_t i = 0; i < arg_count; i += 1) |
| 608 | ir_ref_instruction(args[i]); | 658 | ir_ref_instruction(args[i]); |
| 609 | } | | |
| 610 | | 659 | |
| 611 | return &call_instruction->base; | 660 | return &call_instruction->base; |
| 612 | } | 661 | } |
| 613 | | 662 | |
| 614 | static IrInstruction *ir_build_call_from(IrBuilder *irb, IrInstruction *old_instruction, | 663 | static IrInstruction *ir_build_call_from(IrBuilder *irb, IrInstruction *old_instruction, |
| 615 | IrInstruction *fn, size_t arg_count, IrInstruction **args) | 664 | FnTableEntry *fn_entry, IrInstruction *fn_ref, size_t arg_count, IrInstruction **args) |
| 616 | { | 665 | { |
| 617 | IrInstruction *new_instruction = ir_build_call(irb, old_instruction->source_node, fn, arg_count, args); | 666 | IrInstruction *new_instruction = ir_build_call(irb, old_instruction->source_node, fn_entry, fn_ref, arg_count, args); |
| 618 | ir_link_new_instruction(new_instruction, old_instruction); | 667 | ir_link_new_instruction(new_instruction, old_instruction); |
| 619 | return new_instruction; | 668 | return new_instruction; |
| 620 | } | 669 | } |
| ... | @@ -706,24 +755,55 @@ static IrInstruction *ir_build_container_init_list(IrBuilder *irb, AstNode *sour | ... | @@ -706,24 +755,55 @@ static IrInstruction *ir_build_container_init_list(IrBuilder *irb, AstNode *sour |
| 706 | return &container_init_list_instruction->base; | 755 | return &container_init_list_instruction->base; |
| 707 | } | 756 | } |
| 708 | | 757 | |
| | 758 | static IrInstruction *ir_build_container_init_list_from(IrBuilder *irb, IrInstruction *old_instruction, |
| | 759 | IrInstruction *container_type, size_t item_count, IrInstruction **items) |
| | 760 | { |
| | 761 | IrInstruction *new_instruction = ir_build_container_init_list(irb, old_instruction->source_node, |
| | 762 | container_type, item_count, items); |
| | 763 | ir_link_new_instruction(new_instruction, old_instruction); |
| | 764 | return new_instruction; |
| | 765 | } |
| | 766 | |
| 709 | static IrInstruction *ir_build_container_init_fields(IrBuilder *irb, AstNode *source_node, | 767 | static IrInstruction *ir_build_container_init_fields(IrBuilder *irb, AstNode *source_node, |
| 710 | IrInstruction *container_type, size_t field_count, Buf **field_names, IrInstruction **field_values) | 768 | IrInstruction *container_type, size_t field_count, IrInstructionContainerInitFieldsField *fields) |
| 711 | { | 769 | { |
| 712 | IrInstructionContainerInitFields *container_init_fields_instruction = | 770 | IrInstructionContainerInitFields *container_init_fields_instruction = |
| 713 | ir_build_instruction<IrInstructionContainerInitFields>(irb, source_node); | 771 | ir_build_instruction<IrInstructionContainerInitFields>(irb, source_node); |
| 714 | container_init_fields_instruction->container_type = container_type; | 772 | container_init_fields_instruction->container_type = container_type; |
| 715 | container_init_fields_instruction->field_count = field_count; | 773 | container_init_fields_instruction->field_count = field_count; |
| 716 | container_init_fields_instruction->field_names = field_names; | 774 | container_init_fields_instruction->fields = fields; |
| 717 | container_init_fields_instruction->field_values = field_values; | | |
| 718 | | 775 | |
| 719 | ir_ref_instruction(container_type); | 776 | ir_ref_instruction(container_type); |
| 720 | for (size_t i = 0; i < field_count; i += 1) { | 777 | for (size_t i = 0; i < field_count; i += 1) { |
| 721 | ir_ref_instruction(field_values[i]); | 778 | ir_ref_instruction(fields[i].value); |
| 722 | } | 779 | } |
| 723 | | 780 | |
| 724 | return &container_init_fields_instruction->base; | 781 | return &container_init_fields_instruction->base; |
| 725 | } | 782 | } |
| 726 | | 783 | |
| | 784 | static IrInstruction *ir_build_struct_init(IrBuilder *irb, AstNode *source_node, |
| | 785 | TypeTableEntry *struct_type, size_t field_count, IrInstructionStructInitField *fields) |
| | 786 | { |
| | 787 | IrInstructionStructInit *struct_init_instruction = ir_build_instruction<IrInstructionStructInit>(irb, source_node); |
| | 788 | struct_init_instruction->struct_type = struct_type; |
| | 789 | struct_init_instruction->field_count = field_count; |
| | 790 | struct_init_instruction->fields = fields; |
| | 791 | |
| | 792 | for (size_t i = 0; i < field_count; i += 1) |
| | 793 | ir_ref_instruction(fields[i].value); |
| | 794 | |
| | 795 | return &struct_init_instruction->base; |
| | 796 | } |
| | 797 | |
| | 798 | static IrInstruction *ir_build_struct_init_from(IrBuilder *irb, IrInstruction *old_instruction, |
| | 799 | TypeTableEntry *struct_type, size_t field_count, IrInstructionStructInitField *fields) |
| | 800 | { |
| | 801 | IrInstruction *new_instruction = ir_build_struct_init(irb, old_instruction->source_node, |
| | 802 | struct_type, field_count, fields); |
| | 803 | ir_link_new_instruction(new_instruction, old_instruction); |
| | 804 | return new_instruction; |
| | 805 | } |
| | 806 | |
| 727 | static IrInstruction *ir_build_unreachable(IrBuilder *irb, AstNode *source_node) { | 807 | static IrInstruction *ir_build_unreachable(IrBuilder *irb, AstNode *source_node) { |
| 728 | IrInstructionUnreachable *unreachable_instruction = | 808 | IrInstructionUnreachable *unreachable_instruction = |
| 729 | ir_build_instruction<IrInstructionUnreachable>(irb, source_node); | 809 | ir_build_instruction<IrInstructionUnreachable>(irb, source_node); |
| ... | @@ -1442,7 +1522,7 @@ static IrInstruction *ir_gen_decl_ref(IrBuilder *irb, AstNode *source_node, AstN | ... | @@ -1442,7 +1522,7 @@ static IrInstruction *ir_gen_decl_ref(IrBuilder *irb, AstNode *source_node, AstN |
| 1442 | ref_instruction = ir_build_const_fn(irb, source_node, fn_entry); | 1522 | ref_instruction = ir_build_const_fn(irb, source_node, fn_entry); |
| 1443 | } | 1523 | } |
| 1444 | if (lval != LValPurposeNone) | 1524 | if (lval != LValPurposeNone) |
| 1445 | return ir_build_un_op(irb, source_node, IrUnOpAddressOf, ref_instruction); | 1525 | return ir_build_ref(irb, source_node, ref_instruction); |
| 1446 | else | 1526 | else |
| 1447 | return ref_instruction; | 1527 | return ref_instruction; |
| 1448 | } else if (decl_node->type == NodeTypeContainerDecl) { | 1528 | } else if (decl_node->type == NodeTypeContainerDecl) { |
| ... | @@ -1455,14 +1535,14 @@ static IrInstruction *ir_gen_decl_ref(IrBuilder *irb, AstNode *source_node, AstN | ... | @@ -1455,14 +1535,14 @@ static IrInstruction *ir_gen_decl_ref(IrBuilder *irb, AstNode *source_node, AstN |
| 1455 | ref_instruction = ir_build_const_type(irb, source_node, decl_node->data.struct_decl.type_entry); | 1535 | ref_instruction = ir_build_const_type(irb, source_node, decl_node->data.struct_decl.type_entry); |
| 1456 | } | 1536 | } |
| 1457 | if (lval != LValPurposeNone) | 1537 | if (lval != LValPurposeNone) |
| 1458 | return ir_build_un_op(irb, source_node, IrUnOpAddressOf, ref_instruction); | 1538 | return ir_build_ref(irb, source_node, ref_instruction); |
| 1459 | else | 1539 | else |
| 1460 | return ref_instruction; | 1540 | return ref_instruction; |
| 1461 | } else if (decl_node->type == NodeTypeTypeDecl) { | 1541 | } else if (decl_node->type == NodeTypeTypeDecl) { |
| 1462 | TypeTableEntry *child_type = decl_node->data.type_decl.child_type_entry; | 1542 | TypeTableEntry *child_type = decl_node->data.type_decl.child_type_entry; |
| 1463 | IrInstruction *ref_instruction = ir_build_const_type(irb, source_node, child_type); | 1543 | IrInstruction *ref_instruction = ir_build_const_type(irb, source_node, child_type); |
| 1464 | if (lval != LValPurposeNone) | 1544 | if (lval != LValPurposeNone) |
| 1465 | return ir_build_un_op(irb, source_node, IrUnOpAddressOf, ref_instruction); | 1545 | return ir_build_ref(irb, source_node, ref_instruction); |
| 1466 | else | 1546 | else |
| 1467 | return ref_instruction; | 1547 | return ref_instruction; |
| 1468 | } else { | 1548 | } else { |
| ... | @@ -1712,7 +1792,6 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, AstNode *node) { | ... | @@ -1712,7 +1792,6 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, AstNode *node) { |
| 1712 | case BuiltinFnIdDivExact: | 1792 | case BuiltinFnIdDivExact: |
| 1713 | case BuiltinFnIdTruncate: | 1793 | case BuiltinFnIdTruncate: |
| 1714 | case BuiltinFnIdIntType: | 1794 | case BuiltinFnIdIntType: |
| 1715 | case BuiltinFnIdSetFnStaticEval: | | |
| 1716 | case BuiltinFnIdSetFnNoInline: | 1795 | case BuiltinFnIdSetFnNoInline: |
| 1717 | zig_panic("TODO IR gen more builtin functions"); | 1796 | zig_panic("TODO IR gen more builtin functions"); |
| 1718 | } | 1797 | } |
| ... | @@ -1726,9 +1805,9 @@ static IrInstruction *ir_gen_fn_call(IrBuilder *irb, AstNode *node) { | ... | @@ -1726,9 +1805,9 @@ static IrInstruction *ir_gen_fn_call(IrBuilder *irb, AstNode *node) { |
| 1726 | return ir_gen_builtin_fn_call(irb, node); | 1805 | return ir_gen_builtin_fn_call(irb, node); |
| 1727 | | 1806 | |
| 1728 | AstNode *fn_ref_node = node->data.fn_call_expr.fn_ref_expr; | 1807 | AstNode *fn_ref_node = node->data.fn_call_expr.fn_ref_expr; |
| 1729 | IrInstruction *fn = ir_gen_node(irb, fn_ref_node, node->block_context); | 1808 | IrInstruction *fn_ref = ir_gen_node(irb, fn_ref_node, node->block_context); |
| 1730 | if (fn == irb->codegen->invalid_instruction) | 1809 | if (fn_ref == irb->codegen->invalid_instruction) |
| 1731 | return fn; | 1810 | return fn_ref; |
| 1732 | | 1811 | |
| 1733 | size_t arg_count = node->data.fn_call_expr.params.length; | 1812 | size_t arg_count = node->data.fn_call_expr.params.length; |
| 1734 | IrInstruction **args = allocate<IrInstruction*>(arg_count); | 1813 | IrInstruction **args = allocate<IrInstruction*>(arg_count); |
| ... | @@ -1737,7 +1816,7 @@ static IrInstruction *ir_gen_fn_call(IrBuilder *irb, AstNode *node) { | ... | @@ -1737,7 +1816,7 @@ static IrInstruction *ir_gen_fn_call(IrBuilder *irb, AstNode *node) { |
| 1737 | args[i] = ir_gen_node(irb, arg_node, node->block_context); | 1816 | args[i] = ir_gen_node(irb, arg_node, node->block_context); |
| 1738 | } | 1817 | } |
| 1739 | | 1818 | |
| 1740 | return ir_build_call(irb, node, fn, arg_count, args); | 1819 | return ir_build_call(irb, node, nullptr, fn_ref, arg_count, args); |
| 1741 | } | 1820 | } |
| 1742 | | 1821 | |
| 1743 | static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, AstNode *node) { | 1822 | static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, AstNode *node) { |
| ... | @@ -1754,7 +1833,7 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, AstNode *node) { | ... | @@ -1754,7 +1833,7 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, AstNode *node) { |
| 1754 | IrBasicBlock *else_block = ir_build_basic_block(irb, "Else"); | 1833 | IrBasicBlock *else_block = ir_build_basic_block(irb, "Else"); |
| 1755 | IrBasicBlock *endif_block = ir_build_basic_block(irb, "EndIf"); | 1834 | IrBasicBlock *endif_block = ir_build_basic_block(irb, "EndIf"); |
| 1756 | | 1835 | |
| 1757 | bool is_inline = (node->block_context->fn_entry == nullptr); | 1836 | bool is_inline = ir_should_inline(irb) || node->data.if_bool_expr.is_inline; |
| 1758 | ir_build_cond_br(irb, condition->source_node, condition, then_block, else_block, is_inline); | 1837 | ir_build_cond_br(irb, condition->source_node, condition, then_block, else_block, is_inline); |
| 1759 | | 1838 | |
| 1760 | ir_set_cursor_at_end(irb, then_block); | 1839 | ir_set_cursor_at_end(irb, then_block); |
| ... | @@ -1865,8 +1944,7 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, AstNode *node) | ... | @@ -1865,8 +1944,7 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, AstNode *node) |
| 1865 | | 1944 | |
| 1866 | if (kind == ContainerInitKindStruct) { | 1945 | if (kind == ContainerInitKindStruct) { |
| 1867 | size_t field_count = container_init_expr->entries.length; | 1946 | size_t field_count = container_init_expr->entries.length; |
| 1868 | IrInstruction **values = allocate<IrInstruction *>(field_count); | 1947 | IrInstructionContainerInitFieldsField *fields = allocate<IrInstructionContainerInitFieldsField>(field_count); |
| 1869 | Buf **names = allocate<Buf *>(field_count); | | |
| 1870 | for (size_t i = 0; i < field_count; i += 1) { | 1948 | for (size_t i = 0; i < field_count; i += 1) { |
| 1871 | AstNode *entry_node = container_init_expr->entries.at(i); | 1949 | AstNode *entry_node = container_init_expr->entries.at(i); |
| 1872 | assert(entry_node->type == NodeTypeStructValueField); | 1950 | assert(entry_node->type == NodeTypeStructValueField); |
| ... | @@ -1877,10 +1955,11 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, AstNode *node) | ... | @@ -1877,10 +1955,11 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, AstNode *node) |
| 1877 | if (expr_value == irb->codegen->invalid_instruction) | 1955 | if (expr_value == irb->codegen->invalid_instruction) |
| 1878 | return expr_value; | 1956 | return expr_value; |
| 1879 | | 1957 | |
| 1880 | names[i] = name; | 1958 | fields[i].name = name; |
| 1881 | values[i] = expr_value; | 1959 | fields[i].value = expr_value; |
| | 1960 | fields[i].source_node = entry_node; |
| 1882 | } | 1961 | } |
| 1883 | return ir_build_container_init_fields(irb, node, container_type, field_count, names, values); | 1962 | return ir_build_container_init_fields(irb, node, container_type, field_count, fields); |
| 1884 | } else if (kind == ContainerInitKindArray) { | 1963 | } else if (kind == ContainerInitKindArray) { |
| 1885 | size_t item_count = container_init_expr->entries.length; | 1964 | size_t item_count = container_init_expr->entries.length; |
| 1886 | IrInstruction **values = allocate<IrInstruction *>(item_count); | 1965 | IrInstruction **values = allocate<IrInstruction *>(item_count); |
| ... | @@ -1919,7 +1998,7 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, AstNode *node) { | ... | @@ -1919,7 +1998,7 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, AstNode *node) { |
| 1919 | bool is_shadowable = false; | 1998 | bool is_shadowable = false; |
| 1920 | bool is_const = variable_declaration->is_const; | 1999 | bool is_const = variable_declaration->is_const; |
| 1921 | bool is_extern = variable_declaration->is_extern; | 2000 | bool is_extern = variable_declaration->is_extern; |
| 1922 | bool is_inline = variable_declaration->is_inline; | 2001 | bool is_inline = ir_should_inline(irb) || variable_declaration->is_inline; |
| 1923 | VariableTableEntry *var = ir_add_local_var(irb, node, node->block_context, | 2002 | VariableTableEntry *var = ir_add_local_var(irb, node, node->block_context, |
| 1924 | variable_declaration->symbol, is_const, is_const, is_shadowable, is_inline); | 2003 | variable_declaration->symbol, is_const, is_const, is_shadowable, is_inline); |
| 1925 | | 2004 | |
| ... | @@ -1943,7 +2022,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, AstNode *node) { | ... | @@ -1943,7 +2022,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, AstNode *node) { |
| 1943 | ir_build_basic_block(irb, "WhileContinue") : cond_block; | 2022 | ir_build_basic_block(irb, "WhileContinue") : cond_block; |
| 1944 | IrBasicBlock *end_block = ir_build_basic_block(irb, "WhileEnd"); | 2023 | IrBasicBlock *end_block = ir_build_basic_block(irb, "WhileEnd"); |
| 1945 | | 2024 | |
| 1946 | bool is_inline = node->data.while_expr.is_inline; | 2025 | bool is_inline = ir_should_inline(irb) || node->data.while_expr.is_inline; |
| 1947 | ir_build_br(irb, node, cond_block, is_inline); | 2026 | ir_build_br(irb, node, cond_block, is_inline); |
| 1948 | | 2027 | |
| 1949 | if (continue_expr_node) { | 2028 | if (continue_expr_node) { |
| ... | @@ -1998,7 +2077,7 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, AstNode *node) { | ... | @@ -1998,7 +2077,7 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, AstNode *node) { |
| 1998 | } else { | 2077 | } else { |
| 1999 | elem_var_type = ir_build_ptr_type_child(irb, elem_node, pointer_type); | 2078 | elem_var_type = ir_build_ptr_type_child(irb, elem_node, pointer_type); |
| 2000 | } | 2079 | } |
| 2001 | bool is_inline = node->data.for_expr.is_inline; | 2080 | bool is_inline = ir_should_inline(irb) || node->data.for_expr.is_inline; |
| 2002 | | 2081 | |
| 2003 | BlockContext *child_scope = new_block_context(node, parent_scope); | 2082 | BlockContext *child_scope = new_block_context(node, parent_scope); |
| 2004 | child_scope->parent_loop_node = node; | 2083 | child_scope->parent_loop_node = node; |
| ... | @@ -2219,7 +2298,7 @@ static IrInstruction *ir_gen_if_var_expr(IrBuilder *irb, AstNode *node) { | ... | @@ -2219,7 +2298,7 @@ static IrInstruction *ir_gen_if_var_expr(IrBuilder *irb, AstNode *node) { |
| 2219 | IrBasicBlock *else_block = ir_build_basic_block(irb, "MaybeElse"); | 2298 | IrBasicBlock *else_block = ir_build_basic_block(irb, "MaybeElse"); |
| 2220 | IrBasicBlock *endif_block = ir_build_basic_block(irb, "MaybeEndIf"); | 2299 | IrBasicBlock *endif_block = ir_build_basic_block(irb, "MaybeEndIf"); |
| 2221 | | 2300 | |
| 2222 | bool is_inline = (node->block_context->fn_entry == nullptr); | 2301 | bool is_inline = ir_should_inline(irb) || node->data.if_var_expr.is_inline; |
| 2223 | ir_build_cond_br(irb, node, is_nonnull_value, then_block, else_block, is_inline); | 2302 | ir_build_cond_br(irb, node, is_nonnull_value, then_block, else_block, is_inline); |
| 2224 | | 2303 | |
| 2225 | ir_set_cursor_at_end(irb, then_block); | 2304 | ir_set_cursor_at_end(irb, then_block); |
| ... | @@ -2322,7 +2401,7 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, AstNode *node) { | ... | @@ -2322,7 +2401,7 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, AstNode *node) { |
| 2322 | | 2401 | |
| 2323 | size_t prong_count = node->data.switch_expr.prongs.length; | 2402 | size_t prong_count = node->data.switch_expr.prongs.length; |
| 2324 | ZigList<IrInstructionSwitchBrCase> cases = {0}; | 2403 | ZigList<IrInstructionSwitchBrCase> cases = {0}; |
| 2325 | bool is_inline = node->data.switch_expr.is_inline || (node->block_context->fn_entry == nullptr); | 2404 | bool is_inline = ir_should_inline(irb) || node->data.switch_expr.is_inline; |
| 2326 | | 2405 | |
| 2327 | ZigList<IrInstruction *> incoming_values = {0}; | 2406 | ZigList<IrInstruction *> incoming_values = {0}; |
| 2328 | ZigList<IrBasicBlock *> incoming_blocks = {0}; | 2407 | ZigList<IrBasicBlock *> incoming_blocks = {0}; |
| ... | @@ -2495,7 +2574,7 @@ static IrInstruction *ir_gen_label(IrBuilder *irb, AstNode *node) { | ... | @@ -2495,7 +2574,7 @@ static IrInstruction *ir_gen_label(IrBuilder *irb, AstNode *node) { |
| 2495 | node->block_context->label_table.put(label_name, label); | 2574 | node->block_context->label_table.put(label_name, label); |
| 2496 | } | 2575 | } |
| 2497 | | 2576 | |
| 2498 | bool is_inline = (node->block_context->fn_entry == nullptr); | 2577 | bool is_inline = ir_should_inline(irb); |
| 2499 | ir_build_br(irb, node, label_block, is_inline); | 2578 | ir_build_br(irb, node, label_block, is_inline); |
| 2500 | ir_set_cursor_at_end(irb, label_block); | 2579 | ir_set_cursor_at_end(irb, label_block); |
| 2501 | return ir_build_const_void(irb, node); | 2580 | return ir_build_const_void(irb, node); |
| ... | @@ -2535,56 +2614,58 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, BlockContex | ... | @@ -2535,56 +2614,58 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, BlockContex |
| 2535 | node->block_context = block_context; | 2614 | node->block_context = block_context; |
| 2536 | | 2615 | |
| 2537 | switch (node->type) { | 2616 | switch (node->type) { |
| | 2617 | case NodeTypeStructValueField: |
| | 2618 | zig_unreachable(); |
| 2538 | case NodeTypeBlock: | 2619 | case NodeTypeBlock: |
| 2539 | return ir_gen_block(irb, node); | 2620 | return ir_lval_wrap(irb, ir_gen_block(irb, node), lval); |
| 2540 | case NodeTypeBinOpExpr: | 2621 | case NodeTypeBinOpExpr: |
| 2541 | return ir_gen_bin_op(irb, node); | 2622 | return ir_lval_wrap(irb, ir_gen_bin_op(irb, node), lval); |
| 2542 | case NodeTypeNumberLiteral: | 2623 | case NodeTypeNumberLiteral: |
| 2543 | return ir_gen_num_lit(irb, node); | 2624 | return ir_lval_wrap(irb, ir_gen_num_lit(irb, node), lval); |
| 2544 | case NodeTypeSymbol: | 2625 | case NodeTypeSymbol: |
| 2545 | return ir_gen_symbol(irb, node, lval); | 2626 | return ir_gen_symbol(irb, node, lval); |
| 2546 | case NodeTypeFnCallExpr: | 2627 | case NodeTypeFnCallExpr: |
| 2547 | return ir_lval_wrap(irb, ir_gen_fn_call(irb, node), lval); | 2628 | return ir_lval_wrap(irb, ir_gen_fn_call(irb, node), lval); |
| 2548 | case NodeTypeIfBoolExpr: | 2629 | case NodeTypeIfBoolExpr: |
| 2549 | return ir_gen_if_bool_expr(irb, node); | 2630 | return ir_lval_wrap(irb, ir_gen_if_bool_expr(irb, node), lval); |
| 2550 | case NodeTypePrefixOpExpr: | 2631 | case NodeTypePrefixOpExpr: |
| 2551 | return ir_gen_prefix_op_expr(irb, node, lval); | 2632 | return ir_gen_prefix_op_expr(irb, node, lval); |
| 2552 | case NodeTypeContainerInitExpr: | 2633 | case NodeTypeContainerInitExpr: |
| 2553 | return ir_gen_container_init_expr(irb, node); | 2634 | return ir_lval_wrap(irb, ir_gen_container_init_expr(irb, node), lval); |
| 2554 | case NodeTypeVariableDeclaration: | 2635 | case NodeTypeVariableDeclaration: |
| 2555 | return ir_gen_var_decl(irb, node); | 2636 | return ir_lval_wrap(irb, ir_gen_var_decl(irb, node), lval); |
| 2556 | case NodeTypeWhileExpr: | 2637 | case NodeTypeWhileExpr: |
| 2557 | return ir_gen_while_expr(irb, node); | 2638 | return ir_lval_wrap(irb, ir_gen_while_expr(irb, node), lval); |
| 2558 | case NodeTypeForExpr: | 2639 | case NodeTypeForExpr: |
| 2559 | return ir_gen_for_expr(irb, node); | 2640 | return ir_lval_wrap(irb, ir_gen_for_expr(irb, node), lval); |
| 2560 | case NodeTypeArrayAccessExpr: | 2641 | case NodeTypeArrayAccessExpr: |
| 2561 | return ir_gen_array_access(irb, node, lval); | 2642 | return ir_gen_array_access(irb, node, lval); |
| 2562 | case NodeTypeReturnExpr: | 2643 | case NodeTypeReturnExpr: |
| 2563 | return ir_gen_return(irb, node); | 2644 | return ir_lval_wrap(irb, ir_gen_return(irb, node), lval); |
| 2564 | case NodeTypeFieldAccessExpr: | 2645 | case NodeTypeFieldAccessExpr: |
| 2565 | return ir_gen_field_access(irb, node, lval); | 2646 | return ir_gen_field_access(irb, node, lval); |
| 2566 | case NodeTypeThisLiteral: | 2647 | case NodeTypeThisLiteral: |
| 2567 | return ir_gen_this_literal(irb, node); | 2648 | return ir_lval_wrap(irb, ir_gen_this_literal(irb, node), lval); |
| 2568 | case NodeTypeBoolLiteral: | 2649 | case NodeTypeBoolLiteral: |
| 2569 | return ir_gen_bool_literal(irb, node); | 2650 | return ir_lval_wrap(irb, ir_gen_bool_literal(irb, node), lval); |
| 2570 | case NodeTypeArrayType: | 2651 | case NodeTypeArrayType: |
| 2571 | return ir_gen_array_type(irb, node); | 2652 | return ir_lval_wrap(irb, ir_gen_array_type(irb, node), lval); |
| 2572 | case NodeTypeStringLiteral: | 2653 | case NodeTypeStringLiteral: |
| 2573 | return ir_gen_string_literal(irb, node); | 2654 | return ir_lval_wrap(irb, ir_gen_string_literal(irb, node), lval); |
| 2574 | case NodeTypeUndefinedLiteral: | 2655 | case NodeTypeUndefinedLiteral: |
| 2575 | return ir_gen_undefined_literal(irb, node); | 2656 | return ir_lval_wrap(irb, ir_gen_undefined_literal(irb, node), lval); |
| 2576 | case NodeTypeAsmExpr: | 2657 | case NodeTypeAsmExpr: |
| 2577 | return ir_gen_asm_expr(irb, node); | 2658 | return ir_lval_wrap(irb, ir_gen_asm_expr(irb, node), lval); |
| 2578 | case NodeTypeNullLiteral: | 2659 | case NodeTypeNullLiteral: |
| 2579 | return ir_gen_null_literal(irb, node); | 2660 | return ir_lval_wrap(irb, ir_gen_null_literal(irb, node), lval); |
| 2580 | case NodeTypeIfVarExpr: | 2661 | case NodeTypeIfVarExpr: |
| 2581 | return ir_gen_if_var_expr(irb, node); | 2662 | return ir_lval_wrap(irb, ir_gen_if_var_expr(irb, node), lval); |
| 2582 | case NodeTypeSwitchExpr: | 2663 | case NodeTypeSwitchExpr: |
| 2583 | return ir_gen_switch_expr(irb, node); | 2664 | return ir_lval_wrap(irb, ir_gen_switch_expr(irb, node), lval); |
| 2584 | case NodeTypeLabel: | 2665 | case NodeTypeLabel: |
| 2585 | return ir_gen_label(irb, node); | 2666 | return ir_lval_wrap(irb, ir_gen_label(irb, node), lval); |
| 2586 | case NodeTypeGoto: | 2667 | case NodeTypeGoto: |
| 2587 | return ir_gen_goto(irb, node); | 2668 | return ir_lval_wrap(irb, ir_gen_goto(irb, node), lval); |
| 2588 | case NodeTypeTypeLiteral: | 2669 | case NodeTypeTypeLiteral: |
| 2589 | return ir_lval_wrap(irb, ir_gen_type_literal(irb, node), lval); | 2670 | return ir_lval_wrap(irb, ir_gen_type_literal(irb, node), lval); |
| 2590 | case NodeTypeUnwrapErrorExpr: | 2671 | case NodeTypeUnwrapErrorExpr: |
| ... | @@ -2604,7 +2685,6 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, BlockContex | ... | @@ -2604,7 +2685,6 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, BlockContex |
| 2604 | case NodeTypeUse: | 2685 | case NodeTypeUse: |
| 2605 | case NodeTypeContainerDecl: | 2686 | case NodeTypeContainerDecl: |
| 2606 | case NodeTypeStructField: | 2687 | case NodeTypeStructField: |
| 2607 | case NodeTypeStructValueField: | | |
| 2608 | case NodeTypeSwitchProng: | 2688 | case NodeTypeSwitchProng: |
| 2609 | case NodeTypeSwitchRange: | 2689 | case NodeTypeSwitchRange: |
| 2610 | case NodeTypeErrorValueDecl: | 2690 | case NodeTypeErrorValueDecl: |
| ... | @@ -2642,7 +2722,7 @@ static bool ir_goto_pass2(IrBuilder *irb) { | ... | @@ -2642,7 +2722,7 @@ static bool ir_goto_pass2(IrBuilder *irb) { |
| 2642 | } | 2722 | } |
| 2643 | label->used = true; | 2723 | label->used = true; |
| 2644 | | 2724 | |
| 2645 | bool is_inline = goto_node->data.goto_expr.is_inline || (goto_node->block_context->fn_entry == nullptr); | 2725 | bool is_inline = ir_should_inline(irb) || goto_node->data.goto_expr.is_inline; |
| 2646 | IrInstruction *new_instruction = ir_create_br(irb, goto_node, label->bb, is_inline); | 2726 | IrInstruction *new_instruction = ir_create_br(irb, goto_node, label->bb, is_inline); |
| 2647 | new_instruction->ref_count = old_instruction->ref_count; | 2727 | new_instruction->ref_count = old_instruction->ref_count; |
| 2648 | *slot = new_instruction; | 2728 | *slot = new_instruction; |
| ... | @@ -2703,6 +2783,21 @@ IrInstruction *ir_gen_fn(CodeGen *codegn, FnTableEntry *fn_entry) { | ... | @@ -2703,6 +2783,21 @@ IrInstruction *ir_gen_fn(CodeGen *codegn, FnTableEntry *fn_entry) { |
| 2703 | return ir_gen(codegn, body_node, scope, ir_executable); | 2783 | return ir_gen(codegn, body_node, scope, ir_executable); |
| 2704 | } | 2784 | } |
| 2705 | | 2785 | |
| | 2786 | static IrInstruction *ir_eval_fn(IrAnalyze *ira, IrInstruction *source_instruction, |
| | 2787 | size_t arg_count, IrInstruction **args) |
| | 2788 | { |
| | 2789 | zig_panic("TODO ir_eval_fn"); |
| | 2790 | } |
| | 2791 | |
| | 2792 | static bool ir_emit_global_runtime_side_effect(IrAnalyze *ira, IrInstruction *source_instruction) { |
| | 2793 | if (ir_should_inline(&ira->new_irb)) { |
| | 2794 | add_node_error(ira->codegen, source_instruction->source_node, |
| | 2795 | buf_sprintf("unable to evaluate constant expression")); |
| | 2796 | return false; |
| | 2797 | } |
| | 2798 | return true; |
| | 2799 | } |
| | 2800 | |
| 2706 | static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstruction *instruction, TypeTableEntry *other_type) { | 2801 | static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstruction *instruction, TypeTableEntry *other_type) { |
| 2707 | TypeTableEntry *other_type_underlying = get_underlying_type(other_type); | 2802 | TypeTableEntry *other_type_underlying = get_underlying_type(other_type); |
| 2708 | | 2803 | |
| ... | @@ -2918,20 +3013,15 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod | ... | @@ -2918,20 +3013,15 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod |
| 2918 | } | 3013 | } |
| 2919 | | 3014 | |
| 2920 | static IrInstruction *ir_resolve_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value, | 3015 | static IrInstruction *ir_resolve_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value, |
| 2921 | IrInstruction *dest_type, CastOp cast_op, bool need_alloca) | 3016 | TypeTableEntry *wanted_type, CastOp cast_op, bool need_alloca) |
| 2922 | { | 3017 | { |
| 2923 | assert(dest_type->type_entry->id == TypeTableEntryIdMetaType); | | |
| 2924 | assert(dest_type->static_value.special != ConstValSpecialRuntime); | | |
| 2925 | TypeTableEntry *wanted_type = dest_type->static_value.data.x_type; | | |
| 2926 | | | |
| 2927 | if (value->static_value.special != ConstValSpecialRuntime) { | 3018 | if (value->static_value.special != ConstValSpecialRuntime) { |
| 2928 | IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->source_node, wanted_type); | 3019 | IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->source_node, wanted_type, false); |
| 2929 | eval_const_expr_implicit_cast(cast_op, &value->static_value, value->type_entry, | 3020 | eval_const_expr_implicit_cast(cast_op, &value->static_value, value->type_entry, |
| 2930 | &result->static_value, wanted_type); | 3021 | &result->static_value, wanted_type); |
| 2931 | return result; | 3022 | return result; |
| 2932 | } else { | 3023 | } else { |
| 2933 | IrInstruction *result = ir_build_cast(&ira->new_irb, source_instr->source_node, | 3024 | IrInstruction *result = ir_build_cast(&ira->new_irb, source_instr->source_node, wanted_type, value, cast_op); |
| 2934 | dest_type, value, cast_op); | | |
| 2935 | result->type_entry = wanted_type; | 3025 | result->type_entry = wanted_type; |
| 2936 | if (need_alloca && source_instr->source_node->block_context->fn_entry) { | 3026 | if (need_alloca && source_instr->source_node->block_context->fn_entry) { |
| 2937 | source_instr->source_node->block_context->fn_entry->alloca_list.append(result); | 3027 | source_instr->source_node->block_context->fn_entry->alloca_list.append(result); |
| ... | @@ -3126,12 +3216,8 @@ static FnTableEntry *ir_resolve_fn(IrAnalyze *ira, IrInstruction *fn_value) { | ... | @@ -3126,12 +3216,8 @@ static FnTableEntry *ir_resolve_fn(IrAnalyze *ira, IrInstruction *fn_value) { |
| 3126 | } | 3216 | } |
| 3127 | | 3217 | |
| 3128 | static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_instr, | 3218 | static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_instr, |
| 3129 | IrInstruction *dest_type, IrInstruction *value) | 3219 | TypeTableEntry *wanted_type, IrInstruction *value) |
| 3130 | { | 3220 | { |
| 3131 | assert(dest_type->type_entry->id == TypeTableEntryIdMetaType); | | |
| 3132 | assert(dest_type->static_value.special != ConstValSpecialRuntime); | | |
| 3133 | | | |
| 3134 | TypeTableEntry *wanted_type = dest_type->static_value.data.x_type; | | |
| 3135 | TypeTableEntry *actual_type = value->type_entry; | 3221 | TypeTableEntry *actual_type = value->type_entry; |
| 3136 | TypeTableEntry *wanted_type_canon = get_underlying_type(wanted_type); | 3222 | TypeTableEntry *wanted_type_canon = get_underlying_type(wanted_type); |
| 3137 | TypeTableEntry *actual_type_canon = get_underlying_type(actual_type); | 3223 | TypeTableEntry *actual_type_canon = get_underlying_type(actual_type); |
| ... | @@ -3147,21 +3233,21 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst | ... | @@ -3147,21 +3233,21 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 3147 | | 3233 | |
| 3148 | // explicit match or non-const to const | 3234 | // explicit match or non-const to const |
| 3149 | if (types_match_const_cast_only(wanted_type, actual_type)) { | 3235 | if (types_match_const_cast_only(wanted_type, actual_type)) { |
| 3150 | return ir_resolve_cast(ira, source_instr, value, dest_type, CastOpNoop, false); | 3236 | return ir_resolve_cast(ira, source_instr, value, wanted_type, CastOpNoop, false); |
| 3151 | } | 3237 | } |
| 3152 | | 3238 | |
| 3153 | // explicit cast from bool to int | 3239 | // explicit cast from bool to int |
| 3154 | if (wanted_type_canon->id == TypeTableEntryIdInt && | 3240 | if (wanted_type_canon->id == TypeTableEntryIdInt && |
| 3155 | actual_type_canon->id == TypeTableEntryIdBool) | 3241 | actual_type_canon->id == TypeTableEntryIdBool) |
| 3156 | { | 3242 | { |
| 3157 | return ir_resolve_cast(ira, source_instr, value, dest_type, CastOpBoolToInt, false); | 3243 | return ir_resolve_cast(ira, source_instr, value, wanted_type, CastOpBoolToInt, false); |
| 3158 | } | 3244 | } |
| 3159 | | 3245 | |
| 3160 | // explicit cast from pointer to isize or usize | 3246 | // explicit cast from pointer to isize or usize |
| 3161 | if ((wanted_type_canon == isize_type || wanted_type_canon == usize_type) && | 3247 | if ((wanted_type_canon == isize_type || wanted_type_canon == usize_type) && |
| 3162 | type_is_codegen_pointer(actual_type_canon)) | 3248 | type_is_codegen_pointer(actual_type_canon)) |
| 3163 | { | 3249 | { |
| 3164 | return ir_resolve_cast(ira, source_instr, value, dest_type, CastOpPtrToInt, false); | 3250 | return ir_resolve_cast(ira, source_instr, value, wanted_type, CastOpPtrToInt, false); |
| 3165 | } | 3251 | } |
| 3166 | | 3252 | |
| 3167 | | 3253 | |
| ... | @@ -3169,7 +3255,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst | ... | @@ -3169,7 +3255,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 3169 | if (wanted_type_canon->id == TypeTableEntryIdPointer && | 3255 | if (wanted_type_canon->id == TypeTableEntryIdPointer && |
| 3170 | (actual_type_canon == isize_type || actual_type_canon == usize_type)) | 3256 | (actual_type_canon == isize_type || actual_type_canon == usize_type)) |
| 3171 | { | 3257 | { |
| 3172 | return ir_resolve_cast(ira, source_instr, value, dest_type, CastOpIntToPtr, false); | 3258 | return ir_resolve_cast(ira, source_instr, value, wanted_type, CastOpIntToPtr, false); |
| 3173 | } | 3259 | } |
| 3174 | | 3260 | |
| 3175 | // explicit widening or shortening cast | 3261 | // explicit widening or shortening cast |
| ... | @@ -3178,21 +3264,21 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst | ... | @@ -3178,21 +3264,21 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 3178 | (wanted_type_canon->id == TypeTableEntryIdFloat && | 3264 | (wanted_type_canon->id == TypeTableEntryIdFloat && |
| 3179 | actual_type_canon->id == TypeTableEntryIdFloat)) | 3265 | actual_type_canon->id == TypeTableEntryIdFloat)) |
| 3180 | { | 3266 | { |
| 3181 | return ir_resolve_cast(ira, source_instr, value, dest_type, CastOpWidenOrShorten, false); | 3267 | return ir_resolve_cast(ira, source_instr, value, wanted_type, CastOpWidenOrShorten, false); |
| 3182 | } | 3268 | } |
| 3183 | | 3269 | |
| 3184 | // explicit cast from int to float | 3270 | // explicit cast from int to float |
| 3185 | if (wanted_type_canon->id == TypeTableEntryIdFloat && | 3271 | if (wanted_type_canon->id == TypeTableEntryIdFloat && |
| 3186 | actual_type_canon->id == TypeTableEntryIdInt) | 3272 | actual_type_canon->id == TypeTableEntryIdInt) |
| 3187 | { | 3273 | { |
| 3188 | return ir_resolve_cast(ira, source_instr, value, dest_type, CastOpIntToFloat, false); | 3274 | return ir_resolve_cast(ira, source_instr, value, wanted_type, CastOpIntToFloat, false); |
| 3189 | } | 3275 | } |
| 3190 | | 3276 | |
| 3191 | // explicit cast from float to int | 3277 | // explicit cast from float to int |
| 3192 | if (wanted_type_canon->id == TypeTableEntryIdInt && | 3278 | if (wanted_type_canon->id == TypeTableEntryIdInt && |
| 3193 | actual_type_canon->id == TypeTableEntryIdFloat) | 3279 | actual_type_canon->id == TypeTableEntryIdFloat) |
| 3194 | { | 3280 | { |
| 3195 | return ir_resolve_cast(ira, source_instr, value, dest_type, CastOpFloatToInt, false); | 3281 | return ir_resolve_cast(ira, source_instr, value, wanted_type, CastOpFloatToInt, false); |
| 3196 | } | 3282 | } |
| 3197 | | 3283 | |
| 3198 | // explicit cast from array to slice | 3284 | // explicit cast from array to slice |
| ... | @@ -3202,7 +3288,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst | ... | @@ -3202,7 +3288,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 3202 | wanted_type->data.structure.fields[0].type_entry->data.pointer.child_type, | 3288 | wanted_type->data.structure.fields[0].type_entry->data.pointer.child_type, |
| 3203 | actual_type->data.array.child_type)) | 3289 | actual_type->data.array.child_type)) |
| 3204 | { | 3290 | { |
| 3205 | return ir_resolve_cast(ira, source_instr, value, dest_type, CastOpToUnknownSizeArray, true); | 3291 | return ir_resolve_cast(ira, source_instr, value, wanted_type, CastOpToUnknownSizeArray, true); |
| 3206 | } | 3292 | } |
| 3207 | | 3293 | |
| 3208 | // explicit cast from []T to []u8 or []u8 to []T | 3294 | // explicit cast from []T to []u8 or []u8 to []T |
| ... | @@ -3212,8 +3298,9 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst | ... | @@ -3212,8 +3298,9 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 3212 | (wanted_type->data.structure.fields[0].type_entry->data.pointer.is_const || | 3298 | (wanted_type->data.structure.fields[0].type_entry->data.pointer.is_const || |
| 3213 | !actual_type->data.structure.fields[0].type_entry->data.pointer.is_const)) | 3299 | !actual_type->data.structure.fields[0].type_entry->data.pointer.is_const)) |
| 3214 | { | 3300 | { |
| 3215 | mark_impure_fn(ira->codegen, source_instr->source_node->block_context, source_instr->source_node); | 3301 | if (!ir_emit_global_runtime_side_effect(ira, source_instr)) |
| 3216 | return ir_resolve_cast(ira, source_instr, value, dest_type, CastOpResizeSlice, true); | 3302 | return ira->codegen->invalid_instruction; |
| | 3303 | return ir_resolve_cast(ira, source_instr, value, wanted_type, CastOpResizeSlice, true); |
| 3217 | } | 3304 | } |
| 3218 | | 3305 | |
| 3219 | // explicit cast from [N]u8 to []T | 3306 | // explicit cast from [N]u8 to []T |
| ... | @@ -3221,11 +3308,12 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst | ... | @@ -3221,11 +3308,12 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 3221 | actual_type->id == TypeTableEntryIdArray && | 3308 | actual_type->id == TypeTableEntryIdArray && |
| 3222 | is_u8(actual_type->data.array.child_type)) | 3309 | is_u8(actual_type->data.array.child_type)) |
| 3223 | { | 3310 | { |
| 3224 | mark_impure_fn(ira->codegen, source_instr->source_node->block_context, source_instr->source_node); | 3311 | if (!ir_emit_global_runtime_side_effect(ira, source_instr)) |
| | 3312 | return ira->codegen->invalid_instruction; |
| 3225 | uint64_t child_type_size = type_size(ira->codegen, | 3313 | uint64_t child_type_size = type_size(ira->codegen, |
| 3226 | wanted_type->data.structure.fields[0].type_entry->data.pointer.child_type); | 3314 | wanted_type->data.structure.fields[0].type_entry->data.pointer.child_type); |
| 3227 | if (actual_type->data.array.len % child_type_size == 0) { | 3315 | if (actual_type->data.array.len % child_type_size == 0) { |
| 3228 | return ir_resolve_cast(ira, source_instr, value, dest_type, CastOpBytesToSlice, true); | 3316 | return ir_resolve_cast(ira, source_instr, value, wanted_type, CastOpBytesToSlice, true); |
| 3229 | } else { | 3317 | } else { |
| 3230 | add_node_error(ira->codegen, source_instr->source_node, | 3318 | add_node_error(ira->codegen, source_instr->source_node, |
| 3231 | buf_sprintf("unable to convert %s to %s: size mismatch", | 3319 | buf_sprintf("unable to convert %s to %s: size mismatch", |
| ... | @@ -3238,7 +3326,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst | ... | @@ -3238,7 +3326,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 3238 | if ((actual_type->id == TypeTableEntryIdPointer || actual_type->id == TypeTableEntryIdFn) && | 3326 | if ((actual_type->id == TypeTableEntryIdPointer || actual_type->id == TypeTableEntryIdFn) && |
| 3239 | (wanted_type->id == TypeTableEntryIdPointer || wanted_type->id == TypeTableEntryIdFn)) | 3327 | (wanted_type->id == TypeTableEntryIdPointer || wanted_type->id == TypeTableEntryIdFn)) |
| 3240 | { | 3328 | { |
| 3241 | return ir_resolve_cast(ira, source_instr, value, dest_type, CastOpPointerReinterpret, false); | 3329 | return ir_resolve_cast(ira, source_instr, value, wanted_type, CastOpPointerReinterpret, false); |
| 3242 | } | 3330 | } |
| 3243 | | 3331 | |
| 3244 | // explicit cast from maybe pointer to another maybe pointer | 3332 | // explicit cast from maybe pointer to another maybe pointer |
| ... | @@ -3249,13 +3337,13 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst | ... | @@ -3249,13 +3337,13 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 3249 | (wanted_type->data.maybe.child_type->id == TypeTableEntryIdPointer || | 3337 | (wanted_type->data.maybe.child_type->id == TypeTableEntryIdPointer || |
| 3250 | wanted_type->data.maybe.child_type->id == TypeTableEntryIdFn)) | 3338 | wanted_type->data.maybe.child_type->id == TypeTableEntryIdFn)) |
| 3251 | { | 3339 | { |
| 3252 | return ir_resolve_cast(ira, source_instr, value, dest_type, CastOpPointerReinterpret, false); | 3340 | return ir_resolve_cast(ira, source_instr, value, wanted_type, CastOpPointerReinterpret, false); |
| 3253 | } | 3341 | } |
| 3254 | | 3342 | |
| 3255 | // explicit cast from child type of maybe type to maybe type | 3343 | // explicit cast from child type of maybe type to maybe type |
| 3256 | if (wanted_type->id == TypeTableEntryIdMaybe) { | 3344 | if (wanted_type->id == TypeTableEntryIdMaybe) { |
| 3257 | if (types_match_const_cast_only(wanted_type->data.maybe.child_type, actual_type)) { | 3345 | if (types_match_const_cast_only(wanted_type->data.maybe.child_type, actual_type)) { |
| 3258 | IrInstruction *cast_instruction = ir_resolve_cast(ira, source_instr, value, dest_type, | 3346 | IrInstruction *cast_instruction = ir_resolve_cast(ira, source_instr, value, wanted_type, |
| 3259 | CastOpMaybeWrap, true); | 3347 | CastOpMaybeWrap, true); |
| 3260 | cast_instruction->return_knowledge = ReturnKnowledgeKnownNonNull; | 3348 | cast_instruction->return_knowledge = ReturnKnowledgeKnownNonNull; |
| 3261 | return cast_instruction; | 3349 | return cast_instruction; |
| ... | @@ -3263,7 +3351,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst | ... | @@ -3263,7 +3351,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 3263 | actual_type->id == TypeTableEntryIdNumLitFloat) | 3351 | actual_type->id == TypeTableEntryIdNumLitFloat) |
| 3264 | { | 3352 | { |
| 3265 | if (ir_num_lit_fits_in_other_type(ira, value, wanted_type->data.maybe.child_type)) { | 3353 | if (ir_num_lit_fits_in_other_type(ira, value, wanted_type->data.maybe.child_type)) { |
| 3266 | IrInstruction *cast_instruction = ir_resolve_cast(ira, source_instr, value, dest_type, | 3354 | IrInstruction *cast_instruction = ir_resolve_cast(ira, source_instr, value, wanted_type, |
| 3267 | CastOpMaybeWrap, true); | 3355 | CastOpMaybeWrap, true); |
| 3268 | cast_instruction->return_knowledge = ReturnKnowledgeKnownNonNull; | 3356 | cast_instruction->return_knowledge = ReturnKnowledgeKnownNonNull; |
| 3269 | return cast_instruction; | 3357 | return cast_instruction; |
| ... | @@ -3277,7 +3365,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst | ... | @@ -3277,7 +3365,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 3277 | if (wanted_type->id == TypeTableEntryIdMaybe && | 3365 | if (wanted_type->id == TypeTableEntryIdMaybe && |
| 3278 | actual_type->id == TypeTableEntryIdNullLit) | 3366 | actual_type->id == TypeTableEntryIdNullLit) |
| 3279 | { | 3367 | { |
| 3280 | IrInstruction *cast_instruction = ir_resolve_cast(ira, source_instr, value, dest_type, | 3368 | IrInstruction *cast_instruction = ir_resolve_cast(ira, source_instr, value, wanted_type, |
| 3281 | CastOpNullToMaybe, true); | 3369 | CastOpNullToMaybe, true); |
| 3282 | cast_instruction->return_knowledge = ReturnKnowledgeKnownNull; | 3370 | cast_instruction->return_knowledge = ReturnKnowledgeKnownNull; |
| 3283 | return cast_instruction; | 3371 | return cast_instruction; |
| ... | @@ -3286,7 +3374,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst | ... | @@ -3286,7 +3374,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 3286 | // explicit cast from child type of error type to error type | 3374 | // explicit cast from child type of error type to error type |
| 3287 | if (wanted_type->id == TypeTableEntryIdErrorUnion) { | 3375 | if (wanted_type->id == TypeTableEntryIdErrorUnion) { |
| 3288 | if (types_match_const_cast_only(wanted_type->data.error.child_type, actual_type)) { | 3376 | if (types_match_const_cast_only(wanted_type->data.error.child_type, actual_type)) { |
| 3289 | IrInstruction *cast_instruction = ir_resolve_cast(ira, source_instr, value, dest_type, | 3377 | IrInstruction *cast_instruction = ir_resolve_cast(ira, source_instr, value, wanted_type, |
| 3290 | CastOpErrorWrap, true); | 3378 | CastOpErrorWrap, true); |
| 3291 | cast_instruction->return_knowledge = ReturnKnowledgeKnownNonError; | 3379 | cast_instruction->return_knowledge = ReturnKnowledgeKnownNonError; |
| 3292 | return cast_instruction; | 3380 | return cast_instruction; |
| ... | @@ -3294,7 +3382,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst | ... | @@ -3294,7 +3382,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 3294 | actual_type->id == TypeTableEntryIdNumLitFloat) | 3382 | actual_type->id == TypeTableEntryIdNumLitFloat) |
| 3295 | { | 3383 | { |
| 3296 | if (ir_num_lit_fits_in_other_type(ira, value, wanted_type->data.error.child_type)) { | 3384 | if (ir_num_lit_fits_in_other_type(ira, value, wanted_type->data.error.child_type)) { |
| 3297 | IrInstruction *cast_instruction = ir_resolve_cast(ira, source_instr, value, dest_type, | 3385 | IrInstruction *cast_instruction = ir_resolve_cast(ira, source_instr, value, wanted_type, |
| 3298 | CastOpErrorWrap, true); | 3386 | CastOpErrorWrap, true); |
| 3299 | cast_instruction->return_knowledge = ReturnKnowledgeKnownNonError; | 3387 | cast_instruction->return_knowledge = ReturnKnowledgeKnownNonError; |
| 3300 | return cast_instruction; | 3388 | return cast_instruction; |
| ... | @@ -3308,7 +3396,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst | ... | @@ -3308,7 +3396,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 3308 | if (wanted_type->id == TypeTableEntryIdErrorUnion && | 3396 | if (wanted_type->id == TypeTableEntryIdErrorUnion && |
| 3309 | actual_type->id == TypeTableEntryIdPureError) | 3397 | actual_type->id == TypeTableEntryIdPureError) |
| 3310 | { | 3398 | { |
| 3311 | IrInstruction *cast_instruction = ir_resolve_cast(ira, source_instr, value, dest_type, | 3399 | IrInstruction *cast_instruction = ir_resolve_cast(ira, source_instr, value, wanted_type, |
| 3312 | CastOpPureErrorWrap, false); | 3400 | CastOpPureErrorWrap, false); |
| 3313 | cast_instruction->return_knowledge = ReturnKnowledgeKnownError; | 3401 | cast_instruction->return_knowledge = ReturnKnowledgeKnownError; |
| 3314 | return cast_instruction; | 3402 | return cast_instruction; |
| ... | @@ -3333,7 +3421,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst | ... | @@ -3333,7 +3421,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 3333 | } else { | 3421 | } else { |
| 3334 | zig_unreachable(); | 3422 | zig_unreachable(); |
| 3335 | } | 3423 | } |
| 3336 | return ir_resolve_cast(ira, source_instr, value, dest_type, op, false); | 3424 | return ir_resolve_cast(ira, source_instr, value, wanted_type, op, false); |
| 3337 | } else { | 3425 | } else { |
| 3338 | return ira->codegen->invalid_instruction; | 3426 | return ira->codegen->invalid_instruction; |
| 3339 | } | 3427 | } |
| ... | @@ -3351,7 +3439,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst | ... | @@ -3351,7 +3439,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 3351 | if (bignum_fits_in_bits(&bn, wanted_type->data.integral.bit_count, | 3439 | if (bignum_fits_in_bits(&bn, wanted_type->data.integral.bit_count, |
| 3352 | wanted_type->data.integral.is_signed)) | 3440 | wanted_type->data.integral.is_signed)) |
| 3353 | { | 3441 | { |
| 3354 | return ir_resolve_cast(ira, source_instr, value, dest_type, CastOpErrToInt, false); | 3442 | return ir_resolve_cast(ira, source_instr, value, wanted_type, CastOpErrToInt, false); |
| 3355 | } else { | 3443 | } else { |
| 3356 | add_node_error(ira->codegen, source_instr->source_node, | 3444 | add_node_error(ira->codegen, source_instr->source_node, |
| 3357 | buf_sprintf("too many error values to fit in '%s'", buf_ptr(&wanted_type->name))); | 3445 | buf_sprintf("too many error values to fit in '%s'", buf_ptr(&wanted_type->name))); |
| ... | @@ -3364,7 +3452,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst | ... | @@ -3364,7 +3452,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 3364 | wanted_type->id == TypeTableEntryIdEnum && | 3452 | wanted_type->id == TypeTableEntryIdEnum && |
| 3365 | wanted_type->data.enumeration.gen_field_count == 0) | 3453 | wanted_type->data.enumeration.gen_field_count == 0) |
| 3366 | { | 3454 | { |
| 3367 | return ir_resolve_cast(ira, source_instr, value, dest_type, CastOpIntToEnum, false); | 3455 | return ir_resolve_cast(ira, source_instr, value, wanted_type, CastOpIntToEnum, false); |
| 3368 | } | 3456 | } |
| 3369 | | 3457 | |
| 3370 | // explicit cast from enum type with no payload to integer | 3458 | // explicit cast from enum type with no payload to integer |
| ... | @@ -3372,12 +3460,12 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst | ... | @@ -3372,12 +3460,12 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 3372 | actual_type->id == TypeTableEntryIdEnum && | 3460 | actual_type->id == TypeTableEntryIdEnum && |
| 3373 | actual_type->data.enumeration.gen_field_count == 0) | 3461 | actual_type->data.enumeration.gen_field_count == 0) |
| 3374 | { | 3462 | { |
| 3375 | return ir_resolve_cast(ira, source_instr, value, dest_type, CastOpEnumToInt, false); | 3463 | return ir_resolve_cast(ira, source_instr, value, wanted_type, CastOpEnumToInt, false); |
| 3376 | } | 3464 | } |
| 3377 | | 3465 | |
| 3378 | // explicit cast from undefined to anything | 3466 | // explicit cast from undefined to anything |
| 3379 | if (actual_type->id == TypeTableEntryIdUndefLit) { | 3467 | if (actual_type->id == TypeTableEntryIdUndefLit) { |
| 3380 | return ir_resolve_cast(ira, source_instr, value, dest_type, CastOpNoop, false); | 3468 | return ir_resolve_cast(ira, source_instr, value, wanted_type, CastOpNoop, false); |
| 3381 | } | 3469 | } |
| 3382 | | 3470 | |
| 3383 | add_node_error(ira->codegen, source_instr->source_node, | 3471 | add_node_error(ira->codegen, source_instr->source_node, |
| ... | @@ -3410,11 +3498,7 @@ static IrInstruction *ir_get_casted_value(IrAnalyze *ira, IrInstruction *value, | ... | @@ -3410,11 +3498,7 @@ static IrInstruction *ir_get_casted_value(IrAnalyze *ira, IrInstruction *value, |
| 3410 | return ira->codegen->invalid_instruction; | 3498 | return ira->codegen->invalid_instruction; |
| 3411 | | 3499 | |
| 3412 | case ImplicitCastMatchResultYes: | 3500 | case ImplicitCastMatchResultYes: |
| 3413 | { | 3501 | return ir_analyze_cast(ira, value, expected_type, value); |
| 3414 | IrInstruction *dest_type = ir_create_const_type(&ira->new_irb, value->source_node, expected_type); | | |
| 3415 | IrInstruction *cast_instruction = ir_analyze_cast(ira, value, dest_type, value); | | |
| 3416 | return cast_instruction; | | |
| 3417 | } | | |
| 3418 | case ImplicitCastMatchResultReportedError: | 3502 | case ImplicitCastMatchResultReportedError: |
| 3419 | return ira->codegen->invalid_instruction; | 3503 | return ira->codegen->invalid_instruction; |
| 3420 | } | 3504 | } |
| ... | @@ -3422,6 +3506,58 @@ static IrInstruction *ir_get_casted_value(IrAnalyze *ira, IrInstruction *value, | ... | @@ -3422,6 +3506,58 @@ static IrInstruction *ir_get_casted_value(IrAnalyze *ira, IrInstruction *value, |
| 3422 | zig_unreachable(); | 3506 | zig_unreachable(); |
| 3423 | } | 3507 | } |
| 3424 | | 3508 | |
| | 3509 | static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruction, IrInstruction *ptr) { |
| | 3510 | TypeTableEntry *type_entry = ptr->type_entry; |
| | 3511 | if (type_entry->id == TypeTableEntryIdInvalid) { |
| | 3512 | return ira->codegen->invalid_instruction; |
| | 3513 | } else if (type_entry->id == TypeTableEntryIdPointer) { |
| | 3514 | TypeTableEntry *child_type = type_entry->data.pointer.child_type; |
| | 3515 | if (ptr->static_value.special != ConstValSpecialRuntime) { |
| | 3516 | ConstExprValue *pointee = const_ptr_pointee(&ptr->static_value); |
| | 3517 | if (pointee->special != ConstValSpecialRuntime) { |
| | 3518 | IrInstruction *result = ir_create_const(&ira->new_irb, source_instruction->source_node, |
| | 3519 | child_type, pointee->depends_on_compile_var); |
| | 3520 | result->static_value = *pointee; |
| | 3521 | return result; |
| | 3522 | } |
| | 3523 | } |
| | 3524 | IrInstruction *load_ptr_instruction = ir_build_load_ptr(&ira->new_irb, source_instruction->source_node, ptr); |
| | 3525 | load_ptr_instruction->type_entry = child_type; |
| | 3526 | return load_ptr_instruction; |
| | 3527 | } else { |
| | 3528 | add_node_error(ira->codegen, source_instruction->source_node, |
| | 3529 | buf_sprintf("attempt to dereference non pointer type '%s'", |
| | 3530 | buf_ptr(&type_entry->name))); |
| | 3531 | return ira->codegen->invalid_instruction; |
| | 3532 | } |
| | 3533 | } |
| | 3534 | |
| | 3535 | static TypeTableEntry *ir_analyze_ref(IrAnalyze *ira, IrInstruction *source_instruction, IrInstruction *value) { |
| | 3536 | if (value->type_entry->id == TypeTableEntryIdInvalid) |
| | 3537 | return ira->codegen->builtin_types.entry_invalid; |
| | 3538 | |
| | 3539 | bool is_inline = ir_should_inline(&ira->new_irb); |
| | 3540 | if (is_inline || value->static_value.special != ConstValSpecialRuntime) { |
| | 3541 | ConstExprValue *val = ir_resolve_const(ira, value); |
| | 3542 | if (!val) |
| | 3543 | return ira->codegen->builtin_types.entry_invalid; |
| | 3544 | return ir_analyze_const_ptr(ira, source_instruction, val, value->type_entry, false); |
| | 3545 | } |
| | 3546 | |
| | 3547 | TypeTableEntry *ptr_type = get_pointer_to_type(ira->codegen, value->type_entry, true); |
| | 3548 | if (handle_is_ptr(value->type_entry)) { |
| | 3549 | // this instruction is a noop - codegen can pass the pointer we already have as the result |
| | 3550 | ir_link_new_instruction(value, source_instruction); |
| | 3551 | return ptr_type; |
| | 3552 | } else { |
| | 3553 | FnTableEntry *fn_entry = source_instruction->source_node->block_context->fn_entry; |
| | 3554 | IrInstruction *new_instruction = ir_build_ref_from(&ira->new_irb, source_instruction, value); |
| | 3555 | fn_entry->alloca_list.append(new_instruction); |
| | 3556 | return ptr_type; |
| | 3557 | } |
| | 3558 | } |
| | 3559 | |
| | 3560 | |
| 3425 | static bool ir_resolve_usize(IrAnalyze *ira, IrInstruction *value, uint64_t *out) { | 3561 | static bool ir_resolve_usize(IrAnalyze *ira, IrInstruction *value, uint64_t *out) { |
| 3426 | if (value->type_entry->id == TypeTableEntryIdInvalid) | 3562 | if (value->type_entry->id == TypeTableEntryIdInvalid) |
| 3427 | return false; | 3563 | return false; |
| ... | @@ -3580,6 +3716,7 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp | ... | @@ -3580,6 +3716,7 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp |
| 3580 | case TypeTableEntryIdNamespace: | 3716 | case TypeTableEntryIdNamespace: |
| 3581 | case TypeTableEntryIdBlock: | 3717 | case TypeTableEntryIdBlock: |
| 3582 | case TypeTableEntryIdGenericFn: | 3718 | case TypeTableEntryIdGenericFn: |
| | 3719 | case TypeTableEntryIdBoundFn: |
| 3583 | if (!is_equality_cmp) { | 3720 | if (!is_equality_cmp) { |
| 3584 | add_node_error(ira->codegen, source_node, | 3721 | add_node_error(ira->codegen, source_node, |
| 3585 | buf_sprintf("operator not allowed for type '%s'", buf_ptr(&resolved_type->name))); | 3722 | buf_sprintf("operator not allowed for type '%s'", buf_ptr(&resolved_type->name))); |
| ... | @@ -3944,6 +4081,7 @@ static TypeTableEntry *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruc | ... | @@ -3944,6 +4081,7 @@ static TypeTableEntry *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruc |
| 3944 | case TypeTableEntryIdUnion: | 4081 | case TypeTableEntryIdUnion: |
| 3945 | case TypeTableEntryIdFn: | 4082 | case TypeTableEntryIdFn: |
| 3946 | case TypeTableEntryIdGenericFn: | 4083 | case TypeTableEntryIdGenericFn: |
| | 4084 | case TypeTableEntryIdBoundFn: |
| 3947 | // OK | 4085 | // OK |
| 3948 | break; | 4086 | break; |
| 3949 | } | 4087 | } |
| ... | @@ -3966,13 +4104,121 @@ static TypeTableEntry *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruc | ... | @@ -3966,13 +4104,121 @@ static TypeTableEntry *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruc |
| 3966 | return ira->codegen->builtin_types.entry_void; | 4104 | return ira->codegen->builtin_types.entry_void; |
| 3967 | } | 4105 | } |
| 3968 | | 4106 | |
| | 4107 | static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call_instruction, |
| | 4108 | FnTableEntry *fn_entry, TypeTableEntry *fn_type, IrInstruction *fn_ref, |
| | 4109 | IrInstruction *first_arg_ptr, bool is_inline) |
| | 4110 | { |
| | 4111 | FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id; |
| | 4112 | size_t first_arg_1_or_0 = first_arg_ptr ? 1 : 0; |
| | 4113 | size_t src_param_count = fn_type_id->param_count; |
| | 4114 | size_t call_param_count = call_instruction->arg_count + first_arg_1_or_0; |
| | 4115 | AstNode *source_node = call_instruction->base.source_node; |
| | 4116 | |
| | 4117 | AstNode *fn_proto_node = fn_entry ? fn_entry->proto_node : nullptr;; |
| | 4118 | |
| | 4119 | if (fn_type_id->is_var_args) { |
| | 4120 | if (call_param_count < src_param_count) { |
| | 4121 | ErrorMsg *msg = add_node_error(ira->codegen, source_node, |
| | 4122 | buf_sprintf("expected at least %zu arguments, found %zu", src_param_count, call_param_count)); |
| | 4123 | if (fn_proto_node) { |
| | 4124 | add_error_note(ira->codegen, msg, fn_proto_node, |
| | 4125 | buf_sprintf("declared here")); |
| | 4126 | } |
| | 4127 | return ira->codegen->builtin_types.entry_invalid; |
| | 4128 | } |
| | 4129 | } else if (src_param_count != call_param_count) { |
| | 4130 | ErrorMsg *msg = add_node_error(ira->codegen, source_node, |
| | 4131 | buf_sprintf("expected %zu arguments, found %zu", src_param_count, call_param_count)); |
| | 4132 | if (fn_proto_node) { |
| | 4133 | add_error_note(ira->codegen, msg, fn_proto_node, |
| | 4134 | buf_sprintf("declared here")); |
| | 4135 | } |
| | 4136 | return ira->codegen->builtin_types.entry_invalid; |
| | 4137 | } |
| | 4138 | |
| | 4139 | IrInstruction **casted_args = allocate<IrInstruction *>(call_param_count); |
| | 4140 | size_t next_arg_index = 0; |
| | 4141 | if (first_arg_ptr) { |
| | 4142 | IrInstruction *first_arg = ir_get_deref(ira, first_arg_ptr, first_arg_ptr); |
| | 4143 | if (first_arg->type_entry->id == TypeTableEntryIdInvalid) |
| | 4144 | return ira->codegen->builtin_types.entry_invalid; |
| | 4145 | |
| | 4146 | TypeTableEntry *param_type = fn_type_id->param_info[next_arg_index].type; |
| | 4147 | if (param_type->id == TypeTableEntryIdInvalid) |
| | 4148 | return ira->codegen->builtin_types.entry_invalid; |
| | 4149 | |
| | 4150 | IrInstruction *casted_arg = ir_get_casted_value(ira, first_arg, param_type); |
| | 4151 | if (casted_arg->type_entry->id == TypeTableEntryIdInvalid) |
| | 4152 | return ira->codegen->builtin_types.entry_invalid; |
| | 4153 | |
| | 4154 | if (is_inline && !ir_resolve_const(ira, casted_arg)) |
| | 4155 | return ira->codegen->builtin_types.entry_invalid; |
| | 4156 | |
| | 4157 | casted_args[next_arg_index] = casted_arg; |
| | 4158 | next_arg_index += 1; |
| | 4159 | } |
| | 4160 | for (size_t call_i = 0; call_i < call_instruction->arg_count; call_i += 1) { |
| | 4161 | IrInstruction *old_arg = call_instruction->args[call_i]->other; |
| | 4162 | if (old_arg->type_entry->id == TypeTableEntryIdInvalid) |
| | 4163 | return ira->codegen->builtin_types.entry_invalid; |
| | 4164 | IrInstruction *casted_arg; |
| | 4165 | if (next_arg_index < src_param_count) { |
| | 4166 | TypeTableEntry *param_type = fn_type_id->param_info[next_arg_index].type; |
| | 4167 | if (param_type->id == TypeTableEntryIdInvalid) |
| | 4168 | return ira->codegen->builtin_types.entry_invalid; |
| | 4169 | casted_arg = ir_get_casted_value(ira, old_arg, param_type); |
| | 4170 | if (casted_arg->type_entry->id == TypeTableEntryIdInvalid) |
| | 4171 | return ira->codegen->builtin_types.entry_invalid; |
| | 4172 | } else { |
| | 4173 | casted_arg = old_arg; |
| | 4174 | } |
| | 4175 | |
| | 4176 | if (is_inline && !ir_resolve_const(ira, casted_arg)) |
| | 4177 | return ira->codegen->builtin_types.entry_invalid; |
| | 4178 | |
| | 4179 | casted_args[next_arg_index] = casted_arg; |
| | 4180 | next_arg_index += 1; |
| | 4181 | } |
| | 4182 | |
| | 4183 | assert(next_arg_index == call_param_count); |
| | 4184 | |
| | 4185 | TypeTableEntry *return_type = fn_type_id->return_type; |
| | 4186 | if (return_type->id == TypeTableEntryIdInvalid) |
| | 4187 | return ira->codegen->builtin_types.entry_invalid; |
| | 4188 | |
| | 4189 | if (is_inline) { |
| | 4190 | IrInstruction *result = ir_eval_fn(ira, &call_instruction->base, call_param_count, casted_args); |
| | 4191 | if (result->type_entry->id == TypeTableEntryIdInvalid) |
| | 4192 | return ira->codegen->builtin_types.entry_invalid; |
| | 4193 | |
| | 4194 | ConstExprValue *out_val = ir_build_const_from(ira, &call_instruction->base, |
| | 4195 | result->static_value.depends_on_compile_var); |
| | 4196 | *out_val = result->static_value; |
| | 4197 | return ir_finish_anal(ira, return_type); |
| | 4198 | } |
| | 4199 | |
| | 4200 | IrInstruction *new_call_instruction = ir_build_call_from(&ira->new_irb, &call_instruction->base, |
| | 4201 | fn_entry, fn_ref, call_param_count, casted_args); |
| | 4202 | |
| | 4203 | if (type_has_bits(return_type) && handle_is_ptr(return_type)) |
| | 4204 | call_instruction->base.source_node->block_context->fn_entry->alloca_list.append(new_call_instruction); |
| | 4205 | |
| | 4206 | return ir_finish_anal(ira, return_type); |
| | 4207 | } |
| | 4208 | |
| 3969 | static TypeTableEntry *ir_analyze_instruction_call(IrAnalyze *ira, IrInstructionCall *call_instruction) { | 4209 | static TypeTableEntry *ir_analyze_instruction_call(IrAnalyze *ira, IrInstructionCall *call_instruction) { |
| 3970 | IrInstruction *fn_ref = call_instruction->fn->other; | 4210 | IrInstruction *fn_ref = call_instruction->fn_ref->other; |
| 3971 | if (fn_ref->type_entry->id == TypeTableEntryIdInvalid) | 4211 | if (fn_ref->type_entry->id == TypeTableEntryIdInvalid) |
| 3972 | return ira->codegen->builtin_types.entry_invalid; | 4212 | return ira->codegen->builtin_types.entry_invalid; |
| 3973 | | 4213 | |
| 3974 | if (fn_ref->static_value.special != ConstValSpecialRuntime) { | 4214 | bool is_inline = call_instruction->is_inline || ir_should_inline(&ira->new_irb); |
| | 4215 | |
| | 4216 | if (is_inline || fn_ref->static_value.special != ConstValSpecialRuntime) { |
| 3975 | if (fn_ref->type_entry->id == TypeTableEntryIdMetaType) { | 4217 | if (fn_ref->type_entry->id == TypeTableEntryIdMetaType) { |
| | 4218 | TypeTableEntry *dest_type = ir_resolve_type(ira, fn_ref); |
| | 4219 | if (!dest_type) |
| | 4220 | return ira->codegen->builtin_types.entry_invalid; |
| | 4221 | |
| 3976 | size_t actual_param_count = call_instruction->arg_count; | 4222 | size_t actual_param_count = call_instruction->arg_count; |
| 3977 | | 4223 | |
| 3978 | if (actual_param_count != 1) { | 4224 | if (actual_param_count != 1) { |
| ... | @@ -3982,38 +4228,39 @@ static TypeTableEntry *ir_analyze_instruction_call(IrAnalyze *ira, IrInstruction | ... | @@ -3982,38 +4228,39 @@ static TypeTableEntry *ir_analyze_instruction_call(IrAnalyze *ira, IrInstruction |
| 3982 | } | 4228 | } |
| 3983 | | 4229 | |
| 3984 | IrInstruction *arg = call_instruction->args[0]->other; | 4230 | IrInstruction *arg = call_instruction->args[0]->other; |
| 3985 | IrInstruction *cast_instruction = ir_analyze_cast(ira, &call_instruction->base, fn_ref, arg); | 4231 | |
| 3986 | if (cast_instruction == ira->codegen->invalid_instruction) | 4232 | IrInstruction *cast_instruction = ir_analyze_cast(ira, &call_instruction->base, dest_type, arg); |
| | 4233 | if (cast_instruction->type_entry->id == TypeTableEntryIdInvalid) |
| 3987 | return ira->codegen->builtin_types.entry_invalid; | 4234 | return ira->codegen->builtin_types.entry_invalid; |
| 3988 | | 4235 | |
| 3989 | ir_link_new_instruction(cast_instruction, &call_instruction->base); | 4236 | ir_link_new_instruction(cast_instruction, &call_instruction->base); |
| 3990 | return ir_finish_anal(ira, cast_instruction->type_entry); | 4237 | return ir_finish_anal(ira, cast_instruction->type_entry); |
| 3991 | } else if (fn_ref->type_entry->id == TypeTableEntryIdFn) { | 4238 | } else if (fn_ref->type_entry->id == TypeTableEntryIdFn) { |
| 3992 | // TODO fully port over the fn call analyze code to IR | 4239 | FnTableEntry *fn_table_entry = ir_resolve_fn(ira, fn_ref); |
| 3993 | FnTableEntry *fn_table_entry = fn_ref->static_value.data.x_fn; | 4240 | return ir_analyze_fn_call(ira, call_instruction, fn_table_entry, fn_table_entry->type_entry, |
| 3994 | TypeTableEntry *fn_type = fn_table_entry->type_entry; | 4241 | fn_ref, nullptr, is_inline); |
| 3995 | | 4242 | } else if (fn_ref->type_entry->id == TypeTableEntryIdBoundFn) { |
| 3996 | IrInstruction **casted_args = allocate<IrInstruction *>(call_instruction->arg_count); | 4243 | assert(fn_ref->static_value.special == ConstValSpecialStatic); |
| 3997 | for (size_t i = 0; i < call_instruction->arg_count; i += 1) { | 4244 | FnTableEntry *fn_table_entry = fn_ref->static_value.data.x_bound_fn.fn; |
| 3998 | TypeTableEntry *param_type = fn_type->data.fn.fn_type_id.param_info[i].type; | 4245 | IrInstruction *first_arg_ptr = fn_ref->static_value.data.x_bound_fn.first_arg; |
| 3999 | IrInstruction *old_arg = call_instruction->args[i]->other; | 4246 | return ir_analyze_fn_call(ira, call_instruction, fn_table_entry, fn_table_entry->type_entry, |
| 4000 | if (old_arg->type_entry->id == TypeTableEntryIdInvalid) | 4247 | nullptr, first_arg_ptr, is_inline); |
| 4001 | return ira->codegen->builtin_types.entry_invalid; | 4248 | } else if (fn_ref->type_entry->id == TypeTableEntryIdGenericFn) { |
| 4002 | casted_args[i] = ir_get_casted_value(ira, old_arg, param_type); | 4249 | zig_panic("TODO generic fn call"); |
| 4003 | } | | |
| 4004 | | | |
| 4005 | ir_build_call_from(&ira->new_irb, &call_instruction->base, | | |
| 4006 | fn_ref, call_instruction->arg_count, casted_args); | | |
| 4007 | | | |
| 4008 | return ir_finish_anal(ira, fn_type->data.fn.fn_type_id.return_type); | | |
| 4009 | } else { | 4250 | } else { |
| 4010 | zig_panic("TODO analyze more fn call types"); | 4251 | add_node_error(ira->codegen, fn_ref->source_node, |
| | 4252 | buf_sprintf("type '%s' not a function", buf_ptr(&fn_ref->type_entry->name))); |
| | 4253 | return ira->codegen->builtin_types.entry_invalid; |
| 4011 | } | 4254 | } |
| 4012 | } else { | 4255 | } |
| 4013 | //ir_build_call_from(&ira->new_irb, &call_instruction->base, | | |
| 4014 | // call_instruction->fn, call_instruction->arg_count, call_instruction->args); | | |
| 4015 | | 4256 | |
| 4016 | zig_panic("TODO analyze fn call"); | 4257 | if (fn_ref->type_entry->id == TypeTableEntryIdFn) { |
| | 4258 | return ir_analyze_fn_call(ira, call_instruction, nullptr, fn_ref->type_entry, |
| | 4259 | fn_ref, nullptr, false); |
| | 4260 | } else { |
| | 4261 | add_node_error(ira->codegen, fn_ref->source_node, |
| | 4262 | buf_sprintf("type '%s' not a function", buf_ptr(&fn_ref->type_entry->name))); |
| | 4263 | return ira->codegen->builtin_types.entry_invalid; |
| 4017 | } | 4264 | } |
| 4018 | } | 4265 | } |
| 4019 | | 4266 | |
| ... | @@ -4071,6 +4318,7 @@ static TypeTableEntry *ir_analyze_unary_prefix_op_err(IrAnalyze *ira, IrInstruct | ... | @@ -4071,6 +4318,7 @@ static TypeTableEntry *ir_analyze_unary_prefix_op_err(IrAnalyze *ira, IrInstruct |
| 4071 | case TypeTableEntryIdUnion: | 4318 | case TypeTableEntryIdUnion: |
| 4072 | case TypeTableEntryIdFn: | 4319 | case TypeTableEntryIdFn: |
| 4073 | case TypeTableEntryIdGenericFn: | 4320 | case TypeTableEntryIdGenericFn: |
| | 4321 | case TypeTableEntryIdBoundFn: |
| 4074 | { | 4322 | { |
| 4075 | ConstExprValue *out_val = ir_build_const_from(ira, &un_op_instruction->base, | 4323 | ConstExprValue *out_val = ir_build_const_from(ira, &un_op_instruction->base, |
| 4076 | value->static_value.depends_on_compile_var); | 4324 | value->static_value.depends_on_compile_var); |
| ... | @@ -4119,6 +4367,7 @@ static TypeTableEntry *ir_analyze_unary_address_of(IrAnalyze *ira, IrInstruction | ... | @@ -4119,6 +4367,7 @@ static TypeTableEntry *ir_analyze_unary_address_of(IrAnalyze *ira, IrInstruction |
| 4119 | case TypeTableEntryIdUnreachable: | 4367 | case TypeTableEntryIdUnreachable: |
| 4120 | case TypeTableEntryIdVar: | 4368 | case TypeTableEntryIdVar: |
| 4121 | case TypeTableEntryIdGenericFn: | 4369 | case TypeTableEntryIdGenericFn: |
| | 4370 | case TypeTableEntryIdBoundFn: |
| 4122 | add_node_error(ira->codegen, un_op_instruction->base.source_node, | 4371 | add_node_error(ira->codegen, un_op_instruction->base.source_node, |
| 4123 | buf_sprintf("unable to get address of type '%s'", buf_ptr(&target_type->name))); | 4372 | buf_sprintf("unable to get address of type '%s'", buf_ptr(&target_type->name))); |
| 4124 | // TODO if type decl, add note pointing to type decl declaration | 4373 | // TODO if type decl, add note pointing to type decl declaration |
| ... | @@ -4217,6 +4466,7 @@ static TypeTableEntry *ir_analyze_maybe(IrAnalyze *ira, IrInstructionUnOp *un_op | ... | @@ -4217,6 +4466,7 @@ static TypeTableEntry *ir_analyze_maybe(IrAnalyze *ira, IrInstructionUnOp *un_op |
| 4217 | case TypeTableEntryIdNamespace: | 4466 | case TypeTableEntryIdNamespace: |
| 4218 | case TypeTableEntryIdBlock: | 4467 | case TypeTableEntryIdBlock: |
| 4219 | case TypeTableEntryIdGenericFn: | 4468 | case TypeTableEntryIdGenericFn: |
| | 4469 | case TypeTableEntryIdBoundFn: |
| 4220 | { | 4470 | { |
| 4221 | ConstExprValue *out_val = ir_build_const_from(ira, &un_op_instruction->base, | 4471 | ConstExprValue *out_val = ir_build_const_from(ira, &un_op_instruction->base, |
| 4222 | value->static_value.depends_on_compile_var); | 4472 | value->static_value.depends_on_compile_var); |
| ... | @@ -4626,7 +4876,7 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc | ... | @@ -4626,7 +4876,7 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc |
| 4626 | | 4876 | |
| 4627 | static TypeTableEntry *ir_analyze_container_member_access_inner(IrAnalyze *ira, | 4877 | static TypeTableEntry *ir_analyze_container_member_access_inner(IrAnalyze *ira, |
| 4628 | TypeTableEntry *bare_struct_type, Buf *field_name, IrInstructionFieldPtr *field_ptr_instruction, | 4878 | TypeTableEntry *bare_struct_type, Buf *field_name, IrInstructionFieldPtr *field_ptr_instruction, |
| 4629 | TypeTableEntry *container_type) | 4879 | IrInstruction *container_ptr, TypeTableEntry *container_type) |
| 4630 | { | 4880 | { |
| 4631 | if (!is_slice(bare_struct_type)) { | 4881 | if (!is_slice(bare_struct_type)) { |
| 4632 | BlockContext *container_block_context = get_container_block_context(bare_struct_type); | 4882 | BlockContext *container_block_context = get_container_block_context(bare_struct_type); |
| ... | @@ -4634,7 +4884,15 @@ static TypeTableEntry *ir_analyze_container_member_access_inner(IrAnalyze *ira, | ... | @@ -4634,7 +4884,15 @@ static TypeTableEntry *ir_analyze_container_member_access_inner(IrAnalyze *ira, |
| 4634 | auto entry = container_block_context->decl_table.maybe_get(field_name); | 4884 | auto entry = container_block_context->decl_table.maybe_get(field_name); |
| 4635 | AstNode *fn_decl_node = entry ? entry->value : nullptr; | 4885 | AstNode *fn_decl_node = entry ? entry->value : nullptr; |
| 4636 | if (fn_decl_node && fn_decl_node->type == NodeTypeFnProto) { | 4886 | if (fn_decl_node && fn_decl_node->type == NodeTypeFnProto) { |
| 4637 | zig_panic("TODO member function call"); | 4887 | resolve_top_level_decl(ira->codegen, fn_decl_node, false); |
| | 4888 | TopLevelDecl *tld = get_as_top_level_decl(fn_decl_node); |
| | 4889 | if (tld->resolution == TldResolutionInvalid) |
| | 4890 | return ira->codegen->builtin_types.entry_invalid; |
| | 4891 | FnTableEntry *fn_entry = fn_decl_node->data.fn_proto.fn_table_entry; |
| | 4892 | bool depends_on_compile_var = container_ptr->static_value.depends_on_compile_var; |
| | 4893 | IrInstruction *bound_fn_value = ir_build_const_bound_fn(&ira->new_irb, |
| | 4894 | field_ptr_instruction->base.source_node, fn_entry, container_ptr, depends_on_compile_var); |
| | 4895 | return ir_analyze_ref(ira, &field_ptr_instruction->base, bound_fn_value); |
| 4638 | } | 4896 | } |
| 4639 | } | 4897 | } |
| 4640 | add_node_error(ira->codegen, field_ptr_instruction->base.source_node, | 4898 | add_node_error(ira->codegen, field_ptr_instruction->base.source_node, |
| ... | @@ -4643,14 +4901,12 @@ static TypeTableEntry *ir_analyze_container_member_access_inner(IrAnalyze *ira, | ... | @@ -4643,14 +4901,12 @@ static TypeTableEntry *ir_analyze_container_member_access_inner(IrAnalyze *ira, |
| 4643 | } | 4901 | } |
| 4644 | | 4902 | |
| 4645 | | 4903 | |
| 4646 | static TypeTableEntry *ir_analyze_container_member_access(IrAnalyze *ira, Buf *field_name, | 4904 | static TypeTableEntry *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_name, |
| 4647 | IrInstructionFieldPtr *field_ptr_instruction, TypeTableEntry *container_type) | 4905 | IrInstructionFieldPtr *field_ptr_instruction, IrInstruction *container_ptr, TypeTableEntry *container_type) |
| 4648 | { | 4906 | { |
| 4649 | IrInstruction *container_ptr = field_ptr_instruction->container_ptr->other; | | |
| 4650 | TypeTableEntry *bare_type = container_ref_type(container_type); | 4907 | TypeTableEntry *bare_type = container_ref_type(container_type); |
| 4651 | if (!type_is_complete(bare_type)) { | 4908 | if (!type_is_complete(bare_type)) |
| 4652 | resolve_container_type(ira->codegen, bare_type); | 4909 | resolve_container_type(ira->codegen, bare_type); |
| 4653 | } | | |
| 4654 | | 4910 | |
| 4655 | if (bare_type->id == TypeTableEntryIdStruct) { | 4911 | if (bare_type->id == TypeTableEntryIdStruct) { |
| 4656 | TypeStructField *field = find_struct_type_field(bare_type, field_name); | 4912 | TypeStructField *field = find_struct_type_field(bare_type, field_name); |
| ... | @@ -4659,10 +4915,17 @@ static TypeTableEntry *ir_analyze_container_member_access(IrAnalyze *ira, Buf *f | ... | @@ -4659,10 +4915,17 @@ static TypeTableEntry *ir_analyze_container_member_access(IrAnalyze *ira, Buf *f |
| 4659 | return get_pointer_to_type(ira->codegen, field->type_entry, false); | 4915 | return get_pointer_to_type(ira->codegen, field->type_entry, false); |
| 4660 | } else { | 4916 | } else { |
| 4661 | return ir_analyze_container_member_access_inner(ira, bare_type, field_name, | 4917 | return ir_analyze_container_member_access_inner(ira, bare_type, field_name, |
| 4662 | field_ptr_instruction, container_type); | 4918 | field_ptr_instruction, container_ptr, container_type); |
| 4663 | } | 4919 | } |
| 4664 | } else if (bare_type->id == TypeTableEntryIdEnum) { | 4920 | } else if (bare_type->id == TypeTableEntryIdEnum) { |
| 4665 | zig_panic("TODO enum field ptr"); | 4921 | TypeEnumField *field = find_enum_type_field(bare_type, field_name); |
| | 4922 | if (field) { |
| | 4923 | ir_build_enum_field_ptr_from(&ira->new_irb, &field_ptr_instruction->base, container_ptr, field); |
| | 4924 | return get_pointer_to_type(ira->codegen, field->type_entry, false); |
| | 4925 | } else { |
| | 4926 | return ir_analyze_container_member_access_inner(ira, bare_type, field_name, |
| | 4927 | field_ptr_instruction, container_ptr, container_type); |
| | 4928 | } |
| 4666 | } else if (bare_type->id == TypeTableEntryIdUnion) { | 4929 | } else if (bare_type->id == TypeTableEntryIdUnion) { |
| 4667 | zig_panic("TODO"); | 4930 | zig_panic("TODO"); |
| 4668 | } else { | 4931 | } else { |
| ... | @@ -4733,7 +4996,7 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru | ... | @@ -4733,7 +4996,7 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru |
| 4733 | if (container_type->id == TypeTableEntryIdInvalid) { | 4996 | if (container_type->id == TypeTableEntryIdInvalid) { |
| 4734 | return container_type; | 4997 | return container_type; |
| 4735 | } else if (is_container_ref(container_type)) { | 4998 | } else if (is_container_ref(container_type)) { |
| 4736 | return ir_analyze_container_member_access(ira, field_name, field_ptr_instruction, container_type); | 4999 | return ir_analyze_container_field_ptr(ira, field_name, field_ptr_instruction, container_ptr, container_type); |
| 4737 | } else if (container_type->id == TypeTableEntryIdArray) { | 5000 | } else if (container_type->id == TypeTableEntryIdArray) { |
| 4738 | if (buf_eql_str(field_name, "len")) { | 5001 | if (buf_eql_str(field_name, "len")) { |
| 4739 | ConstExprValue *len_val = allocate<ConstExprValue>(1); | 5002 | ConstExprValue *len_val = allocate<ConstExprValue>(1); |
| ... | @@ -4749,24 +5012,38 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru | ... | @@ -4749,24 +5012,38 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru |
| 4749 | return ira->codegen->builtin_types.entry_invalid; | 5012 | return ira->codegen->builtin_types.entry_invalid; |
| 4750 | } | 5013 | } |
| 4751 | } else if (container_type->id == TypeTableEntryIdMetaType) { | 5014 | } else if (container_type->id == TypeTableEntryIdMetaType) { |
| 4752 | zig_panic("TODO type field access"); | 5015 | ConstExprValue *container_ptr_val = ir_resolve_const(ira, container_ptr); |
| 4753 | //TypeTableEntry *child_type = ir_resolve_type(ira, container_ptr); | 5016 | if (!container_ptr_val) |
| 4754 | | 5017 | return ira->codegen->builtin_types.entry_invalid; |
| 4755 | //if (child_type->id == TypeTableEntryIdInvalid) { | 5018 | ConstExprValue *child_val = const_ptr_pointee(container_ptr_val); |
| 4756 | // return ira->codegen->builtin_types.entry_invalid; | 5019 | TypeTableEntry *child_type = child_val->data.x_type; |
| 4757 | //} else if (child_type->id == TypeTableEntryIdEnum) { | 5020 | |
| 4758 | // zig_panic("TODO enum type field"); | 5021 | if (child_type->id == TypeTableEntryIdInvalid) { |
| 4759 | //} else if (child_type->id == TypeTableEntryIdStruct) { | 5022 | return ira->codegen->builtin_types.entry_invalid; |
| 4760 | // zig_panic("TODO struct type field"); | 5023 | } else if (child_type->id == TypeTableEntryIdEnum) { |
| 4761 | //} else if (child_type->id == TypeTableEntryIdPureError) { | 5024 | zig_panic("TODO enum type field"); |
| 4762 | // zig_panic("TODO error type field"); | 5025 | } else if (child_type->id == TypeTableEntryIdStruct) { |
| 4763 | //} else if (child_type->id == TypeTableEntryIdInt) { | 5026 | BlockContext *container_block_context = get_container_block_context(child_type); |
| 4764 | // zig_panic("TODO integer type field"); | 5027 | auto entry = container_block_context->decl_table.maybe_get(field_name); |
| 4765 | //} else { | 5028 | AstNode *decl_node = entry ? entry->value : nullptr; |
| 4766 | // add_node_error(ira->codegen, source_node, | 5029 | if (decl_node) { |
| 4767 | // buf_sprintf("type '%s' does not support field access", buf_ptr(&container_type->name))); | 5030 | bool depends_on_compile_var = container_ptr->static_value.depends_on_compile_var; |
| 4768 | // return ira->codegen->builtin_types.entry_invalid; | 5031 | return ir_analyze_decl_ref(ira, &field_ptr_instruction->base, decl_node, depends_on_compile_var); |
| 4769 | //} | 5032 | } else { |
| | 5033 | add_node_error(ira->codegen, source_node, |
| | 5034 | buf_sprintf("container '%s' has no member called '%s'", |
| | 5035 | buf_ptr(&child_type->name), buf_ptr(field_name))); |
| | 5036 | return ira->codegen->builtin_types.entry_invalid; |
| | 5037 | } |
| | 5038 | } else if (child_type->id == TypeTableEntryIdPureError) { |
| | 5039 | zig_panic("TODO error type field"); |
| | 5040 | } else if (child_type->id == TypeTableEntryIdInt) { |
| | 5041 | zig_panic("TODO integer type field"); |
| | 5042 | } else { |
| | 5043 | add_node_error(ira->codegen, source_node, |
| | 5044 | buf_sprintf("type '%s' does not support field access", buf_ptr(&container_type->name))); |
| | 5045 | return ira->codegen->builtin_types.entry_invalid; |
| | 5046 | } |
| 4770 | } else if (container_type->id == TypeTableEntryIdNamespace) { | 5047 | } else if (container_type->id == TypeTableEntryIdNamespace) { |
| 4771 | ConstExprValue *container_ptr_val = ir_resolve_const(ira, container_ptr); | 5048 | ConstExprValue *container_ptr_val = ir_resolve_const(ira, container_ptr); |
| 4772 | if (!container_ptr_val) | 5049 | if (!container_ptr_val) |
| ... | @@ -4817,28 +5094,10 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru | ... | @@ -4817,28 +5094,10 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru |
| 4817 | | 5094 | |
| 4818 | static TypeTableEntry *ir_analyze_instruction_load_ptr(IrAnalyze *ira, IrInstructionLoadPtr *load_ptr_instruction) { | 5095 | static TypeTableEntry *ir_analyze_instruction_load_ptr(IrAnalyze *ira, IrInstructionLoadPtr *load_ptr_instruction) { |
| 4819 | IrInstruction *ptr = load_ptr_instruction->ptr->other; | 5096 | IrInstruction *ptr = load_ptr_instruction->ptr->other; |
| 4820 | TypeTableEntry *type_entry = ptr->type_entry; | 5097 | IrInstruction *result = ir_get_deref(ira, &load_ptr_instruction->base, ptr); |
| 4821 | if (type_entry->id == TypeTableEntryIdInvalid) { | 5098 | ir_link_new_instruction(result, &load_ptr_instruction->base); |
| 4822 | return type_entry; | 5099 | assert(result->type_entry); |
| 4823 | } else if (type_entry->id == TypeTableEntryIdPointer) { | 5100 | return result->type_entry; |
| 4824 | TypeTableEntry *child_type = type_entry->data.pointer.child_type; | | |
| 4825 | if (ptr->static_value.special != ConstValSpecialRuntime) { | | |
| 4826 | ConstExprValue *pointee = const_ptr_pointee(&ptr->static_value); | | |
| 4827 | if (pointee->special != ConstValSpecialRuntime) { | | |
| 4828 | ConstExprValue *out_val = ir_build_const_from(ira, &load_ptr_instruction->base, | | |
| 4829 | pointee->depends_on_compile_var); | | |
| 4830 | *out_val = *pointee; | | |
| 4831 | return child_type; | | |
| 4832 | } | | |
| 4833 | } | | |
| 4834 | ir_build_load_ptr_from(&ira->new_irb, &load_ptr_instruction->base, ptr); | | |
| 4835 | return child_type; | | |
| 4836 | } else { | | |
| 4837 | add_node_error(ira->codegen, load_ptr_instruction->base.source_node, | | |
| 4838 | buf_sprintf("attempt to dereference non pointer type '%s'", | | |
| 4839 | buf_ptr(&type_entry->name))); | | |
| 4840 | return ira->codegen->builtin_types.entry_invalid; | | |
| 4841 | } | | |
| 4842 | } | 5101 | } |
| 4843 | | 5102 | |
| 4844 | static TypeTableEntry *ir_analyze_instruction_store_ptr(IrAnalyze *ira, IrInstructionStorePtr *store_ptr_instruction) { | 5103 | static TypeTableEntry *ir_analyze_instruction_store_ptr(IrAnalyze *ira, IrInstructionStorePtr *store_ptr_instruction) { |
| ... | @@ -4911,6 +5170,7 @@ static TypeTableEntry *ir_analyze_instruction_typeof(IrAnalyze *ira, IrInstructi | ... | @@ -4911,6 +5170,7 @@ static TypeTableEntry *ir_analyze_instruction_typeof(IrAnalyze *ira, IrInstructi |
| 4911 | case TypeTableEntryIdNamespace: | 5170 | case TypeTableEntryIdNamespace: |
| 4912 | case TypeTableEntryIdBlock: | 5171 | case TypeTableEntryIdBlock: |
| 4913 | case TypeTableEntryIdGenericFn: | 5172 | case TypeTableEntryIdGenericFn: |
| | 5173 | case TypeTableEntryIdBoundFn: |
| 4914 | case TypeTableEntryIdMetaType: | 5174 | case TypeTableEntryIdMetaType: |
| 4915 | case TypeTableEntryIdVoid: | 5175 | case TypeTableEntryIdVoid: |
| 4916 | case TypeTableEntryIdBool: | 5176 | case TypeTableEntryIdBool: |
| ... | @@ -5148,6 +5408,7 @@ static TypeTableEntry *ir_analyze_instruction_slice_type(IrAnalyze *ira, | ... | @@ -5148,6 +5408,7 @@ static TypeTableEntry *ir_analyze_instruction_slice_type(IrAnalyze *ira, |
| 5148 | case TypeTableEntryIdFn: | 5408 | case TypeTableEntryIdFn: |
| 5149 | case TypeTableEntryIdNamespace: | 5409 | case TypeTableEntryIdNamespace: |
| 5150 | case TypeTableEntryIdGenericFn: | 5410 | case TypeTableEntryIdGenericFn: |
| | 5411 | case TypeTableEntryIdBoundFn: |
| 5151 | { | 5412 | { |
| 5152 | TypeTableEntry *result_type = get_slice_type(ira->codegen, resolved_child_type, is_const); | 5413 | TypeTableEntry *result_type = get_slice_type(ira->codegen, resolved_child_type, is_const); |
| 5153 | ConstExprValue *out_val = ir_build_const_from(ira, &slice_type_instruction->base, | 5414 | ConstExprValue *out_val = ir_build_const_from(ira, &slice_type_instruction->base, |
| ... | @@ -5161,8 +5422,9 @@ static TypeTableEntry *ir_analyze_instruction_slice_type(IrAnalyze *ira, | ... | @@ -5161,8 +5422,9 @@ static TypeTableEntry *ir_analyze_instruction_slice_type(IrAnalyze *ira, |
| 5161 | | 5422 | |
| 5162 | static TypeTableEntry *ir_analyze_instruction_asm(IrAnalyze *ira, IrInstructionAsm *asm_instruction) { | 5423 | static TypeTableEntry *ir_analyze_instruction_asm(IrAnalyze *ira, IrInstructionAsm *asm_instruction) { |
| 5163 | assert(asm_instruction->base.source_node->type == NodeTypeAsmExpr); | 5424 | assert(asm_instruction->base.source_node->type == NodeTypeAsmExpr); |
| 5164 | mark_impure_fn(ira->codegen, asm_instruction->base.source_node->block_context, | 5425 | |
| 5165 | asm_instruction->base.source_node); | 5426 | if (!ir_emit_global_runtime_side_effect(ira, &asm_instruction->base)) |
| | 5427 | return ira->codegen->builtin_types.entry_invalid; |
| 5166 | | 5428 | |
| 5167 | // TODO validate the output types and variable types | 5429 | // TODO validate the output types and variable types |
| 5168 | | 5430 | |
| ... | @@ -5236,6 +5498,7 @@ static TypeTableEntry *ir_analyze_instruction_array_type(IrAnalyze *ira, | ... | @@ -5236,6 +5498,7 @@ static TypeTableEntry *ir_analyze_instruction_array_type(IrAnalyze *ira, |
| 5236 | case TypeTableEntryIdFn: | 5498 | case TypeTableEntryIdFn: |
| 5237 | case TypeTableEntryIdNamespace: | 5499 | case TypeTableEntryIdNamespace: |
| 5238 | case TypeTableEntryIdGenericFn: | 5500 | case TypeTableEntryIdGenericFn: |
| | 5501 | case TypeTableEntryIdBoundFn: |
| 5239 | { | 5502 | { |
| 5240 | TypeTableEntry *result_type = get_array_type(ira->codegen, child_type, size); | 5503 | TypeTableEntry *result_type = get_array_type(ira->codegen, child_type, size); |
| 5241 | bool depends_on_compile_var = child_type_value->static_value.depends_on_compile_var || | 5504 | bool depends_on_compile_var = child_type_value->static_value.depends_on_compile_var || |
| ... | @@ -5306,6 +5569,7 @@ static TypeTableEntry *ir_analyze_instruction_size_of(IrAnalyze *ira, | ... | @@ -5306,6 +5569,7 @@ static TypeTableEntry *ir_analyze_instruction_size_of(IrAnalyze *ira, |
| 5306 | case TypeTableEntryIdNumLitFloat: | 5569 | case TypeTableEntryIdNumLitFloat: |
| 5307 | case TypeTableEntryIdNumLitInt: | 5570 | case TypeTableEntryIdNumLitInt: |
| 5308 | case TypeTableEntryIdGenericFn: | 5571 | case TypeTableEntryIdGenericFn: |
| | 5572 | case TypeTableEntryIdBoundFn: |
| 5309 | case TypeTableEntryIdMetaType: | 5573 | case TypeTableEntryIdMetaType: |
| 5310 | case TypeTableEntryIdFn: | 5574 | case TypeTableEntryIdFn: |
| 5311 | case TypeTableEntryIdNamespace: | 5575 | case TypeTableEntryIdNamespace: |
| ... | @@ -5469,7 +5733,7 @@ static TypeTableEntry *ir_analyze_instruction_switch_br(IrAnalyze *ira, | ... | @@ -5469,7 +5733,7 @@ static TypeTableEntry *ir_analyze_instruction_switch_br(IrAnalyze *ira, |
| 5469 | return ir_unreach_error(ira); | 5733 | return ir_unreach_error(ira); |
| 5470 | | 5734 | |
| 5471 | size_t case_count = switch_br_instruction->case_count; | 5735 | size_t case_count = switch_br_instruction->case_count; |
| 5472 | bool is_inline = switch_br_instruction->is_inline; | 5736 | bool is_inline = ir_should_inline(&ira->new_irb) || switch_br_instruction->is_inline; |
| 5473 | | 5737 | |
| 5474 | if (is_inline || target_value->static_value.special != ConstValSpecialRuntime) { | 5738 | if (is_inline || target_value->static_value.special != ConstValSpecialRuntime) { |
| 5475 | ConstExprValue *target_val = ir_resolve_const(ira, target_value); | 5739 | ConstExprValue *target_val = ir_resolve_const(ira, target_value); |
| ... | @@ -5599,6 +5863,7 @@ static TypeTableEntry *ir_analyze_instruction_switch_target(IrAnalyze *ira, | ... | @@ -5599,6 +5863,7 @@ static TypeTableEntry *ir_analyze_instruction_switch_target(IrAnalyze *ira, |
| 5599 | case TypeTableEntryIdUnion: | 5863 | case TypeTableEntryIdUnion: |
| 5600 | case TypeTableEntryIdBlock: | 5864 | case TypeTableEntryIdBlock: |
| 5601 | case TypeTableEntryIdGenericFn: | 5865 | case TypeTableEntryIdGenericFn: |
| | 5866 | case TypeTableEntryIdBoundFn: |
| 5602 | add_node_error(ira->codegen, switch_target_instruction->base.source_node, | 5867 | add_node_error(ira->codegen, switch_target_instruction->base.source_node, |
| 5603 | buf_sprintf("invalid switch target type '%s'", buf_ptr(&target_type->name))); | 5868 | buf_sprintf("invalid switch target type '%s'", buf_ptr(&target_type->name))); |
| 5604 | // TODO if this is a typedecl, add error note showing the declaration of the type decl | 5869 | // TODO if this is a typedecl, add error note showing the declaration of the type decl |
| ... | @@ -5741,51 +6006,222 @@ static TypeTableEntry *ir_analyze_instruction_array_len(IrAnalyze *ira, | ... | @@ -5741,51 +6006,222 @@ static TypeTableEntry *ir_analyze_instruction_array_len(IrAnalyze *ira, |
| 5741 | | 6006 | |
| 5742 | static TypeTableEntry *ir_analyze_instruction_ref(IrAnalyze *ira, IrInstructionRef *ref_instruction) { | 6007 | static TypeTableEntry *ir_analyze_instruction_ref(IrAnalyze *ira, IrInstructionRef *ref_instruction) { |
| 5743 | IrInstruction *value = ref_instruction->value->other; | 6008 | IrInstruction *value = ref_instruction->value->other; |
| 5744 | if (value->type_entry->id == TypeTableEntryIdInvalid) | 6009 | return ir_analyze_ref(ira, &ref_instruction->base, value); |
| 5745 | return ira->codegen->builtin_types.entry_invalid; | 6010 | } |
| 5746 | | 6011 | |
| 5747 | FnTableEntry *fn_entry = ref_instruction->base.source_node->block_context->fn_entry; | 6012 | static TypeTableEntry *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruction *instruction, |
| 5748 | if (!fn_entry || value->static_value.special != ConstValSpecialRuntime) { | 6013 | TypeTableEntry *container_type, size_t instr_field_count, IrInstructionContainerInitFieldsField *fields, |
| 5749 | ConstExprValue *val = ir_resolve_const(ira, value); | 6014 | bool depends_on_compile_var) |
| 5750 | if (!val) | 6015 | { |
| | 6016 | size_t actual_field_count = container_type->data.structure.src_field_count; |
| | 6017 | |
| | 6018 | IrInstruction *first_non_const_instruction = nullptr; |
| | 6019 | |
| | 6020 | AstNode **field_assign_nodes = allocate<AstNode *>(actual_field_count); |
| | 6021 | |
| | 6022 | IrInstructionStructInitField *new_fields = allocate<IrInstructionStructInitField>(actual_field_count); |
| | 6023 | |
| | 6024 | FnTableEntry *fn_entry = instruction->source_node->block_context->fn_entry; |
| | 6025 | bool outside_fn = (fn_entry == nullptr); |
| | 6026 | |
| | 6027 | ConstExprValue const_val = {}; |
| | 6028 | const_val.special = ConstValSpecialStatic; |
| | 6029 | const_val.depends_on_compile_var = depends_on_compile_var; |
| | 6030 | const_val.data.x_struct.fields = allocate<ConstExprValue>(actual_field_count); |
| | 6031 | for (size_t i = 0; i < instr_field_count; i += 1) { |
| | 6032 | IrInstructionContainerInitFieldsField *field = &fields[i]; |
| | 6033 | |
| | 6034 | IrInstruction *field_value = field->value->other; |
| | 6035 | if (field_value->type_entry->id == TypeTableEntryIdInvalid) |
| | 6036 | return ira->codegen->builtin_types.entry_invalid; |
| | 6037 | |
| | 6038 | TypeStructField *type_field = find_struct_type_field(container_type, field->name); |
| | 6039 | if (!type_field) { |
| | 6040 | add_node_error(ira->codegen, field->source_node, |
| | 6041 | buf_sprintf("no member named '%s' in '%s'", |
| | 6042 | buf_ptr(field->name), buf_ptr(&container_type->name))); |
| | 6043 | return ira->codegen->builtin_types.entry_invalid; |
| | 6044 | } |
| | 6045 | |
| | 6046 | if (type_field->type_entry->id == TypeTableEntryIdInvalid) |
| 5751 | return ira->codegen->builtin_types.entry_invalid; | 6047 | return ira->codegen->builtin_types.entry_invalid; |
| 5752 | return ir_analyze_const_ptr(ira, &ref_instruction->base, val, value->type_entry, false); | 6048 | |
| | 6049 | size_t field_index = type_field->src_index; |
| | 6050 | AstNode *existing_assign_node = field_assign_nodes[field_index]; |
| | 6051 | if (existing_assign_node) { |
| | 6052 | ErrorMsg *msg = add_node_error(ira->codegen, field->source_node, buf_sprintf("duplicate field")); |
| | 6053 | add_error_note(ira->codegen, msg, existing_assign_node, buf_sprintf("other field here")); |
| | 6054 | continue; |
| | 6055 | } |
| | 6056 | field_assign_nodes[field_index] = field->source_node; |
| | 6057 | |
| | 6058 | new_fields[field_index].value = field_value; |
| | 6059 | new_fields[field_index].type_struct_field = type_field; |
| | 6060 | |
| | 6061 | if (const_val.special == ConstValSpecialStatic) { |
| | 6062 | if (outside_fn || field_value->static_value.special != ConstValSpecialRuntime) { |
| | 6063 | ConstExprValue *field_val = ir_resolve_const(ira, field_value); |
| | 6064 | if (!field_val) |
| | 6065 | return ira->codegen->builtin_types.entry_invalid; |
| | 6066 | |
| | 6067 | const_val.data.x_struct.fields[field_index] = *field_val; |
| | 6068 | const_val.depends_on_compile_var = const_val.depends_on_compile_var || field_val->depends_on_compile_var; |
| | 6069 | } else { |
| | 6070 | first_non_const_instruction = field_value; |
| | 6071 | const_val.special = ConstValSpecialRuntime; |
| | 6072 | } |
| | 6073 | } |
| 5753 | } | 6074 | } |
| 5754 | | 6075 | |
| 5755 | TypeTableEntry *ptr_type = get_pointer_to_type(ira->codegen, value->type_entry, true); | 6076 | bool any_missing = false; |
| 5756 | if (handle_is_ptr(value->type_entry)) { | 6077 | for (size_t i = 0; i < actual_field_count; i += 1) { |
| 5757 | // this instruction is a noop - codegen can pass the pointer we already have as the result | 6078 | if (!field_assign_nodes[i]) { |
| 5758 | ir_link_new_instruction(value, &ref_instruction->base); | 6079 | add_node_error(ira->codegen, instruction->source_node, |
| 5759 | return ptr_type; | 6080 | buf_sprintf("missing field: '%s'", buf_ptr(container_type->data.structure.fields[i].name))); |
| 5760 | } else { | 6081 | any_missing = true; |
| 5761 | fn_entry->alloca_list.append(&ref_instruction->base); | 6082 | } |
| 5762 | ir_build_ref_from(&ira->new_irb, &ref_instruction->base, value); | 6083 | } |
| 5763 | return ptr_type; | 6084 | if (any_missing) |
| | 6085 | return ira->codegen->builtin_types.entry_invalid; |
| | 6086 | |
| | 6087 | if (const_val.special == ConstValSpecialStatic) { |
| | 6088 | ConstExprValue *out_val = ir_build_const_from(ira, instruction, const_val.depends_on_compile_var); |
| | 6089 | *out_val = const_val; |
| | 6090 | return container_type; |
| | 6091 | } |
| | 6092 | |
| | 6093 | if (outside_fn) { |
| | 6094 | add_node_error(ira->codegen, first_non_const_instruction->source_node, |
| | 6095 | buf_sprintf("unable to evaluate constant expression")); |
| | 6096 | return ira->codegen->builtin_types.entry_invalid; |
| 5764 | } | 6097 | } |
| | 6098 | |
| | 6099 | IrInstruction *new_instruction = ir_build_struct_init_from(&ira->new_irb, instruction, |
| | 6100 | container_type, actual_field_count, new_fields); |
| | 6101 | fn_entry->alloca_list.append(new_instruction); |
| | 6102 | return container_type; |
| 5765 | } | 6103 | } |
| 5766 | | 6104 | |
| 5767 | static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) { | 6105 | static TypeTableEntry *ir_analyze_instruction_container_init_list(IrAnalyze *ira, IrInstructionContainerInitList *instruction) { |
| 5768 | switch (instruction->id) { | 6106 | IrInstruction *container_type_value = instruction->container_type->other; |
| 5769 | case IrInstructionIdInvalid: | 6107 | TypeTableEntry *container_type = ir_resolve_type(ira, container_type_value); |
| 5770 | zig_unreachable(); | 6108 | if (!container_type) |
| 5771 | case IrInstructionIdReturn: | 6109 | return ira->codegen->builtin_types.entry_invalid; |
| 5772 | return ir_analyze_instruction_return(ira, (IrInstructionReturn *)instruction); | 6110 | |
| 5773 | case IrInstructionIdConst: | 6111 | size_t elem_count = instruction->item_count; |
| 5774 | return ir_analyze_instruction_const(ira, (IrInstructionConst *)instruction); | 6112 | bool depends_on_compile_var = container_type_value->static_value.depends_on_compile_var; |
| 5775 | case IrInstructionIdUnOp: | 6113 | |
| 5776 | return ir_analyze_instruction_un_op(ira, (IrInstructionUnOp *)instruction); | 6114 | if (container_type->id == TypeTableEntryIdStruct && !is_slice(container_type) && elem_count == 0) { |
| 5777 | case IrInstructionIdBinOp: | 6115 | return ir_analyze_container_init_fields(ira, &instruction->base, container_type, 0, nullptr, depends_on_compile_var); |
| 5778 | return ir_analyze_instruction_bin_op(ira, (IrInstructionBinOp *)instruction); | 6116 | } else if (is_slice(container_type)) { |
| 5779 | case IrInstructionIdDeclVar: | 6117 | TypeTableEntry *pointer_type = container_type->data.structure.fields[slice_ptr_index].type_entry; |
| 5780 | return ir_analyze_instruction_decl_var(ira, (IrInstructionDeclVar *)instruction); | 6118 | assert(pointer_type->id == TypeTableEntryIdPointer); |
| 5781 | case IrInstructionIdLoadPtr: | 6119 | TypeTableEntry *child_type = pointer_type->data.pointer.child_type; |
| 5782 | return ir_analyze_instruction_load_ptr(ira, (IrInstructionLoadPtr *)instruction); | 6120 | |
| 5783 | case IrInstructionIdStorePtr: | 6121 | ConstExprValue const_val = {}; |
| 5784 | return ir_analyze_instruction_store_ptr(ira, (IrInstructionStorePtr *)instruction); | 6122 | const_val.special = ConstValSpecialStatic; |
| 5785 | case IrInstructionIdElemPtr: | 6123 | const_val.depends_on_compile_var = depends_on_compile_var; |
| 5786 | return ir_analyze_instruction_elem_ptr(ira, (IrInstructionElemPtr *)instruction); | 6124 | const_val.data.x_array.elements = allocate<ConstExprValue>(elem_count); |
| 5787 | case IrInstructionIdVarPtr: | 6125 | const_val.data.x_array.size = elem_count; |
| 5788 | return ir_analyze_instruction_var_ptr(ira, (IrInstructionVarPtr *)instruction); | 6126 | |
| | 6127 | FnTableEntry *fn_entry = instruction->base.source_node->block_context->fn_entry; |
| | 6128 | bool outside_fn = (fn_entry == nullptr); |
| | 6129 | |
| | 6130 | IrInstruction **new_items = allocate<IrInstruction *>(elem_count); |
| | 6131 | |
| | 6132 | IrInstruction *first_non_const_instruction = nullptr; |
| | 6133 | |
| | 6134 | for (size_t i = 0; i < elem_count; i += 1) { |
| | 6135 | IrInstruction *arg_value = instruction->items[i]->other; |
| | 6136 | if (arg_value->type_entry->id == TypeTableEntryIdInvalid) |
| | 6137 | return ira->codegen->builtin_types.entry_invalid; |
| | 6138 | |
| | 6139 | new_items[i] = arg_value; |
| | 6140 | |
| | 6141 | if (const_val.special == ConstValSpecialStatic) { |
| | 6142 | if (outside_fn || arg_value->static_value.special != ConstValSpecialRuntime) { |
| | 6143 | ConstExprValue *elem_val = ir_resolve_const(ira, arg_value); |
| | 6144 | if (!elem_val) |
| | 6145 | return ira->codegen->builtin_types.entry_invalid; |
| | 6146 | |
| | 6147 | const_val.data.x_array.elements[i] = *elem_val; |
| | 6148 | const_val.depends_on_compile_var = const_val.depends_on_compile_var || elem_val->depends_on_compile_var; |
| | 6149 | } else { |
| | 6150 | first_non_const_instruction = arg_value; |
| | 6151 | const_val.special = ConstValSpecialRuntime; |
| | 6152 | } |
| | 6153 | } |
| | 6154 | } |
| | 6155 | |
| | 6156 | TypeTableEntry *fixed_size_array_type = get_array_type(ira->codegen, child_type, elem_count); |
| | 6157 | if (const_val.special == ConstValSpecialStatic) { |
| | 6158 | ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base, const_val.depends_on_compile_var); |
| | 6159 | *out_val = const_val; |
| | 6160 | return fixed_size_array_type; |
| | 6161 | } |
| | 6162 | |
| | 6163 | if (outside_fn) { |
| | 6164 | add_node_error(ira->codegen, first_non_const_instruction->source_node, |
| | 6165 | buf_sprintf("unable to evaluate constant expression")); |
| | 6166 | return ira->codegen->builtin_types.entry_invalid; |
| | 6167 | } |
| | 6168 | |
| | 6169 | IrInstruction *new_instruction = ir_build_container_init_list_from(&ira->new_irb, &instruction->base, |
| | 6170 | container_type_value, elem_count, new_items); |
| | 6171 | fn_entry->alloca_list.append(new_instruction); |
| | 6172 | return fixed_size_array_type; |
| | 6173 | } else if (container_type->id == TypeTableEntryIdArray) { |
| | 6174 | // same as slice init but we make a compile error if the length is wrong |
| | 6175 | zig_panic("TODO array container init"); |
| | 6176 | } else if (container_type->id == TypeTableEntryIdVoid) { |
| | 6177 | if (elem_count != 0) { |
| | 6178 | add_node_error(ira->codegen, instruction->base.source_node, |
| | 6179 | buf_sprintf("void expression expects no arguments")); |
| | 6180 | return ira->codegen->builtin_types.entry_invalid; |
| | 6181 | } |
| | 6182 | return ir_analyze_void(ira, &instruction->base); |
| | 6183 | } else { |
| | 6184 | add_node_error(ira->codegen, instruction->base.source_node, |
| | 6185 | buf_sprintf("type '%s' does not support array initialization", |
| | 6186 | buf_ptr(&container_type->name))); |
| | 6187 | return ira->codegen->builtin_types.entry_invalid; |
| | 6188 | } |
| | 6189 | } |
| | 6190 | |
| | 6191 | static TypeTableEntry *ir_analyze_instruction_container_init_fields(IrAnalyze *ira, IrInstructionContainerInitFields *instruction) { |
| | 6192 | IrInstruction *container_type_value = instruction->container_type->other; |
| | 6193 | TypeTableEntry *container_type = ir_resolve_type(ira, container_type_value); |
| | 6194 | if (!container_type) |
| | 6195 | return ira->codegen->builtin_types.entry_invalid; |
| | 6196 | |
| | 6197 | bool depends_on_compile_var = container_type_value->static_value.depends_on_compile_var; |
| | 6198 | |
| | 6199 | return ir_analyze_container_init_fields(ira, &instruction->base, container_type, |
| | 6200 | instruction->field_count, instruction->fields, depends_on_compile_var); |
| | 6201 | } |
| | 6202 | |
| | 6203 | static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) { |
| | 6204 | switch (instruction->id) { |
| | 6205 | case IrInstructionIdInvalid: |
| | 6206 | zig_unreachable(); |
| | 6207 | case IrInstructionIdReturn: |
| | 6208 | return ir_analyze_instruction_return(ira, (IrInstructionReturn *)instruction); |
| | 6209 | case IrInstructionIdConst: |
| | 6210 | return ir_analyze_instruction_const(ira, (IrInstructionConst *)instruction); |
| | 6211 | case IrInstructionIdUnOp: |
| | 6212 | return ir_analyze_instruction_un_op(ira, (IrInstructionUnOp *)instruction); |
| | 6213 | case IrInstructionIdBinOp: |
| | 6214 | return ir_analyze_instruction_bin_op(ira, (IrInstructionBinOp *)instruction); |
| | 6215 | case IrInstructionIdDeclVar: |
| | 6216 | return ir_analyze_instruction_decl_var(ira, (IrInstructionDeclVar *)instruction); |
| | 6217 | case IrInstructionIdLoadPtr: |
| | 6218 | return ir_analyze_instruction_load_ptr(ira, (IrInstructionLoadPtr *)instruction); |
| | 6219 | case IrInstructionIdStorePtr: |
| | 6220 | return ir_analyze_instruction_store_ptr(ira, (IrInstructionStorePtr *)instruction); |
| | 6221 | case IrInstructionIdElemPtr: |
| | 6222 | return ir_analyze_instruction_elem_ptr(ira, (IrInstructionElemPtr *)instruction); |
| | 6223 | case IrInstructionIdVarPtr: |
| | 6224 | return ir_analyze_instruction_var_ptr(ira, (IrInstructionVarPtr *)instruction); |
| 5789 | case IrInstructionIdFieldPtr: | 6225 | case IrInstructionIdFieldPtr: |
| 5790 | return ir_analyze_instruction_field_ptr(ira, (IrInstructionFieldPtr *)instruction); | 6226 | return ir_analyze_instruction_field_ptr(ira, (IrInstructionFieldPtr *)instruction); |
| 5791 | case IrInstructionIdCall: | 6227 | case IrInstructionIdCall: |
| ... | @@ -5844,10 +6280,14 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi | ... | @@ -5844,10 +6280,14 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi |
| 5844 | return ir_analyze_instruction_array_len(ira, (IrInstructionArrayLen *)instruction); | 6280 | return ir_analyze_instruction_array_len(ira, (IrInstructionArrayLen *)instruction); |
| 5845 | case IrInstructionIdRef: | 6281 | case IrInstructionIdRef: |
| 5846 | return ir_analyze_instruction_ref(ira, (IrInstructionRef *)instruction); | 6282 | return ir_analyze_instruction_ref(ira, (IrInstructionRef *)instruction); |
| 5847 | case IrInstructionIdCast: | | |
| 5848 | case IrInstructionIdContainerInitList: | 6283 | case IrInstructionIdContainerInitList: |
| | 6284 | return ir_analyze_instruction_container_init_list(ira, (IrInstructionContainerInitList *)instruction); |
| 5849 | case IrInstructionIdContainerInitFields: | 6285 | case IrInstructionIdContainerInitFields: |
| | 6286 | return ir_analyze_instruction_container_init_fields(ira, (IrInstructionContainerInitFields *)instruction); |
| | 6287 | case IrInstructionIdCast: |
| 5850 | case IrInstructionIdStructFieldPtr: | 6288 | case IrInstructionIdStructFieldPtr: |
| | 6289 | case IrInstructionIdEnumFieldPtr: |
| | 6290 | case IrInstructionIdStructInit: |
| 5851 | zig_panic("TODO analyze more instructions"); | 6291 | zig_panic("TODO analyze more instructions"); |
| 5852 | } | 6292 | } |
| 5853 | zig_unreachable(); | 6293 | zig_unreachable(); |
| ... | @@ -5947,6 +6387,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { | ... | @@ -5947,6 +6387,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 5947 | case IrInstructionIdCast: | 6387 | case IrInstructionIdCast: |
| 5948 | case IrInstructionIdContainerInitList: | 6388 | case IrInstructionIdContainerInitList: |
| 5949 | case IrInstructionIdContainerInitFields: | 6389 | case IrInstructionIdContainerInitFields: |
| | 6390 | case IrInstructionIdStructInit: |
| 5950 | case IrInstructionIdFieldPtr: | 6391 | case IrInstructionIdFieldPtr: |
| 5951 | case IrInstructionIdElemPtr: | 6392 | case IrInstructionIdElemPtr: |
| 5952 | case IrInstructionIdVarPtr: | 6393 | case IrInstructionIdVarPtr: |
| ... | @@ -5955,6 +6396,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { | ... | @@ -5955,6 +6396,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 5955 | case IrInstructionIdPtrTypeChild: | 6396 | case IrInstructionIdPtrTypeChild: |
| 5956 | case IrInstructionIdArrayLen: | 6397 | case IrInstructionIdArrayLen: |
| 5957 | case IrInstructionIdStructFieldPtr: | 6398 | case IrInstructionIdStructFieldPtr: |
| | 6399 | case IrInstructionIdEnumFieldPtr: |
| 5958 | case IrInstructionIdArrayType: | 6400 | case IrInstructionIdArrayType: |
| 5959 | case IrInstructionIdSliceType: | 6401 | case IrInstructionIdSliceType: |
| 5960 | case IrInstructionIdCompileVar: | 6402 | case IrInstructionIdCompileVar: |
| ... | @@ -6393,46 +6835,6 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) { | ... | @@ -6393,46 +6835,6 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) { |
| 6393 | // return g->builtin_types.entry_void; | 6835 | // return g->builtin_types.entry_void; |
| 6394 | //} | 6836 | //} |
| 6395 | // | 6837 | // |
| 6396 | //static TypeTableEntry *analyze_set_fn_static_eval(CodeGen *g, ImportTableEntry *import, | | |
| 6397 | // BlockContext *context, AstNode *node) | | |
| 6398 | //{ | | |
| 6399 | // AstNode **fn_node = &node->data.fn_call_expr.params.at(0); | | |
| 6400 | // AstNode **value_node = &node->data.fn_call_expr.params.at(1); | | |
| 6401 | // | | |
| 6402 | // FnTableEntry *fn_entry = resolve_const_expr_fn(g, import, context, fn_node); | | |
| 6403 | // if (!fn_entry) { | | |
| 6404 | // return g->builtin_types.entry_invalid; | | |
| 6405 | // } | | |
| 6406 | // | | |
| 6407 | // bool want_static_eval; | | |
| 6408 | // bool ok = resolve_const_expr_bool(g, import, context, value_node, &want_static_eval); | | |
| 6409 | // if (!ok) { | | |
| 6410 | // return g->builtin_types.entry_invalid; | | |
| 6411 | // } | | |
| 6412 | // | | |
| 6413 | // if (fn_entry->fn_static_eval_set_node) { | | |
| 6414 | // ErrorMsg *msg = add_node_error(g, node, buf_sprintf("function static eval attribute set twice")); | | |
| 6415 | // add_error_note(g, msg, fn_entry->fn_static_eval_set_node, buf_sprintf("first set here")); | | |
| 6416 | // return g->builtin_types.entry_invalid; | | |
| 6417 | // } | | |
| 6418 | // fn_entry->fn_static_eval_set_node = node; | | |
| 6419 | // | | |
| 6420 | // if (want_static_eval && !context->fn_entry->is_pure) { | | |
| 6421 | // add_node_error(g, node, buf_sprintf("attribute appears too late within function")); | | |
| 6422 | // return g->builtin_types.entry_invalid; | | |
| 6423 | // } | | |
| 6424 | // | | |
| 6425 | // if (want_static_eval) { | | |
| 6426 | // fn_entry->want_pure = WantPureTrue; | | |
| 6427 | // fn_entry->want_pure_attr_node = node; | | |
| 6428 | // } else { | | |
| 6429 | // fn_entry->want_pure = WantPureFalse; | | |
| 6430 | // fn_entry->is_pure = false; | | |
| 6431 | // } | | |
| 6432 | // | | |
| 6433 | // return g->builtin_types.entry_void; | | |
| 6434 | //} | | |
| 6435 | // | | |
| 6436 | //static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, | 6838 | //static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, |
| 6437 | // TypeTableEntry *expected_type, AstNode *node) | 6839 | // TypeTableEntry *expected_type, AstNode *node) |
| 6438 | //{ | 6840 | //{ |
| ... | @@ -6634,713 +7036,10 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) { | ... | @@ -6634,713 +7036,10 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) { |
| 6634 | // return analyze_set_fn_test(g, import, context, node); | 7036 | // return analyze_set_fn_test(g, import, context, node); |
| 6635 | // case BuiltinFnIdSetFnNoInline: | 7037 | // case BuiltinFnIdSetFnNoInline: |
| 6636 | // return analyze_set_fn_no_inline(g, import, context, node); | 7038 | // return analyze_set_fn_no_inline(g, import, context, node); |
| 6637 | // case BuiltinFnIdSetFnStaticEval: | | |
| 6638 | // return analyze_set_fn_static_eval(g, import, context, node); | | |
| 6639 | // } | 7039 | // } |
| 6640 | // zig_unreachable(); | 7040 | // zig_unreachable(); |
| 6641 | //} | 7041 | //} |
| 6642 | | 7042 | |
| 6643 | //static TypeTableEntry *analyze_container_init_expr(CodeGen *g, ImportTableEntry *import, | | |
| 6644 | // BlockContext *context, AstNode *node) | | |
| 6645 | //{ | | |
| 6646 | // assert(node->type == NodeTypeContainerInitExpr); | | |
| 6647 | // | | |
| 6648 | // AstNodeContainerInitExpr *container_init_expr = &node->data.container_init_expr; | | |
| 6649 | // | | |
| 6650 | // ContainerInitKind kind = container_init_expr->kind; | | |
| 6651 | // | | |
| 6652 | // if (container_init_expr->type->type == NodeTypeFieldAccessExpr) { | | |
| 6653 | // container_init_expr->type->data.field_access_expr.container_init_expr_node = node; | | |
| 6654 | // } | | |
| 6655 | // | | |
| 6656 | // TypeTableEntry *container_meta_type = analyze_expression(g, import, context, nullptr, | | |
| 6657 | // container_init_expr->type); | | |
| 6658 | // | | |
| 6659 | // if (container_meta_type->id == TypeTableEntryIdInvalid) { | | |
| 6660 | // return g->builtin_types.entry_invalid; | | |
| 6661 | // } | | |
| 6662 | // | | |
| 6663 | // if (node->data.container_init_expr.enum_type) { | | |
| 6664 | // get_resolved_expr(node)->const_val = get_resolved_expr(container_init_expr->type)->const_val; | | |
| 6665 | // return node->data.container_init_expr.enum_type; | | |
| 6666 | // } | | |
| 6667 | // | | |
| 6668 | // TypeTableEntry *container_type = resolve_type(g, container_init_expr->type); | | |
| 6669 | // | | |
| 6670 | // if (container_type->id == TypeTableEntryIdInvalid) { | | |
| 6671 | // return container_type; | | |
| 6672 | // } else if (container_type->id == TypeTableEntryIdStruct && | | |
| 6673 | // !container_type->data.structure.is_slice && | | |
| 6674 | // (kind == ContainerInitKindStruct || (kind == ContainerInitKindArray && | | |
| 6675 | // container_init_expr->entries.length == 0))) | | |
| 6676 | // { | | |
| 6677 | // StructValExprCodeGen *codegen = &container_init_expr->resolved_struct_val_expr; | | |
| 6678 | // codegen->type_entry = container_type; | | |
| 6679 | // codegen->source_node = node; | | |
| 6680 | // | | |
| 6681 | // | | |
| 6682 | // size_t expr_field_count = container_init_expr->entries.length; | | |
| 6683 | // size_t actual_field_count = container_type->data.structure.src_field_count; | | |
| 6684 | // | | |
| 6685 | // AstNode *non_const_expr_culprit = nullptr; | | |
| 6686 | // | | |
| 6687 | // size_t *field_use_counts = allocate<size_t>(actual_field_count); | | |
| 6688 | // ConstExprValue *const_val = &get_resolved_expr(node)->const_val; | | |
| 6689 | // const_val->ok = true; | | |
| 6690 | // const_val->data.x_struct.fields = allocate<ConstExprValue*>(actual_field_count); | | |
| 6691 | // for (size_t i = 0; i < expr_field_count; i += 1) { | | |
| 6692 | // AstNode *val_field_node = container_init_expr->entries.at(i); | | |
| 6693 | // assert(val_field_node->type == NodeTypeStructValueField); | | |
| 6694 | // | | |
| 6695 | // val_field_node->block_context = context; | | |
| 6696 | // | | |
| 6697 | // TypeStructField *type_field = find_struct_type_field(container_type, | | |
| 6698 | // val_field_node->data.struct_val_field.name); | | |
| 6699 | // | | |
| 6700 | // if (!type_field) { | | |
| 6701 | // add_node_error(g, val_field_node, | | |
| 6702 | // buf_sprintf("no member named '%s' in '%s'", | | |
| 6703 | // buf_ptr(val_field_node->data.struct_val_field.name), buf_ptr(&container_type->name))); | | |
| 6704 | // continue; | | |
| 6705 | // } | | |
| 6706 | // | | |
| 6707 | // if (type_field->type_entry->id == TypeTableEntryIdInvalid) { | | |
| 6708 | // return g->builtin_types.entry_invalid; | | |
| 6709 | // } | | |
| 6710 | // | | |
| 6711 | // size_t field_index = type_field->src_index; | | |
| 6712 | // field_use_counts[field_index] += 1; | | |
| 6713 | // if (field_use_counts[field_index] > 1) { | | |
| 6714 | // add_node_error(g, val_field_node, buf_sprintf("duplicate field")); | | |
| 6715 | // continue; | | |
| 6716 | // } | | |
| 6717 | // | | |
| 6718 | // val_field_node->data.struct_val_field.type_struct_field = type_field; | | |
| 6719 | // | | |
| 6720 | // analyze_expression(g, import, context, type_field->type_entry, | | |
| 6721 | // val_field_node->data.struct_val_field.expr); | | |
| 6722 | // | | |
| 6723 | // if (const_val->ok) { | | |
| 6724 | // ConstExprValue *field_val = | | |
| 6725 | // &get_resolved_expr(val_field_node->data.struct_val_field.expr)->const_val; | | |
| 6726 | // if (field_val->ok) { | | |
| 6727 | // const_val->data.x_struct.fields[field_index] = field_val; | | |
| 6728 | // const_val->depends_on_compile_var = const_val->depends_on_compile_var || field_val->depends_on_compile_var; | | |
| 6729 | // } else { | | |
| 6730 | // const_val->ok = false; | | |
| 6731 | // non_const_expr_culprit = val_field_node->data.struct_val_field.expr; | | |
| 6732 | // } | | |
| 6733 | // } | | |
| 6734 | // } | | |
| 6735 | // if (!const_val->ok) { | | |
| 6736 | // assert(non_const_expr_culprit); | | |
| 6737 | // if (context->fn_entry) { | | |
| 6738 | // context->fn_entry->struct_val_expr_alloca_list.append(codegen); | | |
| 6739 | // } else { | | |
| 6740 | // add_node_error(g, non_const_expr_culprit, buf_sprintf("unable to evaluate constant expression")); | | |
| 6741 | // } | | |
| 6742 | // } | | |
| 6743 | // | | |
| 6744 | // for (size_t i = 0; i < actual_field_count; i += 1) { | | |
| 6745 | // if (field_use_counts[i] == 0) { | | |
| 6746 | // add_node_error(g, node, | | |
| 6747 | // buf_sprintf("missing field: '%s'", buf_ptr(container_type->data.structure.fields[i].name))); | | |
| 6748 | // } | | |
| 6749 | // } | | |
| 6750 | // return container_type; | | |
| 6751 | // } else if (container_type->id == TypeTableEntryIdStruct && | | |
| 6752 | // container_type->data.structure.is_slice && | | |
| 6753 | // kind == ContainerInitKindArray) | | |
| 6754 | // { | | |
| 6755 | // size_t elem_count = container_init_expr->entries.length; | | |
| 6756 | // | | |
| 6757 | // TypeTableEntry *pointer_type = container_type->data.structure.fields[0].type_entry; | | |
| 6758 | // assert(pointer_type->id == TypeTableEntryIdPointer); | | |
| 6759 | // TypeTableEntry *child_type = pointer_type->data.pointer.child_type; | | |
| 6760 | // | | |
| 6761 | // ConstExprValue *const_val = &get_resolved_expr(node)->const_val; | | |
| 6762 | // const_val->ok = true; | | |
| 6763 | // const_val->data.x_array.fields = allocate<ConstExprValue*>(elem_count); | | |
| 6764 | // | | |
| 6765 | // for (size_t i = 0; i < elem_count; i += 1) { | | |
| 6766 | // AstNode **elem_node = &container_init_expr->entries.at(i); | | |
| 6767 | // analyze_expression(g, import, context, child_type, *elem_node); | | |
| 6768 | // | | |
| 6769 | // if (const_val->ok) { | | |
| 6770 | // ConstExprValue *elem_const_val = &get_resolved_expr(*elem_node)->const_val; | | |
| 6771 | // if (elem_const_val->ok) { | | |
| 6772 | // const_val->data.x_array.fields[i] = elem_const_val; | | |
| 6773 | // const_val->depends_on_compile_var = const_val->depends_on_compile_var || | | |
| 6774 | // elem_const_val->depends_on_compile_var; | | |
| 6775 | // } else { | | |
| 6776 | // const_val->ok = false; | | |
| 6777 | // } | | |
| 6778 | // } | | |
| 6779 | // } | | |
| 6780 | // | | |
| 6781 | // TypeTableEntry *fixed_size_array_type = get_array_type(g, child_type, elem_count); | | |
| 6782 | // | | |
| 6783 | // StructValExprCodeGen *codegen = &container_init_expr->resolved_struct_val_expr; | | |
| 6784 | // codegen->type_entry = fixed_size_array_type; | | |
| 6785 | // codegen->source_node = node; | | |
| 6786 | // if (!const_val->ok) { | | |
| 6787 | // if (!context->fn_entry) { | | |
| 6788 | // add_node_error(g, node, | | |
| 6789 | // buf_sprintf("unable to evaluate constant expression")); | | |
| 6790 | // } else { | | |
| 6791 | // context->fn_entry->struct_val_expr_alloca_list.append(codegen); | | |
| 6792 | // } | | |
| 6793 | // } | | |
| 6794 | // | | |
| 6795 | // return fixed_size_array_type; | | |
| 6796 | // } else if (container_type->id == TypeTableEntryIdArray) { | | |
| 6797 | // zig_panic("TODO array container init"); | | |
| 6798 | // return container_type; | | |
| 6799 | // } else if (container_type->id == TypeTableEntryIdVoid) { | | |
| 6800 | // if (container_init_expr->entries.length != 0) { | | |
| 6801 | // add_node_error(g, node, buf_sprintf("void expression expects no arguments")); | | |
| 6802 | // return g->builtin_types.entry_invalid; | | |
| 6803 | // } else { | | |
| 6804 | // return resolve_expr_const_val_as_void(g, node); | | |
| 6805 | // } | | |
| 6806 | // } else { | | |
| 6807 | // add_node_error(g, node, | | |
| 6808 | // buf_sprintf("type '%s' does not support %s initialization syntax", | | |
| 6809 | // buf_ptr(&container_type->name), err_container_init_syntax_name(kind))); | | |
| 6810 | // return g->builtin_types.entry_invalid; | | |
| 6811 | // } | | |
| 6812 | //} | | |
| 6813 | | | |
| 6814 | | | |
| 6815 | | | |
| 6816 | //static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, | | |
| 6817 | // TypeTableEntry *expected_type, AstNode *node) | | |
| 6818 | //{ | | |
| 6819 | // assert(node->type == NodeTypeFieldAccessExpr); | | |
| 6820 | // | | |
| 6821 | // AstNode **struct_expr_node = &node->data.field_access_expr.struct_expr; | | |
| 6822 | // TypeTableEntry *struct_type = analyze_expression(g, import, context, nullptr, *struct_expr_node); | | |
| 6823 | // Buf *field_name = node->data.field_access_expr.field_name; | | |
| 6824 | // | | |
| 6825 | // if (struct_type->id == TypeTableEntryIdInvalid) { | | |
| 6826 | // return struct_type; | | |
| 6827 | // } else if (is_container_ref(struct_type)) { | | |
| 6828 | // return analyze_container_member_access(g, field_name, node, struct_type); | | |
| 6829 | // } else if (struct_type->id == TypeTableEntryIdArray) { | | |
| 6830 | // if (buf_eql_str(field_name, "len")) { | | |
| 6831 | // return resolve_expr_const_val_as_unsigned_num_lit(g, node, expected_type, | | |
| 6832 | // struct_type->data.array.len, false); | | |
| 6833 | // } else { | | |
| 6834 | // add_node_error(g, node, | | |
| 6835 | // buf_sprintf("no member named '%s' in '%s'", buf_ptr(field_name), | | |
| 6836 | // buf_ptr(&struct_type->name))); | | |
| 6837 | // return g->builtin_types.entry_invalid; | | |
| 6838 | // } | | |
| 6839 | // } else if (struct_type->id == TypeTableEntryIdMetaType) { | | |
| 6840 | // TypeTableEntry *child_type = resolve_type(g, *struct_expr_node); | | |
| 6841 | // | | |
| 6842 | // if (child_type->id == TypeTableEntryIdInvalid) { | | |
| 6843 | // return g->builtin_types.entry_invalid; | | |
| 6844 | // } else if (child_type->id == TypeTableEntryIdEnum) { | | |
| 6845 | // AstNode *container_init_node = node->data.field_access_expr.container_init_expr_node; | | |
| 6846 | // AstNode *value_node; | | |
| 6847 | // if (container_init_node) { | | |
| 6848 | // assert(container_init_node->type == NodeTypeContainerInitExpr); | | |
| 6849 | // size_t param_count = container_init_node->data.container_init_expr.entries.length; | | |
| 6850 | // if (param_count > 1) { | | |
| 6851 | // AstNode *first_invalid_node = container_init_node->data.container_init_expr.entries.at(1); | | |
| 6852 | // add_node_error(g, first_executing_node(first_invalid_node), | | |
| 6853 | // buf_sprintf("enum values accept only one parameter")); | | |
| 6854 | // return child_type; | | |
| 6855 | // } else { | | |
| 6856 | // if (param_count == 1) { | | |
| 6857 | // value_node = container_init_node->data.container_init_expr.entries.at(0); | | |
| 6858 | // } else { | | |
| 6859 | // value_node = nullptr; | | |
| 6860 | // } | | |
| 6861 | // container_init_node->data.container_init_expr.enum_type = child_type; | | |
| 6862 | // } | | |
| 6863 | // } else { | | |
| 6864 | // value_node = nullptr; | | |
| 6865 | // } | | |
| 6866 | // return analyze_enum_value_expr(g, import, context, node, value_node, child_type, field_name, node); | | |
| 6867 | // } else if (child_type->id == TypeTableEntryIdStruct) { | | |
| 6868 | // BlockContext *container_block_context = get_container_block_context(child_type); | | |
| 6869 | // auto entry = container_block_context->decl_table.maybe_get(field_name); | | |
| 6870 | // AstNode *decl_node = entry ? entry->value : nullptr; | | |
| 6871 | // if (decl_node) { | | |
| 6872 | // bool pointer_only = false; | | |
| 6873 | // return analyze_decl_ref(g, node, decl_node, pointer_only, context, false); | | |
| 6874 | // } else { | | |
| 6875 | // add_node_error(g, node, | | |
| 6876 | // buf_sprintf("container '%s' has no member called '%s'", | | |
| 6877 | // buf_ptr(&child_type->name), buf_ptr(field_name))); | | |
| 6878 | // return g->builtin_types.entry_invalid; | | |
| 6879 | // } | | |
| 6880 | // } else if (child_type->id == TypeTableEntryIdPureError) { | | |
| 6881 | // return analyze_error_literal_expr(g, import, context, node, field_name); | | |
| 6882 | // } else if (child_type->id == TypeTableEntryIdInt) { | | |
| 6883 | // bool depends_on_compile_var = | | |
| 6884 | // get_resolved_expr(*struct_expr_node)->const_val.depends_on_compile_var; | | |
| 6885 | // if (buf_eql_str(field_name, "bit_count")) { | | |
| 6886 | // return resolve_expr_const_val_as_unsigned_num_lit(g, node, expected_type, | | |
| 6887 | // child_type->data.integral.bit_count, depends_on_compile_var); | | |
| 6888 | // } else if (buf_eql_str(field_name, "is_signed")) { | | |
| 6889 | // return resolve_expr_const_val_as_bool(g, node, child_type->data.integral.is_signed, | | |
| 6890 | // depends_on_compile_var); | | |
| 6891 | // } else { | | |
| 6892 | // add_node_error(g, node, | | |
| 6893 | // buf_sprintf("type '%s' has no member called '%s'", | | |
| 6894 | // buf_ptr(&child_type->name), buf_ptr(field_name))); | | |
| 6895 | // return g->builtin_types.entry_invalid; | | |
| 6896 | // } | | |
| 6897 | // } else { | | |
| 6898 | // add_node_error(g, node, | | |
| 6899 | // buf_sprintf("type '%s' does not support field access", buf_ptr(&struct_type->name))); | | |
| 6900 | // return g->builtin_types.entry_invalid; | | |
| 6901 | // } | | |
| 6902 | // } else { | | |
| 6903 | // add_node_error(g, node, | | |
| 6904 | // buf_sprintf("type '%s' does not support field access", buf_ptr(&struct_type->name))); | | |
| 6905 | // return g->builtin_types.entry_invalid; | | |
| 6906 | // } | | |
| 6907 | //} | | |
| 6908 | // | | |
| 6909 | //static TypeTableEntry *bad_method_call(CodeGen *g, AstNode *node, TypeTableEntry *container_type, | | |
| 6910 | // TypeTableEntry *expected_param_type, FnTableEntry *fn_table_entry) | | |
| 6911 | //{ | | |
| 6912 | // ErrorMsg *msg = add_node_error(g, node, | | |
| 6913 | // buf_sprintf("function called as method of '%s', but first parameter is of type '%s'", | | |
| 6914 | // buf_ptr(&container_type->name), | | |
| 6915 | // buf_ptr(&expected_param_type->name))); | | |
| 6916 | // if (fn_table_entry) { | | |
| 6917 | // add_error_note(g, msg, fn_table_entry->proto_node, buf_sprintf("function declared here")); | | |
| 6918 | // } | | |
| 6919 | // return g->builtin_types.entry_invalid; | | |
| 6920 | //} | | |
| 6921 | // | | |
| 6922 | //// Before calling this function, set node->data.fn_call_expr.fn_table_entry if the function is known | | |
| 6923 | //// at compile time. Otherwise this is a function pointer call. | | |
| 6924 | //static TypeTableEntry *analyze_fn_call_ptr(CodeGen *g, ImportTableEntry *import, BlockContext *context, | | |
| 6925 | // TypeTableEntry *expected_type, AstNode *node, TypeTableEntry *fn_type, | | |
| 6926 | // AstNode *struct_node) | | |
| 6927 | //{ | | |
| 6928 | // assert(node->type == NodeTypeFnCallExpr); | | |
| 6929 | // | | |
| 6930 | // if (fn_type->id == TypeTableEntryIdInvalid) { | | |
| 6931 | // return fn_type; | | |
| 6932 | // } | | |
| 6933 | // | | |
| 6934 | // // The function call might include inline parameters which we need to ignore according to the | | |
| 6935 | // // fn_type. | | |
| 6936 | // FnTableEntry *fn_table_entry = node->data.fn_call_expr.fn_entry; | | |
| 6937 | // AstNode *generic_proto_node = fn_table_entry ? | | |
| 6938 | // fn_table_entry->proto_node->data.fn_proto.generic_proto_node : nullptr; | | |
| 6939 | // | | |
| 6940 | // // count parameters | | |
| 6941 | // size_t struct_node_1_or_0 = struct_node ? 1 : 0; | | |
| 6942 | // size_t src_param_count = fn_type->data.fn.fn_type_id.param_count + | | |
| 6943 | // (generic_proto_node ? generic_proto_node->data.fn_proto.inline_arg_count : 0); | | |
| 6944 | // size_t call_param_count = node->data.fn_call_expr.params.length; | | |
| 6945 | // size_t expect_arg_count = src_param_count - struct_node_1_or_0; | | |
| 6946 | // | | |
| 6947 | // bool ok_invocation = true; | | |
| 6948 | // | | |
| 6949 | // if (fn_type->data.fn.fn_type_id.is_var_args) { | | |
| 6950 | // if (call_param_count < expect_arg_count) { | | |
| 6951 | // ok_invocation = false; | | |
| 6952 | // add_node_error(g, node, | | |
| 6953 | // buf_sprintf("expected at least %zu arguments, found %zu", src_param_count, call_param_count)); | | |
| 6954 | // } | | |
| 6955 | // } else if (expect_arg_count != call_param_count) { | | |
| 6956 | // ok_invocation = false; | | |
| 6957 | // add_node_error(g, node, | | |
| 6958 | // buf_sprintf("expected %zu arguments, found %zu", expect_arg_count, call_param_count)); | | |
| 6959 | // } | | |
| 6960 | // | | |
| 6961 | // bool all_args_const_expr = true; | | |
| 6962 | // | | |
| 6963 | // if (struct_node) { | | |
| 6964 | // Expr *struct_expr = get_resolved_expr(struct_node); | | |
| 6965 | // ConstExprValue *struct_const_val = &struct_expr->const_val; | | |
| 6966 | // if (!struct_const_val->ok) { | | |
| 6967 | // all_args_const_expr = false; | | |
| 6968 | // } | | |
| 6969 | // | | |
| 6970 | // FnTypeParamInfo *param_info = &fn_type->data.fn.fn_type_id.param_info[0]; | | |
| 6971 | // TypeTableEntry *expected_param_type = param_info->type; | | |
| 6972 | // TypeTableEntry *container_bare_type = container_ref_type(struct_expr->type_entry); | | |
| 6973 | // if (is_container_ref(expected_param_type)) { | | |
| 6974 | // TypeTableEntry *param_bare_type = container_ref_type(expected_param_type); | | |
| 6975 | // if (param_bare_type != container_bare_type) { | | |
| 6976 | // return bad_method_call(g, node, container_bare_type, expected_param_type, fn_table_entry); | | |
| 6977 | // } | | |
| 6978 | // } else { | | |
| 6979 | // return bad_method_call(g, node, container_bare_type, expected_param_type, fn_table_entry); | | |
| 6980 | // } | | |
| 6981 | // } | | |
| 6982 | // | | |
| 6983 | // // analyze each parameter. in the case of a method, we already analyzed the | | |
| 6984 | // // first parameter in order to figure out which struct we were calling a method on. | | |
| 6985 | // size_t next_type_i = struct_node_1_or_0; | | |
| 6986 | // for (size_t call_i = 0; call_i < call_param_count; call_i += 1) { | | |
| 6987 | // size_t proto_i = call_i + struct_node_1_or_0; | | |
| 6988 | // AstNode **param_node = &node->data.fn_call_expr.params.at(call_i); | | |
| 6989 | // // determine the expected type for each parameter | | |
| 6990 | // TypeTableEntry *expected_param_type = nullptr; | | |
| 6991 | // if (proto_i < src_param_count) { | | |
| 6992 | // if (generic_proto_node && | | |
| 6993 | // generic_proto_node->data.fn_proto.params.at(proto_i)->data.param_decl.is_inline) | | |
| 6994 | // { | | |
| 6995 | // continue; | | |
| 6996 | // } | | |
| 6997 | // | | |
| 6998 | // FnTypeParamInfo *param_info = &fn_type->data.fn.fn_type_id.param_info[next_type_i]; | | |
| 6999 | // next_type_i += 1; | | |
| 7000 | // | | |
| 7001 | // expected_param_type = param_info->type; | | |
| 7002 | // } | | |
| 7003 | // TypeTableEntry *param_type = analyze_expression(g, import, context, expected_param_type, *param_node); | | |
| 7004 | // if (param_type->id == TypeTableEntryIdInvalid) { | | |
| 7005 | // return param_type; | | |
| 7006 | // } | | |
| 7007 | // | | |
| 7008 | // ConstExprValue *const_arg_val = &get_resolved_expr(*param_node)->const_val; | | |
| 7009 | // if (!const_arg_val->ok) { | | |
| 7010 | // all_args_const_expr = false; | | |
| 7011 | // } | | |
| 7012 | // } | | |
| 7013 | // | | |
| 7014 | // TypeTableEntry *return_type = fn_type->data.fn.fn_type_id.return_type; | | |
| 7015 | // | | |
| 7016 | // if (return_type->id == TypeTableEntryIdInvalid) { | | |
| 7017 | // return return_type; | | |
| 7018 | // } | | |
| 7019 | // | | |
| 7020 | // ConstExprValue *result_val = &get_resolved_expr(node)->const_val; | | |
| 7021 | // if (ok_invocation && fn_table_entry && fn_table_entry->is_pure && fn_table_entry->want_pure != WantPureFalse) { | | |
| 7022 | // if (fn_table_entry->anal_state == FnAnalStateReady) { | | |
| 7023 | // analyze_fn_body(g, fn_table_entry); | | |
| 7024 | // if (fn_table_entry->proto_node->data.fn_proto.skip) { | | |
| 7025 | // return g->builtin_types.entry_invalid; | | |
| 7026 | // } | | |
| 7027 | // } | | |
| 7028 | // if (all_args_const_expr) { | | |
| 7029 | // if (fn_table_entry->is_pure && fn_table_entry->anal_state == FnAnalStateComplete) { | | |
| 7030 | // if (eval_fn(g, node, fn_table_entry, result_val, 1000, struct_node)) { | | |
| 7031 | // // function evaluation generated an error | | |
| 7032 | // return g->builtin_types.entry_invalid; | | |
| 7033 | // } | | |
| 7034 | // return return_type; | | |
| 7035 | // } | | |
| 7036 | // } | | |
| 7037 | // } | | |
| 7038 | // if (!ok_invocation || !fn_table_entry || !fn_table_entry->is_pure || fn_table_entry->want_pure == WantPureFalse) { | | |
| 7039 | // // calling an impure fn is impure | | |
| 7040 | // mark_impure_fn(g, context, node); | | |
| 7041 | // if (fn_table_entry && fn_table_entry->want_pure == WantPureTrue) { | | |
| 7042 | // return g->builtin_types.entry_invalid; | | |
| 7043 | // } | | |
| 7044 | // } | | |
| 7045 | // | | |
| 7046 | // // TODO | | |
| 7047 | // //if (handle_is_ptr(return_type)) { | | |
| 7048 | // // if (context->fn_entry) { | | |
| 7049 | // // context->fn_entry->cast_alloca_list.append(node); | | |
| 7050 | // // } else if (!result_val->ok) { | | |
| 7051 | // // add_node_error(g, node, buf_sprintf("unable to evaluate constant expression")); | | |
| 7052 | // // } | | |
| 7053 | // //} | | |
| 7054 | // | | |
| 7055 | // return return_type; | | |
| 7056 | //} | | |
| 7057 | // | | |
| 7058 | //static TypeTableEntry *analyze_fn_call_with_inline_args(CodeGen *g, ImportTableEntry *import, | | |
| 7059 | // BlockContext *parent_context, TypeTableEntry *expected_type, AstNode *call_node, | | |
| 7060 | // FnTableEntry *fn_table_entry, AstNode *struct_node) | | |
| 7061 | //{ | | |
| 7062 | // assert(call_node->type == NodeTypeFnCallExpr); | | |
| 7063 | // assert(fn_table_entry); | | |
| 7064 | // | | |
| 7065 | // AstNode *decl_node = fn_table_entry->proto_node; | | |
| 7066 | // | | |
| 7067 | // // count parameters | | |
| 7068 | // size_t struct_node_1_or_0 = (struct_node ? 1 : 0); | | |
| 7069 | // size_t src_param_count = decl_node->data.fn_proto.params.length; | | |
| 7070 | // size_t call_param_count = call_node->data.fn_call_expr.params.length; | | |
| 7071 | // | | |
| 7072 | // if (src_param_count != call_param_count + struct_node_1_or_0) { | | |
| 7073 | // add_node_error(g, call_node, | | |
| 7074 | // buf_sprintf("expected %zu arguments, found %zu", src_param_count - struct_node_1_or_0, call_param_count)); | | |
| 7075 | // return g->builtin_types.entry_invalid; | | |
| 7076 | // } | | |
| 7077 | // | | |
| 7078 | // size_t inline_or_var_type_arg_count = decl_node->data.fn_proto.inline_or_var_type_arg_count; | | |
| 7079 | // assert(inline_or_var_type_arg_count > 0); | | |
| 7080 | // | | |
| 7081 | // BlockContext *child_context = decl_node->owner->block_context; | | |
| 7082 | // size_t next_generic_param_index = 0; | | |
| 7083 | // | | |
| 7084 | // GenericFnTypeId *generic_fn_type_id = allocate<GenericFnTypeId>(1); | | |
| 7085 | // generic_fn_type_id->decl_node = decl_node; | | |
| 7086 | // generic_fn_type_id->generic_param_count = inline_or_var_type_arg_count; | | |
| 7087 | // generic_fn_type_id->generic_params = allocate<GenericParamValue>(inline_or_var_type_arg_count); | | |
| 7088 | // | | |
| 7089 | // size_t next_impl_i = 0; | | |
| 7090 | // for (size_t call_i = 0; call_i < call_param_count; call_i += 1) { | | |
| 7091 | // size_t proto_i = call_i + struct_node_1_or_0; | | |
| 7092 | // AstNode *generic_param_decl_node = decl_node->data.fn_proto.params.at(proto_i); | | |
| 7093 | // assert(generic_param_decl_node->type == NodeTypeParamDecl); | | |
| 7094 | // | | |
| 7095 | // AstNode **generic_param_type_node = &generic_param_decl_node->data.param_decl.type; | | |
| 7096 | // TypeTableEntry *expected_param_type = analyze_type_expr(g, decl_node->owner, child_context, | | |
| 7097 | // *generic_param_type_node); | | |
| 7098 | // if (expected_param_type->id == TypeTableEntryIdInvalid) { | | |
| 7099 | // return expected_param_type; | | |
| 7100 | // } | | |
| 7101 | // | | |
| 7102 | // bool is_var_type = (expected_param_type->id == TypeTableEntryIdVar); | | |
| 7103 | // bool is_inline = generic_param_decl_node->data.param_decl.is_inline; | | |
| 7104 | // if (!is_inline && !is_var_type) { | | |
| 7105 | // next_impl_i += 1; | | |
| 7106 | // continue; | | |
| 7107 | // } | | |
| 7108 | // | | |
| 7109 | // | | |
| 7110 | // AstNode **param_node = &call_node->data.fn_call_expr.params.at(call_i); | | |
| 7111 | // TypeTableEntry *param_type = analyze_expression(g, import, parent_context, | | |
| 7112 | // is_var_type ? nullptr : expected_param_type, *param_node); | | |
| 7113 | // if (param_type->id == TypeTableEntryIdInvalid) { | | |
| 7114 | // return param_type; | | |
| 7115 | // } | | |
| 7116 | // | | |
| 7117 | // // set child_context so that the previous param is in scope | | |
| 7118 | // child_context = new_block_context(generic_param_decl_node, child_context); | | |
| 7119 | // | | |
| 7120 | // ConstExprValue *const_val = &get_resolved_expr(*param_node)->const_val; | | |
| 7121 | // if (is_inline && !const_val->ok) { | | |
| 7122 | // add_node_error(g, *param_node, | | |
| 7123 | // buf_sprintf("unable to evaluate constant expression for inline parameter")); | | |
| 7124 | // | | |
| 7125 | // return g->builtin_types.entry_invalid; | | |
| 7126 | // } | | |
| 7127 | // | | |
| 7128 | // VariableTableEntry *var = add_local_var_shadowable(g, generic_param_decl_node, decl_node->owner, child_context, | | |
| 7129 | // generic_param_decl_node->data.param_decl.name, param_type, true, *param_node, true); | | |
| 7130 | // // This generic function instance could be called with anything, so when this variable is read it | | |
| 7131 | // // needs to know that it depends on compile time variable data. | | |
| 7132 | // var->force_depends_on_compile_var = true; | | |
| 7133 | // | | |
| 7134 | // GenericParamValue *generic_param_value = | | |
| 7135 | // &generic_fn_type_id->generic_params[next_generic_param_index]; | | |
| 7136 | // generic_param_value->type = param_type; | | |
| 7137 | // generic_param_value->node = is_inline ? *param_node : nullptr; | | |
| 7138 | // generic_param_value->impl_index = next_impl_i; | | |
| 7139 | // next_generic_param_index += 1; | | |
| 7140 | // | | |
| 7141 | // if (!is_inline) { | | |
| 7142 | // next_impl_i += 1; | | |
| 7143 | // } | | |
| 7144 | // } | | |
| 7145 | // | | |
| 7146 | // assert(next_generic_param_index == inline_or_var_type_arg_count); | | |
| 7147 | // | | |
| 7148 | // auto entry = g->generic_table.maybe_get(generic_fn_type_id); | | |
| 7149 | // FnTableEntry *impl_fn; | | |
| 7150 | // if (entry) { | | |
| 7151 | // AstNode *impl_decl_node = entry->value; | | |
| 7152 | // assert(impl_decl_node->type == NodeTypeFnProto); | | |
| 7153 | // impl_fn = impl_decl_node->data.fn_proto.fn_table_entry; | | |
| 7154 | // } else { | | |
| 7155 | // AstNode *decl_node = generic_fn_type_id->decl_node; | | |
| 7156 | // AstNode *impl_fn_def_node = ast_clone_subtree_special(decl_node->data.fn_proto.fn_def_node, | | |
| 7157 | // &g->next_node_index, AstCloneSpecialOmitInlineParams); | | |
| 7158 | // AstNode *impl_decl_node = impl_fn_def_node->data.fn_def.fn_proto; | | |
| 7159 | // impl_decl_node->data.fn_proto.inline_arg_count = 0; | | |
| 7160 | // impl_decl_node->data.fn_proto.inline_or_var_type_arg_count = 0; | | |
| 7161 | // impl_decl_node->data.fn_proto.generic_proto_node = decl_node; | | |
| 7162 | // | | |
| 7163 | // // replace var arg types with actual types | | |
| 7164 | // for (size_t generic_arg_i = 0; generic_arg_i < inline_or_var_type_arg_count; generic_arg_i += 1) { | | |
| 7165 | // GenericParamValue *generic_param_value = &generic_fn_type_id->generic_params[generic_arg_i]; | | |
| 7166 | // if (!generic_param_value->node) { | | |
| 7167 | // size_t impl_i = generic_param_value->impl_index; | | |
| 7168 | // AstNode *impl_param_decl_node = impl_decl_node->data.fn_proto.params.at(impl_i); | | |
| 7169 | // assert(impl_param_decl_node->type == NodeTypeParamDecl); | | |
| 7170 | // | | |
| 7171 | // impl_param_decl_node->data.param_decl.type = create_ast_type_node(g, import, | | |
| 7172 | // generic_param_value->type, impl_param_decl_node); | | |
| 7173 | // normalize_parent_ptrs(impl_param_decl_node); | | |
| 7174 | // } | | |
| 7175 | // } | | |
| 7176 | // | | |
| 7177 | // preview_fn_proto_instance(g, import, impl_decl_node, child_context); | | |
| 7178 | // g->generic_table.put(generic_fn_type_id, impl_decl_node); | | |
| 7179 | // impl_fn = impl_decl_node->data.fn_proto.fn_table_entry; | | |
| 7180 | // } | | |
| 7181 | // | | |
| 7182 | // call_node->data.fn_call_expr.fn_entry = impl_fn; | | |
| 7183 | // return analyze_fn_call_ptr(g, import, parent_context, expected_type, call_node, | | |
| 7184 | // impl_fn->type_entry, struct_node); | | |
| 7185 | //} | | |
| 7186 | // | | |
| 7187 | //static TypeTableEntry *analyze_generic_fn_call(CodeGen *g, ImportTableEntry *import, BlockContext *parent_context, | | |
| 7188 | // TypeTableEntry *expected_type, AstNode *node, TypeTableEntry *generic_fn_type) | | |
| 7189 | //{ | | |
| 7190 | // assert(node->type == NodeTypeFnCallExpr); | | |
| 7191 | // assert(generic_fn_type->id == TypeTableEntryIdGenericFn); | | |
| 7192 | // | | |
| 7193 | // AstNode *decl_node = generic_fn_type->data.generic_fn.decl_node; | | |
| 7194 | // assert(decl_node->type == NodeTypeContainerDecl); | | |
| 7195 | // ZigList<AstNode *> *generic_params = &decl_node->data.struct_decl.generic_params; | | |
| 7196 | // | | |
| 7197 | // size_t expected_param_count = generic_params->length; | | |
| 7198 | // size_t actual_param_count = node->data.fn_call_expr.params.length; | | |
| 7199 | // | | |
| 7200 | // if (actual_param_count != expected_param_count) { | | |
| 7201 | // add_node_error(g, first_executing_node(node), | | |
| 7202 | // buf_sprintf("expected %zu arguments, found %zu", expected_param_count, actual_param_count)); | | |
| 7203 | // return g->builtin_types.entry_invalid; | | |
| 7204 | // } | | |
| 7205 | // | | |
| 7206 | // GenericFnTypeId *generic_fn_type_id = allocate<GenericFnTypeId>(1); | | |
| 7207 | // generic_fn_type_id->decl_node = decl_node; | | |
| 7208 | // generic_fn_type_id->generic_param_count = actual_param_count; | | |
| 7209 | // generic_fn_type_id->generic_params = allocate<GenericParamValue>(actual_param_count); | | |
| 7210 | // | | |
| 7211 | // BlockContext *child_context = decl_node->owner->block_context; | | |
| 7212 | // for (size_t i = 0; i < actual_param_count; i += 1) { | | |
| 7213 | // AstNode *generic_param_decl_node = generic_params->at(i); | | |
| 7214 | // assert(generic_param_decl_node->type == NodeTypeParamDecl); | | |
| 7215 | // | | |
| 7216 | // AstNode **generic_param_type_node = &generic_param_decl_node->data.param_decl.type; | | |
| 7217 | // | | |
| 7218 | // TypeTableEntry *expected_param_type = analyze_type_expr(g, decl_node->owner, | | |
| 7219 | // child_context, *generic_param_type_node); | | |
| 7220 | // if (expected_param_type->id == TypeTableEntryIdInvalid) { | | |
| 7221 | // return expected_param_type; | | |
| 7222 | // } | | |
| 7223 | // | | |
| 7224 | // | | |
| 7225 | // | | |
| 7226 | // AstNode **param_node = &node->data.fn_call_expr.params.at(i); | | |
| 7227 | // | | |
| 7228 | // TypeTableEntry *param_type = analyze_expression(g, import, parent_context, expected_param_type, | | |
| 7229 | // *param_node); | | |
| 7230 | // if (param_type->id == TypeTableEntryIdInvalid) { | | |
| 7231 | // return param_type; | | |
| 7232 | // } | | |
| 7233 | // | | |
| 7234 | // // set child_context so that the previous param is in scope | | |
| 7235 | // child_context = new_block_context(generic_param_decl_node, child_context); | | |
| 7236 | // | | |
| 7237 | // ConstExprValue *const_val = &get_resolved_expr(*param_node)->const_val; | | |
| 7238 | // if (const_val->ok) { | | |
| 7239 | // VariableTableEntry *var = add_local_var(g, generic_param_decl_node, decl_node->owner, child_context, | | |
| 7240 | // generic_param_decl_node->data.param_decl.name, param_type, true, *param_node); | | |
| 7241 | // var->force_depends_on_compile_var = true; | | |
| 7242 | // } else { | | |
| 7243 | // add_node_error(g, *param_node, buf_sprintf("unable to evaluate constant expression")); | | |
| 7244 | // | | |
| 7245 | // return g->builtin_types.entry_invalid; | | |
| 7246 | // } | | |
| 7247 | // | | |
| 7248 | // GenericParamValue *generic_param_value = &generic_fn_type_id->generic_params[i]; | | |
| 7249 | // generic_param_value->type = param_type; | | |
| 7250 | // generic_param_value->node = *param_node; | | |
| 7251 | // } | | |
| 7252 | // | | |
| 7253 | // auto entry = g->generic_table.maybe_get(generic_fn_type_id); | | |
| 7254 | // if (entry) { | | |
| 7255 | // AstNode *impl_decl_node = entry->value; | | |
| 7256 | // assert(impl_decl_node->type == NodeTypeContainerDecl); | | |
| 7257 | // TypeTableEntry *type_entry = impl_decl_node->data.struct_decl.type_entry; | | |
| 7258 | // return resolve_expr_const_val_as_type(g, node, type_entry, false); | | |
| 7259 | // } | | |
| 7260 | // | | |
| 7261 | // // make a type from the generic parameters supplied | | |
| 7262 | // assert(decl_node->type == NodeTypeContainerDecl); | | |
| 7263 | // AstNode *impl_decl_node = ast_clone_subtree(decl_node, &g->next_node_index); | | |
| 7264 | // g->generic_table.put(generic_fn_type_id, impl_decl_node); | | |
| 7265 | // scan_struct_decl(g, import, child_context, impl_decl_node); | | |
| 7266 | // TypeTableEntry *type_entry = impl_decl_node->data.struct_decl.type_entry; | | |
| 7267 | // resolve_struct_type(g, import, type_entry); | | |
| 7268 | // return resolve_expr_const_val_as_type(g, node, type_entry, false); | | |
| 7269 | //} | | |
| 7270 | // | | |
| 7271 | //static TypeTableEntry *analyze_fn_call_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, | | |
| 7272 | // TypeTableEntry *expected_type, AstNode *node) | | |
| 7273 | //{ | | |
| 7274 | // AstNode *fn_ref_expr = node->data.fn_call_expr.fn_ref_expr; | | |
| 7275 | // | | |
| 7276 | // if (node->data.fn_call_expr.is_builtin) { | | |
| 7277 | // zig_panic("moved builtin fn call code to ir.cpp"); | | |
| 7278 | // } | | |
| 7279 | // | | |
| 7280 | // TypeTableEntry *invoke_type_entry = analyze_expression(g, import, context, nullptr, fn_ref_expr); | | |
| 7281 | // if (invoke_type_entry->id == TypeTableEntryIdInvalid) { | | |
| 7282 | // return g->builtin_types.entry_invalid; | | |
| 7283 | // } | | |
| 7284 | // | | |
| 7285 | // // use constant expression evaluator to figure out the function at compile time. | | |
| 7286 | // // otherwise we treat this as a function pointer. | | |
| 7287 | // ConstExprValue *const_val = &get_resolved_expr(fn_ref_expr)->const_val; | | |
| 7288 | // | | |
| 7289 | // if (const_val->ok) { | | |
| 7290 | // if (invoke_type_entry->id == TypeTableEntryIdMetaType) { | | |
| 7291 | // zig_unreachable(); | | |
| 7292 | // } else if (invoke_type_entry->id == TypeTableEntryIdFn) { | | |
| 7293 | // AstNode *struct_node; | | |
| 7294 | // if (fn_ref_expr->type == NodeTypeFieldAccessExpr && | | |
| 7295 | // fn_ref_expr->data.field_access_expr.is_member_fn) | | |
| 7296 | // { | | |
| 7297 | // struct_node = fn_ref_expr->data.field_access_expr.struct_expr; | | |
| 7298 | // } else { | | |
| 7299 | // struct_node = nullptr; | | |
| 7300 | // } | | |
| 7301 | // | | |
| 7302 | // FnTableEntry *fn_table_entry = const_val->data.x_fn; | | |
| 7303 | // node->data.fn_call_expr.fn_entry = fn_table_entry; | | |
| 7304 | // return analyze_fn_call_ptr(g, import, context, expected_type, node, | | |
| 7305 | // fn_table_entry->type_entry, struct_node); | | |
| 7306 | // } else if (invoke_type_entry->id == TypeTableEntryIdGenericFn) { | | |
| 7307 | // TypeTableEntry *generic_fn_type = const_val->data.x_type; | | |
| 7308 | // AstNode *decl_node = generic_fn_type->data.generic_fn.decl_node; | | |
| 7309 | // if (decl_node->type == NodeTypeFnProto) { | | |
| 7310 | // AstNode *struct_node; | | |
| 7311 | // if (fn_ref_expr->type == NodeTypeFieldAccessExpr && | | |
| 7312 | // fn_ref_expr->data.field_access_expr.is_member_fn) | | |
| 7313 | // { | | |
| 7314 | // struct_node = fn_ref_expr->data.field_access_expr.struct_expr; | | |
| 7315 | // } else { | | |
| 7316 | // struct_node = nullptr; | | |
| 7317 | // } | | |
| 7318 | // | | |
| 7319 | // FnTableEntry *fn_table_entry = decl_node->data.fn_proto.fn_table_entry; | | |
| 7320 | // if (fn_table_entry->proto_node->data.fn_proto.skip) { | | |
| 7321 | // return g->builtin_types.entry_invalid; | | |
| 7322 | // } | | |
| 7323 | // return analyze_fn_call_with_inline_args(g, import, context, expected_type, node, | | |
| 7324 | // fn_table_entry, struct_node); | | |
| 7325 | // } else { | | |
| 7326 | // return analyze_generic_fn_call(g, import, context, expected_type, node, const_val->data.x_type); | | |
| 7327 | // } | | |
| 7328 | // } else { | | |
| 7329 | // add_node_error(g, fn_ref_expr, | | |
| 7330 | // buf_sprintf("type '%s' not a function", buf_ptr(&invoke_type_entry->name))); | | |
| 7331 | // return g->builtin_types.entry_invalid; | | |
| 7332 | // } | | |
| 7333 | // } | | |
| 7334 | // | | |
| 7335 | // // function pointer | | |
| 7336 | // if (invoke_type_entry->id == TypeTableEntryIdFn) { | | |
| 7337 | // return analyze_fn_call_ptr(g, import, context, expected_type, node, invoke_type_entry, nullptr); | | |
| 7338 | // } else { | | |
| 7339 | // add_node_error(g, fn_ref_expr, | | |
| 7340 | // buf_sprintf("type '%s' not a function", buf_ptr(&invoke_type_entry->name))); | | |
| 7341 | // return g->builtin_types.entry_invalid; | | |
| 7342 | // } | | |
| 7343 | //} | | |
| 7344 | //static TypeTableEntry *analyze_return_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, | 7043 | //static TypeTableEntry *analyze_return_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, |
| 7345 | // TypeTableEntry *expected_type, AstNode *node) | 7044 | // TypeTableEntry *expected_type, AstNode *node) |
| 7346 | //{ | 7045 | //{ |
| ... | @@ -7476,68 +7175,6 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) { | ... | @@ -7476,68 +7175,6 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) { |
| 7476 | // return enum_type; | 7175 | // return enum_type; |
| 7477 | //} | 7176 | //} |
| 7478 | // | 7177 | // |
| 7479 | //static TypeTableEntry *analyze_container_member_access_inner(CodeGen *g, | | |
| 7480 | // TypeTableEntry *bare_struct_type, Buf *field_name, AstNode *node, TypeTableEntry *struct_type) | | |
| 7481 | //{ | | |
| 7482 | // assert(node->type == NodeTypeFieldAccessExpr); | | |
| 7483 | // if (!is_slice(bare_struct_type)) { | | |
| 7484 | // BlockContext *container_block_context = get_container_block_context(bare_struct_type); | | |
| 7485 | // assert(container_block_context); | | |
| 7486 | // auto entry = container_block_context->decl_table.maybe_get(field_name); | | |
| 7487 | // AstNode *fn_decl_node = entry ? entry->value : nullptr; | | |
| 7488 | // if (fn_decl_node && fn_decl_node->type == NodeTypeFnProto) { | | |
| 7489 | // resolve_top_level_decl(g, fn_decl_node, false); | | |
| 7490 | // TopLevelDecl *tld = get_as_top_level_decl(fn_decl_node); | | |
| 7491 | // if (tld->resolution == TldResolutionInvalid) { | | |
| 7492 | // return g->builtin_types.entry_invalid; | | |
| 7493 | // } | | |
| 7494 | // | | |
| 7495 | // node->data.field_access_expr.is_member_fn = true; | | |
| 7496 | // FnTableEntry *fn_entry = fn_decl_node->data.fn_proto.fn_table_entry; | | |
| 7497 | // if (fn_entry->type_entry->id == TypeTableEntryIdGenericFn) { | | |
| 7498 | // return resolve_expr_const_val_as_generic_fn(g, node, fn_entry->type_entry, false); | | |
| 7499 | // } else { | | |
| 7500 | // return resolve_expr_const_val_as_fn(g, node, fn_entry, false); | | |
| 7501 | // } | | |
| 7502 | // } | | |
| 7503 | // } | | |
| 7504 | // add_node_error(g, node, | | |
| 7505 | // buf_sprintf("no member named '%s' in '%s'", buf_ptr(field_name), buf_ptr(&bare_struct_type->name))); | | |
| 7506 | // return g->builtin_types.entry_invalid; | | |
| 7507 | //} | | |
| 7508 | // | | |
| 7509 | //static TypeTableEntry *analyze_container_member_access(CodeGen *g, | | |
| 7510 | // Buf *field_name, AstNode *node, TypeTableEntry *struct_type) | | |
| 7511 | //{ | | |
| 7512 | // TypeTableEntry *bare_type = container_ref_type(struct_type); | | |
| 7513 | // if (!type_is_complete(bare_type)) { | | |
| 7514 | // resolve_container_type(g, bare_type); | | |
| 7515 | // } | | |
| 7516 | // | | |
| 7517 | // node->data.field_access_expr.bare_container_type = bare_type; | | |
| 7518 | // | | |
| 7519 | // if (bare_type->id == TypeTableEntryIdStruct) { | | |
| 7520 | // node->data.field_access_expr.type_struct_field = find_struct_type_field(bare_type, field_name); | | |
| 7521 | // if (node->data.field_access_expr.type_struct_field) { | | |
| 7522 | // return node->data.field_access_expr.type_struct_field->type_entry; | | |
| 7523 | // } else { | | |
| 7524 | // return analyze_container_member_access_inner(g, bare_type, field_name, | | |
| 7525 | // node, struct_type); | | |
| 7526 | // } | | |
| 7527 | // } else if (bare_type->id == TypeTableEntryIdEnum) { | | |
| 7528 | // node->data.field_access_expr.type_enum_field = find_enum_type_field(bare_type, field_name); | | |
| 7529 | // if (node->data.field_access_expr.type_enum_field) { | | |
| 7530 | // return node->data.field_access_expr.type_enum_field->type_entry; | | |
| 7531 | // } else { | | |
| 7532 | // return analyze_container_member_access_inner(g, bare_type, field_name, | | |
| 7533 | // node, struct_type); | | |
| 7534 | // } | | |
| 7535 | // } else if (bare_type->id == TypeTableEntryIdUnion) { | | |
| 7536 | // zig_panic("TODO"); | | |
| 7537 | // } else { | | |
| 7538 | // zig_unreachable(); | | |
| 7539 | // } | | |
| 7540 | //} | | |
| 7541 | // | 7178 | // |
| 7542 | //static TypeTableEntry *analyze_slice_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, | 7179 | //static TypeTableEntry *analyze_slice_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, |
| 7543 | // AstNode *node) | 7180 | // AstNode *node) |
| ... | @@ -7887,19 +7524,6 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) { | ... | @@ -7887,19 +7524,6 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) { |
| 7887 | // return g->builtin_types.entry_invalid; | 7524 | // return g->builtin_types.entry_invalid; |
| 7888 | //} | 7525 | //} |
| 7889 | // | 7526 | // |
| 7890 | //static TypeTableEntry *analyze_fn_proto_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, | | |
| 7891 | // TypeTableEntry *expected_type, AstNode *node) | | |
| 7892 | //{ | | |
| 7893 | // TypeTableEntry *type_entry = analyze_fn_proto_type(g, import, context, expected_type, node, | | |
| 7894 | // false, false, nullptr); | | |
| 7895 | // | | |
| 7896 | // if (type_entry->id == TypeTableEntryIdInvalid) { | | |
| 7897 | // return type_entry; | | |
| 7898 | // } | | |
| 7899 | // | | |
| 7900 | // return resolve_expr_const_val_as_type(g, node, type_entry, false); | | |
| 7901 | //} | | |
| 7902 | // | | |
| 7903 | //static void validate_voided_expr(CodeGen *g, AstNode *source_node, TypeTableEntry *type_entry) { | 7527 | //static void validate_voided_expr(CodeGen *g, AstNode *source_node, TypeTableEntry *type_entry) { |
| 7904 | // if (type_entry->id == TypeTableEntryIdMetaType) { | 7528 | // if (type_entry->id == TypeTableEntryIdMetaType) { |
| 7905 | // add_node_error(g, first_executing_node(source_node), buf_sprintf("expected expression, found type")); | 7529 | // add_node_error(g, first_executing_node(source_node), buf_sprintf("expected expression, found type")); |
| ... | @@ -8239,92 +7863,6 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) { | ... | @@ -8239,92 +7863,6 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) { |
| 8239 | // } | 7863 | // } |
| 8240 | //} | 7864 | //} |
| 8241 | // | 7865 | // |
| 8242 | //static LLVMValueRef gen_fn_call_expr(CodeGen *g, AstNode *node) { | | |
| 8243 | // assert(node->type == NodeTypeFnCallExpr); | | |
| 8244 | // | | |
| 8245 | // if (node->data.fn_call_expr.is_builtin) { | | |
| 8246 | // return gen_builtin_fn_call_expr(g, node); | | |
| 8247 | // } | | |
| 8248 | // | | |
| 8249 | // FnTableEntry *fn_table_entry = node->data.fn_call_expr.fn_entry; | | |
| 8250 | // TypeTableEntry *struct_type = nullptr; | | |
| 8251 | // AstNode *first_param_expr = nullptr; | | |
| 8252 | // | | |
| 8253 | // AstNode *fn_ref_expr = node->data.fn_call_expr.fn_ref_expr; | | |
| 8254 | // if (fn_ref_expr->type == NodeTypeFieldAccessExpr && | | |
| 8255 | // fn_ref_expr->data.field_access_expr.is_member_fn) | | |
| 8256 | // { | | |
| 8257 | // first_param_expr = fn_ref_expr->data.field_access_expr.struct_expr; | | |
| 8258 | // struct_type = get_expr_type(first_param_expr); | | |
| 8259 | // } | | |
| 8260 | // | | |
| 8261 | // TypeTableEntry *fn_type; | | |
| 8262 | // LLVMValueRef fn_val; | | |
| 8263 | // AstNode *generic_proto_node; | | |
| 8264 | // if (fn_table_entry) { | | |
| 8265 | // fn_val = fn_table_entry->fn_value; | | |
| 8266 | // fn_type = fn_table_entry->type_entry; | | |
| 8267 | // generic_proto_node = fn_table_entry->proto_node->data.fn_proto.generic_proto_node; | | |
| 8268 | // } else { | | |
| 8269 | // fn_val = gen_expr(g, fn_ref_expr); | | |
| 8270 | // fn_type = get_expr_type(fn_ref_expr); | | |
| 8271 | // generic_proto_node = nullptr; | | |
| 8272 | // } | | |
| 8273 | // | | |
| 8274 | // TypeTableEntry *src_return_type = fn_type->data.fn.fn_type_id.return_type; | | |
| 8275 | // | | |
| 8276 | // bool ret_has_bits = type_has_bits(src_return_type); | | |
| 8277 | // | | |
| 8278 | // size_t fn_call_param_count = node->data.fn_call_expr.params.length; | | |
| 8279 | // bool first_arg_ret = ret_has_bits && handle_is_ptr(src_return_type); | | |
| 8280 | // size_t actual_param_count = fn_call_param_count + (struct_type ? 1 : 0) + (first_arg_ret ? 1 : 0); | | |
| 8281 | // bool is_var_args = fn_type->data.fn.fn_type_id.is_var_args; | | |
| 8282 | // | | |
| 8283 | // // don't really include void values | | |
| 8284 | // LLVMValueRef *gen_param_values = allocate<LLVMValueRef>(actual_param_count); | | |
| 8285 | // | | |
| 8286 | // size_t gen_param_index = 0; | | |
| 8287 | // if (first_arg_ret) { | | |
| 8288 | // gen_param_values[gen_param_index] = node->data.fn_call_expr.tmp_ptr; | | |
| 8289 | // gen_param_index += 1; | | |
| 8290 | // } | | |
| 8291 | // if (struct_type && type_has_bits(struct_type)) { | | |
| 8292 | // gen_param_values[gen_param_index] = gen_expr(g, first_param_expr); | | |
| 8293 | // assert(gen_param_values[gen_param_index]); | | |
| 8294 | // gen_param_index += 1; | | |
| 8295 | // } | | |
| 8296 | // | | |
| 8297 | // for (size_t call_i = 0; call_i < fn_call_param_count; call_i += 1) { | | |
| 8298 | // size_t proto_i = call_i + (struct_type ? 1 : 0); | | |
| 8299 | // if (generic_proto_node && | | |
| 8300 | // generic_proto_node->data.fn_proto.params.at(proto_i)->data.param_decl.is_inline) | | |
| 8301 | // { | | |
| 8302 | // continue; | | |
| 8303 | // } | | |
| 8304 | // AstNode *expr_node = node->data.fn_call_expr.params.at(call_i); | | |
| 8305 | // LLVMValueRef param_value = gen_expr(g, expr_node); | | |
| 8306 | // assert(param_value); | | |
| 8307 | // TypeTableEntry *param_type = get_expr_type(expr_node); | | |
| 8308 | // if (is_var_args || type_has_bits(param_type)) { | | |
| 8309 | // gen_param_values[gen_param_index] = param_value; | | |
| 8310 | // gen_param_index += 1; | | |
| 8311 | // } | | |
| 8312 | // } | | |
| 8313 | // | | |
| 8314 | // LLVMValueRef result = ZigLLVMBuildCall(g->builder, fn_val, | | |
| 8315 | // gen_param_values, gen_param_index, fn_type->data.fn.calling_convention, ""); | | |
| 8316 | // | | |
| 8317 | // if (src_return_type->id == TypeTableEntryIdUnreachable) { | | |
| 8318 | // return LLVMBuildUnreachable(g->builder); | | |
| 8319 | // } else if (!ret_has_bits) { | | |
| 8320 | // return nullptr; | | |
| 8321 | // } else if (first_arg_ret) { | | |
| 8322 | // return node->data.fn_call_expr.tmp_ptr; | | |
| 8323 | // } else { | | |
| 8324 | // return result; | | |
| 8325 | // } | | |
| 8326 | //} | | |
| 8327 | // | | |
| 8328 | //static LLVMValueRef gen_array_base_ptr(CodeGen *g, AstNode *node) { | 7866 | //static LLVMValueRef gen_array_base_ptr(CodeGen *g, AstNode *node) { |
| 8329 | // TypeTableEntry *type_entry = get_expr_type(node); | 7867 | // TypeTableEntry *type_entry = get_expr_type(node); |
| 8330 | // | 7868 | // |
| ... | @@ -8356,46 +7894,6 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) { | ... | @@ -8356,46 +7894,6 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) { |
| 8356 | // return gen_array_elem_ptr(g, node, array_ptr, array_type, subscript_value); | 7894 | // return gen_array_elem_ptr(g, node, array_ptr, array_type, subscript_value); |
| 8357 | //} | 7895 | //} |
| 8358 | // | 7896 | // |
| 8359 | //static LLVMValueRef gen_field_ptr(CodeGen *g, AstNode *node, TypeTableEntry **out_type_entry) { | | |
| 8360 | // assert(node->type == NodeTypeFieldAccessExpr); | | |
| 8361 | // | | |
| 8362 | // AstNode *struct_expr_node = node->data.field_access_expr.struct_expr; | | |
| 8363 | // | | |
| 8364 | // *out_type_entry = node->data.field_access_expr.type_struct_field->type_entry; | | |
| 8365 | // if (!type_has_bits(*out_type_entry)) { | | |
| 8366 | // return nullptr; | | |
| 8367 | // } | | |
| 8368 | // | | |
| 8369 | // LLVMValueRef struct_ptr; | | |
| 8370 | // if (struct_expr_node->type == NodeTypeSymbol) { | | |
| 8371 | // VariableTableEntry *var = get_resolved_expr(struct_expr_node)->variable; | | |
| 8372 | // assert(var); | | |
| 8373 | // | | |
| 8374 | // if (var->type->id == TypeTableEntryIdPointer) { | | |
| 8375 | // struct_ptr = LLVMBuildLoad(g->builder, var->value_ref, ""); | | |
| 8376 | // } else { | | |
| 8377 | // struct_ptr = var->value_ref; | | |
| 8378 | // } | | |
| 8379 | // } else if (struct_expr_node->type == NodeTypeFieldAccessExpr) { | | |
| 8380 | // struct_ptr = gen_field_access_expr(g, struct_expr_node, true); | | |
| 8381 | // TypeTableEntry *field_type = get_expr_type(struct_expr_node); | | |
| 8382 | // if (field_type->id == TypeTableEntryIdPointer) { | | |
| 8383 | // // we have a double pointer so we must dereference it once | | |
| 8384 | // struct_ptr = LLVMBuildLoad(g->builder, struct_ptr, ""); | | |
| 8385 | // } | | |
| 8386 | // } else { | | |
| 8387 | // struct_ptr = gen_expr(g, struct_expr_node); | | |
| 8388 | // } | | |
| 8389 | // | | |
| 8390 | // assert(LLVMGetTypeKind(LLVMTypeOf(struct_ptr)) == LLVMPointerTypeKind); | | |
| 8391 | // assert(LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(struct_ptr))) == LLVMStructTypeKind); | | |
| 8392 | // | | |
| 8393 | // size_t gen_field_index = node->data.field_access_expr.type_struct_field->gen_index; | | |
| 8394 | // assert(gen_field_index != SIZE_MAX); | | |
| 8395 | // | | |
| 8396 | // return LLVMBuildStructGEP(g->builder, struct_ptr, gen_field_index, ""); | | |
| 8397 | //} | | |
| 8398 | // | | |
| 8399 | //static LLVMValueRef gen_slice_expr(CodeGen *g, AstNode *node) { | 7897 | //static LLVMValueRef gen_slice_expr(CodeGen *g, AstNode *node) { |
| 8400 | // assert(node->type == NodeTypeSliceExpr); | 7898 | // assert(node->type == NodeTypeSliceExpr); |
| 8401 | // | 7899 | // |
| ... | @@ -8771,87 +8269,6 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) { | ... | @@ -8771,87 +8269,6 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) { |
| 8771 | // zig_unreachable(); | 8269 | // zig_unreachable(); |
| 8772 | //} | 8270 | //} |
| 8773 | // | 8271 | // |
| 8774 | //static LLVMValueRef gen_if_bool_expr_raw(CodeGen *g, AstNode *source_node, LLVMValueRef cond_value, | | |
| 8775 | // AstNode *then_node, AstNode *else_node) | | |
| 8776 | //{ | | |
| 8777 | // assert(then_node); | | |
| 8778 | // assert(else_node); | | |
| 8779 | // | | |
| 8780 | // TypeTableEntry *then_type = get_expr_type(then_node); | | |
| 8781 | // TypeTableEntry *else_type = get_expr_type(else_node); | | |
| 8782 | // | | |
| 8783 | // bool use_then_value = type_has_bits(then_type); | | |
| 8784 | // bool use_else_value = type_has_bits(else_type); | | |
| 8785 | // | | |
| 8786 | // LLVMBasicBlockRef then_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "Then"); | | |
| 8787 | // LLVMBasicBlockRef else_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "Else"); | | |
| 8788 | // | | |
| 8789 | // LLVMBasicBlockRef endif_block = nullptr; | | |
| 8790 | // bool then_endif_reachable = then_type->id != TypeTableEntryIdUnreachable; | | |
| 8791 | // bool else_endif_reachable = else_type->id != TypeTableEntryIdUnreachable; | | |
| 8792 | // if (then_endif_reachable || else_endif_reachable) { | | |
| 8793 | // endif_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "EndIf"); | | |
| 8794 | // } | | |
| 8795 | // | | |
| 8796 | // LLVMBuildCondBr(g->builder, cond_value, then_block, else_block); | | |
| 8797 | // | | |
| 8798 | // LLVMPositionBuilderAtEnd(g->builder, then_block); | | |
| 8799 | // LLVMValueRef then_expr_result = gen_expr(g, then_node); | | |
| 8800 | // if (then_endif_reachable) { | | |
| 8801 | // clear_debug_source_node(g); | | |
| 8802 | // LLVMBuildBr(g->builder, endif_block); | | |
| 8803 | // } | | |
| 8804 | // LLVMBasicBlockRef after_then_block = LLVMGetInsertBlock(g->builder); | | |
| 8805 | // | | |
| 8806 | // LLVMPositionBuilderAtEnd(g->builder, else_block); | | |
| 8807 | // LLVMValueRef else_expr_result = gen_expr(g, else_node); | | |
| 8808 | // if (else_endif_reachable) { | | |
| 8809 | // clear_debug_source_node(g); | | |
| 8810 | // LLVMBuildBr(g->builder, endif_block); | | |
| 8811 | // } | | |
| 8812 | // LLVMBasicBlockRef after_else_block = LLVMGetInsertBlock(g->builder); | | |
| 8813 | // | | |
| 8814 | // if (then_endif_reachable || else_endif_reachable) { | | |
| 8815 | // LLVMPositionBuilderAtEnd(g->builder, endif_block); | | |
| 8816 | // if (use_then_value && use_else_value) { | | |
| 8817 | // LLVMValueRef phi = LLVMBuildPhi(g->builder, LLVMTypeOf(then_expr_result), ""); | | |
| 8818 | // LLVMValueRef incoming_values[2] = {then_expr_result, else_expr_result}; | | |
| 8819 | // LLVMBasicBlockRef incoming_blocks[2] = {after_then_block, after_else_block}; | | |
| 8820 | // LLVMAddIncoming(phi, incoming_values, incoming_blocks, 2); | | |
| 8821 | // return phi; | | |
| 8822 | // } else if (use_then_value) { | | |
| 8823 | // return then_expr_result; | | |
| 8824 | // } else if (use_else_value) { | | |
| 8825 | // return else_expr_result; | | |
| 8826 | // } | | |
| 8827 | // } | | |
| 8828 | // | | |
| 8829 | // return nullptr; | | |
| 8830 | //} | | |
| 8831 | // | | |
| 8832 | //static LLVMValueRef gen_if_bool_expr(CodeGen *g, AstNode *node) { | | |
| 8833 | // assert(node->type == NodeTypeIfBoolExpr); | | |
| 8834 | // assert(node->data.if_bool_expr.condition); | | |
| 8835 | // assert(node->data.if_bool_expr.then_block); | | |
| 8836 | // | | |
| 8837 | // ConstExprValue *const_val = &get_resolved_expr(node->data.if_bool_expr.condition)->const_val; | | |
| 8838 | // if (const_val->ok) { | | |
| 8839 | // if (const_val->data.x_bool) { | | |
| 8840 | // return gen_expr(g, node->data.if_bool_expr.then_block); | | |
| 8841 | // } else if (node->data.if_bool_expr.else_node) { | | |
| 8842 | // return gen_expr(g, node->data.if_bool_expr.else_node); | | |
| 8843 | // } else { | | |
| 8844 | // return nullptr; | | |
| 8845 | // } | | |
| 8846 | // } else { | | |
| 8847 | // LLVMValueRef cond_value = gen_expr(g, node->data.if_bool_expr.condition); | | |
| 8848 | // | | |
| 8849 | // return gen_if_bool_expr_raw(g, node, cond_value, | | |
| 8850 | // node->data.if_bool_expr.then_block, | | |
| 8851 | // node->data.if_bool_expr.else_node); | | |
| 8852 | // } | | |
| 8853 | //} | | |
| 8854 | // | | |
| 8855 | //static LLVMValueRef gen_block(CodeGen *g, AstNode *block_node, TypeTableEntry *implicit_return_type) { | 8272 | //static LLVMValueRef gen_block(CodeGen *g, AstNode *block_node, TypeTableEntry *implicit_return_type) { |
| 8856 | // assert(block_node->type == NodeTypeBlock); | 8273 | // assert(block_node->type == NodeTypeBlock); |
| 8857 | // | 8274 | // |
| ... | @@ -8876,140 +8293,6 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) { | ... | @@ -8876,140 +8293,6 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) { |
| 8876 | // } | 8293 | // } |
| 8877 | //} | 8294 | //} |
| 8878 | // | 8295 | // |
| 8879 | //static LLVMValueRef gen_container_init_expr(CodeGen *g, AstNode *node) { | | |
| 8880 | // assert(node->type == NodeTypeContainerInitExpr); | | |
| 8881 | // | | |
| 8882 | // TypeTableEntry *type_entry = get_expr_type(node); | | |
| 8883 | // | | |
| 8884 | // | | |
| 8885 | // if (node->data.container_init_expr.enum_type) { | | |
| 8886 | // size_t param_count = node->data.container_init_expr.entries.length; | | |
| 8887 | // AstNode *arg1_node; | | |
| 8888 | // if (param_count == 1) { | | |
| 8889 | // arg1_node = node->data.container_init_expr.entries.at(0); | | |
| 8890 | // } else { | | |
| 8891 | // assert(param_count == 0); | | |
| 8892 | // arg1_node = nullptr; | | |
| 8893 | // } | | |
| 8894 | // return gen_enum_value_expr(g, node->data.container_init_expr.type, | | |
| 8895 | // node->data.container_init_expr.enum_type, arg1_node); | | |
| 8896 | // } | | |
| 8897 | // | | |
| 8898 | // | | |
| 8899 | // if (type_entry->id == TypeTableEntryIdStruct) { | | |
| 8900 | // assert(node->data.container_init_expr.kind == ContainerInitKindStruct); | | |
| 8901 | // | | |
| 8902 | // size_t src_field_count = type_entry->data.structure.src_field_count; | | |
| 8903 | // assert(src_field_count == node->data.container_init_expr.entries.length); | | |
| 8904 | // | | |
| 8905 | // StructValExprCodeGen *struct_val_expr_node = &node->data.container_init_expr.resolved_struct_val_expr; | | |
| 8906 | // LLVMValueRef tmp_struct_ptr = struct_val_expr_node->ptr; | | |
| 8907 | // | | |
| 8908 | // for (size_t i = 0; i < src_field_count; i += 1) { | | |
| 8909 | // AstNode *field_node = node->data.container_init_expr.entries.at(i); | | |
| 8910 | // assert(field_node->type == NodeTypeStructValueField); | | |
| 8911 | // TypeStructField *type_struct_field = field_node->data.struct_val_field.type_struct_field; | | |
| 8912 | // if (type_struct_field->type_entry->id == TypeTableEntryIdVoid) { | | |
| 8913 | // continue; | | |
| 8914 | // } | | |
| 8915 | // assert(buf_eql_buf(type_struct_field->name, field_node->data.struct_val_field.name)); | | |
| 8916 | // | | |
| 8917 | // set_debug_source_node(g, field_node); | | |
| 8918 | // LLVMValueRef field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, type_struct_field->gen_index, ""); | | |
| 8919 | // AstNode *expr_node = field_node->data.struct_val_field.expr; | | |
| 8920 | // LLVMValueRef value = gen_expr(g, expr_node); | | |
| 8921 | // gen_assign_raw(g, field_node, BinOpTypeAssign, field_ptr, value, | | |
| 8922 | // type_struct_field->type_entry, get_expr_type(expr_node)); | | |
| 8923 | // } | | |
| 8924 | // | | |
| 8925 | // return tmp_struct_ptr; | | |
| 8926 | // } else if (type_entry->id == TypeTableEntryIdVoid) { | | |
| 8927 | // assert(node->data.container_init_expr.entries.length == 0); | | |
| 8928 | // return nullptr; | | |
| 8929 | // } else if (type_entry->id == TypeTableEntryIdArray) { | | |
| 8930 | // StructValExprCodeGen *struct_val_expr_node = &node->data.container_init_expr.resolved_struct_val_expr; | | |
| 8931 | // LLVMValueRef tmp_array_ptr = struct_val_expr_node->ptr; | | |
| 8932 | // | | |
| 8933 | // size_t field_count = type_entry->data.array.len; | | |
| 8934 | // assert(field_count == node->data.container_init_expr.entries.length); | | |
| 8935 | // | | |
| 8936 | // TypeTableEntry *child_type = type_entry->data.array.child_type; | | |
| 8937 | // | | |
| 8938 | // for (size_t i = 0; i < field_count; i += 1) { | | |
| 8939 | // AstNode *field_node = node->data.container_init_expr.entries.at(i); | | |
| 8940 | // LLVMValueRef elem_val = gen_expr(g, field_node); | | |
| 8941 | // | | |
| 8942 | // LLVMValueRef indices[] = { | | |
| 8943 | // LLVMConstNull(g->builtin_types.entry_usize->type_ref), | | |
| 8944 | // LLVMConstInt(g->builtin_types.entry_usize->type_ref, i, false), | | |
| 8945 | // }; | | |
| 8946 | // set_debug_source_node(g, field_node); | | |
| 8947 | // LLVMValueRef elem_ptr = LLVMBuildInBoundsGEP(g->builder, tmp_array_ptr, indices, 2, ""); | | |
| 8948 | // gen_assign_raw(g, field_node, BinOpTypeAssign, elem_ptr, elem_val, | | |
| 8949 | // child_type, get_expr_type(field_node)); | | |
| 8950 | // } | | |
| 8951 | // | | |
| 8952 | // return tmp_array_ptr; | | |
| 8953 | // } else { | | |
| 8954 | // zig_unreachable(); | | |
| 8955 | // } | | |
| 8956 | //} | | |
| 8957 | // | | |
| 8958 | //static LLVMValueRef gen_while_expr(CodeGen *g, AstNode *node) { | | |
| 8959 | // assert(node->type == NodeTypeWhileExpr); | | |
| 8960 | // assert(node->data.while_expr.condition); | | |
| 8961 | // assert(node->data.while_expr.body); | | |
| 8962 | // | | |
| 8963 | // //AstNode *continue_expr_node = node->data.while_expr.continue_expr; | | |
| 8964 | // | | |
| 8965 | // bool condition_always_true = node->data.while_expr.condition_always_true; | | |
| 8966 | // //bool contains_break = node->data.while_expr.contains_break; | | |
| 8967 | // if (condition_always_true) { | | |
| 8968 | // // generate a forever loop | | |
| 8969 | // zig_panic("TODO IR"); | | |
| 8970 | // | | |
| 8971 | // //LLVMBasicBlockRef body_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "WhileBody"); | | |
| 8972 | // //LLVMBasicBlockRef continue_block = continue_expr_node ? | | |
| 8973 | // // LLVMAppendBasicBlock(g->cur_fn->fn_value, "WhileContinue") : body_block; | | |
| 8974 | // //LLVMBasicBlockRef end_block = nullptr; | | |
| 8975 | // //if (contains_break) { | | |
| 8976 | // // end_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "WhileEnd"); | | |
| 8977 | // //} | | |
| 8978 | // | | |
| 8979 | // //set_debug_source_node(g, node); | | |
| 8980 | // //LLVMBuildBr(g->builder, body_block); | | |
| 8981 | // | | |
| 8982 | // //if (continue_expr_node) { | | |
| 8983 | // // LLVMPositionBuilderAtEnd(g->builder, continue_block); | | |
| 8984 | // | | |
| 8985 | // // gen_expr(g, continue_expr_node); | | |
| 8986 | // | | |
| 8987 | // // set_debug_source_node(g, node); | | |
| 8988 | // // LLVMBuildBr(g->builder, body_block); | | |
| 8989 | // //} | | |
| 8990 | // | | |
| 8991 | // //LLVMPositionBuilderAtEnd(g->builder, body_block); | | |
| 8992 | // //g->break_block_stack.append(end_block); | | |
| 8993 | // //g->continue_block_stack.append(continue_block); | | |
| 8994 | // //gen_expr(g, node->data.while_expr.body); | | |
| 8995 | // //g->break_block_stack.pop(); | | |
| 8996 | // //g->continue_block_stack.pop(); | | |
| 8997 | // | | |
| 8998 | // //if (get_expr_type(node->data.while_expr.body)->id != TypeTableEntryIdUnreachable) { | | |
| 8999 | // // set_debug_source_node(g, node); | | |
| 9000 | // // LLVMBuildBr(g->builder, continue_block); | | |
| 9001 | // //} | | |
| 9002 | // | | |
| 9003 | // //if (contains_break) { | | |
| 9004 | // // LLVMPositionBuilderAtEnd(g->builder, end_block); | | |
| 9005 | // //} | | |
| 9006 | // } else { | | |
| 9007 | // zig_panic("moved to ir.cpp"); | | |
| 9008 | // } | | |
| 9009 | // | | |
| 9010 | // return nullptr; | | |
| 9011 | //} | | |
| 9012 | | | |
| 9013 | //static LLVMValueRef gen_break(CodeGen *g, AstNode *node) { | 8296 | //static LLVMValueRef gen_break(CodeGen *g, AstNode *node) { |
| 9014 | // assert(node->type == NodeTypeBreak); | 8297 | // assert(node->type == NodeTypeBreak); |
| 9015 | // LLVMBasicBlockRef dest_block = g->break_block_stack.last(); | 8298 | // LLVMBasicBlockRef dest_block = g->break_block_stack.last(); |
| ... | @@ -9164,44 +8447,6 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) { | ... | @@ -9164,44 +8447,6 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) { |
| 9164 | // } | 8447 | // } |
| 9165 | //} | 8448 | //} |
| 9166 | // | 8449 | // |
| 9167 | //static LLVMValueRef gen_field_access_expr(CodeGen *g, AstNode *node, bool is_lvalue) { | | |
| 9168 | // assert(node->type == NodeTypeFieldAccessExpr); | | |
| 9169 | // | | |
| 9170 | // AstNode *struct_expr = node->data.field_access_expr.struct_expr; | | |
| 9171 | // TypeTableEntry *struct_type = get_expr_type(struct_expr); | | |
| 9172 | // | | |
| 9173 | // if (struct_type->id == TypeTableEntryIdArray) { | | |
| 9174 | // Buf *name = node->data.field_access_expr.field_name; | | |
| 9175 | // assert(buf_eql_str(name, "len")); | | |
| 9176 | // return LLVMConstInt(g->builtin_types.entry_usize->type_ref, | | |
| 9177 | // struct_type->data.array.len, false); | | |
| 9178 | // } else if (struct_type->id == TypeTableEntryIdStruct || (struct_type->id == TypeTableEntryIdPointer && | | |
| 9179 | // struct_type->data.pointer.child_type->id == TypeTableEntryIdStruct)) | | |
| 9180 | // { | | |
| 9181 | // TypeTableEntry *type_entry; | | |
| 9182 | // LLVMValueRef ptr = gen_field_ptr(g, node, &type_entry); | | |
| 9183 | // if (is_lvalue || handle_is_ptr(type_entry)) { | | |
| 9184 | // return ptr; | | |
| 9185 | // } else { | | |
| 9186 | // return LLVMBuildLoad(g->builder, ptr, ""); | | |
| 9187 | // } | | |
| 9188 | // } else if (struct_type->id == TypeTableEntryIdMetaType) { | | |
| 9189 | // assert(!is_lvalue); | | |
| 9190 | // TypeTableEntry *child_type = get_type_for_type_node(struct_expr); | | |
| 9191 | // if (child_type->id == TypeTableEntryIdEnum) { | | |
| 9192 | // return gen_enum_value_expr(g, node, child_type, nullptr); | | |
| 9193 | // } else { | | |
| 9194 | // zig_unreachable(); | | |
| 9195 | // } | | |
| 9196 | // } else if (struct_type->id == TypeTableEntryIdNamespace) { | | |
| 9197 | // VariableTableEntry *variable = get_resolved_expr(node)->variable; | | |
| 9198 | // assert(variable); | | |
| 9199 | // return gen_variable(g, node, variable); | | |
| 9200 | // } else { | | |
| 9201 | // zig_unreachable(); | | |
| 9202 | // } | | |
| 9203 | //} | | |
| 9204 | // | | |
| 9205 | //static LLVMValueRef gen_return(CodeGen *g, AstNode *source_node, LLVMValueRef value, ReturnKnowledge rk) { | 8450 | //static LLVMValueRef gen_return(CodeGen *g, AstNode *source_node, LLVMValueRef value, ReturnKnowledge rk) { |
| 9206 | // BlockContext *defer_inner_block = source_node->block_context; | 8451 | // BlockContext *defer_inner_block = source_node->block_context; |
| 9207 | // BlockContext *defer_outer_block = source_node->block_context->fn_entry->fn_def_node->block_context; | 8452 | // BlockContext *defer_outer_block = source_node->block_context->fn_entry->fn_def_node->block_context; |