| author | |
| committer | |
| log | b40a8efb9a72e69cd7e9061fc4c08d5e705b0fbd |
| tree | b62377262318b6f6d76a0b75d43dff106e553a2f |
| parent | 183ee0965fac6322651666834776d9832cc95ddd |
* AstGen: implement `anyframe_literal` and `anyframe_type`.
* Introduce `makeSubBlock` to avoid redundant AstGen code for GenZir
scopes. Allows adding/removing a field without possibility of
accidentally introducing a bug of forgetting to set the new field.
* Add to GenZir `nosuspend_node` and `suspend_node` in preparation for
implementing `suspend` blocks and `nosuspend` blocks.
* AstGen: fix assembly to support clobbers, multiple outputs, and
outputs without `->` syntax.
- `asm` and `asm_volatile` move to `Extended` enum with `small` being
repurposed for a few things. This frees up 2 ZIR tags, 1 of which
is used in this commit and 1 is leftover.
* AstGen: fix `simple_types` incorrectly having multiple conflicting
values for "undefined" and "null".
- Also add "anyframe" to `simple_types`.
* Add `anyframe_type` to type.zig, value.zig and `Zir.Inst.Ref`.
- Also add i128 and u128 types to `Zir.Inst.Ref` and `simple_types`.
* Sema/Zir: Fix incorrect math causing the function body to be messed
up for Extended-encoded functions.
* Zir: support `i32` fields for "extra" payloads.6 files changed, 513 insertions(+), 364 deletions(-)
src/AstGen.zig+154-264| ... | ... | @@ -723,8 +723,12 @@ pub fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) Inn |
| 723 | 723 | }, |
| 724 | 724 | .enum_literal => return simpleStrTok(gz, scope, rl, main_tokens[node], node, .enum_literal), |
| 725 | 725 | .error_value => return simpleStrTok(gz, scope, rl, node_datas[node].rhs, node, .error_value), |
| 726 | .anyframe_literal => return astgen.failNode(node, "async and related features are not yet supported", .{}), | |
| 727 | .anyframe_type => return astgen.failNode(node, "async and related features are not yet supported", .{}), | |
| 726 | .anyframe_literal => return rvalue(gz, scope, rl, .anyframe_type, node), | |
| 727 | .anyframe_type => { | |
| 728 | const return_type = try typeExpr(gz, scope, node_datas[node].rhs); | |
| 729 | const result = try gz.addUnNode(.anyframe_type, return_type, node); | |
| 730 | return rvalue(gz, scope, rl, result, node); | |
| 731 | }, | |
| 728 | 732 | .@"catch" => { |
| 729 | 733 | const catch_token = main_tokens[node]; |
| 730 | 734 | const payload_token: ?ast.TokenIndex = if (token_tags[catch_token + 1] == .pipe) |
| ... | ... | @@ -1546,18 +1550,10 @@ fn labeledBlockExpr( |
| 1546 | 1550 | const block_inst = try gz.addBlock(zir_tag, block_node); |
| 1547 | 1551 | try gz.instructions.append(astgen.gpa, block_inst); |
| 1548 | 1552 | |
| 1549 | var block_scope: GenZir = .{ | |
| 1550 | .parent = parent_scope, | |
| 1551 | .decl_node_index = gz.decl_node_index, | |
| 1552 | .astgen = gz.astgen, | |
| 1553 | .force_comptime = gz.force_comptime, | |
| 1554 | .ref_start_index = gz.ref_start_index, | |
| 1555 | .instructions = .{}, | |
| 1556 | // TODO @as here is working around a stage1 miscompilation bug :( | |
| 1557 | .label = @as(?GenZir.Label, GenZir.Label{ | |
| 1558 | .token = label_token, | |
| 1559 | .block_inst = block_inst, | |
| 1560 | }), | |
| 1553 | var block_scope = gz.makeSubBlock(parent_scope); | |
| 1554 | block_scope.label = GenZir.Label{ | |
| 1555 | .token = label_token, | |
| 1556 | .block_inst = block_inst, | |
| 1561 | 1557 | }; |
| 1562 | 1558 | block_scope.setBreakResultLoc(rl); |
| 1563 | 1559 | defer block_scope.instructions.deinit(astgen.gpa); |
| ... | ... | @@ -1695,10 +1691,9 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: ast.Node.Index) Inner |
| 1695 | 1691 | .array_type_sentinel, |
| 1696 | 1692 | .elem_type, |
| 1697 | 1693 | .indexable_ptr_len, |
| 1694 | .anyframe_type, | |
| 1698 | 1695 | .as, |
| 1699 | 1696 | .as_node, |
| 1700 | .@"asm", | |
| 1701 | .asm_volatile, | |
| 1702 | 1697 | .bit_and, |
| 1703 | 1698 | .bitcast, |
| 1704 | 1699 | .bitcast_result_ptr, |
| ... | ... | @@ -2095,13 +2090,7 @@ fn varDecl( |
| 2095 | 2090 | |
| 2096 | 2091 | // Detect whether the initialization expression actually uses the |
| 2097 | 2092 | // result location pointer. |
| 2098 | var init_scope: GenZir = .{ | |
| 2099 | .parent = scope, | |
| 2100 | .decl_node_index = gz.decl_node_index, | |
| 2101 | .force_comptime = gz.force_comptime, | |
| 2102 | .ref_start_index = gz.ref_start_index, | |
| 2103 | .astgen = astgen, | |
| 2104 | }; | |
| 2093 | var init_scope = gz.makeSubBlock(scope); | |
| 2105 | 2094 | defer init_scope.instructions.deinit(gpa); |
| 2106 | 2095 | |
| 2107 | 2096 | var resolve_inferred_alloc: Zir.Inst.Ref = .none; |
| ... | ... | @@ -3778,14 +3767,7 @@ fn tryExpr( |
| 3778 | 3767 | return astgen.failNode(node, "invalid 'try' outside function scope", .{}); |
| 3779 | 3768 | }; |
| 3780 | 3769 | |
| 3781 | var block_scope: GenZir = .{ | |
| 3782 | .parent = scope, | |
| 3783 | .decl_node_index = parent_gz.decl_node_index, | |
| 3784 | .astgen = astgen, | |
| 3785 | .force_comptime = parent_gz.force_comptime, | |
| 3786 | .ref_start_index = parent_gz.ref_start_index, | |
| 3787 | .instructions = .{}, | |
| 3788 | }; | |
| 3770 | var block_scope = parent_gz.makeSubBlock(scope); | |
| 3789 | 3771 | block_scope.setBreakResultLoc(rl); |
| 3790 | 3772 | defer block_scope.instructions.deinit(astgen.gpa); |
| 3791 | 3773 | |
| ... | ... | @@ -3811,28 +3793,14 @@ fn tryExpr( |
| 3811 | 3793 | try parent_gz.instructions.append(astgen.gpa, block); |
| 3812 | 3794 | try block_scope.setBlockBody(block); |
| 3813 | 3795 | |
| 3814 | var then_scope: GenZir = .{ | |
| 3815 | .parent = scope, | |
| 3816 | .decl_node_index = parent_gz.decl_node_index, | |
| 3817 | .astgen = astgen, | |
| 3818 | .force_comptime = block_scope.force_comptime, | |
| 3819 | .ref_start_index = parent_gz.ref_start_index, | |
| 3820 | .instructions = .{}, | |
| 3821 | }; | |
| 3796 | var then_scope = parent_gz.makeSubBlock(scope); | |
| 3822 | 3797 | defer then_scope.instructions.deinit(astgen.gpa); |
| 3823 | 3798 | |
| 3824 | 3799 | const err_code = try then_scope.addUnNode(err_ops[1], operand, node); |
| 3825 | 3800 | try genDefers(&then_scope, &fn_block.base, scope, err_code); |
| 3826 | 3801 | const then_result = try then_scope.addUnNode(.ret_node, err_code, node); |
| 3827 | 3802 | |
| 3828 | var else_scope: GenZir = .{ | |
| 3829 | .parent = scope, | |
| 3830 | .decl_node_index = parent_gz.decl_node_index, | |
| 3831 | .astgen = astgen, | |
| 3832 | .force_comptime = block_scope.force_comptime, | |
| 3833 | .ref_start_index = parent_gz.ref_start_index, | |
| 3834 | .instructions = .{}, | |
| 3835 | }; | |
| 3803 | var else_scope = parent_gz.makeSubBlock(scope); | |
| 3836 | 3804 | defer else_scope.instructions.deinit(astgen.gpa); |
| 3837 | 3805 | |
| 3838 | 3806 | block_scope.break_count += 1; |
| ... | ... | @@ -3878,14 +3846,7 @@ fn orelseCatchExpr( |
| 3878 | 3846 | const astgen = parent_gz.astgen; |
| 3879 | 3847 | const tree = &astgen.file.tree; |
| 3880 | 3848 | |
| 3881 | var block_scope: GenZir = .{ | |
| 3882 | .parent = scope, | |
| 3883 | .decl_node_index = parent_gz.decl_node_index, | |
| 3884 | .astgen = astgen, | |
| 3885 | .force_comptime = parent_gz.force_comptime, | |
| 3886 | .ref_start_index = parent_gz.ref_start_index, | |
| 3887 | .instructions = .{}, | |
| 3888 | }; | |
| 3849 | var block_scope = parent_gz.makeSubBlock(scope); | |
| 3889 | 3850 | block_scope.setBreakResultLoc(rl); |
| 3890 | 3851 | defer block_scope.instructions.deinit(astgen.gpa); |
| 3891 | 3852 | |
| ... | ... | @@ -3906,14 +3867,7 @@ fn orelseCatchExpr( |
| 3906 | 3867 | try parent_gz.instructions.append(astgen.gpa, block); |
| 3907 | 3868 | try block_scope.setBlockBody(block); |
| 3908 | 3869 | |
| 3909 | var then_scope: GenZir = .{ | |
| 3910 | .parent = scope, | |
| 3911 | .decl_node_index = parent_gz.decl_node_index, | |
| 3912 | .astgen = astgen, | |
| 3913 | .force_comptime = block_scope.force_comptime, | |
| 3914 | .ref_start_index = parent_gz.ref_start_index, | |
| 3915 | .instructions = .{}, | |
| 3916 | }; | |
| 3870 | var then_scope = parent_gz.makeSubBlock(scope); | |
| 3917 | 3871 | defer then_scope.instructions.deinit(astgen.gpa); |
| 3918 | 3872 | |
| 3919 | 3873 | var err_val_scope: Scope.LocalVal = undefined; |
| ... | ... | @@ -3939,14 +3893,7 @@ fn orelseCatchExpr( |
| 3939 | 3893 | // instructions into place until we know whether to keep store_to_block_ptr |
| 3940 | 3894 | // instructions or not. |
| 3941 | 3895 | |
| 3942 | var else_scope: GenZir = .{ | |
| 3943 | .parent = scope, | |
| 3944 | .decl_node_index = parent_gz.decl_node_index, | |
| 3945 | .astgen = astgen, | |
| 3946 | .force_comptime = block_scope.force_comptime, | |
| 3947 | .ref_start_index = parent_gz.ref_start_index, | |
| 3948 | .instructions = .{}, | |
| 3949 | }; | |
| 3896 | var else_scope = parent_gz.makeSubBlock(scope); | |
| 3950 | 3897 | defer else_scope.instructions.deinit(astgen.gpa); |
| 3951 | 3898 | |
| 3952 | 3899 | // This could be a pointer or value depending on `unwrap_op`. |
| ... | ... | @@ -4140,13 +4087,7 @@ fn boolBinOp( |
| 4140 | 4087 | const lhs = try expr(gz, scope, bool_rl, node_datas[node].lhs); |
| 4141 | 4088 | const bool_br = try gz.addBoolBr(zir_tag, lhs); |
| 4142 | 4089 | |
| 4143 | var rhs_scope: GenZir = .{ | |
| 4144 | .parent = scope, | |
| 4145 | .decl_node_index = gz.decl_node_index, | |
| 4146 | .astgen = gz.astgen, | |
| 4147 | .force_comptime = gz.force_comptime, | |
| 4148 | .ref_start_index = gz.ref_start_index, | |
| 4149 | }; | |
| 4090 | var rhs_scope = gz.makeSubBlock(scope); | |
| 4150 | 4091 | defer rhs_scope.instructions.deinit(gz.astgen.gpa); |
| 4151 | 4092 | const rhs = try expr(&rhs_scope, &rhs_scope.base, bool_rl, node_datas[node].rhs); |
| 4152 | 4093 | _ = try rhs_scope.addBreak(.break_inline, bool_br, rhs); |
| ... | ... | @@ -4167,14 +4108,7 @@ fn ifExpr( |
| 4167 | 4108 | const tree = &astgen.file.tree; |
| 4168 | 4109 | const token_tags = tree.tokens.items(.tag); |
| 4169 | 4110 | |
| 4170 | var block_scope: GenZir = .{ | |
| 4171 | .parent = scope, | |
| 4172 | .decl_node_index = parent_gz.decl_node_index, | |
| 4173 | .astgen = astgen, | |
| 4174 | .force_comptime = parent_gz.force_comptime, | |
| 4175 | .ref_start_index = parent_gz.ref_start_index, | |
| 4176 | .instructions = .{}, | |
| 4177 | }; | |
| 4111 | var block_scope = parent_gz.makeSubBlock(scope); | |
| 4178 | 4112 | block_scope.setBreakResultLoc(rl); |
| 4179 | 4113 | defer block_scope.instructions.deinit(astgen.gpa); |
| 4180 | 4114 | |
| ... | ... | @@ -4218,14 +4152,7 @@ fn ifExpr( |
| 4218 | 4152 | try parent_gz.instructions.append(astgen.gpa, block); |
| 4219 | 4153 | try block_scope.setBlockBody(block); |
| 4220 | 4154 | |
| 4221 | var then_scope: GenZir = .{ | |
| 4222 | .parent = scope, | |
| 4223 | .decl_node_index = parent_gz.decl_node_index, | |
| 4224 | .astgen = astgen, | |
| 4225 | .force_comptime = block_scope.force_comptime, | |
| 4226 | .ref_start_index = parent_gz.ref_start_index, | |
| 4227 | .instructions = .{}, | |
| 4228 | }; | |
| 4155 | var then_scope = parent_gz.makeSubBlock(scope); | |
| 4229 | 4156 | defer then_scope.instructions.deinit(astgen.gpa); |
| 4230 | 4157 | |
| 4231 | 4158 | var payload_val_scope: Scope.LocalVal = undefined; |
| ... | ... | @@ -4273,14 +4200,7 @@ fn ifExpr( |
| 4273 | 4200 | // instructions into place until we know whether to keep store_to_block_ptr |
| 4274 | 4201 | // instructions or not. |
| 4275 | 4202 | |
| 4276 | var else_scope: GenZir = .{ | |
| 4277 | .parent = scope, | |
| 4278 | .decl_node_index = parent_gz.decl_node_index, | |
| 4279 | .astgen = astgen, | |
| 4280 | .force_comptime = block_scope.force_comptime, | |
| 4281 | .ref_start_index = parent_gz.ref_start_index, | |
| 4282 | .instructions = .{}, | |
| 4283 | }; | |
| 4203 | var else_scope = parent_gz.makeSubBlock(scope); | |
| 4284 | 4204 | defer else_scope.instructions.deinit(astgen.gpa); |
| 4285 | 4205 | |
| 4286 | 4206 | const else_node = if_full.ast.else_expr; |
| ... | ... | @@ -4424,25 +4344,11 @@ fn whileExpr( |
| 4424 | 4344 | const loop_block = try parent_gz.addBlock(loop_tag, node); |
| 4425 | 4345 | try parent_gz.instructions.append(astgen.gpa, loop_block); |
| 4426 | 4346 | |
| 4427 | var loop_scope: GenZir = .{ | |
| 4428 | .parent = scope, | |
| 4429 | .decl_node_index = parent_gz.decl_node_index, | |
| 4430 | .astgen = astgen, | |
| 4431 | .force_comptime = parent_gz.force_comptime, | |
| 4432 | .ref_start_index = parent_gz.ref_start_index, | |
| 4433 | .instructions = .{}, | |
| 4434 | }; | |
| 4347 | var loop_scope = parent_gz.makeSubBlock(scope); | |
| 4435 | 4348 | loop_scope.setBreakResultLoc(rl); |
| 4436 | 4349 | defer loop_scope.instructions.deinit(astgen.gpa); |
| 4437 | 4350 | |
| 4438 | var continue_scope: GenZir = .{ | |
| 4439 | .parent = &loop_scope.base, | |
| 4440 | .decl_node_index = parent_gz.decl_node_index, | |
| 4441 | .astgen = astgen, | |
| 4442 | .force_comptime = loop_scope.force_comptime, | |
| 4443 | .ref_start_index = parent_gz.ref_start_index, | |
| 4444 | .instructions = .{}, | |
| 4445 | }; | |
| 4351 | var continue_scope = parent_gz.makeSubBlock(&loop_scope.base); | |
| 4446 | 4352 | defer continue_scope.instructions.deinit(astgen.gpa); |
| 4447 | 4353 | |
| 4448 | 4354 | const payload_is_ref = if (while_full.payload_token) |payload_token| |
| ... | ... | @@ -4505,14 +4411,7 @@ fn whileExpr( |
| 4505 | 4411 | }); |
| 4506 | 4412 | } |
| 4507 | 4413 | |
| 4508 | var then_scope: GenZir = .{ | |
| 4509 | .parent = &continue_scope.base, | |
| 4510 | .decl_node_index = parent_gz.decl_node_index, | |
| 4511 | .astgen = astgen, | |
| 4512 | .force_comptime = continue_scope.force_comptime, | |
| 4513 | .ref_start_index = parent_gz.ref_start_index, | |
| 4514 | .instructions = .{}, | |
| 4515 | }; | |
| 4414 | var then_scope = parent_gz.makeSubBlock(&continue_scope.base); | |
| 4516 | 4415 | defer then_scope.instructions.deinit(astgen.gpa); |
| 4517 | 4416 | |
| 4518 | 4417 | var payload_val_scope: Scope.LocalVal = undefined; |
| ... | ... | @@ -4557,14 +4456,7 @@ fn whileExpr( |
| 4557 | 4456 | loop_scope.break_count += 1; |
| 4558 | 4457 | const then_result = try expr(&then_scope, then_sub_scope, loop_scope.break_result_loc, while_full.ast.then_expr); |
| 4559 | 4458 | |
| 4560 | var else_scope: GenZir = .{ | |
| 4561 | .parent = &continue_scope.base, | |
| 4562 | .decl_node_index = parent_gz.decl_node_index, | |
| 4563 | .astgen = astgen, | |
| 4564 | .force_comptime = continue_scope.force_comptime, | |
| 4565 | .ref_start_index = parent_gz.ref_start_index, | |
| 4566 | .instructions = .{}, | |
| 4567 | }; | |
| 4459 | var else_scope = parent_gz.makeSubBlock(&continue_scope.base); | |
| 4568 | 4460 | defer else_scope.instructions.deinit(astgen.gpa); |
| 4569 | 4461 | |
| 4570 | 4462 | const else_node = while_full.ast.else_expr; |
| ... | ... | @@ -4659,25 +4551,11 @@ fn forExpr( |
| 4659 | 4551 | const loop_block = try parent_gz.addBlock(loop_tag, node); |
| 4660 | 4552 | try parent_gz.instructions.append(astgen.gpa, loop_block); |
| 4661 | 4553 | |
| 4662 | var loop_scope: GenZir = .{ | |
| 4663 | .parent = scope, | |
| 4664 | .decl_node_index = parent_gz.decl_node_index, | |
| 4665 | .astgen = astgen, | |
| 4666 | .force_comptime = parent_gz.force_comptime, | |
| 4667 | .ref_start_index = parent_gz.ref_start_index, | |
| 4668 | .instructions = .{}, | |
| 4669 | }; | |
| 4554 | var loop_scope = parent_gz.makeSubBlock(scope); | |
| 4670 | 4555 | loop_scope.setBreakResultLoc(rl); |
| 4671 | 4556 | defer loop_scope.instructions.deinit(astgen.gpa); |
| 4672 | 4557 | |
| 4673 | var cond_scope: GenZir = .{ | |
| 4674 | .parent = &loop_scope.base, | |
| 4675 | .decl_node_index = parent_gz.decl_node_index, | |
| 4676 | .astgen = astgen, | |
| 4677 | .force_comptime = loop_scope.force_comptime, | |
| 4678 | .ref_start_index = parent_gz.ref_start_index, | |
| 4679 | .instructions = .{}, | |
| 4680 | }; | |
| 4558 | var cond_scope = parent_gz.makeSubBlock(&loop_scope.base); | |
| 4681 | 4559 | defer cond_scope.instructions.deinit(astgen.gpa); |
| 4682 | 4560 | |
| 4683 | 4561 | // check condition i < array_expr.len |
| ... | ... | @@ -4714,14 +4592,7 @@ fn forExpr( |
| 4714 | 4592 | }); |
| 4715 | 4593 | } |
| 4716 | 4594 | |
| 4717 | var then_scope: GenZir = .{ | |
| 4718 | .parent = &cond_scope.base, | |
| 4719 | .decl_node_index = parent_gz.decl_node_index, | |
| 4720 | .astgen = astgen, | |
| 4721 | .force_comptime = cond_scope.force_comptime, | |
| 4722 | .ref_start_index = parent_gz.ref_start_index, | |
| 4723 | .instructions = .{}, | |
| 4724 | }; | |
| 4595 | var then_scope = parent_gz.makeSubBlock(&cond_scope.base); | |
| 4725 | 4596 | defer then_scope.instructions.deinit(astgen.gpa); |
| 4726 | 4597 | |
| 4727 | 4598 | var payload_val_scope: Scope.LocalVal = undefined; |
| ... | ... | @@ -4773,14 +4644,7 @@ fn forExpr( |
| 4773 | 4644 | loop_scope.break_count += 1; |
| 4774 | 4645 | const then_result = try expr(&then_scope, then_sub_scope, loop_scope.break_result_loc, for_full.ast.then_expr); |
| 4775 | 4646 | |
| 4776 | var else_scope: GenZir = .{ | |
| 4777 | .parent = &cond_scope.base, | |
| 4778 | .decl_node_index = parent_gz.decl_node_index, | |
| 4779 | .astgen = astgen, | |
| 4780 | .force_comptime = cond_scope.force_comptime, | |
| 4781 | .ref_start_index = parent_gz.ref_start_index, | |
| 4782 | .instructions = .{}, | |
| 4783 | }; | |
| 4647 | var else_scope = parent_gz.makeSubBlock(&cond_scope.base); | |
| 4784 | 4648 | defer else_scope.instructions.deinit(astgen.gpa); |
| 4785 | 4649 | |
| 4786 | 4650 | const else_node = for_full.ast.else_expr; |
| ... | ... | @@ -5076,14 +4940,7 @@ fn switchExpr( |
| 5076 | 4940 | var multi_cases_payload = ArrayListUnmanaged(u32){}; |
| 5077 | 4941 | defer multi_cases_payload.deinit(gpa); |
| 5078 | 4942 | |
| 5079 | var block_scope: GenZir = .{ | |
| 5080 | .parent = scope, | |
| 5081 | .decl_node_index = parent_gz.decl_node_index, | |
| 5082 | .astgen = astgen, | |
| 5083 | .force_comptime = parent_gz.force_comptime, | |
| 5084 | .ref_start_index = parent_gz.ref_start_index, | |
| 5085 | .instructions = .{}, | |
| 5086 | }; | |
| 4943 | var block_scope = parent_gz.makeSubBlock(scope); | |
| 5087 | 4944 | block_scope.setBreakResultLoc(rl); |
| 5088 | 4945 | defer block_scope.instructions.deinit(gpa); |
| 5089 | 4946 | |
| ... | ... | @@ -5091,14 +4948,7 @@ fn switchExpr( |
| 5091 | 4948 | const switch_block = try parent_gz.addBlock(undefined, switch_node); |
| 5092 | 4949 | |
| 5093 | 4950 | // We re-use this same scope for all cases, including the special prong, if any. |
| 5094 | var case_scope: GenZir = .{ | |
| 5095 | .parent = &block_scope.base, | |
| 5096 | .decl_node_index = parent_gz.decl_node_index, | |
| 5097 | .astgen = astgen, | |
| 5098 | .force_comptime = parent_gz.force_comptime, | |
| 5099 | .ref_start_index = parent_gz.ref_start_index, | |
| 5100 | .instructions = .{}, | |
| 5101 | }; | |
| 4951 | var case_scope = parent_gz.makeSubBlock(&block_scope.base); | |
| 5102 | 4952 | defer case_scope.instructions.deinit(gpa); |
| 5103 | 4953 | |
| 5104 | 4954 | // Do the else/`_` first because it goes first in the payload. |
| ... | ... | @@ -5846,57 +5696,109 @@ fn asmExpr( |
| 5846 | 5696 | const tree = &astgen.file.tree; |
| 5847 | 5697 | const main_tokens = tree.nodes.items(.main_token); |
| 5848 | 5698 | const node_datas = tree.nodes.items(.data); |
| 5699 | const token_tags = tree.tokens.items(.tag); | |
| 5849 | 5700 | |
| 5850 | 5701 | const asm_source = try comptimeExpr(gz, scope, .{ .ty = .const_slice_u8_type }, full.ast.template); |
| 5851 | 5702 | |
| 5852 | 5703 | // See https://github.com/ziglang/zig/issues/215 and related issues discussing |
| 5853 | // possible inline assembly improvements. Until this is settled, I am avoiding | |
| 5854 | // potentially wasting time implementing status quo assembly that is not used by | |
| 5855 | // any of the standard library. | |
| 5856 | if (full.outputs.len > 1) { | |
| 5857 | return astgen.failNode(node, "TODO more than 1 asm output", .{}); | |
| 5704 | // possible inline assembly improvements. Until then here is status quo AstGen | |
| 5705 | // for assembly syntax. It's used by std lib crypto aesni.zig. | |
| 5706 | ||
| 5707 | if (full.outputs.len > 32) { | |
| 5708 | return astgen.failNode(full.outputs[32], "too many asm outputs", .{}); | |
| 5858 | 5709 | } |
| 5859 | const output: struct { | |
| 5860 | ty: Zir.Inst.Ref = .none, | |
| 5861 | constraint: u32 = 0, | |
| 5862 | } = if (full.outputs.len == 0) .{} else blk: { | |
| 5863 | const output_node = full.outputs[0]; | |
| 5864 | const out_type_node = node_datas[output_node].lhs; | |
| 5865 | if (out_type_node == 0) { | |
| 5866 | return astgen.failNode(out_type_node, "TODO asm with non -> output", .{}); | |
| 5710 | var outputs_buffer: [32]Zir.Inst.Asm.Output = undefined; | |
| 5711 | const outputs = outputs_buffer[0..full.outputs.len]; | |
| 5712 | ||
| 5713 | var output_type_bits: u32 = 0; | |
| 5714 | ||
| 5715 | for (full.outputs) |output_node, i| { | |
| 5716 | const symbolic_name = main_tokens[output_node]; | |
| 5717 | const name = try gz.identAsString(symbolic_name); | |
| 5718 | const constraint_token = symbolic_name + 2; | |
| 5719 | const constraint = (try gz.strLitAsString(constraint_token)).index; | |
| 5720 | const has_arrow = token_tags[symbolic_name + 4] == .arrow; | |
| 5721 | if (has_arrow) { | |
| 5722 | output_type_bits |= @as(u32, 1) << @intCast(u5, i); | |
| 5723 | const out_type_node = node_datas[output_node].lhs; | |
| 5724 | const out_type_inst = try typeExpr(gz, scope, out_type_node); | |
| 5725 | outputs[i] = .{ | |
| 5726 | .name = name, | |
| 5727 | .constraint = constraint, | |
| 5728 | .operand = out_type_inst, | |
| 5729 | }; | |
| 5730 | } else { | |
| 5731 | const ident_token = symbolic_name + 4; | |
| 5732 | const str_index = try gz.identAsString(ident_token); | |
| 5733 | // TODO this needs extra code for local variables. Have a look at #215 and related | |
| 5734 | // issues and decide how to handle outputs. Do we want this to be identifiers? | |
| 5735 | // Or maybe we want to force this to be expressions with a pointer type. | |
| 5736 | // Until that is figured out this is only hooked up for referencing Decls. | |
| 5737 | const operand = try gz.addStrTok(.decl_ref, str_index, ident_token); | |
| 5738 | outputs[i] = .{ | |
| 5739 | .name = name, | |
| 5740 | .constraint = constraint, | |
| 5741 | .operand = operand, | |
| 5742 | }; | |
| 5867 | 5743 | } |
| 5868 | const constraint_token = main_tokens[output_node] + 2; | |
| 5869 | break :blk .{ | |
| 5870 | .ty = try typeExpr(gz, scope, out_type_node), | |
| 5871 | .constraint = (try gz.strLitAsString(constraint_token)).index, | |
| 5872 | }; | |
| 5873 | }; | |
| 5744 | } | |
| 5874 | 5745 | |
| 5875 | const constraints = try arena.alloc(u32, full.inputs.len); | |
| 5876 | const args = try arena.alloc(Zir.Inst.Ref, full.inputs.len); | |
| 5746 | if (full.inputs.len > 32) { | |
| 5747 | return astgen.failNode(full.inputs[32], "too many asm inputs", .{}); | |
| 5748 | } | |
| 5749 | var inputs_buffer: [32]Zir.Inst.Asm.Input = undefined; | |
| 5750 | const inputs = inputs_buffer[0..full.inputs.len]; | |
| 5751 | ||
| 5752 | for (full.inputs) |input_node, i| { | |
| 5753 | const symbolic_name = main_tokens[input_node]; | |
| 5754 | const name = try gz.identAsString(symbolic_name); | |
| 5755 | const constraint_token = symbolic_name + 2; | |
| 5756 | const constraint = (try gz.strLitAsString(constraint_token)).index; | |
| 5757 | const has_arrow = token_tags[symbolic_name + 4] == .arrow; | |
| 5758 | const operand = try expr(gz, scope, .{ .ty = .usize_type }, node_datas[input_node].lhs); | |
| 5759 | inputs[i] = .{ | |
| 5760 | .name = name, | |
| 5761 | .constraint = constraint, | |
| 5762 | .operand = operand, | |
| 5763 | }; | |
| 5764 | } | |
| 5877 | 5765 | |
| 5878 | for (full.inputs) |input, i| { | |
| 5879 | const constraint_token = main_tokens[input] + 2; | |
| 5880 | constraints[i] = (try gz.strLitAsString(constraint_token)).index; | |
| 5881 | args[i] = try expr(gz, scope, .{ .ty = .usize_type }, node_datas[input].lhs); | |
| 5766 | var clobbers_buffer: [32]u32 = undefined; | |
| 5767 | var clobber_i: usize = 0; | |
| 5768 | if (full.first_clobber) |first_clobber| clobbers: { | |
| 5769 | // asm ("foo" ::: "a", "b") | |
| 5770 | // asm ("foo" ::: "a", "b",) | |
| 5771 | var tok_i = first_clobber; | |
| 5772 | while (true) : (tok_i += 1) { | |
| 5773 | if (clobber_i >= clobbers_buffer.len) { | |
| 5774 | return astgen.failTok(tok_i, "too many asm clobbers", .{}); | |
| 5775 | } | |
| 5776 | clobbers_buffer[clobber_i] = (try gz.strLitAsString(tok_i)).index; | |
| 5777 | clobber_i += 1; | |
| 5778 | tok_i += 1; | |
| 5779 | switch (token_tags[tok_i]) { | |
| 5780 | .r_paren => break :clobbers, | |
| 5781 | .comma => { | |
| 5782 | if (token_tags[tok_i + 1] == .r_paren) { | |
| 5783 | break :clobbers; | |
| 5784 | } else { | |
| 5785 | continue; | |
| 5786 | } | |
| 5787 | }, | |
| 5788 | else => unreachable, | |
| 5789 | } | |
| 5790 | } | |
| 5882 | 5791 | } |
| 5883 | 5792 | |
| 5884 | const tag: Zir.Inst.Tag = if (full.volatile_token != null) .asm_volatile else .@"asm"; | |
| 5885 | const result = try gz.addPlNode(tag, node, Zir.Inst.Asm{ | |
| 5793 | const result = try gz.addAsm(.{ | |
| 5794 | .node = node, | |
| 5886 | 5795 | .asm_source = asm_source, |
| 5887 | .output_type = output.ty, | |
| 5888 | .args_len = @intCast(u32, full.inputs.len), | |
| 5889 | .clobbers_len = 0, // TODO implement asm clobbers | |
| 5796 | .is_volatile = full.volatile_token != null, | |
| 5797 | .output_type_bits = output_type_bits, | |
| 5798 | .outputs = outputs, | |
| 5799 | .inputs = inputs, | |
| 5800 | .clobbers = clobbers_buffer[0..clobber_i], | |
| 5890 | 5801 | }); |
| 5891 | ||
| 5892 | try astgen.extra.ensureCapacity(astgen.gpa, astgen.extra.items.len + | |
| 5893 | args.len + constraints.len + @boolToInt(output.ty != .none)); | |
| 5894 | if (output.ty != .none) { | |
| 5895 | astgen.extra.appendAssumeCapacity(output.constraint); | |
| 5896 | } | |
| 5897 | astgen.appendRefsAssumeCapacity(args); | |
| 5898 | astgen.extra.appendSliceAssumeCapacity(constraints); | |
| 5899 | ||
| 5900 | 5802 | return rvalue(gz, scope, rl, result, node); |
| 5901 | 5803 | } |
| 5902 | 5804 | |
| ... | ... | @@ -5982,14 +5884,7 @@ fn asRlPtr( |
| 5982 | 5884 | // as well as the store instruction, instead passing the result as an rvalue. |
| 5983 | 5885 | const astgen = parent_gz.astgen; |
| 5984 | 5886 | |
| 5985 | var as_scope: GenZir = .{ | |
| 5986 | .parent = scope, | |
| 5987 | .decl_node_index = parent_gz.decl_node_index, | |
| 5988 | .astgen = astgen, | |
| 5989 | .force_comptime = parent_gz.force_comptime, | |
| 5990 | .ref_start_index = parent_gz.ref_start_index, | |
| 5991 | .instructions = .{}, | |
| 5992 | }; | |
| 5887 | var as_scope = parent_gz.makeSubBlock(scope); | |
| 5993 | 5888 | defer as_scope.instructions.deinit(astgen.gpa); |
| 5994 | 5889 | |
| 5995 | 5890 | as_scope.rl_ptr = try as_scope.addBin(.coerce_result_ptr, dest_type, result_ptr); |
| ... | ... | @@ -6701,14 +6596,8 @@ fn cImport( |
| 6701 | 6596 | const astgen = gz.astgen; |
| 6702 | 6597 | const gpa = astgen.gpa; |
| 6703 | 6598 | |
| 6704 | var block_scope: GenZir = .{ | |
| 6705 | .parent = scope, | |
| 6706 | .decl_node_index = gz.decl_node_index, | |
| 6707 | .astgen = astgen, | |
| 6708 | .force_comptime = true, | |
| 6709 | .ref_start_index = gz.ref_start_index, | |
| 6710 | .instructions = .{}, | |
| 6711 | }; | |
| 6599 | var block_scope = gz.makeSubBlock(scope); | |
| 6600 | block_scope.force_comptime = true; | |
| 6712 | 6601 | defer block_scope.instructions.deinit(gpa); |
| 6713 | 6602 | |
| 6714 | 6603 | const block_inst = try gz.addBlock(.c_import, node); |
| ... | ... | @@ -6802,43 +6691,44 @@ fn callExpr( |
| 6802 | 6691 | } |
| 6803 | 6692 | |
| 6804 | 6693 | pub const simple_types = std.ComptimeStringMap(Zir.Inst.Ref, .{ |
| 6805 | .{ "u8", .u8_type }, | |
| 6806 | .{ "i8", .i8_type }, | |
| 6807 | .{ "u16", .u16_type }, | |
| 6808 | .{ "i16", .i16_type }, | |
| 6809 | .{ "u32", .u32_type }, | |
| 6810 | .{ "i32", .i32_type }, | |
| 6811 | .{ "u64", .u64_type }, | |
| 6812 | .{ "i64", .i64_type }, | |
| 6813 | .{ "usize", .usize_type }, | |
| 6814 | .{ "isize", .isize_type }, | |
| 6815 | .{ "c_short", .c_short_type }, | |
| 6816 | .{ "c_ushort", .c_ushort_type }, | |
| 6694 | .{ "anyerror", .anyerror_type }, | |
| 6695 | .{ "anyframe", .anyframe_type }, | |
| 6696 | .{ "bool", .bool_type }, | |
| 6817 | 6697 | .{ "c_int", .c_int_type }, |
| 6818 | .{ "c_uint", .c_uint_type }, | |
| 6819 | 6698 | .{ "c_long", .c_long_type }, |
| 6820 | .{ "c_ulong", .c_ulong_type }, | |
| 6699 | .{ "c_longdouble", .c_longdouble_type }, | |
| 6821 | 6700 | .{ "c_longlong", .c_longlong_type }, |
| 6701 | .{ "c_short", .c_short_type }, | |
| 6702 | .{ "c_uint", .c_uint_type }, | |
| 6703 | .{ "c_ulong", .c_ulong_type }, | |
| 6822 | 6704 | .{ "c_ulonglong", .c_ulonglong_type }, |
| 6823 | .{ "c_longdouble", .c_longdouble_type }, | |
| 6705 | .{ "c_ushort", .c_ushort_type }, | |
| 6706 | .{ "c_void", .c_void_type }, | |
| 6707 | .{ "comptime_float", .comptime_float_type }, | |
| 6708 | .{ "comptime_int", .comptime_int_type }, | |
| 6709 | .{ "f128", .f128_type }, | |
| 6824 | 6710 | .{ "f16", .f16_type }, |
| 6825 | 6711 | .{ "f32", .f32_type }, |
| 6826 | 6712 | .{ "f64", .f64_type }, |
| 6827 | .{ "f128", .f128_type }, | |
| 6828 | .{ "c_void", .c_void_type }, | |
| 6829 | .{ "bool", .bool_type }, | |
| 6830 | .{ "void", .void_type }, | |
| 6831 | .{ "type", .type_type }, | |
| 6832 | .{ "anyerror", .anyerror_type }, | |
| 6833 | .{ "comptime_int", .comptime_int_type }, | |
| 6834 | .{ "comptime_float", .comptime_float_type }, | |
| 6713 | .{ "false", .bool_false }, | |
| 6714 | .{ "i16", .i16_type }, | |
| 6715 | .{ "i32", .i32_type }, | |
| 6716 | .{ "i64", .i64_type }, | |
| 6717 | .{ "i128", .i128_type }, | |
| 6718 | .{ "i8", .i8_type }, | |
| 6719 | .{ "isize", .isize_type }, | |
| 6835 | 6720 | .{ "noreturn", .noreturn_type }, |
| 6836 | .{ "null", .null_type }, | |
| 6837 | .{ "undefined", .undefined_type }, | |
| 6838 | .{ "undefined", .undef }, | |
| 6839 | 6721 | .{ "null", .null_value }, |
| 6840 | 6722 | .{ "true", .bool_true }, |
| 6841 | .{ "false", .bool_false }, | |
| 6723 | .{ "type", .type_type }, | |
| 6724 | .{ "u16", .u16_type }, | |
| 6725 | .{ "u32", .u32_type }, | |
| 6726 | .{ "u64", .u64_type }, | |
| 6727 | .{ "u128", .u128_type }, | |
| 6728 | .{ "u8", .u8_type }, | |
| 6729 | .{ "undefined", .undef }, | |
| 6730 | .{ "usize", .usize_type }, | |
| 6731 | .{ "void", .void_type }, | |
| 6842 | 6732 | }); |
| 6843 | 6733 | |
| 6844 | 6734 | fn nodeMayNeedMemoryLocation(tree: *const ast.Tree, start_node: ast.Node.Index) bool { |
src/Module.zig+95-2| ... | ... | @@ -1085,6 +1085,21 @@ pub const Scope = struct { |
| 1085 | 1085 | /// a result location pointer. |
| 1086 | 1086 | labeled_store_to_block_ptr_list: ArrayListUnmanaged(Zir.Inst.Index) = .{}, |
| 1087 | 1087 | |
| 1088 | suspend_node: ast.Node.Index = 0, | |
| 1089 | nosuspend_node: ast.Node.Index = 0, | |
| 1090 | ||
| 1091 | pub fn makeSubBlock(gz: *GenZir, scope: *Scope) GenZir { | |
| 1092 | return .{ | |
| 1093 | .force_comptime = gz.force_comptime, | |
| 1094 | .ref_start_index = gz.ref_start_index, | |
| 1095 | .decl_node_index = gz.decl_node_index, | |
| 1096 | .parent = scope, | |
| 1097 | .astgen = gz.astgen, | |
| 1098 | .suspend_node = gz.suspend_node, | |
| 1099 | .nosuspend_node = gz.nosuspend_node, | |
| 1100 | }; | |
| 1101 | } | |
| 1102 | ||
| 1088 | 1103 | pub const Label = struct { |
| 1089 | 1104 | token: ast.TokenIndex, |
| 1090 | 1105 | block_inst: Zir.Inst.Index, |
| ... | ... | @@ -1674,9 +1689,9 @@ pub const Scope = struct { |
| 1674 | 1689 | @as(usize, @boolToInt(args.type_inst != .none)) + |
| 1675 | 1690 | @as(usize, @boolToInt(args.align_inst != .none)), |
| 1676 | 1691 | ); |
| 1677 | const payload_index = gz.astgen.addExtra(Zir.Inst.AllocExtended{ | |
| 1692 | const payload_index = gz.astgen.addExtraAssumeCapacity(Zir.Inst.AllocExtended{ | |
| 1678 | 1693 | .src_node = gz.nodeIndexToRelative(args.node), |
| 1679 | }) catch unreachable; // ensureUnusedCapacity above | |
| 1694 | }); | |
| 1680 | 1695 | if (args.type_inst != .none) { |
| 1681 | 1696 | astgen.extra.appendAssumeCapacity(@enumToInt(args.type_inst)); |
| 1682 | 1697 | } |
| ... | ... | @@ -1703,6 +1718,64 @@ pub const Scope = struct { |
| 1703 | 1718 | return gz.indexToRef(new_index); |
| 1704 | 1719 | } |
| 1705 | 1720 | |
| 1721 | pub fn addAsm( | |
| 1722 | gz: *GenZir, | |
| 1723 | args: struct { | |
| 1724 | /// Absolute node index. This function does the conversion to offset from Decl. | |
| 1725 | node: ast.Node.Index, | |
| 1726 | asm_source: Zir.Inst.Ref, | |
| 1727 | output_type_bits: u32, | |
| 1728 | is_volatile: bool, | |
| 1729 | outputs: []const Zir.Inst.Asm.Output, | |
| 1730 | inputs: []const Zir.Inst.Asm.Input, | |
| 1731 | clobbers: []const u32, | |
| 1732 | }, | |
| 1733 | ) !Zir.Inst.Ref { | |
| 1734 | const astgen = gz.astgen; | |
| 1735 | const gpa = astgen.gpa; | |
| 1736 | ||
| 1737 | try gz.instructions.ensureUnusedCapacity(gpa, 1); | |
| 1738 | try astgen.instructions.ensureUnusedCapacity(gpa, 1); | |
| 1739 | try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.Asm).Struct.fields.len + | |
| 1740 | args.outputs.len * @typeInfo(Zir.Inst.Asm.Output).Struct.fields.len + | |
| 1741 | args.inputs.len * @typeInfo(Zir.Inst.Asm.Input).Struct.fields.len + | |
| 1742 | args.clobbers.len); | |
| 1743 | ||
| 1744 | const payload_index = gz.astgen.addExtraAssumeCapacity(Zir.Inst.Asm{ | |
| 1745 | .src_node = gz.nodeIndexToRelative(args.node), | |
| 1746 | .asm_source = args.asm_source, | |
| 1747 | .output_type_bits = args.output_type_bits, | |
| 1748 | }); | |
| 1749 | for (args.outputs) |output| { | |
| 1750 | _ = gz.astgen.addExtraAssumeCapacity(output); | |
| 1751 | } | |
| 1752 | for (args.inputs) |input| { | |
| 1753 | _ = gz.astgen.addExtraAssumeCapacity(input); | |
| 1754 | } | |
| 1755 | gz.astgen.extra.appendSliceAssumeCapacity(args.clobbers); | |
| 1756 | ||
| 1757 | // * 0b00000000_000XXXXX - `outputs_len`. | |
| 1758 | // * 0b000000XX_XXX00000 - `inputs_len`. | |
| 1759 | // * 0b0XXXXX00_00000000 - `clobbers_len`. | |
| 1760 | // * 0bX0000000_00000000 - is volatile | |
| 1761 | const small: u16 = @intCast(u16, args.outputs.len) | | |
| 1762 | @intCast(u16, args.inputs.len << 5) | | |
| 1763 | @intCast(u16, args.clobbers.len << 10) | | |
| 1764 | (@as(u16, @boolToInt(args.is_volatile)) << 15); | |
| 1765 | ||
| 1766 | const new_index = @intCast(Zir.Inst.Index, astgen.instructions.len); | |
| 1767 | astgen.instructions.appendAssumeCapacity(.{ | |
| 1768 | .tag = .extended, | |
| 1769 | .data = .{ .extended = .{ | |
| 1770 | .opcode = .@"asm", | |
| 1771 | .small = small, | |
| 1772 | .operand = payload_index, | |
| 1773 | } }, | |
| 1774 | }); | |
| 1775 | gz.instructions.appendAssumeCapacity(new_index); | |
| 1776 | return gz.indexToRef(new_index); | |
| 1777 | } | |
| 1778 | ||
| 1706 | 1779 | /// Note that this returns a `Zir.Inst.Index` not a ref. |
| 1707 | 1780 | /// Does *not* append the block instruction to the scope. |
| 1708 | 1781 | /// Leaves the `payload_index` field undefined. |
| ... | ... | @@ -2209,6 +2282,18 @@ pub const SrcLoc = struct { |
| 2209 | 2282 | const token_starts = tree.tokens.items(.start); |
| 2210 | 2283 | return token_starts[tok_index]; |
| 2211 | 2284 | }, |
| 2285 | ||
| 2286 | .node_offset_anyframe_type => |node_off| { | |
| 2287 | const tree = src_loc.file_scope.tree; | |
| 2288 | const node_datas = tree.nodes.items(.data); | |
| 2289 | const node_tags = tree.nodes.items(.tag); | |
| 2290 | const parent_node = src_loc.declRelativeToNodeIndex(node_off); | |
| 2291 | const node = node_datas[parent_node].rhs; | |
| 2292 | const main_tokens = tree.nodes.items(.main_token); | |
| 2293 | const tok_index = main_tokens[node]; | |
| 2294 | const token_starts = tree.tokens.items(.start); | |
| 2295 | return token_starts[tok_index]; | |
| 2296 | }, | |
| 2212 | 2297 | } |
| 2213 | 2298 | } |
| 2214 | 2299 | }; |
| ... | ... | @@ -2368,6 +2453,12 @@ pub const LazySrcLoc = union(enum) { |
| 2368 | 2453 | /// the return type node. |
| 2369 | 2454 | /// The Decl is determined contextually. |
| 2370 | 2455 | node_offset_fn_type_ret_ty: i32, |
| 2456 | /// The source location points to the type expression of an `anyframe->T` | |
| 2457 | /// expression, found by taking this AST node index offset from the containing | |
| 2458 | /// Decl AST node, which points to a `anyframe->T` expression AST node. Next, navigate | |
| 2459 | /// to the type expression. | |
| 2460 | /// The Decl is determined contextually. | |
| 2461 | node_offset_anyframe_type: i32, | |
| 2371 | 2462 | |
| 2372 | 2463 | /// Upgrade to a `SrcLoc` based on the `Decl` or file in the provided scope. |
| 2373 | 2464 | pub fn toSrcLoc(lazy: LazySrcLoc, scope: *Scope) SrcLoc { |
| ... | ... | @@ -2407,6 +2498,7 @@ pub const LazySrcLoc = union(enum) { |
| 2407 | 2498 | .node_offset_switch_range, |
| 2408 | 2499 | .node_offset_fn_type_cc, |
| 2409 | 2500 | .node_offset_fn_type_ret_ty, |
| 2501 | .node_offset_anyframe_type, | |
| 2410 | 2502 | => .{ |
| 2411 | 2503 | .file_scope = scope.getFileScope(), |
| 2412 | 2504 | .parent_decl_node = scope.srcDecl().?.src_node, |
| ... | ... | @@ -2453,6 +2545,7 @@ pub const LazySrcLoc = union(enum) { |
| 2453 | 2545 | .node_offset_switch_range, |
| 2454 | 2546 | .node_offset_fn_type_cc, |
| 2455 | 2547 | .node_offset_fn_type_ret_ty, |
| 2548 | .node_offset_anyframe_type, | |
| 2456 | 2549 | => .{ |
| 2457 | 2550 | .file_scope = decl.getFileScope(), |
| 2458 | 2551 | .parent_decl_node = decl.src_node, |
src/Sema.zig+59-26| ... | ... | @@ -138,14 +138,13 @@ pub fn analyzeBody( |
| 138 | 138 | .alloc_inferred_comptime => try sema.zirAllocInferredComptime(block, inst), |
| 139 | 139 | .alloc_mut => try sema.zirAllocMut(block, inst), |
| 140 | 140 | .alloc_comptime => try sema.zirAllocComptime(block, inst), |
| 141 | .anyframe_type => try sema.zirAnyframeType(block, inst), | |
| 141 | 142 | .array_cat => try sema.zirArrayCat(block, inst), |
| 142 | 143 | .array_mul => try sema.zirArrayMul(block, inst), |
| 143 | 144 | .array_type => try sema.zirArrayType(block, inst), |
| 144 | 145 | .array_type_sentinel => try sema.zirArrayTypeSentinel(block, inst), |
| 145 | 146 | .as => try sema.zirAs(block, inst), |
| 146 | 147 | .as_node => try sema.zirAsNode(block, inst), |
| 147 | .@"asm" => try sema.zirAsm(block, inst, false), | |
| 148 | .asm_volatile => try sema.zirAsm(block, inst, true), | |
| 149 | 148 | .bit_and => try sema.zirBitwise(block, inst, .bit_and), |
| 150 | 149 | .bit_not => try sema.zirBitNot(block, inst), |
| 151 | 150 | .bit_or => try sema.zirBitwise(block, inst, .bit_or), |
| ... | ... | @@ -518,6 +517,7 @@ fn zirExtended(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerErro |
| 518 | 517 | .frame_address => return sema.zirFrameAddress( block, extended), |
| 519 | 518 | .alloc => return sema.zirAllocExtended( block, extended), |
| 520 | 519 | .builtin_extern => return sema.zirBuiltinExtern( block, extended), |
| 520 | .@"asm" => return sema.zirAsm( block, extended), | |
| 521 | 521 | .c_undef => return sema.zirCUndef( block, extended), |
| 522 | 522 | .c_include => return sema.zirCInclude( block, extended), |
| 523 | 523 | .c_define => return sema.zirCDefine( block, extended), |
| ... | ... | @@ -2173,6 +2173,19 @@ fn zirArrayTypeSentinel(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) |
| 2173 | 2173 | return sema.mod.constType(sema.arena, .unneeded, array_ty); |
| 2174 | 2174 | } |
| 2175 | 2175 | |
| 2176 | fn zirAnyframeType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst { | |
| 2177 | const tracy = trace(@src()); | |
| 2178 | defer tracy.end(); | |
| 2179 | ||
| 2180 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; | |
| 2181 | const src = inst_data.src(); | |
| 2182 | const operand_src: LazySrcLoc = .{ .node_offset_anyframe_type = inst_data.src_node }; | |
| 2183 | const return_type = try sema.resolveType(block, operand_src, inst_data.operand); | |
| 2184 | const anyframe_type = try Type.Tag.anyframe_T.create(sema.arena, return_type); | |
| 2185 | ||
| 2186 | return sema.mod.constType(sema.arena, src, anyframe_type); | |
| 2187 | } | |
| 2188 | ||
| 2176 | 2189 | fn zirErrorUnionType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst { |
| 2177 | 2190 | const tracy = trace(@src()); |
| 2178 | 2191 | defer tracy.end(); |
| ... | ... | @@ -4394,42 +4407,62 @@ fn zirLoad(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*I |
| 4394 | 4407 | fn zirAsm( |
| 4395 | 4408 | sema: *Sema, |
| 4396 | 4409 | block: *Scope.Block, |
| 4397 | inst: Zir.Inst.Index, | |
| 4398 | is_volatile: bool, | |
| 4410 | extended: Zir.Inst.Extended.InstData, | |
| 4399 | 4411 | ) InnerError!*Inst { |
| 4400 | 4412 | const tracy = trace(@src()); |
| 4401 | 4413 | defer tracy.end(); |
| 4402 | 4414 | |
| 4403 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; | |
| 4404 | const src = inst_data.src(); | |
| 4405 | const asm_source_src: LazySrcLoc = .{ .node_offset_asm_source = inst_data.src_node }; | |
| 4406 | const ret_ty_src: LazySrcLoc = .{ .node_offset_asm_ret_ty = inst_data.src_node }; | |
| 4407 | const extra = sema.code.extraData(Zir.Inst.Asm, inst_data.payload_index); | |
| 4415 | const extra = sema.code.extraData(Zir.Inst.Asm, extended.operand); | |
| 4416 | const src: LazySrcLoc = .{ .node_offset = extra.data.src_node }; | |
| 4417 | const asm_source_src: LazySrcLoc = .{ .node_offset_asm_source = extra.data.src_node }; | |
| 4418 | const ret_ty_src: LazySrcLoc = .{ .node_offset_asm_ret_ty = extra.data.src_node }; | |
| 4408 | 4419 | const asm_source = try sema.resolveConstString(block, asm_source_src, extra.data.asm_source); |
| 4420 | const outputs_len = @truncate(u5, extended.small); | |
| 4421 | const inputs_len = @truncate(u5, extended.small >> 5); | |
| 4422 | const clobbers_len = @truncate(u5, extended.small >> 10); | |
| 4423 | const is_volatile = @truncate(u1, extended.small >> 15) != 0; | |
| 4424 | ||
| 4425 | if (outputs_len > 1) { | |
| 4426 | return sema.mod.fail(&block.base, src, "TODO implement Sema for asm with more than 1 output", .{}); | |
| 4427 | } | |
| 4409 | 4428 | |
| 4410 | 4429 | var extra_i = extra.end; |
| 4430 | var output_type_bits = extra.data.output_type_bits; | |
| 4431 | ||
| 4411 | 4432 | const Output = struct { constraint: []const u8, ty: Type }; |
| 4412 | const output: ?Output = if (extra.data.output_type != .none) blk: { | |
| 4413 | const constraint = sema.code.nullTerminatedString(sema.code.extra[extra_i]); | |
| 4414 | extra_i += 1; | |
| 4433 | const output: ?Output = if (outputs_len == 0) null else blk: { | |
| 4434 | const output = sema.code.extraData(Zir.Inst.Asm.Output, extra_i); | |
| 4435 | extra_i = output.end; | |
| 4436 | ||
| 4437 | const is_type = @truncate(u1, output_type_bits) != 0; | |
| 4438 | output_type_bits >>= 1; | |
| 4439 | ||
| 4440 | if (!is_type) { | |
| 4441 | return sema.mod.fail(&block.base, src, "TODO implement Sema for asm with non `->` output", .{}); | |
| 4442 | } | |
| 4443 | ||
| 4444 | const constraint = sema.code.nullTerminatedString(output.data.constraint); | |
| 4415 | 4445 | break :blk Output{ |
| 4416 | 4446 | .constraint = constraint, |
| 4417 | .ty = try sema.resolveType(block, ret_ty_src, extra.data.output_type), | |
| 4447 | .ty = try sema.resolveType(block, ret_ty_src, output.data.operand), | |
| 4418 | 4448 | }; |
| 4419 | } else null; | |
| 4449 | }; | |
| 4420 | 4450 | |
| 4421 | const args = try sema.arena.alloc(*Inst, extra.data.args_len); | |
| 4422 | const inputs = try sema.arena.alloc([]const u8, extra.data.args_len); | |
| 4423 | const clobbers = try sema.arena.alloc([]const u8, extra.data.clobbers_len); | |
| 4451 | const args = try sema.arena.alloc(*Inst, inputs_len); | |
| 4452 | const inputs = try sema.arena.alloc([]const u8, inputs_len); | |
| 4424 | 4453 | |
| 4425 | for (args) |*arg| { | |
| 4426 | arg.* = try sema.resolveInst(@intToEnum(Zir.Inst.Ref, sema.code.extra[extra_i])); | |
| 4427 | extra_i += 1; | |
| 4428 | } | |
| 4429 | for (inputs) |*name| { | |
| 4430 | name.* = sema.code.nullTerminatedString(sema.code.extra[extra_i]); | |
| 4431 | extra_i += 1; | |
| 4454 | for (args) |*arg, arg_i| { | |
| 4455 | const input = sema.code.extraData(Zir.Inst.Asm.Input, extra_i); | |
| 4456 | extra_i = input.end; | |
| 4457 | ||
| 4458 | const name = sema.code.nullTerminatedString(input.data.name); | |
| 4459 | _ = name; // TODO: use the name | |
| 4460 | ||
| 4461 | arg.* = try sema.resolveInst(input.data.operand); | |
| 4462 | inputs[arg_i] = sema.code.nullTerminatedString(input.data.constraint); | |
| 4432 | 4463 | } |
| 4464 | ||
| 4465 | const clobbers = try sema.arena.alloc([]const u8, clobbers_len); | |
| 4433 | 4466 | for (clobbers) |*name| { |
| 4434 | 4467 | name.* = sema.code.nullTerminatedString(sema.code.extra[extra_i]); |
| 4435 | 4468 | extra_i += 1; |
| ... | ... | @@ -5408,7 +5441,7 @@ fn zirFuncExtended( |
| 5408 | 5441 | |
| 5409 | 5442 | var extra_index: usize = extra.end; |
| 5410 | 5443 | if (small.has_lib_name) { |
| 5411 | const lib_name = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]); | |
| 5444 | const lib_name = sema.code.nullTerminatedString(sema.code.extra[extra_index]); | |
| 5412 | 5445 | extra_index += 1; |
| 5413 | 5446 | return sema.mod.fail(&block.base, src, "TODO: implement Sema func lib name", .{}); |
| 5414 | 5447 | } |
| ... | ... | @@ -5428,7 +5461,7 @@ fn zirFuncExtended( |
| 5428 | 5461 | } else .Unspecified; |
| 5429 | 5462 | |
| 5430 | 5463 | const param_types = sema.code.refSlice(extra_index, extra.data.param_types_len); |
| 5431 | extra_index += 1; | |
| 5464 | extra_index += param_types.len; | |
| 5432 | 5465 | |
| 5433 | 5466 | const body = sema.code.extra[extra_index..][0..extra.data.body_len]; |
| 5434 | 5467 |
src/Zir.zig+153-57| ... | ... | @@ -60,7 +60,8 @@ pub fn extraData(code: Zir, comptime T: type, index: usize) struct { data: T, en |
| 60 | 60 | @field(result, field.name) = switch (field.field_type) { |
| 61 | 61 | u32 => code.extra[i], |
| 62 | 62 | Inst.Ref => @intToEnum(Inst.Ref, code.extra[i]), |
| 63 | else => unreachable, | |
| 63 | i32 => @bitCast(i32, code.extra[i]), | |
| 64 | else => @compileError("bad field type"), | |
| 64 | 65 | }; |
| 65 | 66 | i += 1; |
| 66 | 67 | } |
| ... | ... | @@ -165,18 +166,15 @@ pub const Inst = struct { |
| 165 | 166 | /// error if the indexable object is not indexable. |
| 166 | 167 | /// Uses the `un_node` field. The AST node is the for loop node. |
| 167 | 168 | indexable_ptr_len, |
| 169 | /// Create a `anyframe->T` type. | |
| 170 | /// Uses the `un_node` field. | |
| 171 | anyframe_type, | |
| 168 | 172 | /// Type coercion. No source location attached. |
| 169 | 173 | /// Uses the `bin` field. |
| 170 | 174 | as, |
| 171 | 175 | /// Type coercion to the function's return type. |
| 172 | 176 | /// Uses the `pl_node` field. Payload is `As`. AST node could be many things. |
| 173 | 177 | as_node, |
| 174 | /// Inline assembly. Non-volatile. | |
| 175 | /// Uses the `pl_node` union field. Payload is `Asm`. AST node is the assembly node. | |
| 176 | @"asm", | |
| 177 | /// Inline assembly with the volatile attribute. | |
| 178 | /// Uses the `pl_node` union field. Payload is `Asm`. AST node is the assembly node. | |
| 179 | asm_volatile, | |
| 180 | 178 | /// Bitwise AND. `&` |
| 181 | 179 | bit_and, |
| 182 | 180 | /// Bitcast a value to a different type. |
| ... | ... | @@ -967,10 +965,9 @@ pub const Inst = struct { |
| 967 | 965 | .array_type_sentinel, |
| 968 | 966 | .elem_type, |
| 969 | 967 | .indexable_ptr_len, |
| 968 | .anyframe_type, | |
| 970 | 969 | .as, |
| 971 | 970 | .as_node, |
| 972 | .@"asm", | |
| 973 | .asm_volatile, | |
| 974 | 971 | .bit_and, |
| 975 | 972 | .bitcast, |
| 976 | 973 | .bitcast_result_ptr, |
| ... | ... | @@ -1259,6 +1256,14 @@ pub const Inst = struct { |
| 1259 | 1256 | /// The `@extern` builtin. |
| 1260 | 1257 | /// `operand` is payload index to `BinNode`. |
| 1261 | 1258 | builtin_extern, |
| 1259 | /// Inline assembly. | |
| 1260 | /// `small`: | |
| 1261 | /// * 0b00000000_000XXXXX - `outputs_len`. | |
| 1262 | /// * 0b000000XX_XXX00000 - `inputs_len`. | |
| 1263 | /// * 0b0XXXXX00_00000000 - `clobbers_len`. | |
| 1264 | /// * 0bX0000000_00000000 - is volatile | |
| 1265 | /// `operand` is payload index to `Asm`. | |
| 1266 | @"asm", | |
| 1262 | 1267 | /// `operand` is payload index to `UnNode`. |
| 1263 | 1268 | c_undef, |
| 1264 | 1269 | /// `operand` is payload index to `UnNode`. |
| ... | ... | @@ -1313,6 +1318,8 @@ pub const Inst = struct { |
| 1313 | 1318 | i32_type, |
| 1314 | 1319 | u64_type, |
| 1315 | 1320 | i64_type, |
| 1321 | u128_type, | |
| 1322 | i128_type, | |
| 1316 | 1323 | usize_type, |
| 1317 | 1324 | isize_type, |
| 1318 | 1325 | c_short_type, |
| ... | ... | @@ -1336,17 +1343,10 @@ pub const Inst = struct { |
| 1336 | 1343 | comptime_int_type, |
| 1337 | 1344 | comptime_float_type, |
| 1338 | 1345 | noreturn_type, |
| 1346 | anyframe_type, | |
| 1339 | 1347 | null_type, |
| 1340 | 1348 | undefined_type, |
| 1341 | fn_noreturn_no_args_type, | |
| 1342 | fn_void_no_args_type, | |
| 1343 | fn_naked_noreturn_no_args_type, | |
| 1344 | fn_ccc_void_no_args_type, | |
| 1345 | single_const_pointer_to_comptime_int_type, | |
| 1346 | const_slice_u8_type, | |
| 1347 | 1349 | enum_literal_type, |
| 1348 | manyptr_u8_type, | |
| 1349 | manyptr_const_u8_type, | |
| 1350 | 1350 | atomic_ordering_type, |
| 1351 | 1351 | atomic_rmw_op_type, |
| 1352 | 1352 | calling_convention_type, |
| ... | ... | @@ -1355,6 +1355,14 @@ pub const Inst = struct { |
| 1355 | 1355 | call_options_type, |
| 1356 | 1356 | export_options_type, |
| 1357 | 1357 | extern_options_type, |
| 1358 | manyptr_u8_type, | |
| 1359 | manyptr_const_u8_type, | |
| 1360 | fn_noreturn_no_args_type, | |
| 1361 | fn_void_no_args_type, | |
| 1362 | fn_naked_noreturn_no_args_type, | |
| 1363 | fn_ccc_void_no_args_type, | |
| 1364 | single_const_pointer_to_comptime_int_type, | |
| 1365 | const_slice_u8_type, | |
| 1358 | 1366 | |
| 1359 | 1367 | /// `undefined` (untyped) |
| 1360 | 1368 | undef, |
| ... | ... | @@ -1418,6 +1426,14 @@ pub const Inst = struct { |
| 1418 | 1426 | .ty = Type.initTag(.type), |
| 1419 | 1427 | .val = Value.initTag(.i64_type), |
| 1420 | 1428 | }, |
| 1429 | .u128_type = .{ | |
| 1430 | .ty = Type.initTag(.type), | |
| 1431 | .val = Value.initTag(.u128_type), | |
| 1432 | }, | |
| 1433 | .i128_type = .{ | |
| 1434 | .ty = Type.initTag(.type), | |
| 1435 | .val = Value.initTag(.i128_type), | |
| 1436 | }, | |
| 1421 | 1437 | .usize_type = .{ |
| 1422 | 1438 | .ty = Type.initTag(.type), |
| 1423 | 1439 | .val = Value.initTag(.usize_type), |
| ... | ... | @@ -1510,6 +1526,10 @@ pub const Inst = struct { |
| 1510 | 1526 | .ty = Type.initTag(.type), |
| 1511 | 1527 | .val = Value.initTag(.noreturn_type), |
| 1512 | 1528 | }, |
| 1529 | .anyframe_type = .{ | |
| 1530 | .ty = Type.initTag(.type), | |
| 1531 | .val = Value.initTag(.anyframe_type), | |
| 1532 | }, | |
| 1513 | 1533 | .null_type = .{ |
| 1514 | 1534 | .ty = Type.initTag(.type), |
| 1515 | 1535 | .val = Value.initTag(.null_type), |
| ... | ... | @@ -1806,17 +1826,35 @@ pub const Inst = struct { |
| 1806 | 1826 | } |
| 1807 | 1827 | }; |
| 1808 | 1828 | |
| 1809 | /// Stored in extra. Trailing is: | |
| 1810 | /// * output_constraint: u32 // index into string_bytes (null terminated) if output is present | |
| 1811 | /// * arg: Ref // for every args_len. | |
| 1812 | /// * constraint: u32 // index into string_bytes (null terminated) for every args_len. | |
| 1813 | /// * clobber: u32 // index into string_bytes (null terminated) for every clobbers_len. | |
| 1829 | /// Trailing: | |
| 1830 | /// 0. Output for every outputs_len | |
| 1831 | /// 1. Input for every inputs_len | |
| 1832 | /// 2. clobber: u32 // index into string_bytes (null terminated) for every clobbers_len. | |
| 1814 | 1833 | pub const Asm = struct { |
| 1834 | src_node: i32, | |
| 1815 | 1835 | asm_source: Ref, |
| 1816 | /// May be omitted. | |
| 1817 | output_type: Ref, | |
| 1818 | args_len: u32, | |
| 1819 | clobbers_len: u32, | |
| 1836 | /// 1 bit for each outputs_len: whether it uses `-> T` or not. | |
| 1837 | /// 0b0 - operand is a pointer to where to store the output. | |
| 1838 | /// 0b1 - operand is a type; asm expression has the output as the result. | |
| 1839 | /// 0b0X is the first output, 0bX0 is the second, etc. | |
| 1840 | output_type_bits: u32, | |
| 1841 | ||
| 1842 | pub const Output = struct { | |
| 1843 | /// index into string_bytes (null terminated) | |
| 1844 | name: u32, | |
| 1845 | /// index into string_bytes (null terminated) | |
| 1846 | constraint: u32, | |
| 1847 | /// How to interpret this is determined by `output_type_bits`. | |
| 1848 | operand: Ref, | |
| 1849 | }; | |
| 1850 | ||
| 1851 | pub const Input = struct { | |
| 1852 | /// index into string_bytes (null terminated) | |
| 1853 | name: u32, | |
| 1854 | /// index into string_bytes (null terminated) | |
| 1855 | constraint: u32, | |
| 1856 | operand: Ref, | |
| 1857 | }; | |
| 1820 | 1858 | }; |
| 1821 | 1859 | |
| 1822 | 1860 | /// Trailing: |
| ... | ... | @@ -2298,6 +2336,7 @@ const Writer = struct { |
| 2298 | 2336 | .alloc_mut, |
| 2299 | 2337 | .alloc_comptime, |
| 2300 | 2338 | .indexable_ptr_len, |
| 2339 | .anyframe_type, | |
| 2301 | 2340 | .bit_not, |
| 2302 | 2341 | .bool_not, |
| 2303 | 2342 | .negate, |
| ... | ... | @@ -2430,10 +2469,6 @@ const Writer = struct { |
| 2430 | 2469 | .builtin_async_call, |
| 2431 | 2470 | => try self.writePlNode(stream, inst), |
| 2432 | 2471 | |
| 2433 | .@"asm", | |
| 2434 | .asm_volatile, | |
| 2435 | => try self.writePlNodeAsm(stream, inst), | |
| 2436 | ||
| 2437 | 2472 | .error_set_decl => try self.writePlNodeErrorSetDecl(stream, inst), |
| 2438 | 2473 | |
| 2439 | 2474 | .add_with_overflow, |
| ... | ... | @@ -2603,7 +2638,9 @@ const Writer = struct { |
| 2603 | 2638 | .builtin_src, |
| 2604 | 2639 | => try self.writeExtNode(stream, extended), |
| 2605 | 2640 | |
| 2606 | .func, | |
| 2641 | .@"asm" => try self.writeAsm(stream, extended), | |
| 2642 | .func => try self.writeFuncExtended(stream, extended), | |
| 2643 | ||
| 2607 | 2644 | .alloc, |
| 2608 | 2645 | .builtin_extern, |
| 2609 | 2646 | .c_undef, |
| ... | ... | @@ -2794,49 +2831,74 @@ const Writer = struct { |
| 2794 | 2831 | try self.writeSrc(stream, inst_data.src()); |
| 2795 | 2832 | } |
| 2796 | 2833 | |
| 2797 | fn writePlNodeAsm(self: *Writer, stream: anytype, inst: Inst.Index) !void { | |
| 2798 | const inst_data = self.code.instructions.items(.data)[inst].pl_node; | |
| 2799 | const extra = self.code.extraData(Inst.Asm, inst_data.payload_index); | |
| 2800 | var extra_i: usize = extra.end; | |
| 2834 | fn writeAsm(self: *Writer, stream: anytype, extended: Inst.Extended.InstData) !void { | |
| 2835 | const extra = self.code.extraData(Inst.Asm, extended.operand); | |
| 2836 | const src: LazySrcLoc = .{ .node_offset = extra.data.src_node }; | |
| 2837 | const outputs_len = @truncate(u5, extended.small); | |
| 2838 | const inputs_len = @truncate(u5, extended.small >> 5); | |
| 2839 | const clobbers_len = @truncate(u5, extended.small >> 10); | |
| 2840 | const is_volatile = @truncate(u1, extended.small >> 15) != 0; | |
| 2801 | 2841 | |
| 2802 | if (extra.data.output_type != .none) { | |
| 2803 | const constraint_str_index = self.code.extra[extra_i]; | |
| 2804 | extra_i += 1; | |
| 2805 | const constraint = self.code.nullTerminatedString(constraint_str_index); | |
| 2806 | try stream.print("\"{}\"->", .{std.zig.fmtEscapes(constraint)}); | |
| 2807 | try self.writeInstRef(stream, extra.data.output_type); | |
| 2808 | try stream.writeAll(", "); | |
| 2809 | } | |
| 2842 | try self.writeFlag(stream, "volatile, ", is_volatile); | |
| 2843 | try self.writeInstRef(stream, extra.data.asm_source); | |
| 2844 | try stream.writeAll(", "); | |
| 2845 | ||
| 2846 | var extra_i: usize = extra.end; | |
| 2847 | var output_type_bits = extra.data.output_type_bits; | |
| 2810 | 2848 | { |
| 2811 | 2849 | var i: usize = 0; |
| 2812 | while (i < extra.data.args_len) : (i += 1) { | |
| 2813 | const arg = @intToEnum(Zir.Inst.Ref, self.code.extra[extra_i]); | |
| 2814 | extra_i += 1; | |
| 2815 | try self.writeInstRef(stream, arg); | |
| 2816 | try stream.writeAll(", "); | |
| 2850 | while (i < outputs_len) : (i += 1) { | |
| 2851 | const output = self.code.extraData(Inst.Asm.Output, extra_i); | |
| 2852 | extra_i = output.end; | |
| 2853 | ||
| 2854 | const is_type = @truncate(u1, output_type_bits) != 0; | |
| 2855 | output_type_bits >>= 1; | |
| 2856 | ||
| 2857 | const name = self.code.nullTerminatedString(output.data.name); | |
| 2858 | const constraint = self.code.nullTerminatedString(output.data.constraint); | |
| 2859 | try stream.print("output({}, \"{}\", ", .{ | |
| 2860 | std.zig.fmtId(name), std.zig.fmtEscapes(constraint), | |
| 2861 | }); | |
| 2862 | try self.writeFlag(stream, "->", is_type); | |
| 2863 | try self.writeInstRef(stream, output.data.operand); | |
| 2864 | try stream.writeAll(")"); | |
| 2865 | if (i + 1 < outputs_len) { | |
| 2866 | try stream.writeAll("), "); | |
| 2867 | } | |
| 2817 | 2868 | } |
| 2818 | 2869 | } |
| 2819 | 2870 | { |
| 2820 | 2871 | var i: usize = 0; |
| 2821 | while (i < extra.data.args_len) : (i += 1) { | |
| 2822 | const str_index = self.code.extra[extra_i]; | |
| 2823 | extra_i += 1; | |
| 2824 | const constraint = self.code.nullTerminatedString(str_index); | |
| 2825 | try stream.print("\"{}\", ", .{std.zig.fmtEscapes(constraint)}); | |
| 2872 | while (i < inputs_len) : (i += 1) { | |
| 2873 | const input = self.code.extraData(Inst.Asm.Input, extra_i); | |
| 2874 | extra_i = input.end; | |
| 2875 | ||
| 2876 | const name = self.code.nullTerminatedString(input.data.name); | |
| 2877 | const constraint = self.code.nullTerminatedString(input.data.constraint); | |
| 2878 | try stream.print("input({}, \"{}\", ", .{ | |
| 2879 | std.zig.fmtId(name), std.zig.fmtEscapes(constraint), | |
| 2880 | }); | |
| 2881 | try self.writeInstRef(stream, input.data.operand); | |
| 2882 | try stream.writeAll(")"); | |
| 2883 | if (i + 1 < inputs_len) { | |
| 2884 | try stream.writeAll(", "); | |
| 2885 | } | |
| 2826 | 2886 | } |
| 2827 | 2887 | } |
| 2828 | 2888 | { |
| 2829 | 2889 | var i: usize = 0; |
| 2830 | while (i < extra.data.clobbers_len) : (i += 1) { | |
| 2890 | while (i < clobbers_len) : (i += 1) { | |
| 2831 | 2891 | const str_index = self.code.extra[extra_i]; |
| 2832 | 2892 | extra_i += 1; |
| 2833 | 2893 | const clobber = self.code.nullTerminatedString(str_index); |
| 2834 | try stream.print("{}, ", .{std.zig.fmtId(clobber)}); | |
| 2894 | try stream.print("{}", .{std.zig.fmtId(clobber)}); | |
| 2895 | if (i + 1 < clobbers_len) { | |
| 2896 | try stream.writeAll(", "); | |
| 2897 | } | |
| 2835 | 2898 | } |
| 2836 | 2899 | } |
| 2837 | try self.writeInstRef(stream, extra.data.asm_source); | |
| 2838 | 2900 | try stream.writeAll(") "); |
| 2839 | try self.writeSrc(stream, inst_data.src()); | |
| 2901 | try self.writeSrc(stream, src); | |
| 2840 | 2902 | } |
| 2841 | 2903 | |
| 2842 | 2904 | fn writePlNodeOverflowArithmetic(self: *Writer, stream: anytype, inst: Inst.Index) !void { |
| ... | ... | @@ -3467,6 +3529,40 @@ const Writer = struct { |
| 3467 | 3529 | ); |
| 3468 | 3530 | } |
| 3469 | 3531 | |
| 3532 | fn writeFuncExtended(self: *Writer, stream: anytype, extended: Inst.Extended.InstData) !void { | |
| 3533 | const extra = self.code.extraData(Inst.ExtendedFunc, extended.operand); | |
| 3534 | const src: LazySrcLoc = .{ .node_offset = extra.data.src_node }; | |
| 3535 | const small = @bitCast(Inst.ExtendedFunc.Small, extended.small); | |
| 3536 | ||
| 3537 | var extra_index: usize = extra.end; | |
| 3538 | if (small.has_lib_name) { | |
| 3539 | const lib_name = self.code.nullTerminatedString(self.code.extra[extra_index]); | |
| 3540 | extra_index += 1; | |
| 3541 | try stream.print("lib_name=\"{}\", ", .{std.zig.fmtEscapes(lib_name)}); | |
| 3542 | } | |
| 3543 | const cc: Inst.Ref = if (!small.has_cc) .none else blk: { | |
| 3544 | const cc = @intToEnum(Zir.Inst.Ref, self.code.extra[extra_index]); | |
| 3545 | extra_index += 1; | |
| 3546 | break :blk cc; | |
| 3547 | }; | |
| 3548 | ||
| 3549 | const param_types = self.code.refSlice(extra_index, extra.data.param_types_len); | |
| 3550 | extra_index += param_types.len; | |
| 3551 | ||
| 3552 | const body = self.code.extra[extra_index..][0..extra.data.body_len]; | |
| 3553 | ||
| 3554 | return self.writeFuncCommon( | |
| 3555 | stream, | |
| 3556 | param_types, | |
| 3557 | extra.data.return_type, | |
| 3558 | small.is_inferred_error, | |
| 3559 | small.is_var_args, | |
| 3560 | cc, | |
| 3561 | body, | |
| 3562 | src, | |
| 3563 | ); | |
| 3564 | } | |
| 3565 | ||
| 3470 | 3566 | fn writeBoolBr(self: *Writer, stream: anytype, inst: Inst.Index) !void { |
| 3471 | 3567 | const inst_data = self.code.instructions.items(.data)[inst].bool_br; |
| 3472 | 3568 | const extra = self.code.extraData(Inst.Block, inst_data.payload_index); |
src/type.zig+37-7| ... | ... | @@ -95,6 +95,8 @@ pub const Type = extern union { |
| 95 | 95 | |
| 96 | 96 | .anyerror_void_error_union, .error_union => return .ErrorUnion, |
| 97 | 97 | |
| 98 | .anyframe_T, .@"anyframe" => return .AnyFrame, | |
| 99 | ||
| 98 | 100 | .empty_struct, |
| 99 | 101 | .empty_struct_literal, |
| 100 | 102 | .@"struct", |
| ... | ... | @@ -620,6 +622,7 @@ pub const Type = extern union { |
| 620 | 622 | .call_options, |
| 621 | 623 | .export_options, |
| 622 | 624 | .extern_options, |
| 625 | .@"anyframe", | |
| 623 | 626 | => unreachable, |
| 624 | 627 | |
| 625 | 628 | .array_u8, |
| ... | ... | @@ -637,6 +640,7 @@ pub const Type = extern union { |
| 637 | 640 | .optional, |
| 638 | 641 | .optional_single_mut_pointer, |
| 639 | 642 | .optional_single_const_pointer, |
| 643 | .anyframe_T, | |
| 640 | 644 | => return self.copyPayloadShallow(allocator, Payload.ElemType), |
| 641 | 645 | |
| 642 | 646 | .int_signed, |
| ... | ... | @@ -754,6 +758,7 @@ pub const Type = extern union { |
| 754 | 758 | .void, |
| 755 | 759 | .type, |
| 756 | 760 | .anyerror, |
| 761 | .@"anyframe", | |
| 757 | 762 | .comptime_int, |
| 758 | 763 | .comptime_float, |
| 759 | 764 | .noreturn, |
| ... | ... | @@ -820,6 +825,12 @@ pub const Type = extern union { |
| 820 | 825 | continue; |
| 821 | 826 | }, |
| 822 | 827 | |
| 828 | .anyframe_T => { | |
| 829 | const return_type = ty.castTag(.anyframe_T).?.data; | |
| 830 | try writer.print("anyframe->", .{}); | |
| 831 | ty = return_type; | |
| 832 | continue; | |
| 833 | }, | |
| 823 | 834 | .array_u8 => { |
| 824 | 835 | const len = ty.castTag(.array_u8).?.data; |
| 825 | 836 | return writer.print("[{d}]u8", .{len}); |
| ... | ... | @@ -994,6 +1005,7 @@ pub const Type = extern union { |
| 994 | 1005 | .void => return Value.initTag(.void_type), |
| 995 | 1006 | .type => return Value.initTag(.type_type), |
| 996 | 1007 | .anyerror => return Value.initTag(.anyerror_type), |
| 1008 | .@"anyframe" => return Value.initTag(.anyframe_type), | |
| 997 | 1009 | .comptime_int => return Value.initTag(.comptime_int_type), |
| 998 | 1010 | .comptime_float => return Value.initTag(.comptime_float_type), |
| 999 | 1011 | .noreturn => return Value.initTag(.noreturn_type), |
| ... | ... | @@ -1075,6 +1087,8 @@ pub const Type = extern union { |
| 1075 | 1087 | .call_options, |
| 1076 | 1088 | .export_options, |
| 1077 | 1089 | .extern_options, |
| 1090 | .@"anyframe", | |
| 1091 | .anyframe_T, | |
| 1078 | 1092 | => true, |
| 1079 | 1093 | |
| 1080 | 1094 | .@"struct" => { |
| ... | ... | @@ -1223,6 +1237,8 @@ pub const Type = extern union { |
| 1223 | 1237 | .pointer, |
| 1224 | 1238 | .manyptr_u8, |
| 1225 | 1239 | .manyptr_const_u8, |
| 1240 | .@"anyframe", | |
| 1241 | .anyframe_T, | |
| 1226 | 1242 | => return @divExact(target.cpu.arch.ptrBitWidth(), 8), |
| 1227 | 1243 | |
| 1228 | 1244 | .c_short => return @divExact(CType.short.sizeInBits(target), 8), |
| ... | ... | @@ -1388,7 +1404,11 @@ pub const Type = extern union { |
| 1388 | 1404 | .i64, .u64 => return 8, |
| 1389 | 1405 | .u128, .i128 => return 16, |
| 1390 | 1406 | |
| 1391 | .isize, .usize => return @divExact(target.cpu.arch.ptrBitWidth(), 8), | |
| 1407 | .isize, | |
| 1408 | .usize, | |
| 1409 | .@"anyframe", | |
| 1410 | .anyframe_T, | |
| 1411 | => return @divExact(target.cpu.arch.ptrBitWidth(), 8), | |
| 1392 | 1412 | |
| 1393 | 1413 | .const_slice, |
| 1394 | 1414 | .mut_slice, |
| ... | ... | @@ -1536,7 +1556,11 @@ pub const Type = extern union { |
| 1536 | 1556 | .i64, .u64, .f64 => 64, |
| 1537 | 1557 | .u128, .i128, .f128 => 128, |
| 1538 | 1558 | |
| 1539 | .isize, .usize => target.cpu.arch.ptrBitWidth(), | |
| 1559 | .isize, | |
| 1560 | .usize, | |
| 1561 | .@"anyframe", | |
| 1562 | .anyframe_T, | |
| 1563 | => target.cpu.arch.ptrBitWidth(), | |
| 1540 | 1564 | |
| 1541 | 1565 | .const_slice, |
| 1542 | 1566 | .mut_slice, |
| ... | ... | @@ -2256,6 +2280,8 @@ pub const Type = extern union { |
| 2256 | 2280 | .call_options, |
| 2257 | 2281 | .export_options, |
| 2258 | 2282 | .extern_options, |
| 2283 | .@"anyframe", | |
| 2284 | .anyframe_T, | |
| 2259 | 2285 | => return null, |
| 2260 | 2286 | |
| 2261 | 2287 | .@"struct" => { |
| ... | ... | @@ -2666,9 +2692,10 @@ pub const Type = extern union { |
| 2666 | 2692 | comptime_int, |
| 2667 | 2693 | comptime_float, |
| 2668 | 2694 | noreturn, |
| 2695 | @"anyframe", | |
| 2696 | @"null", | |
| 2697 | @"undefined", | |
| 2669 | 2698 | enum_literal, |
| 2670 | manyptr_u8, | |
| 2671 | manyptr_const_u8, | |
| 2672 | 2699 | atomic_ordering, |
| 2673 | 2700 | atomic_rmw_op, |
| 2674 | 2701 | calling_convention, |
| ... | ... | @@ -2677,15 +2704,15 @@ pub const Type = extern union { |
| 2677 | 2704 | call_options, |
| 2678 | 2705 | export_options, |
| 2679 | 2706 | extern_options, |
| 2680 | @"null", | |
| 2681 | @"undefined", | |
| 2707 | manyptr_u8, | |
| 2708 | manyptr_const_u8, | |
| 2682 | 2709 | fn_noreturn_no_args, |
| 2683 | 2710 | fn_void_no_args, |
| 2684 | 2711 | fn_naked_noreturn_no_args, |
| 2685 | 2712 | fn_ccc_void_no_args, |
| 2686 | 2713 | single_const_pointer_to_comptime_int, |
| 2687 | anyerror_void_error_union, | |
| 2688 | 2714 | const_slice_u8, |
| 2715 | anyerror_void_error_union, | |
| 2689 | 2716 | /// This is a special type for variadic parameters of a function call. |
| 2690 | 2717 | /// Casts to it will validate that the type can be passed to a c calling convetion function. |
| 2691 | 2718 | var_args_param, |
| ... | ... | @@ -2719,6 +2746,7 @@ pub const Type = extern union { |
| 2719 | 2746 | optional_single_mut_pointer, |
| 2720 | 2747 | optional_single_const_pointer, |
| 2721 | 2748 | error_union, |
| 2749 | anyframe_T, | |
| 2722 | 2750 | error_set, |
| 2723 | 2751 | error_set_single, |
| 2724 | 2752 | empty_struct, |
| ... | ... | @@ -2790,6 +2818,7 @@ pub const Type = extern union { |
| 2790 | 2818 | .call_options, |
| 2791 | 2819 | .export_options, |
| 2792 | 2820 | .extern_options, |
| 2821 | .@"anyframe", | |
| 2793 | 2822 | => @compileError("Type Tag " ++ @tagName(t) ++ " has no payload"), |
| 2794 | 2823 | |
| 2795 | 2824 | .array_u8, |
| ... | ... | @@ -2807,6 +2836,7 @@ pub const Type = extern union { |
| 2807 | 2836 | .optional, |
| 2808 | 2837 | .optional_single_mut_pointer, |
| 2809 | 2838 | .optional_single_const_pointer, |
| 2839 | .anyframe_T, | |
| 2810 | 2840 | => Payload.ElemType, |
| 2811 | 2841 | |
| 2812 | 2842 | .int_signed, |
src/value.zig+15-8| ... | ... | @@ -55,17 +55,10 @@ pub const Value = extern union { |
| 55 | 55 | comptime_int_type, |
| 56 | 56 | comptime_float_type, |
| 57 | 57 | noreturn_type, |
| 58 | anyframe_type, | |
| 58 | 59 | null_type, |
| 59 | 60 | undefined_type, |
| 60 | fn_noreturn_no_args_type, | |
| 61 | fn_void_no_args_type, | |
| 62 | fn_naked_noreturn_no_args_type, | |
| 63 | fn_ccc_void_no_args_type, | |
| 64 | single_const_pointer_to_comptime_int_type, | |
| 65 | const_slice_u8_type, | |
| 66 | 61 | enum_literal_type, |
| 67 | manyptr_u8_type, | |
| 68 | manyptr_const_u8_type, | |
| 69 | 62 | atomic_ordering_type, |
| 70 | 63 | atomic_rmw_op_type, |
| 71 | 64 | calling_convention_type, |
| ... | ... | @@ -74,6 +67,14 @@ pub const Value = extern union { |
| 74 | 67 | call_options_type, |
| 75 | 68 | export_options_type, |
| 76 | 69 | extern_options_type, |
| 70 | manyptr_u8_type, | |
| 71 | manyptr_const_u8_type, | |
| 72 | fn_noreturn_no_args_type, | |
| 73 | fn_void_no_args_type, | |
| 74 | fn_naked_noreturn_no_args_type, | |
| 75 | fn_ccc_void_no_args_type, | |
| 76 | single_const_pointer_to_comptime_int_type, | |
| 77 | const_slice_u8_type, | |
| 77 | 78 | |
| 78 | 79 | undef, |
| 79 | 80 | zero, |
| ... | ... | @@ -166,6 +167,7 @@ pub const Value = extern union { |
| 166 | 167 | .fn_naked_noreturn_no_args_type, |
| 167 | 168 | .fn_ccc_void_no_args_type, |
| 168 | 169 | .single_const_pointer_to_comptime_int_type, |
| 170 | .anyframe_type, | |
| 169 | 171 | .const_slice_u8_type, |
| 170 | 172 | .enum_literal_type, |
| 171 | 173 | .undef, |
| ... | ... | @@ -334,6 +336,7 @@ pub const Value = extern union { |
| 334 | 336 | .fn_naked_noreturn_no_args_type, |
| 335 | 337 | .fn_ccc_void_no_args_type, |
| 336 | 338 | .single_const_pointer_to_comptime_int_type, |
| 339 | .anyframe_type, | |
| 337 | 340 | .const_slice_u8_type, |
| 338 | 341 | .enum_literal_type, |
| 339 | 342 | .undef, |
| ... | ... | @@ -502,6 +505,7 @@ pub const Value = extern union { |
| 502 | 505 | .fn_naked_noreturn_no_args_type => return out_stream.writeAll("fn() callconv(.Naked) noreturn"), |
| 503 | 506 | .fn_ccc_void_no_args_type => return out_stream.writeAll("fn() callconv(.C) void"), |
| 504 | 507 | .single_const_pointer_to_comptime_int_type => return out_stream.writeAll("*const comptime_int"), |
| 508 | .anyframe_type => return out_stream.writeAll("anyframe"), | |
| 505 | 509 | .const_slice_u8_type => return out_stream.writeAll("[]const u8"), |
| 506 | 510 | .enum_literal_type => return out_stream.writeAll("@Type(.EnumLiteral)"), |
| 507 | 511 | .manyptr_u8_type => return out_stream.writeAll("[*]u8"), |
| ... | ... | @@ -633,6 +637,7 @@ pub const Value = extern union { |
| 633 | 637 | .fn_naked_noreturn_no_args_type => Type.initTag(.fn_naked_noreturn_no_args), |
| 634 | 638 | .fn_ccc_void_no_args_type => Type.initTag(.fn_ccc_void_no_args), |
| 635 | 639 | .single_const_pointer_to_comptime_int_type => Type.initTag(.single_const_pointer_to_comptime_int), |
| 640 | .anyframe_type => Type.initTag(.@"anyframe"), | |
| 636 | 641 | .const_slice_u8_type => Type.initTag(.const_slice_u8), |
| 637 | 642 | .enum_literal_type => Type.initTag(.enum_literal), |
| 638 | 643 | .manyptr_u8_type => Type.initTag(.manyptr_u8), |
| ... | ... | @@ -1070,6 +1075,7 @@ pub const Value = extern union { |
| 1070 | 1075 | .fn_naked_noreturn_no_args_type, |
| 1071 | 1076 | .fn_ccc_void_no_args_type, |
| 1072 | 1077 | .single_const_pointer_to_comptime_int_type, |
| 1078 | .anyframe_type, | |
| 1073 | 1079 | .const_slice_u8_type, |
| 1074 | 1080 | .enum_literal_type, |
| 1075 | 1081 | .ty, |
| ... | ... | @@ -1338,6 +1344,7 @@ pub const Value = extern union { |
| 1338 | 1344 | .fn_naked_noreturn_no_args_type, |
| 1339 | 1345 | .fn_ccc_void_no_args_type, |
| 1340 | 1346 | .single_const_pointer_to_comptime_int_type, |
| 1347 | .anyframe_type, | |
| 1341 | 1348 | .const_slice_u8_type, |
| 1342 | 1349 | .enum_literal_type, |
| 1343 | 1350 | .manyptr_u8_type, |