authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-01-04 18:12:45-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-01-04 18:12:45-07:00
log1c24ef0d0b09a12a1fe98056f2fc04de78a82df3
treeb80e1fe8fe801541f962c1965cb84c3167a68feb
parent5087ec6f41ba928e14596e00822dc117aeb90a12

stage2: introduce std.builtin.CompilerBackend

This allows Zig code to perform conditional compilation based on a tag by which a Zig compiler implementation identifies itself. See the doc comment in this commit for more details.

3 files changed, 77 insertions(+), 5 deletions(-)

lib/std/builtin.zig+55
...@@ -694,6 +694,61 @@ pub const ExternOptions = struct {...@@ -694,6 +694,61 @@ pub const ExternOptions = struct {
694 is_thread_local: bool = false,694 is_thread_local: bool = false,
695};695};
696696
697/// This enum is set by the compiler and communicates which compiler backend is
698/// used to produce machine code.
699/// Think carefully before deciding to observe this value. Nearly all code should
700/// be agnostic to the backend that implements the language. The use case
701/// to use this value is to **work around problems with compiler implementations.**
702///
703/// Avoid failing the compilation if the compiler backend does not match a
704/// whitelist of backends; rather one should detect that a known problem would
705/// occur in a blacklist of backends.
706///
707/// The enum is nonexhaustive so that alternate Zig language implementations may
708/// choose a number as their tag (please use a random number generator rather
709/// than a "cute" number) and codebases can interact with these values even if
710/// this upstream enum does not have a name for the number. Of course, upstream
711/// is happy to accept pull requests to add Zig implementations to this enum.
712///
713/// This data structure is part of the Zig language specification.
714pub const CompilerBackend = enum(u64) {
715 /// It is allowed for a compiler implementation to not reveal its identity,
716 /// in which case this value is appropriate. Be cool and make sure your
717 /// code supports `other` Zig compilers!
718 other = 0,
719 /// The original Zig compiler created in 2015 by Andrew Kelley.
720 /// Implemented in C++. Uses LLVM.
721 stage1 = 1,
722 /// The reference implementation self-hosted compiler of Zig, using the
723 /// LLVM backend.
724 stage2_llvm = 2,
725 /// The reference implementation self-hosted compiler of Zig, using the
726 /// backend that generates C source code.
727 /// Note that one can observe whether the compilation will output C code
728 /// directly with `object_format` value rather than the `compiler_backend` value.
729 stage2_c = 3,
730 /// The reference implementation self-hosted compiler of Zig, using the
731 /// WebAssembly backend.
732 stage2_wasm = 4,
733 /// The reference implementation self-hosted compiler of Zig, using the
734 /// arm backend.
735 stage2_arm = 5,
736 /// The reference implementation self-hosted compiler of Zig, using the
737 /// x86_64 backend.
738 stage2_x86_64 = 6,
739 /// The reference implementation self-hosted compiler of Zig, using the
740 /// aarch64 backend.
741 stage2_aarch64 = 7,
742 /// The reference implementation self-hosted compiler of Zig, using the
743 /// x86 backend.
744 stage2_x86 = 8,
745 /// The reference implementation self-hosted compiler of Zig, using the
746 /// riscv64 backend.
747 stage2_riscv64 = 9,
748
749 _,
750};
751
697/// This function type is used by the Zig language code generation and752/// This function type is used by the Zig language code generation and
698/// therefore must be kept in sync with the compiler implementation.753/// therefore must be kept in sync with the compiler implementation.
699pub const TestFn = struct {754pub const TestFn = struct {
src/Compilation.zig+17
...@@ -4538,12 +4538,28 @@ pub fn generateBuiltinZigSource(comp: *Compilation, allocator: Allocator) Alloca...@@ -4538,12 +4538,28 @@ pub fn generateBuiltinZigSource(comp: *Compilation, allocator: Allocator) Alloca
4538 const stage2_x86_cx16 = target.cpu.arch == .x86_64 and4538 const stage2_x86_cx16 = target.cpu.arch == .x86_64 and
4539 std.Target.x86.featureSetHas(target.cpu.features, .cx16);4539 std.Target.x86.featureSetHas(target.cpu.features, .cx16);
45404540
4541 const zig_backend: std.builtin.CompilerBackend = blk: {
4542 if (use_stage1) break :blk .stage1;
4543 if (build_options.have_llvm and comp.bin_file.options.use_llvm) break :blk .stage2_llvm;
4544 if (comp.bin_file.options.object_format == .c) break :blk .stage2_c;
4545 break :blk switch (target.cpu.arch) {
4546 .wasm32, .wasm64 => std.builtin.CompilerBackend.stage2_wasm,
4547 .arm, .armeb, .thumb, .thumbeb => .stage2_arm,
4548 .x86_64 => .stage2_x86_64,
4549 .i386 => .stage2_x86,
4550 .aarch64, .aarch64_be, .aarch64_32 => .stage2_aarch64,
4551 .riscv64 => .stage2_riscv64,
4552 else => .other,
4553 };
4554 };
4555
4541 @setEvalBranchQuota(4000);4556 @setEvalBranchQuota(4000);
4542 try buffer.writer().print(4557 try buffer.writer().print(
4543 \\const std = @import("std");4558 \\const std = @import("std");
4544 \\/// Zig version. When writing code that supports multiple versions of Zig, prefer4559 \\/// Zig version. When writing code that supports multiple versions of Zig, prefer
4545 \\/// feature detection (i.e. with `@hasDecl` or `@hasField`) over version checks.4560 \\/// feature detection (i.e. with `@hasDecl` or `@hasField`) over version checks.
4546 \\pub const zig_version = std.SemanticVersion.parse("{s}") catch unreachable;4561 \\pub const zig_version = std.SemanticVersion.parse("{s}") catch unreachable;
4562 \\pub const zig_backend = std.builtin.CompilerBackend.{};
4547 \\/// Temporary until self-hosted is feature complete.4563 \\/// Temporary until self-hosted is feature complete.
4548 \\pub const zig_is_stage2 = {};4564 \\pub const zig_is_stage2 = {};
4549 \\/// Temporary until self-hosted supports the `cpu.arch` value.4565 \\/// Temporary until self-hosted supports the `cpu.arch` value.
...@@ -4563,6 +4579,7 @@ pub fn generateBuiltinZigSource(comp: *Compilation, allocator: Allocator) Alloca...@@ -4563,6 +4579,7 @@ pub fn generateBuiltinZigSource(comp: *Compilation, allocator: Allocator) Alloca
4563 \\4579 \\
4564 , .{4580 , .{
4565 build_options.version,4581 build_options.version,
4582 std.zig.fmtId(@tagName(zig_backend)),
4566 !use_stage1,4583 !use_stage1,
4567 std.zig.fmtId(@tagName(target.cpu.arch)),4584 std.zig.fmtId(@tagName(target.cpu.arch)),
4568 stage2_x86_cx16,4585 stage2_x86_cx16,
test/behavior.zig+5-5
...@@ -7,7 +7,7 @@ test {...@@ -7,7 +7,7 @@ test {
7 _ = @import("behavior/bugs/3586.zig");7 _ = @import("behavior/bugs/3586.zig");
8 _ = @import("behavior/slice_sentinel_comptime.zig");8 _ = @import("behavior/slice_sentinel_comptime.zig");
99
10 if (!builtin.zig_is_stage2 or builtin.stage2_arch != .x86_64) {10 if (builtin.zig_backend != .stage2_x86_64) {
11 // Tests that pass for stage1, llvm backend, C backend, wasm backend, and arm backend.11 // Tests that pass for stage1, llvm backend, C backend, wasm backend, and arm backend.
12 _ = @import("behavior/bugs/679.zig");12 _ = @import("behavior/bugs/679.zig");
13 _ = @import("behavior/bugs/4560.zig");13 _ = @import("behavior/bugs/4560.zig");
...@@ -19,7 +19,7 @@ test {...@@ -19,7 +19,7 @@ test {
19 _ = @import("behavior/type_info.zig");19 _ = @import("behavior/type_info.zig");
20 _ = @import("behavior/type.zig");20 _ = @import("behavior/type.zig");
2121
22 if (!builtin.zig_is_stage2 or builtin.stage2_arch != .arm) {22 if (builtin.zig_backend != .stage2_arm) {
23 // Tests that pass for stage1, llvm backend, C backend, wasm backend.23 // Tests that pass for stage1, llvm backend, C backend, wasm backend.
24 _ = @import("behavior/basic.zig");24 _ = @import("behavior/basic.zig");
25 _ = @import("behavior/bitcast.zig");25 _ = @import("behavior/bitcast.zig");
...@@ -57,7 +57,7 @@ test {...@@ -57,7 +57,7 @@ test {
57 _ = @import("behavior/void.zig");57 _ = @import("behavior/void.zig");
58 _ = @import("behavior/while.zig");58 _ = @import("behavior/while.zig");
5959
60 if (!builtin.zig_is_stage2 or builtin.stage2_arch != .wasm32) {60 if (builtin.zig_backend != .stage2_wasm) {
61 // Tests that pass for stage1, llvm backend, C backend61 // Tests that pass for stage1, llvm backend, C backend
62 _ = @import("behavior/align.zig");62 _ = @import("behavior/align.zig");
63 _ = @import("behavior/array.zig");63 _ = @import("behavior/array.zig");
...@@ -67,7 +67,7 @@ test {...@@ -67,7 +67,7 @@ test {
67 _ = @import("behavior/optional.zig");67 _ = @import("behavior/optional.zig");
68 _ = @import("behavior/translate_c_macros.zig");68 _ = @import("behavior/translate_c_macros.zig");
6969
70 if (builtin.object_format != .c) {70 if (builtin.zig_backend != .stage2_c) {
71 // Tests that pass for stage1 and the llvm backend.71 // Tests that pass for stage1 and the llvm backend.
72 _ = @import("behavior/align_llvm.zig");72 _ = @import("behavior/align_llvm.zig");
73 _ = @import("behavior/alignof.zig");73 _ = @import("behavior/alignof.zig");
...@@ -109,7 +109,7 @@ test {...@@ -109,7 +109,7 @@ test {
109 _ = @import("behavior/union.zig");109 _ = @import("behavior/union.zig");
110 _ = @import("behavior/widening.zig");110 _ = @import("behavior/widening.zig");
111111
112 if (builtin.zig_is_stage2) {112 if (builtin.zig_backend != .stage1) {
113 // When all comptime_memory.zig tests pass, #9646 can be closed.113 // When all comptime_memory.zig tests pass, #9646 can be closed.
114 // _ = @import("behavior/comptime_memory.zig");114 // _ = @import("behavior/comptime_memory.zig");
115 _ = @import("behavior/slice_stage2.zig");115 _ = @import("behavior/slice_stage2.zig");