aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/AstGen.zig41
-rw-r--r--src/Module.zig33
-rw-r--r--src/Sema.zig42
-rw-r--r--src/Zir.zig70
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;