diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/AstGen.zig | 41 | ||||
| -rw-r--r-- | src/Module.zig | 33 | ||||
| -rw-r--r-- | src/Sema.zig | 42 | ||||
| -rw-r--r-- | src/Zir.zig | 70 |
4 files changed, 118 insertions, 68 deletions
diff --git a/src/AstGen.zig b/src/AstGen.zig index 88cddc39b9..5994ca0d7f 100644 --- a/src/AstGen.zig +++ b/src/AstGen.zig @@ -900,11 +900,6 @@ pub fn nosuspendExpr( try astgen.errNoteNode(gz.nosuspend_node, "other nosuspend block here", .{}), }); } - if (gz.suspend_node != 0) { - return astgen.failNodeNotes(node, "inside a suspend block, nosuspend is implied", .{}, &[_]u32{ - try astgen.errNoteNode(gz.suspend_node, "suspend block here", .{}), - }); - } gz.nosuspend_node = node; const result = try expr(gz, scope, rl, body_node); gz.nosuspend_node = 0; @@ -1803,6 +1798,8 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: ast.Node.Index) Inner .bool_and, .bool_or, .call_compile_time, + .call_nosuspend, + .call_async, .cmp_lt, .cmp_lte, .cmp_eq, @@ -1876,7 +1873,6 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: ast.Node.Index) Inner .slice_end, .slice_sentinel, .import, - .typeof_peer, .switch_block, .switch_block_multi, .switch_block_else, @@ -2001,7 +1997,6 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: ast.Node.Index) Inner .ensure_result_non_error, .@"export", .set_eval_branch_quota, - .compile_log, .ensure_err_payload_void, .@"break", .break_inline, @@ -6074,11 +6069,7 @@ fn typeOf( items[param_i] = try expr(gz, scope, .none, param); } - const result = try gz.addPlNode(.typeof_peer, node, Zir.Inst.MultiOp{ - .operands_len = @intCast(u32, params.len), - }); - try gz.astgen.appendRefs(items); - + const result = try gz.addExtendedMultiOp(.typeof_peer, node, items); return rvalue(gz, scope, rl, result, node); } @@ -6138,10 +6129,7 @@ fn builtinCall( for (params) |param, i| arg_refs[i] = try expr(gz, scope, .none, param); - const result = try gz.addPlNode(.compile_log, node, Zir.Inst.MultiOp{ - .operands_len = @intCast(u32, params.len), - }); - try gz.astgen.appendRefs(arg_refs); + const result = try gz.addExtendedMultiOp(.compile_log, node, arg_refs); return rvalue(gz, scope, rl, result, node); }, .field => { @@ -6745,9 +6733,6 @@ fn callExpr( call: ast.full.Call, ) InnerError!Zir.Inst.Ref { const astgen = gz.astgen; - if (call.async_token) |async_token| { - return astgen.failTok(async_token, "async and related features are not yet supported", .{}); - } const lhs = try expr(gz, scope, .none, call.ast.fn_expr); const args = try astgen.gpa.alloc(Zir.Inst.Ref, call.ast.params.len); @@ -6764,9 +6749,17 @@ fn callExpr( args[i] = try expr(gz, scope, .{ .ty = param_type }, param_node); } - const modifier: std.builtin.CallOptions.Modifier = switch (call.async_token != null) { - true => .async_kw, - false => .auto, + const modifier: std.builtin.CallOptions.Modifier = blk: { + if (gz.force_comptime) { + break :blk .compile_time; + } + if (call.async_token != null) { + break :blk .async_kw; + } + if (gz.nosuspend_node != 0) { + break :blk .no_async; + } + break :blk .auto; }; const result: Zir.Inst.Ref = res: { const tag: Zir.Inst.Tag = switch (modifier) { @@ -6774,10 +6767,10 @@ fn callExpr( true => break :res try gz.addUnNode(.call_none, lhs, node), false => .call, }, - .async_kw => return astgen.failNode(node, "async and related features are not yet supported", .{}), + .async_kw => .call_async, .never_tail => unreachable, .never_inline => unreachable, - .no_async => return astgen.failNode(node, "async and related features are not yet supported", .{}), + .no_async => .call_nosuspend, .always_tail => unreachable, .always_inline => unreachable, .compile_time => .call_compile_time, diff --git a/src/Module.zig b/src/Module.zig index 4e69d301f3..ef5ecc934d 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -1533,6 +1533,39 @@ pub const Scope = struct { return gz.indexToRef(new_index); } + pub fn addExtendedMultiOp( + gz: *GenZir, + opcode: Zir.Inst.Extended, + node: ast.Node.Index, + operands: []const Zir.Inst.Ref, + ) !Zir.Inst.Ref { + const astgen = gz.astgen; + const gpa = astgen.gpa; + + try gz.instructions.ensureUnusedCapacity(gpa, 1); + try astgen.instructions.ensureUnusedCapacity(gpa, 1); + try astgen.extra.ensureUnusedCapacity( + gpa, + @typeInfo(Zir.Inst.NodeMultiOp).Struct.fields.len + operands.len, + ); + + const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.NodeMultiOp{ + .src_node = gz.nodeIndexToRelative(node), + }); + const new_index = @intCast(Zir.Inst.Index, astgen.instructions.len); + astgen.instructions.appendAssumeCapacity(.{ + .tag = .extended, + .data = .{ .extended = .{ + .opcode = opcode, + .small = @intCast(u16, operands.len), + .operand = payload_index, + } }, + }); + gz.instructions.appendAssumeCapacity(new_index); + astgen.appendRefsAssumeCapacity(operands); + return gz.indexToRef(new_index); + } + pub fn addArrayTypeSentinel( gz: *GenZir, len: Zir.Inst.Ref, diff --git a/src/Sema.zig b/src/Sema.zig index 0648ca1b1c..e8f413c7e8 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -161,6 +161,8 @@ pub fn analyzeBody( .call => try sema.zirCall(block, inst, .auto, false), .call_chkused => try sema.zirCall(block, inst, .auto, true), .call_compile_time => try sema.zirCall(block, inst, .compile_time, false), + .call_nosuspend => try sema.zirCall(block, inst, .no_async, false), + .call_async => try sema.zirCall(block, inst, .async_kw, false), .call_none => try sema.zirCallNone(block, inst, false), .call_none_chkused => try sema.zirCallNone(block, inst, true), .cmp_eq => try sema.zirCmp(block, inst, .eq), @@ -254,7 +256,6 @@ pub fn analyzeBody( .bit_size_of => try sema.zirBitSizeOf(block, inst), .typeof => try sema.zirTypeof(block, inst), .typeof_elem => try sema.zirTypeofElem(block, inst), - .typeof_peer => try sema.zirTypeofPeer(block, inst), .log2_int_type => try sema.zirLog2IntType(block, inst), .typeof_log2_int_type => try sema.zirTypeofLog2IntType(block, inst), .xor => try sema.zirBitwise(block, inst, .xor), @@ -403,10 +404,6 @@ pub fn analyzeBody( try sema.zirEnsureResultUsed(block, inst); continue; }, - .compile_log => { - try sema.zirCompileLog(block, inst); - continue; - }, .set_eval_branch_quota => { try sema.zirSetEvalBranchQuota(block, inst); continue; @@ -519,6 +516,8 @@ fn zirExtended(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerErro .alloc => return sema.zirAllocExtended( block, extended), .builtin_extern => return sema.zirBuiltinExtern( block, extended), .@"asm" => return sema.zirAsm( block, extended), + .typeof_peer => return sema.zirTypeofPeer( block, extended), + .compile_log => return sema.zirCompileLog( block, extended), .c_undef => return sema.zirCUndef( block, extended), .c_include => return sema.zirCInclude( block, extended), .c_define => return sema.zirCDefine( block, extended), @@ -1533,14 +1532,18 @@ fn zirCompileError(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Inner return sema.mod.fail(&block.base, src, "{s}", .{msg}); } -fn zirCompileLog(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!void { +fn zirCompileLog( + sema: *Sema, + block: *Scope.Block, + extended: Zir.Inst.Extended.InstData, +) InnerError!*Inst { var managed = sema.mod.compile_log_text.toManaged(sema.gpa); defer sema.mod.compile_log_text = managed.moveToUnmanaged(); const writer = managed.writer(); - const inst_data = sema.code.instructions.items(.data)[inst].pl_node; - const extra = sema.code.extraData(Zir.Inst.MultiOp, inst_data.payload_index); - const args = sema.code.refSlice(extra.end, extra.data.operands_len); + const extra = sema.code.extraData(Zir.Inst.NodeMultiOp, extended.operand); + const src: LazySrcLoc = .{ .node_offset = extra.data.src_node }; + const args = sema.code.refSlice(extra.end, extended.small); for (args) |arg_ref, i| { if (i != 0) try writer.print(", ", .{}); @@ -1556,8 +1559,12 @@ fn zirCompileLog(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerEr const gop = try sema.mod.compile_log_decls.getOrPut(sema.gpa, sema.owner_decl); if (!gop.found_existing) { - gop.entry.value = inst_data.src().toSrcLoc(&block.base); + gop.entry.value = src.toSrcLoc(&block.base); } + return sema.mod.constInst(sema.arena, src, .{ + .ty = Type.initTag(.void), + .val = Value.initTag(.void_value), + }); } fn zirRepeat(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!Zir.Inst.Index { @@ -4680,16 +4687,19 @@ fn zirLog2IntType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerE return sema.mod.fail(&block.base, src, "TODO: implement Sema.zirLog2IntType", .{}); } -fn zirTypeofPeer(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst { +fn zirTypeofPeer( + sema: *Sema, + block: *Scope.Block, + extended: Zir.Inst.Extended.InstData, +) InnerError!*Inst { const tracy = trace(@src()); defer tracy.end(); - const inst_data = sema.code.instructions.items(.data)[inst].pl_node; - const src = inst_data.src(); - const extra = sema.code.extraData(Zir.Inst.MultiOp, inst_data.payload_index); - const args = sema.code.refSlice(extra.end, extra.data.operands_len); + const extra = sema.code.extraData(Zir.Inst.NodeMultiOp, extended.operand); + const src: LazySrcLoc = .{ .node_offset = extra.data.src_node }; + const args = sema.code.refSlice(extra.end, extended.small); - const inst_list = try sema.gpa.alloc(*ir.Inst, extra.data.operands_len); + const inst_list = try sema.gpa.alloc(*ir.Inst, args.len); defer sema.gpa.free(inst_list); for (args) |arg_ref, i| { diff --git a/src/Zir.zig b/src/Zir.zig index 9b0a40600c..d2a520a43e 100644 --- a/src/Zir.zig +++ b/src/Zir.zig @@ -238,6 +238,10 @@ pub const Inst = struct { call_chkused, /// Same as `call` but with modifier `.compile_time`. call_compile_time, + /// Same as `call` but with modifier `.no_suspend`. + call_nosuspend, + /// Same as `call` but with modifier `.async_kw`. + call_async, /// Function call with modifier `.auto`, empty parameter list. /// Uses the `un_node` field. Operand is callee. AST node is the function call. call_none, @@ -266,10 +270,6 @@ pub const Inst = struct { /// Uses the `bin` union field. /// LHS is destination element type, RHS is result pointer. coerce_result_ptr, - /// Log compile time variables and emit an error message. - /// Uses the `pl_node` union field. The AST node is the compile log builtin call. - /// The payload is `MultiOp`. - compile_log, /// Conditional branch. Splits control flow based on a boolean condition value. /// Uses the `pl_node` union field. AST node is an if, while, for, etc. /// Payload is `CondBr`. @@ -523,10 +523,6 @@ pub const Inst = struct { /// Given a value which is a pointer, returns the element type. /// Uses the `un_node` field. typeof_elem, - /// The builtin `@TypeOf` which returns the type after Peer Type Resolution - /// of one or more params. - /// Uses the `pl_node` field. AST node is the `@TypeOf` call. Payload is `MultiOp`. - typeof_peer, /// Given a value, look at the type of it, which must be an integer type. /// Returns the integer type for the RHS of a shift operation. /// Uses the `un_node` field. @@ -990,6 +986,8 @@ pub const Inst = struct { .call, .call_chkused, .call_compile_time, + .call_nosuspend, + .call_async, .call_none, .call_none_chkused, .cmp_lt, @@ -1085,12 +1083,10 @@ pub const Inst = struct { .slice_end, .slice_sentinel, .import, - .typeof_peer, .typeof_log2_int_type, .log2_int_type, .resolve_inferred_alloc, .set_eval_branch_quota, - .compile_log, .switch_capture, .switch_capture_ref, .switch_capture_multi, @@ -1268,6 +1264,17 @@ pub const Inst = struct { /// * 0bX0000000_00000000 - is volatile /// `operand` is payload index to `Asm`. @"asm", + /// Log compile time variables and emit an error message. + /// `operand` is payload index to `NodeMultiOp`. + /// `small` is `operands_len`. + /// The AST node is the compile log builtin call. + compile_log, + /// The builtin `@TypeOf` which returns the type after Peer Type Resolution + /// of one or more params. + /// `operand` is payload index to `NodeMultiOp`. + /// `small` is `operands_len`. + /// The AST node is the builtin call. + typeof_peer, /// `operand` is payload index to `UnNode`. c_undef, /// `operand` is payload index to `UnNode`. @@ -1897,6 +1904,11 @@ pub const Inst = struct { operands_len: u32, }; + /// Trailing: operand: Ref, // for each `operands_len` (stored in `small`). + pub const NodeMultiOp = struct { + src_node: i32, + }; + /// This data is stored inside extra, with trailing operands according to `body_len`. /// Each operand is an `Index`. pub const Block = struct { @@ -2540,6 +2552,8 @@ const Writer = struct { .call, .call_chkused, .call_compile_time, + .call_nosuspend, + .call_async, => try self.writePlNodeCall(stream, inst), .block, @@ -2584,10 +2598,6 @@ const Writer = struct { .switch_block_ref_else_multi => try self.writePlNodeSwitchBlockMulti(stream, inst, .@"else"), .switch_block_ref_under_multi => try self.writePlNodeSwitchBlockMulti(stream, inst, .under), - .compile_log, - .typeof_peer, - => try self.writePlNodeMultiOp(stream, inst), - .field_ptr, .field_val, => try self.writePlNodeField(stream, inst), @@ -2646,6 +2656,10 @@ const Writer = struct { .@"asm" => try self.writeAsm(stream, extended), .func => try self.writeFuncExtended(stream, extended), + .compile_log, + .typeof_peer, + => try self.writeNodeMultiOp(stream, extended), + .alloc, .builtin_extern, .c_undef, @@ -2836,6 +2850,19 @@ const Writer = struct { try self.writeSrc(stream, inst_data.src()); } + fn writeNodeMultiOp(self: *Writer, stream: anytype, extended: Inst.Extended.InstData) !void { + const extra = self.code.extraData(Inst.NodeMultiOp, extended.operand); + const src: LazySrcLoc = .{ .node_offset = extra.data.src_node }; + const operands = self.code.refSlice(extra.end, extended.small); + + for (operands) |operand, i| { + if (i != 0) try stream.writeAll(", "); + try self.writeInstRef(stream, operand); + } + try stream.writeAll(")) "); + try self.writeSrc(stream, src); + } + fn writeAsm(self: *Writer, stream: anytype, extended: Inst.Extended.InstData) !void { const extra = self.code.extraData(Inst.Asm, extended.operand); const src: LazySrcLoc = .{ .node_offset = extra.data.src_node }; @@ -2902,7 +2929,7 @@ const Writer = struct { } } } - try stream.writeAll(") "); + try stream.writeAll(")) "); try self.writeSrc(stream, src); } @@ -3457,19 +3484,6 @@ const Writer = struct { try self.writeSrc(stream, inst_data.src()); } - fn writePlNodeMultiOp(self: *Writer, stream: anytype, inst: Inst.Index) !void { - const inst_data = self.code.instructions.items(.data)[inst].pl_node; - const extra = self.code.extraData(Inst.MultiOp, inst_data.payload_index); - const operands = self.code.refSlice(extra.end, extra.data.operands_len); - - for (operands) |operand, i| { - if (i != 0) try stream.writeAll(", "); - try self.writeInstRef(stream, operand); - } - try stream.writeAll(") "); - try self.writeSrc(stream, inst_data.src()); - } - fn writePlNodeField(self: *Writer, stream: anytype, inst: Inst.Index) !void { const inst_data = self.code.instructions.items(.data)[inst].pl_node; const extra = self.code.extraData(Inst.Field, inst_data.payload_index).data; |
