authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-11-25 04:11:46-05:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2023-11-25 04:11:46-05:00
log648f592db10d3354dcf7e36264291dd82f4d0e3a
tree3658d6c3541a2ae95321d25ef84707f0ab7ef669
parent18608223ef5e588598d21dfe71678dbc62f320e4
parentc6e02044da8ce1176fa67fe2d1c6de7802927171
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #18109 from nektro/std-compiler

compiler: move BuiltinFn and AstRlAnnotate to std.zig namespace

9 files changed, 2129 insertions(+), 2137 deletions(-)

CMakeLists.txt+1-1
......@@ -508,6 +508,7 @@ set(ZIG_STAGE2_SOURCES
508508 "${CMAKE_SOURCE_DIR}/lib/std/unicode.zig"
509509 "${CMAKE_SOURCE_DIR}/lib/std/zig.zig"
510510 "${CMAKE_SOURCE_DIR}/lib/std/zig/Ast.zig"
511 "${CMAKE_SOURCE_DIR}/lib/std/zig/AstRlAnnotate.zig"
511512 "${CMAKE_SOURCE_DIR}/lib/std/zig/CrossTarget.zig"
512513 "${CMAKE_SOURCE_DIR}/lib/std/zig/c_builtins.zig"
513514 "${CMAKE_SOURCE_DIR}/lib/std/zig/Parse.zig"
......@@ -521,7 +522,6 @@ set(ZIG_STAGE2_SOURCES
521522 "${CMAKE_SOURCE_DIR}/lib/std/zig/tokenizer.zig"
522523 "${CMAKE_SOURCE_DIR}/src/Air.zig"
523524 "${CMAKE_SOURCE_DIR}/src/AstGen.zig"
524 "${CMAKE_SOURCE_DIR}/src/AstRlAnnotate.zig"
525525 "${CMAKE_SOURCE_DIR}/src/Compilation.zig"
526526 "${CMAKE_SOURCE_DIR}/src/Liveness.zig"
527527 "${CMAKE_SOURCE_DIR}/src/Module.zig"
lib/std/zig.zig+2
......@@ -17,6 +17,8 @@ pub const primitives = @import("zig/primitives.zig");
1717pub const Ast = @import("zig/Ast.zig");
1818pub const system = @import("zig/system.zig");
1919pub const CrossTarget = @import("zig/CrossTarget.zig");
20pub const BuiltinFn = @import("zig/BuiltinFn.zig");
21pub const AstRlAnnotate = @import("zig/AstRlAnnotate.zig");
2022
2123// Character literal parsing
2224pub const ParsedCharLiteral = string_literal.ParsedCharLiteral;
lib/std/zig/AstRlAnnotate.zig created+1105
......@@ -0,0 +1,1105 @@
1//! AstRlAnnotate is a simple pass which runs over the AST before AstGen to
2//! determine which expressions require result locations.
3//!
4//! In some cases, AstGen can choose whether to provide a result pointer or to
5//! just use standard `break` instructions from a block. The latter choice can
6//! result in more efficient ZIR and runtime code, but does not allow for RLS to
7//! occur. Thus, we want to provide a real result pointer (from an alloc) only
8//! when necessary.
9//!
10//! To achive this, we need to determine which expressions require a result
11//! pointer. This pass is reponsible for analyzing all syntax forms which may
12//! provide a result location and, if sub-expressions consume this result
13//! pointer non-trivially (e.g. writing through field pointers), marking the
14//! node as requiring a result location.
15
16const std = @import("std");
17const AstRlAnnotate = @This();
18const Ast = std.zig.Ast;
19const Allocator = std.mem.Allocator;
20const AutoHashMapUnmanaged = std.AutoHashMapUnmanaged;
21const BuiltinFn = std.zig.BuiltinFn;
22const assert = std.debug.assert;
23
24gpa: Allocator,
25arena: Allocator,
26tree: *const Ast,
27
28/// Certain nodes are placed in this set under the following conditions:
29/// * if-else: either branch consumes the result location
30/// * labeled block: any break consumes the result location
31/// * switch: any prong consumes the result location
32/// * orelse/catch: the RHS expression consumes the result location
33/// * while/for: any break consumes the result location
34/// * @as: the second operand consumes the result location
35/// * const: the init expression consumes the result location
36/// * return: the return expression consumes the result location
37nodes_need_rl: RlNeededSet = .{},
38
39pub const RlNeededSet = AutoHashMapUnmanaged(Ast.Node.Index, void);
40
41const ResultInfo = packed struct {
42 /// Do we have a known result type?
43 have_type: bool,
44 /// Do we (potentially) have a result pointer? Note that this pointer's type
45 /// may not be known due to it being an inferred alloc.
46 have_ptr: bool,
47
48 const none: ResultInfo = .{ .have_type = false, .have_ptr = false };
49 const typed_ptr: ResultInfo = .{ .have_type = true, .have_ptr = true };
50 const inferred_ptr: ResultInfo = .{ .have_type = false, .have_ptr = true };
51 const type_only: ResultInfo = .{ .have_type = true, .have_ptr = false };
52};
53
54/// A labeled block or a loop. When this block is broken from, `consumes_res_ptr`
55/// should be set if the break expression consumed the result pointer.
56const Block = struct {
57 parent: ?*Block,
58 label: ?[]const u8,
59 is_loop: bool,
60 ri: ResultInfo,
61 consumes_res_ptr: bool,
62};
63
64pub fn annotate(gpa: Allocator, arena: Allocator, tree: Ast) Allocator.Error!RlNeededSet {
65 var astrl: AstRlAnnotate = .{
66 .gpa = gpa,
67 .arena = arena,
68 .tree = &tree,
69 };
70 defer astrl.deinit(gpa);
71
72 if (tree.errors.len != 0) {
73 // We can't perform analysis on a broken AST. AstGen will not run in
74 // this case.
75 return .{};
76 }
77
78 for (tree.containerDeclRoot().ast.members) |member_node| {
79 _ = try astrl.expr(member_node, null, ResultInfo.none);
80 }
81
82 return astrl.nodes_need_rl.move();
83}
84
85fn deinit(astrl: *AstRlAnnotate, gpa: Allocator) void {
86 astrl.nodes_need_rl.deinit(gpa);
87}
88
89fn containerDecl(
90 astrl: *AstRlAnnotate,
91 block: ?*Block,
92 full: Ast.full.ContainerDecl,
93) !void {
94 const tree = astrl.tree;
95 const token_tags = tree.tokens.items(.tag);
96 switch (token_tags[full.ast.main_token]) {
97 .keyword_struct => {
98 if (full.ast.arg != 0) {
99 _ = try astrl.expr(full.ast.arg, block, ResultInfo.type_only);
100 }
101 for (full.ast.members) |member_node| {
102 _ = try astrl.expr(member_node, block, ResultInfo.none);
103 }
104 },
105 .keyword_union => {
106 if (full.ast.arg != 0) {
107 _ = try astrl.expr(full.ast.arg, block, ResultInfo.type_only);
108 }
109 for (full.ast.members) |member_node| {
110 _ = try astrl.expr(member_node, block, ResultInfo.none);
111 }
112 },
113 .keyword_enum => {
114 if (full.ast.arg != 0) {
115 _ = try astrl.expr(full.ast.arg, block, ResultInfo.type_only);
116 }
117 for (full.ast.members) |member_node| {
118 _ = try astrl.expr(member_node, block, ResultInfo.none);
119 }
120 },
121 .keyword_opaque => {
122 for (full.ast.members) |member_node| {
123 _ = try astrl.expr(member_node, block, ResultInfo.none);
124 }
125 },
126 else => unreachable,
127 }
128}
129
130/// Returns true if `rl` provides a result pointer and the expression consumes it.
131fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultInfo) Allocator.Error!bool {
132 const tree = astrl.tree;
133 const token_tags = tree.tokens.items(.tag);
134 const node_datas = tree.nodes.items(.data);
135 const node_tags = tree.nodes.items(.tag);
136 switch (node_tags[node]) {
137 .root,
138 .switch_case_one,
139 .switch_case_inline_one,
140 .switch_case,
141 .switch_case_inline,
142 .switch_range,
143 .for_range,
144 .asm_output,
145 .asm_input,
146 => unreachable,
147
148 .@"errdefer", .@"defer" => {
149 _ = try astrl.expr(node_datas[node].rhs, block, ResultInfo.none);
150 return false;
151 },
152
153 .container_field_init,
154 .container_field_align,
155 .container_field,
156 => {
157 const full = tree.fullContainerField(node).?;
158 _ = try astrl.expr(full.ast.type_expr, block, ResultInfo.type_only);
159 if (full.ast.align_expr != 0) {
160 _ = try astrl.expr(full.ast.align_expr, block, ResultInfo.type_only);
161 }
162 if (full.ast.value_expr != 0) {
163 _ = try astrl.expr(full.ast.value_expr, block, ResultInfo.type_only);
164 }
165 return false;
166 },
167 .@"usingnamespace" => {
168 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.type_only);
169 return false;
170 },
171 .test_decl => {
172 _ = try astrl.expr(node_datas[node].rhs, block, ResultInfo.none);
173 return false;
174 },
175 .global_var_decl,
176 .local_var_decl,
177 .simple_var_decl,
178 .aligned_var_decl,
179 => {
180 const full = tree.fullVarDecl(node).?;
181 const init_ri = if (full.ast.type_node != 0) init_ri: {
182 _ = try astrl.expr(full.ast.type_node, block, ResultInfo.type_only);
183 break :init_ri ResultInfo.typed_ptr;
184 } else ResultInfo.inferred_ptr;
185 if (full.ast.init_node == 0) {
186 // No init node, so we're done.
187 return false;
188 }
189 switch (token_tags[full.ast.mut_token]) {
190 .keyword_const => {
191 const init_consumes_rl = try astrl.expr(full.ast.init_node, block, init_ri);
192 if (init_consumes_rl) {
193 try astrl.nodes_need_rl.putNoClobber(astrl.gpa, node, {});
194 }
195 return false;
196 },
197 .keyword_var => {
198 // We'll create an alloc either way, so don't care if the
199 // result pointer is consumed.
200 _ = try astrl.expr(full.ast.init_node, block, init_ri);
201 return false;
202 },
203 else => unreachable,
204 }
205 },
206 .assign_destructure => {
207 const lhs_count = tree.extra_data[node_datas[node].lhs];
208 const all_lhs = tree.extra_data[node_datas[node].lhs + 1 ..][0..lhs_count];
209 for (all_lhs) |lhs| {
210 _ = try astrl.expr(lhs, block, ResultInfo.none);
211 }
212 // We don't need to gather any meaningful data here, because destructures always use RLS
213 _ = try astrl.expr(node_datas[node].rhs, block, ResultInfo.none);
214 return false;
215 },
216 .assign => {
217 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none);
218 _ = try astrl.expr(node_datas[node].rhs, block, ResultInfo.typed_ptr);
219 return false;
220 },
221 .assign_shl,
222 .assign_shl_sat,
223 .assign_shr,
224 .assign_bit_and,
225 .assign_bit_or,
226 .assign_bit_xor,
227 .assign_div,
228 .assign_sub,
229 .assign_sub_wrap,
230 .assign_sub_sat,
231 .assign_mod,
232 .assign_add,
233 .assign_add_wrap,
234 .assign_add_sat,
235 .assign_mul,
236 .assign_mul_wrap,
237 .assign_mul_sat,
238 => {
239 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none);
240 _ = try astrl.expr(node_datas[node].rhs, block, ResultInfo.none);
241 return false;
242 },
243 .shl, .shr => {
244 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none);
245 _ = try astrl.expr(node_datas[node].rhs, block, ResultInfo.type_only);
246 return false;
247 },
248 .add,
249 .add_wrap,
250 .add_sat,
251 .sub,
252 .sub_wrap,
253 .sub_sat,
254 .mul,
255 .mul_wrap,
256 .mul_sat,
257 .div,
258 .mod,
259 .shl_sat,
260 .bit_and,
261 .bit_or,
262 .bit_xor,
263 .bang_equal,
264 .equal_equal,
265 .greater_than,
266 .greater_or_equal,
267 .less_than,
268 .less_or_equal,
269 .array_cat,
270 => {
271 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none);
272 _ = try astrl.expr(node_datas[node].rhs, block, ResultInfo.none);
273 return false;
274 },
275 .array_mult => {
276 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none);
277 _ = try astrl.expr(node_datas[node].rhs, block, ResultInfo.type_only);
278 return false;
279 },
280 .error_union, .merge_error_sets => {
281 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none);
282 _ = try astrl.expr(node_datas[node].rhs, block, ResultInfo.none);
283 return false;
284 },
285 .bool_and,
286 .bool_or,
287 => {
288 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.type_only);
289 _ = try astrl.expr(node_datas[node].rhs, block, ResultInfo.type_only);
290 return false;
291 },
292 .bool_not => {
293 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.type_only);
294 return false;
295 },
296 .bit_not, .negation, .negation_wrap => {
297 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none);
298 return false;
299 },
300
301 // These nodes are leaves and never consume a result location.
302 .identifier,
303 .string_literal,
304 .multiline_string_literal,
305 .number_literal,
306 .unreachable_literal,
307 .asm_simple,
308 .@"asm",
309 .enum_literal,
310 .error_value,
311 .anyframe_literal,
312 .@"continue",
313 .char_literal,
314 .error_set_decl,
315 => return false,
316
317 .builtin_call_two, .builtin_call_two_comma => {
318 if (node_datas[node].lhs == 0) {
319 return astrl.builtinCall(block, ri, node, &.{});
320 } else if (node_datas[node].rhs == 0) {
321 return astrl.builtinCall(block, ri, node, &.{node_datas[node].lhs});
322 } else {
323 return astrl.builtinCall(block, ri, node, &.{ node_datas[node].lhs, node_datas[node].rhs });
324 }
325 },
326 .builtin_call, .builtin_call_comma => {
327 const params = tree.extra_data[node_datas[node].lhs..node_datas[node].rhs];
328 return astrl.builtinCall(block, ri, node, params);
329 },
330
331 .call_one,
332 .call_one_comma,
333 .async_call_one,
334 .async_call_one_comma,
335 .call,
336 .call_comma,
337 .async_call,
338 .async_call_comma,
339 => {
340 var buf: [1]Ast.Node.Index = undefined;
341 const full = tree.fullCall(&buf, node).?;
342 _ = try astrl.expr(full.ast.fn_expr, block, ResultInfo.none);
343 for (full.ast.params) |param_node| {
344 _ = try astrl.expr(param_node, block, ResultInfo.type_only);
345 }
346 return switch (node_tags[node]) {
347 .call_one,
348 .call_one_comma,
349 .call,
350 .call_comma,
351 => false, // TODO: once function calls are passed result locations this will change
352 .async_call_one,
353 .async_call_one_comma,
354 .async_call,
355 .async_call_comma,
356 => ri.have_ptr, // always use result ptr for frames
357 else => unreachable,
358 };
359 },
360
361 .@"return" => {
362 if (node_datas[node].lhs != 0) {
363 const ret_val_consumes_rl = try astrl.expr(node_datas[node].lhs, block, ResultInfo.typed_ptr);
364 if (ret_val_consumes_rl) {
365 try astrl.nodes_need_rl.putNoClobber(astrl.gpa, node, {});
366 }
367 }
368 return false;
369 },
370
371 .field_access => {
372 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none);
373 return false;
374 },
375
376 .if_simple, .@"if" => {
377 const full = tree.fullIf(node).?;
378 if (full.error_token != null or full.payload_token != null) {
379 _ = try astrl.expr(full.ast.cond_expr, block, ResultInfo.none);
380 } else {
381 _ = try astrl.expr(full.ast.cond_expr, block, ResultInfo.type_only); // bool
382 }
383
384 if (full.ast.else_expr == 0) {
385 _ = try astrl.expr(full.ast.then_expr, block, ResultInfo.none);
386 return false;
387 } else {
388 const then_uses_rl = try astrl.expr(full.ast.then_expr, block, ri);
389 const else_uses_rl = try astrl.expr(full.ast.else_expr, block, ri);
390 const uses_rl = then_uses_rl or else_uses_rl;
391 if (uses_rl) try astrl.nodes_need_rl.putNoClobber(astrl.gpa, node, {});
392 return uses_rl;
393 }
394 },
395
396 .while_simple, .while_cont, .@"while" => {
397 const full = tree.fullWhile(node).?;
398 const label: ?[]const u8 = if (full.label_token) |label_token| label: {
399 break :label try astrl.identString(label_token);
400 } else null;
401 if (full.error_token != null or full.payload_token != null) {
402 _ = try astrl.expr(full.ast.cond_expr, block, ResultInfo.none);
403 } else {
404 _ = try astrl.expr(full.ast.cond_expr, block, ResultInfo.type_only); // bool
405 }
406 var new_block: Block = .{
407 .parent = block,
408 .label = label,
409 .is_loop = true,
410 .ri = ri,
411 .consumes_res_ptr = false,
412 };
413 if (full.ast.cont_expr != 0) {
414 _ = try astrl.expr(full.ast.cont_expr, &new_block, ResultInfo.none);
415 }
416 _ = try astrl.expr(full.ast.then_expr, &new_block, ResultInfo.none);
417 const else_consumes_rl = if (full.ast.else_expr != 0) else_rl: {
418 break :else_rl try astrl.expr(full.ast.else_expr, block, ri);
419 } else false;
420 if (new_block.consumes_res_ptr or else_consumes_rl) {
421 try astrl.nodes_need_rl.putNoClobber(astrl.gpa, node, {});
422 return true;
423 } else {
424 return false;
425 }
426 },
427
428 .for_simple, .@"for" => {
429 const full = tree.fullFor(node).?;
430 const label: ?[]const u8 = if (full.label_token) |label_token| label: {
431 break :label try astrl.identString(label_token);
432 } else null;
433 for (full.ast.inputs) |input| {
434 if (node_tags[input] == .for_range) {
435 _ = try astrl.expr(node_datas[input].lhs, block, ResultInfo.type_only);
436 if (node_datas[input].rhs != 0) {
437 _ = try astrl.expr(node_datas[input].rhs, block, ResultInfo.type_only);
438 }
439 } else {
440 _ = try astrl.expr(input, block, ResultInfo.none);
441 }
442 }
443 var new_block: Block = .{
444 .parent = block,
445 .label = label,
446 .is_loop = true,
447 .ri = ri,
448 .consumes_res_ptr = false,
449 };
450 _ = try astrl.expr(full.ast.then_expr, &new_block, ResultInfo.none);
451 const else_consumes_rl = if (full.ast.else_expr != 0) else_rl: {
452 break :else_rl try astrl.expr(full.ast.else_expr, block, ri);
453 } else false;
454 if (new_block.consumes_res_ptr or else_consumes_rl) {
455 try astrl.nodes_need_rl.putNoClobber(astrl.gpa, node, {});
456 return true;
457 } else {
458 return false;
459 }
460 },
461
462 .slice_open => {
463 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none);
464 _ = try astrl.expr(node_datas[node].rhs, block, ResultInfo.type_only);
465 return false;
466 },
467 .slice => {
468 const extra = tree.extraData(node_datas[node].rhs, Ast.Node.Slice);
469 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none);
470 _ = try astrl.expr(extra.start, block, ResultInfo.type_only);
471 _ = try astrl.expr(extra.end, block, ResultInfo.type_only);
472 return false;
473 },
474 .slice_sentinel => {
475 const extra = tree.extraData(node_datas[node].rhs, Ast.Node.SliceSentinel);
476 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none);
477 _ = try astrl.expr(extra.start, block, ResultInfo.type_only);
478 if (extra.end != 0) {
479 _ = try astrl.expr(extra.end, block, ResultInfo.type_only);
480 }
481 _ = try astrl.expr(extra.sentinel, block, ResultInfo.none);
482 return false;
483 },
484 .deref => {
485 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none);
486 return false;
487 },
488 .address_of => {
489 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none);
490 return false;
491 },
492 .optional_type => {
493 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.type_only);
494 return false;
495 },
496 .grouped_expression,
497 .@"try",
498 .@"await",
499 .@"nosuspend",
500 .unwrap_optional,
501 => return astrl.expr(node_datas[node].lhs, block, ri),
502
503 .block_two, .block_two_semicolon => {
504 if (node_datas[node].lhs == 0) {
505 return astrl.blockExpr(block, ri, node, &.{});
506 } else if (node_datas[node].rhs == 0) {
507 return astrl.blockExpr(block, ri, node, &.{node_datas[node].lhs});
508 } else {
509 return astrl.blockExpr(block, ri, node, &.{ node_datas[node].lhs, node_datas[node].rhs });
510 }
511 },
512 .block, .block_semicolon => {
513 const statements = tree.extra_data[node_datas[node].lhs..node_datas[node].rhs];
514 return astrl.blockExpr(block, ri, node, statements);
515 },
516 .anyframe_type => {
517 _ = try astrl.expr(node_datas[node].rhs, block, ResultInfo.type_only);
518 return false;
519 },
520 .@"catch", .@"orelse" => {
521 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none);
522 const rhs_consumes_rl = try astrl.expr(node_datas[node].rhs, block, ri);
523 if (rhs_consumes_rl) {
524 try astrl.nodes_need_rl.putNoClobber(astrl.gpa, node, {});
525 }
526 return rhs_consumes_rl;
527 },
528
529 .ptr_type_aligned,
530 .ptr_type_sentinel,
531 .ptr_type,
532 .ptr_type_bit_range,
533 => {
534 const full = tree.fullPtrType(node).?;
535 _ = try astrl.expr(full.ast.child_type, block, ResultInfo.type_only);
536 if (full.ast.sentinel != 0) {
537 _ = try astrl.expr(full.ast.sentinel, block, ResultInfo.type_only);
538 }
539 if (full.ast.addrspace_node != 0) {
540 _ = try astrl.expr(full.ast.addrspace_node, block, ResultInfo.type_only);
541 }
542 if (full.ast.align_node != 0) {
543 _ = try astrl.expr(full.ast.align_node, block, ResultInfo.type_only);
544 }
545 if (full.ast.bit_range_start != 0) {
546 assert(full.ast.bit_range_end != 0);
547 _ = try astrl.expr(full.ast.bit_range_start, block, ResultInfo.type_only);
548 _ = try astrl.expr(full.ast.bit_range_end, block, ResultInfo.type_only);
549 }
550 return false;
551 },
552
553 .container_decl,
554 .container_decl_trailing,
555 .container_decl_arg,
556 .container_decl_arg_trailing,
557 .container_decl_two,
558 .container_decl_two_trailing,
559 .tagged_union,
560 .tagged_union_trailing,
561 .tagged_union_enum_tag,
562 .tagged_union_enum_tag_trailing,
563 .tagged_union_two,
564 .tagged_union_two_trailing,
565 => {
566 var buf: [2]Ast.Node.Index = undefined;
567 try astrl.containerDecl(block, tree.fullContainerDecl(&buf, node).?);
568 return false;
569 },
570
571 .@"break" => {
572 if (node_datas[node].rhs == 0) {
573 // Breaks with void are not interesting
574 return false;
575 }
576
577 var opt_cur_block = block;
578 if (node_datas[node].lhs == 0) {
579 // No label - we're breaking from a loop.
580 while (opt_cur_block) |cur_block| : (opt_cur_block = cur_block.parent) {
581 if (cur_block.is_loop) break;
582 }
583 } else {
584 const break_label = try astrl.identString(node_datas[node].lhs);
585 while (opt_cur_block) |cur_block| : (opt_cur_block = cur_block.parent) {
586 const block_label = cur_block.label orelse continue;
587 if (std.mem.eql(u8, block_label, break_label)) break;
588 }
589 }
590
591 if (opt_cur_block) |target_block| {
592 const consumes_break_rl = try astrl.expr(node_datas[node].rhs, block, target_block.ri);
593 if (consumes_break_rl) target_block.consumes_res_ptr = true;
594 } else {
595 // No corresponding scope to break from - AstGen will emit an error.
596 _ = try astrl.expr(node_datas[node].rhs, block, ResultInfo.none);
597 }
598
599 return false;
600 },
601
602 .array_type => {
603 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.type_only);
604 _ = try astrl.expr(node_datas[node].rhs, block, ResultInfo.type_only);
605 return false;
606 },
607 .array_type_sentinel => {
608 const extra = tree.extraData(node_datas[node].rhs, Ast.Node.ArrayTypeSentinel);
609 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.type_only);
610 _ = try astrl.expr(extra.elem_type, block, ResultInfo.type_only);
611 _ = try astrl.expr(extra.sentinel, block, ResultInfo.type_only);
612 return false;
613 },
614 .array_access => {
615 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none);
616 _ = try astrl.expr(node_datas[node].rhs, block, ResultInfo.type_only);
617 return false;
618 },
619 .@"comptime" => {
620 // AstGen will emit an error if the scope is already comptime, so we can assume it is
621 // not. This means the result location is not forwarded.
622 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none);
623 return false;
624 },
625 .@"switch", .switch_comma => {
626 const operand_node = node_datas[node].lhs;
627 const extra = tree.extraData(node_datas[node].rhs, Ast.Node.SubRange);
628 const case_nodes = tree.extra_data[extra.start..extra.end];
629
630 _ = try astrl.expr(operand_node, block, ResultInfo.none);
631
632 var any_prong_consumed_rl = false;
633 for (case_nodes) |case_node| {
634 const case = tree.fullSwitchCase(case_node).?;
635 for (case.ast.values) |item_node| {
636 if (node_tags[item_node] == .switch_range) {
637 _ = try astrl.expr(node_datas[item_node].lhs, block, ResultInfo.none);
638 _ = try astrl.expr(node_datas[item_node].rhs, block, ResultInfo.none);
639 } else {
640 _ = try astrl.expr(item_node, block, ResultInfo.none);
641 }
642 }
643 if (try astrl.expr(case.ast.target_expr, block, ri)) {
644 any_prong_consumed_rl = true;
645 }
646 }
647 if (any_prong_consumed_rl) {
648 try astrl.nodes_need_rl.putNoClobber(astrl.gpa, node, {});
649 }
650 return any_prong_consumed_rl;
651 },
652 .@"suspend" => {
653 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none);
654 return false;
655 },
656 .@"resume" => {
657 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none);
658 return false;
659 },
660
661 .array_init_one,
662 .array_init_one_comma,
663 .array_init_dot_two,
664 .array_init_dot_two_comma,
665 .array_init_dot,
666 .array_init_dot_comma,
667 .array_init,
668 .array_init_comma,
669 => {
670 var buf: [2]Ast.Node.Index = undefined;
671 const full = tree.fullArrayInit(&buf, node).?;
672
673 if (full.ast.type_expr != 0) {
674 // Explicitly typed init does not participate in RLS
675 _ = try astrl.expr(full.ast.type_expr, block, ResultInfo.none);
676 for (full.ast.elements) |elem_init| {
677 _ = try astrl.expr(elem_init, block, ResultInfo.type_only);
678 }
679 return false;
680 }
681
682 if (ri.have_type) {
683 // Always forward type information
684 // If we have a result pointer, we use and forward it
685 for (full.ast.elements) |elem_init| {
686 _ = try astrl.expr(elem_init, block, ri);
687 }
688 return ri.have_ptr;
689 } else {
690 // Untyped init does not consume result location
691 for (full.ast.elements) |elem_init| {
692 _ = try astrl.expr(elem_init, block, ResultInfo.none);
693 }
694 return false;
695 }
696 },
697
698 .struct_init_one,
699 .struct_init_one_comma,
700 .struct_init_dot_two,
701 .struct_init_dot_two_comma,
702 .struct_init_dot,
703 .struct_init_dot_comma,
704 .struct_init,
705 .struct_init_comma,
706 => {
707 var buf: [2]Ast.Node.Index = undefined;
708 const full = tree.fullStructInit(&buf, node).?;
709
710 if (full.ast.type_expr != 0) {
711 // Explicitly typed init does not participate in RLS
712 _ = try astrl.expr(full.ast.type_expr, block, ResultInfo.none);
713 for (full.ast.fields) |field_init| {
714 _ = try astrl.expr(field_init, block, ResultInfo.type_only);
715 }
716 return false;
717 }
718
719 if (ri.have_type) {
720 // Always forward type information
721 // If we have a result pointer, we use and forward it
722 for (full.ast.fields) |field_init| {
723 _ = try astrl.expr(field_init, block, ri);
724 }
725 return ri.have_ptr;
726 } else {
727 // Untyped init does not consume result location
728 for (full.ast.fields) |field_init| {
729 _ = try astrl.expr(field_init, block, ResultInfo.none);
730 }
731 return false;
732 }
733 },
734
735 .fn_proto_simple,
736 .fn_proto_multi,
737 .fn_proto_one,
738 .fn_proto,
739 .fn_decl,
740 => {
741 var buf: [1]Ast.Node.Index = undefined;
742 const full = tree.fullFnProto(&buf, node).?;
743 const body_node = if (node_tags[node] == .fn_decl) node_datas[node].rhs else 0;
744 {
745 var it = full.iterate(tree);
746 while (it.next()) |param| {
747 if (param.anytype_ellipsis3 == null) {
748 _ = try astrl.expr(param.type_expr, block, ResultInfo.type_only);
749 }
750 }
751 }
752 if (full.ast.align_expr != 0) {
753 _ = try astrl.expr(full.ast.align_expr, block, ResultInfo.type_only);
754 }
755 if (full.ast.addrspace_expr != 0) {
756 _ = try astrl.expr(full.ast.addrspace_expr, block, ResultInfo.type_only);
757 }
758 if (full.ast.section_expr != 0) {
759 _ = try astrl.expr(full.ast.section_expr, block, ResultInfo.type_only);
760 }
761 if (full.ast.callconv_expr != 0) {
762 _ = try astrl.expr(full.ast.callconv_expr, block, ResultInfo.type_only);
763 }
764 _ = try astrl.expr(full.ast.return_type, block, ResultInfo.type_only);
765 if (body_node != 0) {
766 _ = try astrl.expr(body_node, block, ResultInfo.none);
767 }
768 return false;
769 },
770 }
771}
772
773fn identString(astrl: *AstRlAnnotate, token: Ast.TokenIndex) ![]const u8 {
774 const tree = astrl.tree;
775 const token_tags = tree.tokens.items(.tag);
776 assert(token_tags[token] == .identifier);
777 const ident_name = tree.tokenSlice(token);
778 if (!std.mem.startsWith(u8, ident_name, "@")) {
779 return ident_name;
780 }
781 return std.zig.string_literal.parseAlloc(astrl.arena, ident_name[1..]) catch |err| switch (err) {
782 error.OutOfMemory => error.OutOfMemory,
783 error.InvalidLiteral => "", // This pass can safely return garbage on invalid AST
784 };
785}
786
787fn blockExpr(astrl: *AstRlAnnotate, parent_block: ?*Block, ri: ResultInfo, node: Ast.Node.Index, statements: []const Ast.Node.Index) !bool {
788 const tree = astrl.tree;
789 const token_tags = tree.tokens.items(.tag);
790 const main_tokens = tree.nodes.items(.main_token);
791
792 const lbrace = main_tokens[node];
793 if (token_tags[lbrace - 1] == .colon and
794 token_tags[lbrace - 2] == .identifier)
795 {
796 // Labeled block
797 var new_block: Block = .{
798 .parent = parent_block,
799 .label = try astrl.identString(lbrace - 2),
800 .is_loop = false,
801 .ri = ri,
802 .consumes_res_ptr = false,
803 };
804 for (statements) |statement| {
805 _ = try astrl.expr(statement, &new_block, ResultInfo.none);
806 }
807 if (new_block.consumes_res_ptr) {
808 try astrl.nodes_need_rl.putNoClobber(astrl.gpa, node, {});
809 }
810 return new_block.consumes_res_ptr;
811 } else {
812 // Unlabeled block
813 for (statements) |statement| {
814 _ = try astrl.expr(statement, parent_block, ResultInfo.none);
815 }
816 return false;
817 }
818}
819
820fn builtinCall(astrl: *AstRlAnnotate, block: ?*Block, ri: ResultInfo, node: Ast.Node.Index, args: []const Ast.Node.Index) !bool {
821 _ = ri; // Currently, no builtin consumes its result location.
822
823 const tree = astrl.tree;
824 const main_tokens = tree.nodes.items(.main_token);
825 const builtin_token = main_tokens[node];
826 const builtin_name = tree.tokenSlice(builtin_token);
827 const info = BuiltinFn.list.get(builtin_name) orelse return false;
828 if (info.param_count) |expected| {
829 if (expected != args.len) return false;
830 }
831 switch (info.tag) {
832 .import => return false,
833 .compile_log, .TypeOf => {
834 for (args) |arg_node| {
835 _ = try astrl.expr(arg_node, block, ResultInfo.none);
836 }
837 return false;
838 },
839 .as => {
840 _ = try astrl.expr(args[0], block, ResultInfo.type_only);
841 _ = try astrl.expr(args[1], block, ResultInfo.type_only);
842 return false;
843 },
844 .bit_cast => {
845 _ = try astrl.expr(args[0], block, ResultInfo.none);
846 return false;
847 },
848 .union_init => {
849 _ = try astrl.expr(args[0], block, ResultInfo.type_only);
850 _ = try astrl.expr(args[1], block, ResultInfo.type_only);
851 _ = try astrl.expr(args[2], block, ResultInfo.type_only);
852 return false;
853 },
854 .c_import => {
855 _ = try astrl.expr(args[0], block, ResultInfo.none);
856 return false;
857 },
858 .min, .max => {
859 for (args) |arg_node| {
860 _ = try astrl.expr(arg_node, block, ResultInfo.none);
861 }
862 return false;
863 },
864 .@"export" => {
865 _ = try astrl.expr(args[0], block, ResultInfo.none);
866 _ = try astrl.expr(args[1], block, ResultInfo.type_only);
867 return false;
868 },
869 .@"extern" => {
870 _ = try astrl.expr(args[0], block, ResultInfo.type_only);
871 _ = try astrl.expr(args[1], block, ResultInfo.type_only);
872 return false;
873 },
874 // These builtins take no args and do not consume the result pointer.
875 .src,
876 .This,
877 .return_address,
878 .error_return_trace,
879 .frame,
880 .breakpoint,
881 .in_comptime,
882 .panic,
883 .trap,
884 .c_va_start,
885 => return false,
886 // TODO: this is a workaround for llvm/llvm-project#68409
887 // Zig tracking issue: #16876
888 .frame_address => return true,
889 // These builtins take a single argument with a known result type, but do not consume their
890 // result pointer.
891 .size_of,
892 .bit_size_of,
893 .align_of,
894 .compile_error,
895 .set_eval_branch_quota,
896 .int_from_bool,
897 .int_from_error,
898 .error_from_int,
899 .embed_file,
900 .error_name,
901 .set_runtime_safety,
902 .Type,
903 .c_undef,
904 .c_include,
905 .wasm_memory_size,
906 .splat,
907 .fence,
908 .set_float_mode,
909 .set_align_stack,
910 .set_cold,
911 .type_info,
912 .work_item_id,
913 .work_group_size,
914 .work_group_id,
915 => {
916 _ = try astrl.expr(args[0], block, ResultInfo.type_only);
917 return false;
918 },
919 // These builtins take a single argument with no result information and do not consume their
920 // result pointer.
921 .int_from_ptr,
922 .int_from_enum,
923 .sqrt,
924 .sin,
925 .cos,
926 .tan,
927 .exp,
928 .exp2,
929 .log,
930 .log2,
931 .log10,
932 .abs,
933 .floor,
934 .ceil,
935 .trunc,
936 .round,
937 .tag_name,
938 .type_name,
939 .Frame,
940 .frame_size,
941 .int_from_float,
942 .float_from_int,
943 .ptr_from_int,
944 .enum_from_int,
945 .float_cast,
946 .int_cast,
947 .truncate,
948 .error_cast,
949 .ptr_cast,
950 .align_cast,
951 .addrspace_cast,
952 .const_cast,
953 .volatile_cast,
954 .clz,
955 .ctz,
956 .pop_count,
957 .byte_swap,
958 .bit_reverse,
959 => {
960 _ = try astrl.expr(args[0], block, ResultInfo.none);
961 return false;
962 },
963 .div_exact,
964 .div_floor,
965 .div_trunc,
966 .mod,
967 .rem,
968 => {
969 _ = try astrl.expr(args[0], block, ResultInfo.none);
970 _ = try astrl.expr(args[1], block, ResultInfo.none);
971 return false;
972 },
973 .shl_exact, .shr_exact => {
974 _ = try astrl.expr(args[0], block, ResultInfo.none);
975 _ = try astrl.expr(args[1], block, ResultInfo.type_only);
976 return false;
977 },
978 .bit_offset_of,
979 .offset_of,
980 .field_parent_ptr,
981 .has_decl,
982 .has_field,
983 .field,
984 => {
985 _ = try astrl.expr(args[0], block, ResultInfo.type_only);
986 _ = try astrl.expr(args[1], block, ResultInfo.type_only);
987 return false;
988 },
989 .wasm_memory_grow => {
990 _ = try astrl.expr(args[0], block, ResultInfo.type_only);
991 _ = try astrl.expr(args[1], block, ResultInfo.type_only);
992 return false;
993 },
994 .c_define => {
995 _ = try astrl.expr(args[0], block, ResultInfo.type_only);
996 _ = try astrl.expr(args[1], block, ResultInfo.none);
997 return false;
998 },
999 .reduce => {
1000 _ = try astrl.expr(args[0], block, ResultInfo.type_only);
1001 _ = try astrl.expr(args[1], block, ResultInfo.none);
1002 return false;
1003 },
1004 .add_with_overflow, .sub_with_overflow, .mul_with_overflow, .shl_with_overflow => {
1005 _ = try astrl.expr(args[0], block, ResultInfo.none);
1006 _ = try astrl.expr(args[1], block, ResultInfo.none);
1007 return false;
1008 },
1009 .atomic_load => {
1010 _ = try astrl.expr(args[0], block, ResultInfo.type_only);
1011 _ = try astrl.expr(args[1], block, ResultInfo.none);
1012 _ = try astrl.expr(args[2], block, ResultInfo.type_only);
1013 return false;
1014 },
1015 .atomic_rmw => {
1016 _ = try astrl.expr(args[0], block, ResultInfo.type_only);
1017 _ = try astrl.expr(args[1], block, ResultInfo.none);
1018 _ = try astrl.expr(args[2], block, ResultInfo.type_only);
1019 _ = try astrl.expr(args[3], block, ResultInfo.type_only);
1020 _ = try astrl.expr(args[4], block, ResultInfo.type_only);
1021 return false;
1022 },
1023 .atomic_store => {
1024 _ = try astrl.expr(args[0], block, ResultInfo.type_only);
1025 _ = try astrl.expr(args[1], block, ResultInfo.none);
1026 _ = try astrl.expr(args[2], block, ResultInfo.type_only);
1027 _ = try astrl.expr(args[3], block, ResultInfo.type_only);
1028 return false;
1029 },
1030 .mul_add => {
1031 _ = try astrl.expr(args[0], block, ResultInfo.type_only);
1032 _ = try astrl.expr(args[1], block, ResultInfo.type_only);
1033 _ = try astrl.expr(args[2], block, ResultInfo.type_only);
1034 return false;
1035 },
1036 .call => {
1037 _ = try astrl.expr(args[0], block, ResultInfo.type_only);
1038 _ = try astrl.expr(args[1], block, ResultInfo.none);
1039 _ = try astrl.expr(args[2], block, ResultInfo.none);
1040 return false;
1041 },
1042 .memcpy => {
1043 _ = try astrl.expr(args[0], block, ResultInfo.none);
1044 _ = try astrl.expr(args[1], block, ResultInfo.none);
1045 return false;
1046 },
1047 .memset => {
1048 _ = try astrl.expr(args[0], block, ResultInfo.none);
1049 _ = try astrl.expr(args[1], block, ResultInfo.type_only);
1050 return false;
1051 },
1052 .shuffle => {
1053 _ = try astrl.expr(args[0], block, ResultInfo.type_only);
1054 _ = try astrl.expr(args[1], block, ResultInfo.none);
1055 _ = try astrl.expr(args[2], block, ResultInfo.none);
1056 _ = try astrl.expr(args[3], block, ResultInfo.none);
1057 return false;
1058 },
1059 .select => {
1060 _ = try astrl.expr(args[0], block, ResultInfo.type_only);
1061 _ = try astrl.expr(args[1], block, ResultInfo.none);
1062 _ = try astrl.expr(args[2], block, ResultInfo.none);
1063 _ = try astrl.expr(args[3], block, ResultInfo.none);
1064 return false;
1065 },
1066 .async_call => {
1067 _ = try astrl.expr(args[0], block, ResultInfo.none);
1068 _ = try astrl.expr(args[1], block, ResultInfo.none);
1069 _ = try astrl.expr(args[2], block, ResultInfo.none);
1070 _ = try astrl.expr(args[3], block, ResultInfo.none);
1071 return false; // buffer passed as arg for frame data
1072 },
1073 .Vector => {
1074 _ = try astrl.expr(args[0], block, ResultInfo.type_only);
1075 _ = try astrl.expr(args[1], block, ResultInfo.type_only);
1076 return false;
1077 },
1078 .prefetch => {
1079 _ = try astrl.expr(args[0], block, ResultInfo.none);
1080 _ = try astrl.expr(args[1], block, ResultInfo.type_only);
1081 return false;
1082 },
1083 .c_va_arg => {
1084 _ = try astrl.expr(args[0], block, ResultInfo.none);
1085 _ = try astrl.expr(args[1], block, ResultInfo.type_only);
1086 return false;
1087 },
1088 .c_va_copy => {
1089 _ = try astrl.expr(args[0], block, ResultInfo.none);
1090 return false;
1091 },
1092 .c_va_end => {
1093 _ = try astrl.expr(args[0], block, ResultInfo.none);
1094 return false;
1095 },
1096 .cmpxchg_strong, .cmpxchg_weak => {
1097 _ = try astrl.expr(args[0], block, ResultInfo.none);
1098 _ = try astrl.expr(args[1], block, ResultInfo.type_only);
1099 _ = try astrl.expr(args[2], block, ResultInfo.type_only);
1100 _ = try astrl.expr(args[3], block, ResultInfo.type_only);
1101 _ = try astrl.expr(args[4], block, ResultInfo.type_only);
1102 return false;
1103 },
1104 }
1105}
lib/std/zig/BuiltinFn.zig created+1017
......@@ -0,0 +1,1017 @@
1const std = @import("std");
2
3pub const Tag = enum {
4 add_with_overflow,
5 addrspace_cast,
6 align_cast,
7 align_of,
8 as,
9 async_call,
10 atomic_load,
11 atomic_rmw,
12 atomic_store,
13 bit_cast,
14 bit_offset_of,
15 int_from_bool,
16 bit_size_of,
17 breakpoint,
18 mul_add,
19 byte_swap,
20 bit_reverse,
21 offset_of,
22 call,
23 c_define,
24 c_import,
25 c_include,
26 clz,
27 cmpxchg_strong,
28 cmpxchg_weak,
29 compile_error,
30 compile_log,
31 const_cast,
32 ctz,
33 c_undef,
34 c_va_arg,
35 c_va_copy,
36 c_va_end,
37 c_va_start,
38 div_exact,
39 div_floor,
40 div_trunc,
41 embed_file,
42 int_from_enum,
43 error_name,
44 error_return_trace,
45 int_from_error,
46 error_cast,
47 @"export",
48 @"extern",
49 fence,
50 field,
51 field_parent_ptr,
52 float_cast,
53 int_from_float,
54 frame,
55 Frame,
56 frame_address,
57 frame_size,
58 has_decl,
59 has_field,
60 import,
61 in_comptime,
62 int_cast,
63 enum_from_int,
64 error_from_int,
65 float_from_int,
66 ptr_from_int,
67 max,
68 memcpy,
69 memset,
70 min,
71 wasm_memory_size,
72 wasm_memory_grow,
73 mod,
74 mul_with_overflow,
75 panic,
76 pop_count,
77 prefetch,
78 ptr_cast,
79 int_from_ptr,
80 rem,
81 return_address,
82 select,
83 set_align_stack,
84 set_cold,
85 set_eval_branch_quota,
86 set_float_mode,
87 set_runtime_safety,
88 shl_exact,
89 shl_with_overflow,
90 shr_exact,
91 shuffle,
92 size_of,
93 splat,
94 reduce,
95 src,
96 sqrt,
97 sin,
98 cos,
99 tan,
100 exp,
101 exp2,
102 log,
103 log2,
104 log10,
105 abs,
106 floor,
107 ceil,
108 trunc,
109 round,
110 sub_with_overflow,
111 tag_name,
112 This,
113 trap,
114 truncate,
115 Type,
116 type_info,
117 type_name,
118 TypeOf,
119 union_init,
120 Vector,
121 volatile_cast,
122 work_item_id,
123 work_group_size,
124 work_group_id,
125};
126
127pub const MemLocRequirement = enum {
128 /// The builtin never needs a memory location.
129 never,
130 /// The builtin always needs a memory location.
131 always,
132 /// The builtin forwards the question to argument at index 0.
133 forward0,
134 /// The builtin forwards the question to argument at index 1.
135 forward1,
136};
137
138pub const EvalToError = enum {
139 /// The builtin cannot possibly evaluate to an error.
140 never,
141 /// The builtin will always evaluate to an error.
142 always,
143 /// The builtin may or may not evaluate to an error depending on the parameters.
144 maybe,
145};
146
147tag: Tag,
148
149/// Info about the builtin call's ability to take advantage of a result location pointer.
150needs_mem_loc: MemLocRequirement = .never,
151/// Info about the builtin call's possibility of returning an error.
152eval_to_error: EvalToError = .never,
153/// `true` if the builtin call can be the left-hand side of an expression (assigned to).
154allows_lvalue: bool = false,
155/// The number of parameters to this builtin function. `null` means variable number
156/// of parameters.
157param_count: ?u8,
158
159pub const list = list: {
160 @setEvalBranchQuota(3000);
161 break :list std.ComptimeStringMap(@This(), .{
162 .{
163 "@addWithOverflow",
164 .{
165 .tag = .add_with_overflow,
166 .param_count = 2,
167 },
168 },
169 .{
170 "@addrSpaceCast",
171 .{
172 .tag = .addrspace_cast,
173 .param_count = 1,
174 },
175 },
176 .{
177 "@alignCast",
178 .{
179 .tag = .align_cast,
180 .param_count = 1,
181 },
182 },
183 .{
184 "@alignOf",
185 .{
186 .tag = .align_of,
187 .param_count = 1,
188 },
189 },
190 .{
191 "@as",
192 .{
193 .tag = .as,
194 .needs_mem_loc = .forward1,
195 .eval_to_error = .maybe,
196 .param_count = 2,
197 },
198 },
199 .{
200 "@asyncCall",
201 .{
202 .tag = .async_call,
203 .param_count = 4,
204 },
205 },
206 .{
207 "@atomicLoad",
208 .{
209 .tag = .atomic_load,
210 .param_count = 3,
211 },
212 },
213 .{
214 "@atomicRmw",
215 .{
216 .tag = .atomic_rmw,
217 .param_count = 5,
218 },
219 },
220 .{
221 "@atomicStore",
222 .{
223 .tag = .atomic_store,
224 .param_count = 4,
225 },
226 },
227 .{
228 "@bitCast",
229 .{
230 .tag = .bit_cast,
231 .needs_mem_loc = .forward0,
232 .param_count = 1,
233 },
234 },
235 .{
236 "@bitOffsetOf",
237 .{
238 .tag = .bit_offset_of,
239 .param_count = 2,
240 },
241 },
242 .{
243 "@intFromBool",
244 .{
245 .tag = .int_from_bool,
246 .param_count = 1,
247 },
248 },
249 .{
250 "@bitSizeOf",
251 .{
252 .tag = .bit_size_of,
253 .param_count = 1,
254 },
255 },
256 .{
257 "@breakpoint",
258 .{
259 .tag = .breakpoint,
260 .param_count = 0,
261 },
262 },
263 .{
264 "@mulAdd",
265 .{
266 .tag = .mul_add,
267 .param_count = 4,
268 },
269 },
270 .{
271 "@byteSwap",
272 .{
273 .tag = .byte_swap,
274 .param_count = 1,
275 },
276 },
277 .{
278 "@bitReverse",
279 .{
280 .tag = .bit_reverse,
281 .param_count = 1,
282 },
283 },
284 .{
285 "@offsetOf",
286 .{
287 .tag = .offset_of,
288 .param_count = 2,
289 },
290 },
291 .{
292 "@call",
293 .{
294 .tag = .call,
295 .needs_mem_loc = .always,
296 .eval_to_error = .maybe,
297 .param_count = 3,
298 },
299 },
300 .{
301 "@cDefine",
302 .{
303 .tag = .c_define,
304 .param_count = 2,
305 },
306 },
307 .{
308 "@cImport",
309 .{
310 .tag = .c_import,
311 .param_count = 1,
312 },
313 },
314 .{
315 "@cInclude",
316 .{
317 .tag = .c_include,
318 .param_count = 1,
319 },
320 },
321 .{
322 "@clz",
323 .{
324 .tag = .clz,
325 .param_count = 1,
326 },
327 },
328 .{
329 "@cmpxchgStrong",
330 .{
331 .tag = .cmpxchg_strong,
332 .param_count = 6,
333 },
334 },
335 .{
336 "@cmpxchgWeak",
337 .{
338 .tag = .cmpxchg_weak,
339 .param_count = 6,
340 },
341 },
342 .{
343 "@compileError",
344 .{
345 .tag = .compile_error,
346 .param_count = 1,
347 },
348 },
349 .{
350 "@compileLog",
351 .{
352 .tag = .compile_log,
353 .param_count = null,
354 },
355 },
356 .{
357 "@constCast",
358 .{
359 .tag = .const_cast,
360 .param_count = 1,
361 },
362 },
363 .{
364 "@ctz",
365 .{
366 .tag = .ctz,
367 .param_count = 1,
368 },
369 },
370 .{
371 "@cUndef",
372 .{
373 .tag = .c_undef,
374 .param_count = 1,
375 },
376 },
377 .{
378 "@cVaArg", .{
379 .tag = .c_va_arg,
380 .param_count = 2,
381 },
382 },
383 .{
384 "@cVaCopy", .{
385 .tag = .c_va_copy,
386 .param_count = 1,
387 },
388 },
389 .{
390 "@cVaEnd", .{
391 .tag = .c_va_end,
392 .param_count = 1,
393 },
394 },
395 .{
396 "@cVaStart", .{
397 .tag = .c_va_start,
398 .param_count = 0,
399 },
400 },
401 .{
402 "@divExact",
403 .{
404 .tag = .div_exact,
405 .param_count = 2,
406 },
407 },
408 .{
409 "@divFloor",
410 .{
411 .tag = .div_floor,
412 .param_count = 2,
413 },
414 },
415 .{
416 "@divTrunc",
417 .{
418 .tag = .div_trunc,
419 .param_count = 2,
420 },
421 },
422 .{
423 "@embedFile",
424 .{
425 .tag = .embed_file,
426 .param_count = 1,
427 },
428 },
429 .{
430 "@intFromEnum",
431 .{
432 .tag = .int_from_enum,
433 .param_count = 1,
434 },
435 },
436 .{
437 "@errorName",
438 .{
439 .tag = .error_name,
440 .param_count = 1,
441 },
442 },
443 .{
444 "@errorReturnTrace",
445 .{
446 .tag = .error_return_trace,
447 .param_count = 0,
448 },
449 },
450 .{
451 "@intFromError",
452 .{
453 .tag = .int_from_error,
454 .param_count = 1,
455 },
456 },
457 .{
458 "@errorCast",
459 .{
460 .tag = .error_cast,
461 .eval_to_error = .always,
462 .param_count = 1,
463 },
464 },
465 .{
466 "@export",
467 .{
468 .tag = .@"export",
469 .param_count = 2,
470 },
471 },
472 .{
473 "@extern",
474 .{
475 .tag = .@"extern",
476 .param_count = 2,
477 },
478 },
479 .{
480 "@fence",
481 .{
482 .tag = .fence,
483 .param_count = 1,
484 },
485 },
486 .{
487 "@field",
488 .{
489 .tag = .field,
490 .needs_mem_loc = .always,
491 .eval_to_error = .maybe,
492 .param_count = 2,
493 .allows_lvalue = true,
494 },
495 },
496 .{
497 "@fieldParentPtr",
498 .{
499 .tag = .field_parent_ptr,
500 .param_count = 3,
501 },
502 },
503 .{
504 "@floatCast",
505 .{
506 .tag = .float_cast,
507 .param_count = 1,
508 },
509 },
510 .{
511 "@intFromFloat",
512 .{
513 .tag = .int_from_float,
514 .param_count = 1,
515 },
516 },
517 .{
518 "@frame",
519 .{
520 .tag = .frame,
521 .param_count = 0,
522 },
523 },
524 .{
525 "@Frame",
526 .{
527 .tag = .Frame,
528 .param_count = 1,
529 },
530 },
531 .{
532 "@frameAddress",
533 .{
534 .tag = .frame_address,
535 .param_count = 0,
536 },
537 },
538 .{
539 "@frameSize",
540 .{
541 .tag = .frame_size,
542 .param_count = 1,
543 },
544 },
545 .{
546 "@hasDecl",
547 .{
548 .tag = .has_decl,
549 .param_count = 2,
550 },
551 },
552 .{
553 "@hasField",
554 .{
555 .tag = .has_field,
556 .param_count = 2,
557 },
558 },
559 .{
560 "@import",
561 .{
562 .tag = .import,
563 .param_count = 1,
564 },
565 },
566 .{
567 "@inComptime",
568 .{
569 .tag = .in_comptime,
570 .param_count = 0,
571 },
572 },
573 .{
574 "@intCast",
575 .{
576 .tag = .int_cast,
577 .param_count = 1,
578 },
579 },
580 .{
581 "@enumFromInt",
582 .{
583 .tag = .enum_from_int,
584 .param_count = 1,
585 },
586 },
587 .{
588 "@errorFromInt",
589 .{
590 .tag = .error_from_int,
591 .eval_to_error = .always,
592 .param_count = 1,
593 },
594 },
595 .{
596 "@floatFromInt",
597 .{
598 .tag = .float_from_int,
599 .param_count = 1,
600 },
601 },
602 .{
603 "@ptrFromInt",
604 .{
605 .tag = .ptr_from_int,
606 .param_count = 1,
607 },
608 },
609 .{
610 "@max",
611 .{
612 .tag = .max,
613 .param_count = null,
614 },
615 },
616 .{
617 "@memcpy",
618 .{
619 .tag = .memcpy,
620 .param_count = 2,
621 },
622 },
623 .{
624 "@memset",
625 .{
626 .tag = .memset,
627 .param_count = 2,
628 },
629 },
630 .{
631 "@min",
632 .{
633 .tag = .min,
634 .param_count = null,
635 },
636 },
637 .{
638 "@wasmMemorySize",
639 .{
640 .tag = .wasm_memory_size,
641 .param_count = 1,
642 },
643 },
644 .{
645 "@wasmMemoryGrow",
646 .{
647 .tag = .wasm_memory_grow,
648 .param_count = 2,
649 },
650 },
651 .{
652 "@mod",
653 .{
654 .tag = .mod,
655 .param_count = 2,
656 },
657 },
658 .{
659 "@mulWithOverflow",
660 .{
661 .tag = .mul_with_overflow,
662 .param_count = 2,
663 },
664 },
665 .{
666 "@panic",
667 .{
668 .tag = .panic,
669 .param_count = 1,
670 },
671 },
672 .{
673 "@popCount",
674 .{
675 .tag = .pop_count,
676 .param_count = 1,
677 },
678 },
679 .{
680 "@prefetch",
681 .{
682 .tag = .prefetch,
683 .param_count = 2,
684 },
685 },
686 .{
687 "@ptrCast",
688 .{
689 .tag = .ptr_cast,
690 .param_count = 1,
691 },
692 },
693 .{
694 "@intFromPtr",
695 .{
696 .tag = .int_from_ptr,
697 .param_count = 1,
698 },
699 },
700 .{
701 "@rem",
702 .{
703 .tag = .rem,
704 .param_count = 2,
705 },
706 },
707 .{
708 "@returnAddress",
709 .{
710 .tag = .return_address,
711 .param_count = 0,
712 },
713 },
714 .{
715 "@select",
716 .{
717 .tag = .select,
718 .param_count = 4,
719 },
720 },
721 .{
722 "@setAlignStack",
723 .{
724 .tag = .set_align_stack,
725 .param_count = 1,
726 },
727 },
728 .{
729 "@setCold",
730 .{
731 .tag = .set_cold,
732 .param_count = 1,
733 },
734 },
735 .{
736 "@setEvalBranchQuota",
737 .{
738 .tag = .set_eval_branch_quota,
739 .param_count = 1,
740 },
741 },
742 .{
743 "@setFloatMode",
744 .{
745 .tag = .set_float_mode,
746 .param_count = 1,
747 },
748 },
749 .{
750 "@setRuntimeSafety",
751 .{
752 .tag = .set_runtime_safety,
753 .param_count = 1,
754 },
755 },
756 .{
757 "@shlExact",
758 .{
759 .tag = .shl_exact,
760 .param_count = 2,
761 },
762 },
763 .{
764 "@shlWithOverflow",
765 .{
766 .tag = .shl_with_overflow,
767 .param_count = 2,
768 },
769 },
770 .{
771 "@shrExact",
772 .{
773 .tag = .shr_exact,
774 .param_count = 2,
775 },
776 },
777 .{
778 "@shuffle",
779 .{
780 .tag = .shuffle,
781 .param_count = 4,
782 },
783 },
784 .{
785 "@sizeOf",
786 .{
787 .tag = .size_of,
788 .param_count = 1,
789 },
790 },
791 .{
792 "@splat",
793 .{
794 .tag = .splat,
795 .param_count = 1,
796 },
797 },
798 .{
799 "@reduce",
800 .{
801 .tag = .reduce,
802 .param_count = 2,
803 },
804 },
805 .{
806 "@src",
807 .{
808 .tag = .src,
809 .needs_mem_loc = .always,
810 .param_count = 0,
811 },
812 },
813 .{
814 "@sqrt",
815 .{
816 .tag = .sqrt,
817 .param_count = 1,
818 },
819 },
820 .{
821 "@sin",
822 .{
823 .tag = .sin,
824 .param_count = 1,
825 },
826 },
827 .{
828 "@cos",
829 .{
830 .tag = .cos,
831 .param_count = 1,
832 },
833 },
834 .{
835 "@tan",
836 .{
837 .tag = .tan,
838 .param_count = 1,
839 },
840 },
841 .{
842 "@exp",
843 .{
844 .tag = .exp,
845 .param_count = 1,
846 },
847 },
848 .{
849 "@exp2",
850 .{
851 .tag = .exp2,
852 .param_count = 1,
853 },
854 },
855 .{
856 "@log",
857 .{
858 .tag = .log,
859 .param_count = 1,
860 },
861 },
862 .{
863 "@log2",
864 .{
865 .tag = .log2,
866 .param_count = 1,
867 },
868 },
869 .{
870 "@log10",
871 .{
872 .tag = .log10,
873 .param_count = 1,
874 },
875 },
876 .{
877 "@abs",
878 .{
879 .tag = .abs,
880 .param_count = 1,
881 },
882 },
883 .{
884 "@floor",
885 .{
886 .tag = .floor,
887 .param_count = 1,
888 },
889 },
890 .{
891 "@ceil",
892 .{
893 .tag = .ceil,
894 .param_count = 1,
895 },
896 },
897 .{
898 "@trunc",
899 .{
900 .tag = .trunc,
901 .param_count = 1,
902 },
903 },
904 .{
905 "@round",
906 .{
907 .tag = .round,
908 .param_count = 1,
909 },
910 },
911 .{
912 "@subWithOverflow",
913 .{
914 .tag = .sub_with_overflow,
915 .param_count = 2,
916 },
917 },
918 .{
919 "@tagName",
920 .{
921 .tag = .tag_name,
922 .param_count = 1,
923 },
924 },
925 .{
926 "@This",
927 .{
928 .tag = .This,
929 .param_count = 0,
930 },
931 },
932 .{
933 "@trap",
934 .{
935 .tag = .trap,
936 .param_count = 0,
937 },
938 },
939 .{
940 "@truncate",
941 .{
942 .tag = .truncate,
943 .param_count = 1,
944 },
945 },
946 .{
947 "@Type",
948 .{
949 .tag = .Type,
950 .param_count = 1,
951 },
952 },
953 .{
954 "@typeInfo",
955 .{
956 .tag = .type_info,
957 .param_count = 1,
958 },
959 },
960 .{
961 "@typeName",
962 .{
963 .tag = .type_name,
964 .param_count = 1,
965 },
966 },
967 .{
968 "@TypeOf",
969 .{
970 .tag = .TypeOf,
971 .param_count = null,
972 },
973 },
974 .{
975 "@unionInit",
976 .{
977 .tag = .union_init,
978 .needs_mem_loc = .always,
979 .param_count = 3,
980 },
981 },
982 .{
983 "@Vector",
984 .{
985 .tag = .Vector,
986 .param_count = 2,
987 },
988 },
989 .{
990 "@volatileCast",
991 .{
992 .tag = .volatile_cast,
993 .param_count = 1,
994 },
995 },
996 .{
997 "@workItemId", .{
998 .tag = .work_item_id,
999 .param_count = 1,
1000 },
1001 },
1002 .{
1003 "@workGroupSize",
1004 .{
1005 .tag = .work_group_size,
1006 .param_count = 1,
1007 },
1008 },
1009 .{
1010 "@workGroupId",
1011 .{
1012 .tag = .work_group_id,
1013 .param_count = 1,
1014 },
1015 },
1016 });
1017};
src/AstGen.zig+2-12
......@@ -13,9 +13,8 @@ const StringIndexContext = std.hash_map.StringIndexContext;
1313const isPrimitive = std.zig.primitives.isPrimitive;
1414
1515const Zir = @import("Zir.zig");
16const trace = @import("tracy.zig").trace;
17const BuiltinFn = @import("BuiltinFn.zig");
18const AstRlAnnotate = @import("AstRlAnnotate.zig");
16const BuiltinFn = std.zig.BuiltinFn;
17const AstRlAnnotate = std.zig.AstRlAnnotate;
1918
2019gpa: Allocator,
2120tree: *const Ast,
......@@ -2265,9 +2264,6 @@ fn blockExpr(
22652264 block_node: Ast.Node.Index,
22662265 statements: []const Ast.Node.Index,
22672266) InnerError!Zir.Inst.Ref {
2268 const tracy = trace(@src());
2269 defer tracy.end();
2270
22712267 const astgen = gz.astgen;
22722268 const tree = astgen.tree;
22732269 const main_tokens = tree.nodes.items(.main_token);
......@@ -2349,9 +2345,6 @@ fn labeledBlockExpr(
23492345 statements: []const Ast.Node.Index,
23502346 force_comptime: bool,
23512347) InnerError!Zir.Inst.Ref {
2352 const tracy = trace(@src());
2353 defer tracy.end();
2354
23552348 const astgen = gz.astgen;
23562349 const tree = astgen.tree;
23572350 const main_tokens = tree.nodes.items(.main_token);
......@@ -7473,9 +7466,6 @@ fn identifier(
74737466 ri: ResultInfo,
74747467 ident: Ast.Node.Index,
74757468) InnerError!Zir.Inst.Ref {
7476 const tracy = trace(@src());
7477 defer tracy.end();
7478
74797469 const astgen = gz.astgen;
74807470 const tree = astgen.tree;
74817471 const main_tokens = tree.nodes.items(.main_token);
src/AstRlAnnotate.zig deleted-1105
......@@ -1,1105 +0,0 @@
1//! AstRlAnnotate is a simple pass which runs over the AST before AstGen to
2//! determine which expressions require result locations.
3//!
4//! In some cases, AstGen can choose whether to provide a result pointer or to
5//! just use standard `break` instructions from a block. The latter choice can
6//! result in more efficient ZIR and runtime code, but does not allow for RLS to
7//! occur. Thus, we want to provide a real result pointer (from an alloc) only
8//! when necessary.
9//!
10//! To achive this, we need to determine which expressions require a result
11//! pointer. This pass is reponsible for analyzing all syntax forms which may
12//! provide a result location and, if sub-expressions consume this result
13//! pointer non-trivially (e.g. writing through field pointers), marking the
14//! node as requiring a result location.
15
16const std = @import("std");
17const AstRlAnnotate = @This();
18const Ast = std.zig.Ast;
19const Allocator = std.mem.Allocator;
20const AutoHashMapUnmanaged = std.AutoHashMapUnmanaged;
21const BuiltinFn = @import("BuiltinFn.zig");
22const assert = std.debug.assert;
23
24gpa: Allocator,
25arena: Allocator,
26tree: *const Ast,
27
28/// Certain nodes are placed in this set under the following conditions:
29/// * if-else: either branch consumes the result location
30/// * labeled block: any break consumes the result location
31/// * switch: any prong consumes the result location
32/// * orelse/catch: the RHS expression consumes the result location
33/// * while/for: any break consumes the result location
34/// * @as: the second operand consumes the result location
35/// * const: the init expression consumes the result location
36/// * return: the return expression consumes the result location
37nodes_need_rl: RlNeededSet = .{},
38
39pub const RlNeededSet = AutoHashMapUnmanaged(Ast.Node.Index, void);
40
41const ResultInfo = packed struct {
42 /// Do we have a known result type?
43 have_type: bool,
44 /// Do we (potentially) have a result pointer? Note that this pointer's type
45 /// may not be known due to it being an inferred alloc.
46 have_ptr: bool,
47
48 const none: ResultInfo = .{ .have_type = false, .have_ptr = false };
49 const typed_ptr: ResultInfo = .{ .have_type = true, .have_ptr = true };
50 const inferred_ptr: ResultInfo = .{ .have_type = false, .have_ptr = true };
51 const type_only: ResultInfo = .{ .have_type = true, .have_ptr = false };
52};
53
54/// A labeled block or a loop. When this block is broken from, `consumes_res_ptr`
55/// should be set if the break expression consumed the result pointer.
56const Block = struct {
57 parent: ?*Block,
58 label: ?[]const u8,
59 is_loop: bool,
60 ri: ResultInfo,
61 consumes_res_ptr: bool,
62};
63
64pub fn annotate(gpa: Allocator, arena: Allocator, tree: Ast) Allocator.Error!RlNeededSet {
65 var astrl: AstRlAnnotate = .{
66 .gpa = gpa,
67 .arena = arena,
68 .tree = &tree,
69 };
70 defer astrl.deinit(gpa);
71
72 if (tree.errors.len != 0) {
73 // We can't perform analysis on a broken AST. AstGen will not run in
74 // this case.
75 return .{};
76 }
77
78 for (tree.containerDeclRoot().ast.members) |member_node| {
79 _ = try astrl.expr(member_node, null, ResultInfo.none);
80 }
81
82 return astrl.nodes_need_rl.move();
83}
84
85fn deinit(astrl: *AstRlAnnotate, gpa: Allocator) void {
86 astrl.nodes_need_rl.deinit(gpa);
87}
88
89fn containerDecl(
90 astrl: *AstRlAnnotate,
91 block: ?*Block,
92 full: Ast.full.ContainerDecl,
93) !void {
94 const tree = astrl.tree;
95 const token_tags = tree.tokens.items(.tag);
96 switch (token_tags[full.ast.main_token]) {
97 .keyword_struct => {
98 if (full.ast.arg != 0) {
99 _ = try astrl.expr(full.ast.arg, block, ResultInfo.type_only);
100 }
101 for (full.ast.members) |member_node| {
102 _ = try astrl.expr(member_node, block, ResultInfo.none);
103 }
104 },
105 .keyword_union => {
106 if (full.ast.arg != 0) {
107 _ = try astrl.expr(full.ast.arg, block, ResultInfo.type_only);
108 }
109 for (full.ast.members) |member_node| {
110 _ = try astrl.expr(member_node, block, ResultInfo.none);
111 }
112 },
113 .keyword_enum => {
114 if (full.ast.arg != 0) {
115 _ = try astrl.expr(full.ast.arg, block, ResultInfo.type_only);
116 }
117 for (full.ast.members) |member_node| {
118 _ = try astrl.expr(member_node, block, ResultInfo.none);
119 }
120 },
121 .keyword_opaque => {
122 for (full.ast.members) |member_node| {
123 _ = try astrl.expr(member_node, block, ResultInfo.none);
124 }
125 },
126 else => unreachable,
127 }
128}
129
130/// Returns true if `rl` provides a result pointer and the expression consumes it.
131fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultInfo) Allocator.Error!bool {
132 const tree = astrl.tree;
133 const token_tags = tree.tokens.items(.tag);
134 const node_datas = tree.nodes.items(.data);
135 const node_tags = tree.nodes.items(.tag);
136 switch (node_tags[node]) {
137 .root,
138 .switch_case_one,
139 .switch_case_inline_one,
140 .switch_case,
141 .switch_case_inline,
142 .switch_range,
143 .for_range,
144 .asm_output,
145 .asm_input,
146 => unreachable,
147
148 .@"errdefer", .@"defer" => {
149 _ = try astrl.expr(node_datas[node].rhs, block, ResultInfo.none);
150 return false;
151 },
152
153 .container_field_init,
154 .container_field_align,
155 .container_field,
156 => {
157 const full = tree.fullContainerField(node).?;
158 _ = try astrl.expr(full.ast.type_expr, block, ResultInfo.type_only);
159 if (full.ast.align_expr != 0) {
160 _ = try astrl.expr(full.ast.align_expr, block, ResultInfo.type_only);
161 }
162 if (full.ast.value_expr != 0) {
163 _ = try astrl.expr(full.ast.value_expr, block, ResultInfo.type_only);
164 }
165 return false;
166 },
167 .@"usingnamespace" => {
168 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.type_only);
169 return false;
170 },
171 .test_decl => {
172 _ = try astrl.expr(node_datas[node].rhs, block, ResultInfo.none);
173 return false;
174 },
175 .global_var_decl,
176 .local_var_decl,
177 .simple_var_decl,
178 .aligned_var_decl,
179 => {
180 const full = tree.fullVarDecl(node).?;
181 const init_ri = if (full.ast.type_node != 0) init_ri: {
182 _ = try astrl.expr(full.ast.type_node, block, ResultInfo.type_only);
183 break :init_ri ResultInfo.typed_ptr;
184 } else ResultInfo.inferred_ptr;
185 if (full.ast.init_node == 0) {
186 // No init node, so we're done.
187 return false;
188 }
189 switch (token_tags[full.ast.mut_token]) {
190 .keyword_const => {
191 const init_consumes_rl = try astrl.expr(full.ast.init_node, block, init_ri);
192 if (init_consumes_rl) {
193 try astrl.nodes_need_rl.putNoClobber(astrl.gpa, node, {});
194 }
195 return false;
196 },
197 .keyword_var => {
198 // We'll create an alloc either way, so don't care if the
199 // result pointer is consumed.
200 _ = try astrl.expr(full.ast.init_node, block, init_ri);
201 return false;
202 },
203 else => unreachable,
204 }
205 },
206 .assign_destructure => {
207 const lhs_count = tree.extra_data[node_datas[node].lhs];
208 const all_lhs = tree.extra_data[node_datas[node].lhs + 1 ..][0..lhs_count];
209 for (all_lhs) |lhs| {
210 _ = try astrl.expr(lhs, block, ResultInfo.none);
211 }
212 // We don't need to gather any meaningful data here, because destructures always use RLS
213 _ = try astrl.expr(node_datas[node].rhs, block, ResultInfo.none);
214 return false;
215 },
216 .assign => {
217 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none);
218 _ = try astrl.expr(node_datas[node].rhs, block, ResultInfo.typed_ptr);
219 return false;
220 },
221 .assign_shl,
222 .assign_shl_sat,
223 .assign_shr,
224 .assign_bit_and,
225 .assign_bit_or,
226 .assign_bit_xor,
227 .assign_div,
228 .assign_sub,
229 .assign_sub_wrap,
230 .assign_sub_sat,
231 .assign_mod,
232 .assign_add,
233 .assign_add_wrap,
234 .assign_add_sat,
235 .assign_mul,
236 .assign_mul_wrap,
237 .assign_mul_sat,
238 => {
239 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none);
240 _ = try astrl.expr(node_datas[node].rhs, block, ResultInfo.none);
241 return false;
242 },
243 .shl, .shr => {
244 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none);
245 _ = try astrl.expr(node_datas[node].rhs, block, ResultInfo.type_only);
246 return false;
247 },
248 .add,
249 .add_wrap,
250 .add_sat,
251 .sub,
252 .sub_wrap,
253 .sub_sat,
254 .mul,
255 .mul_wrap,
256 .mul_sat,
257 .div,
258 .mod,
259 .shl_sat,
260 .bit_and,
261 .bit_or,
262 .bit_xor,
263 .bang_equal,
264 .equal_equal,
265 .greater_than,
266 .greater_or_equal,
267 .less_than,
268 .less_or_equal,
269 .array_cat,
270 => {
271 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none);
272 _ = try astrl.expr(node_datas[node].rhs, block, ResultInfo.none);
273 return false;
274 },
275 .array_mult => {
276 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none);
277 _ = try astrl.expr(node_datas[node].rhs, block, ResultInfo.type_only);
278 return false;
279 },
280 .error_union, .merge_error_sets => {
281 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none);
282 _ = try astrl.expr(node_datas[node].rhs, block, ResultInfo.none);
283 return false;
284 },
285 .bool_and,
286 .bool_or,
287 => {
288 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.type_only);
289 _ = try astrl.expr(node_datas[node].rhs, block, ResultInfo.type_only);
290 return false;
291 },
292 .bool_not => {
293 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.type_only);
294 return false;
295 },
296 .bit_not, .negation, .negation_wrap => {
297 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none);
298 return false;
299 },
300
301 // These nodes are leaves and never consume a result location.
302 .identifier,
303 .string_literal,
304 .multiline_string_literal,
305 .number_literal,
306 .unreachable_literal,
307 .asm_simple,
308 .@"asm",
309 .enum_literal,
310 .error_value,
311 .anyframe_literal,
312 .@"continue",
313 .char_literal,
314 .error_set_decl,
315 => return false,
316
317 .builtin_call_two, .builtin_call_two_comma => {
318 if (node_datas[node].lhs == 0) {
319 return astrl.builtinCall(block, ri, node, &.{});
320 } else if (node_datas[node].rhs == 0) {
321 return astrl.builtinCall(block, ri, node, &.{node_datas[node].lhs});
322 } else {
323 return astrl.builtinCall(block, ri, node, &.{ node_datas[node].lhs, node_datas[node].rhs });
324 }
325 },
326 .builtin_call, .builtin_call_comma => {
327 const params = tree.extra_data[node_datas[node].lhs..node_datas[node].rhs];
328 return astrl.builtinCall(block, ri, node, params);
329 },
330
331 .call_one,
332 .call_one_comma,
333 .async_call_one,
334 .async_call_one_comma,
335 .call,
336 .call_comma,
337 .async_call,
338 .async_call_comma,
339 => {
340 var buf: [1]Ast.Node.Index = undefined;
341 const full = tree.fullCall(&buf, node).?;
342 _ = try astrl.expr(full.ast.fn_expr, block, ResultInfo.none);
343 for (full.ast.params) |param_node| {
344 _ = try astrl.expr(param_node, block, ResultInfo.type_only);
345 }
346 return switch (node_tags[node]) {
347 .call_one,
348 .call_one_comma,
349 .call,
350 .call_comma,
351 => false, // TODO: once function calls are passed result locations this will change
352 .async_call_one,
353 .async_call_one_comma,
354 .async_call,
355 .async_call_comma,
356 => ri.have_ptr, // always use result ptr for frames
357 else => unreachable,
358 };
359 },
360
361 .@"return" => {
362 if (node_datas[node].lhs != 0) {
363 const ret_val_consumes_rl = try astrl.expr(node_datas[node].lhs, block, ResultInfo.typed_ptr);
364 if (ret_val_consumes_rl) {
365 try astrl.nodes_need_rl.putNoClobber(astrl.gpa, node, {});
366 }
367 }
368 return false;
369 },
370
371 .field_access => {
372 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none);
373 return false;
374 },
375
376 .if_simple, .@"if" => {
377 const full = tree.fullIf(node).?;
378 if (full.error_token != null or full.payload_token != null) {
379 _ = try astrl.expr(full.ast.cond_expr, block, ResultInfo.none);
380 } else {
381 _ = try astrl.expr(full.ast.cond_expr, block, ResultInfo.type_only); // bool
382 }
383
384 if (full.ast.else_expr == 0) {
385 _ = try astrl.expr(full.ast.then_expr, block, ResultInfo.none);
386 return false;
387 } else {
388 const then_uses_rl = try astrl.expr(full.ast.then_expr, block, ri);
389 const else_uses_rl = try astrl.expr(full.ast.else_expr, block, ri);
390 const uses_rl = then_uses_rl or else_uses_rl;
391 if (uses_rl) try astrl.nodes_need_rl.putNoClobber(astrl.gpa, node, {});
392 return uses_rl;
393 }
394 },
395
396 .while_simple, .while_cont, .@"while" => {
397 const full = tree.fullWhile(node).?;
398 const label: ?[]const u8 = if (full.label_token) |label_token| label: {
399 break :label try astrl.identString(label_token);
400 } else null;
401 if (full.error_token != null or full.payload_token != null) {
402 _ = try astrl.expr(full.ast.cond_expr, block, ResultInfo.none);
403 } else {
404 _ = try astrl.expr(full.ast.cond_expr, block, ResultInfo.type_only); // bool
405 }
406 var new_block: Block = .{
407 .parent = block,
408 .label = label,
409 .is_loop = true,
410 .ri = ri,
411 .consumes_res_ptr = false,
412 };
413 if (full.ast.cont_expr != 0) {
414 _ = try astrl.expr(full.ast.cont_expr, &new_block, ResultInfo.none);
415 }
416 _ = try astrl.expr(full.ast.then_expr, &new_block, ResultInfo.none);
417 const else_consumes_rl = if (full.ast.else_expr != 0) else_rl: {
418 break :else_rl try astrl.expr(full.ast.else_expr, block, ri);
419 } else false;
420 if (new_block.consumes_res_ptr or else_consumes_rl) {
421 try astrl.nodes_need_rl.putNoClobber(astrl.gpa, node, {});
422 return true;
423 } else {
424 return false;
425 }
426 },
427
428 .for_simple, .@"for" => {
429 const full = tree.fullFor(node).?;
430 const label: ?[]const u8 = if (full.label_token) |label_token| label: {
431 break :label try astrl.identString(label_token);
432 } else null;
433 for (full.ast.inputs) |input| {
434 if (node_tags[input] == .for_range) {
435 _ = try astrl.expr(node_datas[input].lhs, block, ResultInfo.type_only);
436 if (node_datas[input].rhs != 0) {
437 _ = try astrl.expr(node_datas[input].rhs, block, ResultInfo.type_only);
438 }
439 } else {
440 _ = try astrl.expr(input, block, ResultInfo.none);
441 }
442 }
443 var new_block: Block = .{
444 .parent = block,
445 .label = label,
446 .is_loop = true,
447 .ri = ri,
448 .consumes_res_ptr = false,
449 };
450 _ = try astrl.expr(full.ast.then_expr, &new_block, ResultInfo.none);
451 const else_consumes_rl = if (full.ast.else_expr != 0) else_rl: {
452 break :else_rl try astrl.expr(full.ast.else_expr, block, ri);
453 } else false;
454 if (new_block.consumes_res_ptr or else_consumes_rl) {
455 try astrl.nodes_need_rl.putNoClobber(astrl.gpa, node, {});
456 return true;
457 } else {
458 return false;
459 }
460 },
461
462 .slice_open => {
463 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none);
464 _ = try astrl.expr(node_datas[node].rhs, block, ResultInfo.type_only);
465 return false;
466 },
467 .slice => {
468 const extra = tree.extraData(node_datas[node].rhs, Ast.Node.Slice);
469 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none);
470 _ = try astrl.expr(extra.start, block, ResultInfo.type_only);
471 _ = try astrl.expr(extra.end, block, ResultInfo.type_only);
472 return false;
473 },
474 .slice_sentinel => {
475 const extra = tree.extraData(node_datas[node].rhs, Ast.Node.SliceSentinel);
476 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none);
477 _ = try astrl.expr(extra.start, block, ResultInfo.type_only);
478 if (extra.end != 0) {
479 _ = try astrl.expr(extra.end, block, ResultInfo.type_only);
480 }
481 _ = try astrl.expr(extra.sentinel, block, ResultInfo.none);
482 return false;
483 },
484 .deref => {
485 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none);
486 return false;
487 },
488 .address_of => {
489 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none);
490 return false;
491 },
492 .optional_type => {
493 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.type_only);
494 return false;
495 },
496 .grouped_expression,
497 .@"try",
498 .@"await",
499 .@"nosuspend",
500 .unwrap_optional,
501 => return astrl.expr(node_datas[node].lhs, block, ri),
502
503 .block_two, .block_two_semicolon => {
504 if (node_datas[node].lhs == 0) {
505 return astrl.blockExpr(block, ri, node, &.{});
506 } else if (node_datas[node].rhs == 0) {
507 return astrl.blockExpr(block, ri, node, &.{node_datas[node].lhs});
508 } else {
509 return astrl.blockExpr(block, ri, node, &.{ node_datas[node].lhs, node_datas[node].rhs });
510 }
511 },
512 .block, .block_semicolon => {
513 const statements = tree.extra_data[node_datas[node].lhs..node_datas[node].rhs];
514 return astrl.blockExpr(block, ri, node, statements);
515 },
516 .anyframe_type => {
517 _ = try astrl.expr(node_datas[node].rhs, block, ResultInfo.type_only);
518 return false;
519 },
520 .@"catch", .@"orelse" => {
521 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none);
522 const rhs_consumes_rl = try astrl.expr(node_datas[node].rhs, block, ri);
523 if (rhs_consumes_rl) {
524 try astrl.nodes_need_rl.putNoClobber(astrl.gpa, node, {});
525 }
526 return rhs_consumes_rl;
527 },
528
529 .ptr_type_aligned,
530 .ptr_type_sentinel,
531 .ptr_type,
532 .ptr_type_bit_range,
533 => {
534 const full = tree.fullPtrType(node).?;
535 _ = try astrl.expr(full.ast.child_type, block, ResultInfo.type_only);
536 if (full.ast.sentinel != 0) {
537 _ = try astrl.expr(full.ast.sentinel, block, ResultInfo.type_only);
538 }
539 if (full.ast.addrspace_node != 0) {
540 _ = try astrl.expr(full.ast.addrspace_node, block, ResultInfo.type_only);
541 }
542 if (full.ast.align_node != 0) {
543 _ = try astrl.expr(full.ast.align_node, block, ResultInfo.type_only);
544 }
545 if (full.ast.bit_range_start != 0) {
546 assert(full.ast.bit_range_end != 0);
547 _ = try astrl.expr(full.ast.bit_range_start, block, ResultInfo.type_only);
548 _ = try astrl.expr(full.ast.bit_range_end, block, ResultInfo.type_only);
549 }
550 return false;
551 },
552
553 .container_decl,
554 .container_decl_trailing,
555 .container_decl_arg,
556 .container_decl_arg_trailing,
557 .container_decl_two,
558 .container_decl_two_trailing,
559 .tagged_union,
560 .tagged_union_trailing,
561 .tagged_union_enum_tag,
562 .tagged_union_enum_tag_trailing,
563 .tagged_union_two,
564 .tagged_union_two_trailing,
565 => {
566 var buf: [2]Ast.Node.Index = undefined;
567 try astrl.containerDecl(block, tree.fullContainerDecl(&buf, node).?);
568 return false;
569 },
570
571 .@"break" => {
572 if (node_datas[node].rhs == 0) {
573 // Breaks with void are not interesting
574 return false;
575 }
576
577 var opt_cur_block = block;
578 if (node_datas[node].lhs == 0) {
579 // No label - we're breaking from a loop.
580 while (opt_cur_block) |cur_block| : (opt_cur_block = cur_block.parent) {
581 if (cur_block.is_loop) break;
582 }
583 } else {
584 const break_label = try astrl.identString(node_datas[node].lhs);
585 while (opt_cur_block) |cur_block| : (opt_cur_block = cur_block.parent) {
586 const block_label = cur_block.label orelse continue;
587 if (std.mem.eql(u8, block_label, break_label)) break;
588 }
589 }
590
591 if (opt_cur_block) |target_block| {
592 const consumes_break_rl = try astrl.expr(node_datas[node].rhs, block, target_block.ri);
593 if (consumes_break_rl) target_block.consumes_res_ptr = true;
594 } else {
595 // No corresponding scope to break from - AstGen will emit an error.
596 _ = try astrl.expr(node_datas[node].rhs, block, ResultInfo.none);
597 }
598
599 return false;
600 },
601
602 .array_type => {
603 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.type_only);
604 _ = try astrl.expr(node_datas[node].rhs, block, ResultInfo.type_only);
605 return false;
606 },
607 .array_type_sentinel => {
608 const extra = tree.extraData(node_datas[node].rhs, Ast.Node.ArrayTypeSentinel);
609 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.type_only);
610 _ = try astrl.expr(extra.elem_type, block, ResultInfo.type_only);
611 _ = try astrl.expr(extra.sentinel, block, ResultInfo.type_only);
612 return false;
613 },
614 .array_access => {
615 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none);
616 _ = try astrl.expr(node_datas[node].rhs, block, ResultInfo.type_only);
617 return false;
618 },
619 .@"comptime" => {
620 // AstGen will emit an error if the scope is already comptime, so we can assume it is
621 // not. This means the result location is not forwarded.
622 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none);
623 return false;
624 },
625 .@"switch", .switch_comma => {
626 const operand_node = node_datas[node].lhs;
627 const extra = tree.extraData(node_datas[node].rhs, Ast.Node.SubRange);
628 const case_nodes = tree.extra_data[extra.start..extra.end];
629
630 _ = try astrl.expr(operand_node, block, ResultInfo.none);
631
632 var any_prong_consumed_rl = false;
633 for (case_nodes) |case_node| {
634 const case = tree.fullSwitchCase(case_node).?;
635 for (case.ast.values) |item_node| {
636 if (node_tags[item_node] == .switch_range) {
637 _ = try astrl.expr(node_datas[item_node].lhs, block, ResultInfo.none);
638 _ = try astrl.expr(node_datas[item_node].rhs, block, ResultInfo.none);
639 } else {
640 _ = try astrl.expr(item_node, block, ResultInfo.none);
641 }
642 }
643 if (try astrl.expr(case.ast.target_expr, block, ri)) {
644 any_prong_consumed_rl = true;
645 }
646 }
647 if (any_prong_consumed_rl) {
648 try astrl.nodes_need_rl.putNoClobber(astrl.gpa, node, {});
649 }
650 return any_prong_consumed_rl;
651 },
652 .@"suspend" => {
653 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none);
654 return false;
655 },
656 .@"resume" => {
657 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none);
658 return false;
659 },
660
661 .array_init_one,
662 .array_init_one_comma,
663 .array_init_dot_two,
664 .array_init_dot_two_comma,
665 .array_init_dot,
666 .array_init_dot_comma,
667 .array_init,
668 .array_init_comma,
669 => {
670 var buf: [2]Ast.Node.Index = undefined;
671 const full = tree.fullArrayInit(&buf, node).?;
672
673 if (full.ast.type_expr != 0) {
674 // Explicitly typed init does not participate in RLS
675 _ = try astrl.expr(full.ast.type_expr, block, ResultInfo.none);
676 for (full.ast.elements) |elem_init| {
677 _ = try astrl.expr(elem_init, block, ResultInfo.type_only);
678 }
679 return false;
680 }
681
682 if (ri.have_type) {
683 // Always forward type information
684 // If we have a result pointer, we use and forward it
685 for (full.ast.elements) |elem_init| {
686 _ = try astrl.expr(elem_init, block, ri);
687 }
688 return ri.have_ptr;
689 } else {
690 // Untyped init does not consume result location
691 for (full.ast.elements) |elem_init| {
692 _ = try astrl.expr(elem_init, block, ResultInfo.none);
693 }
694 return false;
695 }
696 },
697
698 .struct_init_one,
699 .struct_init_one_comma,
700 .struct_init_dot_two,
701 .struct_init_dot_two_comma,
702 .struct_init_dot,
703 .struct_init_dot_comma,
704 .struct_init,
705 .struct_init_comma,
706 => {
707 var buf: [2]Ast.Node.Index = undefined;
708 const full = tree.fullStructInit(&buf, node).?;
709
710 if (full.ast.type_expr != 0) {
711 // Explicitly typed init does not participate in RLS
712 _ = try astrl.expr(full.ast.type_expr, block, ResultInfo.none);
713 for (full.ast.fields) |field_init| {
714 _ = try astrl.expr(field_init, block, ResultInfo.type_only);
715 }
716 return false;
717 }
718
719 if (ri.have_type) {
720 // Always forward type information
721 // If we have a result pointer, we use and forward it
722 for (full.ast.fields) |field_init| {
723 _ = try astrl.expr(field_init, block, ri);
724 }
725 return ri.have_ptr;
726 } else {
727 // Untyped init does not consume result location
728 for (full.ast.fields) |field_init| {
729 _ = try astrl.expr(field_init, block, ResultInfo.none);
730 }
731 return false;
732 }
733 },
734
735 .fn_proto_simple,
736 .fn_proto_multi,
737 .fn_proto_one,
738 .fn_proto,
739 .fn_decl,
740 => {
741 var buf: [1]Ast.Node.Index = undefined;
742 const full = tree.fullFnProto(&buf, node).?;
743 const body_node = if (node_tags[node] == .fn_decl) node_datas[node].rhs else 0;
744 {
745 var it = full.iterate(tree);
746 while (it.next()) |param| {
747 if (param.anytype_ellipsis3 == null) {
748 _ = try astrl.expr(param.type_expr, block, ResultInfo.type_only);
749 }
750 }
751 }
752 if (full.ast.align_expr != 0) {
753 _ = try astrl.expr(full.ast.align_expr, block, ResultInfo.type_only);
754 }
755 if (full.ast.addrspace_expr != 0) {
756 _ = try astrl.expr(full.ast.addrspace_expr, block, ResultInfo.type_only);
757 }
758 if (full.ast.section_expr != 0) {
759 _ = try astrl.expr(full.ast.section_expr, block, ResultInfo.type_only);
760 }
761 if (full.ast.callconv_expr != 0) {
762 _ = try astrl.expr(full.ast.callconv_expr, block, ResultInfo.type_only);
763 }
764 _ = try astrl.expr(full.ast.return_type, block, ResultInfo.type_only);
765 if (body_node != 0) {
766 _ = try astrl.expr(body_node, block, ResultInfo.none);
767 }
768 return false;
769 },
770 }
771}
772
773fn identString(astrl: *AstRlAnnotate, token: Ast.TokenIndex) ![]const u8 {
774 const tree = astrl.tree;
775 const token_tags = tree.tokens.items(.tag);
776 assert(token_tags[token] == .identifier);
777 const ident_name = tree.tokenSlice(token);
778 if (!std.mem.startsWith(u8, ident_name, "@")) {
779 return ident_name;
780 }
781 return std.zig.string_literal.parseAlloc(astrl.arena, ident_name[1..]) catch |err| switch (err) {
782 error.OutOfMemory => error.OutOfMemory,
783 error.InvalidLiteral => "", // This pass can safely return garbage on invalid AST
784 };
785}
786
787fn blockExpr(astrl: *AstRlAnnotate, parent_block: ?*Block, ri: ResultInfo, node: Ast.Node.Index, statements: []const Ast.Node.Index) !bool {
788 const tree = astrl.tree;
789 const token_tags = tree.tokens.items(.tag);
790 const main_tokens = tree.nodes.items(.main_token);
791
792 const lbrace = main_tokens[node];
793 if (token_tags[lbrace - 1] == .colon and
794 token_tags[lbrace - 2] == .identifier)
795 {
796 // Labeled block
797 var new_block: Block = .{
798 .parent = parent_block,
799 .label = try astrl.identString(lbrace - 2),
800 .is_loop = false,
801 .ri = ri,
802 .consumes_res_ptr = false,
803 };
804 for (statements) |statement| {
805 _ = try astrl.expr(statement, &new_block, ResultInfo.none);
806 }
807 if (new_block.consumes_res_ptr) {
808 try astrl.nodes_need_rl.putNoClobber(astrl.gpa, node, {});
809 }
810 return new_block.consumes_res_ptr;
811 } else {
812 // Unlabeled block
813 for (statements) |statement| {
814 _ = try astrl.expr(statement, parent_block, ResultInfo.none);
815 }
816 return false;
817 }
818}
819
820fn builtinCall(astrl: *AstRlAnnotate, block: ?*Block, ri: ResultInfo, node: Ast.Node.Index, args: []const Ast.Node.Index) !bool {
821 _ = ri; // Currently, no builtin consumes its result location.
822
823 const tree = astrl.tree;
824 const main_tokens = tree.nodes.items(.main_token);
825 const builtin_token = main_tokens[node];
826 const builtin_name = tree.tokenSlice(builtin_token);
827 const info = BuiltinFn.list.get(builtin_name) orelse return false;
828 if (info.param_count) |expected| {
829 if (expected != args.len) return false;
830 }
831 switch (info.tag) {
832 .import => return false,
833 .compile_log, .TypeOf => {
834 for (args) |arg_node| {
835 _ = try astrl.expr(arg_node, block, ResultInfo.none);
836 }
837 return false;
838 },
839 .as => {
840 _ = try astrl.expr(args[0], block, ResultInfo.type_only);
841 _ = try astrl.expr(args[1], block, ResultInfo.type_only);
842 return false;
843 },
844 .bit_cast => {
845 _ = try astrl.expr(args[0], block, ResultInfo.none);
846 return false;
847 },
848 .union_init => {
849 _ = try astrl.expr(args[0], block, ResultInfo.type_only);
850 _ = try astrl.expr(args[1], block, ResultInfo.type_only);
851 _ = try astrl.expr(args[2], block, ResultInfo.type_only);
852 return false;
853 },
854 .c_import => {
855 _ = try astrl.expr(args[0], block, ResultInfo.none);
856 return false;
857 },
858 .min, .max => {
859 for (args) |arg_node| {
860 _ = try astrl.expr(arg_node, block, ResultInfo.none);
861 }
862 return false;
863 },
864 .@"export" => {
865 _ = try astrl.expr(args[0], block, ResultInfo.none);
866 _ = try astrl.expr(args[1], block, ResultInfo.type_only);
867 return false;
868 },
869 .@"extern" => {
870 _ = try astrl.expr(args[0], block, ResultInfo.type_only);
871 _ = try astrl.expr(args[1], block, ResultInfo.type_only);
872 return false;
873 },
874 // These builtins take no args and do not consume the result pointer.
875 .src,
876 .This,
877 .return_address,
878 .error_return_trace,
879 .frame,
880 .breakpoint,
881 .in_comptime,
882 .panic,
883 .trap,
884 .c_va_start,
885 => return false,
886 // TODO: this is a workaround for llvm/llvm-project#68409
887 // Zig tracking issue: #16876
888 .frame_address => return true,
889 // These builtins take a single argument with a known result type, but do not consume their
890 // result pointer.
891 .size_of,
892 .bit_size_of,
893 .align_of,
894 .compile_error,
895 .set_eval_branch_quota,
896 .int_from_bool,
897 .int_from_error,
898 .error_from_int,
899 .embed_file,
900 .error_name,
901 .set_runtime_safety,
902 .Type,
903 .c_undef,
904 .c_include,
905 .wasm_memory_size,
906 .splat,
907 .fence,
908 .set_float_mode,
909 .set_align_stack,
910 .set_cold,
911 .type_info,
912 .work_item_id,
913 .work_group_size,
914 .work_group_id,
915 => {
916 _ = try astrl.expr(args[0], block, ResultInfo.type_only);
917 return false;
918 },
919 // These builtins take a single argument with no result information and do not consume their
920 // result pointer.
921 .int_from_ptr,
922 .int_from_enum,
923 .sqrt,
924 .sin,
925 .cos,
926 .tan,
927 .exp,
928 .exp2,
929 .log,
930 .log2,
931 .log10,
932 .abs,
933 .floor,
934 .ceil,
935 .trunc,
936 .round,
937 .tag_name,
938 .type_name,
939 .Frame,
940 .frame_size,
941 .int_from_float,
942 .float_from_int,
943 .ptr_from_int,
944 .enum_from_int,
945 .float_cast,
946 .int_cast,
947 .truncate,
948 .error_cast,
949 .ptr_cast,
950 .align_cast,
951 .addrspace_cast,
952 .const_cast,
953 .volatile_cast,
954 .clz,
955 .ctz,
956 .pop_count,
957 .byte_swap,
958 .bit_reverse,
959 => {
960 _ = try astrl.expr(args[0], block, ResultInfo.none);
961 return false;
962 },
963 .div_exact,
964 .div_floor,
965 .div_trunc,
966 .mod,
967 .rem,
968 => {
969 _ = try astrl.expr(args[0], block, ResultInfo.none);
970 _ = try astrl.expr(args[1], block, ResultInfo.none);
971 return false;
972 },
973 .shl_exact, .shr_exact => {
974 _ = try astrl.expr(args[0], block, ResultInfo.none);
975 _ = try astrl.expr(args[1], block, ResultInfo.type_only);
976 return false;
977 },
978 .bit_offset_of,
979 .offset_of,
980 .field_parent_ptr,
981 .has_decl,
982 .has_field,
983 .field,
984 => {
985 _ = try astrl.expr(args[0], block, ResultInfo.type_only);
986 _ = try astrl.expr(args[1], block, ResultInfo.type_only);
987 return false;
988 },
989 .wasm_memory_grow => {
990 _ = try astrl.expr(args[0], block, ResultInfo.type_only);
991 _ = try astrl.expr(args[1], block, ResultInfo.type_only);
992 return false;
993 },
994 .c_define => {
995 _ = try astrl.expr(args[0], block, ResultInfo.type_only);
996 _ = try astrl.expr(args[1], block, ResultInfo.none);
997 return false;
998 },
999 .reduce => {
1000 _ = try astrl.expr(args[0], block, ResultInfo.type_only);
1001 _ = try astrl.expr(args[1], block, ResultInfo.none);
1002 return false;
1003 },
1004 .add_with_overflow, .sub_with_overflow, .mul_with_overflow, .shl_with_overflow => {
1005 _ = try astrl.expr(args[0], block, ResultInfo.none);
1006 _ = try astrl.expr(args[1], block, ResultInfo.none);
1007 return false;
1008 },
1009 .atomic_load => {
1010 _ = try astrl.expr(args[0], block, ResultInfo.type_only);
1011 _ = try astrl.expr(args[1], block, ResultInfo.none);
1012 _ = try astrl.expr(args[2], block, ResultInfo.type_only);
1013 return false;
1014 },
1015 .atomic_rmw => {
1016 _ = try astrl.expr(args[0], block, ResultInfo.type_only);
1017 _ = try astrl.expr(args[1], block, ResultInfo.none);
1018 _ = try astrl.expr(args[2], block, ResultInfo.type_only);
1019 _ = try astrl.expr(args[3], block, ResultInfo.type_only);
1020 _ = try astrl.expr(args[4], block, ResultInfo.type_only);
1021 return false;
1022 },
1023 .atomic_store => {
1024 _ = try astrl.expr(args[0], block, ResultInfo.type_only);
1025 _ = try astrl.expr(args[1], block, ResultInfo.none);
1026 _ = try astrl.expr(args[2], block, ResultInfo.type_only);
1027 _ = try astrl.expr(args[3], block, ResultInfo.type_only);
1028 return false;
1029 },
1030 .mul_add => {
1031 _ = try astrl.expr(args[0], block, ResultInfo.type_only);
1032 _ = try astrl.expr(args[1], block, ResultInfo.type_only);
1033 _ = try astrl.expr(args[2], block, ResultInfo.type_only);
1034 return false;
1035 },
1036 .call => {
1037 _ = try astrl.expr(args[0], block, ResultInfo.type_only);
1038 _ = try astrl.expr(args[1], block, ResultInfo.none);
1039 _ = try astrl.expr(args[2], block, ResultInfo.none);
1040 return false;
1041 },
1042 .memcpy => {
1043 _ = try astrl.expr(args[0], block, ResultInfo.none);
1044 _ = try astrl.expr(args[1], block, ResultInfo.none);
1045 return false;
1046 },
1047 .memset => {
1048 _ = try astrl.expr(args[0], block, ResultInfo.none);
1049 _ = try astrl.expr(args[1], block, ResultInfo.type_only);
1050 return false;
1051 },
1052 .shuffle => {
1053 _ = try astrl.expr(args[0], block, ResultInfo.type_only);
1054 _ = try astrl.expr(args[1], block, ResultInfo.none);
1055 _ = try astrl.expr(args[2], block, ResultInfo.none);
1056 _ = try astrl.expr(args[3], block, ResultInfo.none);
1057 return false;
1058 },
1059 .select => {
1060 _ = try astrl.expr(args[0], block, ResultInfo.type_only);
1061 _ = try astrl.expr(args[1], block, ResultInfo.none);
1062 _ = try astrl.expr(args[2], block, ResultInfo.none);
1063 _ = try astrl.expr(args[3], block, ResultInfo.none);
1064 return false;
1065 },
1066 .async_call => {
1067 _ = try astrl.expr(args[0], block, ResultInfo.none);
1068 _ = try astrl.expr(args[1], block, ResultInfo.none);
1069 _ = try astrl.expr(args[2], block, ResultInfo.none);
1070 _ = try astrl.expr(args[3], block, ResultInfo.none);
1071 return false; // buffer passed as arg for frame data
1072 },
1073 .Vector => {
1074 _ = try astrl.expr(args[0], block, ResultInfo.type_only);
1075 _ = try astrl.expr(args[1], block, ResultInfo.type_only);
1076 return false;
1077 },
1078 .prefetch => {
1079 _ = try astrl.expr(args[0], block, ResultInfo.none);
1080 _ = try astrl.expr(args[1], block, ResultInfo.type_only);
1081 return false;
1082 },
1083 .c_va_arg => {
1084 _ = try astrl.expr(args[0], block, ResultInfo.none);
1085 _ = try astrl.expr(args[1], block, ResultInfo.type_only);
1086 return false;
1087 },
1088 .c_va_copy => {
1089 _ = try astrl.expr(args[0], block, ResultInfo.none);
1090 return false;
1091 },
1092 .c_va_end => {
1093 _ = try astrl.expr(args[0], block, ResultInfo.none);
1094 return false;
1095 },
1096 .cmpxchg_strong, .cmpxchg_weak => {
1097 _ = try astrl.expr(args[0], block, ResultInfo.none);
1098 _ = try astrl.expr(args[1], block, ResultInfo.type_only);
1099 _ = try astrl.expr(args[2], block, ResultInfo.type_only);
1100 _ = try astrl.expr(args[3], block, ResultInfo.type_only);
1101 _ = try astrl.expr(args[4], block, ResultInfo.type_only);
1102 return false;
1103 },
1104 }
1105}
src/BuiltinFn.zig deleted-1017
......@@ -1,1017 +0,0 @@
1const std = @import("std");
2
3pub const Tag = enum {
4 add_with_overflow,
5 addrspace_cast,
6 align_cast,
7 align_of,
8 as,
9 async_call,
10 atomic_load,
11 atomic_rmw,
12 atomic_store,
13 bit_cast,
14 bit_offset_of,
15 int_from_bool,
16 bit_size_of,
17 breakpoint,
18 mul_add,
19 byte_swap,
20 bit_reverse,
21 offset_of,
22 call,
23 c_define,
24 c_import,
25 c_include,
26 clz,
27 cmpxchg_strong,
28 cmpxchg_weak,
29 compile_error,
30 compile_log,
31 const_cast,
32 ctz,
33 c_undef,
34 c_va_arg,
35 c_va_copy,
36 c_va_end,
37 c_va_start,
38 div_exact,
39 div_floor,
40 div_trunc,
41 embed_file,
42 int_from_enum,
43 error_name,
44 error_return_trace,
45 int_from_error,
46 error_cast,
47 @"export",
48 @"extern",
49 fence,
50 field,
51 field_parent_ptr,
52 float_cast,
53 int_from_float,
54 frame,
55 Frame,
56 frame_address,
57 frame_size,
58 has_decl,
59 has_field,
60 import,
61 in_comptime,
62 int_cast,
63 enum_from_int,
64 error_from_int,
65 float_from_int,
66 ptr_from_int,
67 max,
68 memcpy,
69 memset,
70 min,
71 wasm_memory_size,
72 wasm_memory_grow,
73 mod,
74 mul_with_overflow,
75 panic,
76 pop_count,
77 prefetch,
78 ptr_cast,
79 int_from_ptr,
80 rem,
81 return_address,
82 select,
83 set_align_stack,
84 set_cold,
85 set_eval_branch_quota,
86 set_float_mode,
87 set_runtime_safety,
88 shl_exact,
89 shl_with_overflow,
90 shr_exact,
91 shuffle,
92 size_of,
93 splat,
94 reduce,
95 src,
96 sqrt,
97 sin,
98 cos,
99 tan,
100 exp,
101 exp2,
102 log,
103 log2,
104 log10,
105 abs,
106 floor,
107 ceil,
108 trunc,
109 round,
110 sub_with_overflow,
111 tag_name,
112 This,
113 trap,
114 truncate,
115 Type,
116 type_info,
117 type_name,
118 TypeOf,
119 union_init,
120 Vector,
121 volatile_cast,
122 work_item_id,
123 work_group_size,
124 work_group_id,
125};
126
127pub const MemLocRequirement = enum {
128 /// The builtin never needs a memory location.
129 never,
130 /// The builtin always needs a memory location.
131 always,
132 /// The builtin forwards the question to argument at index 0.
133 forward0,
134 /// The builtin forwards the question to argument at index 1.
135 forward1,
136};
137
138pub const EvalToError = enum {
139 /// The builtin cannot possibly evaluate to an error.
140 never,
141 /// The builtin will always evaluate to an error.
142 always,
143 /// The builtin may or may not evaluate to an error depending on the parameters.
144 maybe,
145};
146
147tag: Tag,
148
149/// Info about the builtin call's ability to take advantage of a result location pointer.
150needs_mem_loc: MemLocRequirement = .never,
151/// Info about the builtin call's possibility of returning an error.
152eval_to_error: EvalToError = .never,
153/// `true` if the builtin call can be the left-hand side of an expression (assigned to).
154allows_lvalue: bool = false,
155/// The number of parameters to this builtin function. `null` means variable number
156/// of parameters.
157param_count: ?u8,
158
159pub const list = list: {
160 @setEvalBranchQuota(3000);
161 break :list std.ComptimeStringMap(@This(), .{
162 .{
163 "@addWithOverflow",
164 .{
165 .tag = .add_with_overflow,
166 .param_count = 2,
167 },
168 },
169 .{
170 "@addrSpaceCast",
171 .{
172 .tag = .addrspace_cast,
173 .param_count = 1,
174 },
175 },
176 .{
177 "@alignCast",
178 .{
179 .tag = .align_cast,
180 .param_count = 1,
181 },
182 },
183 .{
184 "@alignOf",
185 .{
186 .tag = .align_of,
187 .param_count = 1,
188 },
189 },
190 .{
191 "@as",
192 .{
193 .tag = .as,
194 .needs_mem_loc = .forward1,
195 .eval_to_error = .maybe,
196 .param_count = 2,
197 },
198 },
199 .{
200 "@asyncCall",
201 .{
202 .tag = .async_call,
203 .param_count = 4,
204 },
205 },
206 .{
207 "@atomicLoad",
208 .{
209 .tag = .atomic_load,
210 .param_count = 3,
211 },
212 },
213 .{
214 "@atomicRmw",
215 .{
216 .tag = .atomic_rmw,
217 .param_count = 5,
218 },
219 },
220 .{
221 "@atomicStore",
222 .{
223 .tag = .atomic_store,
224 .param_count = 4,
225 },
226 },
227 .{
228 "@bitCast",
229 .{
230 .tag = .bit_cast,
231 .needs_mem_loc = .forward0,
232 .param_count = 1,
233 },
234 },
235 .{
236 "@bitOffsetOf",
237 .{
238 .tag = .bit_offset_of,
239 .param_count = 2,
240 },
241 },
242 .{
243 "@intFromBool",
244 .{
245 .tag = .int_from_bool,
246 .param_count = 1,
247 },
248 },
249 .{
250 "@bitSizeOf",
251 .{
252 .tag = .bit_size_of,
253 .param_count = 1,
254 },
255 },
256 .{
257 "@breakpoint",
258 .{
259 .tag = .breakpoint,
260 .param_count = 0,
261 },
262 },
263 .{
264 "@mulAdd",
265 .{
266 .tag = .mul_add,
267 .param_count = 4,
268 },
269 },
270 .{
271 "@byteSwap",
272 .{
273 .tag = .byte_swap,
274 .param_count = 1,
275 },
276 },
277 .{
278 "@bitReverse",
279 .{
280 .tag = .bit_reverse,
281 .param_count = 1,
282 },
283 },
284 .{
285 "@offsetOf",
286 .{
287 .tag = .offset_of,
288 .param_count = 2,
289 },
290 },
291 .{
292 "@call",
293 .{
294 .tag = .call,
295 .needs_mem_loc = .always,
296 .eval_to_error = .maybe,
297 .param_count = 3,
298 },
299 },
300 .{
301 "@cDefine",
302 .{
303 .tag = .c_define,
304 .param_count = 2,
305 },
306 },
307 .{
308 "@cImport",
309 .{
310 .tag = .c_import,
311 .param_count = 1,
312 },
313 },
314 .{
315 "@cInclude",
316 .{
317 .tag = .c_include,
318 .param_count = 1,
319 },
320 },
321 .{
322 "@clz",
323 .{
324 .tag = .clz,
325 .param_count = 1,
326 },
327 },
328 .{
329 "@cmpxchgStrong",
330 .{
331 .tag = .cmpxchg_strong,
332 .param_count = 6,
333 },
334 },
335 .{
336 "@cmpxchgWeak",
337 .{
338 .tag = .cmpxchg_weak,
339 .param_count = 6,
340 },
341 },
342 .{
343 "@compileError",
344 .{
345 .tag = .compile_error,
346 .param_count = 1,
347 },
348 },
349 .{
350 "@compileLog",
351 .{
352 .tag = .compile_log,
353 .param_count = null,
354 },
355 },
356 .{
357 "@constCast",
358 .{
359 .tag = .const_cast,
360 .param_count = 1,
361 },
362 },
363 .{
364 "@ctz",
365 .{
366 .tag = .ctz,
367 .param_count = 1,
368 },
369 },
370 .{
371 "@cUndef",
372 .{
373 .tag = .c_undef,
374 .param_count = 1,
375 },
376 },
377 .{
378 "@cVaArg", .{
379 .tag = .c_va_arg,
380 .param_count = 2,
381 },
382 },
383 .{
384 "@cVaCopy", .{
385 .tag = .c_va_copy,
386 .param_count = 1,
387 },
388 },
389 .{
390 "@cVaEnd", .{
391 .tag = .c_va_end,
392 .param_count = 1,
393 },
394 },
395 .{
396 "@cVaStart", .{
397 .tag = .c_va_start,
398 .param_count = 0,
399 },
400 },
401 .{
402 "@divExact",
403 .{
404 .tag = .div_exact,
405 .param_count = 2,
406 },
407 },
408 .{
409 "@divFloor",
410 .{
411 .tag = .div_floor,
412 .param_count = 2,
413 },
414 },
415 .{
416 "@divTrunc",
417 .{
418 .tag = .div_trunc,
419 .param_count = 2,
420 },
421 },
422 .{
423 "@embedFile",
424 .{
425 .tag = .embed_file,
426 .param_count = 1,
427 },
428 },
429 .{
430 "@intFromEnum",
431 .{
432 .tag = .int_from_enum,
433 .param_count = 1,
434 },
435 },
436 .{
437 "@errorName",
438 .{
439 .tag = .error_name,
440 .param_count = 1,
441 },
442 },
443 .{
444 "@errorReturnTrace",
445 .{
446 .tag = .error_return_trace,
447 .param_count = 0,
448 },
449 },
450 .{
451 "@intFromError",
452 .{
453 .tag = .int_from_error,
454 .param_count = 1,
455 },
456 },
457 .{
458 "@errorCast",
459 .{
460 .tag = .error_cast,
461 .eval_to_error = .always,
462 .param_count = 1,
463 },
464 },
465 .{
466 "@export",
467 .{
468 .tag = .@"export",
469 .param_count = 2,
470 },
471 },
472 .{
473 "@extern",
474 .{
475 .tag = .@"extern",
476 .param_count = 2,
477 },
478 },
479 .{
480 "@fence",
481 .{
482 .tag = .fence,
483 .param_count = 1,
484 },
485 },
486 .{
487 "@field",
488 .{
489 .tag = .field,
490 .needs_mem_loc = .always,
491 .eval_to_error = .maybe,
492 .param_count = 2,
493 .allows_lvalue = true,
494 },
495 },
496 .{
497 "@fieldParentPtr",
498 .{
499 .tag = .field_parent_ptr,
500 .param_count = 3,
501 },
502 },
503 .{
504 "@floatCast",
505 .{
506 .tag = .float_cast,
507 .param_count = 1,
508 },
509 },
510 .{
511 "@intFromFloat",
512 .{
513 .tag = .int_from_float,
514 .param_count = 1,
515 },
516 },
517 .{
518 "@frame",
519 .{
520 .tag = .frame,
521 .param_count = 0,
522 },
523 },
524 .{
525 "@Frame",
526 .{
527 .tag = .Frame,
528 .param_count = 1,
529 },
530 },
531 .{
532 "@frameAddress",
533 .{
534 .tag = .frame_address,
535 .param_count = 0,
536 },
537 },
538 .{
539 "@frameSize",
540 .{
541 .tag = .frame_size,
542 .param_count = 1,
543 },
544 },
545 .{
546 "@hasDecl",
547 .{
548 .tag = .has_decl,
549 .param_count = 2,
550 },
551 },
552 .{
553 "@hasField",
554 .{
555 .tag = .has_field,
556 .param_count = 2,
557 },
558 },
559 .{
560 "@import",
561 .{
562 .tag = .import,
563 .param_count = 1,
564 },
565 },
566 .{
567 "@inComptime",
568 .{
569 .tag = .in_comptime,
570 .param_count = 0,
571 },
572 },
573 .{
574 "@intCast",
575 .{
576 .tag = .int_cast,
577 .param_count = 1,
578 },
579 },
580 .{
581 "@enumFromInt",
582 .{
583 .tag = .enum_from_int,
584 .param_count = 1,
585 },
586 },
587 .{
588 "@errorFromInt",
589 .{
590 .tag = .error_from_int,
591 .eval_to_error = .always,
592 .param_count = 1,
593 },
594 },
595 .{
596 "@floatFromInt",
597 .{
598 .tag = .float_from_int,
599 .param_count = 1,
600 },
601 },
602 .{
603 "@ptrFromInt",
604 .{
605 .tag = .ptr_from_int,
606 .param_count = 1,
607 },
608 },
609 .{
610 "@max",
611 .{
612 .tag = .max,
613 .param_count = null,
614 },
615 },
616 .{
617 "@memcpy",
618 .{
619 .tag = .memcpy,
620 .param_count = 2,
621 },
622 },
623 .{
624 "@memset",
625 .{
626 .tag = .memset,
627 .param_count = 2,
628 },
629 },
630 .{
631 "@min",
632 .{
633 .tag = .min,
634 .param_count = null,
635 },
636 },
637 .{
638 "@wasmMemorySize",
639 .{
640 .tag = .wasm_memory_size,
641 .param_count = 1,
642 },
643 },
644 .{
645 "@wasmMemoryGrow",
646 .{
647 .tag = .wasm_memory_grow,
648 .param_count = 2,
649 },
650 },
651 .{
652 "@mod",
653 .{
654 .tag = .mod,
655 .param_count = 2,
656 },
657 },
658 .{
659 "@mulWithOverflow",
660 .{
661 .tag = .mul_with_overflow,
662 .param_count = 2,
663 },
664 },
665 .{
666 "@panic",
667 .{
668 .tag = .panic,
669 .param_count = 1,
670 },
671 },
672 .{
673 "@popCount",
674 .{
675 .tag = .pop_count,
676 .param_count = 1,
677 },
678 },
679 .{
680 "@prefetch",
681 .{
682 .tag = .prefetch,
683 .param_count = 2,
684 },
685 },
686 .{
687 "@ptrCast",
688 .{
689 .tag = .ptr_cast,
690 .param_count = 1,
691 },
692 },
693 .{
694 "@intFromPtr",
695 .{
696 .tag = .int_from_ptr,
697 .param_count = 1,
698 },
699 },
700 .{
701 "@rem",
702 .{
703 .tag = .rem,
704 .param_count = 2,
705 },
706 },
707 .{
708 "@returnAddress",
709 .{
710 .tag = .return_address,
711 .param_count = 0,
712 },
713 },
714 .{
715 "@select",
716 .{
717 .tag = .select,
718 .param_count = 4,
719 },
720 },
721 .{
722 "@setAlignStack",
723 .{
724 .tag = .set_align_stack,
725 .param_count = 1,
726 },
727 },
728 .{
729 "@setCold",
730 .{
731 .tag = .set_cold,
732 .param_count = 1,
733 },
734 },
735 .{
736 "@setEvalBranchQuota",
737 .{
738 .tag = .set_eval_branch_quota,
739 .param_count = 1,
740 },
741 },
742 .{
743 "@setFloatMode",
744 .{
745 .tag = .set_float_mode,
746 .param_count = 1,
747 },
748 },
749 .{
750 "@setRuntimeSafety",
751 .{
752 .tag = .set_runtime_safety,
753 .param_count = 1,
754 },
755 },
756 .{
757 "@shlExact",
758 .{
759 .tag = .shl_exact,
760 .param_count = 2,
761 },
762 },
763 .{
764 "@shlWithOverflow",
765 .{
766 .tag = .shl_with_overflow,
767 .param_count = 2,
768 },
769 },
770 .{
771 "@shrExact",
772 .{
773 .tag = .shr_exact,
774 .param_count = 2,
775 },
776 },
777 .{
778 "@shuffle",
779 .{
780 .tag = .shuffle,
781 .param_count = 4,
782 },
783 },
784 .{
785 "@sizeOf",
786 .{
787 .tag = .size_of,
788 .param_count = 1,
789 },
790 },
791 .{
792 "@splat",
793 .{
794 .tag = .splat,
795 .param_count = 1,
796 },
797 },
798 .{
799 "@reduce",
800 .{
801 .tag = .reduce,
802 .param_count = 2,
803 },
804 },
805 .{
806 "@src",
807 .{
808 .tag = .src,
809 .needs_mem_loc = .always,
810 .param_count = 0,
811 },
812 },
813 .{
814 "@sqrt",
815 .{
816 .tag = .sqrt,
817 .param_count = 1,
818 },
819 },
820 .{
821 "@sin",
822 .{
823 .tag = .sin,
824 .param_count = 1,
825 },
826 },
827 .{
828 "@cos",
829 .{
830 .tag = .cos,
831 .param_count = 1,
832 },
833 },
834 .{
835 "@tan",
836 .{
837 .tag = .tan,
838 .param_count = 1,
839 },
840 },
841 .{
842 "@exp",
843 .{
844 .tag = .exp,
845 .param_count = 1,
846 },
847 },
848 .{
849 "@exp2",
850 .{
851 .tag = .exp2,
852 .param_count = 1,
853 },
854 },
855 .{
856 "@log",
857 .{
858 .tag = .log,
859 .param_count = 1,
860 },
861 },
862 .{
863 "@log2",
864 .{
865 .tag = .log2,
866 .param_count = 1,
867 },
868 },
869 .{
870 "@log10",
871 .{
872 .tag = .log10,
873 .param_count = 1,
874 },
875 },
876 .{
877 "@abs",
878 .{
879 .tag = .abs,
880 .param_count = 1,
881 },
882 },
883 .{
884 "@floor",
885 .{
886 .tag = .floor,
887 .param_count = 1,
888 },
889 },
890 .{
891 "@ceil",
892 .{
893 .tag = .ceil,
894 .param_count = 1,
895 },
896 },
897 .{
898 "@trunc",
899 .{
900 .tag = .trunc,
901 .param_count = 1,
902 },
903 },
904 .{
905 "@round",
906 .{
907 .tag = .round,
908 .param_count = 1,
909 },
910 },
911 .{
912 "@subWithOverflow",
913 .{
914 .tag = .sub_with_overflow,
915 .param_count = 2,
916 },
917 },
918 .{
919 "@tagName",
920 .{
921 .tag = .tag_name,
922 .param_count = 1,
923 },
924 },
925 .{
926 "@This",
927 .{
928 .tag = .This,
929 .param_count = 0,
930 },
931 },
932 .{
933 "@trap",
934 .{
935 .tag = .trap,
936 .param_count = 0,
937 },
938 },
939 .{
940 "@truncate",
941 .{
942 .tag = .truncate,
943 .param_count = 1,
944 },
945 },
946 .{
947 "@Type",
948 .{
949 .tag = .Type,
950 .param_count = 1,
951 },
952 },
953 .{
954 "@typeInfo",
955 .{
956 .tag = .type_info,
957 .param_count = 1,
958 },
959 },
960 .{
961 "@typeName",
962 .{
963 .tag = .type_name,
964 .param_count = 1,
965 },
966 },
967 .{
968 "@TypeOf",
969 .{
970 .tag = .TypeOf,
971 .param_count = null,
972 },
973 },
974 .{
975 "@unionInit",
976 .{
977 .tag = .union_init,
978 .needs_mem_loc = .always,
979 .param_count = 3,
980 },
981 },
982 .{
983 "@Vector",
984 .{
985 .tag = .Vector,
986 .param_count = 2,
987 },
988 },
989 .{
990 "@volatileCast",
991 .{
992 .tag = .volatile_cast,
993 .param_count = 1,
994 },
995 },
996 .{
997 "@workItemId", .{
998 .tag = .work_item_id,
999 .param_count = 1,
1000 },
1001 },
1002 .{
1003 "@workGroupSize",
1004 .{
1005 .tag = .work_group_size,
1006 .param_count = 1,
1007 },
1008 },
1009 .{
1010 "@workGroupId",
1011 .{
1012 .tag = .work_group_id,
1013 .param_count = 1,
1014 },
1015 },
1016 });
1017};
src/Module.zig+1-1
......@@ -34,7 +34,7 @@ const isUpDir = @import("introspect.zig").isUpDir;
3434const clang = @import("clang.zig");
3535const InternPool = @import("InternPool.zig");
3636const Alignment = InternPool.Alignment;
37const BuiltinFn = @import("BuiltinFn.zig");
37const BuiltinFn = std.zig.BuiltinFn;
3838
3939comptime {
4040 @setEvalBranchQuota(4000);
src/reduce/Walk.zig+1-1
......@@ -2,7 +2,7 @@ const std = @import("std");
22const Ast = std.zig.Ast;
33const Walk = @This();
44const assert = std.debug.assert;
5const BuiltinFn = @import("../BuiltinFn.zig");
5const BuiltinFn = std.zig.BuiltinFn;
66
77ast: *const Ast,
88transformations: *std.ArrayList(Transformation),