diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2020-03-04 18:05:34 -0500 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2020-03-04 18:05:34 -0500 |
| commit | 378bf1c3b71fdcc823fb9a5382400ec0a659fc00 (patch) | |
| tree | 412c9f53fcefcb5117b89323cbf526289a4a90a0 /src | |
| parent | 24fc69acad303d9049a99683d3bf1f41185d22db (diff) | |
| parent | 116e2a93f1ab068ee46f4b7cce6b3306334cdec6 (diff) | |
| download | zig-378bf1c3b71fdcc823fb9a5382400ec0a659fc00.tar.gz zig-378bf1c3b71fdcc823fb9a5382400ec0a659fc00.zip | |
Merge branch 'LemonBoy-fix-439'
Diffstat (limited to 'src')
| -rw-r--r-- | src/all_types.hpp | 6 | ||||
| -rw-r--r-- | src/codegen.cpp | 2 | ||||
| -rw-r--r-- | src/ir.cpp | 77 | ||||
| -rw-r--r-- | src/ir_print.cpp | 8 |
4 files changed, 80 insertions, 13 deletions
diff --git a/src/all_types.hpp b/src/all_types.hpp index 9f6bfd80a5..2a3ab2041a 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -3286,7 +3286,11 @@ struct IrInstGenUnreachable { struct IrInstSrcTypeOf { IrInstSrc base; - IrInstSrc *value; + union { + IrInstSrc *scalar; // value_count == 1 + IrInstSrc **list; // value_count > 1 + } value; + size_t value_count; }; struct IrInstSrcSetCold { diff --git a/src/codegen.cpp b/src/codegen.cpp index 51e2f4625e..ef567c27aa 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -8142,7 +8142,7 @@ static void define_builtin_fns(CodeGen *g) { create_builtin_fn(g, BuiltinFnIdTypeInfo, "typeInfo", 1); create_builtin_fn(g, BuiltinFnIdType, "Type", 1); create_builtin_fn(g, BuiltinFnIdHasField, "hasField", 2); - create_builtin_fn(g, BuiltinFnIdTypeof, "TypeOf", 1); + create_builtin_fn(g, BuiltinFnIdTypeof, "TypeOf", SIZE_MAX); create_builtin_fn(g, BuiltinFnIdAddWithOverflow, "addWithOverflow", 4); create_builtin_fn(g, BuiltinFnIdSubWithOverflow, "subWithOverflow", 4); create_builtin_fn(g, BuiltinFnIdMulWithOverflow, "mulWithOverflow", 4); diff --git a/src/ir.cpp b/src/ir.cpp index d203e0aa91..56ba634189 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -2766,9 +2766,24 @@ static IrInstGen *ir_build_load_ptr_gen(IrAnalyze *ira, IrInst *source_instructi return &instruction->base; } -static IrInstSrc *ir_build_typeof(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *value) { +static IrInstSrc *ir_build_typeof_n(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc **values, size_t value_count) +{ + assert(value_count >= 2); + IrInstSrcTypeOf *instruction = ir_build_instruction<IrInstSrcTypeOf>(irb, scope, source_node); - instruction->value = value; + instruction->value.list = values; + instruction->value_count = value_count; + + for (size_t i = 0; i < value_count; i++) + ir_ref_instruction(values[i], irb->current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_typeof_1(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *value) { + IrInstSrcTypeOf *instruction = ir_build_instruction<IrInstSrcTypeOf>(irb, scope, source_node); + instruction->value.scalar = value; ir_ref_instruction(value, irb->current_basic_block); @@ -6043,7 +6058,7 @@ static IrInstSrc *ir_gen_fn_call_with_args(IrBuilderSrc *irb, Scope *scope, AstN if (fn_ref == irb->codegen->invalid_inst_src) return fn_ref; - IrInstSrc *fn_type = ir_build_typeof(irb, scope, source_node, fn_ref); + IrInstSrc *fn_type = ir_build_typeof_1(irb, scope, source_node, fn_ref); IrInstSrc **args = heap::c_allocator.allocate<IrInstSrc*>(args_len); for (size_t i = 0; i < args_len; i += 1) { @@ -6104,12 +6119,33 @@ static IrInstSrc *ir_gen_builtin_fn_call(IrBuilderSrc *irb, Scope *scope, AstNod { Scope *sub_scope = create_typeof_scope(irb->codegen, node, scope); - AstNode *arg_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg = ir_gen_node(irb, arg_node, sub_scope); - if (arg == irb->codegen->invalid_inst_src) - return arg; + size_t arg_count = node->data.fn_call_expr.params.length; + + IrInstSrc *type_of; + + if (arg_count == 0) { + add_node_error(irb->codegen, node, + buf_sprintf("expected at least 1 argument, found 0")); + return irb->codegen->invalid_inst_src; + } else if (arg_count == 1) { + AstNode *arg0_node = node->data.fn_call_expr.params.at(0); + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, sub_scope); + if (arg0_value == irb->codegen->invalid_inst_src) + return arg0_value; - IrInstSrc *type_of = ir_build_typeof(irb, scope, node, arg); + type_of = ir_build_typeof_1(irb, scope, node, arg0_value); + } else { + IrInstSrc **args = heap::c_allocator.allocate<IrInstSrc*>(arg_count); + for (size_t i = 0; i < arg_count; i += 1) { + AstNode *arg_node = node->data.fn_call_expr.params.at(i); + IrInstSrc *arg = ir_gen_node(irb, arg_node, sub_scope); + if (arg == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; + args[i] = arg; + } + + type_of = ir_build_typeof_n(irb, scope, node, args, arg_count); + } return ir_lval_wrap(irb, scope, type_of, lval, result_loc); } case BuiltinFnIdSetCold: @@ -21662,10 +21698,31 @@ static IrInstGen *ir_analyze_instruction_load_ptr(IrAnalyze *ira, IrInstSrcLoadP } static IrInstGen *ir_analyze_instruction_typeof(IrAnalyze *ira, IrInstSrcTypeOf *typeof_instruction) { - IrInstGen *expr_value = typeof_instruction->value->child; - ZigType *type_entry = expr_value->value->type; + ZigType *type_entry; + + const size_t value_count = typeof_instruction->value_count; + + // Fast path for the common case of TypeOf with a single argument + if (value_count < 2) { + type_entry = typeof_instruction->value.scalar->child->value->type; + } else { + IrInstGen **args = heap::c_allocator.allocate<IrInstGen*>(value_count); + for (size_t i = 0; i < value_count; i += 1) { + IrInstGen *value = typeof_instruction->value.list[i]->child; + if (type_is_invalid(value->value->type)) + return ira->codegen->invalid_inst_gen; + args[i] = value; + } + + type_entry = ir_resolve_peer_types(ira, typeof_instruction->base.base.source_node, + nullptr, args, value_count); + + heap::c_allocator.deallocate(args, value_count); + } + if (type_is_invalid(type_entry)) return ira->codegen->invalid_inst_gen; + return ir_const_type(ira, &typeof_instruction->base.base, type_entry); } diff --git a/src/ir_print.cpp b/src/ir_print.cpp index 1cfe904660..e66b4a3cdf 100644 --- a/src/ir_print.cpp +++ b/src/ir_print.cpp @@ -1118,7 +1118,13 @@ static void ir_print_vector_store_elem(IrPrintGen *irp, IrInstGenVectorStoreElem static void ir_print_typeof(IrPrintSrc *irp, IrInstSrcTypeOf *instruction) { fprintf(irp->f, "@TypeOf("); - ir_print_other_inst_src(irp, instruction->value); + if (instruction->value_count == 1) { + ir_print_other_inst_src(irp, instruction->value.scalar); + } else { + for (size_t i = 0; i < instruction->value_count; i += 1) { + ir_print_other_inst_src(irp, instruction->value.list[i]); + } + } fprintf(irp->f, ")"); } |
