| author | |
| committer | |
| log | e70c34cdb7ea7d9b7b6feddb2d8e6194ed1188a4 |
| tree | ad94bd45b4ca65ec72820bed6d5bd7c35f60690f |
| parent | 5a8c445779b3b87ba38fbcac0efcc7ebb3787161 |
* AstGen emits async_call instruction for variable declarations of
async calls.
* Sema analyzes async_call instruction.
* Liveness handles call_async AIR instruction.
* Fix Type.eql for async frame types.6 files changed, 187 insertions(+), 70 deletions(-)
src/Air.zig+1| ... | ... | @@ -1075,6 +1075,7 @@ pub const Call = struct { |
| 1075 | 1075 | |
| 1076 | 1076 | /// Trailing is a list of `Inst.Ref` for every `args_len`. |
| 1077 | 1077 | pub const AsyncCall = struct { |
| 1078 | frame_ptr: Inst.Ref, | |
| 1078 | 1079 | callee: Inst.Ref, |
| 1079 | 1080 | args_len: u32, |
| 1080 | 1081 | }; |
src/AstGen.zig+99-22| ... | ... | @@ -2541,6 +2541,8 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As |
| 2541 | 2541 | .alloc_inferred_mut, |
| 2542 | 2542 | .alloc_inferred_comptime, |
| 2543 | 2543 | .alloc_inferred_comptime_mut, |
| 2544 | .async_call, | |
| 2545 | .async_field_call, | |
| 2544 | 2546 | .make_ptr_const, |
| 2545 | 2547 | .array_cat, |
| 2546 | 2548 | .array_mul, |
| ... | ... | @@ -2788,7 +2790,6 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As |
| 2788 | 2790 | .validate_deref, |
| 2789 | 2791 | .save_err_ret_index, |
| 2790 | 2792 | .restore_err_ret_index, |
| 2791 | .async_call, | |
| 2792 | 2793 | => break :b true, |
| 2793 | 2794 | |
| 2794 | 2795 | .@"defer" => unreachable, |
| ... | ... | @@ -3301,11 +3302,17 @@ fn varDecl( |
| 3301 | 3302 | } else a: { |
| 3302 | 3303 | const alloc = alloc: { |
| 3303 | 3304 | if (align_inst == .none) { |
| 3304 | const tag: Zir.Inst.Tag = if (is_comptime) | |
| 3305 | .alloc_inferred_comptime_mut | |
| 3306 | else | |
| 3307 | .alloc_inferred_mut; | |
| 3308 | break :alloc try gz.addNode(tag, node); | |
| 3305 | var params: [1]Ast.Node.Index = undefined; | |
| 3306 | if (is_comptime) { | |
| 3307 | break :alloc try gz.addNode(.alloc_inferred_comptime_mut, node); | |
| 3308 | } else { | |
| 3309 | if (nodeGetCall(tree, var_decl.ast.init_node, &params)) |call| { | |
| 3310 | if (call.async_token != null) { | |
| 3311 | return asyncCallExpr(gz, scope, node, call, ident_name, block_arena, name_token); | |
| 3312 | } | |
| 3313 | } | |
| 3314 | break :alloc try gz.addNode(.alloc_inferred_mut, node); | |
| 3315 | } | |
| 3309 | 3316 | } else { |
| 3310 | 3317 | break :alloc try gz.addAllocExtended(.{ |
| 3311 | 3318 | .node = node, |
| ... | ... | @@ -3346,6 +3353,34 @@ fn varDecl( |
| 3346 | 3353 | } |
| 3347 | 3354 | } |
| 3348 | 3355 | |
| 3356 | fn asyncCallExpr( | |
| 3357 | gz: *GenZir, | |
| 3358 | scope: *Scope, | |
| 3359 | node: Ast.Node.Index, | |
| 3360 | call: Ast.full.Call, | |
| 3361 | ident_name: u32, | |
| 3362 | block_arena: Allocator, | |
| 3363 | name_token: Ast.TokenIndex, | |
| 3364 | ) InnerError!*Scope { | |
| 3365 | gz.rl_ty_inst = .none; | |
| 3366 | ||
| 3367 | const call_inst = try callExprInner(gz, scope, node, call, .async_kw, false, true); | |
| 3368 | ||
| 3369 | try gz.addDbgVar(.dbg_var_ptr, ident_name, call_inst); | |
| 3370 | ||
| 3371 | const sub_scope = try block_arena.create(Scope.LocalPtr); | |
| 3372 | sub_scope.* = .{ | |
| 3373 | .parent = scope, | |
| 3374 | .gen_zir = gz, | |
| 3375 | .name = ident_name, | |
| 3376 | .ptr = call_inst, | |
| 3377 | .token_src = name_token, | |
| 3378 | .maybe_comptime = false, | |
| 3379 | .id_cat = .@"local variable", | |
| 3380 | }; | |
| 3381 | return &sub_scope.base; | |
| 3382 | } | |
| 3383 | ||
| 3349 | 3384 | fn emitDbgNode(gz: *GenZir, node: Ast.Node.Index) !void { |
| 3350 | 3385 | // The instruction emitted here is for debugging runtime code. |
| 3351 | 3386 | // If the current block will be evaluated only during semantic analysis |
| ... | ... | @@ -9076,9 +9111,6 @@ fn callExpr( |
| 9076 | 9111 | node: Ast.Node.Index, |
| 9077 | 9112 | call: Ast.full.Call, |
| 9078 | 9113 | ) InnerError!Zir.Inst.Ref { |
| 9079 | const astgen = gz.astgen; | |
| 9080 | ||
| 9081 | const callee = try calleeExpr(gz, scope, call.ast.fn_expr); | |
| 9082 | 9114 | const modifier: std.builtin.CallModifier = blk: { |
| 9083 | 9115 | if (gz.is_comptime) { |
| 9084 | 9116 | break :blk .compile_time; |
| ... | ... | @@ -9092,6 +9124,29 @@ fn callExpr( |
| 9092 | 9124 | break :blk .auto; |
| 9093 | 9125 | }; |
| 9094 | 9126 | |
| 9127 | // If our result location is a try/catch/error-union-if/return, a function argument, | |
| 9128 | // or an initializer for a `const` variable, the error trace propagates. | |
| 9129 | // Otherwise, it should always be popped (handled in Sema). | |
| 9130 | const propagate_error_trace = switch (ri.ctx) { | |
| 9131 | .error_handling_expr, .@"return", .fn_arg, .const_init => true, | |
| 9132 | else => false, | |
| 9133 | }; | |
| 9134 | const call_inst = try callExprInner(gz, scope, node, call, modifier, propagate_error_trace, false); | |
| 9135 | return rvalue(gz, ri, call_inst, node); // TODO function call with result location | |
| 9136 | } | |
| 9137 | ||
| 9138 | fn callExprInner( | |
| 9139 | gz: *GenZir, | |
| 9140 | scope: *Scope, | |
| 9141 | node: Ast.Node.Index, | |
| 9142 | call: Ast.full.Call, | |
| 9143 | modifier: std.builtin.CallModifier, | |
| 9144 | propagate_error_trace: bool, | |
| 9145 | is_async: bool, | |
| 9146 | ) InnerError!Zir.Inst.Ref { | |
| 9147 | const astgen = gz.astgen; | |
| 9148 | const callee = try calleeExpr(gz, scope, call.ast.fn_expr); | |
| 9149 | ||
| 9095 | 9150 | { |
| 9096 | 9151 | astgen.advanceSourceCursor(astgen.tree.tokens.items(.start)[call.ast.lparen]); |
| 9097 | 9152 | const line = astgen.source_line - gz.decl_line; |
| ... | ... | @@ -9139,17 +9194,12 @@ fn callExpr( |
| 9139 | 9194 | scratch_index += 1; |
| 9140 | 9195 | } |
| 9141 | 9196 | |
| 9142 | // If our result location is a try/catch/error-union-if/return, a function argument, | |
| 9143 | // or an initializer for a `const` variable, the error trace propagates. | |
| 9144 | // Otherwise, it should always be popped (handled in Sema). | |
| 9145 | const propagate_error_trace = switch (ri.ctx) { | |
| 9146 | .error_handling_expr, .@"return", .fn_arg, .const_init => true, | |
| 9147 | else => false, | |
| 9148 | }; | |
| 9149 | ||
| 9150 | 9197 | switch (callee) { |
| 9151 | 9198 | .direct => |callee_obj| { |
| 9152 | const payload_index = try addExtra(astgen, Zir.Inst.Call{ | |
| 9199 | const payload_index = if (is_async) try addExtra(astgen, Zir.Inst.AsyncCall{ | |
| 9200 | .callee = callee_obj, | |
| 9201 | .args_len = @intCast(call.ast.params.len), | |
| 9202 | }) else try addExtra(astgen, Zir.Inst.Call{ | |
| 9153 | 9203 | .callee = callee_obj, |
| 9154 | 9204 | .flags = .{ |
| 9155 | 9205 | .pop_error_return_trace = !propagate_error_trace, |
| ... | ... | @@ -9161,7 +9211,7 @@ fn callExpr( |
| 9161 | 9211 | try astgen.extra.appendSlice(astgen.gpa, astgen.scratch.items[scratch_top..]); |
| 9162 | 9212 | } |
| 9163 | 9213 | gz.astgen.instructions.set(call_index, .{ |
| 9164 | .tag = .call, | |
| 9214 | .tag = if (is_async) .async_call else .call, | |
| 9165 | 9215 | .data = .{ .pl_node = .{ |
| 9166 | 9216 | .src_node = gz.nodeIndexToRelative(node), |
| 9167 | 9217 | .payload_index = payload_index, |
| ... | ... | @@ -9169,7 +9219,11 @@ fn callExpr( |
| 9169 | 9219 | }); |
| 9170 | 9220 | }, |
| 9171 | 9221 | .field => |callee_field| { |
| 9172 | const payload_index = try addExtra(astgen, Zir.Inst.FieldCall{ | |
| 9222 | const payload_index = if (is_async) try addExtra(astgen, Zir.Inst.AsyncFieldCall{ | |
| 9223 | .obj_ptr = callee_field.obj_ptr, | |
| 9224 | .field_name_start = callee_field.field_name_start, | |
| 9225 | .args_len = @intCast(call.ast.params.len), | |
| 9226 | }) else try addExtra(astgen, Zir.Inst.FieldCall{ | |
| 9173 | 9227 | .obj_ptr = callee_field.obj_ptr, |
| 9174 | 9228 | .field_name_start = callee_field.field_name_start, |
| 9175 | 9229 | .flags = .{ |
| ... | ... | @@ -9182,7 +9236,7 @@ fn callExpr( |
| 9182 | 9236 | try astgen.extra.appendSlice(astgen.gpa, astgen.scratch.items[scratch_top..]); |
| 9183 | 9237 | } |
| 9184 | 9238 | gz.astgen.instructions.set(call_index, .{ |
| 9185 | .tag = .field_call, | |
| 9239 | .tag = if (is_async) .async_field_call else .field_call, | |
| 9186 | 9240 | .data = .{ .pl_node = .{ |
| 9187 | 9241 | .src_node = gz.nodeIndexToRelative(node), |
| 9188 | 9242 | .payload_index = payload_index, |
| ... | ... | @@ -9190,7 +9244,7 @@ fn callExpr( |
| 9190 | 9244 | }); |
| 9191 | 9245 | }, |
| 9192 | 9246 | } |
| 9193 | return rvalue(gz, ri, call_inst, node); // TODO function call with result location | |
| 9247 | return call_inst; | |
| 9194 | 9248 | } |
| 9195 | 9249 | |
| 9196 | 9250 | const Callee = union(enum) { |
| ... | ... | @@ -10321,6 +10375,29 @@ fn nodeUsesAnonNameStrategy(tree: *const Ast, node: Ast.Node.Index) bool { |
| 10321 | 10375 | } |
| 10322 | 10376 | } |
| 10323 | 10377 | |
| 10378 | fn nodeGetCall( | |
| 10379 | tree: *const Ast, | |
| 10380 | start_node: Ast.Node.Index, | |
| 10381 | params: *[1]Ast.Node.Index, | |
| 10382 | ) ?Ast.full.Call { | |
| 10383 | const node_tags = tree.nodes.items(.tag); | |
| 10384 | const node_datas = tree.nodes.items(.data); | |
| 10385 | ||
| 10386 | var node = start_node; | |
| 10387 | while (true) { | |
| 10388 | switch (node_tags[node]) { | |
| 10389 | .call_one, .call_one_comma, .async_call_one, .async_call_one_comma => { | |
| 10390 | return tree.callOne(params, node); | |
| 10391 | }, | |
| 10392 | .call, .call_comma, .async_call, .async_call_comma => { | |
| 10393 | return tree.callFull(node); | |
| 10394 | }, | |
| 10395 | .grouped_expression => node = node_datas[node].lhs, | |
| 10396 | else => return null, | |
| 10397 | } | |
| 10398 | } | |
| 10399 | } | |
| 10400 | ||
| 10324 | 10401 | /// Applies `rl` semantics to `result`. Expressions which do not do their own handling of |
| 10325 | 10402 | /// result locations must call this function on their result. |
| 10326 | 10403 | /// As an example, if the `ResultLoc` is `ptr`, it will write the result to the pointer. |
src/Sema.zig+28-14| ... | ... | @@ -409,11 +409,7 @@ pub const Block = struct { |
| 409 | 409 | return mod.namespacePtr(block.namespace).file_scope; |
| 410 | 410 | } |
| 411 | 411 | |
| 412 | fn addTy( | |
| 413 | block: *Block, | |
| 414 | tag: Air.Inst.Tag, | |
| 415 | ty: Type, | |
| 416 | ) error{OutOfMemory}!Air.Inst.Ref { | |
| 412 | fn addTy(block: *Block, tag: Air.Inst.Tag, ty: Type) error{OutOfMemory}!Air.Inst.Ref { | |
| 417 | 413 | return block.addInst(.{ |
| 418 | 414 | .tag = tag, |
| 419 | 415 | .data = .{ .ty = ty }, |
| ... | ... | @@ -943,7 +939,8 @@ fn analyzeBodyInner( |
| 943 | 939 | .c_import => try sema.zirCImport(block, inst), |
| 944 | 940 | .call => try sema.zirCall(block, inst, Zir.Inst.Call), |
| 945 | 941 | .field_call => try sema.zirCall(block, inst, Zir.Inst.FieldCall), |
| 946 | .async_call => try sema.zirAsyncCall(block, inst), | |
| 942 | .async_call => try sema.zirAsyncCall(block, inst, Zir.Inst.AsyncCall), | |
| 943 | .async_field_call => try sema.zirAsyncCall(block, inst, Zir.Inst.AsyncFieldCall), | |
| 947 | 944 | .closure_get => try sema.zirClosureGet(block, inst), |
| 948 | 945 | .cmp_lt => try sema.zirCmp(block, inst, .lt), |
| 949 | 946 | .cmp_lte => try sema.zirCmp(block, inst, .lte), |
| ... | ... | @@ -6477,18 +6474,33 @@ fn zirCall( |
| 6477 | 6474 | ); |
| 6478 | 6475 | } |
| 6479 | 6476 | |
| 6480 | fn zirAsyncCall(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | |
| 6477 | fn zirAsyncCall( | |
| 6478 | sema: *Sema, | |
| 6479 | block: *Block, | |
| 6480 | inst: Zir.Inst.Index, | |
| 6481 | comptime ExtraType: type, | |
| 6482 | ) CompileError!Air.Inst.Ref { | |
| 6483 | const mod = sema.mod; | |
| 6481 | 6484 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; |
| 6482 | const func_src: LazySrcLoc = .{ .node_offset_async_call_func = inst_data.src_node }; | |
| 6485 | const callee_src: LazySrcLoc = .{ .node_offset_async_call_func = inst_data.src_node }; | |
| 6483 | 6486 | const call_src: LazySrcLoc = .{ .node_offset_var_decl_init = inst_data.src_node }; |
| 6484 | const extra = sema.code.extraData(Zir.Inst.AsyncCall, inst_data.payload_index); | |
| 6487 | const extra = sema.code.extraData(ExtraType, inst_data.payload_index); | |
| 6485 | 6488 | const args_len = extra.data.args_len; |
| 6486 | const callee: ResolvedFieldCallee = .{ .direct = try sema.resolveInst(extra.data.callee) }; | |
| 6489 | const callee: ResolvedFieldCallee = switch (ExtraType) { | |
| 6490 | Zir.Inst.AsyncCall => .{ .direct = try sema.resolveInst(extra.data.callee) }, | |
| 6491 | Zir.Inst.AsyncFieldCall => blk: { | |
| 6492 | const object_ptr = try sema.resolveInst(extra.data.obj_ptr); | |
| 6493 | const field_name = try mod.intern_pool.getOrPutString(sema.gpa, sema.code.nullTerminatedString(extra.data.field_name_start)); | |
| 6494 | const field_name_src: LazySrcLoc = .{ .node_offset_field_name = inst_data.src_node }; | |
| 6495 | break :blk try sema.fieldCallBind(block, callee_src, object_ptr, field_name, field_name_src); | |
| 6496 | }, | |
| 6497 | else => @compileError("unreachable"), | |
| 6498 | }; | |
| 6487 | 6499 | return callCommon( |
| 6488 | 6500 | sema, |
| 6489 | 6501 | block, |
| 6490 | 6502 | inst, |
| 6491 | func_src, | |
| 6503 | callee_src, | |
| 6492 | 6504 | call_src, |
| 6493 | 6505 | callee, |
| 6494 | 6506 | args_len, |
| ... | ... | @@ -7286,8 +7298,9 @@ fn addAsyncCallInst( |
| 7286 | 7298 | args: []const Air.Inst.Ref, |
| 7287 | 7299 | ) Allocator.Error!Air.Inst.Ref { |
| 7288 | 7300 | const mod = sema.mod; |
| 7289 | const frame_ty = try mod.asyncFrameType(callee_fn); | |
| 7290 | const frame_ty_ref = try sema.addType(frame_ty); | |
| 7301 | const ptr_frame_ty = try mod.singleMutPtrType(try mod.asyncFrameType(callee_fn)); | |
| 7302 | const frame_ptr = try block.addTy(.alloc, ptr_frame_ty); | |
| 7303 | const ptr_frame_ty_ref = try sema.addType(ptr_frame_ty); | |
| 7291 | 7304 | try sema.air_extra.ensureUnusedCapacity( |
| 7292 | 7305 | sema.gpa, |
| 7293 | 7306 | @typeInfo(Air.AsyncCall).Struct.fields.len + args.len, |
| ... | ... | @@ -7295,8 +7308,9 @@ fn addAsyncCallInst( |
| 7295 | 7308 | const call_inst = try block.addInst(.{ |
| 7296 | 7309 | .tag = .call_async, |
| 7297 | 7310 | .data = .{ .ty_pl = .{ |
| 7298 | .ty = frame_ty_ref, | |
| 7311 | .ty = ptr_frame_ty_ref, | |
| 7299 | 7312 | .payload = sema.addExtraAssumeCapacity(Air.AsyncCall{ |
| 7313 | .frame_ptr = frame_ptr, | |
| 7300 | 7314 | .callee = callee, |
| 7301 | 7315 | .args_len = @intCast(args.len), |
| 7302 | 7316 | }), |
src/Zir.zig+17-1| ... | ... | @@ -318,6 +318,11 @@ pub const Inst = struct { |
| 318 | 318 | /// Uses the `pl_node` union field with payload `AsyncCall` |
| 319 | 319 | /// AST node is the entire variable declaration, with the init node being a call. |
| 320 | 320 | async_call, |
| 321 | /// Combination of `field_call` and `async_call`. | |
| 322 | /// Corresponds with the syntax `var foo = async bar.baz();`. | |
| 323 | /// Uses the `pl_node` union field with payload `AsyncFieldCall` | |
| 324 | /// AST node is the entire variable declaration, with the init node being a field call. | |
| 325 | async_field_call, | |
| 321 | 326 | /// `<` |
| 322 | 327 | /// Uses the `pl_node` union field. Payload is `Bin`. |
| 323 | 328 | cmp_lt, |
| ... | ... | @@ -1032,6 +1037,7 @@ pub const Inst = struct { |
| 1032 | 1037 | .call, |
| 1033 | 1038 | .field_call, |
| 1034 | 1039 | .async_call, |
| 1040 | .async_field_call, | |
| 1035 | 1041 | .cmp_lt, |
| 1036 | 1042 | .cmp_lte, |
| 1037 | 1043 | .cmp_eq, |
| ... | ... | @@ -1310,6 +1316,8 @@ pub const Inst = struct { |
| 1310 | 1316 | .alloc_inferred_mut, |
| 1311 | 1317 | .alloc_inferred_comptime, |
| 1312 | 1318 | .alloc_inferred_comptime_mut, |
| 1319 | .async_call, | |
| 1320 | .async_field_call, | |
| 1313 | 1321 | .make_ptr_const, |
| 1314 | 1322 | .array_cat, |
| 1315 | 1323 | .array_mul, |
| ... | ... | @@ -1336,7 +1344,6 @@ pub const Inst = struct { |
| 1336 | 1344 | .bool_not, |
| 1337 | 1345 | .call, |
| 1338 | 1346 | .field_call, |
| 1339 | .async_call, | |
| 1340 | 1347 | .cmp_lt, |
| 1341 | 1348 | .cmp_lte, |
| 1342 | 1349 | .cmp_eq, |
| ... | ... | @@ -1572,6 +1579,7 @@ pub const Inst = struct { |
| 1572 | 1579 | .call = .pl_node, |
| 1573 | 1580 | .field_call = .pl_node, |
| 1574 | 1581 | .async_call = .pl_node, |
| 1582 | .async_field_call = .pl_node, | |
| 1575 | 1583 | .cmp_lt = .pl_node, |
| 1576 | 1584 | .cmp_lte = .pl_node, |
| 1577 | 1585 | .cmp_eq = .pl_node, |
| ... | ... | @@ -2549,6 +2557,14 @@ pub const Inst = struct { |
| 2549 | 2557 | args_len: u32, |
| 2550 | 2558 | }; |
| 2551 | 2559 | |
| 2560 | /// Same trailing data as `AsyncCall`, `FieldCall`, and `Call`. | |
| 2561 | pub const AsyncFieldCall = struct { | |
| 2562 | args_len: u32, | |
| 2563 | obj_ptr: Ref, | |
| 2564 | /// Offset into `string_bytes`. | |
| 2565 | field_name_start: u32, | |
| 2566 | }; | |
| 2567 | ||
| 2552 | 2568 | pub const TypeOfPeer = struct { |
| 2553 | 2569 | src_node: i32, |
| 2554 | 2570 | body_len: u32, |
src/print_air.zig+14-4| ... | ... | @@ -701,7 +701,7 @@ const Writer = struct { |
| 701 | 701 | const pl_op = w.air.instructions.items(.data)[inst].pl_op; |
| 702 | 702 | const extra = w.air.extraData(Air.Call, pl_op.payload); |
| 703 | 703 | const args: []const Air.Inst.Ref = @ptrCast(w.air.extra[extra.end..][0..extra.data.args_len]); |
| 704 | return finishWriteCall(w, s, inst, pl_op.operand, args); | |
| 704 | return finishWriteCall(w, s, inst, .none, pl_op.operand, args); | |
| 705 | 705 | } |
| 706 | 706 | |
| 707 | 707 | fn writeCallAsync(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { |
| ... | ... | @@ -709,21 +709,31 @@ const Writer = struct { |
| 709 | 709 | const extra = w.air.extraData(Air.AsyncCall, ty_pl.payload); |
| 710 | 710 | const callee = extra.data.callee; |
| 711 | 711 | const args: []const Air.Inst.Ref = @ptrCast(w.air.extra[extra.end..][0..extra.data.args_len]); |
| 712 | return finishWriteCall(w, s, inst, callee, args); | |
| 712 | const frame_ptr = extra.data.frame_ptr; | |
| 713 | return finishWriteCall(w, s, inst, frame_ptr, callee, args); | |
| 713 | 714 | } |
| 714 | 715 | |
| 715 | 716 | fn finishWriteCall( |
| 716 | 717 | w: *Writer, |
| 717 | 718 | s: anytype, |
| 718 | 719 | inst: Air.Inst.Index, |
| 720 | frame_ptr: Air.Inst.Ref, | |
| 719 | 721 | callee: Air.Inst.Ref, |
| 720 | 722 | args: []const Air.Inst.Ref, |
| 721 | 723 | ) @TypeOf(s).Error!void { |
| 722 | try w.writeOperand(s, inst, 0, callee); | |
| 724 | var op_index: usize = 0; | |
| 725 | if (frame_ptr != .none) { | |
| 726 | try w.writeOperand(s, inst, op_index, frame_ptr); | |
| 727 | op_index += 1; | |
| 728 | try s.writeAll(", "); | |
| 729 | } | |
| 730 | try w.writeOperand(s, inst, op_index, callee); | |
| 731 | op_index += 1; | |
| 723 | 732 | try s.writeAll(", ["); |
| 724 | 733 | for (args, 0..) |arg, i| { |
| 725 | 734 | if (i != 0) try s.writeAll(", "); |
| 726 | try w.writeOperand(s, inst, 1 + i, arg); | |
| 735 | try w.writeOperand(s, inst, op_index, arg); | |
| 736 | op_index += 1; | |
| 727 | 737 | } |
| 728 | 738 | try s.writeAll("]"); |
| 729 | 739 | } |
src/print_zir.zig+28-29| ... | ... | @@ -360,9 +360,10 @@ const Writer = struct { |
| 360 | 360 | .@"export" => try self.writePlNodeExport(stream, inst), |
| 361 | 361 | .export_value => try self.writePlNodeExportValue(stream, inst), |
| 362 | 362 | |
| 363 | .call => try self.writeCall(stream, inst, .direct), | |
| 364 | .field_call => try self.writeCall(stream, inst, .field), | |
| 365 | .async_call => try self.writeAsyncCall(stream, inst), | |
| 363 | .call => try self.writeCall(stream, inst, Zir.Inst.Call), | |
| 364 | .field_call => try self.writeCall(stream, inst, Zir.Inst.FieldCall), | |
| 365 | .async_call => try self.writeCall(stream, inst, Zir.Inst.AsyncCall), | |
| 366 | .async_field_call => try self.writeCall(stream, inst, Zir.Inst.AsyncFieldCall), | |
| 366 | 367 | |
| 367 | 368 | .block, |
| 368 | 369 | .block_comptime, |
| ... | ... | @@ -1188,50 +1189,48 @@ const Writer = struct { |
| 1188 | 1189 | try self.writeSrc(stream, src); |
| 1189 | 1190 | } |
| 1190 | 1191 | |
| 1191 | const CallKind = enum { direct, field }; | |
| 1192 | ||
| 1193 | 1192 | fn writeCall( |
| 1194 | 1193 | self: *Writer, |
| 1195 | 1194 | stream: anytype, |
| 1196 | 1195 | inst: Zir.Inst.Index, |
| 1197 | comptime kind: CallKind, | |
| 1196 | comptime ExtraType: type, | |
| 1198 | 1197 | ) !void { |
| 1199 | 1198 | const inst_data = self.code.instructions.items(.data)[inst].pl_node; |
| 1200 | const ExtraType = switch (kind) { | |
| 1201 | .direct => Zir.Inst.Call, | |
| 1202 | .field => Zir.Inst.FieldCall, | |
| 1203 | }; | |
| 1204 | 1199 | const extra = self.code.extraData(ExtraType, inst_data.payload_index); |
| 1205 | const args_len = extra.data.flags.args_len; | |
| 1200 | const args_len = switch (ExtraType) { | |
| 1201 | Zir.Inst.Call, Zir.Inst.FieldCall => extra.data.flags.args_len, | |
| 1202 | Zir.Inst.AsyncCall, Zir.Inst.AsyncFieldCall => extra.data.args_len, | |
| 1203 | else => @compileError("unreachable"), | |
| 1204 | }; | |
| 1206 | 1205 | const body = self.code.extra[extra.end..]; |
| 1207 | const modifier: std.builtin.CallModifier = @enumFromInt(extra.data.flags.packed_modifier); | |
| 1208 | ||
| 1209 | if (extra.data.flags.ensure_result_used) { | |
| 1210 | try stream.writeAll("nodiscard "); | |
| 1206 | switch (ExtraType) { | |
| 1207 | Zir.Inst.Call, Zir.Inst.FieldCall => if (extra.data.flags.ensure_result_used) { | |
| 1208 | try stream.writeAll("nodiscard "); | |
| 1209 | }, | |
| 1210 | Zir.Inst.AsyncCall, Zir.Inst.AsyncFieldCall => {}, | |
| 1211 | else => @compileError("unreachable"), | |
| 1211 | 1212 | } |
| 1213 | ||
| 1214 | const modifier: std.builtin.CallModifier = switch (ExtraType) { | |
| 1215 | Zir.Inst.Call, Zir.Inst.FieldCall => @enumFromInt(extra.data.flags.packed_modifier), | |
| 1216 | Zir.Inst.AsyncCall, Zir.Inst.AsyncFieldCall => std.builtin.CallModifier.async_kw, | |
| 1217 | else => @compileError("unreachable"), | |
| 1218 | }; | |
| 1219 | ||
| 1212 | 1220 | try stream.print(".{s}, ", .{@tagName(modifier)}); |
| 1213 | switch (kind) { | |
| 1214 | .direct => try self.writeInstRef(stream, extra.data.callee), | |
| 1215 | .field => { | |
| 1221 | ||
| 1222 | switch (ExtraType) { | |
| 1223 | Zir.Inst.Call, Zir.Inst.AsyncCall => try self.writeInstRef(stream, extra.data.callee), | |
| 1224 | Zir.Inst.FieldCall, Zir.Inst.AsyncFieldCall => { | |
| 1216 | 1225 | const field_name = self.code.nullTerminatedString(extra.data.field_name_start); |
| 1217 | 1226 | try self.writeInstRef(stream, extra.data.obj_ptr); |
| 1218 | 1227 | try stream.print(", \"{}\"", .{std.zig.fmtEscapes(field_name)}); |
| 1219 | 1228 | }, |
| 1229 | else => @compileError("unreachable"), | |
| 1220 | 1230 | } |
| 1221 | 1231 | return finishWriteCall(self, stream, body, args_len, extra.end, inst_data.src()); |
| 1222 | 1232 | } |
| 1223 | 1233 | |
| 1224 | fn writeAsyncCall(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void { | |
| 1225 | const inst_data = self.code.instructions.items(.data)[inst].pl_node; | |
| 1226 | const extra = self.code.extraData(Zir.Inst.AsyncCall, inst_data.payload_index); | |
| 1227 | const args_len = extra.data.args_len; | |
| 1228 | const body = self.code.extra[extra.end..]; | |
| 1229 | const callee = extra.data.callee; | |
| 1230 | try stream.print(".{s}, ", .{@tagName(std.builtin.CallModifier.async_kw)}); | |
| 1231 | try self.writeInstRef(stream, callee); | |
| 1232 | return finishWriteCall(self, stream, body, args_len, extra.end, inst_data.src()); | |
| 1233 | } | |
| 1234 | ||
| 1235 | 1234 | fn finishWriteCall( |
| 1236 | 1235 | self: *Writer, |
| 1237 | 1236 | stream: anytype, |