| ... | ... | @@ -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 | 56 | static void ir_instruction_append(IrBasicBlock *basic_block, IrInstruction *instruction) { |
| 53 | 57 | assert(basic_block); |
| 54 | 58 | assert(instruction); |
| ... | ... | @@ -160,6 +164,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionStructFieldPtr * |
| 160 | 164 | return IrInstructionIdStructFieldPtr; |
| 161 | 165 | } |
| 162 | 166 | |
| 167 | static constexpr IrInstructionId ir_instruction_id(IrInstructionEnumFieldPtr *) { |
| 168 | return IrInstructionIdEnumFieldPtr; |
| 169 | } |
| 170 | |
| 163 | 171 | static constexpr IrInstructionId ir_instruction_id(IrInstructionElemPtr *) { |
| 164 | 172 | return IrInstructionIdElemPtr; |
| 165 | 173 | } |
| ... | ... | @@ -276,6 +284,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionRef *) { |
| 276 | 284 | return IrInstructionIdRef; |
| 277 | 285 | } |
| 278 | 286 | |
| 287 | static constexpr IrInstructionId ir_instruction_id(IrInstructionStructInit *) { |
| 288 | return IrInstructionIdStructInit; |
| 289 | } |
| 290 | |
| 279 | 291 | template<typename T> |
| 280 | 292 | static T *ir_create_instruction(IrExecutable *exec, AstNode *source_node) { |
| 281 | 293 | T *special_instruction = allocate<T>(1); |
| ... | ... | @@ -293,15 +305,14 @@ static T *ir_build_instruction(IrBuilder *irb, AstNode *source_node) { |
| 293 | 305 | return special_instruction; |
| 294 | 306 | } |
| 295 | 307 | |
| 296 | | static IrInstruction *ir_build_cast(IrBuilder *irb, AstNode *source_node, IrInstruction *dest_type, |
| 297 | | IrInstruction *value, CastOp cast_op) |
| 308 | static IrInstruction *ir_build_cast(IrBuilder *irb, AstNode *source_node, TypeTableEntry *dest_type, |
| 309 | IrInstruction *value, CastOp cast_op) |
| 298 | 310 | { |
| 299 | 311 | IrInstructionCast *cast_instruction = ir_build_instruction<IrInstructionCast>(irb, source_node); |
| 300 | 312 | cast_instruction->dest_type = dest_type; |
| 301 | 313 | cast_instruction->value = value; |
| 302 | 314 | cast_instruction->cast_op = cast_op; |
| 303 | 315 | |
| 304 | | ir_ref_instruction(dest_type); |
| 305 | 316 | ir_ref_instruction(value); |
| 306 | 317 | |
| 307 | 318 | return &cast_instruction->base; |
| ... | ... | @@ -353,10 +364,14 @@ static IrInstruction *ir_build_return_from(IrBuilder *irb, IrInstruction *old_in |
| 353 | 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 | 371 | IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(irb->exec, source_node); |
| 358 | 372 | const_instruction->base.type_entry = type_entry; |
| 359 | 373 | const_instruction->base.static_value.special = ConstValSpecialStatic; |
| 374 | const_instruction->base.static_value.depends_on_compile_var = depends_on_compile_var; |
| 360 | 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 | 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 | 482 | static IrInstruction *ir_build_const_str_lit(IrBuilder *irb, AstNode *source_node, Buf *str) { |
| 456 | 483 | IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, source_node); |
| 457 | 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 | 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 | 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 | 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 | 652 | call_instruction->arg_count = arg_count; |
| 604 | 653 | call_instruction->args = args; |
| 605 | 654 | |
| 606 | | ir_ref_instruction(fn); |
| 607 | | for (size_t i = 0; i < arg_count; i += 1) { |
| 655 | if (fn_ref) |
| 656 | ir_ref_instruction(fn_ref); |
| 657 | for (size_t i = 0; i < arg_count; i += 1) |
| 608 | 658 | ir_ref_instruction(args[i]); |
| 609 | | } |
| 610 | 659 | |
| 611 | 660 | return &call_instruction->base; |
| 612 | 661 | } |
| 613 | 662 | |
| 614 | 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 | 667 | ir_link_new_instruction(new_instruction, old_instruction); |
| 619 | 668 | return new_instruction; |
| 620 | 669 | } |
| ... | ... | @@ -706,24 +755,55 @@ static IrInstruction *ir_build_container_init_list(IrBuilder *irb, AstNode *sour |
| 706 | 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 | 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 | 770 | IrInstructionContainerInitFields *container_init_fields_instruction = |
| 713 | 771 | ir_build_instruction<IrInstructionContainerInitFields>(irb, source_node); |
| 714 | 772 | container_init_fields_instruction->container_type = container_type; |
| 715 | 773 | container_init_fields_instruction->field_count = field_count; |
| 716 | | container_init_fields_instruction->field_names = field_names; |
| 717 | | container_init_fields_instruction->field_values = field_values; |
| 774 | container_init_fields_instruction->fields = fields; |
| 718 | 775 | |
| 719 | 776 | ir_ref_instruction(container_type); |
| 720 | 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 | 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 | 807 | static IrInstruction *ir_build_unreachable(IrBuilder *irb, AstNode *source_node) { |
| 728 | 808 | IrInstructionUnreachable *unreachable_instruction = |
| 729 | 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 | 1522 | ref_instruction = ir_build_const_fn(irb, source_node, fn_entry); |
| 1443 | 1523 | } |
| 1444 | 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 | 1526 | else |
| 1447 | 1527 | return ref_instruction; |
| 1448 | 1528 | } else if (decl_node->type == NodeTypeContainerDecl) { |
| ... | ... | @@ -1455,14 +1535,14 @@ static IrInstruction *ir_gen_decl_ref(IrBuilder *irb, AstNode *source_node, AstN |
| 1455 | 1535 | ref_instruction = ir_build_const_type(irb, source_node, decl_node->data.struct_decl.type_entry); |
| 1456 | 1536 | } |
| 1457 | 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 | 1539 | else |
| 1460 | 1540 | return ref_instruction; |
| 1461 | 1541 | } else if (decl_node->type == NodeTypeTypeDecl) { |
| 1462 | 1542 | TypeTableEntry *child_type = decl_node->data.type_decl.child_type_entry; |
| 1463 | 1543 | IrInstruction *ref_instruction = ir_build_const_type(irb, source_node, child_type); |
| 1464 | 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 | 1546 | else |
| 1467 | 1547 | return ref_instruction; |
| 1468 | 1548 | } else { |
| ... | ... | @@ -1712,7 +1792,6 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, AstNode *node) { |
| 1712 | 1792 | case BuiltinFnIdDivExact: |
| 1713 | 1793 | case BuiltinFnIdTruncate: |
| 1714 | 1794 | case BuiltinFnIdIntType: |
| 1715 | | case BuiltinFnIdSetFnStaticEval: |
| 1716 | 1795 | case BuiltinFnIdSetFnNoInline: |
| 1717 | 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 | 1805 | return ir_gen_builtin_fn_call(irb, node); |
| 1727 | 1806 | |
| 1728 | 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); |
| 1730 | | if (fn == irb->codegen->invalid_instruction) |
| 1731 | | return fn; |
| 1808 | IrInstruction *fn_ref = ir_gen_node(irb, fn_ref_node, node->block_context); |
| 1809 | if (fn_ref == irb->codegen->invalid_instruction) |
| 1810 | return fn_ref; |
| 1732 | 1811 | |
| 1733 | 1812 | size_t arg_count = node->data.fn_call_expr.params.length; |
| 1734 | 1813 | IrInstruction **args = allocate<IrInstruction*>(arg_count); |
| ... | ... | @@ -1737,7 +1816,7 @@ static IrInstruction *ir_gen_fn_call(IrBuilder *irb, AstNode *node) { |
| 1737 | 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 | 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 | 1833 | IrBasicBlock *else_block = ir_build_basic_block(irb, "Else"); |
| 1755 | 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 | 1837 | ir_build_cond_br(irb, condition->source_node, condition, then_block, else_block, is_inline); |
| 1759 | 1838 | |
| 1760 | 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 | 1944 | |
| 1866 | 1945 | if (kind == ContainerInitKindStruct) { |
| 1867 | 1946 | size_t field_count = container_init_expr->entries.length; |
| 1868 | | IrInstruction **values = allocate<IrInstruction *>(field_count); |
| 1869 | | Buf **names = allocate<Buf *>(field_count); |
| 1947 | IrInstructionContainerInitFieldsField *fields = allocate<IrInstructionContainerInitFieldsField>(field_count); |
| 1870 | 1948 | for (size_t i = 0; i < field_count; i += 1) { |
| 1871 | 1949 | AstNode *entry_node = container_init_expr->entries.at(i); |
| 1872 | 1950 | assert(entry_node->type == NodeTypeStructValueField); |
| ... | ... | @@ -1877,10 +1955,11 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, AstNode *node) |
| 1877 | 1955 | if (expr_value == irb->codegen->invalid_instruction) |
| 1878 | 1956 | return expr_value; |
| 1879 | 1957 | |
| 1880 | | names[i] = name; |
| 1881 | | values[i] = expr_value; |
| 1958 | fields[i].name = name; |
| 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 | 1963 | } else if (kind == ContainerInitKindArray) { |
| 1885 | 1964 | size_t item_count = container_init_expr->entries.length; |
| 1886 | 1965 | IrInstruction **values = allocate<IrInstruction *>(item_count); |
| ... | ... | @@ -1919,7 +1998,7 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, AstNode *node) { |
| 1919 | 1998 | bool is_shadowable = false; |
| 1920 | 1999 | bool is_const = variable_declaration->is_const; |
| 1921 | 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 | 2002 | VariableTableEntry *var = ir_add_local_var(irb, node, node->block_context, |
| 1924 | 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 | 2022 | ir_build_basic_block(irb, "WhileContinue") : cond_block; |
| 1944 | 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 | 2026 | ir_build_br(irb, node, cond_block, is_inline); |
| 1948 | 2027 | |
| 1949 | 2028 | if (continue_expr_node) { |
| ... | ... | @@ -1998,7 +2077,7 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, AstNode *node) { |
| 1998 | 2077 | } else { |
| 1999 | 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 | 2082 | BlockContext *child_scope = new_block_context(node, parent_scope); |
| 2004 | 2083 | child_scope->parent_loop_node = node; |
| ... | ... | @@ -2219,7 +2298,7 @@ static IrInstruction *ir_gen_if_var_expr(IrBuilder *irb, AstNode *node) { |
| 2219 | 2298 | IrBasicBlock *else_block = ir_build_basic_block(irb, "MaybeElse"); |
| 2220 | 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 | 2302 | ir_build_cond_br(irb, node, is_nonnull_value, then_block, else_block, is_inline); |
| 2224 | 2303 | |
| 2225 | 2304 | ir_set_cursor_at_end(irb, then_block); |
| ... | ... | @@ -2322,7 +2401,7 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, AstNode *node) { |
| 2322 | 2401 | |
| 2323 | 2402 | size_t prong_count = node->data.switch_expr.prongs.length; |
| 2324 | 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 | 2406 | ZigList<IrInstruction *> incoming_values = {0}; |
| 2328 | 2407 | ZigList<IrBasicBlock *> incoming_blocks = {0}; |
| ... | ... | @@ -2495,7 +2574,7 @@ static IrInstruction *ir_gen_label(IrBuilder *irb, AstNode *node) { |
| 2495 | 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 | 2578 | ir_build_br(irb, node, label_block, is_inline); |
| 2500 | 2579 | ir_set_cursor_at_end(irb, label_block); |
| 2501 | 2580 | return ir_build_const_void(irb, node); |
| ... | ... | @@ -2535,56 +2614,58 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, BlockContex |
| 2535 | 2614 | node->block_context = block_context; |
| 2536 | 2615 | |
| 2537 | 2616 | switch (node->type) { |
| 2617 | case NodeTypeStructValueField: |
| 2618 | zig_unreachable(); |
| 2538 | 2619 | case NodeTypeBlock: |
| 2539 | | return ir_gen_block(irb, node); |
| 2620 | return ir_lval_wrap(irb, ir_gen_block(irb, node), lval); |
| 2540 | 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 | 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 | 2625 | case NodeTypeSymbol: |
| 2545 | 2626 | return ir_gen_symbol(irb, node, lval); |
| 2546 | 2627 | case NodeTypeFnCallExpr: |
| 2547 | 2628 | return ir_lval_wrap(irb, ir_gen_fn_call(irb, node), lval); |
| 2548 | 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 | 2631 | case NodeTypePrefixOpExpr: |
| 2551 | 2632 | return ir_gen_prefix_op_expr(irb, node, lval); |
| 2552 | 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 | 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 | 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 | 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 | 2641 | case NodeTypeArrayAccessExpr: |
| 2561 | 2642 | return ir_gen_array_access(irb, node, lval); |
| 2562 | 2643 | case NodeTypeReturnExpr: |
| 2563 | | return ir_gen_return(irb, node); |
| 2644 | return ir_lval_wrap(irb, ir_gen_return(irb, node), lval); |
| 2564 | 2645 | case NodeTypeFieldAccessExpr: |
| 2565 | 2646 | return ir_gen_field_access(irb, node, lval); |
| 2566 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 2665 | case NodeTypeLabel: |
| 2585 | | return ir_gen_label(irb, node); |
| 2666 | return ir_lval_wrap(irb, ir_gen_label(irb, node), lval); |
| 2586 | 2667 | case NodeTypeGoto: |
| 2587 | | return ir_gen_goto(irb, node); |
| 2668 | return ir_lval_wrap(irb, ir_gen_goto(irb, node), lval); |
| 2588 | 2669 | case NodeTypeTypeLiteral: |
| 2589 | 2670 | return ir_lval_wrap(irb, ir_gen_type_literal(irb, node), lval); |
| 2590 | 2671 | case NodeTypeUnwrapErrorExpr: |
| ... | ... | @@ -2604,7 +2685,6 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, BlockContex |
| 2604 | 2685 | case NodeTypeUse: |
| 2605 | 2686 | case NodeTypeContainerDecl: |
| 2606 | 2687 | case NodeTypeStructField: |
| 2607 | | case NodeTypeStructValueField: |
| 2608 | 2688 | case NodeTypeSwitchProng: |
| 2609 | 2689 | case NodeTypeSwitchRange: |
| 2610 | 2690 | case NodeTypeErrorValueDecl: |
| ... | ... | @@ -2642,7 +2722,7 @@ static bool ir_goto_pass2(IrBuilder *irb) { |
| 2642 | 2722 | } |
| 2643 | 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 | 2726 | IrInstruction *new_instruction = ir_create_br(irb, goto_node, label->bb, is_inline); |
| 2647 | 2727 | new_instruction->ref_count = old_instruction->ref_count; |
| 2648 | 2728 | *slot = new_instruction; |
| ... | ... | @@ -2703,6 +2783,21 @@ IrInstruction *ir_gen_fn(CodeGen *codegn, FnTableEntry *fn_entry) { |
| 2703 | 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 | 2801 | static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstruction *instruction, TypeTableEntry *other_type) { |
| 2707 | 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 | 3013 | } |
| 2919 | 3014 | |
| 2920 | 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 | 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 | 3020 | eval_const_expr_implicit_cast(cast_op, &value->static_value, value->type_entry, |
| 2930 | 3021 | &result->static_value, wanted_type); |
| 2931 | 3022 | return result; |
| 2932 | 3023 | } else { |
| 2933 | | IrInstruction *result = ir_build_cast(&ira->new_irb, source_instr->source_node, |
| 2934 | | dest_type, value, cast_op); |
| 3024 | IrInstruction *result = ir_build_cast(&ira->new_irb, source_instr->source_node, wanted_type, value, cast_op); |
| 2935 | 3025 | result->type_entry = wanted_type; |
| 2936 | 3026 | if (need_alloca && source_instr->source_node->block_context->fn_entry) { |
| 2937 | 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 | 3216 | } |
| 3127 | 3217 | |
| 3128 | 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 | 3221 | TypeTableEntry *actual_type = value->type_entry; |
| 3136 | 3222 | TypeTableEntry *wanted_type_canon = get_underlying_type(wanted_type); |
| 3137 | 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 | 3233 | |
| 3148 | 3234 | // explicit match or non-const to const |
| 3149 | 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 | 3239 | // explicit cast from bool to int |
| 3154 | 3240 | if (wanted_type_canon->id == TypeTableEntryIdInt && |
| 3155 | 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 | 3246 | // explicit cast from pointer to isize or usize |
| 3161 | 3247 | if ((wanted_type_canon == isize_type || wanted_type_canon == usize_type) && |
| 3162 | 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 | 3255 | if (wanted_type_canon->id == TypeTableEntryIdPointer && |
| 3170 | 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 | 3261 | // explicit widening or shortening cast |
| ... | ... | @@ -3178,21 +3264,21 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 3178 | 3264 | (wanted_type_canon->id == TypeTableEntryIdFloat && |
| 3179 | 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 | 3270 | // explicit cast from int to float |
| 3185 | 3271 | if (wanted_type_canon->id == TypeTableEntryIdFloat && |
| 3186 | 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 | 3277 | // explicit cast from float to int |
| 3192 | 3278 | if (wanted_type_canon->id == TypeTableEntryIdInt && |
| 3193 | 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 | 3284 | // explicit cast from array to slice |
| ... | ... | @@ -3202,7 +3288,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 3202 | 3288 | wanted_type->data.structure.fields[0].type_entry->data.pointer.child_type, |
| 3203 | 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 | 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 | 3298 | (wanted_type->data.structure.fields[0].type_entry->data.pointer.is_const || |
| 3213 | 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); |
| 3216 | | return ir_resolve_cast(ira, source_instr, value, dest_type, CastOpResizeSlice, true); |
| 3301 | if (!ir_emit_global_runtime_side_effect(ira, source_instr)) |
| 3302 | return ira->codegen->invalid_instruction; |
| 3303 | return ir_resolve_cast(ira, source_instr, value, wanted_type, CastOpResizeSlice, true); |
| 3217 | 3304 | } |
| 3218 | 3305 | |
| 3219 | 3306 | // explicit cast from [N]u8 to []T |
| ... | ... | @@ -3221,11 +3308,12 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 3221 | 3308 | actual_type->id == TypeTableEntryIdArray && |
| 3222 | 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 | 3313 | uint64_t child_type_size = type_size(ira->codegen, |
| 3226 | 3314 | wanted_type->data.structure.fields[0].type_entry->data.pointer.child_type); |
| 3227 | 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 | 3317 | } else { |
| 3230 | 3318 | add_node_error(ira->codegen, source_instr->source_node, |
| 3231 | 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 | 3326 | if ((actual_type->id == TypeTableEntryIdPointer || actual_type->id == TypeTableEntryIdFn) && |
| 3239 | 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 | 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 | 3337 | (wanted_type->data.maybe.child_type->id == TypeTableEntryIdPointer || |
| 3250 | 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 | 3343 | // explicit cast from child type of maybe type to maybe type |
| 3256 | 3344 | if (wanted_type->id == TypeTableEntryIdMaybe) { |
| 3257 | 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 | 3347 | CastOpMaybeWrap, true); |
| 3260 | 3348 | cast_instruction->return_knowledge = ReturnKnowledgeKnownNonNull; |
| 3261 | 3349 | return cast_instruction; |
| ... | ... | @@ -3263,7 +3351,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 3263 | 3351 | actual_type->id == TypeTableEntryIdNumLitFloat) |
| 3264 | 3352 | { |
| 3265 | 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 | 3355 | CastOpMaybeWrap, true); |
| 3268 | 3356 | cast_instruction->return_knowledge = ReturnKnowledgeKnownNonNull; |
| 3269 | 3357 | return cast_instruction; |
| ... | ... | @@ -3277,7 +3365,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 3277 | 3365 | if (wanted_type->id == TypeTableEntryIdMaybe && |
| 3278 | 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 | 3369 | CastOpNullToMaybe, true); |
| 3282 | 3370 | cast_instruction->return_knowledge = ReturnKnowledgeKnownNull; |
| 3283 | 3371 | return cast_instruction; |
| ... | ... | @@ -3286,7 +3374,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 3286 | 3374 | // explicit cast from child type of error type to error type |
| 3287 | 3375 | if (wanted_type->id == TypeTableEntryIdErrorUnion) { |
| 3288 | 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 | 3378 | CastOpErrorWrap, true); |
| 3291 | 3379 | cast_instruction->return_knowledge = ReturnKnowledgeKnownNonError; |
| 3292 | 3380 | return cast_instruction; |
| ... | ... | @@ -3294,7 +3382,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 3294 | 3382 | actual_type->id == TypeTableEntryIdNumLitFloat) |
| 3295 | 3383 | { |
| 3296 | 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 | 3386 | CastOpErrorWrap, true); |
| 3299 | 3387 | cast_instruction->return_knowledge = ReturnKnowledgeKnownNonError; |
| 3300 | 3388 | return cast_instruction; |
| ... | ... | @@ -3308,7 +3396,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 3308 | 3396 | if (wanted_type->id == TypeTableEntryIdErrorUnion && |
| 3309 | 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 | 3400 | CastOpPureErrorWrap, false); |
| 3313 | 3401 | cast_instruction->return_knowledge = ReturnKnowledgeKnownError; |
| 3314 | 3402 | return cast_instruction; |
| ... | ... | @@ -3333,7 +3421,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 3333 | 3421 | } else { |
| 3334 | 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 | 3425 | } else { |
| 3338 | 3426 | return ira->codegen->invalid_instruction; |
| 3339 | 3427 | } |
| ... | ... | @@ -3351,7 +3439,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 3351 | 3439 | if (bignum_fits_in_bits(&bn, wanted_type->data.integral.bit_count, |
| 3352 | 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 | 3443 | } else { |
| 3356 | 3444 | add_node_error(ira->codegen, source_instr->source_node, |
| 3357 | 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 | 3452 | wanted_type->id == TypeTableEntryIdEnum && |
| 3365 | 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 | 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 | 3460 | actual_type->id == TypeTableEntryIdEnum && |
| 3373 | 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 | 3466 | // explicit cast from undefined to anything |
| 3379 | 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 | 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 | 3498 | return ira->codegen->invalid_instruction; |
| 3411 | 3499 | |
| 3412 | 3500 | case ImplicitCastMatchResultYes: |
| 3413 | | { |
| 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 | | } |
| 3501 | return ir_analyze_cast(ira, value, expected_type, value); |
| 3418 | 3502 | case ImplicitCastMatchResultReportedError: |
| 3419 | 3503 | return ira->codegen->invalid_instruction; |
| 3420 | 3504 | } |
| ... | ... | @@ -3422,6 +3506,58 @@ static IrInstruction *ir_get_casted_value(IrAnalyze *ira, IrInstruction *value, |
| 3422 | 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 | 3561 | static bool ir_resolve_usize(IrAnalyze *ira, IrInstruction *value, uint64_t *out) { |
| 3426 | 3562 | if (value->type_entry->id == TypeTableEntryIdInvalid) |
| 3427 | 3563 | return false; |
| ... | ... | @@ -3580,6 +3716,7 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp |
| 3580 | 3716 | case TypeTableEntryIdNamespace: |
| 3581 | 3717 | case TypeTableEntryIdBlock: |
| 3582 | 3718 | case TypeTableEntryIdGenericFn: |
| 3719 | case TypeTableEntryIdBoundFn: |
| 3583 | 3720 | if (!is_equality_cmp) { |
| 3584 | 3721 | add_node_error(ira->codegen, source_node, |
| 3585 | 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 | 4081 | case TypeTableEntryIdUnion: |
| 3945 | 4082 | case TypeTableEntryIdFn: |
| 3946 | 4083 | case TypeTableEntryIdGenericFn: |
| 4084 | case TypeTableEntryIdBoundFn: |
| 3947 | 4085 | // OK |
| 3948 | 4086 | break; |
| 3949 | 4087 | } |
| ... | ... | @@ -3966,13 +4104,121 @@ static TypeTableEntry *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruc |
| 3966 | 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 | 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 | 4211 | if (fn_ref->type_entry->id == TypeTableEntryIdInvalid) |
| 3972 | 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 | 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 | 4222 | size_t actual_param_count = call_instruction->arg_count; |
| 3977 | 4223 | |
| 3978 | 4224 | if (actual_param_count != 1) { |
| ... | ... | @@ -3982,38 +4228,39 @@ static TypeTableEntry *ir_analyze_instruction_call(IrAnalyze *ira, IrInstruction |
| 3982 | 4228 | } |
| 3983 | 4229 | |
| 3984 | 4230 | IrInstruction *arg = call_instruction->args[0]->other; |
| 3985 | | IrInstruction *cast_instruction = ir_analyze_cast(ira, &call_instruction->base, fn_ref, arg); |
| 3986 | | if (cast_instruction == ira->codegen->invalid_instruction) |
| 4231 | |
| 4232 | IrInstruction *cast_instruction = ir_analyze_cast(ira, &call_instruction->base, dest_type, arg); |
| 4233 | if (cast_instruction->type_entry->id == TypeTableEntryIdInvalid) |
| 3987 | 4234 | return ira->codegen->builtin_types.entry_invalid; |
| 3988 | 4235 | |
| 3989 | 4236 | ir_link_new_instruction(cast_instruction, &call_instruction->base); |
| 3990 | 4237 | return ir_finish_anal(ira, cast_instruction->type_entry); |
| 3991 | 4238 | } else if (fn_ref->type_entry->id == TypeTableEntryIdFn) { |
| 3992 | | // TODO fully port over the fn call analyze code to IR |
| 3993 | | FnTableEntry *fn_table_entry = fn_ref->static_value.data.x_fn; |
| 3994 | | TypeTableEntry *fn_type = fn_table_entry->type_entry; |
| 3995 | | |
| 3996 | | IrInstruction **casted_args = allocate<IrInstruction *>(call_instruction->arg_count); |
| 3997 | | for (size_t i = 0; i < call_instruction->arg_count; i += 1) { |
| 3998 | | TypeTableEntry *param_type = fn_type->data.fn.fn_type_id.param_info[i].type; |
| 3999 | | IrInstruction *old_arg = call_instruction->args[i]->other; |
| 4000 | | if (old_arg->type_entry->id == TypeTableEntryIdInvalid) |
| 4001 | | return ira->codegen->builtin_types.entry_invalid; |
| 4002 | | casted_args[i] = ir_get_casted_value(ira, old_arg, param_type); |
| 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); |
| 4239 | FnTableEntry *fn_table_entry = ir_resolve_fn(ira, fn_ref); |
| 4240 | return ir_analyze_fn_call(ira, call_instruction, fn_table_entry, fn_table_entry->type_entry, |
| 4241 | fn_ref, nullptr, is_inline); |
| 4242 | } else if (fn_ref->type_entry->id == TypeTableEntryIdBoundFn) { |
| 4243 | assert(fn_ref->static_value.special == ConstValSpecialStatic); |
| 4244 | FnTableEntry *fn_table_entry = fn_ref->static_value.data.x_bound_fn.fn; |
| 4245 | IrInstruction *first_arg_ptr = fn_ref->static_value.data.x_bound_fn.first_arg; |
| 4246 | return ir_analyze_fn_call(ira, call_instruction, fn_table_entry, fn_table_entry->type_entry, |
| 4247 | nullptr, first_arg_ptr, is_inline); |
| 4248 | } else if (fn_ref->type_entry->id == TypeTableEntryIdGenericFn) { |
| 4249 | zig_panic("TODO generic fn call"); |
| 4009 | 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 { |
| 4013 | | //ir_build_call_from(&ira->new_irb, &call_instruction->base, |
| 4014 | | // call_instruction->fn, call_instruction->arg_count, call_instruction->args); |
| 4255 | } |
| 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 | 4318 | case TypeTableEntryIdUnion: |
| 4072 | 4319 | case TypeTableEntryIdFn: |
| 4073 | 4320 | case TypeTableEntryIdGenericFn: |
| 4321 | case TypeTableEntryIdBoundFn: |
| 4074 | 4322 | { |
| 4075 | 4323 | ConstExprValue *out_val = ir_build_const_from(ira, &un_op_instruction->base, |
| 4076 | 4324 | value->static_value.depends_on_compile_var); |
| ... | ... | @@ -4119,6 +4367,7 @@ static TypeTableEntry *ir_analyze_unary_address_of(IrAnalyze *ira, IrInstruction |
| 4119 | 4367 | case TypeTableEntryIdUnreachable: |
| 4120 | 4368 | case TypeTableEntryIdVar: |
| 4121 | 4369 | case TypeTableEntryIdGenericFn: |
| 4370 | case TypeTableEntryIdBoundFn: |
| 4122 | 4371 | add_node_error(ira->codegen, un_op_instruction->base.source_node, |
| 4123 | 4372 | buf_sprintf("unable to get address of type '%s'", buf_ptr(&target_type->name))); |
| 4124 | 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 | 4466 | case TypeTableEntryIdNamespace: |
| 4218 | 4467 | case TypeTableEntryIdBlock: |
| 4219 | 4468 | case TypeTableEntryIdGenericFn: |
| 4469 | case TypeTableEntryIdBoundFn: |
| 4220 | 4470 | { |
| 4221 | 4471 | ConstExprValue *out_val = ir_build_const_from(ira, &un_op_instruction->base, |
| 4222 | 4472 | value->static_value.depends_on_compile_var); |
| ... | ... | @@ -4626,7 +4876,7 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc |
| 4626 | 4876 | |
| 4627 | 4877 | static TypeTableEntry *ir_analyze_container_member_access_inner(IrAnalyze *ira, |
| 4628 | 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 | 4881 | if (!is_slice(bare_struct_type)) { |
| 4632 | 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 | 4884 | auto entry = container_block_context->decl_table.maybe_get(field_name); |
| 4635 | 4885 | AstNode *fn_decl_node = entry ? entry->value : nullptr; |
| 4636 | 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 | 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 | 4901 | } |
| 4644 | 4902 | |
| 4645 | 4903 | |
| 4646 | | static TypeTableEntry *ir_analyze_container_member_access(IrAnalyze *ira, Buf *field_name, |
| 4647 | | IrInstructionFieldPtr *field_ptr_instruction, TypeTableEntry *container_type) |
| 4904 | static TypeTableEntry *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_name, |
| 4905 | IrInstructionFieldPtr *field_ptr_instruction, IrInstruction *container_ptr, TypeTableEntry *container_type) |
| 4648 | 4906 | { |
| 4649 | | IrInstruction *container_ptr = field_ptr_instruction->container_ptr->other; |
| 4650 | 4907 | TypeTableEntry *bare_type = container_ref_type(container_type); |
| 4651 | | if (!type_is_complete(bare_type)) { |
| 4908 | if (!type_is_complete(bare_type)) |
| 4652 | 4909 | resolve_container_type(ira->codegen, bare_type); |
| 4653 | | } |
| 4654 | 4910 | |
| 4655 | 4911 | if (bare_type->id == TypeTableEntryIdStruct) { |
| 4656 | 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 | 4915 | return get_pointer_to_type(ira->codegen, field->type_entry, false); |
| 4660 | 4916 | } else { |
| 4661 | 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 | 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 | 4929 | } else if (bare_type->id == TypeTableEntryIdUnion) { |
| 4667 | 4930 | zig_panic("TODO"); |
| 4668 | 4931 | } else { |
| ... | ... | @@ -4733,7 +4996,7 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru |
| 4733 | 4996 | if (container_type->id == TypeTableEntryIdInvalid) { |
| 4734 | 4997 | return container_type; |
| 4735 | 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 | 5000 | } else if (container_type->id == TypeTableEntryIdArray) { |
| 4738 | 5001 | if (buf_eql_str(field_name, "len")) { |
| 4739 | 5002 | ConstExprValue *len_val = allocate<ConstExprValue>(1); |
| ... | ... | @@ -4749,24 +5012,38 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru |
| 4749 | 5012 | return ira->codegen->builtin_types.entry_invalid; |
| 4750 | 5013 | } |
| 4751 | 5014 | } else if (container_type->id == TypeTableEntryIdMetaType) { |
| 4752 | | zig_panic("TODO type field access"); |
| 4753 | | //TypeTableEntry *child_type = ir_resolve_type(ira, container_ptr); |
| 4754 | | |
| 4755 | | //if (child_type->id == TypeTableEntryIdInvalid) { |
| 4756 | | // return ira->codegen->builtin_types.entry_invalid; |
| 4757 | | //} else if (child_type->id == TypeTableEntryIdEnum) { |
| 4758 | | // zig_panic("TODO enum type field"); |
| 4759 | | //} else if (child_type->id == TypeTableEntryIdStruct) { |
| 4760 | | // zig_panic("TODO struct type field"); |
| 4761 | | //} else if (child_type->id == TypeTableEntryIdPureError) { |
| 4762 | | // zig_panic("TODO error type field"); |
| 4763 | | //} else if (child_type->id == TypeTableEntryIdInt) { |
| 4764 | | // zig_panic("TODO integer type field"); |
| 4765 | | //} else { |
| 4766 | | // add_node_error(ira->codegen, source_node, |
| 4767 | | // buf_sprintf("type '%s' does not support field access", buf_ptr(&container_type->name))); |
| 4768 | | // return ira->codegen->builtin_types.entry_invalid; |
| 4769 | | //} |
| 5015 | ConstExprValue *container_ptr_val = ir_resolve_const(ira, container_ptr); |
| 5016 | if (!container_ptr_val) |
| 5017 | return ira->codegen->builtin_types.entry_invalid; |
| 5018 | ConstExprValue *child_val = const_ptr_pointee(container_ptr_val); |
| 5019 | TypeTableEntry *child_type = child_val->data.x_type; |
| 5020 | |
| 5021 | if (child_type->id == TypeTableEntryIdInvalid) { |
| 5022 | return ira->codegen->builtin_types.entry_invalid; |
| 5023 | } else if (child_type->id == TypeTableEntryIdEnum) { |
| 5024 | zig_panic("TODO enum type field"); |
| 5025 | } else if (child_type->id == TypeTableEntryIdStruct) { |
| 5026 | BlockContext *container_block_context = get_container_block_context(child_type); |
| 5027 | auto entry = container_block_context->decl_table.maybe_get(field_name); |
| 5028 | AstNode *decl_node = entry ? entry->value : nullptr; |
| 5029 | if (decl_node) { |
| 5030 | bool depends_on_compile_var = container_ptr->static_value.depends_on_compile_var; |
| 5031 | return ir_analyze_decl_ref(ira, &field_ptr_instruction->base, decl_node, depends_on_compile_var); |
| 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 | 5047 | } else if (container_type->id == TypeTableEntryIdNamespace) { |
| 4771 | 5048 | ConstExprValue *container_ptr_val = ir_resolve_const(ira, container_ptr); |
| 4772 | 5049 | if (!container_ptr_val) |
| ... | ... | @@ -4817,28 +5094,10 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru |
| 4817 | 5094 | |
| 4818 | 5095 | static TypeTableEntry *ir_analyze_instruction_load_ptr(IrAnalyze *ira, IrInstructionLoadPtr *load_ptr_instruction) { |
| 4819 | 5096 | IrInstruction *ptr = load_ptr_instruction->ptr->other; |
| 4820 | | TypeTableEntry *type_entry = ptr->type_entry; |
| 4821 | | if (type_entry->id == TypeTableEntryIdInvalid) { |
| 4822 | | return type_entry; |
| 4823 | | } else if (type_entry->id == TypeTableEntryIdPointer) { |
| 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 | | } |
| 5097 | IrInstruction *result = ir_get_deref(ira, &load_ptr_instruction->base, ptr); |
| 5098 | ir_link_new_instruction(result, &load_ptr_instruction->base); |
| 5099 | assert(result->type_entry); |
| 5100 | return result->type_entry; |
| 4842 | 5101 | } |
| 4843 | 5102 | |
| 4844 | 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 | 5170 | case TypeTableEntryIdNamespace: |
| 4912 | 5171 | case TypeTableEntryIdBlock: |
| 4913 | 5172 | case TypeTableEntryIdGenericFn: |
| 5173 | case TypeTableEntryIdBoundFn: |
| 4914 | 5174 | case TypeTableEntryIdMetaType: |
| 4915 | 5175 | case TypeTableEntryIdVoid: |
| 4916 | 5176 | case TypeTableEntryIdBool: |
| ... | ... | @@ -5148,6 +5408,7 @@ static TypeTableEntry *ir_analyze_instruction_slice_type(IrAnalyze *ira, |
| 5148 | 5408 | case TypeTableEntryIdFn: |
| 5149 | 5409 | case TypeTableEntryIdNamespace: |
| 5150 | 5410 | case TypeTableEntryIdGenericFn: |
| 5411 | case TypeTableEntryIdBoundFn: |
| 5151 | 5412 | { |
| 5152 | 5413 | TypeTableEntry *result_type = get_slice_type(ira->codegen, resolved_child_type, is_const); |
| 5153 | 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 | 5422 | |
| 5162 | 5423 | static TypeTableEntry *ir_analyze_instruction_asm(IrAnalyze *ira, IrInstructionAsm *asm_instruction) { |
| 5163 | 5424 | assert(asm_instruction->base.source_node->type == NodeTypeAsmExpr); |
| 5164 | | mark_impure_fn(ira->codegen, asm_instruction->base.source_node->block_context, |
| 5165 | | asm_instruction->base.source_node); |
| 5425 | |
| 5426 | if (!ir_emit_global_runtime_side_effect(ira, &asm_instruction->base)) |
| 5427 | return ira->codegen->builtin_types.entry_invalid; |
| 5166 | 5428 | |
| 5167 | 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 | 5498 | case TypeTableEntryIdFn: |
| 5237 | 5499 | case TypeTableEntryIdNamespace: |
| 5238 | 5500 | case TypeTableEntryIdGenericFn: |
| 5501 | case TypeTableEntryIdBoundFn: |
| 5239 | 5502 | { |
| 5240 | 5503 | TypeTableEntry *result_type = get_array_type(ira->codegen, child_type, size); |
| 5241 | 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 | 5569 | case TypeTableEntryIdNumLitFloat: |
| 5307 | 5570 | case TypeTableEntryIdNumLitInt: |
| 5308 | 5571 | case TypeTableEntryIdGenericFn: |
| 5572 | case TypeTableEntryIdBoundFn: |
| 5309 | 5573 | case TypeTableEntryIdMetaType: |
| 5310 | 5574 | case TypeTableEntryIdFn: |
| 5311 | 5575 | case TypeTableEntryIdNamespace: |
| ... | ... | @@ -5469,7 +5733,7 @@ static TypeTableEntry *ir_analyze_instruction_switch_br(IrAnalyze *ira, |
| 5469 | 5733 | return ir_unreach_error(ira); |
| 5470 | 5734 | |
| 5471 | 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 | 5738 | if (is_inline || target_value->static_value.special != ConstValSpecialRuntime) { |
| 5475 | 5739 | ConstExprValue *target_val = ir_resolve_const(ira, target_value); |
| ... | ... | @@ -5599,6 +5863,7 @@ static TypeTableEntry *ir_analyze_instruction_switch_target(IrAnalyze *ira, |
| 5599 | 5863 | case TypeTableEntryIdUnion: |
| 5600 | 5864 | case TypeTableEntryIdBlock: |
| 5601 | 5865 | case TypeTableEntryIdGenericFn: |
| 5866 | case TypeTableEntryIdBoundFn: |
| 5602 | 5867 | add_node_error(ira->codegen, switch_target_instruction->base.source_node, |
| 5603 | 5868 | buf_sprintf("invalid switch target type '%s'", buf_ptr(&target_type->name))); |
| 5604 | 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 | 6006 | |
| 5742 | 6007 | static TypeTableEntry *ir_analyze_instruction_ref(IrAnalyze *ira, IrInstructionRef *ref_instruction) { |
| 5743 | 6008 | IrInstruction *value = ref_instruction->value->other; |
| 5744 | | if (value->type_entry->id == TypeTableEntryIdInvalid) |
| 5745 | | return ira->codegen->builtin_types.entry_invalid; |
| 6009 | return ir_analyze_ref(ira, &ref_instruction->base, value); |
| 6010 | } |
| 5746 | 6011 | |
| 5747 | | FnTableEntry *fn_entry = ref_instruction->base.source_node->block_context->fn_entry; |
| 5748 | | if (!fn_entry || value->static_value.special != ConstValSpecialRuntime) { |
| 5749 | | ConstExprValue *val = ir_resolve_const(ira, value); |
| 5750 | | if (!val) |
| 6012 | static TypeTableEntry *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruction *instruction, |
| 6013 | TypeTableEntry *container_type, size_t instr_field_count, IrInstructionContainerInitFieldsField *fields, |
| 6014 | bool depends_on_compile_var) |
| 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 | 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); |
| 5756 | | if (handle_is_ptr(value->type_entry)) { |
| 5757 | | // this instruction is a noop - codegen can pass the pointer we already have as the result |
| 5758 | | ir_link_new_instruction(value, &ref_instruction->base); |
| 5759 | | return ptr_type; |
| 5760 | | } else { |
| 5761 | | fn_entry->alloca_list.append(&ref_instruction->base); |
| 5762 | | ir_build_ref_from(&ira->new_irb, &ref_instruction->base, value); |
| 5763 | | return ptr_type; |
| 6076 | bool any_missing = false; |
| 6077 | for (size_t i = 0; i < actual_field_count; i += 1) { |
| 6078 | if (!field_assign_nodes[i]) { |
| 6079 | add_node_error(ira->codegen, instruction->source_node, |
| 6080 | buf_sprintf("missing field: '%s'", buf_ptr(container_type->data.structure.fields[i].name))); |
| 6081 | any_missing = true; |
| 6082 | } |
| 6083 | } |
| 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) { |
| 5768 | | switch (instruction->id) { |
| 5769 | | case IrInstructionIdInvalid: |
| 5770 | | zig_unreachable(); |
| 5771 | | case IrInstructionIdReturn: |
| 5772 | | return ir_analyze_instruction_return(ira, (IrInstructionReturn *)instruction); |
| 5773 | | case IrInstructionIdConst: |
| 5774 | | return ir_analyze_instruction_const(ira, (IrInstructionConst *)instruction); |
| 5775 | | case IrInstructionIdUnOp: |
| 5776 | | return ir_analyze_instruction_un_op(ira, (IrInstructionUnOp *)instruction); |
| 5777 | | case IrInstructionIdBinOp: |
| 5778 | | return ir_analyze_instruction_bin_op(ira, (IrInstructionBinOp *)instruction); |
| 5779 | | case IrInstructionIdDeclVar: |
| 5780 | | return ir_analyze_instruction_decl_var(ira, (IrInstructionDeclVar *)instruction); |
| 5781 | | case IrInstructionIdLoadPtr: |
| 5782 | | return ir_analyze_instruction_load_ptr(ira, (IrInstructionLoadPtr *)instruction); |
| 5783 | | case IrInstructionIdStorePtr: |
| 5784 | | return ir_analyze_instruction_store_ptr(ira, (IrInstructionStorePtr *)instruction); |
| 5785 | | case IrInstructionIdElemPtr: |
| 5786 | | return ir_analyze_instruction_elem_ptr(ira, (IrInstructionElemPtr *)instruction); |
| 5787 | | case IrInstructionIdVarPtr: |
| 5788 | | return ir_analyze_instruction_var_ptr(ira, (IrInstructionVarPtr *)instruction); |
| 6105 | static TypeTableEntry *ir_analyze_instruction_container_init_list(IrAnalyze *ira, IrInstructionContainerInitList *instruction) { |
| 6106 | IrInstruction *container_type_value = instruction->container_type->other; |
| 6107 | TypeTableEntry *container_type = ir_resolve_type(ira, container_type_value); |
| 6108 | if (!container_type) |
| 6109 | return ira->codegen->builtin_types.entry_invalid; |
| 6110 | |
| 6111 | size_t elem_count = instruction->item_count; |
| 6112 | bool depends_on_compile_var = container_type_value->static_value.depends_on_compile_var; |
| 6113 | |
| 6114 | if (container_type->id == TypeTableEntryIdStruct && !is_slice(container_type) && elem_count == 0) { |
| 6115 | return ir_analyze_container_init_fields(ira, &instruction->base, container_type, 0, nullptr, depends_on_compile_var); |
| 6116 | } else if (is_slice(container_type)) { |
| 6117 | TypeTableEntry *pointer_type = container_type->data.structure.fields[slice_ptr_index].type_entry; |
| 6118 | assert(pointer_type->id == TypeTableEntryIdPointer); |
| 6119 | TypeTableEntry *child_type = pointer_type->data.pointer.child_type; |
| 6120 | |
| 6121 | ConstExprValue const_val = {}; |
| 6122 | const_val.special = ConstValSpecialStatic; |
| 6123 | const_val.depends_on_compile_var = depends_on_compile_var; |
| 6124 | const_val.data.x_array.elements = allocate<ConstExprValue>(elem_count); |
| 6125 | const_val.data.x_array.size = elem_count; |
| 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 | 6225 | case IrInstructionIdFieldPtr: |
| 5790 | 6226 | return ir_analyze_instruction_field_ptr(ira, (IrInstructionFieldPtr *)instruction); |
| 5791 | 6227 | case IrInstructionIdCall: |
| ... | ... | @@ -5844,10 +6280,14 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi |
| 5844 | 6280 | return ir_analyze_instruction_array_len(ira, (IrInstructionArrayLen *)instruction); |
| 5845 | 6281 | case IrInstructionIdRef: |
| 5846 | 6282 | return ir_analyze_instruction_ref(ira, (IrInstructionRef *)instruction); |
| 5847 | | case IrInstructionIdCast: |
| 5848 | 6283 | case IrInstructionIdContainerInitList: |
| 6284 | return ir_analyze_instruction_container_init_list(ira, (IrInstructionContainerInitList *)instruction); |
| 5849 | 6285 | case IrInstructionIdContainerInitFields: |
| 6286 | return ir_analyze_instruction_container_init_fields(ira, (IrInstructionContainerInitFields *)instruction); |
| 6287 | case IrInstructionIdCast: |
| 5850 | 6288 | case IrInstructionIdStructFieldPtr: |
| 6289 | case IrInstructionIdEnumFieldPtr: |
| 6290 | case IrInstructionIdStructInit: |
| 5851 | 6291 | zig_panic("TODO analyze more instructions"); |
| 5852 | 6292 | } |
| 5853 | 6293 | zig_unreachable(); |
| ... | ... | @@ -5947,6 +6387,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 5947 | 6387 | case IrInstructionIdCast: |
| 5948 | 6388 | case IrInstructionIdContainerInitList: |
| 5949 | 6389 | case IrInstructionIdContainerInitFields: |
| 6390 | case IrInstructionIdStructInit: |
| 5950 | 6391 | case IrInstructionIdFieldPtr: |
| 5951 | 6392 | case IrInstructionIdElemPtr: |
| 5952 | 6393 | case IrInstructionIdVarPtr: |
| ... | ... | @@ -5955,6 +6396,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 5955 | 6396 | case IrInstructionIdPtrTypeChild: |
| 5956 | 6397 | case IrInstructionIdArrayLen: |
| 5957 | 6398 | case IrInstructionIdStructFieldPtr: |
| 6399 | case IrInstructionIdEnumFieldPtr: |
| 5958 | 6400 | case IrInstructionIdArrayType: |
| 5959 | 6401 | case IrInstructionIdSliceType: |
| 5960 | 6402 | case IrInstructionIdCompileVar: |
| ... | ... | @@ -6393,46 +6835,6 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) { |
| 6393 | 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 | 6838 | //static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, |
| 6437 | 6839 | // TypeTableEntry *expected_type, AstNode *node) |
| 6438 | 6840 | //{ |
| ... | ... | @@ -6634,713 +7036,10 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) { |
| 6634 | 7036 | // return analyze_set_fn_test(g, import, context, node); |
| 6635 | 7037 | // case BuiltinFnIdSetFnNoInline: |
| 6636 | 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 | 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 | 7043 | //static TypeTableEntry *analyze_return_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, |
| 7345 | 7044 | // TypeTableEntry *expected_type, AstNode *node) |
| 7346 | 7045 | //{ |
| ... | ... | @@ -7476,68 +7175,6 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) { |
| 7476 | 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 | 7179 | //static TypeTableEntry *analyze_slice_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, |
| 7543 | 7180 | // AstNode *node) |
| ... | ... | @@ -7887,19 +7524,6 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) { |
| 7887 | 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 | 7527 | //static void validate_voided_expr(CodeGen *g, AstNode *source_node, TypeTableEntry *type_entry) { |
| 7904 | 7528 | // if (type_entry->id == TypeTableEntryIdMetaType) { |
| 7905 | 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 | 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 | 7866 | //static LLVMValueRef gen_array_base_ptr(CodeGen *g, AstNode *node) { |
| 8329 | 7867 | // TypeTableEntry *type_entry = get_expr_type(node); |
| 8330 | 7868 | // |
| ... | ... | @@ -8356,46 +7894,6 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) { |
| 8356 | 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 | 7897 | //static LLVMValueRef gen_slice_expr(CodeGen *g, AstNode *node) { |
| 8400 | 7898 | // assert(node->type == NodeTypeSliceExpr); |
| 8401 | 7899 | // |
| ... | ... | @@ -8771,87 +8269,6 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) { |
| 8771 | 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 | 8272 | //static LLVMValueRef gen_block(CodeGen *g, AstNode *block_node, TypeTableEntry *implicit_return_type) { |
| 8856 | 8273 | // assert(block_node->type == NodeTypeBlock); |
| 8857 | 8274 | // |
| ... | ... | @@ -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 | 8296 | //static LLVMValueRef gen_break(CodeGen *g, AstNode *node) { |
| 9014 | 8297 | // assert(node->type == NodeTypeBreak); |
| 9015 | 8298 | // LLVMBasicBlockRef dest_block = g->break_block_stack.last(); |
| ... | ... | @@ -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 | 8450 | //static LLVMValueRef gen_return(CodeGen *g, AstNode *source_node, LLVMValueRef value, ReturnKnowledge rk) { |
| 9206 | 8451 | // BlockContext *defer_inner_block = source_node->block_context; |
| 9207 | 8452 | // BlockContext *defer_outer_block = source_node->block_context->fn_entry->fn_def_node->block_context; |