| ... | @@ -478,7 +478,7 @@ fn zirExtended(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerErro | ... | @@ -478,7 +478,7 @@ fn zirExtended(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerErro |
| 478 | const extended = sema.code.instructions.items(.data)[inst].extended; | 478 | const extended = sema.code.instructions.items(.data)[inst].extended; |
| 479 | switch (extended.opcode) { | 479 | switch (extended.opcode) { |
| 480 | // zig fmt: off | 480 | // zig fmt: off |
| 481 | .func => return sema.zirFuncExtended( block, extended), | 481 | .func => return sema.zirFuncExtended( block, extended, inst), |
| 482 | .variable => return sema.zirVarExtended( block, extended), | 482 | .variable => return sema.zirVarExtended( block, extended), |
| 483 | .ret_ptr => return sema.zirRetPtr( block, extended), | 483 | .ret_ptr => return sema.zirRetPtr( block, extended), |
| 484 | .ret_type => return sema.zirRetType( block, extended), | 484 | .ret_type => return sema.zirRetType( block, extended), |
| ... | @@ -2747,13 +2747,13 @@ fn zirFunc( | ... | @@ -2747,13 +2747,13 @@ fn zirFunc( |
| 2747 | const src = inst_data.src(); | 2747 | const src = inst_data.src(); |
| 2748 | const extra = sema.code.extraData(Zir.Inst.Func, inst_data.payload_index); | 2748 | const extra = sema.code.extraData(Zir.Inst.Func, inst_data.payload_index); |
| 2749 | const param_types = sema.code.refSlice(extra.end, extra.data.param_types_len); | 2749 | const param_types = sema.code.refSlice(extra.end, extra.data.param_types_len); |
| 2750 | const body = sema.code.extra[extra.end + param_types.len ..][0..extra.data.body_len]; | 2750 | const body_inst = if (extra.data.body_len != 0) inst else 0; |
| 2751 | | 2751 | |
| 2752 | return sema.funcCommon( | 2752 | return sema.funcCommon( |
| 2753 | block, | 2753 | block, |
| 2754 | inst_data.src_node, | 2754 | inst_data.src_node, |
| 2755 | param_types, | 2755 | param_types, |
| 2756 | body, | 2756 | body_inst, |
| 2757 | extra.data.return_type, | 2757 | extra.data.return_type, |
| 2758 | .Unspecified, | 2758 | .Unspecified, |
| 2759 | Value.initTag(.null_value), | 2759 | Value.initTag(.null_value), |
| ... | @@ -2767,7 +2767,7 @@ fn funcCommon( | ... | @@ -2767,7 +2767,7 @@ fn funcCommon( |
| 2767 | block: *Scope.Block, | 2767 | block: *Scope.Block, |
| 2768 | src_node_offset: i32, | 2768 | src_node_offset: i32, |
| 2769 | zir_param_types: []const Zir.Inst.Ref, | 2769 | zir_param_types: []const Zir.Inst.Ref, |
| 2770 | body: []const Zir.Inst.Index, | 2770 | body_inst: Zir.Inst.Index, |
| 2771 | zir_return_type: Zir.Inst.Ref, | 2771 | zir_return_type: Zir.Inst.Ref, |
| 2772 | cc: std.builtin.CallingConvention, | 2772 | cc: std.builtin.CallingConvention, |
| 2773 | align_val: Value, | 2773 | align_val: Value, |
| ... | @@ -2778,49 +2778,77 @@ fn funcCommon( | ... | @@ -2778,49 +2778,77 @@ fn funcCommon( |
| 2778 | const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = src_node_offset }; | 2778 | const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = src_node_offset }; |
| 2779 | const return_type = try sema.resolveType(block, ret_ty_src, zir_return_type); | 2779 | const return_type = try sema.resolveType(block, ret_ty_src, zir_return_type); |
| 2780 | | 2780 | |
| 2781 | if (body.len == 0) { | 2781 | const fn_ty: Type = fn_ty: { |
| 2782 | return sema.mod.fail(&block.base, src, "TODO: Sema: implement func with body", .{}); | 2782 | // Hot path for some common function types. |
| 2783 | } | 2783 | if (zir_param_types.len == 0 and !var_args and align_val.tag() == .null_value) { |
| | 2784 | if (return_type.zigTypeTag() == .NoReturn and cc == .Unspecified) { |
| | 2785 | break :fn_ty Type.initTag(.fn_noreturn_no_args); |
| | 2786 | } |
| 2784 | | 2787 | |
| 2785 | // Hot path for some common function types. | 2788 | if (return_type.zigTypeTag() == .Void and cc == .Unspecified) { |
| 2786 | if (zir_param_types.len == 0 and !var_args and align_val.tag() == .null_value) { | 2789 | break :fn_ty Type.initTag(.fn_void_no_args); |
| 2787 | if (return_type.zigTypeTag() == .NoReturn and cc == .Unspecified) { | 2790 | } |
| 2788 | return sema.mod.constType(sema.arena, src, Type.initTag(.fn_noreturn_no_args)); | 2791 | |
| 2789 | } | 2792 | if (return_type.zigTypeTag() == .NoReturn and cc == .Naked) { |
| | 2793 | break :fn_ty Type.initTag(.fn_naked_noreturn_no_args); |
| | 2794 | } |
| 2790 | | 2795 | |
| 2791 | if (return_type.zigTypeTag() == .Void and cc == .Unspecified) { | 2796 | if (return_type.zigTypeTag() == .Void and cc == .C) { |
| 2792 | return sema.mod.constType(sema.arena, src, Type.initTag(.fn_void_no_args)); | 2797 | break :fn_ty Type.initTag(.fn_ccc_void_no_args); |
| | 2798 | } |
| 2793 | } | 2799 | } |
| 2794 | | 2800 | |
| 2795 | if (return_type.zigTypeTag() == .NoReturn and cc == .Naked) { | 2801 | const param_types = try sema.arena.alloc(Type, zir_param_types.len); |
| 2796 | return sema.mod.constType(sema.arena, src, Type.initTag(.fn_naked_noreturn_no_args)); | 2802 | for (zir_param_types) |param_type, i| { |
| | 2803 | // TODO make a compile error from `resolveType` report the source location |
| | 2804 | // of the specific parameter. Will need to take a similar strategy as |
| | 2805 | // `resolveSwitchItemVal` to avoid resolving the source location unless |
| | 2806 | // we actually need to report an error. |
| | 2807 | param_types[i] = try sema.resolveType(block, src, param_type); |
| 2797 | } | 2808 | } |
| 2798 | | 2809 | |
| 2799 | if (return_type.zigTypeTag() == .Void and cc == .C) { | 2810 | if (align_val.tag() != .null_value) { |
| 2800 | return sema.mod.constType(sema.arena, src, Type.initTag(.fn_ccc_void_no_args)); | 2811 | return sema.mod.fail(&block.base, src, "TODO implement support for function prototypes to have alignment specified", .{}); |
| 2801 | } | 2812 | } |
| 2802 | } | | |
| 2803 | | 2813 | |
| 2804 | const param_types = try sema.arena.alloc(Type, zir_param_types.len); | 2814 | break :fn_ty try Type.Tag.function.create(sema.arena, .{ |
| 2805 | for (zir_param_types) |param_type, i| { | 2815 | .param_types = param_types, |
| 2806 | // TODO make a compile error from `resolveType` report the source location | 2816 | .return_type = return_type, |
| 2807 | // of the specific parameter. Will need to take a similar strategy as | 2817 | .cc = cc, |
| 2808 | // `resolveSwitchItemVal` to avoid resolving the source location unless | 2818 | .is_var_args = var_args, |
| 2809 | // we actually need to report an error. | 2819 | }); |
| 2810 | param_types[i] = try sema.resolveType(block, src, param_type); | 2820 | }; |
| 2811 | } | | |
| 2812 | | 2821 | |
| 2813 | if (align_val.tag() != .null_value) { | 2822 | if (body_inst == 0) { |
| 2814 | return sema.mod.fail(&block.base, src, "TODO implement support for function prototypes to have alignment specified", .{}); | 2823 | return sema.mod.constType(sema.arena, src, fn_ty); |
| 2815 | } | 2824 | } |
| 2816 | | 2825 | |
| 2817 | const fn_ty = try Type.Tag.function.create(sema.arena, .{ | 2826 | const is_inline = fn_ty.fnCallingConvention() == .Inline; |
| 2818 | .param_types = param_types, | 2827 | const anal_state: Module.Fn.Analysis = if (is_inline) .inline_only else .queued; |
| 2819 | .return_type = return_type, | 2828 | |
| 2820 | .cc = cc, | 2829 | // Use the Decl's arena for function memory. |
| 2821 | .is_var_args = var_args, | 2830 | var fn_arena = std.heap.ArenaAllocator.init(sema.gpa); |
| | 2831 | errdefer fn_arena.deinit(); |
| | 2832 | |
| | 2833 | const new_func = try fn_arena.allocator.create(Module.Fn); |
| | 2834 | const fn_payload = try fn_arena.allocator.create(Value.Payload.Function); |
| | 2835 | |
| | 2836 | new_func.* = .{ |
| | 2837 | .state = anal_state, |
| | 2838 | .zir_body_inst = body_inst, |
| | 2839 | .owner_decl = sema.owner_decl, |
| | 2840 | .body = undefined, |
| | 2841 | }; |
| | 2842 | fn_payload.* = .{ |
| | 2843 | .base = .{ .tag = .function }, |
| | 2844 | .data = new_func, |
| | 2845 | }; |
| | 2846 | const result = try sema.mod.constInst(sema.arena, src, .{ |
| | 2847 | .ty = fn_ty, |
| | 2848 | .val = Value.initPayload(&fn_payload.base), |
| 2822 | }); | 2849 | }); |
| 2823 | return sema.mod.constType(sema.arena, src, fn_ty); | 2850 | try sema.owner_decl.finalizeNewArena(&fn_arena); |
| | 2851 | return result; |
| 2824 | } | 2852 | } |
| 2825 | | 2853 | |
| 2826 | fn zirAs(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst { | 2854 | fn zirAs(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst { |
| ... | @@ -5461,6 +5489,7 @@ fn zirFuncExtended( | ... | @@ -5461,6 +5489,7 @@ fn zirFuncExtended( |
| 5461 | sema: *Sema, | 5489 | sema: *Sema, |
| 5462 | block: *Scope.Block, | 5490 | block: *Scope.Block, |
| 5463 | extended: Zir.Inst.Extended.InstData, | 5491 | extended: Zir.Inst.Extended.InstData, |
| | 5492 | inst: Zir.Inst.Index, |
| 5464 | ) InnerError!*Inst { | 5493 | ) InnerError!*Inst { |
| 5465 | const tracy = trace(@src()); | 5494 | const tracy = trace(@src()); |
| 5466 | defer tracy.end(); | 5495 | defer tracy.end(); |
| ... | @@ -5502,13 +5531,13 @@ fn zirFuncExtended( | ... | @@ -5502,13 +5531,13 @@ fn zirFuncExtended( |
| 5502 | const param_types = sema.code.refSlice(extra_index, extra.data.param_types_len); | 5531 | const param_types = sema.code.refSlice(extra_index, extra.data.param_types_len); |
| 5503 | extra_index += param_types.len; | 5532 | extra_index += param_types.len; |
| 5504 | | 5533 | |
| 5505 | const body = sema.code.extra[extra_index..][0..extra.data.body_len]; | 5534 | const body_inst = if (extra.data.body_len != 0) inst else 0; |
| 5506 | | 5535 | |
| 5507 | return sema.funcCommon( | 5536 | return sema.funcCommon( |
| 5508 | block, | 5537 | block, |
| 5509 | extra.data.src_node, | 5538 | extra.data.src_node, |
| 5510 | param_types, | 5539 | param_types, |
| 5511 | body, | 5540 | body_inst, |
| 5512 | extra.data.return_type, | 5541 | extra.data.return_type, |
| 5513 | cc, | 5542 | cc, |
| 5514 | align_val, | 5543 | align_val, |