authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-04-30 14:36:02-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-04-30 14:36:02-07:00
logdb7acd83d2fb18fc0fbd1b58e0638f2afaa595fb
treeb729267999627a662f2e3cc3e4bbfc4356ca48b2
parentfb95fd84431e399d79266d5c9c4acd8ea124399a

Sema: implement function declarations


3 files changed, 71 insertions(+), 51 deletions(-)

BRANCH_TODO-14
...@@ -274,17 +274,3 @@ pub fn analyzeNamespace(...@@ -274,17 +274,3 @@ pub fn analyzeNamespace(
274 }274 }
275 }275 }
276276
277 const is_inline = decl_tv.ty.fnCallingConvention() == .Inline;
278 const anal_state: Fn.Analysis = if (is_inline) .inline_only else .queued;
279
280 new_func.* = .{
281 .state = anal_state,
282 .zir = fn_zir,
283 .body = undefined,
284 .owner_decl = decl,
285 };
286 fn_payload.* = .{
287 .base = .{ .tag = .function },
288 .data = new_func,
289 };
290
src/Module.zig+5
...@@ -565,6 +565,11 @@ pub const EnumFull = struct {...@@ -565,6 +565,11 @@ pub const EnumFull = struct {
565/// the `Decl` only, with a `Value` tag of `extern_fn`.565/// the `Decl` only, with a `Value` tag of `extern_fn`.
566pub const Fn = struct {566pub const Fn = struct {
567 owner_decl: *Decl,567 owner_decl: *Decl,
568 /// The ZIR instruction that is a function instruction. Use this to find
569 /// the body. We store this rather than the body directly so that when ZIR
570 /// is regenerated on update(), we can map this to the new corresponding
571 /// ZIR instruction.
572 zir_body_inst: Zir.Inst.Index,
568 /// undefined unless analysis state is `success`.573 /// undefined unless analysis state is `success`.
569 body: ir.Body,574 body: ir.Body,
570 state: Analysis,575 state: Analysis,
src/Sema.zig+66-37
...@@ -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: off480 // 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;
27512751
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);
27802780
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 }
27842787
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 }
27902795
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 }
27942800
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 }
27982809
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 }
28032813
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 location2816 .return_type = return_type,
2807 // of the specific parameter. Will need to take a similar strategy as2817 .cc = cc,
2808 // `resolveSwitchItemVal` to avoid resolving the source location unless2818 .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 }
28122821
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 }
28162825
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}
28252853
2826fn zirAs(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {2854fn 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;
55045533
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;
55065535
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,