authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-05-30 21:18:10-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-05-30 21:18:10-04:00
logc3ef4ac15f4aa0a4bbf546fb46745d445b97d717
tree98158ea6835297c116bbaf2735d32e556e8741c2
parentc84f5a5f91d31b20b2e187d84fc8a80a190a1212
parentbd89a73d5289536948b052eb7f052d6de193441b
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #11752 from ziglang/zir-fancy-fns

stage2: add missing data to ZIR encoding of functions

7 files changed, 883 insertions(+), 264 deletions(-)

src/AstGen.zig+243-81
......@@ -73,7 +73,7 @@ fn setExtra(astgen: *AstGen, index: usize, extra: anytype) void {
7373 Zir.Inst.Call.Flags => @bitCast(u32, @field(extra, field.name)),
7474 Zir.Inst.BuiltinCall.Flags => @bitCast(u32, @field(extra, field.name)),
7575 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)),
7777 else => @compileError("bad field type"),
7878 };
7979 i += 1;
......@@ -1205,7 +1205,7 @@ fn fnProtoExpr(
12051205 break :is_var_args false;
12061206 };
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: {
12091209 break :inst try expr(&block_scope, scope, align_rl, fn_proto.ast.align_expr);
12101210 };
12111211
......@@ -1232,19 +1232,24 @@ fn fnProtoExpr(
12321232 if (is_inferred_error) {
12331233 return astgen.failTok(maybe_bang, "function prototype may not have inferred error set", .{});
12341234 }
1235 var ret_gz = block_scope.makeSubBlock(scope);
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);
1235 const ret_ty = try expr(&block_scope, scope, coerced_type_rl, fn_proto.ast.return_type);
12391236
12401237 const result = try block_scope.addFunc(.{
12411238 .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
12421251 .param_block = block_inst,
1243 .ret_gz = &ret_gz,
1244 .ret_br = ret_br,
12451252 .body_gz = null,
1246 .cc = cc,
1247 .align_inst = align_inst,
12481253 .lib_name = 0,
12491254 .is_var_args = is_var_args,
12501255 .is_inferred_error = false,
......@@ -2262,7 +2267,7 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: Ast.Node.Index) Inner
22622267 .field_val_named,
22632268 .func,
22642269 .func_inferred,
2265 .func_extended,
2270 .func_fancy,
22662271 .int,
22672272 .int_big,
22682273 .float,
......@@ -3373,9 +3378,8 @@ fn fnDecl(
33733378
33743379 const doc_comment_index = try astgen.docCommentAsString(fn_proto.firstToken());
33753380
3376 const has_section_or_addrspace = fn_proto.ast.section_expr != 0 or fn_proto.ast.addrspace_expr != 0;
3377 // Alignment is passed in the func instruction in this case.
3378 wip_members.nextDecl(is_pub, is_export, false, has_section_or_addrspace);
3381 // align, linksection, and addrspace is passed in the func instruction in this case.
3382 wip_members.nextDecl(is_pub, is_export, false, false);
33793383
33803384 var params_scope = &fn_gz.base;
33813385 const is_var_args = is_var_args: {
......@@ -3461,17 +3465,49 @@ fn fnDecl(
34613465 const maybe_bang = tree.firstToken(fn_proto.ast.return_type) - 1;
34623466 const is_inferred_error = token_tags[maybe_bang] == .bang;
34633467
3464 const align_inst: Zir.Inst.Ref = if (fn_proto.ast.align_expr == 0) .none else inst: {
3465 break :inst try expr(&decl_gz, params_scope, align_rl, fn_proto.ast.align_expr);
3468 // After creating the function ZIR instruction, it will need to update the break
3469 // instructions inside the expression blocks for align, addrspace, cc, and ret_ty
3470 // to use the function instruction as the "block" to break from.
3471
3472 var align_gz = decl_gz.makeSubBlock(params_scope);
3473 defer align_gz.unstack();
3474 const align_ref: Zir.Inst.Ref = if (fn_proto.ast.align_expr == 0) .none else inst: {
3475 const inst = try expr(&decl_gz, params_scope, coerced_align_rl, fn_proto.ast.align_expr);
3476 if (align_gz.instructionsSlice().len == 0) {
3477 // In this case we will send a len=0 body which can be encoded more efficiently.
3478 break :inst inst;
3479 }
3480 _ = try align_gz.addBreak(.break_inline, 0, inst);
3481 break :inst inst;
34663482 };
3467 const addrspace_inst: Zir.Inst.Ref = if (fn_proto.ast.addrspace_expr == 0) .none else inst: {
3468 break :inst try expr(&decl_gz, params_scope, .{ .ty = .address_space_type }, fn_proto.ast.addrspace_expr);
3483
3484 var addrspace_gz = decl_gz.makeSubBlock(params_scope);
3485 defer addrspace_gz.unstack();
3486 const addrspace_ref: Zir.Inst.Ref = if (fn_proto.ast.addrspace_expr == 0) .none else inst: {
3487 const inst = try expr(&decl_gz, params_scope, .{ .coerced_ty = .address_space_type }, fn_proto.ast.addrspace_expr);
3488 if (addrspace_gz.instructionsSlice().len == 0) {
3489 // In this case we will send a len=0 body which can be encoded more efficiently.
3490 break :inst inst;
3491 }
3492 _ = try addrspace_gz.addBreak(.break_inline, 0, inst);
3493 break :inst inst;
34693494 };
3470 const section_inst: Zir.Inst.Ref = if (fn_proto.ast.section_expr == 0) .none else inst: {
3471 break :inst try comptimeExpr(&decl_gz, params_scope, .{ .ty = .const_slice_u8_type }, fn_proto.ast.section_expr);
3495
3496 var section_gz = decl_gz.makeSubBlock(params_scope);
3497 defer section_gz.unstack();
3498 const section_ref: Zir.Inst.Ref = if (fn_proto.ast.section_expr == 0) .none else inst: {
3499 const inst = try expr(&decl_gz, params_scope, .{ .coerced_ty = .const_slice_u8_type }, fn_proto.ast.section_expr);
3500 if (section_gz.instructionsSlice().len == 0) {
3501 // In this case we will send a len=0 body which can be encoded more efficiently.
3502 break :inst inst;
3503 }
3504 _ = try section_gz.addBreak(.break_inline, 0, inst);
3505 break :inst inst;
34723506 };
34733507
3474 const cc: Zir.Inst.Ref = blk: {
3508 var cc_gz = decl_gz.makeSubBlock(params_scope);
3509 defer cc_gz.unstack();
3510 const cc_ref: Zir.Inst.Ref = blk: {
34753511 if (fn_proto.ast.callconv_expr != 0) {
34763512 if (has_inline_keyword) {
34773513 return astgen.failNode(
......@@ -3480,12 +3516,18 @@ fn fnDecl(
34803516 .{},
34813517 );
34823518 }
3483 break :blk try expr(
3519 const inst = try expr(
34843520 &decl_gz,
34853521 params_scope,
3486 .{ .ty = .calling_convention_type },
3522 .{ .coerced_ty = .calling_convention_type },
34873523 fn_proto.ast.callconv_expr,
34883524 );
3525 if (cc_gz.instructionsSlice().len == 0) {
3526 // In this case we will send a len=0 body which can be encoded more efficiently.
3527 break :blk inst;
3528 }
3529 _ = try cc_gz.addBreak(.break_inline, 0, inst);
3530 break :blk inst;
34893531 } else if (is_extern) {
34903532 // note: https://github.com/ziglang/zig/issues/5269
34913533 break :blk .calling_convention_c;
......@@ -3498,8 +3540,15 @@ fn fnDecl(
34983540
34993541 var ret_gz = decl_gz.makeSubBlock(params_scope);
35003542 defer ret_gz.unstack();
3501 const ret_ty = try expr(&ret_gz, params_scope, coerced_type_rl, fn_proto.ast.return_type);
3502 const ret_br = try ret_gz.addBreak(.break_inline, 0, ret_ty);
3543 const ret_ref: Zir.Inst.Ref = inst: {
3544 const inst = try expr(&ret_gz, params_scope, coerced_type_rl, fn_proto.ast.return_type);
3545 if (ret_gz.instructionsSlice().len == 0) {
3546 // In this case we will send a len=0 body which can be encoded more efficiently.
3547 break :inst inst;
3548 }
3549 _ = try ret_gz.addBreak(.break_inline, 0, inst);
3550 break :inst inst;
3551 };
35033552
35043553 const func_inst: Zir.Inst.Ref = if (body_node == 0) func: {
35053554 if (!is_extern) {
......@@ -3510,12 +3559,18 @@ fn fnDecl(
35103559 }
35113560 break :func try decl_gz.addFunc(.{
35123561 .src_node = decl_node,
3562 .cc_ref = cc_ref,
3563 .cc_gz = &cc_gz,
3564 .align_ref = align_ref,
3565 .align_gz = &align_gz,
3566 .ret_ref = ret_ref,
35133567 .ret_gz = &ret_gz,
3514 .ret_br = ret_br,
3568 .section_ref = section_ref,
3569 .section_gz = &section_gz,
3570 .addrspace_ref = addrspace_ref,
3571 .addrspace_gz = &addrspace_gz,
35153572 .param_block = block_inst,
35163573 .body_gz = null,
3517 .cc = cc,
3518 .align_inst = align_inst,
35193574 .lib_name = lib_name,
35203575 .is_var_args = is_var_args,
35213576 .is_inferred_error = false,
......@@ -3549,14 +3604,20 @@ fn fnDecl(
35493604
35503605 break :func try decl_gz.addFunc(.{
35513606 .src_node = decl_node,
3607 .cc_ref = cc_ref,
3608 .cc_gz = &cc_gz,
3609 .align_ref = align_ref,
3610 .align_gz = &align_gz,
3611 .ret_ref = ret_ref,
3612 .ret_gz = &ret_gz,
3613 .section_ref = section_ref,
3614 .section_gz = &section_gz,
3615 .addrspace_ref = addrspace_ref,
3616 .addrspace_gz = &addrspace_gz,
35523617 .lbrace_line = lbrace_line,
35533618 .lbrace_column = lbrace_column,
35543619 .param_block = block_inst,
3555 .ret_gz = &ret_gz,
3556 .ret_br = ret_br,
35573620 .body_gz = &fn_gz,
3558 .cc = cc,
3559 .align_inst = align_inst,
35603621 .lib_name = lib_name,
35613622 .is_var_args = is_var_args,
35623623 .is_inferred_error = is_inferred_error,
......@@ -3582,10 +3643,6 @@ fn fnDecl(
35823643 wip_members.appendToDecl(fn_name_str_index);
35833644 wip_members.appendToDecl(block_inst);
35843645 wip_members.appendToDecl(doc_comment_index);
3585 if (has_section_or_addrspace) {
3586 wip_members.appendToDecl(@enumToInt(section_inst));
3587 wip_members.appendToDecl(@enumToInt(addrspace_inst));
3588 }
35893646}
35903647
35913648fn globalVarDecl(
......@@ -3979,14 +4036,22 @@ fn testDecl(
39794036
39804037 const func_inst = try decl_block.addFunc(.{
39814038 .src_node = node,
4039
4040 .cc_ref = .none,
4041 .cc_gz = null,
4042 .align_ref = .none,
4043 .align_gz = null,
4044 .ret_ref = .void_type,
4045 .ret_gz = null,
4046 .section_ref = .none,
4047 .section_gz = null,
4048 .addrspace_ref = .none,
4049 .addrspace_gz = null,
4050
39824051 .lbrace_line = lbrace_line,
39834052 .lbrace_column = lbrace_column,
39844053 .param_block = block_inst,
3985 .ret_gz = null,
3986 .ret_br = 0,
39874054 .body_gz = &fn_block,
3988 .cc = .none,
3989 .align_inst = .none,
39904055 .lib_name = 0,
39914056 .is_var_args = false,
39924057 .is_inferred_error = true,
......@@ -9930,17 +9995,34 @@ const GenZir = struct {
99309995 gz.unstack();
99319996 }
99329997
9933 /// Supports `body_gz` stacked on `ret_gz` stacked on `gz`. Unstacks `body_gz` and `ret_gz`.
9998 /// Must be called with the following stack set up:
9999 /// * gz (bottom)
10000 /// * align_gz
10001 /// * addrspace_gz
10002 /// * section_gz
10003 /// * cc_gz
10004 /// * ret_gz
10005 /// * body_gz (top)
10006 /// Unstacks all of those except for `gz`.
993410007 fn addFunc(gz: *GenZir, args: struct {
993510008 src_node: Ast.Node.Index,
993610009 lbrace_line: u32 = 0,
993710010 lbrace_column: u32 = 0,
9938 body_gz: ?*GenZir,
993910011 param_block: Zir.Inst.Index,
10012
10013 align_gz: ?*GenZir,
10014 addrspace_gz: ?*GenZir,
10015 section_gz: ?*GenZir,
10016 cc_gz: ?*GenZir,
994010017 ret_gz: ?*GenZir,
9941 ret_br: Zir.Inst.Index,
9942 cc: Zir.Inst.Ref,
9943 align_inst: Zir.Inst.Ref,
10018 body_gz: ?*GenZir,
10019
10020 align_ref: Zir.Inst.Ref,
10021 addrspace_ref: Zir.Inst.Ref,
10022 section_ref: Zir.Inst.Ref,
10023 cc_ref: Zir.Inst.Ref,
10024 ret_ref: Zir.Inst.Ref,
10025
994410026 lib_name: u32,
994510027 is_var_args: bool,
994610028 is_inferred_error: bool,
......@@ -9950,11 +10032,13 @@ const GenZir = struct {
995010032 assert(args.src_node != 0);
995110033 const astgen = gz.astgen;
995210034 const gpa = astgen.gpa;
10035 const ret_ref = if (args.ret_ref == .void_type) .none else args.ret_ref;
10036 const new_index = @intCast(Zir.Inst.Index, astgen.instructions.len);
995310037
995410038 try astgen.instructions.ensureUnusedCapacity(gpa, 1);
995510039
995610040 var body: []Zir.Inst.Index = &[0]Zir.Inst.Index{};
9957 var ret_ty: []Zir.Inst.Index = &[0]Zir.Inst.Index{};
10041 var ret_body: []Zir.Inst.Index = &[0]Zir.Inst.Index{};
995810042 var src_locs_buffer: [3]u32 = undefined;
995910043 var src_locs: []u32 = src_locs_buffer[0..0];
996010044 if (args.body_gz) |body_gz| {
......@@ -9978,61 +10062,120 @@ const GenZir = struct {
997810062
997910063 body = body_gz.instructionsSlice();
998010064 if (args.ret_gz) |ret_gz|
9981 ret_ty = ret_gz.instructionsSliceUpto(body_gz);
10065 ret_body = ret_gz.instructionsSliceUpto(body_gz);
998210066 } else {
998310067 if (args.ret_gz) |ret_gz|
9984 ret_ty = ret_gz.instructionsSlice();
10068 ret_body = ret_gz.instructionsSlice();
998510069 }
998610070
9987 if (args.cc != .none or args.lib_name != 0 or
9988 args.is_var_args or args.is_test or args.align_inst != .none or
9989 args.is_extern)
10071 if (args.cc_ref != .none or args.lib_name != 0 or
10072 args.is_var_args or args.is_test or args.is_extern or
10073 args.align_ref != .none or args.section_ref != .none or
10074 args.addrspace_ref != .none)
999010075 {
10076 var align_body: []Zir.Inst.Index = &.{};
10077 var addrspace_body: []Zir.Inst.Index = &.{};
10078 var section_body: []Zir.Inst.Index = &.{};
10079 var cc_body: []Zir.Inst.Index = &.{};
10080 if (args.ret_gz != null) {
10081 align_body = args.align_gz.?.instructionsSliceUpto(args.addrspace_gz.?);
10082 addrspace_body = args.addrspace_gz.?.instructionsSliceUpto(args.section_gz.?);
10083 section_body = args.section_gz.?.instructionsSliceUpto(args.cc_gz.?);
10084 cc_body = args.cc_gz.?.instructionsSliceUpto(args.ret_gz.?);
10085 }
10086
999110087 try astgen.extra.ensureUnusedCapacity(
999210088 gpa,
9993 @typeInfo(Zir.Inst.ExtendedFunc).Struct.fields.len +
9994 ret_ty.len + body.len + src_locs.len +
9995 @boolToInt(args.lib_name != 0) +
9996 @boolToInt(args.align_inst != .none) +
9997 @boolToInt(args.cc != .none),
10089 @typeInfo(Zir.Inst.FuncFancy).Struct.fields.len +
10090 fancyFnExprExtraLen(align_body, args.align_ref) +
10091 fancyFnExprExtraLen(addrspace_body, args.addrspace_ref) +
10092 fancyFnExprExtraLen(section_body, args.section_ref) +
10093 fancyFnExprExtraLen(cc_body, args.cc_ref) +
10094 fancyFnExprExtraLen(ret_body, ret_ref) +
10095 body.len + src_locs.len +
10096 @boolToInt(args.lib_name != 0),
999810097 );
9999 const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.ExtendedFunc{
10098 const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.FuncFancy{
1000010099 .param_block = args.param_block,
10001 .ret_body_len = @intCast(u32, ret_ty.len),
1000210100 .body_len = @intCast(u32, body.len),
1000310101 .bits = .{
1000410102 .is_var_args = args.is_var_args,
1000510103 .is_inferred_error = args.is_inferred_error,
10006 .has_lib_name = args.lib_name != 0,
10007 .has_cc = args.cc != .none,
10008 .has_align = args.align_inst != .none,
1000910104 .is_test = args.is_test,
1001010105 .is_extern = args.is_extern,
10106 .has_lib_name = args.lib_name != 0,
10107
10108 .has_align_ref = args.align_ref != .none,
10109 .has_addrspace_ref = args.addrspace_ref != .none,
10110 .has_section_ref = args.section_ref != .none,
10111 .has_cc_ref = args.cc_ref != .none,
10112 .has_ret_ty_ref = ret_ref != .none,
10113
10114 .has_align_body = align_body.len != 0,
10115 .has_addrspace_body = addrspace_body.len != 0,
10116 .has_section_body = section_body.len != 0,
10117 .has_cc_body = cc_body.len != 0,
10118 .has_ret_ty_body = ret_body.len != 0,
1001110119 },
1001210120 });
1001310121 if (args.lib_name != 0) {
1001410122 astgen.extra.appendAssumeCapacity(args.lib_name);
1001510123 }
10016 if (args.cc != .none) {
10017 astgen.extra.appendAssumeCapacity(@enumToInt(args.cc));
10124
10125 const zir_datas = astgen.instructions.items(.data);
10126 if (align_body.len != 0) {
10127 astgen.extra.appendAssumeCapacity(@intCast(u32, align_body.len));
10128 astgen.extra.appendSliceAssumeCapacity(align_body);
10129 zir_datas[align_body[align_body.len - 1]].@"break".block_inst = new_index;
10130 } else if (args.align_ref != .none) {
10131 astgen.extra.appendAssumeCapacity(@enumToInt(args.align_ref));
10132 }
10133 if (addrspace_body.len != 0) {
10134 astgen.extra.appendAssumeCapacity(@intCast(u32, addrspace_body.len));
10135 astgen.extra.appendSliceAssumeCapacity(addrspace_body);
10136 zir_datas[addrspace_body[addrspace_body.len - 1]].@"break".block_inst = new_index;
10137 } else if (args.addrspace_ref != .none) {
10138 astgen.extra.appendAssumeCapacity(@enumToInt(args.addrspace_ref));
1001810139 }
10019 if (args.align_inst != .none) {
10020 astgen.extra.appendAssumeCapacity(@enumToInt(args.align_inst));
10140 if (section_body.len != 0) {
10141 astgen.extra.appendAssumeCapacity(@intCast(u32, section_body.len));
10142 astgen.extra.appendSliceAssumeCapacity(section_body);
10143 zir_datas[section_body[section_body.len - 1]].@"break".block_inst = new_index;
10144 } else if (args.section_ref != .none) {
10145 astgen.extra.appendAssumeCapacity(@enumToInt(args.section_ref));
1002110146 }
10022 astgen.extra.appendSliceAssumeCapacity(ret_ty);
10147 if (cc_body.len != 0) {
10148 astgen.extra.appendAssumeCapacity(@intCast(u32, cc_body.len));
10149 astgen.extra.appendSliceAssumeCapacity(cc_body);
10150 zir_datas[cc_body[cc_body.len - 1]].@"break".block_inst = new_index;
10151 } else if (args.cc_ref != .none) {
10152 astgen.extra.appendAssumeCapacity(@enumToInt(args.cc_ref));
10153 }
10154 if (ret_body.len != 0) {
10155 astgen.extra.appendAssumeCapacity(@intCast(u32, ret_body.len));
10156 astgen.extra.appendSliceAssumeCapacity(ret_body);
10157 zir_datas[ret_body[ret_body.len - 1]].@"break".block_inst = new_index;
10158 } else if (ret_ref != .none) {
10159 astgen.extra.appendAssumeCapacity(@enumToInt(ret_ref));
10160 }
10161
1002310162 astgen.extra.appendSliceAssumeCapacity(body);
1002410163 astgen.extra.appendSliceAssumeCapacity(src_locs);
10025 // order is important when unstacking
10164
10165 // Order is important when unstacking.
1002610166 if (args.body_gz) |body_gz| body_gz.unstack();
10027 if (args.ret_gz) |ret_gz| ret_gz.unstack();
10167 if (args.ret_gz != null) {
10168 args.ret_gz.?.unstack();
10169 args.cc_gz.?.unstack();
10170 args.section_gz.?.unstack();
10171 args.addrspace_gz.?.unstack();
10172 args.align_gz.?.unstack();
10173 }
10174
1002810175 try gz.instructions.ensureUnusedCapacity(gpa, 1);
1002910176
10030 const new_index = @intCast(Zir.Inst.Index, astgen.instructions.len);
10031 if (args.ret_br != 0) {
10032 astgen.instructions.items(.data)[args.ret_br].@"break".block_inst = new_index;
10033 }
1003410177 astgen.instructions.appendAssumeCapacity(.{
10035 .tag = .func_extended,
10178 .tag = .func_fancy,
1003610179 .data = .{ .pl_node = .{
1003710180 .src_node = gz.nodeIndexToRelative(args.src_node),
1003810181 .payload_index = payload_index,
......@@ -10044,27 +10187,40 @@ const GenZir = struct {
1004410187 try astgen.extra.ensureUnusedCapacity(
1004510188 gpa,
1004610189 @typeInfo(Zir.Inst.Func).Struct.fields.len +
10047 ret_ty.len + body.len + src_locs.len,
10190 @maximum(ret_body.len, @boolToInt(ret_ref != .none)) +
10191 body.len + src_locs.len,
1004810192 );
10193 const ret_body_len = if (ret_body.len != 0)
10194 @intCast(u32, ret_body.len)
10195 else
10196 @boolToInt(ret_ref != .none);
1004910197
1005010198 const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.Func{
1005110199 .param_block = args.param_block,
10052 .ret_body_len = @intCast(u32, ret_ty.len),
10200 .ret_body_len = ret_body_len,
1005310201 .body_len = @intCast(u32, body.len),
1005410202 });
10055 astgen.extra.appendSliceAssumeCapacity(ret_ty);
10203 const zir_datas = astgen.instructions.items(.data);
10204 if (ret_body.len != 0) {
10205 astgen.extra.appendSliceAssumeCapacity(ret_body);
10206 zir_datas[ret_body[ret_body.len - 1]].@"break".block_inst = new_index;
10207 } else if (ret_ref != .none) {
10208 astgen.extra.appendAssumeCapacity(@enumToInt(ret_ref));
10209 }
1005610210 astgen.extra.appendSliceAssumeCapacity(body);
1005710211 astgen.extra.appendSliceAssumeCapacity(src_locs);
10058 // order is important when unstacking
10212
10213 // Order is important when unstacking.
1005910214 if (args.body_gz) |body_gz| body_gz.unstack();
1006010215 if (args.ret_gz) |ret_gz| ret_gz.unstack();
10216 if (args.cc_gz) |cc_gz| cc_gz.unstack();
10217 if (args.section_gz) |section_gz| section_gz.unstack();
10218 if (args.addrspace_gz) |addrspace_gz| addrspace_gz.unstack();
10219 if (args.align_gz) |align_gz| align_gz.unstack();
10220
1006110221 try gz.instructions.ensureUnusedCapacity(gpa, 1);
1006210222
1006310223 const tag: Zir.Inst.Tag = if (args.is_inferred_error) .func_inferred else .func;
10064 const new_index = @intCast(Zir.Inst.Index, astgen.instructions.len);
10065 if (args.ret_br != 0) {
10066 astgen.instructions.items(.data)[args.ret_br].@"break".block_inst = new_index;
10067 }
1006810224 astgen.instructions.appendAssumeCapacity(.{
1006910225 .tag = tag,
1007010226 .data = .{ .pl_node = .{
......@@ -10077,6 +10233,12 @@ const GenZir = struct {
1007710233 }
1007810234 }
1007910235
10236 fn fancyFnExprExtraLen(body: []Zir.Inst.Index, ref: Zir.Inst.Ref) usize {
10237 // In the case of non-empty body, there is one for the body length,
10238 // and then one for each instruction.
10239 return body.len + @boolToInt(ref != .none);
10240 }
10241
1008010242 fn addVar(gz: *GenZir, args: struct {
1008110243 align_inst: Zir.Inst.Ref,
1008210244 lib_name: u32,
src/Module.zig+2-2
......@@ -1595,9 +1595,9 @@ pub const Fn = struct {
15951595 switch (zir_tags[func.zir_body_inst]) {
15961596 .func => return false,
15971597 .func_inferred => return true,
1598 .func_extended => {
1598 .func_fancy => {
15991599 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);
16011601 return extra.data.bits.is_inferred_error;
16021602 },
16031603 else => unreachable,
src/Sema.zig+262-79
......@@ -747,7 +747,7 @@ fn analyzeBodyInner(
747747 .field_call_bind => try sema.zirFieldCallBind(block, inst),
748748 .func => try sema.zirFunc(block, inst, false),
749749 .func_inferred => try sema.zirFunc(block, inst, true),
750 .func_extended => try sema.zirFuncExtended(block, inst),
750 .func_fancy => try sema.zirFuncFancy(block, inst),
751751 .import => try sema.zirImport(block, inst),
752752 .indexable_ptr_len => try sema.zirIndexablePtrLen(block, inst),
753753 .int => try sema.zirInt(block, inst),
......@@ -5190,7 +5190,10 @@ fn analyzeCall(
51905190 // on parameters, we must now do the same for the return type as we just did with
51915191 // each of the parameters, resolving the return type and providing it to the child
51925192 // `Sema` so that it can be used for the `ret_ptr` instruction.
5193 const ret_ty_inst = try sema.resolveBody(&child_block, fn_info.ret_ty_body, module_fn.zir_body_inst);
5193 const ret_ty_inst = if (fn_info.ret_ty_body.len != 0)
5194 try sema.resolveBody(&child_block, fn_info.ret_ty_body, module_fn.zir_body_inst)
5195 else
5196 try sema.resolveInst(fn_info.ret_ty_ref);
51945197 const ret_ty_src = func_src; // TODO better source location
51955198 const bare_return_type = try sema.analyzeAsType(&child_block, ret_ty_src, ret_ty_inst);
51965199 // Create a fresh inferred error set type for inline/comptime calls.
......@@ -6506,9 +6509,34 @@ fn zirFunc(
65066509
65076510 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
65086511 const extra = sema.code.extraData(Zir.Inst.Func, inst_data.payload_index);
6512 const target = sema.mod.getTarget();
6513 const ret_ty_src = inst_data.src(); // TODO better source location
6514
65096515 var extra_index = extra.end;
6510 const ret_ty_body = sema.code.extra[extra_index..][0..extra.data.ret_body_len];
6511 extra_index += ret_ty_body.len;
6516
6517 const ret_ty: Type = switch (extra.data.ret_body_len) {
6518 0 => Type.void,
6519 1 => blk: {
6520 const ret_ty_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);
6521 extra_index += 1;
6522 if (sema.resolveType(block, ret_ty_src, ret_ty_ref)) |ret_ty| {
6523 break :blk ret_ty;
6524 } else |err| switch (err) {
6525 error.GenericPoison => {
6526 break :blk Type.initTag(.generic_poison);
6527 },
6528 else => |e| return e,
6529 }
6530 },
6531 else => blk: {
6532 const ret_ty_body = sema.code.extra[extra_index..][0..extra.data.ret_body_len];
6533 extra_index += ret_ty_body.len;
6534
6535 const ret_ty_val = try sema.resolveGenericBody(block, ret_ty_src, ret_ty_body, inst, Type.type);
6536 var buffer: Value.ToTypeBuffer = undefined;
6537 break :blk try ret_ty_val.toType(&buffer).copy(sema.arena);
6538 },
6539 };
65126540
65136541 var src_locs: Zir.Inst.Func.SrcLocs = undefined;
65146542 const has_body = extra.data.body_len != 0;
......@@ -6526,9 +6554,11 @@ fn zirFunc(
65266554 block,
65276555 inst_data.src_node,
65286556 inst,
6529 ret_ty_body,
6557 0,
6558 target_util.defaultAddressSpace(target, .function),
6559 FuncLinkSection.default,
65306560 cc,
6531 Value.@"null",
6561 ret_ty,
65326562 false,
65336563 inferred_error_set,
65346564 false,
......@@ -6538,6 +6568,44 @@ fn zirFunc(
65386568 );
65396569}
65406570
6571// TODO this function and its callsites along with funcCommon need to be reworked
6572// to handle when callconv, align, linksection, addrspace depend on comptime values
6573// (thus triggering error.GenericPoison)
6574fn resolveGenericBody(
6575 sema: *Sema,
6576 block: *Block,
6577 src: LazySrcLoc,
6578 body: []const Zir.Inst.Index,
6579 func_inst: Zir.Inst.Index,
6580 dest_ty: Type,
6581) !Value {
6582 assert(body.len != 0);
6583
6584 const err = err: {
6585 // Make sure any nested param instructions don't clobber our work.
6586 const prev_params = block.params;
6587 block.params = .{};
6588 defer {
6589 block.params.deinit(sema.gpa);
6590 block.params = prev_params;
6591 }
6592 const uncasted = sema.resolveBody(block, body, func_inst) catch |err| break :err err;
6593 const result = sema.coerce(block, dest_ty, uncasted, src) catch |err| break :err err;
6594 const val = sema.resolveConstValue(block, src, result) catch |err| break :err err;
6595 return val;
6596 };
6597 switch (err) {
6598 error.GenericPoison => {
6599 if (dest_ty.tag() == .type) {
6600 return Value.initTag(.generic_poison_type);
6601 } else {
6602 return Value.initTag(.generic_poison);
6603 }
6604 },
6605 else => |e| return e,
6606 }
6607}
6608
65416609/// Given a library name, examines if the library name should end up in
65426610/// `link.File.Options.system_libs` table (for example, libc is always
65436611/// specified via dedicated flag `link.File.Options.link_libc` instead),
......@@ -6601,14 +6669,27 @@ fn handleExternLibName(
66016669 return sema.gpa.dupeZ(u8, lib_name);
66026670}
66036671
6672const FuncLinkSection = union(enum) {
6673 generic,
6674 default,
6675 explicit: [*:0]const u8,
6676};
6677
66046678fn funcCommon(
66056679 sema: *Sema,
66066680 block: *Block,
66076681 src_node_offset: i32,
66086682 func_inst: Zir.Inst.Index,
6609 ret_ty_body: []const Zir.Inst.Index,
6610 cc: std.builtin.CallingConvention,
6611 align_val: Value,
6683 /// null means generic poison
6684 alignment: ?u32,
6685 /// null means generic poison
6686 address_space: ?std.builtin.AddressSpace,
6687 /// outer null means generic poison; inner null means default link section
6688 section: FuncLinkSection,
6689 /// null means generic poison
6690 cc: ?std.builtin.CallingConvention,
6691 /// this might be Type.generic_poison
6692 bare_return_type: Type,
66126693 var_args: bool,
66136694 inferred_error_set: bool,
66146695 is_extern: bool,
......@@ -6618,42 +6699,15 @@ fn funcCommon(
66186699) CompileError!Air.Inst.Ref {
66196700 const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = src_node_offset };
66206701
6621 // The return type body might be a type expression that depends on generic parameters.
6622 // In such case we need to use a generic_poison value for the return type and mark
6623 // the function as generic.
6624 var is_generic = false;
6625 const bare_return_type: Type = ret_ty: {
6626 if (ret_ty_body.len == 0) break :ret_ty Type.void;
6627
6628 const err = err: {
6629 // Make sure any nested param instructions don't clobber our work.
6630 const prev_params = block.params;
6631 block.params = .{};
6632 defer {
6633 block.params.deinit(sema.gpa);
6634 block.params = prev_params;
6635 }
6636 if (sema.resolveBody(block, ret_ty_body, func_inst)) |ret_ty_inst| {
6637 if (sema.analyzeAsType(block, ret_ty_src, ret_ty_inst)) |ret_ty| {
6638 break :ret_ty ret_ty;
6639 } else |err| break :err err;
6640 } else |err| break :err err;
6641 // Check for generic params.
6642 for (block.params.items) |param| {
6643 if (param.ty.tag() == .generic_poison) is_generic = true;
6644 }
6645 };
6646 switch (err) {
6647 error.GenericPoison => {
6648 // The type is not available until the generic instantiation.
6649 is_generic = true;
6650 break :ret_ty Type.initTag(.generic_poison);
6651 },
6652 else => |e| return e,
6653 }
6654 };
6655
6656 const mod = sema.mod;
6702 var is_generic = bare_return_type.tag() == .generic_poison or
6703 alignment == null or
6704 address_space == null or
6705 section == .generic or
6706 cc == null;
6707 // Check for generic params.
6708 for (block.params.items) |param| {
6709 if (param.ty.tag() == .generic_poison) is_generic = true;
6710 }
66576711
66586712 const new_func: *Module.Fn = new_func: {
66596713 if (!has_body) break :new_func undefined;
......@@ -6670,36 +6724,28 @@ fn funcCommon(
66706724 errdefer if (maybe_inferred_error_set_node) |node| sema.gpa.destroy(node);
66716725 // Note: no need to errdefer since this will still be in its default state at the end of the function.
66726726
6673 const target = mod.getTarget();
6674
6727 const target = sema.mod.getTarget();
66756728 const fn_ty: Type = fn_ty: {
6676 const alignment: u32 = if (align_val.tag() == .null_value) 0 else a: {
6677 const alignment = @intCast(u32, align_val.toUnsignedInt(target));
6678 if (alignment == target_util.defaultFunctionAlignment(target)) {
6679 break :a 0;
6680 } else {
6681 break :a alignment;
6682 }
6683 };
6684
66856729 // Hot path for some common function types.
66866730 // TODO can we eliminate some of these Type tag values? seems unnecessarily complicated.
6687 if (!is_generic and block.params.items.len == 0 and !var_args and
6688 alignment == 0 and !inferred_error_set)
6731 if (!is_generic and block.params.items.len == 0 and !var_args and !inferred_error_set and
6732 alignment.? == 0 and
6733 address_space.? == target_util.defaultAddressSpace(target, .function) and
6734 section == .default)
66896735 {
6690 if (bare_return_type.zigTypeTag() == .NoReturn and cc == .Unspecified) {
6736 if (bare_return_type.zigTypeTag() == .NoReturn and cc.? == .Unspecified) {
66916737 break :fn_ty Type.initTag(.fn_noreturn_no_args);
66926738 }
66936739
6694 if (bare_return_type.zigTypeTag() == .Void and cc == .Unspecified) {
6740 if (bare_return_type.zigTypeTag() == .Void and cc.? == .Unspecified) {
66956741 break :fn_ty Type.initTag(.fn_void_no_args);
66966742 }
66976743
6698 if (bare_return_type.zigTypeTag() == .NoReturn and cc == .Naked) {
6744 if (bare_return_type.zigTypeTag() == .NoReturn and cc.? == .Naked) {
66996745 break :fn_ty Type.initTag(.fn_naked_noreturn_no_args);
67006746 }
67016747
6702 if (bare_return_type.zigTypeTag() == .Void and cc == .C) {
6748 if (bare_return_type.zigTypeTag() == .Void and cc.? == .C) {
67036749 break :fn_ty Type.initTag(.fn_ccc_void_no_args);
67046750 }
67056751 }
......@@ -6745,17 +6791,35 @@ fn funcCommon(
67456791 });
67466792 };
67476793
6794 // stage1 bug workaround
6795 const cc_workaround = cc orelse undefined;
6796 const align_workaround = alignment orelse @as(u32, undefined);
6797
67486798 break :fn_ty try Type.Tag.function.create(sema.arena, .{
67496799 .param_types = param_types,
67506800 .comptime_params = comptime_params.ptr,
67516801 .return_type = return_type,
6752 .cc = cc,
6753 .alignment = alignment,
6802 .cc = cc_workaround,
6803 .cc_is_generic = cc == null,
6804 .alignment = align_workaround,
6805 .align_is_generic = alignment == null,
6806 .section_is_generic = section == .generic,
6807 .addrspace_is_generic = address_space == null,
67546808 .is_var_args = var_args,
67556809 .is_generic = is_generic,
67566810 });
67576811 };
67586812
6813 if (sema.owner_decl.owns_tv) {
6814 switch (section) {
6815 .generic => sema.owner_decl.@"linksection" = undefined,
6816 .default => sema.owner_decl.@"linksection" = null,
6817 .explicit => |s| sema.owner_decl.@"linksection" = s,
6818 }
6819 if (alignment) |a| sema.owner_decl.@"align" = a;
6820 if (address_space) |a| sema.owner_decl.@"addrspace" = a;
6821 }
6822
67596823 if (is_extern) {
67606824 const new_extern_fn = try sema.gpa.create(Module.ExternFn);
67616825 errdefer sema.gpa.destroy(new_extern_fn);
......@@ -16750,16 +16814,20 @@ fn zirVarExtended(
1675016814 return result;
1675116815}
1675216816
16753fn zirFuncExtended(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
16817fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
1675416818 const tracy = trace(@src());
1675516819 defer tracy.end();
1675616820
1675716821 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
1675816822 const src = inst_data.src();
16759 const extra = sema.code.extraData(Zir.Inst.ExtendedFunc, inst_data.payload_index);
16823 const extra = sema.code.extraData(Zir.Inst.FuncFancy, inst_data.payload_index);
16824 const target = sema.mod.getTarget();
1676016825
16761 const cc_src: LazySrcLoc = .{ .node_offset_fn_type_cc = inst_data.src_node };
1676216826 const align_src: LazySrcLoc = src; // TODO add a LazySrcLoc that points at align
16827 const addrspace_src: LazySrcLoc = src; // TODO add a LazySrcLoc that points at addrspace
16828 const section_src: LazySrcLoc = src; // TODO add a LazySrcLoc that points at section
16829 const cc_src: LazySrcLoc = .{ .node_offset_fn_type_cc = inst_data.src_node };
16830 const ret_src: LazySrcLoc = src; // TODO add a LazySrcLoc that points at the return type
1676316831
1676416832 var extra_index: usize = extra.end;
1676516833
......@@ -16769,22 +16837,135 @@ fn zirFuncExtended(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro
1676916837 break :blk lib_name;
1677016838 } else null;
1677116839
16772 const cc: std.builtin.CallingConvention = if (extra.data.bits.has_cc) blk: {
16840 const @"align": ?u32 = if (extra.data.bits.has_align_body) blk: {
16841 const body_len = sema.code.extra[extra_index];
16842 extra_index += 1;
16843 const body = sema.code.extra[extra_index..][0..body_len];
16844 extra_index += body.len;
16845
16846 const val = try sema.resolveGenericBody(block, align_src, body, inst, Type.u16);
16847 if (val.tag() == .generic_poison) {
16848 break :blk null;
16849 }
16850 const alignment = @intCast(u32, val.toUnsignedInt(target));
16851 if (alignment == target_util.defaultFunctionAlignment(target)) {
16852 break :blk 0;
16853 } else {
16854 break :blk alignment;
16855 }
16856 } else if (extra.data.bits.has_align_ref) blk: {
16857 const align_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);
16858 extra_index += 1;
16859 const align_tv = sema.resolveInstConst(block, align_src, align_ref) catch |err| switch (err) {
16860 error.GenericPoison => {
16861 break :blk null;
16862 },
16863 else => |e| return e,
16864 };
16865 const alignment = @intCast(u32, align_tv.val.toUnsignedInt(target));
16866 if (alignment == target_util.defaultFunctionAlignment(target)) {
16867 break :blk 0;
16868 } else {
16869 break :blk alignment;
16870 }
16871 } else 0;
16872
16873 const @"addrspace": ?std.builtin.AddressSpace = if (extra.data.bits.has_addrspace_body) blk: {
16874 const body_len = sema.code.extra[extra_index];
16875 extra_index += 1;
16876 const body = sema.code.extra[extra_index..][0..body_len];
16877 extra_index += body.len;
16878
16879 const addrspace_ty = try sema.getBuiltinType(block, addrspace_src, "AddressSpace");
16880 const val = try sema.resolveGenericBody(block, addrspace_src, body, inst, addrspace_ty);
16881 if (val.tag() == .generic_poison) {
16882 break :blk null;
16883 }
16884 break :blk val.toEnum(std.builtin.AddressSpace);
16885 } else if (extra.data.bits.has_addrspace_ref) blk: {
16886 const addrspace_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);
16887 extra_index += 1;
16888 const addrspace_tv = sema.resolveInstConst(block, addrspace_src, addrspace_ref) catch |err| switch (err) {
16889 error.GenericPoison => {
16890 break :blk null;
16891 },
16892 else => |e| return e,
16893 };
16894 break :blk addrspace_tv.val.toEnum(std.builtin.AddressSpace);
16895 } else target_util.defaultAddressSpace(target, .function);
16896
16897 const @"linksection": FuncLinkSection = if (extra.data.bits.has_section_body) blk: {
16898 const body_len = sema.code.extra[extra_index];
16899 extra_index += 1;
16900 const body = sema.code.extra[extra_index..][0..body_len];
16901 extra_index += body.len;
16902
16903 const val = try sema.resolveGenericBody(block, section_src, body, inst, Type.initTag(.const_slice_u8));
16904 if (val.tag() == .generic_poison) {
16905 break :blk FuncLinkSection{ .generic = {} };
16906 }
16907 _ = val;
16908 return sema.fail(block, section_src, "TODO implement linksection on functions", .{});
16909 } else if (extra.data.bits.has_section_ref) blk: {
16910 const section_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);
16911 extra_index += 1;
16912 const section_tv = sema.resolveInstConst(block, section_src, section_ref) catch |err| switch (err) {
16913 error.GenericPoison => {
16914 break :blk FuncLinkSection{ .generic = {} };
16915 },
16916 else => |e| return e,
16917 };
16918 _ = section_tv;
16919 return sema.fail(block, section_src, "TODO implement linksection on functions", .{});
16920 } else FuncLinkSection{ .default = {} };
16921
16922 const cc: ?std.builtin.CallingConvention = if (extra.data.bits.has_cc_body) blk: {
16923 const body_len = sema.code.extra[extra_index];
16924 extra_index += 1;
16925 const body = sema.code.extra[extra_index..][0..body_len];
16926 extra_index += body.len;
16927
16928 const cc_ty = try sema.getBuiltinType(block, addrspace_src, "CallingConvention");
16929 const val = try sema.resolveGenericBody(block, cc_src, body, inst, cc_ty);
16930 if (val.tag() == .generic_poison) {
16931 break :blk null;
16932 }
16933 break :blk val.toEnum(std.builtin.CallingConvention);
16934 } else if (extra.data.bits.has_cc_ref) blk: {
1677316935 const cc_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);
1677416936 extra_index += 1;
16775 const cc_tv = try sema.resolveInstConst(block, cc_src, cc_ref);
16937 const cc_tv = sema.resolveInstConst(block, cc_src, cc_ref) catch |err| switch (err) {
16938 error.GenericPoison => {
16939 break :blk null;
16940 },
16941 else => |e| return e,
16942 };
1677616943 break :blk cc_tv.val.toEnum(std.builtin.CallingConvention);
16777 } else .Unspecified;
16944 } else std.builtin.CallingConvention.Unspecified;
1677816945
16779 const align_val: Value = if (extra.data.bits.has_align) blk: {
16780 const align_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);
16946 const ret_ty: Type = if (extra.data.bits.has_ret_ty_body) blk: {
16947 const body_len = sema.code.extra[extra_index];
1678116948 extra_index += 1;
16782 const align_tv = try sema.resolveInstConst(block, align_src, align_ref);
16783 break :blk align_tv.val;
16784 } else Value.@"null";
16949 const body = sema.code.extra[extra_index..][0..body_len];
16950 extra_index += body.len;
1678516951
16786 const ret_ty_body = sema.code.extra[extra_index..][0..extra.data.ret_body_len];
16787 extra_index += ret_ty_body.len;
16952 const val = try sema.resolveGenericBody(block, ret_src, body, inst, Type.type);
16953 var buffer: Value.ToTypeBuffer = undefined;
16954 const ty = try val.toType(&buffer).copy(sema.arena);
16955 break :blk ty;
16956 } else if (extra.data.bits.has_ret_ty_ref) blk: {
16957 const ret_ty_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);
16958 extra_index += 1;
16959 const ret_ty_tv = sema.resolveInstConst(block, ret_src, ret_ty_ref) catch |err| switch (err) {
16960 error.GenericPoison => {
16961 break :blk Type.initTag(.generic_poison);
16962 },
16963 else => |e| return e,
16964 };
16965 var buffer: Value.ToTypeBuffer = undefined;
16966 const ty = try ret_ty_tv.val.toType(&buffer).copy(sema.arena);
16967 break :blk ty;
16968 } else Type.void;
1678816969
1678916970 var src_locs: Zir.Inst.Func.SrcLocs = undefined;
1679016971 const has_body = extra.data.body_len != 0;
......@@ -16801,9 +16982,11 @@ fn zirFuncExtended(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro
1680116982 block,
1680216983 inst_data.src_node,
1680316984 inst,
16804 ret_ty_body,
16985 @"align",
16986 @"addrspace",
16987 @"linksection",
1680516988 cc,
16806 align_val,
16989 ret_ty,
1680716990 is_var_args,
1680816991 is_inferred_error,
1680916992 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
7474 Inst.Call.Flags => @bitCast(Inst.Call.Flags, code.extra[i]),
7575 Inst.BuiltinCall.Flags => @bitCast(Inst.BuiltinCall.Flags, code.extra[i]),
7676 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]),
7878 else => @compileError("bad field type"),
7979 };
8080 i += 1;
......@@ -424,8 +424,8 @@ pub const Inst = struct {
424424 func_inferred,
425425 /// Represents a function declaration or function prototype, depending on
426426 /// whether body_len is 0.
427 /// Uses the `pl_node` union field. `payload_index` points to a `ExtendedFunc`.
428 func_extended,
427 /// Uses the `pl_node` union field. `payload_index` points to a `FuncFancy`.
428 func_fancy,
429429 /// Implements the `@import` builtin.
430430 /// Uses the `str_tok` field.
431431 import,
......@@ -1062,7 +1062,7 @@ pub const Inst = struct {
10621062 .field_val_named,
10631063 .func,
10641064 .func_inferred,
1065 .func_extended,
1065 .func_fancy,
10661066 .has_decl,
10671067 .int,
10681068 .int_big,
......@@ -1346,7 +1346,7 @@ pub const Inst = struct {
13461346 .field_val_named,
13471347 .func,
13481348 .func_inferred,
1349 .func_extended,
1349 .func_fancy,
13501350 .has_decl,
13511351 .int,
13521352 .int_big,
......@@ -1599,7 +1599,7 @@ pub const Inst = struct {
15991599 .field_call_bind = .pl_node,
16001600 .func = .pl_node,
16011601 .func_inferred = .pl_node,
1602 .func_extended = .pl_node,
1602 .func_fancy = .pl_node,
16031603 .import = .str_tok,
16041604 .int = .int,
16051605 .int_big = .str,
......@@ -2606,29 +2606,100 @@ pub const Inst = struct {
26062606 };
26072607
26082608 /// Trailing:
2609 /// 0. lib_name: u32, // null terminated string index, if has_lib_name is set
2610 /// 1. cc: Ref, // if has_cc is set
2611 /// 2. align: Ref, // if has_align is set
2612 /// 3. return_type: Index // for each ret_body_len
2613 /// 4. body: Index // for each body_len
2614 /// 5. src_locs: Func.SrcLocs // if body_len != 0
2615 pub const ExtendedFunc = struct {
2609 /// if (ret_body_len == 1) {
2610 /// 0. return_type: Ref
2611 /// }
2612 /// if (ret_body_len > 1) {
2613 /// 1. return_type: Index // for each ret_body_len
2614 /// }
2615 /// 2. body: Index // for each body_len
2616 /// 3. src_locs: SrcLocs // if body_len != 0
2617 pub const Func = struct {
26162618 /// If this is 0 it means a void return type.
2619 /// If this is 1 it means return_type is a simple Ref
26172620 ret_body_len: u32,
26182621 /// Points to the block that contains the param instructions for this function.
26192622 param_block: Index,
26202623 body_len: u32,
2624
2625 pub const SrcLocs = struct {
2626 /// Line index in the source file relative to the parent decl.
2627 lbrace_line: u32,
2628 /// Line index in the source file relative to the parent decl.
2629 rbrace_line: u32,
2630 /// lbrace_column is least significant bits u16
2631 /// rbrace_column is most significant bits u16
2632 columns: u32,
2633 };
2634 };
2635
2636 /// Trailing:
2637 /// 0. lib_name: u32, // null terminated string index, if has_lib_name is set
2638 /// if (has_align_ref and !has_align_body) {
2639 /// 1. align: Ref,
2640 /// }
2641 /// if (has_align_body) {
2642 /// 2. align_body_len: u32
2643 /// 3. align_body: u32 // for each align_body_len
2644 /// }
2645 /// if (has_addrspace_ref and !has_addrspace_body) {
2646 /// 4. addrspace: Ref,
2647 /// }
2648 /// if (has_addrspace_body) {
2649 /// 5. addrspace_body_len: u32
2650 /// 6. addrspace_body: u32 // for each addrspace_body_len
2651 /// }
2652 /// if (has_section_ref and !has_section_body) {
2653 /// 7. section: Ref,
2654 /// }
2655 /// if (has_section_body) {
2656 /// 8. section_body_len: u32
2657 /// 9. section_body: u32 // for each section_body_len
2658 /// }
2659 /// if (has_cc_ref and !has_cc_body) {
2660 /// 10. cc: Ref,
2661 /// }
2662 /// if (has_cc_body) {
2663 /// 11. cc_body_len: u32
2664 /// 12. cc_body: u32 // for each cc_body_len
2665 /// }
2666 /// if (has_ret_ty_ref and !has_ret_ty_body) {
2667 /// 13. ret_ty: Ref,
2668 /// }
2669 /// if (has_ret_ty_body) {
2670 /// 14. ret_ty_body_len: u32
2671 /// 15. ret_ty_body: u32 // for each ret_ty_body_len
2672 /// }
2673 /// 16. body: Index // for each body_len
2674 /// 17. src_locs: Func.SrcLocs // if body_len != 0
2675 pub const FuncFancy = struct {
2676 /// Points to the block that contains the param instructions for this function.
2677 param_block: Index,
2678 body_len: u32,
26212679 bits: Bits,
26222680
2681 /// If both has_cc_ref and has_cc_body are false, it means auto calling convention.
2682 /// If both has_align_ref and has_align_body are false, it means default alignment.
2683 /// If both has_ret_ty_ref and has_ret_ty_body are false, it means void return type.
2684 /// If both has_section_ref and has_section_body are false, it means default section.
2685 /// If both has_addrspace_ref and has_addrspace_body are false, it means default addrspace.
26232686 pub const Bits = packed struct {
26242687 is_var_args: bool,
26252688 is_inferred_error: bool,
2626 has_lib_name: bool,
2627 has_cc: bool,
2628 has_align: bool,
26292689 is_test: bool,
26302690 is_extern: bool,
2631 _: u25 = undefined,
2691 has_align_ref: bool,
2692 has_align_body: bool,
2693 has_addrspace_ref: bool,
2694 has_addrspace_body: bool,
2695 has_section_ref: bool,
2696 has_section_body: bool,
2697 has_cc_ref: bool,
2698 has_cc_body: bool,
2699 has_ret_ty_ref: bool,
2700 has_ret_ty_body: bool,
2701 has_lib_name: bool,
2702 _: u17 = undefined,
26322703 };
26332704 };
26342705
......@@ -2650,28 +2721,6 @@ pub const Inst = struct {
26502721 };
26512722 };
26522723
2653 /// Trailing:
2654 /// 0. return_type: Index // for each ret_body_len
2655 /// 1. body: Index // for each body_len
2656 /// 2. src_locs: SrcLocs // if body_len != 0
2657 pub const Func = struct {
2658 /// If this is 0 it means a void return type.
2659 ret_body_len: u32,
2660 /// Points to the block that contains the param instructions for this function.
2661 param_block: Index,
2662 body_len: u32,
2663
2664 pub const SrcLocs = struct {
2665 /// Line index in the source file relative to the parent decl.
2666 lbrace_line: u32,
2667 /// Line index in the source file relative to the parent decl.
2668 rbrace_line: u32,
2669 /// lbrace_column is least significant bits u16
2670 /// rbrace_column is most significant bits u16
2671 columns: u32,
2672 };
2673 };
2674
26752724 /// This data is stored inside extra, with trailing operands according to `operands_len`.
26762725 /// Each operand is a `Ref`.
26772726 pub const MultiOp = struct {
......@@ -3473,7 +3522,7 @@ pub fn declIterator(zir: Zir, decl_inst: u32) DeclIterator {
34733522 switch (tags[decl_inst]) {
34743523 // Functions are allowed and yield no iterations.
34753524 // There is one case matching this in the extended instruction set below.
3476 .func, .func_inferred, .func_extended => return declIteratorInner(zir, 0, 0),
3525 .func, .func_inferred, .func_fancy => return declIteratorInner(zir, 0, 0),
34773526
34783527 .extended => {
34793528 const extended = datas[decl_inst].extended;
......@@ -3579,18 +3628,77 @@ fn findDeclsInner(
35793628
35803629 const inst_data = datas[inst].pl_node;
35813630 const extra = zir.extraData(Inst.Func, inst_data.payload_index);
3582 const body = zir.extra[extra.end..][0..extra.data.body_len];
3631 var extra_index: usize = extra.end;
3632 switch (extra.data.ret_body_len) {
3633 0 => {},
3634 1 => extra_index += 1,
3635 else => {
3636 const body = zir.extra[extra_index..][0..extra.data.ret_body_len];
3637 extra_index += body.len;
3638 try zir.findDeclsBody(list, body);
3639 },
3640 }
3641 const body = zir.extra[extra_index..][0..extra.data.body_len];
35833642 return zir.findDeclsBody(list, body);
35843643 },
3585 .func_extended => {
3644 .func_fancy => {
35863645 try list.append(inst);
35873646
35883647 const inst_data = datas[inst].pl_node;
3589 const extra = zir.extraData(Inst.ExtendedFunc, inst_data.payload_index);
3648 const extra = zir.extraData(Inst.FuncFancy, inst_data.payload_index);
35903649 var extra_index: usize = extra.end;
35913650 extra_index += @boolToInt(extra.data.bits.has_lib_name);
3592 extra_index += @boolToInt(extra.data.bits.has_cc);
3593 extra_index += @boolToInt(extra.data.bits.has_align);
3651
3652 if (extra.data.bits.has_align_body) {
3653 const body_len = zir.extra[extra_index];
3654 extra_index += 1;
3655 const body = zir.extra[extra_index..][0..body_len];
3656 try zir.findDeclsBody(list, body);
3657 extra_index += body.len;
3658 } else if (extra.data.bits.has_align_ref) {
3659 extra_index += 1;
3660 }
3661
3662 if (extra.data.bits.has_addrspace_body) {
3663 const body_len = zir.extra[extra_index];
3664 extra_index += 1;
3665 const body = zir.extra[extra_index..][0..body_len];
3666 try zir.findDeclsBody(list, body);
3667 extra_index += body.len;
3668 } else if (extra.data.bits.has_addrspace_ref) {
3669 extra_index += 1;
3670 }
3671
3672 if (extra.data.bits.has_section_body) {
3673 const body_len = zir.extra[extra_index];
3674 extra_index += 1;
3675 const body = zir.extra[extra_index..][0..body_len];
3676 try zir.findDeclsBody(list, body);
3677 extra_index += body.len;
3678 } else if (extra.data.bits.has_section_ref) {
3679 extra_index += 1;
3680 }
3681
3682 if (extra.data.bits.has_cc_body) {
3683 const body_len = zir.extra[extra_index];
3684 extra_index += 1;
3685 const body = zir.extra[extra_index..][0..body_len];
3686 try zir.findDeclsBody(list, body);
3687 extra_index += body.len;
3688 } else if (extra.data.bits.has_cc_ref) {
3689 extra_index += 1;
3690 }
3691
3692 if (extra.data.bits.has_ret_ty_body) {
3693 const body_len = zir.extra[extra_index];
3694 extra_index += 1;
3695 const body = zir.extra[extra_index..][0..body_len];
3696 try zir.findDeclsBody(list, body);
3697 extra_index += body.len;
3698 } else if (extra.data.bits.has_ret_ty_ref) {
3699 extra_index += 1;
3700 }
3701
35943702 const body = zir.extra[extra_index..][0..extra.data.body_len];
35953703 return zir.findDeclsBody(list, body);
35963704 },
......@@ -3715,6 +3823,7 @@ pub const FnInfo = struct {
37153823 param_body_inst: Inst.Index,
37163824 ret_ty_body: []const Inst.Index,
37173825 body: []const Inst.Index,
3826 ret_ty_ref: Zir.Inst.Ref,
37183827 total_params_len: u32,
37193828};
37203829
......@@ -3724,38 +3833,84 @@ pub fn getFnInfo(zir: Zir, fn_inst: Inst.Index) FnInfo {
37243833 const info: struct {
37253834 param_block: Inst.Index,
37263835 body: []const Inst.Index,
3836 ret_ty_ref: Inst.Ref,
37273837 ret_ty_body: []const Inst.Index,
37283838 } = switch (tags[fn_inst]) {
37293839 .func, .func_inferred => blk: {
37303840 const inst_data = datas[fn_inst].pl_node;
37313841 const extra = zir.extraData(Inst.Func, inst_data.payload_index);
3842
37323843 var extra_index: usize = extra.end;
3844 var ret_ty_ref: Inst.Ref = .none;
3845 var ret_ty_body: []const Inst.Index = &.{};
37333846
3734 const ret_ty_body = zir.extra[extra_index..][0..extra.data.ret_body_len];
3735 extra_index += ret_ty_body.len;
3847 switch (extra.data.ret_body_len) {
3848 0 => {
3849 ret_ty_ref = .void_type;
3850 },
3851 1 => {
3852 ret_ty_ref = @intToEnum(Inst.Ref, zir.extra[extra_index]);
3853 extra_index += 1;
3854 },
3855 else => {
3856 ret_ty_body = zir.extra[extra_index..][0..extra.data.ret_body_len];
3857 extra_index += ret_ty_body.len;
3858 },
3859 }
37363860
37373861 const body = zir.extra[extra_index..][0..extra.data.body_len];
37383862 extra_index += body.len;
37393863
37403864 break :blk .{
37413865 .param_block = extra.data.param_block,
3866 .ret_ty_ref = ret_ty_ref,
37423867 .ret_ty_body = ret_ty_body,
37433868 .body = body,
37443869 };
37453870 },
3746 .func_extended => blk: {
3871 .func_fancy => blk: {
37473872 const inst_data = datas[fn_inst].pl_node;
3748 const extra = zir.extraData(Inst.ExtendedFunc, inst_data.payload_index);
3873 const extra = zir.extraData(Inst.FuncFancy, inst_data.payload_index);
3874
37493875 var extra_index: usize = extra.end;
3876 var ret_ty_ref: Inst.Ref = .void_type;
3877 var ret_ty_body: []const Inst.Index = &.{};
3878
37503879 extra_index += @boolToInt(extra.data.bits.has_lib_name);
3751 extra_index += @boolToInt(extra.data.bits.has_cc);
3752 extra_index += @boolToInt(extra.data.bits.has_align);
3753 const ret_ty_body = zir.extra[extra_index..][0..extra.data.ret_body_len];
3754 extra_index += ret_ty_body.len;
3880 if (extra.data.bits.has_align_body) {
3881 extra_index += zir.extra[extra_index] + 1;
3882 } else if (extra.data.bits.has_align_ref) {
3883 extra_index += 1;
3884 }
3885 if (extra.data.bits.has_addrspace_body) {
3886 extra_index += zir.extra[extra_index] + 1;
3887 } else if (extra.data.bits.has_addrspace_ref) {
3888 extra_index += 1;
3889 }
3890 if (extra.data.bits.has_section_body) {
3891 extra_index += zir.extra[extra_index] + 1;
3892 } else if (extra.data.bits.has_section_ref) {
3893 extra_index += 1;
3894 }
3895 if (extra.data.bits.has_cc_body) {
3896 extra_index += zir.extra[extra_index] + 1;
3897 } else if (extra.data.bits.has_cc_ref) {
3898 extra_index += 1;
3899 }
3900 if (extra.data.bits.has_ret_ty_body) {
3901 const body_len = zir.extra[extra_index];
3902 extra_index += 1;
3903 ret_ty_body = zir.extra[extra_index..][0..body_len];
3904 extra_index += ret_ty_body.len;
3905 } else if (extra.data.bits.has_ret_ty_ref) {
3906 ret_ty_ref = @intToEnum(Inst.Ref, zir.extra[extra_index]);
3907 extra_index += 1;
3908 }
37553909 const body = zir.extra[extra_index..][0..extra.data.body_len];
37563910 extra_index += body.len;
37573911 break :blk .{
37583912 .param_block = extra.data.param_block,
3913 .ret_ty_ref = ret_ty_ref,
37593914 .ret_ty_body = ret_ty_body,
37603915 .body = body,
37613916 };
......@@ -3778,6 +3933,7 @@ pub fn getFnInfo(zir: Zir, fn_inst: Inst.Index) FnInfo {
37783933 .param_body = param_body,
37793934 .param_body_inst = info.param_block,
37803935 .ret_ty_body = info.ret_ty_body,
3936 .ret_ty_ref = info.ret_ty_ref,
37813937 .body = info.body,
37823938 .total_params_len = total_params_len,
37833939 };
src/print_zir.zig+132-37
......@@ -426,7 +426,7 @@ const Writer = struct {
426426
427427 .func => try self.writeFunc(stream, inst, false),
428428 .func_inferred => try self.writeFunc(stream, inst, true),
429 .func_extended => try self.writeFuncExtended(stream, inst),
429 .func_fancy => try self.writeFuncFancy(stream, inst),
430430
431431 .@"unreachable" => try self.writeUnreachable(stream, inst),
432432
......@@ -1915,10 +1915,24 @@ const Writer = struct {
19151915 const inst_data = self.code.instructions.items(.data)[inst].pl_node;
19161916 const src = inst_data.src();
19171917 const extra = self.code.extraData(Zir.Inst.Func, inst_data.payload_index);
1918
19181919 var extra_index = extra.end;
1920 var ret_ty_ref: Zir.Inst.Ref = .none;
1921 var ret_ty_body: []const Zir.Inst.Index = &.{};
19191922
1920 const ret_ty_body = self.code.extra[extra_index..][0..extra.data.ret_body_len];
1921 extra_index += ret_ty_body.len;
1923 switch (extra.data.ret_body_len) {
1924 0 => {
1925 ret_ty_ref = .void_type;
1926 },
1927 1 => {
1928 ret_ty_ref = @intToEnum(Zir.Inst.Ref, self.code.extra[extra_index]);
1929 extra_index += 1;
1930 },
1931 else => {
1932 ret_ty_body = self.code.extra[extra_index..][0..extra.data.ret_body_len];
1933 extra_index += ret_ty_body.len;
1934 },
1935 }
19221936
19231937 const body = self.code.extra[extra_index..][0..extra.data.body_len];
19241938 extra_index += body.len;
......@@ -1929,43 +1943,96 @@ const Writer = struct {
19291943 }
19301944 return self.writeFuncCommon(
19311945 stream,
1932 ret_ty_body,
19331946 inferred_error_set,
19341947 false,
19351948 false,
1949
19361950 .none,
1951 &.{},
19371952 .none,
1953 &.{},
1954 .none,
1955 &.{},
1956 .none,
1957 &.{},
1958 ret_ty_ref,
1959 ret_ty_body,
1960
19381961 body,
19391962 src,
19401963 src_locs,
19411964 );
19421965 }
19431966
1944 fn writeFuncExtended(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {
1967 fn writeFuncFancy(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {
19451968 const inst_data = self.code.instructions.items(.data)[inst].pl_node;
1946 const extra = self.code.extraData(Zir.Inst.ExtendedFunc, inst_data.payload_index);
1969 const extra = self.code.extraData(Zir.Inst.FuncFancy, inst_data.payload_index);
19471970 const src = inst_data.src();
19481971
19491972 var extra_index: usize = extra.end;
1973 var align_ref: Zir.Inst.Ref = .none;
1974 var align_body: []const Zir.Inst.Index = &.{};
1975 var addrspace_ref: Zir.Inst.Ref = .none;
1976 var addrspace_body: []const Zir.Inst.Index = &.{};
1977 var section_ref: Zir.Inst.Ref = .none;
1978 var section_body: []const Zir.Inst.Index = &.{};
1979 var cc_ref: Zir.Inst.Ref = .none;
1980 var cc_body: []const Zir.Inst.Index = &.{};
1981 var ret_ty_ref: Zir.Inst.Ref = .none;
1982 var ret_ty_body: []const Zir.Inst.Index = &.{};
1983
19501984 if (extra.data.bits.has_lib_name) {
19511985 const lib_name = self.code.nullTerminatedString(self.code.extra[extra_index]);
19521986 extra_index += 1;
19531987 try stream.print("lib_name=\"{}\", ", .{std.zig.fmtEscapes(lib_name)});
19541988 }
19551989 try self.writeFlag(stream, "test, ", extra.data.bits.is_test);
1956 const cc: Zir.Inst.Ref = if (!extra.data.bits.has_cc) .none else blk: {
1957 const cc = @intToEnum(Zir.Inst.Ref, self.code.extra[extra_index]);
1990
1991 if (extra.data.bits.has_align_body) {
1992 const body_len = self.code.extra[extra_index];
19581993 extra_index += 1;
1959 break :blk cc;
1960 };
1961 const align_inst: Zir.Inst.Ref = if (!extra.data.bits.has_align) .none else blk: {
1962 const align_inst = @intToEnum(Zir.Inst.Ref, self.code.extra[extra_index]);
1994 align_body = self.code.extra[extra_index..][0..body_len];
1995 extra_index += align_body.len;
1996 } else if (extra.data.bits.has_align_ref) {
1997 align_ref = @intToEnum(Zir.Inst.Ref, self.code.extra[extra_index]);
19631998 extra_index += 1;
1964 break :blk align_inst;
1965 };
1966
1967 const ret_ty_body = self.code.extra[extra_index..][0..extra.data.ret_body_len];
1968 extra_index += ret_ty_body.len;
1999 }
2000 if (extra.data.bits.has_addrspace_body) {
2001 const body_len = self.code.extra[extra_index];
2002 extra_index += 1;
2003 addrspace_body = self.code.extra[extra_index..][0..body_len];
2004 extra_index += addrspace_body.len;
2005 } else if (extra.data.bits.has_addrspace_ref) {
2006 addrspace_ref = @intToEnum(Zir.Inst.Ref, self.code.extra[extra_index]);
2007 extra_index += 1;
2008 }
2009 if (extra.data.bits.has_section_body) {
2010 const body_len = self.code.extra[extra_index];
2011 extra_index += 1;
2012 section_body = self.code.extra[extra_index..][0..body_len];
2013 extra_index += section_body.len;
2014 } else if (extra.data.bits.has_section_ref) {
2015 section_ref = @intToEnum(Zir.Inst.Ref, self.code.extra[extra_index]);
2016 extra_index += 1;
2017 }
2018 if (extra.data.bits.has_cc_body) {
2019 const body_len = self.code.extra[extra_index];
2020 extra_index += 1;
2021 cc_body = self.code.extra[extra_index..][0..body_len];
2022 extra_index += cc_body.len;
2023 } else if (extra.data.bits.has_cc_ref) {
2024 cc_ref = @intToEnum(Zir.Inst.Ref, self.code.extra[extra_index]);
2025 extra_index += 1;
2026 }
2027 if (extra.data.bits.has_ret_ty_body) {
2028 const body_len = self.code.extra[extra_index];
2029 extra_index += 1;
2030 ret_ty_body = self.code.extra[extra_index..][0..body_len];
2031 extra_index += ret_ty_body.len;
2032 } else if (extra.data.bits.has_ret_ty_ref) {
2033 ret_ty_ref = @intToEnum(Zir.Inst.Ref, self.code.extra[extra_index]);
2034 extra_index += 1;
2035 }
19692036
19702037 const body = self.code.extra[extra_index..][0..extra.data.body_len];
19712038 extra_index += body.len;
......@@ -1976,12 +2043,19 @@ const Writer = struct {
19762043 }
19772044 return self.writeFuncCommon(
19782045 stream,
1979 ret_ty_body,
19802046 extra.data.bits.is_inferred_error,
19812047 extra.data.bits.is_var_args,
19822048 extra.data.bits.is_extern,
1983 cc,
1984 align_inst,
2049 align_ref,
2050 align_body,
2051 addrspace_ref,
2052 addrspace_body,
2053 section_ref,
2054 section_body,
2055 cc_ref,
2056 cc_body,
2057 ret_ty_ref,
2058 ret_ty_body,
19852059 body,
19862060 src,
19872061 src_locs,
......@@ -2126,30 +2200,33 @@ const Writer = struct {
21262200 fn writeFuncCommon(
21272201 self: *Writer,
21282202 stream: anytype,
2129 ret_ty_body: []const Zir.Inst.Index,
21302203 inferred_error_set: bool,
21312204 var_args: bool,
21322205 is_extern: bool,
2133 cc: Zir.Inst.Ref,
2134 align_inst: Zir.Inst.Ref,
2206 align_ref: Zir.Inst.Ref,
2207 align_body: []const Zir.Inst.Index,
2208 addrspace_ref: Zir.Inst.Ref,
2209 addrspace_body: []const Zir.Inst.Index,
2210 section_ref: Zir.Inst.Ref,
2211 section_body: []const Zir.Inst.Index,
2212 cc_ref: Zir.Inst.Ref,
2213 cc_body: []const Zir.Inst.Index,
2214 ret_ty_ref: Zir.Inst.Ref,
2215 ret_ty_body: []const Zir.Inst.Index,
21352216 body: []const Zir.Inst.Index,
21362217 src: LazySrcLoc,
21372218 src_locs: Zir.Inst.Func.SrcLocs,
21382219 ) !void {
2139 if (ret_ty_body.len == 0) {
2140 try stream.writeAll("ret_ty=void");
2141 } else {
2142 try stream.writeAll("ret_ty=");
2143 try self.writeBracedBody(stream, ret_ty_body);
2144 }
2145
2146 try self.writeOptionalInstRef(stream, ", cc=", cc);
2147 try self.writeOptionalInstRef(stream, ", align=", align_inst);
2148 try self.writeFlag(stream, ", vargs", var_args);
2149 try self.writeFlag(stream, ", extern", is_extern);
2150 try self.writeFlag(stream, ", inferror", inferred_error_set);
2151
2152 try stream.writeAll(", body=");
2220 try self.writeOptionalInstRefOrBody(stream, "align=", align_ref, align_body);
2221 try self.writeOptionalInstRefOrBody(stream, "addrspace=", addrspace_ref, addrspace_body);
2222 try self.writeOptionalInstRefOrBody(stream, "section=", section_ref, section_body);
2223 try self.writeOptionalInstRefOrBody(stream, "cc=", cc_ref, cc_body);
2224 try self.writeOptionalInstRefOrBody(stream, "ret_ty=", ret_ty_ref, ret_ty_body);
2225 try self.writeFlag(stream, "vargs, ", var_args);
2226 try self.writeFlag(stream, "extern, ", is_extern);
2227 try self.writeFlag(stream, "inferror, ", inferred_error_set);
2228
2229 try stream.writeAll("body=");
21532230 try self.writeBracedBody(stream, body);
21542231 try stream.writeAll(") ");
21552232 if (body.len != 0) {
......@@ -2199,6 +2276,24 @@ const Writer = struct {
21992276 try self.writeInstRef(stream, inst);
22002277 }
22012278
2279 fn writeOptionalInstRefOrBody(
2280 self: *Writer,
2281 stream: anytype,
2282 prefix: []const u8,
2283 ref: Zir.Inst.Ref,
2284 body: []const Zir.Inst.Index,
2285 ) !void {
2286 if (body.len != 0) {
2287 try stream.writeAll(prefix);
2288 try self.writeBracedBody(stream, body);
2289 try stream.writeAll(", ");
2290 } else if (ref != .none) {
2291 try stream.writeAll(prefix);
2292 try self.writeInstRef(stream, ref);
2293 try stream.writeAll(", ");
2294 }
2295 }
2296
22022297 fn writeFlag(
22032298 self: *Writer,
22042299 stream: anytype,
src/type.zig+4
......@@ -6120,6 +6120,10 @@ pub const Type = extern union {
61206120 cc: std.builtin.CallingConvention,
61216121 is_var_args: bool,
61226122 is_generic: bool,
6123 align_is_generic: bool = false,
6124 cc_is_generic: bool = false,
6125 section_is_generic: bool = false,
6126 addrspace_is_generic: bool = false,
61236127
61246128 pub fn paramIsComptime(self: @This(), i: usize) bool {
61256129 assert(i < self.param_types.len);
test/behavior/align.zig+31-12
......@@ -334,25 +334,44 @@ fn simple4() align(4) i32 {
334334 return 0x19;
335335}
336336
337test "generic function with align param" {
338 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
339 if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
340 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
341 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
342 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
337test "function align expression depends on generic parameter" {
338 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
339 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
343340
344341 // function alignment is a compile error on wasm32/wasm64
345342 if (native_arch == .wasm32 or native_arch == .wasm64) return error.SkipZigTest;
346343 if (native_arch == .thumb) return error.SkipZigTest;
347344
348 try expect(whyWouldYouEverDoThis(1) == 0x1);
349 try expect(whyWouldYouEverDoThis(4) == 0x1);
350 try expect(whyWouldYouEverDoThis(8) == 0x1);
345 const S = struct {
346 fn doTheTest() !void {
347 try expect(foobar(1) == 2);
348 try expect(foobar(4) == 5);
349 try expect(foobar(8) == 9);
350 }
351
352 fn foobar(comptime align_bytes: u8) align(align_bytes) u8 {
353 return align_bytes + 1;
354 }
355 };
356 try S.doTheTest();
357 comptime try S.doTheTest();
351358}
352359
353fn whyWouldYouEverDoThis(comptime align_bytes: u8) align(align_bytes) u8 {
354 _ = align_bytes;
355 return 0x1;
360test "function callconv expression depends on generic parameter" {
361 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
362
363 const S = struct {
364 fn doTheTest() !void {
365 try expect(foobar(.C, 1) == 2);
366 try expect(foobar(.Unspecified, 2) == 3);
367 }
368
369 fn foobar(comptime cc: std.builtin.CallingConvention, arg: u8) callconv(cc) u8 {
370 return arg + 1;
371 }
372 };
373 try S.doTheTest();
374 comptime try S.doTheTest();
356375}
357376
358377test "runtime known array index has best alignment possible" {