authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2023-04-14 22:32:31+01:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-04-23 13:16:42-07:00
log35d82d31be3d2f2611049f41dc2616f898d70871
tree9dfb2332aca1201afb67aea6bf83a9e77bf05c9f
parent42ee364e7b698822a69cba4cd2bda17868657e05

Add `@inComptime` builtin

Resolves: #868

9 files changed, 53 insertions(+), 17 deletions(-)

doc/langref.html.in+11
...@@ -8587,6 +8587,17 @@ test "@hasDecl" {...@@ -8587,6 +8587,17 @@ test "@hasDecl" {
8587 {#see_also|Compile Variables|@embedFile#}8587 {#see_also|Compile Variables|@embedFile#}
8588 {#header_close#}8588 {#header_close#}
85898589
8590 {#header_open|@inComptime#}
8591 <pre>{#syntax#}@inComptime() bool{#endsyntax#}</pre>
8592 <p>
8593 Returns whether the builtin was run in a {#syntax#}comptime{#endsyntax#} context. The result is a compile-time constant.
8594 </p>
8595 <p>
8596 This can be used to provide alternative, comptime-friendly implementations of functions. It should not be used, for instance, to exclude certain functions from being evaluated at comptime.
8597 </p>
8598 {#see_also|comptime#}
8599 {#header_close#}
8600
8590 {#header_open|@intCast#}8601 {#header_open|@intCast#}
8591 <pre>{#syntax#}@intCast(comptime DestType: type, int: anytype) DestType{#endsyntax#}</pre>8602 <pre>{#syntax#}@intCast(comptime DestType: type, int: anytype) DestType{#endsyntax#}</pre>
8592 <p>8603 <p>
lib/std/crypto/sha2.zig+1-7
...@@ -71,12 +71,6 @@ const Sha256Params = Sha2Params32{...@@ -71,12 +71,6 @@ const Sha256Params = Sha2Params32{
7171
72const v4u32 = @Vector(4, u32);72const v4u32 = @Vector(4, u32);
7373
74// TODO: Remove once https://github.com/ziglang/zig/issues/868 is resolved.
75fn isComptime() bool {
76 var a: u8 = 0;
77 return @typeInfo(@TypeOf(.{a})).Struct.fields[0].is_comptime;
78}
79
80/// SHA-22474/// SHA-224
81pub const Sha224 = Sha2x32(Sha224Params);75pub const Sha224 = Sha2x32(Sha224Params);
8276
...@@ -203,7 +197,7 @@ fn Sha2x32(comptime params: Sha2Params32) type {...@@ -203,7 +197,7 @@ fn Sha2x32(comptime params: Sha2Params32) type {
203 s[i] = mem.readIntBig(u32, mem.asBytes(elem));197 s[i] = mem.readIntBig(u32, mem.asBytes(elem));
204 }198 }
205199
206 if (!isComptime()) {200 if (!@inComptime()) {
207 switch (builtin.cpu.arch) {201 switch (builtin.cpu.arch) {
208 .aarch64 => if (builtin.zig_backend != .stage2_c and comptime std.Target.aarch64.featureSetHas(builtin.cpu.features, .sha2)) {202 .aarch64 => if (builtin.zig_backend != .stage2_c and comptime std.Target.aarch64.featureSetHas(builtin.cpu.features, .sha2)) {
209 var x: v4u32 = d.s[0..4].*;203 var x: v4u32 = d.s[0..4].*;
lib/std/fmt.zig+1-8
...@@ -1428,8 +1428,7 @@ pub fn formatInt(...@@ -1428,8 +1428,7 @@ pub fn formatInt(
1428 var a: MinInt = abs_value;1428 var a: MinInt = abs_value;
1429 var index: usize = buf.len;1429 var index: usize = buf.len;
14301430
1431 // TODO isComptime here because of https://github.com/ziglang/zig/issues/13335.1431 if (base == 10) {
1432 if (base == 10 and !isComptime()) {
1433 while (a >= 100) : (a = @divTrunc(a, 100)) {1432 while (a >= 100) : (a = @divTrunc(a, 100)) {
1434 index -= 2;1433 index -= 2;
1435 buf[index..][0..2].* = digits2(@intCast(usize, a % 100));1434 buf[index..][0..2].* = digits2(@intCast(usize, a % 100));
...@@ -1469,12 +1468,6 @@ pub fn formatInt(...@@ -1469,12 +1468,6 @@ pub fn formatInt(
1469 return formatBuf(buf[index..], options, writer);1468 return formatBuf(buf[index..], options, writer);
1470}1469}
14711470
1472// TODO: Remove once https://github.com/ziglang/zig/issues/868 is resolved.
1473fn isComptime() bool {
1474 var a: u8 = 0;
1475 return @typeInfo(@TypeOf(.{a})).Struct.fields[0].is_comptime;
1476}
1477
1478pub fn formatIntBuf(out_buf: []u8, value: anytype, base: u8, case: Case, options: FormatOptions) usize {1471pub fn formatIntBuf(out_buf: []u8, value: anytype, base: u8, case: Case, options: FormatOptions) usize {
1479 var fbs = std.io.fixedBufferStream(out_buf);1472 var fbs = std.io.fixedBufferStream(out_buf);
1480 formatInt(value, base, case, options, fbs.writer()) catch unreachable;1473 formatInt(value, base, case, options, fbs.writer()) catch unreachable;
src/AstGen.zig+1
...@@ -8174,6 +8174,7 @@ fn builtinCall(...@@ -8174,6 +8174,7 @@ fn builtinCall(
8174 .frame => return rvalue(gz, ri, try gz.addNodeExtended(.frame, node), node),8174 .frame => return rvalue(gz, ri, try gz.addNodeExtended(.frame, node), node),
8175 .frame_address => return rvalue(gz, ri, try gz.addNodeExtended(.frame_address, node), node),8175 .frame_address => return rvalue(gz, ri, try gz.addNodeExtended(.frame_address, node), node),
8176 .breakpoint => return rvalue(gz, ri, try gz.addNodeExtended(.breakpoint, node), node),8176 .breakpoint => return rvalue(gz, ri, try gz.addNodeExtended(.breakpoint, node), node),
8177 .in_comptime => return rvalue(gz, ri, try gz.addNodeExtended(.in_comptime, node), node),
81778178
8178 .type_info => return simpleUnOpType(gz, scope, ri, node, params[0], .type_info),8179 .type_info => return simpleUnOpType(gz, scope, ri, node, params[0], .type_info),
8179 .size_of => return simpleUnOpType(gz, scope, ri, node, params[0], .size_of),8180 .size_of => return simpleUnOpType(gz, scope, ri, node, params[0], .size_of),
src/BuiltinFn.zig+8
...@@ -58,6 +58,7 @@ pub const Tag = enum {...@@ -58,6 +58,7 @@ pub const Tag = enum {
58 has_decl,58 has_decl,
59 has_field,59 has_field,
60 import,60 import,
61 in_comptime,
61 int_cast,62 int_cast,
62 int_to_enum,63 int_to_enum,
63 int_to_error,64 int_to_error,
...@@ -560,6 +561,13 @@ pub const list = list: {...@@ -560,6 +561,13 @@ pub const list = list: {
560 .param_count = 1,561 .param_count = 1,
561 },562 },
562 },563 },
564 .{
565 "@inComptime",
566 .{
567 .tag = .in_comptime,
568 .param_count = 0,
569 },
570 },
563 .{571 .{
564 "@intCast",572 "@intCast",
565 .{573 .{
src/Sema.zig+13
...@@ -1166,6 +1166,7 @@ fn analyzeBodyInner(...@@ -1166,6 +1166,7 @@ fn analyzeBodyInner(
1166 .work_item_id => try sema.zirWorkItem( block, extended, extended.opcode),1166 .work_item_id => try sema.zirWorkItem( block, extended, extended.opcode),
1167 .work_group_size => try sema.zirWorkItem( block, extended, extended.opcode),1167 .work_group_size => try sema.zirWorkItem( block, extended, extended.opcode),
1168 .work_group_id => try sema.zirWorkItem( block, extended, extended.opcode),1168 .work_group_id => try sema.zirWorkItem( block, extended, extended.opcode),
1169 .in_comptime => try sema.zirInComptime( block),
1169 // zig fmt: on1170 // zig fmt: on
11701171
1171 .fence => {1172 .fence => {
...@@ -22466,6 +22467,18 @@ fn zirWorkItem(...@@ -22466,6 +22467,18 @@ fn zirWorkItem(
22466 });22467 });
22467}22468}
2246822469
22470fn zirInComptime(
22471 sema: *Sema,
22472 block: *Block,
22473) CompileError!Air.Inst.Ref {
22474 _ = sema;
22475 if (block.is_comptime) {
22476 return Air.Inst.Ref.bool_true;
22477 } else {
22478 return Air.Inst.Ref.bool_false;
22479 }
22480}
22481
22469fn requireRuntimeBlock(sema: *Sema, block: *Block, src: LazySrcLoc, runtime_src: ?LazySrcLoc) !void {22482fn requireRuntimeBlock(sema: *Sema, block: *Block, src: LazySrcLoc, runtime_src: ?LazySrcLoc) !void {
22470 if (block.is_comptime) {22483 if (block.is_comptime) {
22471 const msg = msg: {22484 const msg = msg: {
src/Zir.zig+5-2
...@@ -1994,10 +1994,10 @@ pub const Inst = struct {...@@ -1994,10 +1994,10 @@ pub const Inst = struct {
1994 /// Implement builtin `@cVaArg`.1994 /// Implement builtin `@cVaArg`.
1995 /// `operand` is payload index to `BinNode`.1995 /// `operand` is payload index to `BinNode`.
1996 c_va_arg,1996 c_va_arg,
1997 /// Implement builtin `@cVaStart`.1997 /// Implement builtin `@cVaCopy`.
1998 /// `operand` is payload index to `UnNode`.1998 /// `operand` is payload index to `UnNode`.
1999 c_va_copy,1999 c_va_copy,
2000 /// Implement builtin `@cVaStart`.2000 /// Implement builtin `@cVaEnd`.
2001 /// `operand` is payload index to `UnNode`.2001 /// `operand` is payload index to `UnNode`.
2002 c_va_end,2002 c_va_end,
2003 /// Implement builtin `@cVaStart`.2003 /// Implement builtin `@cVaStart`.
...@@ -2018,6 +2018,9 @@ pub const Inst = struct {...@@ -2018,6 +2018,9 @@ pub const Inst = struct {
2018 /// Implements the `@workGroupId` builtin.2018 /// Implements the `@workGroupId` builtin.
2019 /// `operand` is payload index to `UnNode`.2019 /// `operand` is payload index to `UnNode`.
2020 work_group_id,2020 work_group_id,
2021 /// Implements the `@inComptime` builtin.
2022 /// `operand` is `src_node: i32`.
2023 in_comptime,
20212024
2022 pub const InstData = struct {2025 pub const InstData = struct {
2023 opcode: Extended,2026 opcode: Extended,
src/print_zir.zig+1
...@@ -466,6 +466,7 @@ const Writer = struct {...@@ -466,6 +466,7 @@ const Writer = struct {
466 .frame_address,466 .frame_address,
467 .breakpoint,467 .breakpoint,
468 .c_va_start,468 .c_va_start,
469 .in_comptime,
469 => try self.writeExtNode(stream, extended),470 => try self.writeExtNode(stream, extended),
470471
471 .builtin_src => {472 .builtin_src => {
test/behavior/eval.zig+12
...@@ -1649,3 +1649,15 @@ test "early exit in container level const" {...@@ -1649,3 +1649,15 @@ test "early exit in container level const" {
1649 };1649 };
1650 try expect(S.value == 1);1650 try expect(S.value == 1);
1651}1651}
1652
1653test "@inComptime" {
1654 const S = struct {
1655 fn inComptime() bool {
1656 return @inComptime();
1657 }
1658 };
1659 try expectEqual(false, @inComptime());
1660 try expectEqual(true, comptime @inComptime());
1661 try expectEqual(false, S.inComptime());
1662 try expectEqual(true, comptime S.inComptime());
1663}