authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-04-23 18:28:46-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-04-23 18:35:21-07:00
logb40a8efb9a72e69cd7e9061fc4c08d5e705b0fbd
treeb62377262318b6f6d76a0b75d43dff106e553a2f
parent183ee0965fac6322651666834776d9832cc95ddd

stage2: implement `anyframe`, `anyframe->T` and fix assembly

* 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
723723 },
724724 .enum_literal => return simpleStrTok(gz, scope, rl, main_tokens[node], node, .enum_literal),
725725 .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 },
728732 .@"catch" => {
729733 const catch_token = main_tokens[node];
730734 const payload_token: ?ast.TokenIndex = if (token_tags[catch_token + 1] == .pipe)
......@@ -1546,18 +1550,10 @@ fn labeledBlockExpr(
15461550 const block_inst = try gz.addBlock(zir_tag, block_node);
15471551 try gz.instructions.append(astgen.gpa, block_inst);
15481552
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,
15611557 };
15621558 block_scope.setBreakResultLoc(rl);
15631559 defer block_scope.instructions.deinit(astgen.gpa);
......@@ -1695,10 +1691,9 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: ast.Node.Index) Inner
16951691 .array_type_sentinel,
16961692 .elem_type,
16971693 .indexable_ptr_len,
1694 .anyframe_type,
16981695 .as,
16991696 .as_node,
1700 .@"asm",
1701 .asm_volatile,
17021697 .bit_and,
17031698 .bitcast,
17041699 .bitcast_result_ptr,
......@@ -2095,13 +2090,7 @@ fn varDecl(
20952090
20962091 // Detect whether the initialization expression actually uses the
20972092 // 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);
21052094 defer init_scope.instructions.deinit(gpa);
21062095
21072096 var resolve_inferred_alloc: Zir.Inst.Ref = .none;
......@@ -3778,14 +3767,7 @@ fn tryExpr(
37783767 return astgen.failNode(node, "invalid 'try' outside function scope", .{});
37793768 };
37803769
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);
37893771 block_scope.setBreakResultLoc(rl);
37903772 defer block_scope.instructions.deinit(astgen.gpa);
37913773
......@@ -3811,28 +3793,14 @@ fn tryExpr(
38113793 try parent_gz.instructions.append(astgen.gpa, block);
38123794 try block_scope.setBlockBody(block);
38133795
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);
38223797 defer then_scope.instructions.deinit(astgen.gpa);
38233798
38243799 const err_code = try then_scope.addUnNode(err_ops[1], operand, node);
38253800 try genDefers(&then_scope, &fn_block.base, scope, err_code);
38263801 const then_result = try then_scope.addUnNode(.ret_node, err_code, node);
38273802
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);
38363804 defer else_scope.instructions.deinit(astgen.gpa);
38373805
38383806 block_scope.break_count += 1;
......@@ -3878,14 +3846,7 @@ fn orelseCatchExpr(
38783846 const astgen = parent_gz.astgen;
38793847 const tree = &astgen.file.tree;
38803848
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);
38893850 block_scope.setBreakResultLoc(rl);
38903851 defer block_scope.instructions.deinit(astgen.gpa);
38913852
......@@ -3906,14 +3867,7 @@ fn orelseCatchExpr(
39063867 try parent_gz.instructions.append(astgen.gpa, block);
39073868 try block_scope.setBlockBody(block);
39083869
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);
39173871 defer then_scope.instructions.deinit(astgen.gpa);
39183872
39193873 var err_val_scope: Scope.LocalVal = undefined;
......@@ -3939,14 +3893,7 @@ fn orelseCatchExpr(
39393893 // instructions into place until we know whether to keep store_to_block_ptr
39403894 // instructions or not.
39413895
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);
39503897 defer else_scope.instructions.deinit(astgen.gpa);
39513898
39523899 // This could be a pointer or value depending on `unwrap_op`.
......@@ -4140,13 +4087,7 @@ fn boolBinOp(
41404087 const lhs = try expr(gz, scope, bool_rl, node_datas[node].lhs);
41414088 const bool_br = try gz.addBoolBr(zir_tag, lhs);
41424089
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);
41504091 defer rhs_scope.instructions.deinit(gz.astgen.gpa);
41514092 const rhs = try expr(&rhs_scope, &rhs_scope.base, bool_rl, node_datas[node].rhs);
41524093 _ = try rhs_scope.addBreak(.break_inline, bool_br, rhs);
......@@ -4167,14 +4108,7 @@ fn ifExpr(
41674108 const tree = &astgen.file.tree;
41684109 const token_tags = tree.tokens.items(.tag);
41694110
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);
41784112 block_scope.setBreakResultLoc(rl);
41794113 defer block_scope.instructions.deinit(astgen.gpa);
41804114
......@@ -4218,14 +4152,7 @@ fn ifExpr(
42184152 try parent_gz.instructions.append(astgen.gpa, block);
42194153 try block_scope.setBlockBody(block);
42204154
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);
42294156 defer then_scope.instructions.deinit(astgen.gpa);
42304157
42314158 var payload_val_scope: Scope.LocalVal = undefined;
......@@ -4273,14 +4200,7 @@ fn ifExpr(
42734200 // instructions into place until we know whether to keep store_to_block_ptr
42744201 // instructions or not.
42754202
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);
42844204 defer else_scope.instructions.deinit(astgen.gpa);
42854205
42864206 const else_node = if_full.ast.else_expr;
......@@ -4424,25 +4344,11 @@ fn whileExpr(
44244344 const loop_block = try parent_gz.addBlock(loop_tag, node);
44254345 try parent_gz.instructions.append(astgen.gpa, loop_block);
44264346
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);
44354348 loop_scope.setBreakResultLoc(rl);
44364349 defer loop_scope.instructions.deinit(astgen.gpa);
44374350
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);
44464352 defer continue_scope.instructions.deinit(astgen.gpa);
44474353
44484354 const payload_is_ref = if (while_full.payload_token) |payload_token|
......@@ -4505,14 +4411,7 @@ fn whileExpr(
45054411 });
45064412 }
45074413
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);
45164415 defer then_scope.instructions.deinit(astgen.gpa);
45174416
45184417 var payload_val_scope: Scope.LocalVal = undefined;
......@@ -4557,14 +4456,7 @@ fn whileExpr(
45574456 loop_scope.break_count += 1;
45584457 const then_result = try expr(&then_scope, then_sub_scope, loop_scope.break_result_loc, while_full.ast.then_expr);
45594458
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);
45684460 defer else_scope.instructions.deinit(astgen.gpa);
45694461
45704462 const else_node = while_full.ast.else_expr;
......@@ -4659,25 +4551,11 @@ fn forExpr(
46594551 const loop_block = try parent_gz.addBlock(loop_tag, node);
46604552 try parent_gz.instructions.append(astgen.gpa, loop_block);
46614553
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);
46704555 loop_scope.setBreakResultLoc(rl);
46714556 defer loop_scope.instructions.deinit(astgen.gpa);
46724557
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);
46814559 defer cond_scope.instructions.deinit(astgen.gpa);
46824560
46834561 // check condition i < array_expr.len
......@@ -4714,14 +4592,7 @@ fn forExpr(
47144592 });
47154593 }
47164594
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);
47254596 defer then_scope.instructions.deinit(astgen.gpa);
47264597
47274598 var payload_val_scope: Scope.LocalVal = undefined;
......@@ -4773,14 +4644,7 @@ fn forExpr(
47734644 loop_scope.break_count += 1;
47744645 const then_result = try expr(&then_scope, then_sub_scope, loop_scope.break_result_loc, for_full.ast.then_expr);
47754646
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);
47844648 defer else_scope.instructions.deinit(astgen.gpa);
47854649
47864650 const else_node = for_full.ast.else_expr;
......@@ -5076,14 +4940,7 @@ fn switchExpr(
50764940 var multi_cases_payload = ArrayListUnmanaged(u32){};
50774941 defer multi_cases_payload.deinit(gpa);
50784942
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);
50874944 block_scope.setBreakResultLoc(rl);
50884945 defer block_scope.instructions.deinit(gpa);
50894946
......@@ -5091,14 +4948,7 @@ fn switchExpr(
50914948 const switch_block = try parent_gz.addBlock(undefined, switch_node);
50924949
50934950 // 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);
51024952 defer case_scope.instructions.deinit(gpa);
51034953
51044954 // Do the else/`_` first because it goes first in the payload.
......@@ -5846,57 +5696,109 @@ fn asmExpr(
58465696 const tree = &astgen.file.tree;
58475697 const main_tokens = tree.nodes.items(.main_token);
58485698 const node_datas = tree.nodes.items(.data);
5699 const token_tags = tree.tokens.items(.tag);
58495700
58505701 const asm_source = try comptimeExpr(gz, scope, .{ .ty = .const_slice_u8_type }, full.ast.template);
58515702
58525703 // 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", .{});
58585709 }
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 };
58675743 }
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 }
58745745
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 }
58775765
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 }
58825791 }
58835792
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,
58865795 .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],
58905801 });
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
59005802 return rvalue(gz, scope, rl, result, node);
59015803}
59025804
......@@ -5982,14 +5884,7 @@ fn asRlPtr(
59825884 // as well as the store instruction, instead passing the result as an rvalue.
59835885 const astgen = parent_gz.astgen;
59845886
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);
59935888 defer as_scope.instructions.deinit(astgen.gpa);
59945889
59955890 as_scope.rl_ptr = try as_scope.addBin(.coerce_result_ptr, dest_type, result_ptr);
......@@ -6701,14 +6596,8 @@ fn cImport(
67016596 const astgen = gz.astgen;
67026597 const gpa = astgen.gpa;
67036598
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;
67126601 defer block_scope.instructions.deinit(gpa);
67136602
67146603 const block_inst = try gz.addBlock(.c_import, node);
......@@ -6802,43 +6691,44 @@ fn callExpr(
68026691}
68036692
68046693pub 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 },
68176697 .{ "c_int", .c_int_type },
6818 .{ "c_uint", .c_uint_type },
68196698 .{ "c_long", .c_long_type },
6820 .{ "c_ulong", .c_ulong_type },
6699 .{ "c_longdouble", .c_longdouble_type },
68216700 .{ "c_longlong", .c_longlong_type },
6701 .{ "c_short", .c_short_type },
6702 .{ "c_uint", .c_uint_type },
6703 .{ "c_ulong", .c_ulong_type },
68226704 .{ "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 },
68246710 .{ "f16", .f16_type },
68256711 .{ "f32", .f32_type },
68266712 .{ "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 },
68356720 .{ "noreturn", .noreturn_type },
6836 .{ "null", .null_type },
6837 .{ "undefined", .undefined_type },
6838 .{ "undefined", .undef },
68396721 .{ "null", .null_value },
68406722 .{ "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 },
68426732});
68436733
68446734fn nodeMayNeedMemoryLocation(tree: *const ast.Tree, start_node: ast.Node.Index) bool {
src/Module.zig+95-2
......@@ -1085,6 +1085,21 @@ pub const Scope = struct {
10851085 /// a result location pointer.
10861086 labeled_store_to_block_ptr_list: ArrayListUnmanaged(Zir.Inst.Index) = .{},
10871087
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
10881103 pub const Label = struct {
10891104 token: ast.TokenIndex,
10901105 block_inst: Zir.Inst.Index,
......@@ -1674,9 +1689,9 @@ pub const Scope = struct {
16741689 @as(usize, @boolToInt(args.type_inst != .none)) +
16751690 @as(usize, @boolToInt(args.align_inst != .none)),
16761691 );
1677 const payload_index = gz.astgen.addExtra(Zir.Inst.AllocExtended{
1692 const payload_index = gz.astgen.addExtraAssumeCapacity(Zir.Inst.AllocExtended{
16781693 .src_node = gz.nodeIndexToRelative(args.node),
1679 }) catch unreachable; // ensureUnusedCapacity above
1694 });
16801695 if (args.type_inst != .none) {
16811696 astgen.extra.appendAssumeCapacity(@enumToInt(args.type_inst));
16821697 }
......@@ -1703,6 +1718,64 @@ pub const Scope = struct {
17031718 return gz.indexToRef(new_index);
17041719 }
17051720
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
17061779 /// Note that this returns a `Zir.Inst.Index` not a ref.
17071780 /// Does *not* append the block instruction to the scope.
17081781 /// Leaves the `payload_index` field undefined.
......@@ -2209,6 +2282,18 @@ pub const SrcLoc = struct {
22092282 const token_starts = tree.tokens.items(.start);
22102283 return token_starts[tok_index];
22112284 },
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 },
22122297 }
22132298 }
22142299};
......@@ -2368,6 +2453,12 @@ pub const LazySrcLoc = union(enum) {
23682453 /// the return type node.
23692454 /// The Decl is determined contextually.
23702455 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,
23712462
23722463 /// Upgrade to a `SrcLoc` based on the `Decl` or file in the provided scope.
23732464 pub fn toSrcLoc(lazy: LazySrcLoc, scope: *Scope) SrcLoc {
......@@ -2407,6 +2498,7 @@ pub const LazySrcLoc = union(enum) {
24072498 .node_offset_switch_range,
24082499 .node_offset_fn_type_cc,
24092500 .node_offset_fn_type_ret_ty,
2501 .node_offset_anyframe_type,
24102502 => .{
24112503 .file_scope = scope.getFileScope(),
24122504 .parent_decl_node = scope.srcDecl().?.src_node,
......@@ -2453,6 +2545,7 @@ pub const LazySrcLoc = union(enum) {
24532545 .node_offset_switch_range,
24542546 .node_offset_fn_type_cc,
24552547 .node_offset_fn_type_ret_ty,
2548 .node_offset_anyframe_type,
24562549 => .{
24572550 .file_scope = decl.getFileScope(),
24582551 .parent_decl_node = decl.src_node,
src/Sema.zig+59-26
......@@ -138,14 +138,13 @@ pub fn analyzeBody(
138138 .alloc_inferred_comptime => try sema.zirAllocInferredComptime(block, inst),
139139 .alloc_mut => try sema.zirAllocMut(block, inst),
140140 .alloc_comptime => try sema.zirAllocComptime(block, inst),
141 .anyframe_type => try sema.zirAnyframeType(block, inst),
141142 .array_cat => try sema.zirArrayCat(block, inst),
142143 .array_mul => try sema.zirArrayMul(block, inst),
143144 .array_type => try sema.zirArrayType(block, inst),
144145 .array_type_sentinel => try sema.zirArrayTypeSentinel(block, inst),
145146 .as => try sema.zirAs(block, inst),
146147 .as_node => try sema.zirAsNode(block, inst),
147 .@"asm" => try sema.zirAsm(block, inst, false),
148 .asm_volatile => try sema.zirAsm(block, inst, true),
149148 .bit_and => try sema.zirBitwise(block, inst, .bit_and),
150149 .bit_not => try sema.zirBitNot(block, inst),
151150 .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
518517 .frame_address => return sema.zirFrameAddress( block, extended),
519518 .alloc => return sema.zirAllocExtended( block, extended),
520519 .builtin_extern => return sema.zirBuiltinExtern( block, extended),
520 .@"asm" => return sema.zirAsm( block, extended),
521521 .c_undef => return sema.zirCUndef( block, extended),
522522 .c_include => return sema.zirCInclude( block, extended),
523523 .c_define => return sema.zirCDefine( block, extended),
......@@ -2173,6 +2173,19 @@ fn zirArrayTypeSentinel(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index)
21732173 return sema.mod.constType(sema.arena, .unneeded, array_ty);
21742174}
21752175
2176fn 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
21762189fn zirErrorUnionType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
21772190 const tracy = trace(@src());
21782191 defer tracy.end();
......@@ -4394,42 +4407,62 @@ fn zirLoad(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*I
43944407fn zirAsm(
43954408 sema: *Sema,
43964409 block: *Scope.Block,
4397 inst: Zir.Inst.Index,
4398 is_volatile: bool,
4410 extended: Zir.Inst.Extended.InstData,
43994411) InnerError!*Inst {
44004412 const tracy = trace(@src());
44014413 defer tracy.end();
44024414
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 };
44084419 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 }
44094428
44104429 var extra_i = extra.end;
4430 var output_type_bits = extra.data.output_type_bits;
4431
44114432 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);
44154445 break :blk Output{
44164446 .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),
44184448 };
4419 } else null;
4449 };
44204450
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);
44244453
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);
44324463 }
4464
4465 const clobbers = try sema.arena.alloc([]const u8, clobbers_len);
44334466 for (clobbers) |*name| {
44344467 name.* = sema.code.nullTerminatedString(sema.code.extra[extra_i]);
44354468 extra_i += 1;
......@@ -5408,7 +5441,7 @@ fn zirFuncExtended(
54085441
54095442 var extra_index: usize = extra.end;
54105443 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]);
54125445 extra_index += 1;
54135446 return sema.mod.fail(&block.base, src, "TODO: implement Sema func lib name", .{});
54145447 }
......@@ -5428,7 +5461,7 @@ fn zirFuncExtended(
54285461 } else .Unspecified;
54295462
54305463 const param_types = sema.code.refSlice(extra_index, extra.data.param_types_len);
5431 extra_index += 1;
5464 extra_index += param_types.len;
54325465
54335466 const body = sema.code.extra[extra_index..][0..extra.data.body_len];
54345467
src/Zir.zig+153-57
......@@ -60,7 +60,8 @@ pub fn extraData(code: Zir, comptime T: type, index: usize) struct { data: T, en
6060 @field(result, field.name) = switch (field.field_type) {
6161 u32 => code.extra[i],
6262 Inst.Ref => @intToEnum(Inst.Ref, code.extra[i]),
63 else => unreachable,
63 i32 => @bitCast(i32, code.extra[i]),
64 else => @compileError("bad field type"),
6465 };
6566 i += 1;
6667 }
......@@ -165,18 +166,15 @@ pub const Inst = struct {
165166 /// error if the indexable object is not indexable.
166167 /// Uses the `un_node` field. The AST node is the for loop node.
167168 indexable_ptr_len,
169 /// Create a `anyframe->T` type.
170 /// Uses the `un_node` field.
171 anyframe_type,
168172 /// Type coercion. No source location attached.
169173 /// Uses the `bin` field.
170174 as,
171175 /// Type coercion to the function's return type.
172176 /// Uses the `pl_node` field. Payload is `As`. AST node could be many things.
173177 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,
180178 /// Bitwise AND. `&`
181179 bit_and,
182180 /// Bitcast a value to a different type.
......@@ -967,10 +965,9 @@ pub const Inst = struct {
967965 .array_type_sentinel,
968966 .elem_type,
969967 .indexable_ptr_len,
968 .anyframe_type,
970969 .as,
971970 .as_node,
972 .@"asm",
973 .asm_volatile,
974971 .bit_and,
975972 .bitcast,
976973 .bitcast_result_ptr,
......@@ -1259,6 +1256,14 @@ pub const Inst = struct {
12591256 /// The `@extern` builtin.
12601257 /// `operand` is payload index to `BinNode`.
12611258 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",
12621267 /// `operand` is payload index to `UnNode`.
12631268 c_undef,
12641269 /// `operand` is payload index to `UnNode`.
......@@ -1313,6 +1318,8 @@ pub const Inst = struct {
13131318 i32_type,
13141319 u64_type,
13151320 i64_type,
1321 u128_type,
1322 i128_type,
13161323 usize_type,
13171324 isize_type,
13181325 c_short_type,
......@@ -1336,17 +1343,10 @@ pub const Inst = struct {
13361343 comptime_int_type,
13371344 comptime_float_type,
13381345 noreturn_type,
1346 anyframe_type,
13391347 null_type,
13401348 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,
13471349 enum_literal_type,
1348 manyptr_u8_type,
1349 manyptr_const_u8_type,
13501350 atomic_ordering_type,
13511351 atomic_rmw_op_type,
13521352 calling_convention_type,
......@@ -1355,6 +1355,14 @@ pub const Inst = struct {
13551355 call_options_type,
13561356 export_options_type,
13571357 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,
13581366
13591367 /// `undefined` (untyped)
13601368 undef,
......@@ -1418,6 +1426,14 @@ pub const Inst = struct {
14181426 .ty = Type.initTag(.type),
14191427 .val = Value.initTag(.i64_type),
14201428 },
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 },
14211437 .usize_type = .{
14221438 .ty = Type.initTag(.type),
14231439 .val = Value.initTag(.usize_type),
......@@ -1510,6 +1526,10 @@ pub const Inst = struct {
15101526 .ty = Type.initTag(.type),
15111527 .val = Value.initTag(.noreturn_type),
15121528 },
1529 .anyframe_type = .{
1530 .ty = Type.initTag(.type),
1531 .val = Value.initTag(.anyframe_type),
1532 },
15131533 .null_type = .{
15141534 .ty = Type.initTag(.type),
15151535 .val = Value.initTag(.null_type),
......@@ -1806,17 +1826,35 @@ pub const Inst = struct {
18061826 }
18071827 };
18081828
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.
18141833 pub const Asm = struct {
1834 src_node: i32,
18151835 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 };
18201858 };
18211859
18221860 /// Trailing:
......@@ -2298,6 +2336,7 @@ const Writer = struct {
22982336 .alloc_mut,
22992337 .alloc_comptime,
23002338 .indexable_ptr_len,
2339 .anyframe_type,
23012340 .bit_not,
23022341 .bool_not,
23032342 .negate,
......@@ -2430,10 +2469,6 @@ const Writer = struct {
24302469 .builtin_async_call,
24312470 => try self.writePlNode(stream, inst),
24322471
2433 .@"asm",
2434 .asm_volatile,
2435 => try self.writePlNodeAsm(stream, inst),
2436
24372472 .error_set_decl => try self.writePlNodeErrorSetDecl(stream, inst),
24382473
24392474 .add_with_overflow,
......@@ -2603,7 +2638,9 @@ const Writer = struct {
26032638 .builtin_src,
26042639 => try self.writeExtNode(stream, extended),
26052640
2606 .func,
2641 .@"asm" => try self.writeAsm(stream, extended),
2642 .func => try self.writeFuncExtended(stream, extended),
2643
26072644 .alloc,
26082645 .builtin_extern,
26092646 .c_undef,
......@@ -2794,49 +2831,74 @@ const Writer = struct {
27942831 try self.writeSrc(stream, inst_data.src());
27952832 }
27962833
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;
28012841
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;
28102848 {
28112849 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 }
28172868 }
28182869 }
28192870 {
28202871 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 }
28262886 }
28272887 }
28282888 {
28292889 var i: usize = 0;
2830 while (i < extra.data.clobbers_len) : (i += 1) {
2890 while (i < clobbers_len) : (i += 1) {
28312891 const str_index = self.code.extra[extra_i];
28322892 extra_i += 1;
28332893 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 }
28352898 }
28362899 }
2837 try self.writeInstRef(stream, extra.data.asm_source);
28382900 try stream.writeAll(") ");
2839 try self.writeSrc(stream, inst_data.src());
2901 try self.writeSrc(stream, src);
28402902 }
28412903
28422904 fn writePlNodeOverflowArithmetic(self: *Writer, stream: anytype, inst: Inst.Index) !void {
......@@ -3467,6 +3529,40 @@ const Writer = struct {
34673529 );
34683530 }
34693531
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
34703566 fn writeBoolBr(self: *Writer, stream: anytype, inst: Inst.Index) !void {
34713567 const inst_data = self.code.instructions.items(.data)[inst].bool_br;
34723568 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 {
9595
9696 .anyerror_void_error_union, .error_union => return .ErrorUnion,
9797
98 .anyframe_T, .@"anyframe" => return .AnyFrame,
99
98100 .empty_struct,
99101 .empty_struct_literal,
100102 .@"struct",
......@@ -620,6 +622,7 @@ pub const Type = extern union {
620622 .call_options,
621623 .export_options,
622624 .extern_options,
625 .@"anyframe",
623626 => unreachable,
624627
625628 .array_u8,
......@@ -637,6 +640,7 @@ pub const Type = extern union {
637640 .optional,
638641 .optional_single_mut_pointer,
639642 .optional_single_const_pointer,
643 .anyframe_T,
640644 => return self.copyPayloadShallow(allocator, Payload.ElemType),
641645
642646 .int_signed,
......@@ -754,6 +758,7 @@ pub const Type = extern union {
754758 .void,
755759 .type,
756760 .anyerror,
761 .@"anyframe",
757762 .comptime_int,
758763 .comptime_float,
759764 .noreturn,
......@@ -820,6 +825,12 @@ pub const Type = extern union {
820825 continue;
821826 },
822827
828 .anyframe_T => {
829 const return_type = ty.castTag(.anyframe_T).?.data;
830 try writer.print("anyframe->", .{});
831 ty = return_type;
832 continue;
833 },
823834 .array_u8 => {
824835 const len = ty.castTag(.array_u8).?.data;
825836 return writer.print("[{d}]u8", .{len});
......@@ -994,6 +1005,7 @@ pub const Type = extern union {
9941005 .void => return Value.initTag(.void_type),
9951006 .type => return Value.initTag(.type_type),
9961007 .anyerror => return Value.initTag(.anyerror_type),
1008 .@"anyframe" => return Value.initTag(.anyframe_type),
9971009 .comptime_int => return Value.initTag(.comptime_int_type),
9981010 .comptime_float => return Value.initTag(.comptime_float_type),
9991011 .noreturn => return Value.initTag(.noreturn_type),
......@@ -1075,6 +1087,8 @@ pub const Type = extern union {
10751087 .call_options,
10761088 .export_options,
10771089 .extern_options,
1090 .@"anyframe",
1091 .anyframe_T,
10781092 => true,
10791093
10801094 .@"struct" => {
......@@ -1223,6 +1237,8 @@ pub const Type = extern union {
12231237 .pointer,
12241238 .manyptr_u8,
12251239 .manyptr_const_u8,
1240 .@"anyframe",
1241 .anyframe_T,
12261242 => return @divExact(target.cpu.arch.ptrBitWidth(), 8),
12271243
12281244 .c_short => return @divExact(CType.short.sizeInBits(target), 8),
......@@ -1388,7 +1404,11 @@ pub const Type = extern union {
13881404 .i64, .u64 => return 8,
13891405 .u128, .i128 => return 16,
13901406
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),
13921412
13931413 .const_slice,
13941414 .mut_slice,
......@@ -1536,7 +1556,11 @@ pub const Type = extern union {
15361556 .i64, .u64, .f64 => 64,
15371557 .u128, .i128, .f128 => 128,
15381558
1539 .isize, .usize => target.cpu.arch.ptrBitWidth(),
1559 .isize,
1560 .usize,
1561 .@"anyframe",
1562 .anyframe_T,
1563 => target.cpu.arch.ptrBitWidth(),
15401564
15411565 .const_slice,
15421566 .mut_slice,
......@@ -2256,6 +2280,8 @@ pub const Type = extern union {
22562280 .call_options,
22572281 .export_options,
22582282 .extern_options,
2283 .@"anyframe",
2284 .anyframe_T,
22592285 => return null,
22602286
22612287 .@"struct" => {
......@@ -2666,9 +2692,10 @@ pub const Type = extern union {
26662692 comptime_int,
26672693 comptime_float,
26682694 noreturn,
2695 @"anyframe",
2696 @"null",
2697 @"undefined",
26692698 enum_literal,
2670 manyptr_u8,
2671 manyptr_const_u8,
26722699 atomic_ordering,
26732700 atomic_rmw_op,
26742701 calling_convention,
......@@ -2677,15 +2704,15 @@ pub const Type = extern union {
26772704 call_options,
26782705 export_options,
26792706 extern_options,
2680 @"null",
2681 @"undefined",
2707 manyptr_u8,
2708 manyptr_const_u8,
26822709 fn_noreturn_no_args,
26832710 fn_void_no_args,
26842711 fn_naked_noreturn_no_args,
26852712 fn_ccc_void_no_args,
26862713 single_const_pointer_to_comptime_int,
2687 anyerror_void_error_union,
26882714 const_slice_u8,
2715 anyerror_void_error_union,
26892716 /// This is a special type for variadic parameters of a function call.
26902717 /// Casts to it will validate that the type can be passed to a c calling convetion function.
26912718 var_args_param,
......@@ -2719,6 +2746,7 @@ pub const Type = extern union {
27192746 optional_single_mut_pointer,
27202747 optional_single_const_pointer,
27212748 error_union,
2749 anyframe_T,
27222750 error_set,
27232751 error_set_single,
27242752 empty_struct,
......@@ -2790,6 +2818,7 @@ pub const Type = extern union {
27902818 .call_options,
27912819 .export_options,
27922820 .extern_options,
2821 .@"anyframe",
27932822 => @compileError("Type Tag " ++ @tagName(t) ++ " has no payload"),
27942823
27952824 .array_u8,
......@@ -2807,6 +2836,7 @@ pub const Type = extern union {
28072836 .optional,
28082837 .optional_single_mut_pointer,
28092838 .optional_single_const_pointer,
2839 .anyframe_T,
28102840 => Payload.ElemType,
28112841
28122842 .int_signed,
src/value.zig+15-8
......@@ -55,17 +55,10 @@ pub const Value = extern union {
5555 comptime_int_type,
5656 comptime_float_type,
5757 noreturn_type,
58 anyframe_type,
5859 null_type,
5960 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,
6661 enum_literal_type,
67 manyptr_u8_type,
68 manyptr_const_u8_type,
6962 atomic_ordering_type,
7063 atomic_rmw_op_type,
7164 calling_convention_type,
......@@ -74,6 +67,14 @@ pub const Value = extern union {
7467 call_options_type,
7568 export_options_type,
7669 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,
7778
7879 undef,
7980 zero,
......@@ -166,6 +167,7 @@ pub const Value = extern union {
166167 .fn_naked_noreturn_no_args_type,
167168 .fn_ccc_void_no_args_type,
168169 .single_const_pointer_to_comptime_int_type,
170 .anyframe_type,
169171 .const_slice_u8_type,
170172 .enum_literal_type,
171173 .undef,
......@@ -334,6 +336,7 @@ pub const Value = extern union {
334336 .fn_naked_noreturn_no_args_type,
335337 .fn_ccc_void_no_args_type,
336338 .single_const_pointer_to_comptime_int_type,
339 .anyframe_type,
337340 .const_slice_u8_type,
338341 .enum_literal_type,
339342 .undef,
......@@ -502,6 +505,7 @@ pub const Value = extern union {
502505 .fn_naked_noreturn_no_args_type => return out_stream.writeAll("fn() callconv(.Naked) noreturn"),
503506 .fn_ccc_void_no_args_type => return out_stream.writeAll("fn() callconv(.C) void"),
504507 .single_const_pointer_to_comptime_int_type => return out_stream.writeAll("*const comptime_int"),
508 .anyframe_type => return out_stream.writeAll("anyframe"),
505509 .const_slice_u8_type => return out_stream.writeAll("[]const u8"),
506510 .enum_literal_type => return out_stream.writeAll("@Type(.EnumLiteral)"),
507511 .manyptr_u8_type => return out_stream.writeAll("[*]u8"),
......@@ -633,6 +637,7 @@ pub const Value = extern union {
633637 .fn_naked_noreturn_no_args_type => Type.initTag(.fn_naked_noreturn_no_args),
634638 .fn_ccc_void_no_args_type => Type.initTag(.fn_ccc_void_no_args),
635639 .single_const_pointer_to_comptime_int_type => Type.initTag(.single_const_pointer_to_comptime_int),
640 .anyframe_type => Type.initTag(.@"anyframe"),
636641 .const_slice_u8_type => Type.initTag(.const_slice_u8),
637642 .enum_literal_type => Type.initTag(.enum_literal),
638643 .manyptr_u8_type => Type.initTag(.manyptr_u8),
......@@ -1070,6 +1075,7 @@ pub const Value = extern union {
10701075 .fn_naked_noreturn_no_args_type,
10711076 .fn_ccc_void_no_args_type,
10721077 .single_const_pointer_to_comptime_int_type,
1078 .anyframe_type,
10731079 .const_slice_u8_type,
10741080 .enum_literal_type,
10751081 .ty,
......@@ -1338,6 +1344,7 @@ pub const Value = extern union {
13381344 .fn_naked_noreturn_no_args_type,
13391345 .fn_ccc_void_no_args_type,
13401346 .single_const_pointer_to_comptime_int_type,
1347 .anyframe_type,
13411348 .const_slice_u8_type,
13421349 .enum_literal_type,
13431350 .manyptr_u8_type,