| 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,6 +1075,7 @@ pub const Call = struct { |
| 1075 | 1075 | ||
| 1076 | /// Trailing is a list of `Inst.Ref` for every `args_len`. | 1076 | /// Trailing is a list of `Inst.Ref` for every `args_len`. |
| 1077 | pub const AsyncCall = struct { | 1077 | pub const AsyncCall = struct { |
| 1078 | frame_ptr: Inst.Ref, | ||
| 1078 | callee: Inst.Ref, | 1079 | callee: Inst.Ref, |
| 1079 | args_len: u32, | 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,6 +2541,8 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As |
| 2541 | .alloc_inferred_mut, | 2541 | .alloc_inferred_mut, |
| 2542 | .alloc_inferred_comptime, | 2542 | .alloc_inferred_comptime, |
| 2543 | .alloc_inferred_comptime_mut, | 2543 | .alloc_inferred_comptime_mut, |
| 2544 | .async_call, | ||
| 2545 | .async_field_call, | ||
| 2544 | .make_ptr_const, | 2546 | .make_ptr_const, |
| 2545 | .array_cat, | 2547 | .array_cat, |
| 2546 | .array_mul, | 2548 | .array_mul, |
| ... | @@ -2788,7 +2790,6 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As | ... | @@ -2788,7 +2790,6 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As |
| 2788 | .validate_deref, | 2790 | .validate_deref, |
| 2789 | .save_err_ret_index, | 2791 | .save_err_ret_index, |
| 2790 | .restore_err_ret_index, | 2792 | .restore_err_ret_index, |
| 2791 | .async_call, | ||
| 2792 | => break :b true, | 2793 | => break :b true, |
| 2793 | 2794 | ||
| 2794 | .@"defer" => unreachable, | 2795 | .@"defer" => unreachable, |
| ... | @@ -3301,11 +3302,17 @@ fn varDecl( | ... | @@ -3301,11 +3302,17 @@ fn varDecl( |
| 3301 | } else a: { | 3302 | } else a: { |
| 3302 | const alloc = alloc: { | 3303 | const alloc = alloc: { |
| 3303 | if (align_inst == .none) { | 3304 | if (align_inst == .none) { |
| 3304 | const tag: Zir.Inst.Tag = if (is_comptime) | 3305 | var params: [1]Ast.Node.Index = undefined; |
| 3305 | .alloc_inferred_comptime_mut | 3306 | if (is_comptime) { |
| 3306 | else | 3307 | break :alloc try gz.addNode(.alloc_inferred_comptime_mut, node); |
| 3307 | .alloc_inferred_mut; | 3308 | } else { |
| 3308 | break :alloc try gz.addNode(tag, node); | 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 | } else { | 3316 | } else { |
| 3310 | break :alloc try gz.addAllocExtended(.{ | 3317 | break :alloc try gz.addAllocExtended(.{ |
| 3311 | .node = node, | 3318 | .node = node, |
| ... | @@ -3346,6 +3353,34 @@ fn varDecl( | ... | @@ -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 | fn emitDbgNode(gz: *GenZir, node: Ast.Node.Index) !void { | 3384 | fn emitDbgNode(gz: *GenZir, node: Ast.Node.Index) !void { |
| 3350 | // The instruction emitted here is for debugging runtime code. | 3385 | // The instruction emitted here is for debugging runtime code. |
| 3351 | // If the current block will be evaluated only during semantic analysis | 3386 | // If the current block will be evaluated only during semantic analysis |
| ... | @@ -9076,9 +9111,6 @@ fn callExpr( | ... | @@ -9076,9 +9111,6 @@ fn callExpr( |
| 9076 | node: Ast.Node.Index, | 9111 | node: Ast.Node.Index, |
| 9077 | call: Ast.full.Call, | 9112 | call: Ast.full.Call, |
| 9078 | ) InnerError!Zir.Inst.Ref { | 9113 | ) InnerError!Zir.Inst.Ref { |
| 9079 | const astgen = gz.astgen; | ||
| 9080 | |||
| 9081 | const callee = try calleeExpr(gz, scope, call.ast.fn_expr); | ||
| 9082 | const modifier: std.builtin.CallModifier = blk: { | 9114 | const modifier: std.builtin.CallModifier = blk: { |
| 9083 | if (gz.is_comptime) { | 9115 | if (gz.is_comptime) { |
| 9084 | break :blk .compile_time; | 9116 | break :blk .compile_time; |
| ... | @@ -9092,6 +9124,29 @@ fn callExpr( | ... | @@ -9092,6 +9124,29 @@ fn callExpr( |
| 9092 | break :blk .auto; | 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 | astgen.advanceSourceCursor(astgen.tree.tokens.items(.start)[call.ast.lparen]); | 9151 | astgen.advanceSourceCursor(astgen.tree.tokens.items(.start)[call.ast.lparen]); |
| 9097 | const line = astgen.source_line - gz.decl_line; | 9152 | const line = astgen.source_line - gz.decl_line; |
| ... | @@ -9139,17 +9194,12 @@ fn callExpr( | ... | @@ -9139,17 +9194,12 @@ fn callExpr( |
| 9139 | scratch_index += 1; | 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 | switch (callee) { | 9197 | switch (callee) { |
| 9151 | .direct => |callee_obj| { | 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 | .callee = callee_obj, | 9203 | .callee = callee_obj, |
| 9154 | .flags = .{ | 9204 | .flags = .{ |
| 9155 | .pop_error_return_trace = !propagate_error_trace, | 9205 | .pop_error_return_trace = !propagate_error_trace, |
| ... | @@ -9161,7 +9211,7 @@ fn callExpr( | ... | @@ -9161,7 +9211,7 @@ fn callExpr( |
| 9161 | try astgen.extra.appendSlice(astgen.gpa, astgen.scratch.items[scratch_top..]); | 9211 | try astgen.extra.appendSlice(astgen.gpa, astgen.scratch.items[scratch_top..]); |
| 9162 | } | 9212 | } |
| 9163 | gz.astgen.instructions.set(call_index, .{ | 9213 | gz.astgen.instructions.set(call_index, .{ |
| 9164 | .tag = .call, | 9214 | .tag = if (is_async) .async_call else .call, |
| 9165 | .data = .{ .pl_node = .{ | 9215 | .data = .{ .pl_node = .{ |
| 9166 | .src_node = gz.nodeIndexToRelative(node), | 9216 | .src_node = gz.nodeIndexToRelative(node), |
| 9167 | .payload_index = payload_index, | 9217 | .payload_index = payload_index, |
| ... | @@ -9169,7 +9219,11 @@ fn callExpr( | ... | @@ -9169,7 +9219,11 @@ fn callExpr( |
| 9169 | }); | 9219 | }); |
| 9170 | }, | 9220 | }, |
| 9171 | .field => |callee_field| { | 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 | .obj_ptr = callee_field.obj_ptr, | 9227 | .obj_ptr = callee_field.obj_ptr, |
| 9174 | .field_name_start = callee_field.field_name_start, | 9228 | .field_name_start = callee_field.field_name_start, |
| 9175 | .flags = .{ | 9229 | .flags = .{ |
| ... | @@ -9182,7 +9236,7 @@ fn callExpr( | ... | @@ -9182,7 +9236,7 @@ fn callExpr( |
| 9182 | try astgen.extra.appendSlice(astgen.gpa, astgen.scratch.items[scratch_top..]); | 9236 | try astgen.extra.appendSlice(astgen.gpa, astgen.scratch.items[scratch_top..]); |
| 9183 | } | 9237 | } |
| 9184 | gz.astgen.instructions.set(call_index, .{ | 9238 | gz.astgen.instructions.set(call_index, .{ |
| 9185 | .tag = .field_call, | 9239 | .tag = if (is_async) .async_field_call else .field_call, |
| 9186 | .data = .{ .pl_node = .{ | 9240 | .data = .{ .pl_node = .{ |
| 9187 | .src_node = gz.nodeIndexToRelative(node), | 9241 | .src_node = gz.nodeIndexToRelative(node), |
| 9188 | .payload_index = payload_index, | 9242 | .payload_index = payload_index, |
| ... | @@ -9190,7 +9244,7 @@ fn callExpr( | ... | @@ -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 | const Callee = union(enum) { | 9250 | const Callee = union(enum) { |
| ... | @@ -10321,6 +10375,29 @@ fn nodeUsesAnonNameStrategy(tree: *const Ast, node: Ast.Node.Index) bool { | ... | @@ -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 | /// Applies `rl` semantics to `result`. Expressions which do not do their own handling of | 10401 | /// Applies `rl` semantics to `result`. Expressions which do not do their own handling of |
| 10325 | /// result locations must call this function on their result. | 10402 | /// result locations must call this function on their result. |
| 10326 | /// As an example, if the `ResultLoc` is `ptr`, it will write the result to the pointer. | 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,11 +409,7 @@ pub const Block = struct { |
| 409 | return mod.namespacePtr(block.namespace).file_scope; | 409 | return mod.namespacePtr(block.namespace).file_scope; |
| 410 | } | 410 | } |
| 411 | 411 | ||
| 412 | fn addTy( | 412 | fn addTy(block: *Block, tag: Air.Inst.Tag, ty: Type) error{OutOfMemory}!Air.Inst.Ref { |
| 413 | block: *Block, | ||
| 414 | tag: Air.Inst.Tag, | ||
| 415 | ty: Type, | ||
| 416 | ) error{OutOfMemory}!Air.Inst.Ref { | ||
| 417 | return block.addInst(.{ | 413 | return block.addInst(.{ |
| 418 | .tag = tag, | 414 | .tag = tag, |
| 419 | .data = .{ .ty = ty }, | 415 | .data = .{ .ty = ty }, |
| ... | @@ -943,7 +939,8 @@ fn analyzeBodyInner( | ... | @@ -943,7 +939,8 @@ fn analyzeBodyInner( |
| 943 | .c_import => try sema.zirCImport(block, inst), | 939 | .c_import => try sema.zirCImport(block, inst), |
| 944 | .call => try sema.zirCall(block, inst, Zir.Inst.Call), | 940 | .call => try sema.zirCall(block, inst, Zir.Inst.Call), |
| 945 | .field_call => try sema.zirCall(block, inst, Zir.Inst.FieldCall), | 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 | .closure_get => try sema.zirClosureGet(block, inst), | 944 | .closure_get => try sema.zirClosureGet(block, inst), |
| 948 | .cmp_lt => try sema.zirCmp(block, inst, .lt), | 945 | .cmp_lt => try sema.zirCmp(block, inst, .lt), |
| 949 | .cmp_lte => try sema.zirCmp(block, inst, .lte), | 946 | .cmp_lte => try sema.zirCmp(block, inst, .lte), |
| ... | @@ -6477,18 +6474,33 @@ fn zirCall( | ... | @@ -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 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; | 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 | const call_src: LazySrcLoc = .{ .node_offset_var_decl_init = inst_data.src_node }; | 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 | const args_len = extra.data.args_len; | 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 | return callCommon( | 6499 | return callCommon( |
| 6488 | sema, | 6500 | sema, |
| 6489 | block, | 6501 | block, |
| 6490 | inst, | 6502 | inst, |
| 6491 | func_src, | 6503 | callee_src, |
| 6492 | call_src, | 6504 | call_src, |
| 6493 | callee, | 6505 | callee, |
| 6494 | args_len, | 6506 | args_len, |
| ... | @@ -7286,8 +7298,9 @@ fn addAsyncCallInst( | ... | @@ -7286,8 +7298,9 @@ fn addAsyncCallInst( |
| 7286 | args: []const Air.Inst.Ref, | 7298 | args: []const Air.Inst.Ref, |
| 7287 | ) Allocator.Error!Air.Inst.Ref { | 7299 | ) Allocator.Error!Air.Inst.Ref { |
| 7288 | const mod = sema.mod; | 7300 | const mod = sema.mod; |
| 7289 | const frame_ty = try mod.asyncFrameType(callee_fn); | 7301 | const ptr_frame_ty = try mod.singleMutPtrType(try mod.asyncFrameType(callee_fn)); |
| 7290 | const frame_ty_ref = try sema.addType(frame_ty); | 7302 | const frame_ptr = try block.addTy(.alloc, ptr_frame_ty); |
| 7303 | const ptr_frame_ty_ref = try sema.addType(ptr_frame_ty); | ||
| 7291 | try sema.air_extra.ensureUnusedCapacity( | 7304 | try sema.air_extra.ensureUnusedCapacity( |
| 7292 | sema.gpa, | 7305 | sema.gpa, |
| 7293 | @typeInfo(Air.AsyncCall).Struct.fields.len + args.len, | 7306 | @typeInfo(Air.AsyncCall).Struct.fields.len + args.len, |
| ... | @@ -7295,8 +7308,9 @@ fn addAsyncCallInst( | ... | @@ -7295,8 +7308,9 @@ fn addAsyncCallInst( |
| 7295 | const call_inst = try block.addInst(.{ | 7308 | const call_inst = try block.addInst(.{ |
| 7296 | .tag = .call_async, | 7309 | .tag = .call_async, |
| 7297 | .data = .{ .ty_pl = .{ | 7310 | .data = .{ .ty_pl = .{ |
| 7298 | .ty = frame_ty_ref, | 7311 | .ty = ptr_frame_ty_ref, |
| 7299 | .payload = sema.addExtraAssumeCapacity(Air.AsyncCall{ | 7312 | .payload = sema.addExtraAssumeCapacity(Air.AsyncCall{ |
| 7313 | .frame_ptr = frame_ptr, | ||
| 7300 | .callee = callee, | 7314 | .callee = callee, |
| 7301 | .args_len = @intCast(args.len), | 7315 | .args_len = @intCast(args.len), |
| 7302 | }), | 7316 | }), |
src/Zir.zig+17-1| ... | @@ -318,6 +318,11 @@ pub const Inst = struct { | ... | @@ -318,6 +318,11 @@ pub const Inst = struct { |
| 318 | /// Uses the `pl_node` union field with payload `AsyncCall` | 318 | /// Uses the `pl_node` union field with payload `AsyncCall` |
| 319 | /// AST node is the entire variable declaration, with the init node being a call. | 319 | /// AST node is the entire variable declaration, with the init node being a call. |
| 320 | async_call, | 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 | /// Uses the `pl_node` union field. Payload is `Bin`. | 327 | /// Uses the `pl_node` union field. Payload is `Bin`. |
| 323 | cmp_lt, | 328 | cmp_lt, |
| ... | @@ -1032,6 +1037,7 @@ pub const Inst = struct { | ... | @@ -1032,6 +1037,7 @@ pub const Inst = struct { |
| 1032 | .call, | 1037 | .call, |
| 1033 | .field_call, | 1038 | .field_call, |
| 1034 | .async_call, | 1039 | .async_call, |
| 1040 | .async_field_call, | ||
| 1035 | .cmp_lt, | 1041 | .cmp_lt, |
| 1036 | .cmp_lte, | 1042 | .cmp_lte, |
| 1037 | .cmp_eq, | 1043 | .cmp_eq, |
| ... | @@ -1310,6 +1316,8 @@ pub const Inst = struct { | ... | @@ -1310,6 +1316,8 @@ pub const Inst = struct { |
| 1310 | .alloc_inferred_mut, | 1316 | .alloc_inferred_mut, |
| 1311 | .alloc_inferred_comptime, | 1317 | .alloc_inferred_comptime, |
| 1312 | .alloc_inferred_comptime_mut, | 1318 | .alloc_inferred_comptime_mut, |
| 1319 | .async_call, | ||
| 1320 | .async_field_call, | ||
| 1313 | .make_ptr_const, | 1321 | .make_ptr_const, |
| 1314 | .array_cat, | 1322 | .array_cat, |
| 1315 | .array_mul, | 1323 | .array_mul, |
| ... | @@ -1336,7 +1344,6 @@ pub const Inst = struct { | ... | @@ -1336,7 +1344,6 @@ pub const Inst = struct { |
| 1336 | .bool_not, | 1344 | .bool_not, |
| 1337 | .call, | 1345 | .call, |
| 1338 | .field_call, | 1346 | .field_call, |
| 1339 | .async_call, | ||
| 1340 | .cmp_lt, | 1347 | .cmp_lt, |
| 1341 | .cmp_lte, | 1348 | .cmp_lte, |
| 1342 | .cmp_eq, | 1349 | .cmp_eq, |
| ... | @@ -1572,6 +1579,7 @@ pub const Inst = struct { | ... | @@ -1572,6 +1579,7 @@ pub const Inst = struct { |
| 1572 | .call = .pl_node, | 1579 | .call = .pl_node, |
| 1573 | .field_call = .pl_node, | 1580 | .field_call = .pl_node, |
| 1574 | .async_call = .pl_node, | 1581 | .async_call = .pl_node, |
| 1582 | .async_field_call = .pl_node, | ||
| 1575 | .cmp_lt = .pl_node, | 1583 | .cmp_lt = .pl_node, |
| 1576 | .cmp_lte = .pl_node, | 1584 | .cmp_lte = .pl_node, |
| 1577 | .cmp_eq = .pl_node, | 1585 | .cmp_eq = .pl_node, |
| ... | @@ -2549,6 +2557,14 @@ pub const Inst = struct { | ... | @@ -2549,6 +2557,14 @@ pub const Inst = struct { |
| 2549 | args_len: u32, | 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 | pub const TypeOfPeer = struct { | 2568 | pub const TypeOfPeer = struct { |
| 2553 | src_node: i32, | 2569 | src_node: i32, |
| 2554 | body_len: u32, | 2570 | body_len: u32, |
src/print_air.zig+14-4| ... | @@ -701,7 +701,7 @@ const Writer = struct { | ... | @@ -701,7 +701,7 @@ const Writer = struct { |
| 701 | const pl_op = w.air.instructions.items(.data)[inst].pl_op; | 701 | const pl_op = w.air.instructions.items(.data)[inst].pl_op; |
| 702 | const extra = w.air.extraData(Air.Call, pl_op.payload); | 702 | const extra = w.air.extraData(Air.Call, pl_op.payload); |
| 703 | const args: []const Air.Inst.Ref = @ptrCast(w.air.extra[extra.end..][0..extra.data.args_len]); | 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 | fn writeCallAsync(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | 707 | fn writeCallAsync(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { |
| ... | @@ -709,21 +709,31 @@ const Writer = struct { | ... | @@ -709,21 +709,31 @@ const Writer = struct { |
| 709 | const extra = w.air.extraData(Air.AsyncCall, ty_pl.payload); | 709 | const extra = w.air.extraData(Air.AsyncCall, ty_pl.payload); |
| 710 | const callee = extra.data.callee; | 710 | const callee = extra.data.callee; |
| 711 | const args: []const Air.Inst.Ref = @ptrCast(w.air.extra[extra.end..][0..extra.data.args_len]); | 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 | fn finishWriteCall( | 716 | fn finishWriteCall( |
| 716 | w: *Writer, | 717 | w: *Writer, |
| 717 | s: anytype, | 718 | s: anytype, |
| 718 | inst: Air.Inst.Index, | 719 | inst: Air.Inst.Index, |
| 720 | frame_ptr: Air.Inst.Ref, | ||
| 719 | callee: Air.Inst.Ref, | 721 | callee: Air.Inst.Ref, |
| 720 | args: []const Air.Inst.Ref, | 722 | args: []const Air.Inst.Ref, |
| 721 | ) @TypeOf(s).Error!void { | 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 | try s.writeAll(", ["); | 732 | try s.writeAll(", ["); |
| 724 | for (args, 0..) |arg, i| { | 733 | for (args, 0..) |arg, i| { |
| 725 | if (i != 0) try s.writeAll(", "); | 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 | try s.writeAll("]"); | 738 | try s.writeAll("]"); |
| 729 | } | 739 | } |
src/print_zir.zig+28-29| ... | @@ -360,9 +360,10 @@ const Writer = struct { | ... | @@ -360,9 +360,10 @@ const Writer = struct { |
| 360 | .@"export" => try self.writePlNodeExport(stream, inst), | 360 | .@"export" => try self.writePlNodeExport(stream, inst), |
| 361 | .export_value => try self.writePlNodeExportValue(stream, inst), | 361 | .export_value => try self.writePlNodeExportValue(stream, inst), |
| 362 | 362 | ||
| 363 | .call => try self.writeCall(stream, inst, .direct), | 363 | .call => try self.writeCall(stream, inst, Zir.Inst.Call), |
| 364 | .field_call => try self.writeCall(stream, inst, .field), | 364 | .field_call => try self.writeCall(stream, inst, Zir.Inst.FieldCall), |
| 365 | .async_call => try self.writeAsyncCall(stream, inst), | 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 | .block, | 368 | .block, |
| 368 | .block_comptime, | 369 | .block_comptime, |
| ... | @@ -1188,50 +1189,48 @@ const Writer = struct { | ... | @@ -1188,50 +1189,48 @@ const Writer = struct { |
| 1188 | try self.writeSrc(stream, src); | 1189 | try self.writeSrc(stream, src); |
| 1189 | } | 1190 | } |
| 1190 | 1191 | ||
| 1191 | const CallKind = enum { direct, field }; | ||
| 1192 | |||
| 1193 | fn writeCall( | 1192 | fn writeCall( |
| 1194 | self: *Writer, | 1193 | self: *Writer, |
| 1195 | stream: anytype, | 1194 | stream: anytype, |
| 1196 | inst: Zir.Inst.Index, | 1195 | inst: Zir.Inst.Index, |
| 1197 | comptime kind: CallKind, | 1196 | comptime ExtraType: type, |
| 1198 | ) !void { | 1197 | ) !void { |
| 1199 | const inst_data = self.code.instructions.items(.data)[inst].pl_node; | 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 | const extra = self.code.extraData(ExtraType, inst_data.payload_index); | 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 | const body = self.code.extra[extra.end..]; | 1205 | const body = self.code.extra[extra.end..]; |
| 1207 | const modifier: std.builtin.CallModifier = @enumFromInt(extra.data.flags.packed_modifier); | 1206 | switch (ExtraType) { |
| 1208 | 1207 | Zir.Inst.Call, Zir.Inst.FieldCall => if (extra.data.flags.ensure_result_used) { | |
| 1209 | if (extra.data.flags.ensure_result_used) { | 1208 | try stream.writeAll("nodiscard "); |
| 1210 | 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 | try stream.print(".{s}, ", .{@tagName(modifier)}); | 1220 | try stream.print(".{s}, ", .{@tagName(modifier)}); |
| 1213 | switch (kind) { | 1221 | |
| 1214 | .direct => try self.writeInstRef(stream, extra.data.callee), | 1222 | switch (ExtraType) { |
| 1215 | .field => { | 1223 | Zir.Inst.Call, Zir.Inst.AsyncCall => try self.writeInstRef(stream, extra.data.callee), |
| 1224 | Zir.Inst.FieldCall, Zir.Inst.AsyncFieldCall => { | ||
| 1216 | const field_name = self.code.nullTerminatedString(extra.data.field_name_start); | 1225 | const field_name = self.code.nullTerminatedString(extra.data.field_name_start); |
| 1217 | try self.writeInstRef(stream, extra.data.obj_ptr); | 1226 | try self.writeInstRef(stream, extra.data.obj_ptr); |
| 1218 | try stream.print(", \"{}\"", .{std.zig.fmtEscapes(field_name)}); | 1227 | try stream.print(", \"{}\"", .{std.zig.fmtEscapes(field_name)}); |
| 1219 | }, | 1228 | }, |
| 1229 | else => @compileError("unreachable"), | ||
| 1220 | } | 1230 | } |
| 1221 | return finishWriteCall(self, stream, body, args_len, extra.end, inst_data.src()); | 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 | fn finishWriteCall( | 1234 | fn finishWriteCall( |
| 1236 | self: *Writer, | 1235 | self: *Writer, |
| 1237 | stream: anytype, | 1236 | stream: anytype, |