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