authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-05-29 17:54:16-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-05-30 12:03:53-07:00
log9da3a058d82573efeaf12fe61ab6a312649175ec
treeb86f6f08761289b95c46e10879e476da455de218
parentf846dc420fff629572caa1175bfa64e5fcffaeb5

stage2: add missing data to ZIR encoding of functions

The main purpose of this commit is to prepare to implement support for callconv(), align(), linksection(), and addrspace() annotations on generic functions where the provided expression depends on comptime parameters (making the function generic). It's a rather involved change, so this commit only makes the necessary changes to AstGen without regressing any behavior, and a follow-up commit can finish the task by making the enhancements to Sema. By my quick estimation, the new encoding for functions is a negligible improvement - along the lines of 0.005% fewer total ZIR bytes on average. Still, it's nice that this commit, while adding more data into ZIR, actually ends up reducing the storage size thanks to a slightly more sophisticated encoding. Zir.Inst.ExtendedFunc is renamed to Zir.Inst.FuncFancy to eliminate confusion about it being an extended instruction (it used to be but is no longer). The encoding for this instruction is completely reworked. The encoding for Zir.Inst.Func is also changed slightly - when the return type body length is 1, then only a Zir.Inst.Ref is provided; not a full body. linksection() and addrspace() are now communicated via func_fancy ZIR instruction rather than as part of the corresponding decl. This allows their expressions to observe comptime parameters.

5 files changed, 803 insertions(+), 241 deletions(-)

src/AstGen.zig+271-81
...@@ -73,7 +73,7 @@ fn setExtra(astgen: *AstGen, index: usize, extra: anytype) void {...@@ -73,7 +73,7 @@ fn setExtra(astgen: *AstGen, index: usize, extra: anytype) void {
73 Zir.Inst.Call.Flags => @bitCast(u32, @field(extra, field.name)),73 Zir.Inst.Call.Flags => @bitCast(u32, @field(extra, field.name)),
74 Zir.Inst.BuiltinCall.Flags => @bitCast(u32, @field(extra, field.name)),74 Zir.Inst.BuiltinCall.Flags => @bitCast(u32, @field(extra, field.name)),
75 Zir.Inst.SwitchBlock.Bits => @bitCast(u32, @field(extra, field.name)),75 Zir.Inst.SwitchBlock.Bits => @bitCast(u32, @field(extra, field.name)),
76 Zir.Inst.ExtendedFunc.Bits => @bitCast(u32, @field(extra, field.name)),76 Zir.Inst.FuncFancy.Bits => @bitCast(u32, @field(extra, field.name)),
77 else => @compileError("bad field type"),77 else => @compileError("bad field type"),
78 };78 };
79 i += 1;79 i += 1;
...@@ -1205,7 +1205,7 @@ fn fnProtoExpr(...@@ -1205,7 +1205,7 @@ fn fnProtoExpr(
1205 break :is_var_args false;1205 break :is_var_args false;
1206 };1206 };
12071207
1208 const align_inst: Zir.Inst.Ref = if (fn_proto.ast.align_expr == 0) .none else inst: {1208 const align_ref: Zir.Inst.Ref = if (fn_proto.ast.align_expr == 0) .none else inst: {
1209 break :inst try expr(&block_scope, scope, align_rl, fn_proto.ast.align_expr);1209 break :inst try expr(&block_scope, scope, align_rl, fn_proto.ast.align_expr);
1210 };1210 };
12111211
...@@ -1232,19 +1232,24 @@ fn fnProtoExpr(...@@ -1232,19 +1232,24 @@ fn fnProtoExpr(
1232 if (is_inferred_error) {1232 if (is_inferred_error) {
1233 return astgen.failTok(maybe_bang, "function prototype may not have inferred error set", .{});1233 return astgen.failTok(maybe_bang, "function prototype may not have inferred error set", .{});
1234 }1234 }
1235 var ret_gz = block_scope.makeSubBlock(scope);1235 const ret_ty = try expr(&block_scope, scope, coerced_type_rl, fn_proto.ast.return_type);
1236 defer ret_gz.unstack();
1237 const ret_ty = try expr(&ret_gz, scope, coerced_type_rl, fn_proto.ast.return_type);
1238 const ret_br = try ret_gz.addBreak(.break_inline, 0, ret_ty);
12391236
1240 const result = try block_scope.addFunc(.{1237 const result = try block_scope.addFunc(.{
1241 .src_node = fn_proto.ast.proto_node,1238 .src_node = fn_proto.ast.proto_node,
1239
1240 .cc_ref = cc,
1241 .cc_gz = null,
1242 .align_ref = align_ref,
1243 .align_gz = null,
1244 .ret_ref = ret_ty,
1245 .ret_gz = null,
1246 .section_ref = .none,
1247 .section_gz = null,
1248 .addrspace_ref = .none,
1249 .addrspace_gz = null,
1250
1242 .param_block = block_inst,1251 .param_block = block_inst,
1243 .ret_gz = &ret_gz,
1244 .ret_br = ret_br,
1245 .body_gz = null,1252 .body_gz = null,
1246 .cc = cc,
1247 .align_inst = align_inst,
1248 .lib_name = 0,1253 .lib_name = 0,
1249 .is_var_args = is_var_args,1254 .is_var_args = is_var_args,
1250 .is_inferred_error = false,1255 .is_inferred_error = false,
...@@ -2282,7 +2287,7 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: Ast.Node.Index) Inner...@@ -2282,7 +2287,7 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: Ast.Node.Index) Inner
2282 .field_val_named,2287 .field_val_named,
2283 .func,2288 .func,
2284 .func_inferred,2289 .func_inferred,
2285 .func_extended,2290 .func_fancy,
2286 .int,2291 .int,
2287 .int_big,2292 .int_big,
2288 .float,2293 .float,
...@@ -3395,9 +3400,8 @@ fn fnDecl(...@@ -3395,9 +3400,8 @@ fn fnDecl(
33953400
3396 const doc_comment_index = try astgen.docCommentAsString(fn_proto.firstToken());3401 const doc_comment_index = try astgen.docCommentAsString(fn_proto.firstToken());
33973402
3398 const has_section_or_addrspace = fn_proto.ast.section_expr != 0 or fn_proto.ast.addrspace_expr != 0;3403 // align, linksection, and addrspace is passed in the func instruction in this case.
3399 // Alignment is passed in the func instruction in this case.3404 wip_members.nextDecl(is_pub, is_export, false, false);
3400 wip_members.nextDecl(is_pub, is_export, false, has_section_or_addrspace);
34013405
3402 var params_scope = &fn_gz.base;3406 var params_scope = &fn_gz.base;
3403 const is_var_args = is_var_args: {3407 const is_var_args = is_var_args: {
...@@ -3483,17 +3487,49 @@ fn fnDecl(...@@ -3483,17 +3487,49 @@ fn fnDecl(
3483 const maybe_bang = tree.firstToken(fn_proto.ast.return_type) - 1;3487 const maybe_bang = tree.firstToken(fn_proto.ast.return_type) - 1;
3484 const is_inferred_error = token_tags[maybe_bang] == .bang;3488 const is_inferred_error = token_tags[maybe_bang] == .bang;
34853489
3486 const align_inst: Zir.Inst.Ref = if (fn_proto.ast.align_expr == 0) .none else inst: {3490 // After creating the function ZIR instruction, it will need to update the break
3487 break :inst try expr(&decl_gz, params_scope, align_rl, fn_proto.ast.align_expr);3491 // instructions inside the expression blocks for align, addrspace, cc, and ret_ty
3492 // to use the function instruction as the "block" to break from.
3493
3494 var align_gz = decl_gz.makeSubBlock(params_scope);
3495 defer align_gz.unstack();
3496 const align_ref: Zir.Inst.Ref = if (fn_proto.ast.align_expr == 0) .none else inst: {
3497 const inst = try expr(&decl_gz, params_scope, coerced_align_rl, fn_proto.ast.align_expr);
3498 if (align_gz.instructionsSlice().len == 0) {
3499 // In this case we will send a len=0 body which can be encoded more efficiently.
3500 break :inst inst;
3501 }
3502 _ = try align_gz.addBreak(.break_inline, 0, inst);
3503 break :inst inst;
3488 };3504 };
3489 const addrspace_inst: Zir.Inst.Ref = if (fn_proto.ast.addrspace_expr == 0) .none else inst: {3505
3490 break :inst try expr(&decl_gz, params_scope, .{ .ty = .address_space_type }, fn_proto.ast.addrspace_expr);3506 var addrspace_gz = decl_gz.makeSubBlock(params_scope);
3507 defer addrspace_gz.unstack();
3508 const addrspace_ref: Zir.Inst.Ref = if (fn_proto.ast.addrspace_expr == 0) .none else inst: {
3509 const inst = try expr(&decl_gz, params_scope, .{ .coerced_ty = .address_space_type }, fn_proto.ast.addrspace_expr);
3510 if (addrspace_gz.instructionsSlice().len == 0) {
3511 // In this case we will send a len=0 body which can be encoded more efficiently.
3512 break :inst inst;
3513 }
3514 _ = try addrspace_gz.addBreak(.break_inline, 0, inst);
3515 break :inst inst;
3491 };3516 };
3492 const section_inst: Zir.Inst.Ref = if (fn_proto.ast.section_expr == 0) .none else inst: {3517
3493 break :inst try comptimeExpr(&decl_gz, params_scope, .{ .ty = .const_slice_u8_type }, fn_proto.ast.section_expr);3518 var section_gz = decl_gz.makeSubBlock(params_scope);
3519 defer section_gz.unstack();
3520 const section_ref: Zir.Inst.Ref = if (fn_proto.ast.section_expr == 0) .none else inst: {
3521 const inst = try expr(&decl_gz, params_scope, .{ .coerced_ty = .const_slice_u8_type }, fn_proto.ast.section_expr);
3522 if (section_gz.instructionsSlice().len == 0) {
3523 // In this case we will send a len=0 body which can be encoded more efficiently.
3524 break :inst inst;
3525 }
3526 _ = try section_gz.addBreak(.break_inline, 0, inst);
3527 break :inst inst;
3494 };3528 };
34953529
3496 const cc: Zir.Inst.Ref = blk: {3530 var cc_gz = decl_gz.makeSubBlock(params_scope);
3531 defer cc_gz.unstack();
3532 const cc_ref: Zir.Inst.Ref = blk: {
3497 if (fn_proto.ast.callconv_expr != 0) {3533 if (fn_proto.ast.callconv_expr != 0) {
3498 if (has_inline_keyword) {3534 if (has_inline_keyword) {
3499 return astgen.failNode(3535 return astgen.failNode(
...@@ -3502,12 +3538,18 @@ fn fnDecl(...@@ -3502,12 +3538,18 @@ fn fnDecl(
3502 .{},3538 .{},
3503 );3539 );
3504 }3540 }
3505 break :blk try expr(3541 const inst = try expr(
3506 &decl_gz,3542 &decl_gz,
3507 params_scope,3543 params_scope,
3508 .{ .ty = .calling_convention_type },3544 .{ .coerced_ty = .calling_convention_type },
3509 fn_proto.ast.callconv_expr,3545 fn_proto.ast.callconv_expr,
3510 );3546 );
3547 if (cc_gz.instructionsSlice().len == 0) {
3548 // In this case we will send a len=0 body which can be encoded more efficiently.
3549 break :blk inst;
3550 }
3551 _ = try cc_gz.addBreak(.break_inline, 0, inst);
3552 break :blk inst;
3511 } else if (is_extern) {3553 } else if (is_extern) {
3512 // note: https://github.com/ziglang/zig/issues/52693554 // note: https://github.com/ziglang/zig/issues/5269
3513 break :blk .calling_convention_c;3555 break :blk .calling_convention_c;
...@@ -3520,8 +3562,18 @@ fn fnDecl(...@@ -3520,8 +3562,18 @@ fn fnDecl(
35203562
3521 var ret_gz = decl_gz.makeSubBlock(params_scope);3563 var ret_gz = decl_gz.makeSubBlock(params_scope);
3522 defer ret_gz.unstack();3564 defer ret_gz.unstack();
3523 const ret_ty = try expr(&ret_gz, params_scope, coerced_type_rl, fn_proto.ast.return_type);3565 const ret_ref: Zir.Inst.Ref = switch (nodePrimitive(tree, fn_proto.ast.return_type)) {
3524 const ret_br = try ret_gz.addBreak(.break_inline, 0, ret_ty);3566 .none => inst: {
3567 const inst = try expr(&ret_gz, params_scope, coerced_type_rl, fn_proto.ast.return_type);
3568 if (ret_gz.instructionsSlice().len == 0) {
3569 // In this case we will send a len=0 body which can be encoded more efficiently.
3570 break :inst inst;
3571 }
3572 _ = try ret_gz.addBreak(.break_inline, 0, inst);
3573 break :inst inst;
3574 },
3575 else => |p| p,
3576 };
35253577
3526 const func_inst: Zir.Inst.Ref = if (body_node == 0) func: {3578 const func_inst: Zir.Inst.Ref = if (body_node == 0) func: {
3527 if (!is_extern) {3579 if (!is_extern) {
...@@ -3532,12 +3584,18 @@ fn fnDecl(...@@ -3532,12 +3584,18 @@ fn fnDecl(
3532 }3584 }
3533 break :func try decl_gz.addFunc(.{3585 break :func try decl_gz.addFunc(.{
3534 .src_node = decl_node,3586 .src_node = decl_node,
3587 .cc_ref = cc_ref,
3588 .cc_gz = &cc_gz,
3589 .align_ref = align_ref,
3590 .align_gz = &align_gz,
3591 .ret_ref = ret_ref,
3535 .ret_gz = &ret_gz,3592 .ret_gz = &ret_gz,
3536 .ret_br = ret_br,3593 .section_ref = section_ref,
3594 .section_gz = &section_gz,
3595 .addrspace_ref = addrspace_ref,
3596 .addrspace_gz = &addrspace_gz,
3537 .param_block = block_inst,3597 .param_block = block_inst,
3538 .body_gz = null,3598 .body_gz = null,
3539 .cc = cc,
3540 .align_inst = align_inst,
3541 .lib_name = lib_name,3599 .lib_name = lib_name,
3542 .is_var_args = is_var_args,3600 .is_var_args = is_var_args,
3543 .is_inferred_error = false,3601 .is_inferred_error = false,
...@@ -3571,14 +3629,20 @@ fn fnDecl(...@@ -3571,14 +3629,20 @@ fn fnDecl(
35713629
3572 break :func try decl_gz.addFunc(.{3630 break :func try decl_gz.addFunc(.{
3573 .src_node = decl_node,3631 .src_node = decl_node,
3632 .cc_ref = cc_ref,
3633 .cc_gz = &cc_gz,
3634 .align_ref = align_ref,
3635 .align_gz = &align_gz,
3636 .ret_ref = ret_ref,
3637 .ret_gz = &ret_gz,
3638 .section_ref = section_ref,
3639 .section_gz = &section_gz,
3640 .addrspace_ref = addrspace_ref,
3641 .addrspace_gz = &addrspace_gz,
3574 .lbrace_line = lbrace_line,3642 .lbrace_line = lbrace_line,
3575 .lbrace_column = lbrace_column,3643 .lbrace_column = lbrace_column,
3576 .param_block = block_inst,3644 .param_block = block_inst,
3577 .ret_gz = &ret_gz,
3578 .ret_br = ret_br,
3579 .body_gz = &fn_gz,3645 .body_gz = &fn_gz,
3580 .cc = cc,
3581 .align_inst = align_inst,
3582 .lib_name = lib_name,3646 .lib_name = lib_name,
3583 .is_var_args = is_var_args,3647 .is_var_args = is_var_args,
3584 .is_inferred_error = is_inferred_error,3648 .is_inferred_error = is_inferred_error,
...@@ -3604,10 +3668,6 @@ fn fnDecl(...@@ -3604,10 +3668,6 @@ fn fnDecl(
3604 wip_members.appendToDecl(fn_name_str_index);3668 wip_members.appendToDecl(fn_name_str_index);
3605 wip_members.appendToDecl(block_inst);3669 wip_members.appendToDecl(block_inst);
3606 wip_members.appendToDecl(doc_comment_index);3670 wip_members.appendToDecl(doc_comment_index);
3607 if (has_section_or_addrspace) {
3608 wip_members.appendToDecl(@enumToInt(section_inst));
3609 wip_members.appendToDecl(@enumToInt(addrspace_inst));
3610 }
3611}3671}
36123672
3613fn globalVarDecl(3673fn globalVarDecl(
...@@ -4001,14 +4061,22 @@ fn testDecl(...@@ -4001,14 +4061,22 @@ fn testDecl(
40014061
4002 const func_inst = try decl_block.addFunc(.{4062 const func_inst = try decl_block.addFunc(.{
4003 .src_node = node,4063 .src_node = node,
4064
4065 .cc_ref = .none,
4066 .cc_gz = null,
4067 .align_ref = .none,
4068 .align_gz = null,
4069 .ret_ref = .void_type,
4070 .ret_gz = null,
4071 .section_ref = .none,
4072 .section_gz = null,
4073 .addrspace_ref = .none,
4074 .addrspace_gz = null,
4075
4004 .lbrace_line = lbrace_line,4076 .lbrace_line = lbrace_line,
4005 .lbrace_column = lbrace_column,4077 .lbrace_column = lbrace_column,
4006 .param_block = block_inst,4078 .param_block = block_inst,
4007 .ret_gz = null,
4008 .ret_br = 0,
4009 .body_gz = &fn_block,4079 .body_gz = &fn_block,
4010 .cc = .none,
4011 .align_inst = .none,
4012 .lib_name = 0,4080 .lib_name = 0,
4013 .is_var_args = false,4081 .is_var_args = false,
4014 .is_inferred_error = true,4082 .is_inferred_error = true,
...@@ -8957,6 +9025,31 @@ fn nodeImpliesComptimeOnly(tree: *const Ast, start_node: Ast.Node.Index) bool {...@@ -8957,6 +9025,31 @@ fn nodeImpliesComptimeOnly(tree: *const Ast, start_node: Ast.Node.Index) bool {
8957 }9025 }
8958}9026}
89599027
9028fn nodePrimitive(tree: *const Ast, start_node: Ast.Node.Index) Zir.Inst.Ref {
9029 const node_tags = tree.nodes.items(.tag);
9030 const node_datas = tree.nodes.items(.data);
9031
9032 var node = start_node;
9033 while (true) {
9034 switch (node_tags[node]) {
9035 // Forward the question to the LHS sub-expression.
9036 .grouped_expression => node = node_datas[node].lhs,
9037
9038 .identifier => {
9039 const main_tokens = tree.nodes.items(.main_token);
9040 const ident_bytes = tree.tokenSlice(main_tokens[node]);
9041 if (primitives.get(ident_bytes)) |primitive| {
9042 return primitive;
9043 } else {
9044 return .none;
9045 }
9046 },
9047
9048 else => return .none,
9049 }
9050 }
9051}
9052
8960/// Applies `rl` semantics to `result`. Expressions which do not do their own handling of9053/// Applies `rl` semantics to `result`. Expressions which do not do their own handling of
8961/// result locations must call this function on their result.9054/// result locations must call this function on their result.
8962/// As an example, if the `ResultLoc` is `ptr`, it will write the result to the pointer.9055/// As an example, if the `ResultLoc` is `ptr`, it will write the result to the pointer.
...@@ -9952,17 +10045,34 @@ const GenZir = struct {...@@ -9952,17 +10045,34 @@ const GenZir = struct {
9952 gz.unstack();10045 gz.unstack();
9953 }10046 }
995410047
9955 /// Supports `body_gz` stacked on `ret_gz` stacked on `gz`. Unstacks `body_gz` and `ret_gz`.10048 /// Must be called with the following stack set up:
10049 /// * gz (bottom)
10050 /// * align_gz
10051 /// * addrspace_gz
10052 /// * section_gz
10053 /// * cc_gz
10054 /// * ret_gz
10055 /// * body_gz (top)
10056 /// Unstacks all of those except for `gz`.
9956 fn addFunc(gz: *GenZir, args: struct {10057 fn addFunc(gz: *GenZir, args: struct {
9957 src_node: Ast.Node.Index,10058 src_node: Ast.Node.Index,
9958 lbrace_line: u32 = 0,10059 lbrace_line: u32 = 0,
9959 lbrace_column: u32 = 0,10060 lbrace_column: u32 = 0,
9960 body_gz: ?*GenZir,
9961 param_block: Zir.Inst.Index,10061 param_block: Zir.Inst.Index,
10062
10063 align_gz: ?*GenZir,
10064 addrspace_gz: ?*GenZir,
10065 section_gz: ?*GenZir,
10066 cc_gz: ?*GenZir,
9962 ret_gz: ?*GenZir,10067 ret_gz: ?*GenZir,
9963 ret_br: Zir.Inst.Index,10068 body_gz: ?*GenZir,
9964 cc: Zir.Inst.Ref,10069
9965 align_inst: Zir.Inst.Ref,10070 align_ref: Zir.Inst.Ref,
10071 addrspace_ref: Zir.Inst.Ref,
10072 section_ref: Zir.Inst.Ref,
10073 cc_ref: Zir.Inst.Ref,
10074 ret_ref: Zir.Inst.Ref,
10075
9966 lib_name: u32,10076 lib_name: u32,
9967 is_var_args: bool,10077 is_var_args: bool,
9968 is_inferred_error: bool,10078 is_inferred_error: bool,
...@@ -9972,11 +10082,13 @@ const GenZir = struct {...@@ -9972,11 +10082,13 @@ const GenZir = struct {
9972 assert(args.src_node != 0);10082 assert(args.src_node != 0);
9973 const astgen = gz.astgen;10083 const astgen = gz.astgen;
9974 const gpa = astgen.gpa;10084 const gpa = astgen.gpa;
10085 const ret_ref = if (args.ret_ref == .void_type) .none else args.ret_ref;
10086 const new_index = @intCast(Zir.Inst.Index, astgen.instructions.len);
997510087
9976 try astgen.instructions.ensureUnusedCapacity(gpa, 1);10088 try astgen.instructions.ensureUnusedCapacity(gpa, 1);
997710089
9978 var body: []Zir.Inst.Index = &[0]Zir.Inst.Index{};10090 var body: []Zir.Inst.Index = &[0]Zir.Inst.Index{};
9979 var ret_ty: []Zir.Inst.Index = &[0]Zir.Inst.Index{};10091 var ret_body: []Zir.Inst.Index = &[0]Zir.Inst.Index{};
9980 var src_locs_buffer: [3]u32 = undefined;10092 var src_locs_buffer: [3]u32 = undefined;
9981 var src_locs: []u32 = src_locs_buffer[0..0];10093 var src_locs: []u32 = src_locs_buffer[0..0];
9982 if (args.body_gz) |body_gz| {10094 if (args.body_gz) |body_gz| {
...@@ -10000,61 +10112,120 @@ const GenZir = struct {...@@ -10000,61 +10112,120 @@ const GenZir = struct {
1000010112
10001 body = body_gz.instructionsSlice();10113 body = body_gz.instructionsSlice();
10002 if (args.ret_gz) |ret_gz|10114 if (args.ret_gz) |ret_gz|
10003 ret_ty = ret_gz.instructionsSliceUpto(body_gz);10115 ret_body = ret_gz.instructionsSliceUpto(body_gz);
10004 } else {10116 } else {
10005 if (args.ret_gz) |ret_gz|10117 if (args.ret_gz) |ret_gz|
10006 ret_ty = ret_gz.instructionsSlice();10118 ret_body = ret_gz.instructionsSlice();
10007 }10119 }
1000810120
10009 if (args.cc != .none or args.lib_name != 0 or10121 if (args.cc_ref != .none or args.lib_name != 0 or
10010 args.is_var_args or args.is_test or args.align_inst != .none or10122 args.is_var_args or args.is_test or args.is_extern or
10011 args.is_extern)10123 args.align_ref != .none or args.section_ref != .none or
10124 args.addrspace_ref != .none)
10012 {10125 {
10126 var align_body: []Zir.Inst.Index = &.{};
10127 var addrspace_body: []Zir.Inst.Index = &.{};
10128 var section_body: []Zir.Inst.Index = &.{};
10129 var cc_body: []Zir.Inst.Index = &.{};
10130 if (args.ret_gz != null) {
10131 align_body = args.align_gz.?.instructionsSliceUpto(args.addrspace_gz.?);
10132 addrspace_body = args.addrspace_gz.?.instructionsSliceUpto(args.section_gz.?);
10133 section_body = args.section_gz.?.instructionsSliceUpto(args.cc_gz.?);
10134 cc_body = args.cc_gz.?.instructionsSliceUpto(args.ret_gz.?);
10135 }
10136
10013 try astgen.extra.ensureUnusedCapacity(10137 try astgen.extra.ensureUnusedCapacity(
10014 gpa,10138 gpa,
10015 @typeInfo(Zir.Inst.ExtendedFunc).Struct.fields.len +10139 @typeInfo(Zir.Inst.FuncFancy).Struct.fields.len +
10016 ret_ty.len + body.len + src_locs.len +10140 fancyFnExprExtraLen(align_body, args.align_ref) +
10017 @boolToInt(args.lib_name != 0) +10141 fancyFnExprExtraLen(addrspace_body, args.addrspace_ref) +
10018 @boolToInt(args.align_inst != .none) +10142 fancyFnExprExtraLen(section_body, args.section_ref) +
10019 @boolToInt(args.cc != .none),10143 fancyFnExprExtraLen(cc_body, args.cc_ref) +
10144 fancyFnExprExtraLen(ret_body, ret_ref) +
10145 body.len + src_locs.len +
10146 @boolToInt(args.lib_name != 0),
10020 );10147 );
10021 const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.ExtendedFunc{10148 const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.FuncFancy{
10022 .param_block = args.param_block,10149 .param_block = args.param_block,
10023 .ret_body_len = @intCast(u32, ret_ty.len),
10024 .body_len = @intCast(u32, body.len),10150 .body_len = @intCast(u32, body.len),
10025 .bits = .{10151 .bits = .{
10026 .is_var_args = args.is_var_args,10152 .is_var_args = args.is_var_args,
10027 .is_inferred_error = args.is_inferred_error,10153 .is_inferred_error = args.is_inferred_error,
10028 .has_lib_name = args.lib_name != 0,
10029 .has_cc = args.cc != .none,
10030 .has_align = args.align_inst != .none,
10031 .is_test = args.is_test,10154 .is_test = args.is_test,
10032 .is_extern = args.is_extern,10155 .is_extern = args.is_extern,
10156 .has_lib_name = args.lib_name != 0,
10157
10158 .has_align_ref = args.align_ref != .none,
10159 .has_addrspace_ref = args.addrspace_ref != .none,
10160 .has_section_ref = args.section_ref != .none,
10161 .has_cc_ref = args.cc_ref != .none,
10162 .has_ret_ty_ref = ret_ref != .none,
10163
10164 .has_align_body = align_body.len != 0,
10165 .has_addrspace_body = addrspace_body.len != 0,
10166 .has_section_body = section_body.len != 0,
10167 .has_cc_body = cc_body.len != 0,
10168 .has_ret_ty_body = ret_body.len != 0,
10033 },10169 },
10034 });10170 });
10035 if (args.lib_name != 0) {10171 if (args.lib_name != 0) {
10036 astgen.extra.appendAssumeCapacity(args.lib_name);10172 astgen.extra.appendAssumeCapacity(args.lib_name);
10037 }10173 }
10038 if (args.cc != .none) {10174
10039 astgen.extra.appendAssumeCapacity(@enumToInt(args.cc));10175 const zir_datas = astgen.instructions.items(.data);
10176 if (align_body.len != 0) {
10177 astgen.extra.appendAssumeCapacity(@intCast(u32, align_body.len));
10178 astgen.extra.appendSliceAssumeCapacity(align_body);
10179 zir_datas[align_body[align_body.len - 1]].@"break".block_inst = new_index;
10180 } else if (args.align_ref != .none) {
10181 astgen.extra.appendAssumeCapacity(@enumToInt(args.align_ref));
10182 }
10183 if (addrspace_body.len != 0) {
10184 astgen.extra.appendAssumeCapacity(@intCast(u32, addrspace_body.len));
10185 astgen.extra.appendSliceAssumeCapacity(addrspace_body);
10186 zir_datas[addrspace_body[addrspace_body.len - 1]].@"break".block_inst = new_index;
10187 } else if (args.addrspace_ref != .none) {
10188 astgen.extra.appendAssumeCapacity(@enumToInt(args.addrspace_ref));
10189 }
10190 if (section_body.len != 0) {
10191 astgen.extra.appendAssumeCapacity(@intCast(u32, section_body.len));
10192 astgen.extra.appendSliceAssumeCapacity(section_body);
10193 zir_datas[section_body[section_body.len - 1]].@"break".block_inst = new_index;
10194 } else if (args.section_ref != .none) {
10195 astgen.extra.appendAssumeCapacity(@enumToInt(args.section_ref));
10040 }10196 }
10041 if (args.align_inst != .none) {10197 if (cc_body.len != 0) {
10042 astgen.extra.appendAssumeCapacity(@enumToInt(args.align_inst));10198 astgen.extra.appendAssumeCapacity(@intCast(u32, cc_body.len));
10199 astgen.extra.appendSliceAssumeCapacity(cc_body);
10200 zir_datas[cc_body[cc_body.len - 1]].@"break".block_inst = new_index;
10201 } else if (args.cc_ref != .none) {
10202 astgen.extra.appendAssumeCapacity(@enumToInt(args.cc_ref));
10043 }10203 }
10044 astgen.extra.appendSliceAssumeCapacity(ret_ty);10204 if (ret_body.len != 0) {
10205 astgen.extra.appendAssumeCapacity(@intCast(u32, ret_body.len));
10206 astgen.extra.appendSliceAssumeCapacity(ret_body);
10207 zir_datas[ret_body[ret_body.len - 1]].@"break".block_inst = new_index;
10208 } else if (ret_ref != .none) {
10209 astgen.extra.appendAssumeCapacity(@enumToInt(ret_ref));
10210 }
10211
10045 astgen.extra.appendSliceAssumeCapacity(body);10212 astgen.extra.appendSliceAssumeCapacity(body);
10046 astgen.extra.appendSliceAssumeCapacity(src_locs);10213 astgen.extra.appendSliceAssumeCapacity(src_locs);
10047 // order is important when unstacking10214
10215 // Order is important when unstacking.
10048 if (args.body_gz) |body_gz| body_gz.unstack();10216 if (args.body_gz) |body_gz| body_gz.unstack();
10049 if (args.ret_gz) |ret_gz| ret_gz.unstack();10217 if (args.ret_gz != null) {
10218 args.ret_gz.?.unstack();
10219 args.cc_gz.?.unstack();
10220 args.section_gz.?.unstack();
10221 args.addrspace_gz.?.unstack();
10222 args.align_gz.?.unstack();
10223 }
10224
10050 try gz.instructions.ensureUnusedCapacity(gpa, 1);10225 try gz.instructions.ensureUnusedCapacity(gpa, 1);
1005110226
10052 const new_index = @intCast(Zir.Inst.Index, astgen.instructions.len);
10053 if (args.ret_br != 0) {
10054 astgen.instructions.items(.data)[args.ret_br].@"break".block_inst = new_index;
10055 }
10056 astgen.instructions.appendAssumeCapacity(.{10227 astgen.instructions.appendAssumeCapacity(.{
10057 .tag = .func_extended,10228 .tag = .func_fancy,
10058 .data = .{ .pl_node = .{10229 .data = .{ .pl_node = .{
10059 .src_node = gz.nodeIndexToRelative(args.src_node),10230 .src_node = gz.nodeIndexToRelative(args.src_node),
10060 .payload_index = payload_index,10231 .payload_index = payload_index,
...@@ -10066,27 +10237,40 @@ const GenZir = struct {...@@ -10066,27 +10237,40 @@ const GenZir = struct {
10066 try astgen.extra.ensureUnusedCapacity(10237 try astgen.extra.ensureUnusedCapacity(
10067 gpa,10238 gpa,
10068 @typeInfo(Zir.Inst.Func).Struct.fields.len +10239 @typeInfo(Zir.Inst.Func).Struct.fields.len +
10069 ret_ty.len + body.len + src_locs.len,10240 @maximum(ret_body.len, @boolToInt(ret_ref != .none)) +
10241 body.len + src_locs.len,
10070 );10242 );
10243 const ret_body_len = if (ret_body.len != 0)
10244 @intCast(u32, ret_body.len)
10245 else
10246 @boolToInt(ret_ref != .none);
1007110247
10072 const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.Func{10248 const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.Func{
10073 .param_block = args.param_block,10249 .param_block = args.param_block,
10074 .ret_body_len = @intCast(u32, ret_ty.len),10250 .ret_body_len = ret_body_len,
10075 .body_len = @intCast(u32, body.len),10251 .body_len = @intCast(u32, body.len),
10076 });10252 });
10077 astgen.extra.appendSliceAssumeCapacity(ret_ty);10253 const zir_datas = astgen.instructions.items(.data);
10254 if (ret_body.len != 0) {
10255 astgen.extra.appendSliceAssumeCapacity(ret_body);
10256 zir_datas[ret_body[ret_body.len - 1]].@"break".block_inst = new_index;
10257 } else if (ret_ref != .none) {
10258 astgen.extra.appendAssumeCapacity(@enumToInt(ret_ref));
10259 }
10078 astgen.extra.appendSliceAssumeCapacity(body);10260 astgen.extra.appendSliceAssumeCapacity(body);
10079 astgen.extra.appendSliceAssumeCapacity(src_locs);10261 astgen.extra.appendSliceAssumeCapacity(src_locs);
10080 // order is important when unstacking10262
10263 // Order is important when unstacking.
10081 if (args.body_gz) |body_gz| body_gz.unstack();10264 if (args.body_gz) |body_gz| body_gz.unstack();
10082 if (args.ret_gz) |ret_gz| ret_gz.unstack();10265 if (args.ret_gz) |ret_gz| ret_gz.unstack();
10266 if (args.cc_gz) |cc_gz| cc_gz.unstack();
10267 if (args.section_gz) |section_gz| section_gz.unstack();
10268 if (args.addrspace_gz) |addrspace_gz| addrspace_gz.unstack();
10269 if (args.align_gz) |align_gz| align_gz.unstack();
10270
10083 try gz.instructions.ensureUnusedCapacity(gpa, 1);10271 try gz.instructions.ensureUnusedCapacity(gpa, 1);
1008410272
10085 const tag: Zir.Inst.Tag = if (args.is_inferred_error) .func_inferred else .func;10273 const tag: Zir.Inst.Tag = if (args.is_inferred_error) .func_inferred else .func;
10086 const new_index = @intCast(Zir.Inst.Index, astgen.instructions.len);
10087 if (args.ret_br != 0) {
10088 astgen.instructions.items(.data)[args.ret_br].@"break".block_inst = new_index;
10089 }
10090 astgen.instructions.appendAssumeCapacity(.{10274 astgen.instructions.appendAssumeCapacity(.{
10091 .tag = tag,10275 .tag = tag,
10092 .data = .{ .pl_node = .{10276 .data = .{ .pl_node = .{
...@@ -10099,6 +10283,12 @@ const GenZir = struct {...@@ -10099,6 +10283,12 @@ const GenZir = struct {
10099 }10283 }
10100 }10284 }
1010110285
10286 fn fancyFnExprExtraLen(body: []Zir.Inst.Index, ref: Zir.Inst.Ref) usize {
10287 // In the case of non-empty body, there is one for the body length,
10288 // and then one for each instruction.
10289 return body.len + @boolToInt(ref != .none);
10290 }
10291
10102 fn addVar(gz: *GenZir, args: struct {10292 fn addVar(gz: *GenZir, args: struct {
10103 align_inst: Zir.Inst.Ref,10293 align_inst: Zir.Inst.Ref,
10104 lib_name: u32,10294 lib_name: u32,
src/Module.zig+2-2
...@@ -1595,9 +1595,9 @@ pub const Fn = struct {...@@ -1595,9 +1595,9 @@ pub const Fn = struct {
1595 switch (zir_tags[func.zir_body_inst]) {1595 switch (zir_tags[func.zir_body_inst]) {
1596 .func => return false,1596 .func => return false,
1597 .func_inferred => return true,1597 .func_inferred => return true,
1598 .func_extended => {1598 .func_fancy => {
1599 const inst_data = zir.instructions.items(.data)[func.zir_body_inst].pl_node;1599 const inst_data = zir.instructions.items(.data)[func.zir_body_inst].pl_node;
1600 const extra = zir.extraData(Zir.Inst.ExtendedFunc, inst_data.payload_index);1600 const extra = zir.extraData(Zir.Inst.FuncFancy, inst_data.payload_index);
1601 return extra.data.bits.is_inferred_error;1601 return extra.data.bits.is_inferred_error;
1602 },1602 },
1603 else => unreachable,1603 else => unreachable,
src/Sema.zig+189-68
...@@ -747,7 +747,7 @@ fn analyzeBodyInner(...@@ -747,7 +747,7 @@ fn analyzeBodyInner(
747 .field_call_bind => try sema.zirFieldCallBind(block, inst),747 .field_call_bind => try sema.zirFieldCallBind(block, inst),
748 .func => try sema.zirFunc(block, inst, false),748 .func => try sema.zirFunc(block, inst, false),
749 .func_inferred => try sema.zirFunc(block, inst, true),749 .func_inferred => try sema.zirFunc(block, inst, true),
750 .func_extended => try sema.zirFuncExtended(block, inst),750 .func_fancy => try sema.zirFuncFancy(block, inst),
751 .import => try sema.zirImport(block, inst),751 .import => try sema.zirImport(block, inst),
752 .indexable_ptr_len => try sema.zirIndexablePtrLen(block, inst),752 .indexable_ptr_len => try sema.zirIndexablePtrLen(block, inst),
753 .int => try sema.zirInt(block, inst),753 .int => try sema.zirInt(block, inst),
...@@ -5186,7 +5186,10 @@ fn analyzeCall(...@@ -5186,7 +5186,10 @@ fn analyzeCall(
5186 // on parameters, we must now do the same for the return type as we just did with5186 // on parameters, we must now do the same for the return type as we just did with
5187 // each of the parameters, resolving the return type and providing it to the child5187 // each of the parameters, resolving the return type and providing it to the child
5188 // `Sema` so that it can be used for the `ret_ptr` instruction.5188 // `Sema` so that it can be used for the `ret_ptr` instruction.
5189 const ret_ty_inst = try sema.resolveBody(&child_block, fn_info.ret_ty_body, module_fn.zir_body_inst);5189 const ret_ty_inst = if (fn_info.ret_ty_body.len != 0)
5190 try sema.resolveBody(&child_block, fn_info.ret_ty_body, module_fn.zir_body_inst)
5191 else
5192 try sema.resolveInst(fn_info.ret_ty_ref);
5190 const ret_ty_src = func_src; // TODO better source location5193 const ret_ty_src = func_src; // TODO better source location
5191 const bare_return_type = try sema.analyzeAsType(&child_block, ret_ty_src, ret_ty_inst);5194 const bare_return_type = try sema.analyzeAsType(&child_block, ret_ty_src, ret_ty_inst);
5192 // Create a fresh inferred error set type for inline/comptime calls.5195 // Create a fresh inferred error set type for inline/comptime calls.
...@@ -6497,9 +6500,34 @@ fn zirFunc(...@@ -6497,9 +6500,34 @@ fn zirFunc(
64976500
6498 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;6501 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
6499 const extra = sema.code.extraData(Zir.Inst.Func, inst_data.payload_index);6502 const extra = sema.code.extraData(Zir.Inst.Func, inst_data.payload_index);
6503 const target = sema.mod.getTarget();
6504 const ret_ty_src = inst_data.src(); // TODO better source location
6505
6500 var extra_index = extra.end;6506 var extra_index = extra.end;
6501 const ret_ty_body = sema.code.extra[extra_index..][0..extra.data.ret_body_len];6507
6502 extra_index += ret_ty_body.len;6508 const ret_ty: Type = switch (extra.data.ret_body_len) {
6509 0 => Type.void,
6510 1 => blk: {
6511 const ret_ty_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);
6512 extra_index += 1;
6513 if (sema.resolveType(block, ret_ty_src, ret_ty_ref)) |ret_ty| {
6514 break :blk ret_ty;
6515 } else |err| switch (err) {
6516 error.GenericPoison => {
6517 break :blk Type.initTag(.generic_poison);
6518 },
6519 else => |e| return e,
6520 }
6521 },
6522 else => blk: {
6523 const ret_ty_body = sema.code.extra[extra_index..][0..extra.data.ret_body_len];
6524 extra_index += ret_ty_body.len;
6525
6526 const ret_ty_val = try sema.resolveGenericBody(block, ret_ty_src, ret_ty_body, inst, Type.type);
6527 var buffer: Value.ToTypeBuffer = undefined;
6528 break :blk try ret_ty_val.toType(&buffer).copy(sema.arena);
6529 },
6530 };
65036531
6504 var src_locs: Zir.Inst.Func.SrcLocs = undefined;6532 var src_locs: Zir.Inst.Func.SrcLocs = undefined;
6505 const has_body = extra.data.body_len != 0;6533 const has_body = extra.data.body_len != 0;
...@@ -6517,9 +6545,11 @@ fn zirFunc(...@@ -6517,9 +6545,11 @@ fn zirFunc(
6517 block,6545 block,
6518 inst_data.src_node,6546 inst_data.src_node,
6519 inst,6547 inst,
6520 ret_ty_body,6548 0,
6549 target_util.defaultAddressSpace(target, .function),
6550 null,
6521 cc,6551 cc,
6522 Value.@"null",6552 ret_ty,
6523 false,6553 false,
6524 inferred_error_set,6554 inferred_error_set,
6525 false,6555 false,
...@@ -6529,6 +6559,44 @@ fn zirFunc(...@@ -6529,6 +6559,44 @@ fn zirFunc(
6529 );6559 );
6530}6560}
65316561
6562// TODO this function and its callsites along with funcCommon need to be reworked
6563// to handle when callconv, align, linksection, addrspace depend on comptime values
6564// (thus triggering error.GenericPoison)
6565fn resolveGenericBody(
6566 sema: *Sema,
6567 block: *Block,
6568 src: LazySrcLoc,
6569 body: []const Zir.Inst.Index,
6570 func_inst: Zir.Inst.Index,
6571 dest_ty: Type,
6572) !Value {
6573 assert(body.len != 0);
6574
6575 const err = err: {
6576 // Make sure any nested param instructions don't clobber our work.
6577 const prev_params = block.params;
6578 block.params = .{};
6579 defer {
6580 block.params.deinit(sema.gpa);
6581 block.params = prev_params;
6582 }
6583 const uncasted = sema.resolveBody(block, body, func_inst) catch |err| break :err err;
6584 const result = sema.coerce(block, dest_ty, uncasted, src) catch |err| break :err err;
6585 const val = sema.resolveConstValue(block, src, result) catch |err| break :err err;
6586 return val;
6587 };
6588 switch (err) {
6589 error.GenericPoison => {
6590 if (dest_ty.tag() == .type) {
6591 return Value.initTag(.generic_poison_type);
6592 } else {
6593 return Value.initTag(.generic_poison);
6594 }
6595 },
6596 else => |e| return e,
6597 }
6598}
6599
6532/// Given a library name, examines if the library name should end up in6600/// Given a library name, examines if the library name should end up in
6533/// `link.File.Options.system_libs` table (for example, libc is always6601/// `link.File.Options.system_libs` table (for example, libc is always
6534/// specified via dedicated flag `link.File.Options.link_libc` instead),6602/// specified via dedicated flag `link.File.Options.link_libc` instead),
...@@ -6597,9 +6665,11 @@ fn funcCommon(...@@ -6597,9 +6665,11 @@ fn funcCommon(
6597 block: *Block,6665 block: *Block,
6598 src_node_offset: i32,6666 src_node_offset: i32,
6599 func_inst: Zir.Inst.Index,6667 func_inst: Zir.Inst.Index,
6600 ret_ty_body: []const Zir.Inst.Index,6668 alignment: u32,
6669 address_space: std.builtin.AddressSpace,
6670 section: ?[*:0]const u8,
6601 cc: std.builtin.CallingConvention,6671 cc: std.builtin.CallingConvention,
6602 align_val: Value,6672 bare_return_type: Type,
6603 var_args: bool,6673 var_args: bool,
6604 inferred_error_set: bool,6674 inferred_error_set: bool,
6605 is_extern: bool,6675 is_extern: bool,
...@@ -6609,42 +6679,11 @@ fn funcCommon(...@@ -6609,42 +6679,11 @@ fn funcCommon(
6609) CompileError!Air.Inst.Ref {6679) CompileError!Air.Inst.Ref {
6610 const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = src_node_offset };6680 const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = src_node_offset };
66116681
6612 // The return type body might be a type expression that depends on generic parameters.6682 var is_generic = bare_return_type.tag() == .generic_poison;
6613 // In such case we need to use a generic_poison value for the return type and mark6683 // Check for generic params.
6614 // the function as generic.6684 for (block.params.items) |param| {
6615 var is_generic = false;6685 if (param.ty.tag() == .generic_poison) is_generic = true;
6616 const bare_return_type: Type = ret_ty: {6686 }
6617 if (ret_ty_body.len == 0) break :ret_ty Type.void;
6618
6619 const err = err: {
6620 // Make sure any nested param instructions don't clobber our work.
6621 const prev_params = block.params;
6622 block.params = .{};
6623 defer {
6624 block.params.deinit(sema.gpa);
6625 block.params = prev_params;
6626 }
6627 if (sema.resolveBody(block, ret_ty_body, func_inst)) |ret_ty_inst| {
6628 if (sema.analyzeAsType(block, ret_ty_src, ret_ty_inst)) |ret_ty| {
6629 break :ret_ty ret_ty;
6630 } else |err| break :err err;
6631 } else |err| break :err err;
6632 // Check for generic params.
6633 for (block.params.items) |param| {
6634 if (param.ty.tag() == .generic_poison) is_generic = true;
6635 }
6636 };
6637 switch (err) {
6638 error.GenericPoison => {
6639 // The type is not available until the generic instantiation.
6640 is_generic = true;
6641 break :ret_ty Type.initTag(.generic_poison);
6642 },
6643 else => |e| return e,
6644 }
6645 };
6646
6647 const mod = sema.mod;
66486687
6649 const new_func: *Module.Fn = new_func: {6688 const new_func: *Module.Fn = new_func: {
6650 if (!has_body) break :new_func undefined;6689 if (!has_body) break :new_func undefined;
...@@ -6661,18 +6700,7 @@ fn funcCommon(...@@ -6661,18 +6700,7 @@ fn funcCommon(
6661 errdefer if (maybe_inferred_error_set_node) |node| sema.gpa.destroy(node);6700 errdefer if (maybe_inferred_error_set_node) |node| sema.gpa.destroy(node);
6662 // Note: no need to errdefer since this will still be in its default state at the end of the function.6701 // Note: no need to errdefer since this will still be in its default state at the end of the function.
66636702
6664 const target = mod.getTarget();
6665
6666 const fn_ty: Type = fn_ty: {6703 const fn_ty: Type = fn_ty: {
6667 const alignment: u32 = if (align_val.tag() == .null_value) 0 else a: {
6668 const alignment = @intCast(u32, align_val.toUnsignedInt(target));
6669 if (alignment == target_util.defaultFunctionAlignment(target)) {
6670 break :a 0;
6671 } else {
6672 break :a alignment;
6673 }
6674 };
6675
6676 // Hot path for some common function types.6704 // Hot path for some common function types.
6677 // TODO can we eliminate some of these Type tag values? seems unnecessarily complicated.6705 // TODO can we eliminate some of these Type tag values? seems unnecessarily complicated.
6678 if (!is_generic and block.params.items.len == 0 and !var_args and6706 if (!is_generic and block.params.items.len == 0 and !var_args and
...@@ -6747,6 +6775,12 @@ fn funcCommon(...@@ -6747,6 +6775,12 @@ fn funcCommon(
6747 });6775 });
6748 };6776 };
67496777
6778 if (sema.owner_decl.owns_tv) {
6779 sema.owner_decl.@"linksection" = section;
6780 sema.owner_decl.@"align" = alignment;
6781 sema.owner_decl.@"addrspace" = address_space;
6782 }
6783
6750 if (is_extern) {6784 if (is_extern) {
6751 const new_extern_fn = try sema.gpa.create(Module.ExternFn);6785 const new_extern_fn = try sema.gpa.create(Module.ExternFn);
6752 errdefer sema.gpa.destroy(new_extern_fn);6786 errdefer sema.gpa.destroy(new_extern_fn);
...@@ -16723,16 +16757,20 @@ fn zirVarExtended(...@@ -16723,16 +16757,20 @@ fn zirVarExtended(
16723 return result;16757 return result;
16724}16758}
1672516759
16726fn zirFuncExtended(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {16760fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
16727 const tracy = trace(@src());16761 const tracy = trace(@src());
16728 defer tracy.end();16762 defer tracy.end();
1672916763
16730 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;16764 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
16731 const src = inst_data.src();16765 const src = inst_data.src();
16732 const extra = sema.code.extraData(Zir.Inst.ExtendedFunc, inst_data.payload_index);16766 const extra = sema.code.extraData(Zir.Inst.FuncFancy, inst_data.payload_index);
16767 const target = sema.mod.getTarget();
1673316768
16734 const cc_src: LazySrcLoc = .{ .node_offset_fn_type_cc = inst_data.src_node };
16735 const align_src: LazySrcLoc = src; // TODO add a LazySrcLoc that points at align16769 const align_src: LazySrcLoc = src; // TODO add a LazySrcLoc that points at align
16770 const addrspace_src: LazySrcLoc = src; // TODO add a LazySrcLoc that points at addrspace
16771 const section_src: LazySrcLoc = src; // TODO add a LazySrcLoc that points at section
16772 const cc_src: LazySrcLoc = .{ .node_offset_fn_type_cc = inst_data.src_node };
16773 const ret_src: LazySrcLoc = src; // TODO add a LazySrcLoc that points at the return type
1673616774
16737 var extra_index: usize = extra.end;16775 var extra_index: usize = extra.end;
1673816776
...@@ -16742,22 +16780,103 @@ fn zirFuncExtended(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro...@@ -16742,22 +16780,103 @@ fn zirFuncExtended(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro
16742 break :blk lib_name;16780 break :blk lib_name;
16743 } else null;16781 } else null;
1674416782
16745 const cc: std.builtin.CallingConvention = if (extra.data.bits.has_cc) blk: {16783 const @"align": u32 = if (extra.data.bits.has_align_body) blk: {
16784 const body_len = sema.code.extra[extra_index];
16785 extra_index += 1;
16786 const body = sema.code.extra[extra_index..][0..body_len];
16787 extra_index += body.len;
16788
16789 const val = try sema.resolveGenericBody(block, align_src, body, inst, Type.u16);
16790 const alignment = @intCast(u32, val.toUnsignedInt(target));
16791 if (alignment == target_util.defaultFunctionAlignment(target)) {
16792 break :blk 0;
16793 } else {
16794 break :blk alignment;
16795 }
16796 } else if (extra.data.bits.has_align_ref) blk: {
16797 const align_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);
16798 extra_index += 1;
16799 const align_tv = try sema.resolveInstConst(block, align_src, align_ref);
16800 const alignment = @intCast(u32, align_tv.val.toUnsignedInt(target));
16801 if (alignment == target_util.defaultFunctionAlignment(target)) {
16802 break :blk 0;
16803 } else {
16804 break :blk alignment;
16805 }
16806 } else 0;
16807
16808 const @"addrspace": std.builtin.AddressSpace = if (extra.data.bits.has_addrspace_body) blk: {
16809 const body_len = sema.code.extra[extra_index];
16810 extra_index += 1;
16811 const body = sema.code.extra[extra_index..][0..body_len];
16812 extra_index += body.len;
16813
16814 const addrspace_ty = try sema.getBuiltinType(block, addrspace_src, "AddressSpace");
16815 const val = try sema.resolveGenericBody(block, addrspace_src, body, inst, addrspace_ty);
16816 break :blk val.toEnum(std.builtin.AddressSpace);
16817 } else if (extra.data.bits.has_addrspace_ref) blk: {
16818 const addrspace_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);
16819 extra_index += 1;
16820 const addrspace_tv = try sema.resolveInstConst(block, addrspace_src, addrspace_ref);
16821 break :blk addrspace_tv.val.toEnum(std.builtin.AddressSpace);
16822 } else target_util.defaultAddressSpace(target, .function);
16823
16824 const @"linksection": ?[*:0]const u8 = if (extra.data.bits.has_section_body) {
16825 const body_len = sema.code.extra[extra_index];
16826 extra_index += 1;
16827 const body = sema.code.extra[extra_index..][0..body_len];
16828 extra_index += body.len;
16829
16830 const val = try sema.resolveGenericBody(block, section_src, body, inst, Type.initTag(.const_slice_u8));
16831 _ = val;
16832 return sema.fail(block, section_src, "TODO implement linksection on functions", .{});
16833 } else if (extra.data.bits.has_section_ref) {
16834 const section_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);
16835 extra_index += 1;
16836 const section_tv = try sema.resolveInstConst(block, section_src, section_ref);
16837 _ = section_tv;
16838 return sema.fail(block, section_src, "TODO implement linksection on functions", .{});
16839 } else null;
16840
16841 const cc: std.builtin.CallingConvention = if (extra.data.bits.has_cc_body) blk: {
16842 const body_len = sema.code.extra[extra_index];
16843 extra_index += 1;
16844 const body = sema.code.extra[extra_index..][0..body_len];
16845 extra_index += body.len;
16846
16847 const cc_ty = try sema.getBuiltinType(block, addrspace_src, "CallingConvention");
16848 const val = try sema.resolveGenericBody(block, cc_src, body, inst, cc_ty);
16849 break :blk val.toEnum(std.builtin.CallingConvention);
16850 } else if (extra.data.bits.has_cc_ref) blk: {
16746 const cc_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);16851 const cc_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);
16747 extra_index += 1;16852 extra_index += 1;
16748 const cc_tv = try sema.resolveInstConst(block, cc_src, cc_ref);16853 const cc_tv = try sema.resolveInstConst(block, cc_src, cc_ref);
16749 break :blk cc_tv.val.toEnum(std.builtin.CallingConvention);16854 break :blk cc_tv.val.toEnum(std.builtin.CallingConvention);
16750 } else .Unspecified;16855 } else .Unspecified;
1675116856
16752 const align_val: Value = if (extra.data.bits.has_align) blk: {16857 const ret_ty: Type = if (extra.data.bits.has_ret_ty_body) blk: {
16753 const align_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);16858 const body_len = sema.code.extra[extra_index];
16754 extra_index += 1;16859 extra_index += 1;
16755 const align_tv = try sema.resolveInstConst(block, align_src, align_ref);16860 const body = sema.code.extra[extra_index..][0..body_len];
16756 break :blk align_tv.val;16861 extra_index += body.len;
16757 } else Value.@"null";
1675816862
16759 const ret_ty_body = sema.code.extra[extra_index..][0..extra.data.ret_body_len];16863 const val = try sema.resolveGenericBody(block, ret_src, body, inst, Type.type);
16760 extra_index += ret_ty_body.len;16864 var buffer: Value.ToTypeBuffer = undefined;
16865 const ty = try val.toType(&buffer).copy(sema.arena);
16866 break :blk ty;
16867 } else if (extra.data.bits.has_ret_ty_ref) blk: {
16868 const ret_ty_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);
16869 extra_index += 1;
16870 const ret_ty_tv = sema.resolveInstConst(block, ret_src, ret_ty_ref) catch |err| switch (err) {
16871 error.GenericPoison => {
16872 break :blk Type.initTag(.generic_poison);
16873 },
16874 else => |e| return e,
16875 };
16876 var buffer: Value.ToTypeBuffer = undefined;
16877 const ty = try ret_ty_tv.val.toType(&buffer).copy(sema.arena);
16878 break :blk ty;
16879 } else Type.void;
1676116880
16762 var src_locs: Zir.Inst.Func.SrcLocs = undefined;16881 var src_locs: Zir.Inst.Func.SrcLocs = undefined;
16763 const has_body = extra.data.body_len != 0;16882 const has_body = extra.data.body_len != 0;
...@@ -16774,9 +16893,11 @@ fn zirFuncExtended(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro...@@ -16774,9 +16893,11 @@ fn zirFuncExtended(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro
16774 block,16893 block,
16775 inst_data.src_node,16894 inst_data.src_node,
16776 inst,16895 inst,
16777 ret_ty_body,16896 @"align",
16897 @"addrspace",
16898 @"linksection",
16778 cc,16899 cc,
16779 align_val,16900 ret_ty,
16780 is_var_args,16901 is_var_args,
16781 is_inferred_error,16902 is_inferred_error,
16782 is_extern,16903 is_extern,
src/Zir.zig+209-53
...@@ -74,7 +74,7 @@ pub fn extraData(code: Zir, comptime T: type, index: usize) struct { data: T, en...@@ -74,7 +74,7 @@ pub fn extraData(code: Zir, comptime T: type, index: usize) struct { data: T, en
74 Inst.Call.Flags => @bitCast(Inst.Call.Flags, code.extra[i]),74 Inst.Call.Flags => @bitCast(Inst.Call.Flags, code.extra[i]),
75 Inst.BuiltinCall.Flags => @bitCast(Inst.BuiltinCall.Flags, code.extra[i]),75 Inst.BuiltinCall.Flags => @bitCast(Inst.BuiltinCall.Flags, code.extra[i]),
76 Inst.SwitchBlock.Bits => @bitCast(Inst.SwitchBlock.Bits, code.extra[i]),76 Inst.SwitchBlock.Bits => @bitCast(Inst.SwitchBlock.Bits, code.extra[i]),
77 Inst.ExtendedFunc.Bits => @bitCast(Inst.ExtendedFunc.Bits, code.extra[i]),77 Inst.FuncFancy.Bits => @bitCast(Inst.FuncFancy.Bits, code.extra[i]),
78 else => @compileError("bad field type"),78 else => @compileError("bad field type"),
79 };79 };
80 i += 1;80 i += 1;
...@@ -424,8 +424,8 @@ pub const Inst = struct {...@@ -424,8 +424,8 @@ pub const Inst = struct {
424 func_inferred,424 func_inferred,
425 /// Represents a function declaration or function prototype, depending on425 /// Represents a function declaration or function prototype, depending on
426 /// whether body_len is 0.426 /// whether body_len is 0.
427 /// Uses the `pl_node` union field. `payload_index` points to a `ExtendedFunc`.427 /// Uses the `pl_node` union field. `payload_index` points to a `FuncFancy`.
428 func_extended,428 func_fancy,
429 /// Implements the `@import` builtin.429 /// Implements the `@import` builtin.
430 /// Uses the `str_tok` field.430 /// Uses the `str_tok` field.
431 import,431 import,
...@@ -1070,7 +1070,7 @@ pub const Inst = struct {...@@ -1070,7 +1070,7 @@ pub const Inst = struct {
1070 .field_val_named,1070 .field_val_named,
1071 .func,1071 .func,
1072 .func_inferred,1072 .func_inferred,
1073 .func_extended,1073 .func_fancy,
1074 .has_decl,1074 .has_decl,
1075 .int,1075 .int,
1076 .int_big,1076 .int_big,
...@@ -1356,7 +1356,7 @@ pub const Inst = struct {...@@ -1356,7 +1356,7 @@ pub const Inst = struct {
1356 .field_val_named,1356 .field_val_named,
1357 .func,1357 .func,
1358 .func_inferred,1358 .func_inferred,
1359 .func_extended,1359 .func_fancy,
1360 .has_decl,1360 .has_decl,
1361 .int,1361 .int,
1362 .int_big,1362 .int_big,
...@@ -1611,7 +1611,7 @@ pub const Inst = struct {...@@ -1611,7 +1611,7 @@ pub const Inst = struct {
1611 .field_call_bind = .pl_node,1611 .field_call_bind = .pl_node,
1612 .func = .pl_node,1612 .func = .pl_node,
1613 .func_inferred = .pl_node,1613 .func_inferred = .pl_node,
1614 .func_extended = .pl_node,1614 .func_fancy = .pl_node,
1615 .import = .str_tok,1615 .import = .str_tok,
1616 .int = .int,1616 .int = .int,
1617 .int_big = .str,1617 .int_big = .str,
...@@ -2620,29 +2620,100 @@ pub const Inst = struct {...@@ -2620,29 +2620,100 @@ pub const Inst = struct {
2620 };2620 };
26212621
2622 /// Trailing:2622 /// Trailing:
2623 /// 0. lib_name: u32, // null terminated string index, if has_lib_name is set2623 /// if (ret_body_len == 1) {
2624 /// 1. cc: Ref, // if has_cc is set2624 /// 0. return_type: Ref
2625 /// 2. align: Ref, // if has_align is set2625 /// }
2626 /// 3. return_type: Index // for each ret_body_len2626 /// if (ret_body_len > 1) {
2627 /// 4. body: Index // for each body_len2627 /// 1. return_type: Index // for each ret_body_len
2628 /// 5. src_locs: Func.SrcLocs // if body_len != 02628 /// }
2629 pub const ExtendedFunc = struct {2629 /// 2. body: Index // for each body_len
2630 /// 3. src_locs: SrcLocs // if body_len != 0
2631 pub const Func = struct {
2630 /// If this is 0 it means a void return type.2632 /// If this is 0 it means a void return type.
2633 /// If this is 1 it means return_type is a simple Ref
2631 ret_body_len: u32,2634 ret_body_len: u32,
2632 /// Points to the block that contains the param instructions for this function.2635 /// Points to the block that contains the param instructions for this function.
2633 param_block: Index,2636 param_block: Index,
2634 body_len: u32,2637 body_len: u32,
2638
2639 pub const SrcLocs = struct {
2640 /// Line index in the source file relative to the parent decl.
2641 lbrace_line: u32,
2642 /// Line index in the source file relative to the parent decl.
2643 rbrace_line: u32,
2644 /// lbrace_column is least significant bits u16
2645 /// rbrace_column is most significant bits u16
2646 columns: u32,
2647 };
2648 };
2649
2650 /// Trailing:
2651 /// 0. lib_name: u32, // null terminated string index, if has_lib_name is set
2652 /// if (has_align_ref and !has_align_body) {
2653 /// 1. align: Ref,
2654 /// }
2655 /// if (has_align_body) {
2656 /// 2. align_body_len: u32
2657 /// 3. align_body: u32 // for each align_body_len
2658 /// }
2659 /// if (has_addrspace_ref and !has_addrspace_body) {
2660 /// 4. addrspace: Ref,
2661 /// }
2662 /// if (has_addrspace_body) {
2663 /// 5. addrspace_body_len: u32
2664 /// 6. addrspace_body: u32 // for each addrspace_body_len
2665 /// }
2666 /// if (has_section_ref and !has_section_body) {
2667 /// 7. section: Ref,
2668 /// }
2669 /// if (has_section_body) {
2670 /// 8. section_body_len: u32
2671 /// 9. section_body: u32 // for each section_body_len
2672 /// }
2673 /// if (has_cc_ref and !has_cc_body) {
2674 /// 10. cc: Ref,
2675 /// }
2676 /// if (has_cc_body) {
2677 /// 11. cc_body_len: u32
2678 /// 12. cc_body: u32 // for each cc_body_len
2679 /// }
2680 /// if (has_ret_ty_ref and !has_ret_ty_body) {
2681 /// 13. ret_ty: Ref,
2682 /// }
2683 /// if (has_ret_ty_body) {
2684 /// 14. ret_ty_body_len: u32
2685 /// 15. ret_ty_body: u32 // for each ret_ty_body_len
2686 /// }
2687 /// 16. body: Index // for each body_len
2688 /// 17. src_locs: Func.SrcLocs // if body_len != 0
2689 pub const FuncFancy = struct {
2690 /// Points to the block that contains the param instructions for this function.
2691 param_block: Index,
2692 body_len: u32,
2635 bits: Bits,2693 bits: Bits,
26362694
2695 /// If both has_cc_ref and has_cc_body are false, it means auto calling convention.
2696 /// If both has_align_ref and has_align_body are false, it means default alignment.
2697 /// If both has_ret_ty_ref and has_ret_ty_body are false, it means void return type.
2698 /// If both has_section_ref and has_section_body are false, it means default section.
2699 /// If both has_addrspace_ref and has_addrspace_body are false, it means default addrspace.
2637 pub const Bits = packed struct {2700 pub const Bits = packed struct {
2638 is_var_args: bool,2701 is_var_args: bool,
2639 is_inferred_error: bool,2702 is_inferred_error: bool,
2640 has_lib_name: bool,
2641 has_cc: bool,
2642 has_align: bool,
2643 is_test: bool,2703 is_test: bool,
2644 is_extern: bool,2704 is_extern: bool,
2645 _: u25 = undefined,2705 has_align_ref: bool,
2706 has_align_body: bool,
2707 has_addrspace_ref: bool,
2708 has_addrspace_body: bool,
2709 has_section_ref: bool,
2710 has_section_body: bool,
2711 has_cc_ref: bool,
2712 has_cc_body: bool,
2713 has_ret_ty_ref: bool,
2714 has_ret_ty_body: bool,
2715 has_lib_name: bool,
2716 _: u17 = undefined,
2646 };2717 };
2647 };2718 };
26482719
...@@ -2664,28 +2735,6 @@ pub const Inst = struct {...@@ -2664,28 +2735,6 @@ pub const Inst = struct {
2664 };2735 };
2665 };2736 };
26662737
2667 /// Trailing:
2668 /// 0. return_type: Index // for each ret_body_len
2669 /// 1. body: Index // for each body_len
2670 /// 2. src_locs: SrcLocs // if body_len != 0
2671 pub const Func = struct {
2672 /// If this is 0 it means a void return type.
2673 ret_body_len: u32,
2674 /// Points to the block that contains the param instructions for this function.
2675 param_block: Index,
2676 body_len: u32,
2677
2678 pub const SrcLocs = struct {
2679 /// Line index in the source file relative to the parent decl.
2680 lbrace_line: u32,
2681 /// Line index in the source file relative to the parent decl.
2682 rbrace_line: u32,
2683 /// lbrace_column is least significant bits u16
2684 /// rbrace_column is most significant bits u16
2685 columns: u32,
2686 };
2687 };
2688
2689 /// This data is stored inside extra, with trailing operands according to `operands_len`.2738 /// This data is stored inside extra, with trailing operands according to `operands_len`.
2690 /// Each operand is a `Ref`.2739 /// Each operand is a `Ref`.
2691 pub const MultiOp = struct {2740 pub const MultiOp = struct {
...@@ -3487,7 +3536,7 @@ pub fn declIterator(zir: Zir, decl_inst: u32) DeclIterator {...@@ -3487,7 +3536,7 @@ pub fn declIterator(zir: Zir, decl_inst: u32) DeclIterator {
3487 switch (tags[decl_inst]) {3536 switch (tags[decl_inst]) {
3488 // Functions are allowed and yield no iterations.3537 // Functions are allowed and yield no iterations.
3489 // There is one case matching this in the extended instruction set below.3538 // There is one case matching this in the extended instruction set below.
3490 .func, .func_inferred, .func_extended => return declIteratorInner(zir, 0, 0),3539 .func, .func_inferred, .func_fancy => return declIteratorInner(zir, 0, 0),
34913540
3492 .extended => {3541 .extended => {
3493 const extended = datas[decl_inst].extended;3542 const extended = datas[decl_inst].extended;
...@@ -3593,18 +3642,77 @@ fn findDeclsInner(...@@ -3593,18 +3642,77 @@ fn findDeclsInner(
35933642
3594 const inst_data = datas[inst].pl_node;3643 const inst_data = datas[inst].pl_node;
3595 const extra = zir.extraData(Inst.Func, inst_data.payload_index);3644 const extra = zir.extraData(Inst.Func, inst_data.payload_index);
3596 const body = zir.extra[extra.end..][0..extra.data.body_len];3645 var extra_index: usize = extra.end;
3646 switch (extra.data.ret_body_len) {
3647 0 => {},
3648 1 => extra_index += 1,
3649 else => {
3650 const body = zir.extra[extra_index..][0..extra.data.ret_body_len];
3651 extra_index += body.len;
3652 try zir.findDeclsBody(list, body);
3653 },
3654 }
3655 const body = zir.extra[extra_index..][0..extra.data.body_len];
3597 return zir.findDeclsBody(list, body);3656 return zir.findDeclsBody(list, body);
3598 },3657 },
3599 .func_extended => {3658 .func_fancy => {
3600 try list.append(inst);3659 try list.append(inst);
36013660
3602 const inst_data = datas[inst].pl_node;3661 const inst_data = datas[inst].pl_node;
3603 const extra = zir.extraData(Inst.ExtendedFunc, inst_data.payload_index);3662 const extra = zir.extraData(Inst.FuncFancy, inst_data.payload_index);
3604 var extra_index: usize = extra.end;3663 var extra_index: usize = extra.end;
3605 extra_index += @boolToInt(extra.data.bits.has_lib_name);3664 extra_index += @boolToInt(extra.data.bits.has_lib_name);
3606 extra_index += @boolToInt(extra.data.bits.has_cc);3665
3607 extra_index += @boolToInt(extra.data.bits.has_align);3666 if (extra.data.bits.has_align_body) {
3667 const body_len = zir.extra[extra_index];
3668 extra_index += 1;
3669 const body = zir.extra[extra_index..][0..body_len];
3670 try zir.findDeclsBody(list, body);
3671 extra_index += body.len;
3672 } else if (extra.data.bits.has_align_ref) {
3673 extra_index += 1;
3674 }
3675
3676 if (extra.data.bits.has_addrspace_body) {
3677 const body_len = zir.extra[extra_index];
3678 extra_index += 1;
3679 const body = zir.extra[extra_index..][0..body_len];
3680 try zir.findDeclsBody(list, body);
3681 extra_index += body.len;
3682 } else if (extra.data.bits.has_addrspace_ref) {
3683 extra_index += 1;
3684 }
3685
3686 if (extra.data.bits.has_section_body) {
3687 const body_len = zir.extra[extra_index];
3688 extra_index += 1;
3689 const body = zir.extra[extra_index..][0..body_len];
3690 try zir.findDeclsBody(list, body);
3691 extra_index += body.len;
3692 } else if (extra.data.bits.has_section_ref) {
3693 extra_index += 1;
3694 }
3695
3696 if (extra.data.bits.has_cc_body) {
3697 const body_len = zir.extra[extra_index];
3698 extra_index += 1;
3699 const body = zir.extra[extra_index..][0..body_len];
3700 try zir.findDeclsBody(list, body);
3701 extra_index += body.len;
3702 } else if (extra.data.bits.has_cc_ref) {
3703 extra_index += 1;
3704 }
3705
3706 if (extra.data.bits.has_ret_ty_body) {
3707 const body_len = zir.extra[extra_index];
3708 extra_index += 1;
3709 const body = zir.extra[extra_index..][0..body_len];
3710 try zir.findDeclsBody(list, body);
3711 extra_index += body.len;
3712 } else if (extra.data.bits.has_ret_ty_ref) {
3713 extra_index += 1;
3714 }
3715
3608 const body = zir.extra[extra_index..][0..extra.data.body_len];3716 const body = zir.extra[extra_index..][0..extra.data.body_len];
3609 return zir.findDeclsBody(list, body);3717 return zir.findDeclsBody(list, body);
3610 },3718 },
...@@ -3729,6 +3837,7 @@ pub const FnInfo = struct {...@@ -3729,6 +3837,7 @@ pub const FnInfo = struct {
3729 param_body_inst: Inst.Index,3837 param_body_inst: Inst.Index,
3730 ret_ty_body: []const Inst.Index,3838 ret_ty_body: []const Inst.Index,
3731 body: []const Inst.Index,3839 body: []const Inst.Index,
3840 ret_ty_ref: Zir.Inst.Ref,
3732 total_params_len: u32,3841 total_params_len: u32,
3733};3842};
37343843
...@@ -3738,38 +3847,84 @@ pub fn getFnInfo(zir: Zir, fn_inst: Inst.Index) FnInfo {...@@ -3738,38 +3847,84 @@ pub fn getFnInfo(zir: Zir, fn_inst: Inst.Index) FnInfo {
3738 const info: struct {3847 const info: struct {
3739 param_block: Inst.Index,3848 param_block: Inst.Index,
3740 body: []const Inst.Index,3849 body: []const Inst.Index,
3850 ret_ty_ref: Inst.Ref,
3741 ret_ty_body: []const Inst.Index,3851 ret_ty_body: []const Inst.Index,
3742 } = switch (tags[fn_inst]) {3852 } = switch (tags[fn_inst]) {
3743 .func, .func_inferred => blk: {3853 .func, .func_inferred => blk: {
3744 const inst_data = datas[fn_inst].pl_node;3854 const inst_data = datas[fn_inst].pl_node;
3745 const extra = zir.extraData(Inst.Func, inst_data.payload_index);3855 const extra = zir.extraData(Inst.Func, inst_data.payload_index);
3856
3746 var extra_index: usize = extra.end;3857 var extra_index: usize = extra.end;
3858 var ret_ty_ref: Inst.Ref = .none;
3859 var ret_ty_body: []const Inst.Index = &.{};
37473860
3748 const ret_ty_body = zir.extra[extra_index..][0..extra.data.ret_body_len];3861 switch (extra.data.ret_body_len) {
3749 extra_index += ret_ty_body.len;3862 0 => {
3863 ret_ty_ref = .void_type;
3864 },
3865 1 => {
3866 ret_ty_ref = @intToEnum(Inst.Ref, zir.extra[extra_index]);
3867 extra_index += 1;
3868 },
3869 else => {
3870 ret_ty_body = zir.extra[extra_index..][0..extra.data.ret_body_len];
3871 extra_index += ret_ty_body.len;
3872 },
3873 }
37503874
3751 const body = zir.extra[extra_index..][0..extra.data.body_len];3875 const body = zir.extra[extra_index..][0..extra.data.body_len];
3752 extra_index += body.len;3876 extra_index += body.len;
37533877
3754 break :blk .{3878 break :blk .{
3755 .param_block = extra.data.param_block,3879 .param_block = extra.data.param_block,
3880 .ret_ty_ref = ret_ty_ref,
3756 .ret_ty_body = ret_ty_body,3881 .ret_ty_body = ret_ty_body,
3757 .body = body,3882 .body = body,
3758 };3883 };
3759 },3884 },
3760 .func_extended => blk: {3885 .func_fancy => blk: {
3761 const inst_data = datas[fn_inst].pl_node;3886 const inst_data = datas[fn_inst].pl_node;
3762 const extra = zir.extraData(Inst.ExtendedFunc, inst_data.payload_index);3887 const extra = zir.extraData(Inst.FuncFancy, inst_data.payload_index);
3888
3763 var extra_index: usize = extra.end;3889 var extra_index: usize = extra.end;
3890 var ret_ty_ref: Inst.Ref = .void_type;
3891 var ret_ty_body: []const Inst.Index = &.{};
3892
3764 extra_index += @boolToInt(extra.data.bits.has_lib_name);3893 extra_index += @boolToInt(extra.data.bits.has_lib_name);
3765 extra_index += @boolToInt(extra.data.bits.has_cc);3894 if (extra.data.bits.has_align_body) {
3766 extra_index += @boolToInt(extra.data.bits.has_align);3895 extra_index += zir.extra[extra_index] + 1;
3767 const ret_ty_body = zir.extra[extra_index..][0..extra.data.ret_body_len];3896 } else if (extra.data.bits.has_align_ref) {
3768 extra_index += ret_ty_body.len;3897 extra_index += 1;
3898 }
3899 if (extra.data.bits.has_addrspace_body) {
3900 extra_index += zir.extra[extra_index] + 1;
3901 } else if (extra.data.bits.has_addrspace_ref) {
3902 extra_index += 1;
3903 }
3904 if (extra.data.bits.has_section_body) {
3905 extra_index += zir.extra[extra_index] + 1;
3906 } else if (extra.data.bits.has_section_ref) {
3907 extra_index += 1;
3908 }
3909 if (extra.data.bits.has_cc_body) {
3910 extra_index += zir.extra[extra_index] + 1;
3911 } else if (extra.data.bits.has_cc_ref) {
3912 extra_index += 1;
3913 }
3914 if (extra.data.bits.has_ret_ty_body) {
3915 const body_len = zir.extra[extra_index];
3916 extra_index += 1;
3917 ret_ty_body = zir.extra[extra_index..][0..body_len];
3918 extra_index += ret_ty_body.len;
3919 } else if (extra.data.bits.has_ret_ty_ref) {
3920 ret_ty_ref = @intToEnum(Inst.Ref, zir.extra[extra_index]);
3921 extra_index += 1;
3922 }
3769 const body = zir.extra[extra_index..][0..extra.data.body_len];3923 const body = zir.extra[extra_index..][0..extra.data.body_len];
3770 extra_index += body.len;3924 extra_index += body.len;
3771 break :blk .{3925 break :blk .{
3772 .param_block = extra.data.param_block,3926 .param_block = extra.data.param_block,
3927 .ret_ty_ref = ret_ty_ref,
3773 .ret_ty_body = ret_ty_body,3928 .ret_ty_body = ret_ty_body,
3774 .body = body,3929 .body = body,
3775 };3930 };
...@@ -3792,6 +3947,7 @@ pub fn getFnInfo(zir: Zir, fn_inst: Inst.Index) FnInfo {...@@ -3792,6 +3947,7 @@ pub fn getFnInfo(zir: Zir, fn_inst: Inst.Index) FnInfo {
3792 .param_body = param_body,3947 .param_body = param_body,
3793 .param_body_inst = info.param_block,3948 .param_body_inst = info.param_block,
3794 .ret_ty_body = info.ret_ty_body,3949 .ret_ty_body = info.ret_ty_body,
3950 .ret_ty_ref = info.ret_ty_ref,
3795 .body = info.body,3951 .body = info.body,
3796 .total_params_len = total_params_len,3952 .total_params_len = total_params_len,
3797 };3953 };
src/print_zir.zig+132-37
...@@ -429,7 +429,7 @@ const Writer = struct {...@@ -429,7 +429,7 @@ const Writer = struct {
429429
430 .func => try self.writeFunc(stream, inst, false),430 .func => try self.writeFunc(stream, inst, false),
431 .func_inferred => try self.writeFunc(stream, inst, true),431 .func_inferred => try self.writeFunc(stream, inst, true),
432 .func_extended => try self.writeFuncExtended(stream, inst),432 .func_fancy => try self.writeFuncFancy(stream, inst),
433433
434 .@"unreachable" => try self.writeUnreachable(stream, inst),434 .@"unreachable" => try self.writeUnreachable(stream, inst),
435435
...@@ -1912,10 +1912,24 @@ const Writer = struct {...@@ -1912,10 +1912,24 @@ const Writer = struct {
1912 const inst_data = self.code.instructions.items(.data)[inst].pl_node;1912 const inst_data = self.code.instructions.items(.data)[inst].pl_node;
1913 const src = inst_data.src();1913 const src = inst_data.src();
1914 const extra = self.code.extraData(Zir.Inst.Func, inst_data.payload_index);1914 const extra = self.code.extraData(Zir.Inst.Func, inst_data.payload_index);
1915
1915 var extra_index = extra.end;1916 var extra_index = extra.end;
1917 var ret_ty_ref: Zir.Inst.Ref = .none;
1918 var ret_ty_body: []const Zir.Inst.Index = &.{};
19161919
1917 const ret_ty_body = self.code.extra[extra_index..][0..extra.data.ret_body_len];1920 switch (extra.data.ret_body_len) {
1918 extra_index += ret_ty_body.len;1921 0 => {
1922 ret_ty_ref = .void_type;
1923 },
1924 1 => {
1925 ret_ty_ref = @intToEnum(Zir.Inst.Ref, self.code.extra[extra_index]);
1926 extra_index += 1;
1927 },
1928 else => {
1929 ret_ty_body = self.code.extra[extra_index..][0..extra.data.ret_body_len];
1930 extra_index += ret_ty_body.len;
1931 },
1932 }
19191933
1920 const body = self.code.extra[extra_index..][0..extra.data.body_len];1934 const body = self.code.extra[extra_index..][0..extra.data.body_len];
1921 extra_index += body.len;1935 extra_index += body.len;
...@@ -1926,43 +1940,96 @@ const Writer = struct {...@@ -1926,43 +1940,96 @@ const Writer = struct {
1926 }1940 }
1927 return self.writeFuncCommon(1941 return self.writeFuncCommon(
1928 stream,1942 stream,
1929 ret_ty_body,
1930 inferred_error_set,1943 inferred_error_set,
1931 false,1944 false,
1932 false,1945 false,
1946
1933 .none,1947 .none,
1948 &.{},
1934 .none,1949 .none,
1950 &.{},
1951 .none,
1952 &.{},
1953 .none,
1954 &.{},
1955 ret_ty_ref,
1956 ret_ty_body,
1957
1935 body,1958 body,
1936 src,1959 src,
1937 src_locs,1960 src_locs,
1938 );1961 );
1939 }1962 }
19401963
1941 fn writeFuncExtended(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {1964 fn writeFuncFancy(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {
1942 const inst_data = self.code.instructions.items(.data)[inst].pl_node;1965 const inst_data = self.code.instructions.items(.data)[inst].pl_node;
1943 const extra = self.code.extraData(Zir.Inst.ExtendedFunc, inst_data.payload_index);1966 const extra = self.code.extraData(Zir.Inst.FuncFancy, inst_data.payload_index);
1944 const src = inst_data.src();1967 const src = inst_data.src();
19451968
1946 var extra_index: usize = extra.end;1969 var extra_index: usize = extra.end;
1970 var align_ref: Zir.Inst.Ref = .none;
1971 var align_body: []const Zir.Inst.Index = &.{};
1972 var addrspace_ref: Zir.Inst.Ref = .none;
1973 var addrspace_body: []const Zir.Inst.Index = &.{};
1974 var section_ref: Zir.Inst.Ref = .none;
1975 var section_body: []const Zir.Inst.Index = &.{};
1976 var cc_ref: Zir.Inst.Ref = .none;
1977 var cc_body: []const Zir.Inst.Index = &.{};
1978 var ret_ty_ref: Zir.Inst.Ref = .none;
1979 var ret_ty_body: []const Zir.Inst.Index = &.{};
1980
1947 if (extra.data.bits.has_lib_name) {1981 if (extra.data.bits.has_lib_name) {
1948 const lib_name = self.code.nullTerminatedString(self.code.extra[extra_index]);1982 const lib_name = self.code.nullTerminatedString(self.code.extra[extra_index]);
1949 extra_index += 1;1983 extra_index += 1;
1950 try stream.print("lib_name=\"{}\", ", .{std.zig.fmtEscapes(lib_name)});1984 try stream.print("lib_name=\"{}\", ", .{std.zig.fmtEscapes(lib_name)});
1951 }1985 }
1952 try self.writeFlag(stream, "test, ", extra.data.bits.is_test);1986 try self.writeFlag(stream, "test, ", extra.data.bits.is_test);
1953 const cc: Zir.Inst.Ref = if (!extra.data.bits.has_cc) .none else blk: {1987
1954 const cc = @intToEnum(Zir.Inst.Ref, self.code.extra[extra_index]);1988 if (extra.data.bits.has_align_body) {
1989 const body_len = self.code.extra[extra_index];
1955 extra_index += 1;1990 extra_index += 1;
1956 break :blk cc;1991 align_body = self.code.extra[extra_index..][0..body_len];
1957 };1992 extra_index += align_body.len;
1958 const align_inst: Zir.Inst.Ref = if (!extra.data.bits.has_align) .none else blk: {1993 } else if (extra.data.bits.has_align_ref) {
1959 const align_inst = @intToEnum(Zir.Inst.Ref, self.code.extra[extra_index]);1994 align_ref = @intToEnum(Zir.Inst.Ref, self.code.extra[extra_index]);
1960 extra_index += 1;1995 extra_index += 1;
1961 break :blk align_inst;1996 }
1962 };1997 if (extra.data.bits.has_addrspace_body) {
19631998 const body_len = self.code.extra[extra_index];
1964 const ret_ty_body = self.code.extra[extra_index..][0..extra.data.ret_body_len];1999 extra_index += 1;
1965 extra_index += ret_ty_body.len;2000 addrspace_body = self.code.extra[extra_index..][0..body_len];
2001 extra_index += addrspace_body.len;
2002 } else if (extra.data.bits.has_addrspace_ref) {
2003 addrspace_ref = @intToEnum(Zir.Inst.Ref, self.code.extra[extra_index]);
2004 extra_index += 1;
2005 }
2006 if (extra.data.bits.has_section_body) {
2007 const body_len = self.code.extra[extra_index];
2008 extra_index += 1;
2009 section_body = self.code.extra[extra_index..][0..body_len];
2010 extra_index += section_body.len;
2011 } else if (extra.data.bits.has_section_ref) {
2012 section_ref = @intToEnum(Zir.Inst.Ref, self.code.extra[extra_index]);
2013 extra_index += 1;
2014 }
2015 if (extra.data.bits.has_cc_body) {
2016 const body_len = self.code.extra[extra_index];
2017 extra_index += 1;
2018 cc_body = self.code.extra[extra_index..][0..body_len];
2019 extra_index += cc_body.len;
2020 } else if (extra.data.bits.has_cc_ref) {
2021 cc_ref = @intToEnum(Zir.Inst.Ref, self.code.extra[extra_index]);
2022 extra_index += 1;
2023 }
2024 if (extra.data.bits.has_ret_ty_body) {
2025 const body_len = self.code.extra[extra_index];
2026 extra_index += 1;
2027 ret_ty_body = self.code.extra[extra_index..][0..body_len];
2028 extra_index += ret_ty_body.len;
2029 } else if (extra.data.bits.has_ret_ty_ref) {
2030 ret_ty_ref = @intToEnum(Zir.Inst.Ref, self.code.extra[extra_index]);
2031 extra_index += 1;
2032 }
19662033
1967 const body = self.code.extra[extra_index..][0..extra.data.body_len];2034 const body = self.code.extra[extra_index..][0..extra.data.body_len];
1968 extra_index += body.len;2035 extra_index += body.len;
...@@ -1973,12 +2040,19 @@ const Writer = struct {...@@ -1973,12 +2040,19 @@ const Writer = struct {
1973 }2040 }
1974 return self.writeFuncCommon(2041 return self.writeFuncCommon(
1975 stream,2042 stream,
1976 ret_ty_body,
1977 extra.data.bits.is_inferred_error,2043 extra.data.bits.is_inferred_error,
1978 extra.data.bits.is_var_args,2044 extra.data.bits.is_var_args,
1979 extra.data.bits.is_extern,2045 extra.data.bits.is_extern,
1980 cc,2046 align_ref,
1981 align_inst,2047 align_body,
2048 addrspace_ref,
2049 addrspace_body,
2050 section_ref,
2051 section_body,
2052 cc_ref,
2053 cc_body,
2054 ret_ty_ref,
2055 ret_ty_body,
1982 body,2056 body,
1983 src,2057 src,
1984 src_locs,2058 src_locs,
...@@ -2122,30 +2196,33 @@ const Writer = struct {...@@ -2122,30 +2196,33 @@ const Writer = struct {
2122 fn writeFuncCommon(2196 fn writeFuncCommon(
2123 self: *Writer,2197 self: *Writer,
2124 stream: anytype,2198 stream: anytype,
2125 ret_ty_body: []const Zir.Inst.Index,
2126 inferred_error_set: bool,2199 inferred_error_set: bool,
2127 var_args: bool,2200 var_args: bool,
2128 is_extern: bool,2201 is_extern: bool,
2129 cc: Zir.Inst.Ref,2202 align_ref: Zir.Inst.Ref,
2130 align_inst: Zir.Inst.Ref,2203 align_body: []const Zir.Inst.Index,
2204 addrspace_ref: Zir.Inst.Ref,
2205 addrspace_body: []const Zir.Inst.Index,
2206 section_ref: Zir.Inst.Ref,
2207 section_body: []const Zir.Inst.Index,
2208 cc_ref: Zir.Inst.Ref,
2209 cc_body: []const Zir.Inst.Index,
2210 ret_ty_ref: Zir.Inst.Ref,
2211 ret_ty_body: []const Zir.Inst.Index,
2131 body: []const Zir.Inst.Index,2212 body: []const Zir.Inst.Index,
2132 src: LazySrcLoc,2213 src: LazySrcLoc,
2133 src_locs: Zir.Inst.Func.SrcLocs,2214 src_locs: Zir.Inst.Func.SrcLocs,
2134 ) !void {2215 ) !void {
2135 if (ret_ty_body.len == 0) {2216 try self.writeOptionalInstRefOrBody(stream, "align=", align_ref, align_body);
2136 try stream.writeAll("ret_ty=void");2217 try self.writeOptionalInstRefOrBody(stream, "addrspace=", addrspace_ref, addrspace_body);
2137 } else {2218 try self.writeOptionalInstRefOrBody(stream, "section=", section_ref, section_body);
2138 try stream.writeAll("ret_ty=");2219 try self.writeOptionalInstRefOrBody(stream, "cc=", cc_ref, cc_body);
2139 try self.writeBracedBody(stream, ret_ty_body);2220 try self.writeOptionalInstRefOrBody(stream, "ret_ty=", ret_ty_ref, ret_ty_body);
2140 }2221 try self.writeFlag(stream, "vargs, ", var_args);
21412222 try self.writeFlag(stream, "extern, ", is_extern);
2142 try self.writeOptionalInstRef(stream, ", cc=", cc);2223 try self.writeFlag(stream, "inferror, ", inferred_error_set);
2143 try self.writeOptionalInstRef(stream, ", align=", align_inst);2224
2144 try self.writeFlag(stream, ", vargs", var_args);2225 try stream.writeAll("body=");
2145 try self.writeFlag(stream, ", extern", is_extern);
2146 try self.writeFlag(stream, ", inferror", inferred_error_set);
2147
2148 try stream.writeAll(", body=");
2149 try self.writeBracedBody(stream, body);2226 try self.writeBracedBody(stream, body);
2150 try stream.writeAll(") ");2227 try stream.writeAll(") ");
2151 if (body.len != 0) {2228 if (body.len != 0) {
...@@ -2195,6 +2272,24 @@ const Writer = struct {...@@ -2195,6 +2272,24 @@ const Writer = struct {
2195 try self.writeInstRef(stream, inst);2272 try self.writeInstRef(stream, inst);
2196 }2273 }
21972274
2275 fn writeOptionalInstRefOrBody(
2276 self: *Writer,
2277 stream: anytype,
2278 prefix: []const u8,
2279 ref: Zir.Inst.Ref,
2280 body: []const Zir.Inst.Index,
2281 ) !void {
2282 if (body.len != 0) {
2283 try stream.writeAll(prefix);
2284 try self.writeBracedBody(stream, body);
2285 try stream.writeAll(", ");
2286 } else if (ref != .none) {
2287 try stream.writeAll(prefix);
2288 try self.writeInstRef(stream, ref);
2289 try stream.writeAll(", ");
2290 }
2291 }
2292
2198 fn writeFlag(2293 fn writeFlag(
2199 self: *Writer,2294 self: *Writer,
2200 stream: anytype,2295 stream: anytype,