| author | |
| committer | |
| log | c3ef4ac15f4aa0a4bbf546fb46745d445b97d717 |
| tree | 98158ea6835297c116bbaf2735d32e556e8741c2 |
| parent | c84f5a5f91d31b20b2e187d84fc8a80a190a1212 |
| parent | bd89a73d5289536948b052eb7f052d6de193441b |
| signature |
stage2: add missing data to ZIR encoding of functions7 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 | }; |
| 1207 | 1207 | ||
| 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 | }; |
| 1211 | 1211 | ||
| ... | @@ -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); | ||
| 1239 | 1236 | ||
| 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( |
| 3373 | 3378 | ||
| 3374 | const doc_comment_index = try astgen.docCommentAsString(fn_proto.firstToken()); | 3379 | const doc_comment_index = try astgen.docCommentAsString(fn_proto.firstToken()); |
| 3375 | 3380 | ||
| 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); | ||
| 3379 | 3383 | ||
| 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; |
| 3463 | 3467 | ||
| 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 | }; |
| 3473 | 3507 | ||
| 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/5269 | 3532 | // 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( |
| 3498 | 3540 | ||
| 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 | }; | ||
| 3503 | 3552 | ||
| 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( |
| 3549 | 3604 | ||
| 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 | } |
| 3590 | 3647 | ||
| 3591 | fn globalVarDecl( | 3648 | fn globalVarDecl( |
| ... | @@ -3979,14 +4036,22 @@ fn testDecl( | ... | @@ -3979,14 +4036,22 @@ fn testDecl( |
| 3979 | 4036 | ||
| 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 | } |
| 9932 | 9997 | ||
| 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); | ||
| 9953 | 10037 | ||
| 9954 | try astgen.instructions.ensureUnusedCapacity(gpa, 1); | 10038 | try astgen.instructions.ensureUnusedCapacity(gpa, 1); |
| 9955 | 10039 | ||
| 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 { |
| 9978 | 10062 | ||
| 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 | } |
| 9986 | 10070 | ||
| 9987 | if (args.cc != .none or args.lib_name != 0 or | 10071 | 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 or | 10072 | 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 unstacking | 10164 | |
| 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); |
| 10029 | 10176 | ||
| 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); | ||
| 10049 | 10197 | ||
| 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 unstacking | 10212 | |
| 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); |
| 10062 | 10222 | ||
| 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 | } |
| 10079 | 10235 | ||
| 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 with | 5190 | // 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 child | 5191 | // 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 location | 5197 | 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( |
| 6506 | 6509 | ||
| 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 | }; | ||
| 6512 | 6540 | ||
| 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 | } |
| 6540 | 6570 | ||
| 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) | ||
| 6574 | fn 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 in | 6609 | /// Given a library name, examines if the library name should end up in |
| 6542 | /// `link.File.Options.system_libs` table (for example, libc is always | 6610 | /// `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 | } |
| 6603 | 6671 | ||
| 6672 | const FuncLinkSection = union(enum) { | ||
| 6673 | generic, | ||
| 6674 | default, | ||
| 6675 | explicit: [*:0]const u8, | ||
| 6676 | }; | ||
| 6677 | |||
| 6604 | fn funcCommon( | 6678 | fn 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 }; |
| 6620 | 6701 | ||
| 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 mark | 6703 | 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. |
| 6627 | 6708 | 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; | ||
| 6657 | 6711 | ||
| 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. |
| 6672 | 6726 | ||
| 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 and | 6731 | 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 | } |
| 6693 | 6739 | ||
| 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 | } |
| 6697 | 6743 | ||
| 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 | } |
| 6701 | 6747 | ||
| 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 | }; |
| 6747 | 6793 | ||
| 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 | }; |
| 6758 | 6812 | ||
| 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 | } |
| 16752 | 16816 | ||
| 16753 | fn zirFuncExtended(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 16817 | fn 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(); |
| 16756 | 16820 | ||
| 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(); | ||
| 16760 | 16825 | ||
| 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 align | 16826 | 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 | ||
| 16763 | 16831 | ||
| 16764 | var extra_index: usize = extra.end; | 16832 | var extra_index: usize = extra.end; |
| 16765 | 16833 | ||
| ... | @@ -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; |
| 16771 | 16839 | ||
| 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; |
| 16778 | 16945 | ||
| 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"; | ||
| 16785 | 16951 | ||
| 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; | ||
| 16788 | 16969 | ||
| 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 on | 425 | /// 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 | }; |
| 2607 | 2607 | ||
| 2608 | /// Trailing: | 2608 | /// Trailing: |
| 2609 | /// 0. lib_name: u32, // null terminated string index, if has_lib_name is set | 2609 | /// if (ret_body_len == 1) { |
| 2610 | /// 1. cc: Ref, // if has_cc is set | 2610 | /// 0. return_type: Ref |
| 2611 | /// 2. align: Ref, // if has_align is set | 2611 | /// } |
| 2612 | /// 3. return_type: Index // for each ret_body_len | 2612 | /// if (ret_body_len > 1) { |
| 2613 | /// 4. body: Index // for each body_len | 2613 | /// 1. return_type: Index // for each ret_body_len |
| 2614 | /// 5. src_locs: Func.SrcLocs // if body_len != 0 | 2614 | /// } |
| 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, |
| 2622 | 2680 | ||
| 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 | }; |
| 2634 | 2705 | ||
| ... | @@ -2650,28 +2721,6 @@ pub const Inst = struct { | ... | @@ -2650,28 +2721,6 @@ pub const Inst = struct { |
| 2650 | }; | 2721 | }; |
| 2651 | }; | 2722 | }; |
| 2652 | 2723 | ||
| 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), |
| 3477 | 3526 | ||
| 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( |
| 3579 | 3628 | ||
| 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); |
| 3587 | 3646 | ||
| 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 | }; |
| 3720 | 3829 | ||
| ... | @@ -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 = &.{}; | ||
| 3733 | 3846 | ||
| 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 | } | ||
| 3736 | 3860 | ||
| 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; |
| 3739 | 3863 | ||
| 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 { |
| 426 | 426 | ||
| 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), |
| 430 | 430 | ||
| 431 | .@"unreachable" => try self.writeUnreachable(stream, inst), | 431 | .@"unreachable" => try self.writeUnreachable(stream, inst), |
| 432 | 432 | ||
| ... | @@ -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 = &.{}; | ||
| 1919 | 1922 | ||
| 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 | } | ||
| 1922 | 1936 | ||
| 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 | } |
| 1943 | 1966 | ||
| 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(); |
| 1948 | 1971 | ||
| 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) { |
| 1966 | 2001 | 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 | } | ||
| 1969 | 2036 | ||
| 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); |
| 2145 | 2226 | 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 | } |
| 2201 | 2278 | ||
| 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, | ||
| 6123 | 6127 | ||
| 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 | } |
| 336 | 336 | ||
| 337 | test "generic function with align param" { | 337 | test "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; | ||
| 343 | 340 | ||
| 344 | // function alignment is a compile error on wasm32/wasm64 | 341 | // 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; |
| 347 | 344 | ||
| 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 | } |
| 352 | 359 | ||
| 353 | fn whyWouldYouEverDoThis(comptime align_bytes: u8) align(align_bytes) u8 { | 360 | test "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 | } |
| 357 | 376 | ||
| 358 | test "runtime known array index has best alignment possible" { | 377 | test "runtime known array index has best alignment possible" { |