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 {...@@ -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,
...@@ -2262,7 +2267,7 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: Ast.Node.Index) Inner...@@ -2262,7 +2267,7 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: Ast.Node.Index) Inner
2262 .field_val_named,2267 .field_val_named,
2263 .func,2268 .func,
2264 .func_inferred,2269 .func_inferred,
2265 .func_extended,2270 .func_fancy,
2266 .int,2271 .int,
2267 .int_big,2272 .int_big,
2268 .float,2273 .float,
...@@ -3373,9 +3378,8 @@ fn fnDecl(...@@ -3373,9 +3378,8 @@ fn fnDecl(
33733378
3374 const doc_comment_index = try astgen.docCommentAsString(fn_proto.firstToken());3379 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;3381 // align, linksection, and addrspace is passed in the func instruction in this case.
3377 // Alignment is passed in the func instruction in this case.3382 wip_members.nextDecl(is_pub, is_export, false, false);
3378 wip_members.nextDecl(is_pub, is_export, false, has_section_or_addrspace);
33793383
3380 var params_scope = &fn_gz.base;3384 var params_scope = &fn_gz.base;
3381 const is_var_args = is_var_args: {3385 const is_var_args = is_var_args: {
...@@ -3461,17 +3465,49 @@ fn fnDecl(...@@ -3461,17 +3465,49 @@ fn fnDecl(
3461 const maybe_bang = tree.firstToken(fn_proto.ast.return_type) - 1;3465 const maybe_bang = tree.firstToken(fn_proto.ast.return_type) - 1;
3462 const is_inferred_error = token_tags[maybe_bang] == .bang;3466 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: {3468 // After creating the function ZIR instruction, it will need to update the break
3465 break :inst try expr(&decl_gz, params_scope, align_rl, fn_proto.ast.align_expr);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;
3466 };3482 };
3467 const addrspace_inst: Zir.Inst.Ref = if (fn_proto.ast.addrspace_expr == 0) .none else inst: {3483
3468 break :inst try expr(&decl_gz, params_scope, .{ .ty = .address_space_type }, fn_proto.ast.addrspace_expr);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;
3469 };3494 };
3470 const section_inst: Zir.Inst.Ref = if (fn_proto.ast.section_expr == 0) .none else inst: {3495
3471 break :inst try comptimeExpr(&decl_gz, params_scope, .{ .ty = .const_slice_u8_type }, fn_proto.ast.section_expr);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;
3472 };3506 };
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: {
3475 if (fn_proto.ast.callconv_expr != 0) {3511 if (fn_proto.ast.callconv_expr != 0) {
3476 if (has_inline_keyword) {3512 if (has_inline_keyword) {
3477 return astgen.failNode(3513 return astgen.failNode(
...@@ -3480,12 +3516,18 @@ fn fnDecl(...@@ -3480,12 +3516,18 @@ fn fnDecl(
3480 .{},3516 .{},
3481 );3517 );
3482 }3518 }
3483 break :blk try expr(3519 const inst = try expr(
3484 &decl_gz,3520 &decl_gz,
3485 params_scope,3521 params_scope,
3486 .{ .ty = .calling_convention_type },3522 .{ .coerced_ty = .calling_convention_type },
3487 fn_proto.ast.callconv_expr,3523 fn_proto.ast.callconv_expr,
3488 );3524 );
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;
3489 } else if (is_extern) {3531 } else if (is_extern) {
3490 // note: https://github.com/ziglang/zig/issues/52693532 // note: https://github.com/ziglang/zig/issues/5269
3491 break :blk .calling_convention_c;3533 break :blk .calling_convention_c;
...@@ -3498,8 +3540,15 @@ fn fnDecl(...@@ -3498,8 +3540,15 @@ fn fnDecl(
34983540
3499 var ret_gz = decl_gz.makeSubBlock(params_scope);3541 var ret_gz = decl_gz.makeSubBlock(params_scope);
3500 defer ret_gz.unstack();3542 defer ret_gz.unstack();
3501 const ret_ty = try expr(&ret_gz, params_scope, coerced_type_rl, fn_proto.ast.return_type);3543 const ret_ref: Zir.Inst.Ref = inst: {
3502 const ret_br = try ret_gz.addBreak(.break_inline, 0, ret_ty);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
3504 const func_inst: Zir.Inst.Ref = if (body_node == 0) func: {3553 const func_inst: Zir.Inst.Ref = if (body_node == 0) func: {
3505 if (!is_extern) {3554 if (!is_extern) {
...@@ -3510,12 +3559,18 @@ fn fnDecl(...@@ -3510,12 +3559,18 @@ fn fnDecl(
3510 }3559 }
3511 break :func try decl_gz.addFunc(.{3560 break :func try decl_gz.addFunc(.{
3512 .src_node = decl_node,3561 .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,
3513 .ret_gz = &ret_gz,3567 .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,
3515 .param_block = block_inst,3572 .param_block = block_inst,
3516 .body_gz = null,3573 .body_gz = null,
3517 .cc = cc,
3518 .align_inst = align_inst,
3519 .lib_name = lib_name,3574 .lib_name = lib_name,
3520 .is_var_args = is_var_args,3575 .is_var_args = is_var_args,
3521 .is_inferred_error = false,3576 .is_inferred_error = false,
...@@ -3549,14 +3604,20 @@ fn fnDecl(...@@ -3549,14 +3604,20 @@ fn fnDecl(
35493604
3550 break :func try decl_gz.addFunc(.{3605 break :func try decl_gz.addFunc(.{
3551 .src_node = decl_node,3606 .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,
3552 .lbrace_line = lbrace_line,3617 .lbrace_line = lbrace_line,
3553 .lbrace_column = lbrace_column,3618 .lbrace_column = lbrace_column,
3554 .param_block = block_inst,3619 .param_block = block_inst,
3555 .ret_gz = &ret_gz,
3556 .ret_br = ret_br,
3557 .body_gz = &fn_gz,3620 .body_gz = &fn_gz,
3558 .cc = cc,
3559 .align_inst = align_inst,
3560 .lib_name = lib_name,3621 .lib_name = lib_name,
3561 .is_var_args = is_var_args,3622 .is_var_args = is_var_args,
3562 .is_inferred_error = is_inferred_error,3623 .is_inferred_error = is_inferred_error,
...@@ -3582,10 +3643,6 @@ fn fnDecl(...@@ -3582,10 +3643,6 @@ fn fnDecl(
3582 wip_members.appendToDecl(fn_name_str_index);3643 wip_members.appendToDecl(fn_name_str_index);
3583 wip_members.appendToDecl(block_inst);3644 wip_members.appendToDecl(block_inst);
3584 wip_members.appendToDecl(doc_comment_index);3645 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 }
3589}3646}
35903647
3591fn globalVarDecl(3648fn globalVarDecl(
...@@ -3979,14 +4036,22 @@ fn testDecl(...@@ -3979,14 +4036,22 @@ fn testDecl(
39794036
3980 const func_inst = try decl_block.addFunc(.{4037 const func_inst = try decl_block.addFunc(.{
3981 .src_node = node,4038 .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
3982 .lbrace_line = lbrace_line,4051 .lbrace_line = lbrace_line,
3983 .lbrace_column = lbrace_column,4052 .lbrace_column = lbrace_column,
3984 .param_block = block_inst,4053 .param_block = block_inst,
3985 .ret_gz = null,
3986 .ret_br = 0,
3987 .body_gz = &fn_block,4054 .body_gz = &fn_block,
3988 .cc = .none,
3989 .align_inst = .none,
3990 .lib_name = 0,4055 .lib_name = 0,
3991 .is_var_args = false,4056 .is_var_args = false,
3992 .is_inferred_error = true,4057 .is_inferred_error = true,
...@@ -9930,17 +9995,34 @@ const GenZir = struct {...@@ -9930,17 +9995,34 @@ const GenZir = struct {
9930 gz.unstack();9995 gz.unstack();
9931 }9996 }
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`.
9934 fn addFunc(gz: *GenZir, args: struct {10007 fn addFunc(gz: *GenZir, args: struct {
9935 src_node: Ast.Node.Index,10008 src_node: Ast.Node.Index,
9936 lbrace_line: u32 = 0,10009 lbrace_line: u32 = 0,
9937 lbrace_column: u32 = 0,10010 lbrace_column: u32 = 0,
9938 body_gz: ?*GenZir,
9939 param_block: Zir.Inst.Index,10011 param_block: Zir.Inst.Index,
10012
10013 align_gz: ?*GenZir,
10014 addrspace_gz: ?*GenZir,
10015 section_gz: ?*GenZir,
10016 cc_gz: ?*GenZir,
9940 ret_gz: ?*GenZir,10017 ret_gz: ?*GenZir,
9941 ret_br: Zir.Inst.Index,10018 body_gz: ?*GenZir,
9942 cc: Zir.Inst.Ref,10019
9943 align_inst: Zir.Inst.Ref,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
9944 lib_name: u32,10026 lib_name: u32,
9945 is_var_args: bool,10027 is_var_args: bool,
9946 is_inferred_error: bool,10028 is_inferred_error: bool,
...@@ -9950,11 +10032,13 @@ const GenZir = struct {...@@ -9950,11 +10032,13 @@ const GenZir = struct {
9950 assert(args.src_node != 0);10032 assert(args.src_node != 0);
9951 const astgen = gz.astgen;10033 const astgen = gz.astgen;
9952 const gpa = astgen.gpa;10034 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
9954 try astgen.instructions.ensureUnusedCapacity(gpa, 1);10038 try astgen.instructions.ensureUnusedCapacity(gpa, 1);
995510039
9956 var body: []Zir.Inst.Index = &[0]Zir.Inst.Index{};10040 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{};
9958 var src_locs_buffer: [3]u32 = undefined;10042 var src_locs_buffer: [3]u32 = undefined;
9959 var src_locs: []u32 = src_locs_buffer[0..0];10043 var src_locs: []u32 = src_locs_buffer[0..0];
9960 if (args.body_gz) |body_gz| {10044 if (args.body_gz) |body_gz| {
...@@ -9978,61 +10062,120 @@ const GenZir = struct {...@@ -9978,61 +10062,120 @@ const GenZir = struct {
997810062
9979 body = body_gz.instructionsSlice();10063 body = body_gz.instructionsSlice();
9980 if (args.ret_gz) |ret_gz|10064 if (args.ret_gz) |ret_gz|
9981 ret_ty = ret_gz.instructionsSliceUpto(body_gz);10065 ret_body = ret_gz.instructionsSliceUpto(body_gz);
9982 } else {10066 } else {
9983 if (args.ret_gz) |ret_gz|10067 if (args.ret_gz) |ret_gz|
9984 ret_ty = ret_gz.instructionsSlice();10068 ret_body = ret_gz.instructionsSlice();
9985 }10069 }
998610070
9987 if (args.cc != .none or args.lib_name != 0 or10071 if (args.cc_ref != .none or args.lib_name != 0 or
9988 args.is_var_args or args.is_test or args.align_inst != .none or10072 args.is_var_args or args.is_test or args.is_extern or
9989 args.is_extern)10073 args.align_ref != .none or args.section_ref != .none or
10074 args.addrspace_ref != .none)
9990 {10075 {
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
9991 try astgen.extra.ensureUnusedCapacity(10087 try astgen.extra.ensureUnusedCapacity(
9992 gpa,10088 gpa,
9993 @typeInfo(Zir.Inst.ExtendedFunc).Struct.fields.len +10089 @typeInfo(Zir.Inst.FuncFancy).Struct.fields.len +
9994 ret_ty.len + body.len + src_locs.len +10090 fancyFnExprExtraLen(align_body, args.align_ref) +
9995 @boolToInt(args.lib_name != 0) +10091 fancyFnExprExtraLen(addrspace_body, args.addrspace_ref) +
9996 @boolToInt(args.align_inst != .none) +10092 fancyFnExprExtraLen(section_body, args.section_ref) +
9997 @boolToInt(args.cc != .none),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),
9998 );10097 );
9999 const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.ExtendedFunc{10098 const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.FuncFancy{
10000 .param_block = args.param_block,10099 .param_block = args.param_block,
10001 .ret_body_len = @intCast(u32, ret_ty.len),
10002 .body_len = @intCast(u32, body.len),10100 .body_len = @intCast(u32, body.len),
10003 .bits = .{10101 .bits = .{
10004 .is_var_args = args.is_var_args,10102 .is_var_args = args.is_var_args,
10005 .is_inferred_error = args.is_inferred_error,10103 .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,
10009 .is_test = args.is_test,10104 .is_test = args.is_test,
10010 .is_extern = args.is_extern,10105 .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,
10011 },10119 },
10012 });10120 });
10013 if (args.lib_name != 0) {10121 if (args.lib_name != 0) {
10014 astgen.extra.appendAssumeCapacity(args.lib_name);10122 astgen.extra.appendAssumeCapacity(args.lib_name);
10015 }10123 }
10016 if (args.cc != .none) {10124
10017 astgen.extra.appendAssumeCapacity(@enumToInt(args.cc));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));
10018 }10139 }
10019 if (args.align_inst != .none) {10140 if (section_body.len != 0) {
10020 astgen.extra.appendAssumeCapacity(@enumToInt(args.align_inst));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));
10021 }10146 }
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
10023 astgen.extra.appendSliceAssumeCapacity(body);10162 astgen.extra.appendSliceAssumeCapacity(body);
10024 astgen.extra.appendSliceAssumeCapacity(src_locs);10163 astgen.extra.appendSliceAssumeCapacity(src_locs);
10025 // order is important when unstacking10164
10165 // Order is important when unstacking.
10026 if (args.body_gz) |body_gz| body_gz.unstack();10166 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
10028 try gz.instructions.ensureUnusedCapacity(gpa, 1);10175 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 }
10034 astgen.instructions.appendAssumeCapacity(.{10177 astgen.instructions.appendAssumeCapacity(.{
10035 .tag = .func_extended,10178 .tag = .func_fancy,
10036 .data = .{ .pl_node = .{10179 .data = .{ .pl_node = .{
10037 .src_node = gz.nodeIndexToRelative(args.src_node),10180 .src_node = gz.nodeIndexToRelative(args.src_node),
10038 .payload_index = payload_index,10181 .payload_index = payload_index,
...@@ -10044,27 +10187,40 @@ const GenZir = struct {...@@ -10044,27 +10187,40 @@ const GenZir = struct {
10044 try astgen.extra.ensureUnusedCapacity(10187 try astgen.extra.ensureUnusedCapacity(
10045 gpa,10188 gpa,
10046 @typeInfo(Zir.Inst.Func).Struct.fields.len +10189 @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,
10048 );10192 );
10193 const ret_body_len = if (ret_body.len != 0)
10194 @intCast(u32, ret_body.len)
10195 else
10196 @boolToInt(ret_ref != .none);
1004910197
10050 const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.Func{10198 const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.Func{
10051 .param_block = args.param_block,10199 .param_block = args.param_block,
10052 .ret_body_len = @intCast(u32, ret_ty.len),10200 .ret_body_len = ret_body_len,
10053 .body_len = @intCast(u32, body.len),10201 .body_len = @intCast(u32, body.len),
10054 });10202 });
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 }
10056 astgen.extra.appendSliceAssumeCapacity(body);10210 astgen.extra.appendSliceAssumeCapacity(body);
10057 astgen.extra.appendSliceAssumeCapacity(src_locs);10211 astgen.extra.appendSliceAssumeCapacity(src_locs);
10058 // order is important when unstacking10212
10213 // Order is important when unstacking.
10059 if (args.body_gz) |body_gz| body_gz.unstack();10214 if (args.body_gz) |body_gz| body_gz.unstack();
10060 if (args.ret_gz) |ret_gz| ret_gz.unstack();10215 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
10061 try gz.instructions.ensureUnusedCapacity(gpa, 1);10221 try gz.instructions.ensureUnusedCapacity(gpa, 1);
1006210222
10063 const tag: Zir.Inst.Tag = if (args.is_inferred_error) .func_inferred else .func;10223 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 }
10068 astgen.instructions.appendAssumeCapacity(.{10224 astgen.instructions.appendAssumeCapacity(.{
10069 .tag = tag,10225 .tag = tag,
10070 .data = .{ .pl_node = .{10226 .data = .{ .pl_node = .{
...@@ -10077,6 +10233,12 @@ const GenZir = struct {...@@ -10077,6 +10233,12 @@ const GenZir = struct {
10077 }10233 }
10078 }10234 }
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
10080 fn addVar(gz: *GenZir, args: struct {10242 fn addVar(gz: *GenZir, args: struct {
10081 align_inst: Zir.Inst.Ref,10243 align_inst: Zir.Inst.Ref,
10082 lib_name: u32,10244 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+262-79
...@@ -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),
...@@ -5190,7 +5190,10 @@ fn analyzeCall(...@@ -5190,7 +5190,10 @@ fn analyzeCall(
5190 // on parameters, we must now do the same for the return type as we just did with5190 // on parameters, we must now do the same for the return type as we just did with
5191 // each of the parameters, resolving the return type and providing it to the child5191 // each of the parameters, resolving the return type and providing it to the child
5192 // `Sema` so that it can be used for the `ret_ptr` instruction.5192 // `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);
5194 const ret_ty_src = func_src; // TODO better source location5197 const ret_ty_src = func_src; // TODO better source location
5195 const bare_return_type = try sema.analyzeAsType(&child_block, ret_ty_src, ret_ty_inst);5198 const bare_return_type = try sema.analyzeAsType(&child_block, ret_ty_src, ret_ty_inst);
5196 // Create a fresh inferred error set type for inline/comptime calls.5199 // Create a fresh inferred error set type for inline/comptime calls.
...@@ -6506,9 +6509,34 @@ fn zirFunc(...@@ -6506,9 +6509,34 @@ fn zirFunc(
65066509
6507 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;6510 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
6508 const extra = sema.code.extraData(Zir.Inst.Func, inst_data.payload_index);6511 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
6509 var extra_index = extra.end;6515 var extra_index = extra.end;
6510 const ret_ty_body = sema.code.extra[extra_index..][0..extra.data.ret_body_len];6516
6511 extra_index += ret_ty_body.len;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
6513 var src_locs: Zir.Inst.Func.SrcLocs = undefined;6541 var src_locs: Zir.Inst.Func.SrcLocs = undefined;
6514 const has_body = extra.data.body_len != 0;6542 const has_body = extra.data.body_len != 0;
...@@ -6526,9 +6554,11 @@ fn zirFunc(...@@ -6526,9 +6554,11 @@ fn zirFunc(
6526 block,6554 block,
6527 inst_data.src_node,6555 inst_data.src_node,
6528 inst,6556 inst,
6529 ret_ty_body,6557 0,
6558 target_util.defaultAddressSpace(target, .function),
6559 FuncLinkSection.default,
6530 cc,6560 cc,
6531 Value.@"null",6561 ret_ty,
6532 false,6562 false,
6533 inferred_error_set,6563 inferred_error_set,
6534 false,6564 false,
...@@ -6538,6 +6568,44 @@ fn zirFunc(...@@ -6538,6 +6568,44 @@ fn zirFunc(
6538 );6568 );
6539}6569}
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
6541/// Given a library name, examines if the library name should end up in6609/// Given a library name, examines if the library name should end up in
6542/// `link.File.Options.system_libs` table (for example, libc is always6610/// `link.File.Options.system_libs` table (for example, libc is always
6543/// specified via dedicated flag `link.File.Options.link_libc` instead),6611/// specified via dedicated flag `link.File.Options.link_libc` instead),
...@@ -6601,14 +6669,27 @@ fn handleExternLibName(...@@ -6601,14 +6669,27 @@ fn handleExternLibName(
6601 return sema.gpa.dupeZ(u8, lib_name);6669 return sema.gpa.dupeZ(u8, lib_name);
6602}6670}
66036671
6672const FuncLinkSection = union(enum) {
6673 generic,
6674 default,
6675 explicit: [*:0]const u8,
6676};
6677
6604fn funcCommon(6678fn funcCommon(
6605 sema: *Sema,6679 sema: *Sema,
6606 block: *Block,6680 block: *Block,
6607 src_node_offset: i32,6681 src_node_offset: i32,
6608 func_inst: Zir.Inst.Index,6682 func_inst: Zir.Inst.Index,
6609 ret_ty_body: []const Zir.Inst.Index,6683 /// null means generic poison
6610 cc: std.builtin.CallingConvention,6684 alignment: ?u32,
6611 align_val: Value,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,
6612 var_args: bool,6693 var_args: bool,
6613 inferred_error_set: bool,6694 inferred_error_set: bool,
6614 is_extern: bool,6695 is_extern: bool,
...@@ -6618,42 +6699,15 @@ fn funcCommon(...@@ -6618,42 +6699,15 @@ fn funcCommon(
6618) CompileError!Air.Inst.Ref {6699) CompileError!Air.Inst.Ref {
6619 const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = src_node_offset };6700 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.6702 var is_generic = bare_return_type.tag() == .generic_poison or
6622 // In such case we need to use a generic_poison value for the return type and mark6703 alignment == null or
6623 // the function as generic.6704 address_space == null or
6624 var is_generic = false;6705 section == .generic or
6625 const bare_return_type: Type = ret_ty: {6706 cc == null;
6626 if (ret_ty_body.len == 0) break :ret_ty Type.void;6707 // Check for generic params.
66276708 for (block.params.items) |param| {
6628 const err = err: {6709 if (param.ty.tag() == .generic_poison) is_generic = true;
6629 // Make sure any nested param instructions don't clobber our work.6710 }
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;
66576711
6658 const new_func: *Module.Fn = new_func: {6712 const new_func: *Module.Fn = new_func: {
6659 if (!has_body) break :new_func undefined;6713 if (!has_body) break :new_func undefined;
...@@ -6670,36 +6724,28 @@ fn funcCommon(...@@ -6670,36 +6724,28 @@ fn funcCommon(
6670 errdefer if (maybe_inferred_error_set_node) |node| sema.gpa.destroy(node);6724 errdefer if (maybe_inferred_error_set_node) |node| sema.gpa.destroy(node);
6671 // Note: no need to errdefer since this will still be in its default state at the end of the function.6725 // 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();6727 const target = sema.mod.getTarget();
6674
6675 const fn_ty: Type = fn_ty: {6728 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
6685 // Hot path for some common function types.6729 // Hot path for some common function types.
6686 // TODO can we eliminate some of these Type tag values? seems unnecessarily complicated.6730 // 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 and6731 if (!is_generic and block.params.items.len == 0 and !var_args and !inferred_error_set and
6688 alignment == 0 and !inferred_error_set)6732 alignment.? == 0 and
6733 address_space.? == target_util.defaultAddressSpace(target, .function) and
6734 section == .default)
6689 {6735 {
6690 if (bare_return_type.zigTypeTag() == .NoReturn and cc == .Unspecified) {6736 if (bare_return_type.zigTypeTag() == .NoReturn and cc.? == .Unspecified) {
6691 break :fn_ty Type.initTag(.fn_noreturn_no_args);6737 break :fn_ty Type.initTag(.fn_noreturn_no_args);
6692 }6738 }
66936739
6694 if (bare_return_type.zigTypeTag() == .Void and cc == .Unspecified) {6740 if (bare_return_type.zigTypeTag() == .Void and cc.? == .Unspecified) {
6695 break :fn_ty Type.initTag(.fn_void_no_args);6741 break :fn_ty Type.initTag(.fn_void_no_args);
6696 }6742 }
66976743
6698 if (bare_return_type.zigTypeTag() == .NoReturn and cc == .Naked) {6744 if (bare_return_type.zigTypeTag() == .NoReturn and cc.? == .Naked) {
6699 break :fn_ty Type.initTag(.fn_naked_noreturn_no_args);6745 break :fn_ty Type.initTag(.fn_naked_noreturn_no_args);
6700 }6746 }
67016747
6702 if (bare_return_type.zigTypeTag() == .Void and cc == .C) {6748 if (bare_return_type.zigTypeTag() == .Void and cc.? == .C) {
6703 break :fn_ty Type.initTag(.fn_ccc_void_no_args);6749 break :fn_ty Type.initTag(.fn_ccc_void_no_args);
6704 }6750 }
6705 }6751 }
...@@ -6745,17 +6791,35 @@ fn funcCommon(...@@ -6745,17 +6791,35 @@ fn funcCommon(
6745 });6791 });
6746 };6792 };
67476793
6794 // stage1 bug workaround
6795 const cc_workaround = cc orelse undefined;
6796 const align_workaround = alignment orelse @as(u32, undefined);
6797
6748 break :fn_ty try Type.Tag.function.create(sema.arena, .{6798 break :fn_ty try Type.Tag.function.create(sema.arena, .{
6749 .param_types = param_types,6799 .param_types = param_types,
6750 .comptime_params = comptime_params.ptr,6800 .comptime_params = comptime_params.ptr,
6751 .return_type = return_type,6801 .return_type = return_type,
6752 .cc = cc,6802 .cc = cc_workaround,
6753 .alignment = alignment,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,
6754 .is_var_args = var_args,6808 .is_var_args = var_args,
6755 .is_generic = is_generic,6809 .is_generic = is_generic,
6756 });6810 });
6757 };6811 };
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
6759 if (is_extern) {6823 if (is_extern) {
6760 const new_extern_fn = try sema.gpa.create(Module.ExternFn);6824 const new_extern_fn = try sema.gpa.create(Module.ExternFn);
6761 errdefer sema.gpa.destroy(new_extern_fn);6825 errdefer sema.gpa.destroy(new_extern_fn);
...@@ -16750,16 +16814,20 @@ fn zirVarExtended(...@@ -16750,16 +16814,20 @@ fn zirVarExtended(
16750 return result;16814 return result;
16751}16815}
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 {
16754 const tracy = trace(@src());16818 const tracy = trace(@src());
16755 defer tracy.end();16819 defer tracy.end();
1675616820
16757 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;16821 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
16758 const src = inst_data.src();16822 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 };
16762 const align_src: LazySrcLoc = src; // TODO add a LazySrcLoc that points at align16826 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
16764 var extra_index: usize = extra.end;16832 var extra_index: usize = extra.end;
1676516833
...@@ -16769,22 +16837,135 @@ fn zirFuncExtended(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro...@@ -16769,22 +16837,135 @@ fn zirFuncExtended(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro
16769 break :blk lib_name;16837 break :blk lib_name;
16770 } else null;16838 } 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: {
16773 const cc_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);16935 const cc_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);
16774 extra_index += 1;16936 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 };
16776 break :blk cc_tv.val.toEnum(std.builtin.CallingConvention);16943 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: {16946 const ret_ty: Type = if (extra.data.bits.has_ret_ty_body) blk: {
16780 const align_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);16947 const body_len = sema.code.extra[extra_index];
16781 extra_index += 1;16948 extra_index += 1;
16782 const align_tv = try sema.resolveInstConst(block, align_src, align_ref);16949 const body = sema.code.extra[extra_index..][0..body_len];
16783 break :blk align_tv.val;16950 extra_index += body.len;
16784 } else Value.@"null";
1678516951
16786 const ret_ty_body = sema.code.extra[extra_index..][0..extra.data.ret_body_len];16952 const val = try sema.resolveGenericBody(block, ret_src, body, inst, Type.type);
16787 extra_index += ret_ty_body.len;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
16789 var src_locs: Zir.Inst.Func.SrcLocs = undefined;16970 var src_locs: Zir.Inst.Func.SrcLocs = undefined;
16790 const has_body = extra.data.body_len != 0;16971 const has_body = extra.data.body_len != 0;
...@@ -16801,9 +16982,11 @@ fn zirFuncExtended(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro...@@ -16801,9 +16982,11 @@ fn zirFuncExtended(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro
16801 block,16982 block,
16802 inst_data.src_node,16983 inst_data.src_node,
16803 inst,16984 inst,
16804 ret_ty_body,16985 @"align",
16986 @"addrspace",
16987 @"linksection",
16805 cc,16988 cc,
16806 align_val,16989 ret_ty,
16807 is_var_args,16990 is_var_args,
16808 is_inferred_error,16991 is_inferred_error,
16809 is_extern,16992 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,
...@@ -1062,7 +1062,7 @@ pub const Inst = struct {...@@ -1062,7 +1062,7 @@ pub const Inst = struct {
1062 .field_val_named,1062 .field_val_named,
1063 .func,1063 .func,
1064 .func_inferred,1064 .func_inferred,
1065 .func_extended,1065 .func_fancy,
1066 .has_decl,1066 .has_decl,
1067 .int,1067 .int,
1068 .int_big,1068 .int_big,
...@@ -1346,7 +1346,7 @@ pub const Inst = struct {...@@ -1346,7 +1346,7 @@ pub const Inst = struct {
1346 .field_val_named,1346 .field_val_named,
1347 .func,1347 .func,
1348 .func_inferred,1348 .func_inferred,
1349 .func_extended,1349 .func_fancy,
1350 .has_decl,1350 .has_decl,
1351 .int,1351 .int,
1352 .int_big,1352 .int_big,
...@@ -1599,7 +1599,7 @@ pub const Inst = struct {...@@ -1599,7 +1599,7 @@ pub const Inst = struct {
1599 .field_call_bind = .pl_node,1599 .field_call_bind = .pl_node,
1600 .func = .pl_node,1600 .func = .pl_node,
1601 .func_inferred = .pl_node,1601 .func_inferred = .pl_node,
1602 .func_extended = .pl_node,1602 .func_fancy = .pl_node,
1603 .import = .str_tok,1603 .import = .str_tok,
1604 .int = .int,1604 .int = .int,
1605 .int_big = .str,1605 .int_big = .str,
...@@ -2606,29 +2606,100 @@ pub const Inst = struct {...@@ -2606,29 +2606,100 @@ pub const Inst = struct {
2606 };2606 };
26072607
2608 /// Trailing:2608 /// Trailing:
2609 /// 0. lib_name: u32, // null terminated string index, if has_lib_name is set2609 /// if (ret_body_len == 1) {
2610 /// 1. cc: Ref, // if has_cc is set2610 /// 0. return_type: Ref
2611 /// 2. align: Ref, // if has_align is set2611 /// }
2612 /// 3. return_type: Index // for each ret_body_len2612 /// if (ret_body_len > 1) {
2613 /// 4. body: Index // for each body_len2613 /// 1. return_type: Index // for each ret_body_len
2614 /// 5. src_locs: Func.SrcLocs // if body_len != 02614 /// }
2615 pub const ExtendedFunc = struct {2615 /// 2. body: Index // for each body_len
2616 /// 3. src_locs: SrcLocs // if body_len != 0
2617 pub const Func = struct {
2616 /// If this is 0 it means a void return type.2618 /// If this is 0 it means a void return type.
2619 /// If this is 1 it means return_type is a simple Ref
2617 ret_body_len: u32,2620 ret_body_len: u32,
2618 /// Points to the block that contains the param instructions for this function.2621 /// Points to the block that contains the param instructions for this function.
2619 param_block: Index,2622 param_block: Index,
2620 body_len: u32,2623 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,
2621 bits: Bits,2679 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.
2623 pub const Bits = packed struct {2686 pub const Bits = packed struct {
2624 is_var_args: bool,2687 is_var_args: bool,
2625 is_inferred_error: bool,2688 is_inferred_error: bool,
2626 has_lib_name: bool,
2627 has_cc: bool,
2628 has_align: bool,
2629 is_test: bool,2689 is_test: bool,
2630 is_extern: bool,2690 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,
2632 };2703 };
2633 };2704 };
26342705
...@@ -2650,28 +2721,6 @@ pub const Inst = struct {...@@ -2650,28 +2721,6 @@ pub const Inst = struct {
2650 };2721 };
2651 };2722 };
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
2675 /// This data is stored inside extra, with trailing operands according to `operands_len`.2724 /// This data is stored inside extra, with trailing operands according to `operands_len`.
2676 /// Each operand is a `Ref`.2725 /// Each operand is a `Ref`.
2677 pub const MultiOp = struct {2726 pub const MultiOp = struct {
...@@ -3473,7 +3522,7 @@ pub fn declIterator(zir: Zir, decl_inst: u32) DeclIterator {...@@ -3473,7 +3522,7 @@ pub fn declIterator(zir: Zir, decl_inst: u32) DeclIterator {
3473 switch (tags[decl_inst]) {3522 switch (tags[decl_inst]) {
3474 // Functions are allowed and yield no iterations.3523 // Functions are allowed and yield no iterations.
3475 // There is one case matching this in the extended instruction set below.3524 // 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
3478 .extended => {3527 .extended => {
3479 const extended = datas[decl_inst].extended;3528 const extended = datas[decl_inst].extended;
...@@ -3579,18 +3628,77 @@ fn findDeclsInner(...@@ -3579,18 +3628,77 @@ fn findDeclsInner(
35793628
3580 const inst_data = datas[inst].pl_node;3629 const inst_data = datas[inst].pl_node;
3581 const extra = zir.extraData(Inst.Func, inst_data.payload_index);3630 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];
3583 return zir.findDeclsBody(list, body);3642 return zir.findDeclsBody(list, body);
3584 },3643 },
3585 .func_extended => {3644 .func_fancy => {
3586 try list.append(inst);3645 try list.append(inst);
35873646
3588 const inst_data = datas[inst].pl_node;3647 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);
3590 var extra_index: usize = extra.end;3649 var extra_index: usize = extra.end;
3591 extra_index += @boolToInt(extra.data.bits.has_lib_name);3650 extra_index += @boolToInt(extra.data.bits.has_lib_name);
3592 extra_index += @boolToInt(extra.data.bits.has_cc);3651
3593 extra_index += @boolToInt(extra.data.bits.has_align);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
3594 const body = zir.extra[extra_index..][0..extra.data.body_len];3702 const body = zir.extra[extra_index..][0..extra.data.body_len];
3595 return zir.findDeclsBody(list, body);3703 return zir.findDeclsBody(list, body);
3596 },3704 },
...@@ -3715,6 +3823,7 @@ pub const FnInfo = struct {...@@ -3715,6 +3823,7 @@ pub const FnInfo = struct {
3715 param_body_inst: Inst.Index,3823 param_body_inst: Inst.Index,
3716 ret_ty_body: []const Inst.Index,3824 ret_ty_body: []const Inst.Index,
3717 body: []const Inst.Index,3825 body: []const Inst.Index,
3826 ret_ty_ref: Zir.Inst.Ref,
3718 total_params_len: u32,3827 total_params_len: u32,
3719};3828};
37203829
...@@ -3724,38 +3833,84 @@ pub fn getFnInfo(zir: Zir, fn_inst: Inst.Index) FnInfo {...@@ -3724,38 +3833,84 @@ pub fn getFnInfo(zir: Zir, fn_inst: Inst.Index) FnInfo {
3724 const info: struct {3833 const info: struct {
3725 param_block: Inst.Index,3834 param_block: Inst.Index,
3726 body: []const Inst.Index,3835 body: []const Inst.Index,
3836 ret_ty_ref: Inst.Ref,
3727 ret_ty_body: []const Inst.Index,3837 ret_ty_body: []const Inst.Index,
3728 } = switch (tags[fn_inst]) {3838 } = switch (tags[fn_inst]) {
3729 .func, .func_inferred => blk: {3839 .func, .func_inferred => blk: {
3730 const inst_data = datas[fn_inst].pl_node;3840 const inst_data = datas[fn_inst].pl_node;
3731 const extra = zir.extraData(Inst.Func, inst_data.payload_index);3841 const extra = zir.extraData(Inst.Func, inst_data.payload_index);
3842
3732 var extra_index: usize = extra.end;3843 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];3847 switch (extra.data.ret_body_len) {
3735 extra_index += ret_ty_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
3737 const body = zir.extra[extra_index..][0..extra.data.body_len];3861 const body = zir.extra[extra_index..][0..extra.data.body_len];
3738 extra_index += body.len;3862 extra_index += body.len;
37393863
3740 break :blk .{3864 break :blk .{
3741 .param_block = extra.data.param_block,3865 .param_block = extra.data.param_block,
3866 .ret_ty_ref = ret_ty_ref,
3742 .ret_ty_body = ret_ty_body,3867 .ret_ty_body = ret_ty_body,
3743 .body = body,3868 .body = body,
3744 };3869 };
3745 },3870 },
3746 .func_extended => blk: {3871 .func_fancy => blk: {
3747 const inst_data = datas[fn_inst].pl_node;3872 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
3749 var extra_index: usize = extra.end;3875 var extra_index: usize = extra.end;
3876 var ret_ty_ref: Inst.Ref = .void_type;
3877 var ret_ty_body: []const Inst.Index = &.{};
3878
3750 extra_index += @boolToInt(extra.data.bits.has_lib_name);3879 extra_index += @boolToInt(extra.data.bits.has_lib_name);
3751 extra_index += @boolToInt(extra.data.bits.has_cc);3880 if (extra.data.bits.has_align_body) {
3752 extra_index += @boolToInt(extra.data.bits.has_align);3881 extra_index += zir.extra[extra_index] + 1;
3753 const ret_ty_body = zir.extra[extra_index..][0..extra.data.ret_body_len];3882 } else if (extra.data.bits.has_align_ref) {
3754 extra_index += ret_ty_body.len;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 }
3755 const body = zir.extra[extra_index..][0..extra.data.body_len];3909 const body = zir.extra[extra_index..][0..extra.data.body_len];
3756 extra_index += body.len;3910 extra_index += body.len;
3757 break :blk .{3911 break :blk .{
3758 .param_block = extra.data.param_block,3912 .param_block = extra.data.param_block,
3913 .ret_ty_ref = ret_ty_ref,
3759 .ret_ty_body = ret_ty_body,3914 .ret_ty_body = ret_ty_body,
3760 .body = body,3915 .body = body,
3761 };3916 };
...@@ -3778,6 +3933,7 @@ pub fn getFnInfo(zir: Zir, fn_inst: Inst.Index) FnInfo {...@@ -3778,6 +3933,7 @@ pub fn getFnInfo(zir: Zir, fn_inst: Inst.Index) FnInfo {
3778 .param_body = param_body,3933 .param_body = param_body,
3779 .param_body_inst = info.param_block,3934 .param_body_inst = info.param_block,
3780 .ret_ty_body = info.ret_ty_body,3935 .ret_ty_body = info.ret_ty_body,
3936 .ret_ty_ref = info.ret_ty_ref,
3781 .body = info.body,3937 .body = info.body,
3782 .total_params_len = total_params_len,3938 .total_params_len = total_params_len,
3783 };3939 };
src/print_zir.zig+132-37
...@@ -426,7 +426,7 @@ const Writer = struct {...@@ -426,7 +426,7 @@ const Writer = struct {
426426
427 .func => try self.writeFunc(stream, inst, false),427 .func => try self.writeFunc(stream, inst, false),
428 .func_inferred => try self.writeFunc(stream, inst, true),428 .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
431 .@"unreachable" => try self.writeUnreachable(stream, inst),431 .@"unreachable" => try self.writeUnreachable(stream, inst),
432432
...@@ -1915,10 +1915,24 @@ const Writer = struct {...@@ -1915,10 +1915,24 @@ const Writer = struct {
1915 const inst_data = self.code.instructions.items(.data)[inst].pl_node;1915 const inst_data = self.code.instructions.items(.data)[inst].pl_node;
1916 const src = inst_data.src();1916 const src = inst_data.src();
1917 const extra = self.code.extraData(Zir.Inst.Func, inst_data.payload_index);1917 const extra = self.code.extraData(Zir.Inst.Func, inst_data.payload_index);
1918
1918 var extra_index = extra.end;1919 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];1923 switch (extra.data.ret_body_len) {
1921 extra_index += ret_ty_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
1923 const body = self.code.extra[extra_index..][0..extra.data.body_len];1937 const body = self.code.extra[extra_index..][0..extra.data.body_len];
1924 extra_index += body.len;1938 extra_index += body.len;
...@@ -1929,43 +1943,96 @@ const Writer = struct {...@@ -1929,43 +1943,96 @@ const Writer = struct {
1929 }1943 }
1930 return self.writeFuncCommon(1944 return self.writeFuncCommon(
1931 stream,1945 stream,
1932 ret_ty_body,
1933 inferred_error_set,1946 inferred_error_set,
1934 false,1947 false,
1935 false,1948 false,
1949
1936 .none,1950 .none,
1951 &.{},
1937 .none,1952 .none,
1953 &.{},
1954 .none,
1955 &.{},
1956 .none,
1957 &.{},
1958 ret_ty_ref,
1959 ret_ty_body,
1960
1938 body,1961 body,
1939 src,1962 src,
1940 src_locs,1963 src_locs,
1941 );1964 );
1942 }1965 }
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 {
1945 const inst_data = self.code.instructions.items(.data)[inst].pl_node;1968 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);
1947 const src = inst_data.src();1970 const src = inst_data.src();
19481971
1949 var extra_index: usize = extra.end;1972 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
1950 if (extra.data.bits.has_lib_name) {1984 if (extra.data.bits.has_lib_name) {
1951 const lib_name = self.code.nullTerminatedString(self.code.extra[extra_index]);1985 const lib_name = self.code.nullTerminatedString(self.code.extra[extra_index]);
1952 extra_index += 1;1986 extra_index += 1;
1953 try stream.print("lib_name=\"{}\", ", .{std.zig.fmtEscapes(lib_name)});1987 try stream.print("lib_name=\"{}\", ", .{std.zig.fmtEscapes(lib_name)});
1954 }1988 }
1955 try self.writeFlag(stream, "test, ", extra.data.bits.is_test);1989 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: {1990
1957 const cc = @intToEnum(Zir.Inst.Ref, self.code.extra[extra_index]);1991 if (extra.data.bits.has_align_body) {
1992 const body_len = self.code.extra[extra_index];
1958 extra_index += 1;1993 extra_index += 1;
1959 break :blk cc;1994 align_body = self.code.extra[extra_index..][0..body_len];
1960 };1995 extra_index += align_body.len;
1961 const align_inst: Zir.Inst.Ref = if (!extra.data.bits.has_align) .none else blk: {1996 } else if (extra.data.bits.has_align_ref) {
1962 const align_inst = @intToEnum(Zir.Inst.Ref, self.code.extra[extra_index]);1997 align_ref = @intToEnum(Zir.Inst.Ref, self.code.extra[extra_index]);
1963 extra_index += 1;1998 extra_index += 1;
1964 break :blk align_inst;1999 }
1965 };2000 if (extra.data.bits.has_addrspace_body) {
19662001 const body_len = self.code.extra[extra_index];
1967 const ret_ty_body = self.code.extra[extra_index..][0..extra.data.ret_body_len];2002 extra_index += 1;
1968 extra_index += ret_ty_body.len;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
1970 const body = self.code.extra[extra_index..][0..extra.data.body_len];2037 const body = self.code.extra[extra_index..][0..extra.data.body_len];
1971 extra_index += body.len;2038 extra_index += body.len;
...@@ -1976,12 +2043,19 @@ const Writer = struct {...@@ -1976,12 +2043,19 @@ const Writer = struct {
1976 }2043 }
1977 return self.writeFuncCommon(2044 return self.writeFuncCommon(
1978 stream,2045 stream,
1979 ret_ty_body,
1980 extra.data.bits.is_inferred_error,2046 extra.data.bits.is_inferred_error,
1981 extra.data.bits.is_var_args,2047 extra.data.bits.is_var_args,
1982 extra.data.bits.is_extern,2048 extra.data.bits.is_extern,
1983 cc,2049 align_ref,
1984 align_inst,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,
1985 body,2059 body,
1986 src,2060 src,
1987 src_locs,2061 src_locs,
...@@ -2126,30 +2200,33 @@ const Writer = struct {...@@ -2126,30 +2200,33 @@ const Writer = struct {
2126 fn writeFuncCommon(2200 fn writeFuncCommon(
2127 self: *Writer,2201 self: *Writer,
2128 stream: anytype,2202 stream: anytype,
2129 ret_ty_body: []const Zir.Inst.Index,
2130 inferred_error_set: bool,2203 inferred_error_set: bool,
2131 var_args: bool,2204 var_args: bool,
2132 is_extern: bool,2205 is_extern: bool,
2133 cc: Zir.Inst.Ref,2206 align_ref: Zir.Inst.Ref,
2134 align_inst: 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,
2135 body: []const Zir.Inst.Index,2216 body: []const Zir.Inst.Index,
2136 src: LazySrcLoc,2217 src: LazySrcLoc,
2137 src_locs: Zir.Inst.Func.SrcLocs,2218 src_locs: Zir.Inst.Func.SrcLocs,
2138 ) !void {2219 ) !void {
2139 if (ret_ty_body.len == 0) {2220 try self.writeOptionalInstRefOrBody(stream, "align=", align_ref, align_body);
2140 try stream.writeAll("ret_ty=void");2221 try self.writeOptionalInstRefOrBody(stream, "addrspace=", addrspace_ref, addrspace_body);
2141 } else {2222 try self.writeOptionalInstRefOrBody(stream, "section=", section_ref, section_body);
2142 try stream.writeAll("ret_ty=");2223 try self.writeOptionalInstRefOrBody(stream, "cc=", cc_ref, cc_body);
2143 try self.writeBracedBody(stream, ret_ty_body);2224 try self.writeOptionalInstRefOrBody(stream, "ret_ty=", ret_ty_ref, ret_ty_body);
2144 }2225 try self.writeFlag(stream, "vargs, ", var_args);
21452226 try self.writeFlag(stream, "extern, ", is_extern);
2146 try self.writeOptionalInstRef(stream, ", cc=", cc);2227 try self.writeFlag(stream, "inferror, ", inferred_error_set);
2147 try self.writeOptionalInstRef(stream, ", align=", align_inst);2228
2148 try self.writeFlag(stream, ", vargs", var_args);2229 try stream.writeAll("body=");
2149 try self.writeFlag(stream, ", extern", is_extern);
2150 try self.writeFlag(stream, ", inferror", inferred_error_set);
2151
2152 try stream.writeAll(", body=");
2153 try self.writeBracedBody(stream, body);2230 try self.writeBracedBody(stream, body);
2154 try stream.writeAll(") ");2231 try stream.writeAll(") ");
2155 if (body.len != 0) {2232 if (body.len != 0) {
...@@ -2199,6 +2276,24 @@ const Writer = struct {...@@ -2199,6 +2276,24 @@ const Writer = struct {
2199 try self.writeInstRef(stream, inst);2276 try self.writeInstRef(stream, inst);
2200 }2277 }
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
2202 fn writeFlag(2297 fn writeFlag(
2203 self: *Writer,2298 self: *Writer,
2204 stream: anytype,2299 stream: anytype,
src/type.zig+4
...@@ -6120,6 +6120,10 @@ pub const Type = extern union {...@@ -6120,6 +6120,10 @@ pub const Type = extern union {
6120 cc: std.builtin.CallingConvention,6120 cc: std.builtin.CallingConvention,
6121 is_var_args: bool,6121 is_var_args: bool,
6122 is_generic: bool,6122 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
6124 pub fn paramIsComptime(self: @This(), i: usize) bool {6128 pub fn paramIsComptime(self: @This(), i: usize) bool {
6125 assert(i < self.param_types.len);6129 assert(i < self.param_types.len);
test/behavior/align.zig+31-12
...@@ -334,25 +334,44 @@ fn simple4() align(4) i32 {...@@ -334,25 +334,44 @@ fn simple4() align(4) i32 {
334 return 0x19;334 return 0x19;
335}335}
336336
337test "generic function with align param" {337test "function align expression depends on generic parameter" {
338 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;338 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
339 if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;339 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
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;
343340
344 // function alignment is a compile error on wasm32/wasm64341 // function alignment is a compile error on wasm32/wasm64
345 if (native_arch == .wasm32 or native_arch == .wasm64) return error.SkipZigTest;342 if (native_arch == .wasm32 or native_arch == .wasm64) return error.SkipZigTest;
346 if (native_arch == .thumb) return error.SkipZigTest;343 if (native_arch == .thumb) return error.SkipZigTest;
347344
348 try expect(whyWouldYouEverDoThis(1) == 0x1);345 const S = struct {
349 try expect(whyWouldYouEverDoThis(4) == 0x1);346 fn doTheTest() !void {
350 try expect(whyWouldYouEverDoThis(8) == 0x1);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();
351}358}
352359
353fn whyWouldYouEverDoThis(comptime align_bytes: u8) align(align_bytes) u8 {360test "function callconv expression depends on generic parameter" {
354 _ = align_bytes;361 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
355 return 0x1;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();
356}375}
357376
358test "runtime known array index has best alignment possible" {377test "runtime known array index has best alignment possible" {