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(
274274 }
275275 }
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 {
565565/// the `Decl` only, with a `Value` tag of `extern_fn`.
566566pub const Fn = struct {
567567 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,
568573 /// undefined unless analysis state is `success`.
569574 body: ir.Body,
570575 state: Analysis,
src/Sema.zig+66-37
......@@ -478,7 +478,7 @@ fn zirExtended(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerErro
478478 const extended = sema.code.instructions.items(.data)[inst].extended;
479479 switch (extended.opcode) {
480480 // zig fmt: off
481 .func => return sema.zirFuncExtended( block, extended),
481 .func => return sema.zirFuncExtended( block, extended, inst),
482482 .variable => return sema.zirVarExtended( block, extended),
483483 .ret_ptr => return sema.zirRetPtr( block, extended),
484484 .ret_type => return sema.zirRetType( block, extended),
......@@ -2747,13 +2747,13 @@ fn zirFunc(
27472747 const src = inst_data.src();
27482748 const extra = sema.code.extraData(Zir.Inst.Func, inst_data.payload_index);
27492749 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
27522752 return sema.funcCommon(
27532753 block,
27542754 inst_data.src_node,
27552755 param_types,
2756 body,
2756 body_inst,
27572757 extra.data.return_type,
27582758 .Unspecified,
27592759 Value.initTag(.null_value),
......@@ -2767,7 +2767,7 @@ fn funcCommon(
27672767 block: *Scope.Block,
27682768 src_node_offset: i32,
27692769 zir_param_types: []const Zir.Inst.Ref,
2770 body: []const Zir.Inst.Index,
2770 body_inst: Zir.Inst.Index,
27712771 zir_return_type: Zir.Inst.Ref,
27722772 cc: std.builtin.CallingConvention,
27732773 align_val: Value,
......@@ -2778,49 +2778,77 @@ fn funcCommon(
27782778 const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = src_node_offset };
27792779 const return_type = try sema.resolveType(block, ret_ty_src, zir_return_type);
27802780
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 }
27842787
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 }
27902795
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 }
27932799 }
27942800
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);
27972808 }
27982809
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", .{});
28012812 }
2802 }
28032813
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 };
28122821
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);
28152824 }
28162825
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),
28222849 });
2823 return sema.mod.constType(sema.arena, src, fn_ty);
2850 try sema.owner_decl.finalizeNewArena(&fn_arena);
2851 return result;
28242852}
28252853
28262854fn zirAs(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
......@@ -5461,6 +5489,7 @@ fn zirFuncExtended(
54615489 sema: *Sema,
54625490 block: *Scope.Block,
54635491 extended: Zir.Inst.Extended.InstData,
5492 inst: Zir.Inst.Index,
54645493) InnerError!*Inst {
54655494 const tracy = trace(@src());
54665495 defer tracy.end();
......@@ -5502,13 +5531,13 @@ fn zirFuncExtended(
55025531 const param_types = sema.code.refSlice(extra_index, extra.data.param_types_len);
55035532 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
55075536 return sema.funcCommon(
55085537 block,
55095538 extra.data.src_node,
55105539 param_types,
5511 body,
5540 body_inst,
55125541 extra.data.return_type,
55135542 cc,
55145543 align_val,