| ... | @@ -387,6 +387,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionSlice *) { | ... | @@ -387,6 +387,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionSlice *) { |
| 387 | return IrInstructionIdSlice; | 387 | return IrInstructionIdSlice; |
| 388 | } | 388 | } |
| 389 | | 389 | |
| | 390 | static constexpr IrInstructionId ir_instruction_id(IrInstructionMemberCount *) { |
| | 391 | return IrInstructionIdMemberCount; |
| | 392 | } |
| | 393 | |
| 390 | template<typename T> | 394 | template<typename T> |
| 391 | static T *ir_create_instruction(IrExecutable *exec, Scope *scope, AstNode *source_node) { | 395 | static T *ir_create_instruction(IrExecutable *exec, Scope *scope, AstNode *source_node) { |
| 392 | T *special_instruction = allocate<T>(1); | 396 | T *special_instruction = allocate<T>(1); |
| ... | @@ -1596,6 +1600,15 @@ static IrInstruction *ir_build_slice_from(IrBuilder *irb, IrInstruction *old_ins | ... | @@ -1596,6 +1600,15 @@ static IrInstruction *ir_build_slice_from(IrBuilder *irb, IrInstruction *old_ins |
| 1596 | return new_instruction; | 1600 | return new_instruction; |
| 1597 | } | 1601 | } |
| 1598 | | 1602 | |
| | 1603 | static IrInstruction *ir_build_member_count(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *container) { |
| | 1604 | IrInstructionMemberCount *instruction = ir_build_instruction<IrInstructionMemberCount>(irb, scope, source_node); |
| | 1605 | instruction->container = container; |
| | 1606 | |
| | 1607 | ir_ref_instruction(container); |
| | 1608 | |
| | 1609 | return &instruction->base; |
| | 1610 | } |
| | 1611 | |
| 1599 | static void ir_gen_defers_for_block(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, | 1612 | static void ir_gen_defers_for_block(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, |
| 1600 | bool gen_error_defers, bool gen_maybe_defers) | 1613 | bool gen_error_defers, bool gen_maybe_defers) |
| 1601 | { | 1614 | { |
| ... | @@ -2469,8 +2482,16 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo | ... | @@ -2469,8 +2482,16 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo |
| 2469 | | 2482 | |
| 2470 | return ir_build_memset(irb, scope, node, arg0_value, arg1_value, arg2_value); | 2483 | return ir_build_memset(irb, scope, node, arg0_value, arg1_value, arg2_value); |
| 2471 | } | 2484 | } |
| 2472 | case BuiltinFnIdAlignof: | | |
| 2473 | case BuiltinFnIdMemberCount: | 2485 | case BuiltinFnIdMemberCount: |
| | 2486 | { |
| | 2487 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); |
| | 2488 | IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); |
| | 2489 | if (arg0_value == irb->codegen->invalid_instruction) |
| | 2490 | return arg0_value; |
| | 2491 | |
| | 2492 | return ir_build_member_count(irb, scope, node, arg0_value); |
| | 2493 | } |
| | 2494 | case BuiltinFnIdAlignof: |
| 2474 | case BuiltinFnIdAddWithOverflow: | 2495 | case BuiltinFnIdAddWithOverflow: |
| 2475 | case BuiltinFnIdSubWithOverflow: | 2496 | case BuiltinFnIdSubWithOverflow: |
| 2476 | case BuiltinFnIdMulWithOverflow: | 2497 | case BuiltinFnIdMulWithOverflow: |
| ... | @@ -8408,6 +8429,33 @@ static TypeTableEntry *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructio | ... | @@ -8408,6 +8429,33 @@ static TypeTableEntry *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructio |
| 8408 | return return_type; | 8429 | return return_type; |
| 8409 | } | 8430 | } |
| 8410 | | 8431 | |
| | 8432 | static TypeTableEntry *ir_analyze_instruction_member_count(IrAnalyze *ira, IrInstructionMemberCount *instruction) { |
| | 8433 | IrInstruction *container = instruction->container->other; |
| | 8434 | if (container->type_entry->id == TypeTableEntryIdInvalid) |
| | 8435 | return ira->codegen->builtin_types.entry_invalid; |
| | 8436 | TypeTableEntry *container_type = ir_resolve_type(ira, container); |
| | 8437 | TypeTableEntry *canon_type = get_underlying_type(container_type); |
| | 8438 | |
| | 8439 | uint64_t result; |
| | 8440 | if (canon_type->id == TypeTableEntryIdInvalid) { |
| | 8441 | return ira->codegen->builtin_types.entry_invalid; |
| | 8442 | } else if (canon_type->id == TypeTableEntryIdEnum) { |
| | 8443 | result = canon_type->data.enumeration.src_field_count; |
| | 8444 | } else if (canon_type->id == TypeTableEntryIdStruct) { |
| | 8445 | result = canon_type->data.structure.src_field_count; |
| | 8446 | } else if (canon_type->id == TypeTableEntryIdUnion) { |
| | 8447 | result = canon_type->data.unionation.src_field_count; |
| | 8448 | } else { |
| | 8449 | ir_add_error(ira, &instruction->base, buf_sprintf("no value count available for type '%s'", buf_ptr(&container_type->name))); |
| | 8450 | return ira->codegen->builtin_types.entry_invalid; |
| | 8451 | } |
| | 8452 | |
| | 8453 | bool depends_on_compile_var = container->static_value.depends_on_compile_var; |
| | 8454 | ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base, depends_on_compile_var); |
| | 8455 | bignum_init_unsigned(&out_val->data.x_bignum, result); |
| | 8456 | return ira->codegen->builtin_types.entry_num_lit_int; |
| | 8457 | } |
| | 8458 | |
| 8411 | static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) { | 8459 | static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) { |
| 8412 | switch (instruction->id) { | 8460 | switch (instruction->id) { |
| 8413 | case IrInstructionIdInvalid: | 8461 | case IrInstructionIdInvalid: |
| ... | @@ -8530,6 +8578,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi | ... | @@ -8530,6 +8578,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi |
| 8530 | return ir_analyze_instruction_memcpy(ira, (IrInstructionMemcpy *)instruction); | 8578 | return ir_analyze_instruction_memcpy(ira, (IrInstructionMemcpy *)instruction); |
| 8531 | case IrInstructionIdSlice: | 8579 | case IrInstructionIdSlice: |
| 8532 | return ir_analyze_instruction_slice(ira, (IrInstructionSlice *)instruction); | 8580 | return ir_analyze_instruction_slice(ira, (IrInstructionSlice *)instruction); |
| | 8581 | case IrInstructionIdMemberCount: |
| | 8582 | return ir_analyze_instruction_member_count(ira, (IrInstructionMemberCount *)instruction); |
| 8533 | case IrInstructionIdCast: | 8583 | case IrInstructionIdCast: |
| 8534 | case IrInstructionIdStructFieldPtr: | 8584 | case IrInstructionIdStructFieldPtr: |
| 8535 | case IrInstructionIdEnumFieldPtr: | 8585 | case IrInstructionIdEnumFieldPtr: |
| ... | @@ -8675,6 +8725,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { | ... | @@ -8675,6 +8725,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 8675 | case IrInstructionIdBoolNot: | 8725 | case IrInstructionIdBoolNot: |
| 8676 | case IrInstructionIdAlloca: | 8726 | case IrInstructionIdAlloca: |
| 8677 | case IrInstructionIdSlice: | 8727 | case IrInstructionIdSlice: |
| | 8728 | case IrInstructionIdMemberCount: |
| 8678 | return false; | 8729 | return false; |
| 8679 | case IrInstructionIdAsm: | 8730 | case IrInstructionIdAsm: |
| 8680 | { | 8731 | { |
| ... | @@ -8736,23 +8787,6 @@ bool ir_has_side_effects(IrInstruction *instruction) { | ... | @@ -8736,23 +8787,6 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 8736 | // align_in_bytes, false); | 8787 | // align_in_bytes, false); |
| 8737 | // } | 8788 | // } |
| 8738 | // } | 8789 | // } |
| 8739 | // case BuiltinFnIdMemberCount: | | |
| 8740 | // { | | |
| 8741 | // AstNode *type_node = node->data.fn_call_expr.params.at(0); | | |
| 8742 | // TypeTableEntry *type_entry = analyze_type_expr(g, import, context, type_node); | | |
| 8743 | // | | |
| 8744 | // if (type_entry->id == TypeTableEntryIdInvalid) { | | |
| 8745 | // return type_entry; | | |
| 8746 | // } else if (type_entry->id == TypeTableEntryIdEnum) { | | |
| 8747 | // uint64_t value_count = type_entry->data.enumeration.src_field_count; | | |
| 8748 | // return resolve_expr_const_val_as_unsigned_num_lit(g, node, expected_type, | | |
| 8749 | // value_count, false); | | |
| 8750 | // } else { | | |
| 8751 | // add_node_error(g, node, | | |
| 8752 | // buf_sprintf("no value count available for type '%s'", buf_ptr(&type_entry->name))); | | |
| 8753 | // return g->builtin_types.entry_invalid; | | |
| 8754 | // } | | |
| 8755 | // } | | |
| 8756 | // case BuiltinFnIdBreakpoint: | 8790 | // case BuiltinFnIdBreakpoint: |
| 8757 | // mark_impure_fn(g, context, node); | 8791 | // mark_impure_fn(g, context, node); |
| 8758 | // return g->builtin_types.entry_void; | 8792 | // return g->builtin_types.entry_void; |
| ... | @@ -8997,7 +9031,6 @@ bool ir_has_side_effects(IrInstruction *instruction) { | ... | @@ -8997,7 +9031,6 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 8997 | // case BuiltinFnIdAlignof: | 9031 | // case BuiltinFnIdAlignof: |
| 8998 | // case BuiltinFnIdMinValue: | 9032 | // case BuiltinFnIdMinValue: |
| 8999 | // case BuiltinFnIdMaxValue: | 9033 | // case BuiltinFnIdMaxValue: |
| 9000 | // case BuiltinFnIdMemberCount: | | |
| 9001 | // // caught by constant expression eval codegen | 9034 | // // caught by constant expression eval codegen |
| 9002 | // zig_unreachable(); | 9035 | // zig_unreachable(); |
| 9003 | // case BuiltinFnIdCompileVar: | 9036 | // case BuiltinFnIdCompileVar: |