| ... | ... | @@ -478,7 +478,7 @@ fn zirExtended(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerErro |
| 478 | 478 | const extended = sema.code.instructions.items(.data)[inst].extended; |
| 479 | 479 | switch (extended.opcode) { |
| 480 | 480 | // zig fmt: off |
| 481 | | .func => return sema.zirFuncExtended( block, extended), |
| 481 | .func => return sema.zirFuncExtended( block, extended, inst), |
| 482 | 482 | .variable => return sema.zirVarExtended( block, extended), |
| 483 | 483 | .ret_ptr => return sema.zirRetPtr( block, extended), |
| 484 | 484 | .ret_type => return sema.zirRetType( block, extended), |
| ... | ... | @@ -2747,13 +2747,13 @@ fn zirFunc( |
| 2747 | 2747 | const src = inst_data.src(); |
| 2748 | 2748 | const extra = sema.code.extraData(Zir.Inst.Func, inst_data.payload_index); |
| 2749 | 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 | 2752 | return sema.funcCommon( |
| 2753 | 2753 | block, |
| 2754 | 2754 | inst_data.src_node, |
| 2755 | 2755 | param_types, |
| 2756 | | body, |
| 2756 | body_inst, |
| 2757 | 2757 | extra.data.return_type, |
| 2758 | 2758 | .Unspecified, |
| 2759 | 2759 | Value.initTag(.null_value), |
| ... | ... | @@ -2767,7 +2767,7 @@ fn funcCommon( |
| 2767 | 2767 | block: *Scope.Block, |
| 2768 | 2768 | src_node_offset: i32, |
| 2769 | 2769 | zir_param_types: []const Zir.Inst.Ref, |
| 2770 | | body: []const Zir.Inst.Index, |
| 2770 | body_inst: Zir.Inst.Index, |
| 2771 | 2771 | zir_return_type: Zir.Inst.Ref, |
| 2772 | 2772 | cc: std.builtin.CallingConvention, |
| 2773 | 2773 | align_val: Value, |
| ... | ... | @@ -2778,49 +2778,77 @@ fn funcCommon( |
| 2778 | 2778 | const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = src_node_offset }; |
| 2779 | 2779 | const return_type = try sema.resolveType(block, ret_ty_src, zir_return_type); |
| 2780 | 2780 | |
| 2781 | | if (body.len == 0) { |
| 2782 | | return sema.mod.fail(&block.base, src, "TODO: Sema: implement func with body", .{}); |
| 2783 | | } |
| 2781 | const fn_ty: Type = fn_ty: { |
| 2782 | // Hot path for some common function types. |
| 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. |
| 2786 | | if (zir_param_types.len == 0 and !var_args and align_val.tag() == .null_value) { |
| 2787 | | if (return_type.zigTypeTag() == .NoReturn and cc == .Unspecified) { |
| 2788 | | return sema.mod.constType(sema.arena, src, Type.initTag(.fn_noreturn_no_args)); |
| 2789 | | } |
| 2788 | if (return_type.zigTypeTag() == .Void and cc == .Unspecified) { |
| 2789 | break :fn_ty Type.initTag(.fn_void_no_args); |
| 2790 | } |
| 2791 | |
| 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) { |
| 2792 | | return sema.mod.constType(sema.arena, src, Type.initTag(.fn_void_no_args)); |
| 2796 | if (return_type.zigTypeTag() == .Void and cc == .C) { |
| 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) { |
| 2796 | | return sema.mod.constType(sema.arena, src, Type.initTag(.fn_naked_noreturn_no_args)); |
| 2801 | const param_types = try sema.arena.alloc(Type, zir_param_types.len); |
| 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) { |
| 2800 | | return sema.mod.constType(sema.arena, src, Type.initTag(.fn_ccc_void_no_args)); |
| 2810 | if (align_val.tag() != .null_value) { |
| 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); |
| 2805 | | for (zir_param_types) |param_type, i| { |
| 2806 | | // TODO make a compile error from `resolveType` report the source location |
| 2807 | | // of the specific parameter. Will need to take a similar strategy as |
| 2808 | | // `resolveSwitchItemVal` to avoid resolving the source location unless |
| 2809 | | // we actually need to report an error. |
| 2810 | | param_types[i] = try sema.resolveType(block, src, param_type); |
| 2811 | | } |
| 2814 | break :fn_ty try Type.Tag.function.create(sema.arena, .{ |
| 2815 | .param_types = param_types, |
| 2816 | .return_type = return_type, |
| 2817 | .cc = cc, |
| 2818 | .is_var_args = var_args, |
| 2819 | }); |
| 2820 | }; |
| 2812 | 2821 | |
| 2813 | | if (align_val.tag() != .null_value) { |
| 2814 | | return sema.mod.fail(&block.base, src, "TODO implement support for function prototypes to have alignment specified", .{}); |
| 2822 | if (body_inst == 0) { |
| 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, .{ |
| 2818 | | .param_types = param_types, |
| 2819 | | .return_type = return_type, |
| 2820 | | .cc = cc, |
| 2821 | | .is_var_args = var_args, |
| 2826 | const is_inline = fn_ty.fnCallingConvention() == .Inline; |
| 2827 | const anal_state: Module.Fn.Analysis = if (is_inline) .inline_only else .queued; |
| 2828 | |
| 2829 | // Use the Decl's arena for function memory. |
| 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 | 2854 | fn zirAs(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst { |
| ... | ... | @@ -5461,6 +5489,7 @@ fn zirFuncExtended( |
| 5461 | 5489 | sema: *Sema, |
| 5462 | 5490 | block: *Scope.Block, |
| 5463 | 5491 | extended: Zir.Inst.Extended.InstData, |
| 5492 | inst: Zir.Inst.Index, |
| 5464 | 5493 | ) InnerError!*Inst { |
| 5465 | 5494 | const tracy = trace(@src()); |
| 5466 | 5495 | defer tracy.end(); |
| ... | ... | @@ -5502,13 +5531,13 @@ fn zirFuncExtended( |
| 5502 | 5531 | const param_types = sema.code.refSlice(extra_index, extra.data.param_types_len); |
| 5503 | 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 | 5536 | return sema.funcCommon( |
| 5508 | 5537 | block, |
| 5509 | 5538 | extra.data.src_node, |
| 5510 | 5539 | param_types, |
| 5511 | | body, |
| 5540 | body_inst, |
| 5512 | 5541 | extra.data.return_type, |
| 5513 | 5542 | cc, |
| 5514 | 5543 | align_val, |