| ... | @@ -2766,11 +2766,13 @@ static IrInstGen *ir_build_load_ptr_gen(IrAnalyze *ira, IrInst *source_instructi | ... | @@ -2766,11 +2766,13 @@ static IrInstGen *ir_build_load_ptr_gen(IrAnalyze *ira, IrInst *source_instructi |
| 2766 | return &instruction->base; | 2766 | return &instruction->base; |
| 2767 | } | 2767 | } |
| 2768 | | 2768 | |
| 2769 | static IrInstSrc *ir_build_typeof(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *value) { | 2769 | static IrInstSrc *ir_build_typeof(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc **values, size_t value_count) { |
| 2770 | IrInstSrcTypeOf *instruction = ir_build_instruction<IrInstSrcTypeOf>(irb, scope, source_node); | 2770 | IrInstSrcTypeOf *instruction = ir_build_instruction<IrInstSrcTypeOf>(irb, scope, source_node); |
| 2771 | instruction->value = value; | 2771 | instruction->values = values; |
| | 2772 | instruction->value_count = value_count; |
| 2772 | | 2773 | |
| 2773 | ir_ref_instruction(value, irb->current_basic_block); | 2774 | for (size_t i = 0; i < value_count; i++) |
| | 2775 | ir_ref_instruction(values[i], irb->current_basic_block); |
| 2774 | | 2776 | |
| 2775 | return &instruction->base; | 2777 | return &instruction->base; |
| 2776 | } | 2778 | } |
| ... | @@ -6043,7 +6045,9 @@ static IrInstSrc *ir_gen_fn_call_with_args(IrBuilderSrc *irb, Scope *scope, AstN | ... | @@ -6043,7 +6045,9 @@ static IrInstSrc *ir_gen_fn_call_with_args(IrBuilderSrc *irb, Scope *scope, AstN |
| 6043 | if (fn_ref == irb->codegen->invalid_inst_src) | 6045 | if (fn_ref == irb->codegen->invalid_inst_src) |
| 6044 | return fn_ref; | 6046 | return fn_ref; |
| 6045 | | 6047 | |
| 6046 | IrInstSrc *fn_type = ir_build_typeof(irb, scope, source_node, fn_ref); | 6048 | IrInstSrc **typeof_args = heap::c_allocator.allocate<IrInstSrc*>(1); |
| | 6049 | typeof_args[0] = fn_ref; |
| | 6050 | IrInstSrc *fn_type = ir_build_typeof(irb, scope, source_node, typeof_args, 1); |
| 6047 | | 6051 | |
| 6048 | IrInstSrc **args = heap::c_allocator.allocate<IrInstSrc*>(args_len); | 6052 | IrInstSrc **args = heap::c_allocator.allocate<IrInstSrc*>(args_len); |
| 6049 | for (size_t i = 0; i < args_len; i += 1) { | 6053 | for (size_t i = 0; i < args_len; i += 1) { |
| ... | @@ -6104,12 +6108,24 @@ static IrInstSrc *ir_gen_builtin_fn_call(IrBuilderSrc *irb, Scope *scope, AstNod | ... | @@ -6104,12 +6108,24 @@ static IrInstSrc *ir_gen_builtin_fn_call(IrBuilderSrc *irb, Scope *scope, AstNod |
| 6104 | { | 6108 | { |
| 6105 | Scope *sub_scope = create_typeof_scope(irb->codegen, node, scope); | 6109 | Scope *sub_scope = create_typeof_scope(irb->codegen, node, scope); |
| 6106 | | 6110 | |
| 6107 | AstNode *arg_node = node->data.fn_call_expr.params.at(0); | 6111 | size_t arg_count = node->data.fn_call_expr.params.length; |
| 6108 | IrInstSrc *arg = ir_gen_node(irb, arg_node, sub_scope); | 6112 | |
| 6109 | if (arg == irb->codegen->invalid_inst_src) | 6113 | if (arg_count < 1) { |
| 6110 | return arg; | 6114 | add_node_error(irb->codegen, node, |
| | 6115 | buf_sprintf("expected at least 1 argument, found 0")); |
| | 6116 | return irb->codegen->invalid_inst_src; |
| | 6117 | } |
| | 6118 | |
| | 6119 | IrInstSrc **args = heap::c_allocator.allocate<IrInstSrc*>(arg_count); |
| | 6120 | for (size_t i = 0; i < arg_count; i += 1) { |
| | 6121 | AstNode *arg_node = node->data.fn_call_expr.params.at(i); |
| | 6122 | IrInstSrc *arg = ir_gen_node(irb, arg_node, sub_scope); |
| | 6123 | if (arg == irb->codegen->invalid_inst_src) |
| | 6124 | return irb->codegen->invalid_inst_src; |
| | 6125 | args[i] = arg; |
| | 6126 | } |
| 6111 | | 6127 | |
| 6112 | IrInstSrc *type_of = ir_build_typeof(irb, scope, node, arg); | 6128 | IrInstSrc *type_of = ir_build_typeof(irb, scope, node, args, arg_count); |
| 6113 | return ir_lval_wrap(irb, scope, type_of, lval, result_loc); | 6129 | return ir_lval_wrap(irb, scope, type_of, lval, result_loc); |
| 6114 | } | 6130 | } |
| 6115 | case BuiltinFnIdSetCold: | 6131 | case BuiltinFnIdSetCold: |
| ... | @@ -21662,10 +21678,31 @@ static IrInstGen *ir_analyze_instruction_load_ptr(IrAnalyze *ira, IrInstSrcLoadP | ... | @@ -21662,10 +21678,31 @@ static IrInstGen *ir_analyze_instruction_load_ptr(IrAnalyze *ira, IrInstSrcLoadP |
| 21662 | } | 21678 | } |
| 21663 | | 21679 | |
| 21664 | static IrInstGen *ir_analyze_instruction_typeof(IrAnalyze *ira, IrInstSrcTypeOf *typeof_instruction) { | 21680 | static IrInstGen *ir_analyze_instruction_typeof(IrAnalyze *ira, IrInstSrcTypeOf *typeof_instruction) { |
| 21665 | IrInstGen *expr_value = typeof_instruction->value->child; | 21681 | ZigType *type_entry; |
| 21666 | ZigType *type_entry = expr_value->value->type; | 21682 | |
| | 21683 | const size_t value_count = typeof_instruction->value_count; |
| | 21684 | |
| | 21685 | // Fast path for the common case of TypeOf with a single argument |
| | 21686 | if (value_count < 2) { |
| | 21687 | type_entry = typeof_instruction->values[0]->child->value->type; |
| | 21688 | } else { |
| | 21689 | IrInstGen **args = heap::c_allocator.allocate<IrInstGen*>(value_count); |
| | 21690 | for (size_t i = 0; i < value_count; i += 1) { |
| | 21691 | IrInstGen *value = typeof_instruction->values[i]->child; |
| | 21692 | if (type_is_invalid(value->value->type)) |
| | 21693 | return ira->codegen->invalid_inst_gen; |
| | 21694 | args[i] = value; |
| | 21695 | } |
| | 21696 | |
| | 21697 | type_entry = ir_resolve_peer_types(ira, typeof_instruction->base.base.source_node, |
| | 21698 | nullptr, args, value_count); |
| | 21699 | |
| | 21700 | heap::c_allocator.deallocate(args, value_count); |
| | 21701 | } |
| | 21702 | |
| 21667 | if (type_is_invalid(type_entry)) | 21703 | if (type_is_invalid(type_entry)) |
| 21668 | return ira->codegen->invalid_inst_gen; | 21704 | return ira->codegen->invalid_inst_gen; |
| | 21705 | |
| 21669 | return ir_const_type(ira, &typeof_instruction->base.base, type_entry); | 21706 | return ir_const_type(ira, &typeof_instruction->base.base, type_entry); |
| 21670 | } | 21707 | } |
| 21671 | | 21708 | |