| ... | ... | @@ -387,6 +387,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionSlice *) { |
| 387 | 387 | return IrInstructionIdSlice; |
| 388 | 388 | } |
| 389 | 389 | |
| 390 | static constexpr IrInstructionId ir_instruction_id(IrInstructionMemberCount *) { |
| 391 | return IrInstructionIdMemberCount; |
| 392 | } |
| 393 | |
| 390 | 394 | template<typename T> |
| 391 | 395 | static T *ir_create_instruction(IrExecutable *exec, Scope *scope, AstNode *source_node) { |
| 392 | 396 | T *special_instruction = allocate<T>(1); |
| ... | ... | @@ -1596,6 +1600,15 @@ static IrInstruction *ir_build_slice_from(IrBuilder *irb, IrInstruction *old_ins |
| 1596 | 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 | 1612 | static void ir_gen_defers_for_block(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, |
| 1600 | 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 | 2482 | |
| 2470 | 2483 | return ir_build_memset(irb, scope, node, arg0_value, arg1_value, arg2_value); |
| 2471 | 2484 | } |
| 2472 | | case BuiltinFnIdAlignof: |
| 2473 | 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 | 2495 | case BuiltinFnIdAddWithOverflow: |
| 2475 | 2496 | case BuiltinFnIdSubWithOverflow: |
| 2476 | 2497 | case BuiltinFnIdMulWithOverflow: |
| ... | ... | @@ -8408,6 +8429,33 @@ static TypeTableEntry *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructio |
| 8408 | 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 | 8459 | static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) { |
| 8412 | 8460 | switch (instruction->id) { |
| 8413 | 8461 | case IrInstructionIdInvalid: |
| ... | ... | @@ -8530,6 +8578,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi |
| 8530 | 8578 | return ir_analyze_instruction_memcpy(ira, (IrInstructionMemcpy *)instruction); |
| 8531 | 8579 | case IrInstructionIdSlice: |
| 8532 | 8580 | return ir_analyze_instruction_slice(ira, (IrInstructionSlice *)instruction); |
| 8581 | case IrInstructionIdMemberCount: |
| 8582 | return ir_analyze_instruction_member_count(ira, (IrInstructionMemberCount *)instruction); |
| 8533 | 8583 | case IrInstructionIdCast: |
| 8534 | 8584 | case IrInstructionIdStructFieldPtr: |
| 8535 | 8585 | case IrInstructionIdEnumFieldPtr: |
| ... | ... | @@ -8675,6 +8725,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 8675 | 8725 | case IrInstructionIdBoolNot: |
| 8676 | 8726 | case IrInstructionIdAlloca: |
| 8677 | 8727 | case IrInstructionIdSlice: |
| 8728 | case IrInstructionIdMemberCount: |
| 8678 | 8729 | return false; |
| 8679 | 8730 | case IrInstructionIdAsm: |
| 8680 | 8731 | { |
| ... | ... | @@ -8736,23 +8787,6 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 8736 | 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 | 8790 | // case BuiltinFnIdBreakpoint: |
| 8757 | 8791 | // mark_impure_fn(g, context, node); |
| 8758 | 8792 | // return g->builtin_types.entry_void; |
| ... | ... | @@ -8997,7 +9031,6 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 8997 | 9031 | // case BuiltinFnIdAlignof: |
| 8998 | 9032 | // case BuiltinFnIdMinValue: |
| 8999 | 9033 | // case BuiltinFnIdMaxValue: |
| 9000 | | // case BuiltinFnIdMemberCount: |
| 9001 | 9034 | // // caught by constant expression eval codegen |
| 9002 | 9035 | // zig_unreachable(); |
| 9003 | 9036 | // case BuiltinFnIdCompileVar: |