From 12ef0ac7015d795ee90acc82af1523f319f7639e Mon Sep 17 00:00:00 2001 From: mlugg Date: Fri, 14 Apr 2023 22:32:31 +0100 Subject: [PATCH] Add `@inComptime` builtin Resolves: #868 --- doc/langref.html.in | 11 +++++++++++ lib/std/crypto/sha2.zig | 8 +------- lib/std/fmt.zig | 10 ++-------- src/AstGen.zig | 2 ++ src/BuiltinFn.zig | 8 ++++++++ src/Sema.zig | 13 +++++++++++++ src/Zir.zig | 7 +++++-- src/print_zir.zig | 1 + test/behavior/eval.zig | 12 ++++++++++++ 9 files changed, 55 insertions(+), 17 deletions(-) diff --git a/doc/langref.html.in b/doc/langref.html.in index 38e1d674faa9..737cfc53dd48 100644 --- a/doc/langref.html.in +++ b/doc/langref.html.in @@ -8569,6 +8569,17 @@ test "@hasDecl" { {#see_also|Compile Variables|@embedFile#} {#header_close#} + {#header_open|@inComptime#} +
{#syntax#}@inComptime() bool{#endsyntax#}
+

+ Returns whether the builtin was run in a {#syntax#}comptime{#endsyntax#} context. The result is a compile-time constant. +

+

+ 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. +

+ {#see_also|comptime#} + {#header_close#} + {#header_open|@intCast#}
{#syntax#}@intCast(comptime DestType: type, int: anytype) DestType{#endsyntax#}

diff --git a/lib/std/crypto/sha2.zig b/lib/std/crypto/sha2.zig index 24c22ecc9f32..539cb0a7d6cd 100644 --- a/lib/std/crypto/sha2.zig +++ b/lib/std/crypto/sha2.zig @@ -71,12 +71,6 @@ const Sha256Params = Sha2Params32{ const v4u32 = @Vector(4, u32); -// TODO: Remove once https://github.com/ziglang/zig/issues/868 is resolved. -fn isComptime() bool { - var a: u8 = 0; - return @typeInfo(@TypeOf(.{a})).Struct.fields[0].is_comptime; -} - /// SHA-224 pub const Sha224 = Sha2x32(Sha224Params); @@ -203,7 +197,7 @@ fn Sha2x32(comptime params: Sha2Params32) type { s[i] = mem.readIntBig(u32, mem.asBytes(elem)); } - if (!isComptime()) { + if (!@inComptime()) { switch (builtin.cpu.arch) { .aarch64 => if (comptime std.Target.aarch64.featureSetHas(builtin.cpu.features, .sha2)) { var x: v4u32 = d.s[0..4].*; diff --git a/lib/std/fmt.zig b/lib/std/fmt.zig index 1658f8a5020d..686f1a153baf 100644 --- a/lib/std/fmt.zig +++ b/lib/std/fmt.zig @@ -1428,8 +1428,8 @@ pub fn formatInt( var a: MinInt = abs_value; var index: usize = buf.len; - // TODO isComptime here because of https://github.com/ziglang/zig/issues/13335. - if (base == 10 and !isComptime()) { + // TODO: @inComptime check due to this logic at comptime causing failures on aarch64 backend + if (base == 10 and !@inComptime()) { while (a >= 100) : (a = @divTrunc(a, 100)) { index -= 2; buf[index..][0..2].* = digits2(@intCast(usize, a % 100)); @@ -1469,12 +1469,6 @@ pub fn formatInt( return formatBuf(buf[index..], options, writer); } -// TODO: Remove once https://github.com/ziglang/zig/issues/868 is resolved. -fn isComptime() bool { - var a: u8 = 0; - return @typeInfo(@TypeOf(.{a})).Struct.fields[0].is_comptime; -} - pub fn formatIntBuf(out_buf: []u8, value: anytype, base: u8, case: Case, options: FormatOptions) usize { var fbs = std.io.fixedBufferStream(out_buf); formatInt(value, base, case, options, fbs.writer()) catch unreachable; diff --git a/src/AstGen.zig b/src/AstGen.zig index 4419f5e80397..efc6a9fb85ff 100644 --- a/src/AstGen.zig +++ b/src/AstGen.zig @@ -8174,6 +8174,7 @@ fn builtinCall( .frame => return rvalue(gz, ri, try gz.addNodeExtended(.frame, node), node), .frame_address => return rvalue(gz, ri, try gz.addNodeExtended(.frame_address, node), node), .breakpoint => return rvalue(gz, ri, try gz.addNodeExtended(.breakpoint, node), node), + .in_comptime => return rvalue(gz, ri, try gz.addNodeExtended(.in_comptime, node), node), .type_info => return simpleUnOpType(gz, scope, ri, node, params[0], .type_info), .size_of => return simpleUnOpType(gz, scope, ri, node, params[0], .size_of), @@ -8215,6 +8216,7 @@ fn builtinCall( .int_cast => return typeCast(gz, scope, ri, node, params[0], params[1], .int_cast), .ptr_cast => return typeCast(gz, scope, ri, node, params[0], params[1], .ptr_cast), .truncate => return typeCast(gz, scope, ri, node, params[0], params[1], .truncate), + // zig fmt: on .Type => { diff --git a/src/BuiltinFn.zig b/src/BuiltinFn.zig index 4a98a5a6156f..ee11aecbf423 100644 --- a/src/BuiltinFn.zig +++ b/src/BuiltinFn.zig @@ -58,6 +58,7 @@ pub const Tag = enum { has_decl, has_field, import, + in_comptime, int_cast, int_to_enum, int_to_error, @@ -560,6 +561,13 @@ pub const list = list: { .param_count = 1, }, }, + .{ + "@inComptime", + .{ + .tag = .in_comptime, + .param_count = 0, + }, + }, .{ "@intCast", .{ diff --git a/src/Sema.zig b/src/Sema.zig index 9cf342f75b83..49f3a3dc522c 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -1166,6 +1166,7 @@ fn analyzeBodyInner( .work_item_id => try sema.zirWorkItem( block, extended, extended.opcode), .work_group_size => try sema.zirWorkItem( block, extended, extended.opcode), .work_group_id => try sema.zirWorkItem( block, extended, extended.opcode), + .in_comptime => try sema.zirInComptime( block), // zig fmt: on .fence => { @@ -22464,6 +22465,18 @@ fn zirWorkItem( }); } +fn zirInComptime( + sema: *Sema, + block: *Block, +) CompileError!Air.Inst.Ref { + _ = sema; + if (block.is_comptime) { + return Air.Inst.Ref.bool_true; + } else { + return Air.Inst.Ref.bool_false; + } +} + fn requireRuntimeBlock(sema: *Sema, block: *Block, src: LazySrcLoc, runtime_src: ?LazySrcLoc) !void { if (block.is_comptime) { const msg = msg: { diff --git a/src/Zir.zig b/src/Zir.zig index 904e02c7559b..a58b4b407069 100644 --- a/src/Zir.zig +++ b/src/Zir.zig @@ -1994,10 +1994,10 @@ pub const Inst = struct { /// Implement builtin `@cVaArg`. /// `operand` is payload index to `BinNode`. c_va_arg, - /// Implement builtin `@cVaStart`. + /// Implement builtin `@cVaCopy`. /// `operand` is payload index to `UnNode`. c_va_copy, - /// Implement builtin `@cVaStart`. + /// Implement builtin `@cVaEnd`. /// `operand` is payload index to `UnNode`. c_va_end, /// Implement builtin `@cVaStart`. @@ -2018,6 +2018,9 @@ pub const Inst = struct { /// Implements the `@workGroupId` builtin. /// `operand` is payload index to `UnNode`. work_group_id, + /// Implements the `@inComptime` builtin. + /// `operand` is `src_node: i32`. + in_comptime, pub const InstData = struct { opcode: Extended, diff --git a/src/print_zir.zig b/src/print_zir.zig index 79c802f93604..927d8a8b339a 100644 --- a/src/print_zir.zig +++ b/src/print_zir.zig @@ -466,6 +466,7 @@ const Writer = struct { .frame_address, .breakpoint, .c_va_start, + .in_comptime, => try self.writeExtNode(stream, extended), .builtin_src => { diff --git a/test/behavior/eval.zig b/test/behavior/eval.zig index 302de9359155..0b3cf0771aba 100644 --- a/test/behavior/eval.zig +++ b/test/behavior/eval.zig @@ -1649,3 +1649,15 @@ test "early exit in container level const" { }; try expect(S.value == 1); } + +test "@inComptime" { + const S = struct { + fn inComptime() bool { + return @inComptime(); + } + }; + try expectEqual(false, @inComptime()); + try expectEqual(true, comptime @inComptime()); + try expectEqual(false, S.inComptime()); + try expectEqual(true, comptime S.inComptime()); +}