commit 345042ecbc7fb645fd17b69df4e57ffefa5be5a5 (tree)
parent ef62452363de75240b21299e9f80b4851433faaa
Author: Andrew Kelley <andrew@ziglang.org>
Date: Thu, 24 Oct 2019 02:25:22 -0400
Merge pull request #3519 from ziglang/move-builtin-types
move types from builtin to std
Diffstat:
39 files changed, 1385 insertions(+), 1117 deletions(-)
diff --git a/lib/std/build.zig b/lib/std/build.zig
@@ -971,433 +971,14 @@ test "builder.findProgram compiles" {
_ = builder.findProgram([_][]const u8{}, [_][]const u8{}) catch null;
}
-pub const Version = struct {
- major: u32,
- minor: u32,
- patch: u32,
-};
-
-pub const CrossTarget = struct {
- arch: builtin.Arch,
- os: builtin.Os,
- abi: builtin.Abi,
-};
-
-pub const Target = union(enum) {
- Native: void,
- Cross: CrossTarget,
-
- pub fn zigTriple(self: Target, allocator: *Allocator) ![]u8 {
- return std.fmt.allocPrint(
- allocator,
- "{}{}-{}-{}",
- @tagName(self.getArch()),
- Target.archSubArchName(self.getArch()),
- @tagName(self.getOs()),
- @tagName(self.getAbi()),
- );
- }
-
- pub fn allocDescription(self: Target, allocator: *Allocator) ![]u8 {
- // TODO is there anything else worthy of the description that is not
- // already captured in the triple?
- return self.zigTriple(allocator);
- }
-
- pub fn zigTripleNoSubArch(self: Target, allocator: *Allocator) ![]u8 {
- return std.fmt.allocPrint(
- allocator,
- "{}-{}-{}",
- @tagName(self.getArch()),
- @tagName(self.getOs()),
- @tagName(self.getAbi()),
- );
- }
-
- pub fn linuxTriple(self: Target, allocator: *Allocator) ![]u8 {
- return std.fmt.allocPrint(
- allocator,
- "{}-{}-{}",
- @tagName(self.getArch()),
- @tagName(self.getOs()),
- @tagName(self.getAbi()),
- );
- }
-
- pub fn parse(text: []const u8) !Target {
- var it = mem.separate(text, "-");
- const arch_name = it.next() orelse return error.MissingArchitecture;
- const os_name = it.next() orelse return error.MissingOperatingSystem;
- const abi_name = it.next();
-
- var cross = CrossTarget{
- .arch = try parseArchSub(arch_name),
- .os = try parseOs(os_name),
- .abi = undefined,
- };
- cross.abi = if (abi_name) |n| try parseAbi(n) else defaultAbi(cross.arch, cross.os);
- return Target{ .Cross = cross };
- }
-
- pub fn defaultAbi(arch: builtin.Arch, target_os: builtin.Os) builtin.Abi {
- switch (arch) {
- .wasm32, .wasm64 => return .musl,
- else => {},
- }
- switch (target_os) {
- .freestanding,
- .ananas,
- .cloudabi,
- .dragonfly,
- .lv2,
- .solaris,
- .haiku,
- .minix,
- .rtems,
- .nacl,
- .cnk,
- .aix,
- .cuda,
- .nvcl,
- .amdhsa,
- .ps4,
- .elfiamcu,
- .mesa3d,
- .contiki,
- .amdpal,
- .zen,
- .hermit,
- => return .eabi,
- .openbsd,
- .macosx,
- .freebsd,
- .ios,
- .tvos,
- .watchos,
- .fuchsia,
- .kfreebsd,
- .netbsd,
- .hurd,
- => return .gnu,
- .windows,
- .uefi,
- => return .msvc,
- .linux,
- .wasi,
- .emscripten,
- => return .musl,
- }
- }
-
- pub const ParseArchSubError = error{
- UnknownArchitecture,
- UnknownSubArchitecture,
- };
-
- pub fn parseArchSub(text: []const u8) ParseArchSubError!builtin.Arch {
- const info = @typeInfo(builtin.Arch);
- inline for (info.Union.fields) |field| {
- if (mem.eql(u8, text, field.name)) {
- if (field.field_type == void) {
- return (builtin.Arch)(@field(builtin.Arch, field.name));
- } else {
- const sub_info = @typeInfo(field.field_type);
- inline for (sub_info.Enum.fields) |sub_field| {
- const combined = field.name ++ sub_field.name;
- if (mem.eql(u8, text, combined)) {
- return @unionInit(builtin.Arch, field.name, @field(field.field_type, sub_field.name));
- }
- }
- return error.UnknownSubArchitecture;
- }
- }
- }
- return error.UnknownArchitecture;
- }
-
- pub fn parseOs(text: []const u8) !builtin.Os {
- const info = @typeInfo(builtin.Os);
- inline for (info.Enum.fields) |field| {
- if (mem.eql(u8, text, field.name)) {
- return @field(builtin.Os, field.name);
- }
- }
- return error.UnknownOperatingSystem;
- }
-
- pub fn parseAbi(text: []const u8) !builtin.Abi {
- const info = @typeInfo(builtin.Abi);
- inline for (info.Enum.fields) |field| {
- if (mem.eql(u8, text, field.name)) {
- return @field(builtin.Abi, field.name);
- }
- }
- return error.UnknownApplicationBinaryInterface;
- }
-
- fn archSubArchName(arch: builtin.Arch) []const u8 {
- return switch (arch) {
- .arm => |sub| @tagName(sub),
- .armeb => |sub| @tagName(sub),
- .thumb => |sub| @tagName(sub),
- .thumbeb => |sub| @tagName(sub),
- .aarch64 => |sub| @tagName(sub),
- .aarch64_be => |sub| @tagName(sub),
- .kalimba => |sub| @tagName(sub),
- else => "",
- };
- }
-
- pub fn subArchName(self: Target) []const u8 {
- switch (self) {
- .Native => return archSubArchName(builtin.arch),
- .Cross => |cross| return archSubArchName(cross.arch),
- }
- }
-
- pub fn oFileExt(self: Target) []const u8 {
- return switch (self.getAbi()) {
- builtin.Abi.msvc => ".obj",
- else => ".o",
- };
- }
-
- pub fn exeFileExt(self: Target) []const u8 {
- if (self.isWindows()) {
- return ".exe";
- } else if (self.isUefi()) {
- return ".efi";
- } else if (self.isWasm()) {
- return ".wasm";
- } else {
- return "";
- }
- }
+/// Deprecated. Use `builtin.Version`.
+pub const Version = builtin.Version;
- pub fn staticLibSuffix(self: Target) []const u8 {
- if (self.isWasm()) {
- return ".wasm";
- }
- switch (self.getAbi()) {
- .msvc => return ".lib",
- else => return ".a",
- }
- }
-
- pub fn dynamicLibSuffix(self: Target) []const u8 {
- if (self.isDarwin()) {
- return ".dylib";
- }
- switch (self.getOs()) {
- .windows => return ".dll",
- else => return ".so",
- }
- }
-
- pub fn libPrefix(self: Target) []const u8 {
- if (self.isWasm()) {
- return "";
- }
- switch (self.getAbi()) {
- .msvc => return "",
- else => return "lib",
- }
- }
+/// Deprecated. Use `std.Target.Cross`.
+pub const CrossTarget = std.Target.Cross;
- pub fn getOs(self: Target) builtin.Os {
- return switch (self) {
- .Native => builtin.os,
- .Cross => |t| t.os,
- };
- }
-
- pub fn getArch(self: Target) builtin.Arch {
- switch (self) {
- .Native => return builtin.arch,
- .Cross => |t| return t.arch,
- }
- }
-
- pub fn getAbi(self: Target) builtin.Abi {
- switch (self) {
- .Native => return builtin.abi,
- .Cross => |t| return t.abi,
- }
- }
-
- pub fn isMinGW(self: Target) bool {
- return self.isWindows() and self.isGnu();
- }
-
- pub fn isGnu(self: Target) bool {
- return switch (self.getAbi()) {
- .gnu, .gnuabin32, .gnuabi64, .gnueabi, .gnueabihf, .gnux32 => true,
- else => false,
- };
- }
-
- pub fn isDarwin(self: Target) bool {
- return switch (self.getOs()) {
- .ios, .macosx, .watchos, .tvos => true,
- else => false,
- };
- }
-
- pub fn isWindows(self: Target) bool {
- return switch (self.getOs()) {
- .windows => true,
- else => false,
- };
- }
-
- pub fn isLinux(self: Target) bool {
- return switch (self.getOs()) {
- .linux => true,
- else => false,
- };
- }
-
- pub fn isUefi(self: Target) bool {
- return switch (self.getOs()) {
- .uefi => true,
- else => false,
- };
- }
-
- pub fn isWasm(self: Target) bool {
- return switch (self.getArch()) {
- .wasm32, .wasm64 => true,
- else => false,
- };
- }
-
- pub fn isFreeBSD(self: Target) bool {
- return switch (self.getOs()) {
- .freebsd => true,
- else => false,
- };
- }
-
- pub fn isNetBSD(self: Target) bool {
- return switch (self.getOs()) {
- .netbsd => true,
- else => false,
- };
- }
-
- pub fn wantSharedLibSymLinks(self: Target) bool {
- return !self.isWindows();
- }
-
- pub fn osRequiresLibC(self: Target) bool {
- return self.isDarwin() or self.isFreeBSD() or self.isNetBSD();
- }
-
- pub fn getArchPtrBitWidth(self: Target) u32 {
- switch (self.getArch()) {
- .avr,
- .msp430,
- => return 16,
-
- .arc,
- .arm,
- .armeb,
- .hexagon,
- .le32,
- .mips,
- .mipsel,
- .powerpc,
- .r600,
- .riscv32,
- .sparc,
- .sparcel,
- .tce,
- .tcele,
- .thumb,
- .thumbeb,
- .i386,
- .xcore,
- .nvptx,
- .amdil,
- .hsail,
- .spir,
- .kalimba,
- .shave,
- .lanai,
- .wasm32,
- .renderscript32,
- .aarch64_32,
- => return 32,
-
- .aarch64,
- .aarch64_be,
- .mips64,
- .mips64el,
- .powerpc64,
- .powerpc64le,
- .riscv64,
- .x86_64,
- .nvptx64,
- .le64,
- .amdil64,
- .hsail64,
- .spir64,
- .wasm64,
- .renderscript64,
- .amdgcn,
- .bpfel,
- .bpfeb,
- .sparcv9,
- .s390x,
- => return 64,
- }
- }
-
- pub const Executor = union(enum) {
- native,
- qemu: []const u8,
- wine: []const u8,
- unavailable,
- };
-
- pub fn getExternalExecutor(self: Target) Executor {
- if (@TagType(Target)(self) == .Native) return .native;
-
- // If the target OS matches the host OS, we can use QEMU to emulate a foreign architecture.
- if (self.getOs() == builtin.os) {
- return switch (self.getArch()) {
- .aarch64 => Executor{ .qemu = "qemu-aarch64" },
- .aarch64_be => Executor{ .qemu = "qemu-aarch64_be" },
- .arm => Executor{ .qemu = "qemu-arm" },
- .armeb => Executor{ .qemu = "qemu-armeb" },
- .i386 => Executor{ .qemu = "qemu-i386" },
- .mips => Executor{ .qemu = "qemu-mips" },
- .mipsel => Executor{ .qemu = "qemu-mipsel" },
- .mips64 => Executor{ .qemu = "qemu-mips64" },
- .mips64el => Executor{ .qemu = "qemu-mips64el" },
- .powerpc => Executor{ .qemu = "qemu-ppc" },
- .powerpc64 => Executor{ .qemu = "qemu-ppc64" },
- .powerpc64le => Executor{ .qemu = "qemu-ppc64le" },
- .riscv32 => Executor{ .qemu = "qemu-riscv32" },
- .riscv64 => Executor{ .qemu = "qemu-riscv64" },
- .s390x => Executor{ .qemu = "qemu-s390x" },
- .sparc => Executor{ .qemu = "qemu-sparc" },
- .x86_64 => Executor{ .qemu = "qemu-x86_64" },
- else => return .unavailable,
- };
- }
-
- if (self.isWindows()) {
- switch (self.getArchPtrBitWidth()) {
- 32 => return Executor{ .wine = "wine" },
- 64 => return Executor{ .wine = "wine64" },
- else => return .unavailable,
- }
- }
-
- return .unavailable;
- }
-};
+/// Deprecated. Use `std.Target`.
+pub const Target = std.Target;
const Pkg = struct {
name: []const u8,
@@ -2168,8 +1749,8 @@ pub const LibExeObjStep = struct {
}
switch (self.target) {
- Target.Native => {},
- Target.Cross => {
+ .Native => {},
+ .Cross => {
try zig_args.append("-target");
try zig_args.append(self.target.zigTriple(builder.allocator) catch unreachable);
},
@@ -2419,7 +2000,7 @@ pub const RunStep = struct {
}
pub fn addPathDir(self: *RunStep, search_path: []const u8) void {
- const PATH = if (std.os.windows.is_the_target) "Path" else "PATH";
+ const PATH = if (builtin.os == .windows) "Path" else "PATH";
const env_map = self.getEnvMap();
const prev_path = env_map.get(PATH) orelse {
env_map.set(PATH, search_path) catch unreachable;
diff --git a/lib/std/builtin.zig b/lib/std/builtin.zig
@@ -0,0 +1,413 @@
+pub usingnamespace @import("builtin");
+
+/// Deprecated: use `std.Target.Os`.
+pub const Os = std.Target.Os;
+
+/// Deprecated: use `std.Target.Arch`.
+pub const Arch = std.Target.Arch;
+
+/// Deprecated: use `std.Target.Abi`.
+pub const Abi = std.Target.Abi;
+
+/// Deprecated: use `std.Target.ObjectFormat`.
+pub const ObjectFormat = std.Target.ObjectFormat;
+
+/// Deprecated: use `std.Target.SubSystem`.
+pub const SubSystem = std.Target.SubSystem;
+
+/// `explicit_subsystem` is missing when the subsystem is automatically detected,
+/// so Zig standard library has the subsystem detection logic here. This should generally be
+/// used rather than `explicit_subsystem`.
+/// On non-Windows targets, this is `null`.
+pub const subsystem: ?SubSystem = blk: {
+ if (@hasDecl(@This(), "explicit_subsystem")) break :blk explicit_subsystem;
+ switch (os) {
+ .windows => {
+ if (is_test) {
+ break :blk SubSystem.Console;
+ }
+ if (@hasDecl(root, "WinMain") or
+ @hasDecl(root, "wWinMain") or
+ @hasDecl(root, "WinMainCRTStartup") or
+ @hasDecl(root, "wWinMainCRTStartup"))
+ {
+ break :blk SubSystem.Windows;
+ } else {
+ break :blk SubSystem.Console;
+ }
+ },
+ else => break :blk null,
+ }
+};
+
+/// This data structure is used by the Zig language code generation and
+/// therefore must be kept in sync with the compiler implementation.
+pub const StackTrace = struct {
+ index: usize,
+ instruction_addresses: []usize,
+};
+
+/// This data structure is used by the Zig language code generation and
+/// therefore must be kept in sync with the compiler implementation.
+pub const GlobalLinkage = enum {
+ Internal,
+ Strong,
+ Weak,
+ LinkOnce,
+};
+
+/// This data structure is used by the Zig language code generation and
+/// therefore must be kept in sync with the compiler implementation.
+pub const AtomicOrder = enum {
+ Unordered,
+ Monotonic,
+ Acquire,
+ Release,
+ AcqRel,
+ SeqCst,
+};
+
+/// This data structure is used by the Zig language code generation and
+/// therefore must be kept in sync with the compiler implementation.
+pub const AtomicRmwOp = enum {
+ Xchg,
+ Add,
+ Sub,
+ And,
+ Nand,
+ Or,
+ Xor,
+ Max,
+ Min,
+};
+
+/// This data structure is used by the Zig language code generation and
+/// therefore must be kept in sync with the compiler implementation.
+pub const Mode = enum {
+ Debug,
+ ReleaseSafe,
+ ReleaseFast,
+ ReleaseSmall,
+};
+
+/// This data structure is used by the Zig language code generation and
+/// therefore must be kept in sync with the compiler implementation.
+pub const TypeId = enum {
+ Type,
+ Void,
+ Bool,
+ NoReturn,
+ Int,
+ Float,
+ Pointer,
+ Array,
+ Struct,
+ ComptimeFloat,
+ ComptimeInt,
+ Undefined,
+ Null,
+ Optional,
+ ErrorUnion,
+ ErrorSet,
+ Enum,
+ Union,
+ Fn,
+ BoundFn,
+ ArgTuple,
+ Opaque,
+ Frame,
+ AnyFrame,
+ Vector,
+ EnumLiteral,
+};
+
+/// This data structure is used by the Zig language code generation and
+/// therefore must be kept in sync with the compiler implementation.
+pub const TypeInfo = union(TypeId) {
+ Type: void,
+ Void: void,
+ Bool: void,
+ NoReturn: void,
+ Int: Int,
+ Float: Float,
+ Pointer: Pointer,
+ Array: Array,
+ Struct: Struct,
+ ComptimeFloat: void,
+ ComptimeInt: void,
+ Undefined: void,
+ Null: void,
+ Optional: Optional,
+ ErrorUnion: ErrorUnion,
+ ErrorSet: ErrorSet,
+ Enum: Enum,
+ Union: Union,
+ Fn: Fn,
+ BoundFn: Fn,
+ ArgTuple: void,
+ Opaque: void,
+ Frame: void,
+ AnyFrame: AnyFrame,
+ Vector: Vector,
+ EnumLiteral: void,
+
+ /// This data structure is used by the Zig language code generation and
+ /// therefore must be kept in sync with the compiler implementation.
+ pub const Int = struct {
+ is_signed: bool,
+ bits: comptime_int,
+ };
+
+ /// This data structure is used by the Zig language code generation and
+ /// therefore must be kept in sync with the compiler implementation.
+ pub const Float = struct {
+ bits: comptime_int,
+ };
+
+ /// This data structure is used by the Zig language code generation and
+ /// therefore must be kept in sync with the compiler implementation.
+ pub const Pointer = struct {
+ size: Size,
+ is_const: bool,
+ is_volatile: bool,
+ alignment: comptime_int,
+ child: type,
+ is_allowzero: bool,
+
+ /// This data structure is used by the Zig language code generation and
+ /// therefore must be kept in sync with the compiler implementation.
+ pub const Size = enum {
+ One,
+ Many,
+ Slice,
+ C,
+ };
+ };
+
+ /// This data structure is used by the Zig language code generation and
+ /// therefore must be kept in sync with the compiler implementation.
+ pub const Array = struct {
+ len: comptime_int,
+ child: type,
+ };
+
+ /// This data structure is used by the Zig language code generation and
+ /// therefore must be kept in sync with the compiler implementation.
+ pub const ContainerLayout = enum {
+ Auto,
+ Extern,
+ Packed,
+ };
+
+ /// This data structure is used by the Zig language code generation and
+ /// therefore must be kept in sync with the compiler implementation.
+ pub const StructField = struct {
+ name: []const u8,
+ offset: ?comptime_int,
+ field_type: type,
+ };
+
+ /// This data structure is used by the Zig language code generation and
+ /// therefore must be kept in sync with the compiler implementation.
+ pub const Struct = struct {
+ layout: ContainerLayout,
+ fields: []StructField,
+ decls: []Declaration,
+ };
+
+ /// This data structure is used by the Zig language code generation and
+ /// therefore must be kept in sync with the compiler implementation.
+ pub const Optional = struct {
+ child: type,
+ };
+
+ /// This data structure is used by the Zig language code generation and
+ /// therefore must be kept in sync with the compiler implementation.
+ pub const ErrorUnion = struct {
+ error_set: type,
+ payload: type,
+ };
+
+ /// This data structure is used by the Zig language code generation and
+ /// therefore must be kept in sync with the compiler implementation.
+ pub const Error = struct {
+ name: []const u8,
+ value: comptime_int,
+ };
+
+ /// This data structure is used by the Zig language code generation and
+ /// therefore must be kept in sync with the compiler implementation.
+ pub const ErrorSet = ?[]Error;
+
+ /// This data structure is used by the Zig language code generation and
+ /// therefore must be kept in sync with the compiler implementation.
+ pub const EnumField = struct {
+ name: []const u8,
+ value: comptime_int,
+ };
+
+ /// This data structure is used by the Zig language code generation and
+ /// therefore must be kept in sync with the compiler implementation.
+ pub const Enum = struct {
+ layout: ContainerLayout,
+ tag_type: type,
+ fields: []EnumField,
+ decls: []Declaration,
+ };
+
+ /// This data structure is used by the Zig language code generation and
+ /// therefore must be kept in sync with the compiler implementation.
+ pub const UnionField = struct {
+ name: []const u8,
+ enum_field: ?EnumField,
+ field_type: type,
+ };
+
+ /// This data structure is used by the Zig language code generation and
+ /// therefore must be kept in sync with the compiler implementation.
+ pub const Union = struct {
+ layout: ContainerLayout,
+ tag_type: ?type,
+ fields: []UnionField,
+ decls: []Declaration,
+ };
+
+ /// This data structure is used by the Zig language code generation and
+ /// therefore must be kept in sync with the compiler implementation.
+ pub const CallingConvention = enum {
+ Unspecified,
+ C,
+ Cold,
+ Naked,
+ Stdcall,
+ Async,
+ };
+
+ /// This data structure is used by the Zig language code generation and
+ /// therefore must be kept in sync with the compiler implementation.
+ pub const FnArg = struct {
+ is_generic: bool,
+ is_noalias: bool,
+ arg_type: ?type,
+ };
+
+ /// This data structure is used by the Zig language code generation and
+ /// therefore must be kept in sync with the compiler implementation.
+ pub const Fn = struct {
+ calling_convention: CallingConvention,
+ is_generic: bool,
+ is_var_args: bool,
+ return_type: ?type,
+ args: []FnArg,
+ };
+
+ /// This data structure is used by the Zig language code generation and
+ /// therefore must be kept in sync with the compiler implementation.
+ pub const AnyFrame = struct {
+ child: ?type,
+ };
+
+ /// This data structure is used by the Zig language code generation and
+ /// therefore must be kept in sync with the compiler implementation.
+ pub const Vector = struct {
+ len: comptime_int,
+ child: type,
+ };
+
+ /// This data structure is used by the Zig language code generation and
+ /// therefore must be kept in sync with the compiler implementation.
+ pub const Declaration = struct {
+ name: []const u8,
+ is_pub: bool,
+ data: Data,
+
+ /// This data structure is used by the Zig language code generation and
+ /// therefore must be kept in sync with the compiler implementation.
+ pub const Data = union(enum) {
+ Type: type,
+ Var: type,
+ Fn: FnDecl,
+
+ /// This data structure is used by the Zig language code generation and
+ /// therefore must be kept in sync with the compiler implementation.
+ pub const FnDecl = struct {
+ fn_type: type,
+ inline_type: Inline,
+ calling_convention: CallingConvention,
+ is_var_args: bool,
+ is_extern: bool,
+ is_export: bool,
+ lib_name: ?[]const u8,
+ return_type: type,
+ arg_names: [][]const u8,
+
+ /// This data structure is used by the Zig language code generation and
+ /// therefore must be kept in sync with the compiler implementation.
+ pub const Inline = enum {
+ Auto,
+ Always,
+ Never,
+ };
+ };
+ };
+ };
+};
+
+/// This data structure is used by the Zig language code generation and
+/// therefore must be kept in sync with the compiler implementation.
+pub const FloatMode = enum {
+ Strict,
+ Optimized,
+};
+
+/// This data structure is used by the Zig language code generation and
+/// therefore must be kept in sync with the compiler implementation.
+pub const Endian = enum {
+ Big,
+ Little,
+};
+
+/// This data structure is used by the Zig language code generation and
+/// therefore must be kept in sync with the compiler implementation.
+pub const Version = struct {
+ major: u32,
+ minor: u32,
+ patch: u32,
+};
+
+/// This function type is used by the Zig language code generation and
+/// therefore must be kept in sync with the compiler implementation.
+pub const PanicFn = fn ([]const u8, ?*StackTrace) noreturn;
+
+/// This function is used by the Zig language code generation and
+/// therefore must be kept in sync with the compiler implementation.
+pub const panic: PanicFn = if (@hasDecl(root, "panic")) root.panic else default_panic;
+
+/// This function is used by the Zig language code generation and
+/// therefore must be kept in sync with the compiler implementation.
+pub fn default_panic(msg: []const u8, error_return_trace: ?*StackTrace) noreturn {
+ @setCold(true);
+ switch (os) {
+ .freestanding => {
+ while (true) {
+ @breakpoint();
+ }
+ },
+ .wasi => {
+ std.debug.warn("{}", msg);
+ _ = std.os.wasi.proc_raise(std.os.wasi.SIGABRT);
+ unreachable;
+ },
+ .uefi => {
+ // TODO look into using the debug info and logging helpful messages
+ std.os.abort();
+ },
+ else => {
+ const first_trace_addr = @returnAddress();
+ std.debug.panicExtra(error_return_trace, first_trace_addr, "{}", msg);
+ },
+ }
+}
+
+const std = @import("std.zig");
+const root = @import("root");
diff --git a/lib/std/c/darwin.zig b/lib/std/c/darwin.zig
@@ -36,7 +36,7 @@ const mach_hdr = if (@sizeOf(usize) == 8) mach_header_64 else mach_header;
/// export a weak symbol here, to be overridden by the real one.
pub extern "c" var _mh_execute_header: mach_hdr = undefined;
comptime {
- if (std.os.darwin.is_the_target) {
+ if (std.Target.current.isDarwin()) {
@export("_mh_execute_header", _mh_execute_header, .Weak);
}
}
diff --git a/lib/std/child_process.zig b/lib/std/child_process.zig
@@ -17,9 +17,9 @@ const TailQueue = std.TailQueue;
const maxInt = std.math.maxInt;
pub const ChildProcess = struct {
- pid: if (os.windows.is_the_target) void else i32,
- handle: if (os.windows.is_the_target) windows.HANDLE else void,
- thread_handle: if (os.windows.is_the_target) windows.HANDLE else void,
+ pid: if (builtin.os == .windows) void else i32,
+ handle: if (builtin.os == .windows) windows.HANDLE else void,
+ thread_handle: if (builtin.os == .windows) windows.HANDLE else void,
allocator: *mem.Allocator,
@@ -39,16 +39,16 @@ pub const ChildProcess = struct {
stderr_behavior: StdIo,
/// Set to change the user id when spawning the child process.
- uid: if (os.windows.is_the_target) void else ?u32,
+ uid: if (builtin.os == .windows) void else ?u32,
/// Set to change the group id when spawning the child process.
- gid: if (os.windows.is_the_target) void else ?u32,
+ gid: if (builtin.os == .windows) void else ?u32,
/// Set to change the current working directory when spawning the child process.
cwd: ?[]const u8,
- err_pipe: if (os.windows.is_the_target) void else [2]os.fd_t,
- llnode: if (os.windows.is_the_target) void else TailQueue(*ChildProcess).Node,
+ err_pipe: if (builtin.os == .windows) void else [2]os.fd_t,
+ llnode: if (builtin.os == .windows) void else TailQueue(*ChildProcess).Node,
pub const SpawnError = error{OutOfMemory} || os.ExecveError || os.SetIdError ||
os.ChangeCurDirError || windows.CreateProcessError;
@@ -82,8 +82,8 @@ pub const ChildProcess = struct {
.term = null,
.env_map = null,
.cwd = null,
- .uid = if (os.windows.is_the_target) {} else null,
- .gid = if (os.windows.is_the_target) {} else null,
+ .uid = if (builtin.os == .windows) {} else null,
+ .gid = if (builtin.os == .windows) {} else null,
.stdin = null,
.stdout = null,
.stderr = null,
@@ -103,7 +103,7 @@ pub const ChildProcess = struct {
/// On success must call `kill` or `wait`.
pub fn spawn(self: *ChildProcess) !void {
- if (os.windows.is_the_target) {
+ if (builtin.os == .windows) {
return self.spawnWindows();
} else {
return self.spawnPosix();
@@ -117,7 +117,7 @@ pub const ChildProcess = struct {
/// Forcibly terminates child process and then cleans up all resources.
pub fn kill(self: *ChildProcess) !Term {
- if (os.windows.is_the_target) {
+ if (builtin.os == .windows) {
return self.killWindows(1);
} else {
return self.killPosix();
@@ -147,7 +147,7 @@ pub const ChildProcess = struct {
/// Blocks until child process terminates and then cleans up all resources.
pub fn wait(self: *ChildProcess) !Term {
- if (os.windows.is_the_target) {
+ if (builtin.os == .windows) {
return self.waitWindows();
} else {
return self.waitPosix();
diff --git a/lib/std/debug.zig b/lib/std/debug.zig
@@ -133,7 +133,7 @@ pub fn dumpStackTraceFromBase(bp: usize, ip: usize) void {
/// chopping off the irrelevant frames and shifting so that the returned addresses pointer
/// equals the passed in addresses pointer.
pub fn captureStackTrace(first_address: ?usize, stack_trace: *builtin.StackTrace) void {
- if (windows.is_the_target) {
+ if (builtin.os == .windows) {
const addrs = stack_trace.instruction_addresses;
const u32_addrs_len = @intCast(u32, addrs.len);
const first_addr = first_address orelse {
@@ -310,7 +310,7 @@ pub const StackIterator = struct {
};
pub fn writeCurrentStackTrace(out_stream: var, debug_info: *DebugInfo, tty_color: bool, start_addr: ?usize) !void {
- if (windows.is_the_target) {
+ if (builtin.os == .windows) {
return writeCurrentStackTraceWindows(out_stream, debug_info, tty_color, start_addr);
}
var it = StackIterator.init(start_addr);
@@ -342,10 +342,10 @@ pub fn writeCurrentStackTraceWindows(
/// TODO once https://github.com/ziglang/zig/issues/3157 is fully implemented,
/// make this `noasync fn` and remove the individual noasync calls.
pub fn printSourceAtAddress(debug_info: *DebugInfo, out_stream: var, address: usize, tty_color: bool) !void {
- if (windows.is_the_target) {
+ if (builtin.os == .windows) {
return noasync printSourceAtAddressWindows(debug_info, out_stream, address, tty_color);
}
- if (os.darwin.is_the_target) {
+ if (comptime std.Target.current.isDarwin()) {
return noasync printSourceAtAddressMacOs(debug_info, out_stream, address, tty_color);
}
return noasync printSourceAtAddressPosix(debug_info, out_stream, address, tty_color);
@@ -832,10 +832,10 @@ pub const OpenSelfDebugInfoError = error{
pub fn openSelfDebugInfo(allocator: *mem.Allocator) !DebugInfo {
if (builtin.strip_debug_info)
return error.MissingDebugInfo;
- if (windows.is_the_target) {
+ if (builtin.os == .windows) {
return noasync openSelfDebugInfoWindows(allocator);
}
- if (os.darwin.is_the_target) {
+ if (comptime std.Target.current.isDarwin()) {
return noasync openSelfDebugInfoMacOs(allocator);
}
return noasync openSelfDebugInfoPosix(allocator);
@@ -2364,7 +2364,7 @@ pub fn attachSegfaultHandler() void {
if (!have_segfault_handling_support) {
@compileError("segfault handler not supported for this target");
}
- if (windows.is_the_target) {
+ if (builtin.os == .windows) {
windows_segfault_handle = windows.kernel32.AddVectoredExceptionHandler(0, handleSegfaultWindows);
return;
}
@@ -2378,7 +2378,7 @@ pub fn attachSegfaultHandler() void {
}
fn resetSegfaultHandler() void {
- if (windows.is_the_target) {
+ if (builtin.os == .windows) {
if (windows_segfault_handle) |handle| {
assert(windows.kernel32.RemoveVectoredExceptionHandler(handle) != 0);
windows_segfault_handle = null;
diff --git a/lib/std/event/channel.zig b/lib/std/event/channel.zig
@@ -307,7 +307,7 @@ test "std.event.Channel" {
// https://github.com/ziglang/zig/issues/1908
if (builtin.single_threaded) return error.SkipZigTest;
// https://github.com/ziglang/zig/issues/3251
- if (std.os.freebsd.is_the_target) return error.SkipZigTest;
+ if (builtin.os == .freebsd) return error.SkipZigTest;
var loop: Loop = undefined;
// TODO make a multi threaded test
diff --git a/lib/std/event/fs.zig b/lib/std/event/fs.zig
@@ -909,7 +909,7 @@ fn hashString(s: []const u16) u32 {
// var close_op_consumed = false;
// defer if (!close_op_consumed) close_op.finish();
//
-// const flags = if (os.darwin.is_the_target) os.O_SYMLINK | os.O_EVTONLY else 0;
+// const flags = if (comptime std.Target.current.isDarwin()) os.O_SYMLINK | os.O_EVTONLY else 0;
// const mode = 0;
// const fd = try await (async openPosix(self.channel.loop, resolved_path, flags, mode) catch unreachable);
// close_op.setHandle(fd);
diff --git a/lib/std/event/future.zig b/lib/std/event/future.zig
@@ -86,7 +86,7 @@ test "std.event.Future" {
// https://github.com/ziglang/zig/issues/1908
if (builtin.single_threaded) return error.SkipZigTest;
// https://github.com/ziglang/zig/issues/3251
- if (std.os.freebsd.is_the_target) return error.SkipZigTest;
+ if (builtin.os == .freebsd) return error.SkipZigTest;
const allocator = std.heap.direct_allocator;
diff --git a/lib/std/event/lock.zig b/lib/std/event/lock.zig
@@ -119,7 +119,7 @@ test "std.event.Lock" {
// TODO https://github.com/ziglang/zig/issues/1908
if (builtin.single_threaded) return error.SkipZigTest;
// TODO https://github.com/ziglang/zig/issues/3251
- if (std.os.freebsd.is_the_target) return error.SkipZigTest;
+ if (builtin.os == .freebsd) return error.SkipZigTest;
const allocator = std.heap.direct_allocator;
diff --git a/lib/std/fs.zig b/lib/std/fs.zig
@@ -255,7 +255,7 @@ pub const AtomicFile = struct {
assert(!self.finished);
self.file.close();
self.finished = true;
- if (os.windows.is_the_target) {
+ if (builtin.os == .windows) {
const dest_path_w = try os.windows.sliceToPrefixedFileW(self.dest_path);
const tmp_path_w = try os.windows.cStrToPrefixedFileW(&self.tmp_path_buf);
return os.renameW(&tmp_path_w, &dest_path_w);
@@ -659,7 +659,7 @@ pub const Dir = struct {
/// Closing the returned `Dir` is checked illegal behavior.
/// On POSIX targets, this function is comptime-callable.
pub fn cwd() Dir {
- if (os.windows.is_the_target) {
+ if (builtin.os == .windows) {
return Dir{ .fd = os.windows.peb().ProcessParameters.CurrentDirectory.Handle };
} else {
return Dir{ .fd = os.AT_FDCWD };
@@ -711,7 +711,7 @@ pub const Dir = struct {
/// Call `close` on the result when done.
pub fn openDir(self: Dir, sub_path: []const u8) OpenError!Dir {
- if (os.windows.is_the_target) {
+ if (builtin.os == .windows) {
const sub_path_w = try os.windows.sliceToPrefixedFileW(sub_path);
return self.openDirW(&sub_path_w);
}
@@ -722,7 +722,7 @@ pub const Dir = struct {
/// Same as `openDir` except the parameter is null-terminated.
pub fn openDirC(self: Dir, sub_path_c: [*]const u8) OpenError!Dir {
- if (os.windows.is_the_target) {
+ if (builtin.os == .windows) {
const sub_path_w = try os.windows.cStrToPrefixedFileW(sub_path_c);
return self.openDirW(&sub_path_w);
}
@@ -829,7 +829,7 @@ pub const Dir = struct {
/// Returns `error.DirNotEmpty` if the directory is not empty.
/// To delete a directory recursively, see `deleteTree`.
pub fn deleteDir(self: Dir, sub_path: []const u8) DeleteDirError!void {
- if (os.windows.is_the_target) {
+ if (builtin.os == .windows) {
const sub_path_w = try os.windows.sliceToPrefixedFileW(sub_path);
return self.deleteDirW(&sub_path_w);
}
@@ -1146,10 +1146,10 @@ pub fn readLinkC(pathname_c: [*]const u8, buffer: *[MAX_PATH_BYTES]u8) ![]u8 {
pub const OpenSelfExeError = os.OpenError || os.windows.CreateFileError || SelfExePathError;
pub fn openSelfExe() OpenSelfExeError!File {
- if (os.linux.is_the_target) {
+ if (builtin.os == .linux) {
return File.openReadC(c"/proc/self/exe");
}
- if (os.windows.is_the_target) {
+ if (builtin.os == .windows) {
var buf: [os.windows.PATH_MAX_WIDE]u16 = undefined;
const wide_slice = try selfExePathW(&buf);
return File.openReadW(wide_slice.ptr);
@@ -1180,7 +1180,7 @@ pub const SelfExePathError = os.ReadLinkError || os.SysCtlError;
/// been deleted, the file path looks something like `/a/b/c/exe (deleted)`.
/// TODO make the return type of this a null terminated pointer
pub fn selfExePath(out_buffer: *[MAX_PATH_BYTES]u8) SelfExePathError![]u8 {
- if (os.darwin.is_the_target) {
+ if (comptime std.Target.current.isDarwin()) {
var u32_len: u32 = out_buffer.len;
const rc = std.c._NSGetExecutablePath(out_buffer, &u32_len);
if (rc != 0) return error.NameTooLong;
@@ -1228,7 +1228,7 @@ pub fn selfExeDirPathAlloc(allocator: *Allocator) ![]u8 {
/// Get the directory path that contains the current executable.
/// Returned value is a slice of out_buffer.
pub fn selfExeDirPath(out_buffer: *[MAX_PATH_BYTES]u8) SelfExePathError![]const u8 {
- if (os.linux.is_the_target) {
+ if (builtin.os == .linux) {
// If the currently executing binary has been deleted,
// the file path looks something like `/a/b/c/exe (deleted)`
// This path cannot be opened, but it's valid for determining the directory
diff --git a/lib/std/fs/file.zig b/lib/std/fs/file.zig
@@ -27,7 +27,7 @@ pub const File = struct {
/// Call close to clean up.
pub fn openRead(path: []const u8) OpenError!File {
- if (windows.is_the_target) {
+ if (builtin.os == .windows) {
const path_w = try windows.sliceToPrefixedFileW(path);
return openReadW(&path_w);
}
@@ -37,7 +37,7 @@ pub const File = struct {
/// `openRead` except with a null terminated path
pub fn openReadC(path: [*]const u8) OpenError!File {
- if (windows.is_the_target) {
+ if (builtin.os == .windows) {
const path_w = try windows.cStrToPrefixedFileW(path);
return openReadW(&path_w);
}
@@ -69,7 +69,7 @@ pub const File = struct {
/// If a file already exists in the destination it will be truncated.
/// Call close to clean up.
pub fn openWriteMode(path: []const u8, file_mode: Mode) OpenError!File {
- if (windows.is_the_target) {
+ if (builtin.os == .windows) {
const path_w = try windows.sliceToPrefixedFileW(path);
return openWriteModeW(&path_w, file_mode);
}
@@ -79,7 +79,7 @@ pub const File = struct {
/// Same as `openWriteMode` except `path` is null-terminated.
pub fn openWriteModeC(path: [*]const u8, file_mode: Mode) OpenError!File {
- if (windows.is_the_target) {
+ if (builtin.os == .windows) {
const path_w = try windows.cStrToPrefixedFileW(path);
return openWriteModeW(&path_w, file_mode);
}
@@ -106,7 +106,7 @@ pub const File = struct {
/// If a file already exists in the destination this returns OpenError.PathAlreadyExists
/// Call close to clean up.
pub fn openWriteNoClobber(path: []const u8, file_mode: Mode) OpenError!File {
- if (windows.is_the_target) {
+ if (builtin.os == .windows) {
const path_w = try windows.sliceToPrefixedFileW(path);
return openWriteNoClobberW(&path_w, file_mode);
}
@@ -115,7 +115,7 @@ pub const File = struct {
}
pub fn openWriteNoClobberC(path: [*]const u8, file_mode: Mode) OpenError!File {
- if (windows.is_the_target) {
+ if (builtin.os == .windows) {
const path_w = try windows.cStrToPrefixedFileW(path);
return openWriteNoClobberW(&path_w, file_mode);
}
@@ -174,7 +174,7 @@ pub const File = struct {
/// Test whether ANSI escape codes will be treated as such.
pub fn supportsAnsiEscapeCodes(self: File) bool {
- if (windows.is_the_target) {
+ if (builtin.os == .windows) {
return os.isCygwinPty(self.handle);
}
if (self.isTty()) {
@@ -214,7 +214,7 @@ pub const File = struct {
}
pub fn getEndPos(self: File) GetPosError!u64 {
- if (windows.is_the_target) {
+ if (builtin.os == .windows) {
return windows.GetFileSizeEx(self.handle);
}
return (try self.stat()).size;
@@ -223,7 +223,7 @@ pub const File = struct {
pub const ModeError = os.FStatError;
pub fn mode(self: File) ModeError!Mode {
- if (windows.is_the_target) {
+ if (builtin.os == .windows) {
return {};
}
return (try self.stat()).mode;
@@ -246,7 +246,7 @@ pub const File = struct {
pub const StatError = os.FStatError;
pub fn stat(self: File) StatError!Stat {
- if (windows.is_the_target) {
+ if (builtin.os == .windows) {
var io_status_block: windows.IO_STATUS_BLOCK = undefined;
var info: windows.FILE_ALL_INFORMATION = undefined;
const rc = windows.ntdll.NtQueryInformationFile(self.handle, &io_status_block, &info, @sizeOf(windows.FILE_ALL_INFORMATION), .FileAllInformation);
@@ -291,7 +291,7 @@ pub const File = struct {
/// last modification timestamp in nanoseconds
mtime: i64,
) UpdateTimesError!void {
- if (windows.is_the_target) {
+ if (builtin.os == .windows) {
const atime_ft = windows.nanoSecondsToFileTime(atime);
const mtime_ft = windows.nanoSecondsToFileTime(mtime);
return windows.SetFileTime(self.handle, null, &atime_ft, &mtime_ft);
diff --git a/lib/std/fs/path.zig b/lib/std/fs/path.zig
@@ -13,16 +13,16 @@ const process = std.process;
pub const sep_windows = '\\';
pub const sep_posix = '/';
-pub const sep = if (windows.is_the_target) sep_windows else sep_posix;
+pub const sep = if (builtin.os == .windows) sep_windows else sep_posix;
pub const sep_str = [1]u8{sep};
pub const delimiter_windows = ';';
pub const delimiter_posix = ':';
-pub const delimiter = if (windows.is_the_target) delimiter_windows else delimiter_posix;
+pub const delimiter = if (builtin.os == .windows) delimiter_windows else delimiter_posix;
pub fn isSep(byte: u8) bool {
- if (windows.is_the_target) {
+ if (builtin.os == .windows) {
return byte == '/' or byte == '\\';
} else {
return byte == '/';
@@ -72,7 +72,7 @@ fn joinSep(allocator: *Allocator, separator: u8, paths: []const []const u8) ![]u
return buf;
}
-pub const join = if (windows.is_the_target) joinWindows else joinPosix;
+pub const join = if (builtin.os == .windows) joinWindows else joinPosix;
/// Naively combines a series of paths with the native path seperator.
/// Allocates memory for the result, which must be freed by the caller.
@@ -129,7 +129,7 @@ test "join" {
}
pub fn isAbsolute(path: []const u8) bool {
- if (windows.is_the_target) {
+ if (builtin.os == .windows) {
return isAbsoluteWindows(path);
} else {
return isAbsolutePosix(path);
@@ -327,7 +327,7 @@ test "windowsParsePath" {
}
pub fn diskDesignator(path: []const u8) []const u8 {
- if (windows.is_the_target) {
+ if (builtin.os == .windows) {
return diskDesignatorWindows(path);
} else {
return "";
@@ -392,7 +392,7 @@ fn asciiEqlIgnoreCase(s1: []const u8, s2: []const u8) bool {
/// On Windows, this calls `resolveWindows` and on POSIX it calls `resolvePosix`.
pub fn resolve(allocator: *Allocator, paths: []const []const u8) ![]u8 {
- if (windows.is_the_target) {
+ if (builtin.os == .windows) {
return resolveWindows(allocator, paths);
} else {
return resolvePosix(allocator, paths);
@@ -409,7 +409,7 @@ pub fn resolve(allocator: *Allocator, paths: []const []const u8) ![]u8 {
/// Without performing actual syscalls, resolving `..` could be incorrect.
pub fn resolveWindows(allocator: *Allocator, paths: []const []const u8) ![]u8 {
if (paths.len == 0) {
- assert(windows.is_the_target); // resolveWindows called on non windows can't use getCwd
+ assert(builtin.os == .windows); // resolveWindows called on non windows can't use getCwd
return process.getCwdAlloc(allocator);
}
@@ -504,7 +504,7 @@ pub fn resolveWindows(allocator: *Allocator, paths: []const []const u8) ![]u8 {
result_disk_designator = result[0..result_index];
},
WindowsPath.Kind.None => {
- assert(windows.is_the_target); // resolveWindows called on non windows can't use getCwd
+ assert(builtin.os == .windows); // resolveWindows called on non windows can't use getCwd
const cwd = try process.getCwdAlloc(allocator);
defer allocator.free(cwd);
const parsed_cwd = windowsParsePath(cwd);
@@ -519,7 +519,7 @@ pub fn resolveWindows(allocator: *Allocator, paths: []const []const u8) ![]u8 {
},
}
} else {
- assert(windows.is_the_target); // resolveWindows called on non windows can't use getCwd
+ assert(builtin.os == .windows); // resolveWindows called on non windows can't use getCwd
// TODO call get cwd for the result_disk_designator instead of the global one
const cwd = try process.getCwdAlloc(allocator);
defer allocator.free(cwd);
@@ -590,7 +590,7 @@ pub fn resolveWindows(allocator: *Allocator, paths: []const []const u8) ![]u8 {
/// Without performing actual syscalls, resolving `..` could be incorrect.
pub fn resolvePosix(allocator: *Allocator, paths: []const []const u8) ![]u8 {
if (paths.len == 0) {
- assert(!windows.is_the_target); // resolvePosix called on windows can't use getCwd
+ assert(builtin.os != .windows); // resolvePosix called on windows can't use getCwd
return process.getCwdAlloc(allocator);
}
@@ -612,7 +612,7 @@ pub fn resolvePosix(allocator: *Allocator, paths: []const []const u8) ![]u8 {
if (have_abs) {
result = try allocator.alloc(u8, max_size);
} else {
- assert(!windows.is_the_target); // resolvePosix called on windows can't use getCwd
+ assert(builtin.os != .windows); // resolvePosix called on windows can't use getCwd
const cwd = try process.getCwdAlloc(allocator);
defer allocator.free(cwd);
result = try allocator.alloc(u8, max_size + cwd.len + 1);
@@ -653,7 +653,7 @@ pub fn resolvePosix(allocator: *Allocator, paths: []const []const u8) ![]u8 {
test "resolve" {
const cwd = try process.getCwdAlloc(debug.global_allocator);
- if (windows.is_the_target) {
+ if (builtin.os == .windows) {
if (windowsParsePath(cwd).kind == WindowsPath.Kind.Drive) {
cwd[0] = asciiUpper(cwd[0]);
}
@@ -669,7 +669,7 @@ test "resolveWindows" {
// TODO https://github.com/ziglang/zig/issues/3288
return error.SkipZigTest;
}
- if (windows.is_the_target) {
+ if (builtin.os == .windows) {
const cwd = try process.getCwdAlloc(debug.global_allocator);
const parsed_cwd = windowsParsePath(cwd);
{
@@ -735,7 +735,7 @@ fn testResolvePosix(paths: []const []const u8) []u8 {
/// If the path is a file in the current directory (no directory component)
/// then returns null
pub fn dirname(path: []const u8) ?[]const u8 {
- if (windows.is_the_target) {
+ if (builtin.os == .windows) {
return dirnameWindows(path);
} else {
return dirnamePosix(path);
@@ -867,7 +867,7 @@ fn testDirnameWindows(input: []const u8, expected_output: ?[]const u8) void {
}
pub fn basename(path: []const u8) []const u8 {
- if (windows.is_the_target) {
+ if (builtin.os == .windows) {
return basenameWindows(path);
} else {
return basenamePosix(path);
@@ -983,7 +983,7 @@ fn testBasenameWindows(input: []const u8, expected_output: []const u8) void {
/// string is returned.
/// On Windows this canonicalizes the drive to a capital letter and paths to `\\`.
pub fn relative(allocator: *Allocator, from: []const u8, to: []const u8) ![]u8 {
- if (windows.is_the_target) {
+ if (builtin.os == .windows) {
return relativeWindows(allocator, from, to);
} else {
return relativePosix(allocator, from, to);
diff --git a/lib/std/heap.zig b/lib/std/heap.zig
@@ -44,7 +44,7 @@ const DirectAllocator = struct {
if (n == 0)
return (([*]u8)(undefined))[0..0];
- if (os.windows.is_the_target) {
+ if (builtin.os == .windows) {
const w = os.windows;
// Although officially it's at least aligned to page boundary,
@@ -130,7 +130,7 @@ const DirectAllocator = struct {
fn shrink(allocator: *Allocator, old_mem_unaligned: []u8, old_align: u29, new_size: usize, new_align: u29) []u8 {
const old_mem = @alignCast(mem.page_size, old_mem_unaligned);
- if (os.windows.is_the_target) {
+ if (builtin.os == .windows) {
const w = os.windows;
if (new_size == 0) {
// From the docs:
@@ -170,7 +170,7 @@ const DirectAllocator = struct {
fn realloc(allocator: *Allocator, old_mem_unaligned: []u8, old_align: u29, new_size: usize, new_align: u29) ![]u8 {
const old_mem = @alignCast(mem.page_size, old_mem_unaligned);
- if (os.windows.is_the_target) {
+ if (builtin.os == .windows) {
if (old_mem.len == 0) {
return alloc(allocator, new_size, new_align);
}
diff --git a/lib/std/io.zig b/lib/std/io.zig
@@ -37,7 +37,7 @@ pub const is_async = mode != .blocking;
pub const GetStdIoError = os.windows.GetStdHandleError;
pub fn getStdOut() GetStdIoError!File {
- if (os.windows.is_the_target) {
+ if (builtin.os == .windows) {
const handle = try os.windows.GetStdHandle(os.windows.STD_OUTPUT_HANDLE);
return File.openHandle(handle);
}
@@ -45,7 +45,7 @@ pub fn getStdOut() GetStdIoError!File {
}
pub fn getStdErr() GetStdIoError!File {
- if (os.windows.is_the_target) {
+ if (builtin.os == .windows) {
const handle = try os.windows.GetStdHandle(os.windows.STD_ERROR_HANDLE);
return File.openHandle(handle);
}
@@ -53,7 +53,7 @@ pub fn getStdErr() GetStdIoError!File {
}
pub fn getStdIn() GetStdIoError!File {
- if (os.windows.is_the_target) {
+ if (builtin.os == .windows) {
const handle = try os.windows.GetStdHandle(os.windows.STD_INPUT_HANDLE);
return File.openHandle(handle);
}
diff --git a/lib/std/math.zig b/lib/std/math.zig
@@ -202,7 +202,7 @@ pub const Complex = complex.Complex;
pub const big = @import("math/big.zig");
-comptime {
+test "" {
std.meta.refAllDecls(@This());
}
diff --git a/lib/std/os.zig b/lib/std/os.zig
@@ -23,10 +23,6 @@ const elf = std.elf;
const dl = @import("dynamic_library.zig");
const MAX_PATH_BYTES = std.fs.MAX_PATH_BYTES;
-comptime {
- assert(@import("std") == std); // std lib tests require --override-lib-dir
-}
-
pub const darwin = @import("os/darwin.zig");
pub const freebsd = @import("os/freebsd.zig");
pub const linux = @import("os/linux.zig");
@@ -36,6 +32,23 @@ pub const wasi = @import("os/wasi.zig");
pub const windows = @import("os/windows.zig");
pub const zen = @import("os/zen.zig");
+comptime {
+ assert(@import("std") == std); // std lib tests require --override-lib-dir
+}
+
+test "" {
+ _ = darwin;
+ _ = freebsd;
+ _ = linux;
+ _ = netbsd;
+ _ = uefi;
+ _ = wasi;
+ _ = windows;
+ _ = zen;
+
+ _ = @import("os/test.zig");
+}
+
/// When linking libc, this is the C API. Otherwise, it is the OS-specific system interface.
pub const system = if (builtin.link_libc) std.c else switch (builtin.os) {
.macosx, .ios, .watchos, .tvos => darwin,
@@ -72,13 +85,13 @@ pub const errno = system.getErrno;
/// must call `fsync` before `close`.
/// Note: The Zig standard library does not support POSIX thread cancellation.
pub fn close(fd: fd_t) void {
- if (windows.is_the_target) {
+ if (builtin.os == .windows) {
return windows.CloseHandle(fd);
}
- if (wasi.is_the_target) {
+ if (builtin.os == .wasi) {
_ = wasi.fd_close(fd);
}
- if (darwin.is_the_target) {
+ if (comptime std.Target.current.isDarwin()) {
// This avoids the EINTR problem.
switch (darwin.getErrno(darwin.@"close$NOCANCEL"(fd))) {
EBADF => unreachable, // Always a race condition.
@@ -100,12 +113,12 @@ pub const GetRandomError = OpenError;
/// appropriate OS-specific library call. Otherwise it uses the zig standard
/// library implementation.
pub fn getrandom(buffer: []u8) GetRandomError!void {
- if (windows.is_the_target) {
+ if (builtin.os == .windows) {
return windows.RtlGenRandom(buffer);
}
- if (linux.is_the_target or freebsd.is_the_target) {
+ if (builtin.os == .linux or builtin.os == .freebsd) {
var buf = buffer;
- const use_c = !linux.is_the_target or
+ const use_c = builtin.os != .linux or
std.c.versionCheck(builtin.Version{ .major = 2, .minor = 25, .patch = 0 }).ok;
while (buf.len != 0) {
@@ -132,7 +145,7 @@ pub fn getrandom(buffer: []u8) GetRandomError!void {
}
return;
}
- if (wasi.is_the_target) {
+ if (builtin.os == .wasi) {
switch (wasi.random_get(buffer.ptr, buffer.len)) {
0 => return,
else => |err| return unexpectedErrno(err),
@@ -162,7 +175,7 @@ pub fn abort() noreturn {
// MSVCRT abort() sometimes opens a popup window which is undesirable, so
// even when linking libc on Windows we use our own abort implementation.
// See https://github.com/ziglang/zig/issues/2071 for more details.
- if (windows.is_the_target) {
+ if (builtin.os == .windows) {
if (builtin.mode == .Debug) {
@breakpoint();
}
@@ -193,14 +206,14 @@ pub fn raise(sig: u8) RaiseError!void {
}
}
- if (wasi.is_the_target) {
+ if (builtin.os == .wasi) {
switch (wasi.proc_raise(SIGABRT)) {
0 => return,
else => |err| return unexpectedErrno(err),
}
}
- if (linux.is_the_target) {
+ if (builtin.os == .linux) {
var set: linux.sigset_t = undefined;
linux.blockAppSignals(&set);
const tid = linux.syscall0(linux.SYS_gettid);
@@ -232,16 +245,16 @@ pub fn exit(status: u8) noreturn {
if (builtin.link_libc) {
system.exit(status);
}
- if (windows.is_the_target) {
+ if (builtin.os == .windows) {
windows.kernel32.ExitProcess(status);
}
- if (wasi.is_the_target) {
+ if (builtin.os == .wasi) {
wasi.proc_exit(status);
}
- if (linux.is_the_target and !builtin.single_threaded) {
+ if (builtin.os == .linux and !builtin.single_threaded) {
linux.exit_group(status);
}
- if (uefi.is_the_target) {
+ if (builtin.os == .uefi) {
// exit() is only avaliable if exitBootServices() has not been called yet.
// This call to exit should not fail, so we don't care about its return value.
if (uefi.system_table.boot_services) |bs| {
@@ -270,11 +283,11 @@ pub const ReadError = error{
/// If the application has a global event loop enabled, EAGAIN is handled
/// via the event loop. Otherwise EAGAIN results in error.WouldBlock.
pub fn read(fd: fd_t, buf: []u8) ReadError!usize {
- if (windows.is_the_target) {
+ if (builtin.os == .windows) {
return windows.ReadFile(fd, buf);
}
- if (wasi.is_the_target and !builtin.link_libc) {
+ if (builtin.os == .wasi and !builtin.link_libc) {
const iovs = [1]iovec{iovec{
.iov_base = buf.ptr,
.iov_len = buf.len,
@@ -314,7 +327,7 @@ pub fn read(fd: fd_t, buf: []u8) ReadError!usize {
/// Number of bytes read is returned. Upon reading end-of-file, zero is returned.
/// This function is for blocking file descriptors only.
pub fn preadv(fd: fd_t, iov: []const iovec, offset: u64) ReadError!usize {
- if (darwin.is_the_target) {
+ if (comptime std.Target.current.isDarwin()) {
// Darwin does not have preadv but it does have pread.
var off: usize = 0;
var iov_i: usize = 0;
@@ -385,11 +398,11 @@ pub const WriteError = error{
/// Write to a file descriptor. Keeps trying if it gets interrupted.
/// This function is for blocking file descriptors only.
pub fn write(fd: fd_t, bytes: []const u8) WriteError!void {
- if (windows.is_the_target) {
+ if (builtin.os == .windows) {
return windows.WriteFile(fd, bytes);
}
- if (wasi.is_the_target and !builtin.link_libc) {
+ if (builtin.os == .wasi and !builtin.link_libc) {
const ciovs = [1]iovec_const{iovec_const{
.iov_base = bytes.ptr,
.iov_len = bytes.len,
@@ -464,7 +477,7 @@ pub fn writev(fd: fd_t, iov: []const iovec_const) WriteError!void {
/// This function is for blocking file descriptors only. For non-blocking, see
/// `pwritevAsync`.
pub fn pwritev(fd: fd_t, iov: []const iovec_const, offset: u64) WriteError!void {
- if (darwin.is_the_target) {
+ if (comptime std.Target.current.isDarwin()) {
// Darwin does not have pwritev but it does have pwrite.
var off: usize = 0;
var iov_i: usize = 0;
@@ -828,7 +841,7 @@ pub const GetCwdError = error{
/// The result is a slice of out_buffer, indexed from 0.
pub fn getcwd(out_buffer: []u8) GetCwdError![]u8 {
- if (windows.is_the_target) {
+ if (builtin.os == .windows) {
return windows.GetCurrentDirectory(out_buffer);
}
@@ -869,7 +882,7 @@ pub const SymLinkError = error{
/// If `sym_link_path` exists, it will not be overwritten.
/// See also `symlinkC` and `symlinkW`.
pub fn symlink(target_path: []const u8, sym_link_path: []const u8) SymLinkError!void {
- if (windows.is_the_target) {
+ if (builtin.os == .windows) {
const target_path_w = try windows.sliceToPrefixedFileW(target_path);
const sym_link_path_w = try windows.sliceToPrefixedFileW(sym_link_path);
return windows.CreateSymbolicLinkW(&sym_link_path_w, &target_path_w, 0);
@@ -883,7 +896,7 @@ pub fn symlink(target_path: []const u8, sym_link_path: []const u8) SymLinkError!
/// This is the same as `symlink` except the parameters are null-terminated pointers.
/// See also `symlink`.
pub fn symlinkC(target_path: [*]const u8, sym_link_path: [*]const u8) SymLinkError!void {
- if (windows.is_the_target) {
+ if (builtin.os == .windows) {
const target_path_w = try windows.cStrToPrefixedFileW(target_path);
const sym_link_path_w = try windows.cStrToPrefixedFileW(sym_link_path);
return windows.CreateSymbolicLinkW(&sym_link_path_w, &target_path_w, 0);
@@ -958,7 +971,7 @@ pub const UnlinkError = error{
/// Delete a name and possibly the file it refers to.
/// See also `unlinkC`.
pub fn unlink(file_path: []const u8) UnlinkError!void {
- if (windows.is_the_target) {
+ if (builtin.os == .windows) {
const file_path_w = try windows.sliceToPrefixedFileW(file_path);
return windows.DeleteFileW(&file_path_w);
} else {
@@ -969,7 +982,7 @@ pub fn unlink(file_path: []const u8) UnlinkError!void {
/// Same as `unlink` except the parameter is a null terminated UTF8-encoded string.
pub fn unlinkC(file_path: [*]const u8) UnlinkError!void {
- if (windows.is_the_target) {
+ if (builtin.os == .windows) {
const file_path_w = try windows.cStrToPrefixedFileW(file_path);
return windows.DeleteFileW(&file_path_w);
}
@@ -999,7 +1012,7 @@ pub const UnlinkatError = UnlinkError || error{
/// Delete a file name and possibly the file it refers to, based on an open directory handle.
pub fn unlinkat(dirfd: fd_t, file_path: []const u8, flags: u32) UnlinkatError!void {
- if (windows.is_the_target) {
+ if (builtin.os == .windows) {
const file_path_w = try windows.sliceToPrefixedFileW(file_path);
return unlinkatW(dirfd, &file_path_w, flags);
}
@@ -1009,7 +1022,7 @@ pub fn unlinkat(dirfd: fd_t, file_path: []const u8, flags: u32) UnlinkatError!vo
/// Same as `unlinkat` but `file_path` is a null-terminated string.
pub fn unlinkatC(dirfd: fd_t, file_path_c: [*]const u8, flags: u32) UnlinkatError!void {
- if (windows.is_the_target) {
+ if (builtin.os == .windows) {
const file_path_w = try windows.cStrToPrefixedFileW(file_path_c);
return unlinkatW(dirfd, &file_path_w, flags);
}
@@ -1063,7 +1076,6 @@ pub fn unlinkatW(dirfd: fd_t, sub_path_w: [*]const u16, flags: u32) UnlinkatErro
return error.FileBusy;
}
-
var attr = w.OBJECT_ATTRIBUTES{
.Length = @sizeOf(w.OBJECT_ATTRIBUTES),
.RootDirectory = dirfd,
@@ -1121,7 +1133,7 @@ const RenameError = error{
/// Change the name or location of a file.
pub fn rename(old_path: []const u8, new_path: []const u8) RenameError!void {
- if (windows.is_the_target) {
+ if (builtin.os == .windows) {
const old_path_w = try windows.sliceToPrefixedFileW(old_path);
const new_path_w = try windows.sliceToPrefixedFileW(new_path);
return renameW(&old_path_w, &new_path_w);
@@ -1134,7 +1146,7 @@ pub fn rename(old_path: []const u8, new_path: []const u8) RenameError!void {
/// Same as `rename` except the parameters are null-terminated byte arrays.
pub fn renameC(old_path: [*]const u8, new_path: [*]const u8) RenameError!void {
- if (windows.is_the_target) {
+ if (builtin.os == .windows) {
const old_path_w = try windows.cStrToPrefixedFileW(old_path);
const new_path_w = try windows.cStrToPrefixedFileW(new_path);
return renameW(&old_path_w, &new_path_w);
@@ -1189,7 +1201,7 @@ pub const MakeDirError = error{
/// Create a directory.
/// `mode` is ignored on Windows.
pub fn mkdir(dir_path: []const u8, mode: u32) MakeDirError!void {
- if (windows.is_the_target) {
+ if (builtin.os == .windows) {
const dir_path_w = try windows.sliceToPrefixedFileW(dir_path);
return windows.CreateDirectoryW(&dir_path_w, null);
} else {
@@ -1200,7 +1212,7 @@ pub fn mkdir(dir_path: []const u8, mode: u32) MakeDirError!void {
/// Same as `mkdir` but the parameter is a null-terminated UTF8-encoded string.
pub fn mkdirC(dir_path: [*]const u8, mode: u32) MakeDirError!void {
- if (windows.is_the_target) {
+ if (builtin.os == .windows) {
const dir_path_w = try windows.cStrToPrefixedFileW(dir_path);
return windows.CreateDirectoryW(&dir_path_w, null);
}
@@ -1239,7 +1251,7 @@ pub const DeleteDirError = error{
/// Deletes an empty directory.
pub fn rmdir(dir_path: []const u8) DeleteDirError!void {
- if (windows.is_the_target) {
+ if (builtin.os == .windows) {
const dir_path_w = try windows.sliceToPrefixedFileW(dir_path);
return windows.RemoveDirectoryW(&dir_path_w);
} else {
@@ -1250,7 +1262,7 @@ pub fn rmdir(dir_path: []const u8) DeleteDirError!void {
/// Same as `rmdir` except the parameter is null-terminated.
pub fn rmdirC(dir_path: [*]const u8) DeleteDirError!void {
- if (windows.is_the_target) {
+ if (builtin.os == .windows) {
const dir_path_w = try windows.cStrToPrefixedFileW(dir_path);
return windows.RemoveDirectoryW(&dir_path_w);
}
@@ -1286,7 +1298,7 @@ pub const ChangeCurDirError = error{
/// Changes the current working directory of the calling process.
/// `dir_path` is recommended to be a UTF-8 encoded string.
pub fn chdir(dir_path: []const u8) ChangeCurDirError!void {
- if (windows.is_the_target) {
+ if (builtin.os == .windows) {
const dir_path_w = try windows.sliceToPrefixedFileW(dir_path);
@compileError("TODO implement chdir for Windows");
} else {
@@ -1297,7 +1309,7 @@ pub fn chdir(dir_path: []const u8) ChangeCurDirError!void {
/// Same as `chdir` except the parameter is null-terminated.
pub fn chdirC(dir_path: [*]const u8) ChangeCurDirError!void {
- if (windows.is_the_target) {
+ if (builtin.os == .windows) {
const dir_path_w = try windows.cStrToPrefixedFileW(dir_path);
@compileError("TODO implement chdir for Windows");
}
@@ -1328,7 +1340,7 @@ pub const ReadLinkError = error{
/// Read value of a symbolic link.
/// The return value is a slice of `out_buffer` from index 0.
pub fn readlink(file_path: []const u8, out_buffer: []u8) ReadLinkError![]u8 {
- if (windows.is_the_target) {
+ if (builtin.os == .windows) {
const file_path_w = try windows.sliceToPrefixedFileW(file_path);
@compileError("TODO implement readlink for Windows");
} else {
@@ -1339,7 +1351,7 @@ pub fn readlink(file_path: []const u8, out_buffer: []u8) ReadLinkError![]u8 {
/// Same as `readlink` except `file_path` is null-terminated.
pub fn readlinkC(file_path: [*]const u8, out_buffer: []u8) ReadLinkError![]u8 {
- if (windows.is_the_target) {
+ if (builtin.os == .windows) {
const file_path_w = try windows.cStrToPrefixedFileW(file_path);
@compileError("TODO implement readlink for Windows");
}
@@ -1360,7 +1372,7 @@ pub fn readlinkC(file_path: [*]const u8, out_buffer: []u8) ReadLinkError![]u8 {
}
pub fn readlinkatC(dirfd: fd_t, file_path: [*]const u8, out_buffer: []u8) ReadLinkError![]u8 {
- if (windows.is_the_target) {
+ if (builtin.os == .windows) {
const file_path_w = try windows.cStrToPrefixedFileW(file_path);
@compileError("TODO implement readlink for Windows");
}
@@ -1428,7 +1440,7 @@ pub fn setregid(rgid: u32, egid: u32) SetIdError!void {
/// Test whether a file descriptor refers to a terminal.
pub fn isatty(handle: fd_t) bool {
- if (windows.is_the_target) {
+ if (builtin.os == .windows) {
if (isCygwinPty(handle))
return true;
@@ -1438,10 +1450,10 @@ pub fn isatty(handle: fd_t) bool {
if (builtin.link_libc) {
return system.isatty(handle) != 0;
}
- if (wasi.is_the_target) {
+ if (builtin.os == .wasi) {
@compileError("TODO implement std.os.isatty for WASI");
}
- if (linux.is_the_target) {
+ if (builtin.os == .linux) {
var wsz: linux.winsize = undefined;
return linux.syscall3(linux.SYS_ioctl, @bitCast(usize, isize(handle)), linux.TIOCGWINSZ, @ptrToInt(&wsz)) == 0;
}
@@ -1449,7 +1461,7 @@ pub fn isatty(handle: fd_t) bool {
}
pub fn isCygwinPty(handle: fd_t) bool {
- if (!windows.is_the_target) return false;
+ if (builtin.os != .windows) return false;
const size = @sizeOf(windows.FILE_NAME_INFO);
var name_info_bytes align(@alignOf(windows.FILE_NAME_INFO)) = [_]u8{0} ** (size + windows.MAX_PATH);
@@ -1949,7 +1961,7 @@ pub const FStatError = error{SystemResources} || UnexpectedError;
pub fn fstat(fd: fd_t) FStatError!Stat {
var stat: Stat = undefined;
- if (darwin.is_the_target) {
+ if (comptime std.Target.current.isDarwin()) {
switch (darwin.getErrno(darwin.@"fstat$INODE64"(fd, &stat))) {
0 => return stat,
EINVAL => unreachable,
@@ -2215,7 +2227,7 @@ pub const AccessError = error{
/// check user's permissions for a file
/// TODO currently this assumes `mode` is `F_OK` on Windows.
pub fn access(path: []const u8, mode: u32) AccessError!void {
- if (windows.is_the_target) {
+ if (builtin.os == .windows) {
const path_w = try windows.sliceToPrefixedFileW(path);
_ = try windows.GetFileAttributesW(&path_w);
return;
@@ -2226,7 +2238,7 @@ pub fn access(path: []const u8, mode: u32) AccessError!void {
/// Same as `access` except `path` is null-terminated.
pub fn accessC(path: [*]const u8, mode: u32) AccessError!void {
- if (windows.is_the_target) {
+ if (builtin.os == .windows) {
const path_w = try windows.cStrToPrefixedFileW(path);
_ = try windows.GetFileAttributesW(&path_w);
return;
@@ -2346,7 +2358,7 @@ pub const SeekError = error{Unseekable} || UnexpectedError;
/// Repositions read/write file offset relative to the beginning.
pub fn lseek_SET(fd: fd_t, offset: u64) SeekError!void {
- if (linux.is_the_target and !builtin.link_libc and @sizeOf(usize) == 4) {
+ if (builtin.os == .linux and !builtin.link_libc and @sizeOf(usize) == 4) {
var result: u64 = undefined;
switch (errno(system.llseek(fd, offset, &result, SEEK_SET))) {
0 => return,
@@ -2358,7 +2370,7 @@ pub fn lseek_SET(fd: fd_t, offset: u64) SeekError!void {
else => |err| return unexpectedErrno(err),
}
}
- if (windows.is_the_target) {
+ if (builtin.os == .windows) {
return windows.SetFilePointerEx_BEGIN(fd, offset);
}
const ipos = @bitCast(i64, offset); // the OS treats this as unsigned
@@ -2375,7 +2387,7 @@ pub fn lseek_SET(fd: fd_t, offset: u64) SeekError!void {
/// Repositions read/write file offset relative to the current offset.
pub fn lseek_CUR(fd: fd_t, offset: i64) SeekError!void {
- if (linux.is_the_target and !builtin.link_libc and @sizeOf(usize) == 4) {
+ if (builtin.os == .linux and !builtin.link_libc and @sizeOf(usize) == 4) {
var result: u64 = undefined;
switch (errno(system.llseek(fd, @bitCast(u64, offset), &result, SEEK_CUR))) {
0 => return,
@@ -2387,7 +2399,7 @@ pub fn lseek_CUR(fd: fd_t, offset: i64) SeekError!void {
else => |err| return unexpectedErrno(err),
}
}
- if (windows.is_the_target) {
+ if (builtin.os == .windows) {
return windows.SetFilePointerEx_CURRENT(fd, offset);
}
switch (errno(system.lseek(fd, offset, SEEK_CUR))) {
@@ -2403,7 +2415,7 @@ pub fn lseek_CUR(fd: fd_t, offset: i64) SeekError!void {
/// Repositions read/write file offset relative to the end.
pub fn lseek_END(fd: fd_t, offset: i64) SeekError!void {
- if (linux.is_the_target and !builtin.link_libc and @sizeOf(usize) == 4) {
+ if (builtin.os == .linux and !builtin.link_libc and @sizeOf(usize) == 4) {
var result: u64 = undefined;
switch (errno(system.llseek(fd, @bitCast(u64, offset), &result, SEEK_END))) {
0 => return,
@@ -2415,7 +2427,7 @@ pub fn lseek_END(fd: fd_t, offset: i64) SeekError!void {
else => |err| return unexpectedErrno(err),
}
}
- if (windows.is_the_target) {
+ if (builtin.os == .windows) {
return windows.SetFilePointerEx_END(fd, offset);
}
switch (errno(system.lseek(fd, offset, SEEK_END))) {
@@ -2431,7 +2443,7 @@ pub fn lseek_END(fd: fd_t, offset: i64) SeekError!void {
/// Returns the read/write file offset relative to the beginning.
pub fn lseek_CUR_get(fd: fd_t) SeekError!u64 {
- if (linux.is_the_target and !builtin.link_libc and @sizeOf(usize) == 4) {
+ if (builtin.os == .linux and !builtin.link_libc and @sizeOf(usize) == 4) {
var result: u64 = undefined;
switch (errno(system.llseek(fd, 0, &result, SEEK_CUR))) {
0 => return result,
@@ -2443,7 +2455,7 @@ pub fn lseek_CUR_get(fd: fd_t) SeekError!u64 {
else => |err| return unexpectedErrno(err),
}
}
- if (windows.is_the_target) {
+ if (builtin.os == .windows) {
return windows.SetFilePointerEx_CURRENT_get(fd);
}
const rc = system.lseek(fd, 0, SEEK_CUR);
@@ -2492,7 +2504,7 @@ pub const RealPathError = error{
/// The return value is a slice of `out_buffer`, but not necessarily from the beginning.
/// See also `realpathC` and `realpathW`.
pub fn realpath(pathname: []const u8, out_buffer: *[MAX_PATH_BYTES]u8) RealPathError![]u8 {
- if (windows.is_the_target) {
+ if (builtin.os == .windows) {
const pathname_w = try windows.sliceToPrefixedFileW(pathname);
return realpathW(&pathname_w, out_buffer);
}
@@ -2502,11 +2514,11 @@ pub fn realpath(pathname: []const u8, out_buffer: *[MAX_PATH_BYTES]u8) RealPathE
/// Same as `realpath` except `pathname` is null-terminated.
pub fn realpathC(pathname: [*]const u8, out_buffer: *[MAX_PATH_BYTES]u8) RealPathError![]u8 {
- if (windows.is_the_target) {
+ if (builtin.os == .windows) {
const pathname_w = try windows.cStrToPrefixedFileW(pathname);
return realpathW(&pathname_w, out_buffer);
}
- if (linux.is_the_target and !builtin.link_libc) {
+ if (builtin.os == .linux and !builtin.link_libc) {
const fd = try openC(pathname, linux.O_PATH | linux.O_NONBLOCK | linux.O_CLOEXEC, 0);
defer close(fd);
@@ -2584,9 +2596,12 @@ pub fn nanosleep(seconds: u64, nanoseconds: u64) void {
}
}
-pub fn dl_iterate_phdr(comptime T: type, callback: extern fn (info: *dl_phdr_info, size: usize, data: ?*T) i32, data: ?*T) isize {
- // This is implemented only for systems using ELF executables
- if (windows.is_the_target or builtin.os == .uefi or wasi.is_the_target or darwin.is_the_target)
+pub fn dl_iterate_phdr(
+ comptime T: type,
+ callback: extern fn (info: *dl_phdr_info, size: usize, data: ?*T) i32,
+ data: ?*T,
+) isize {
+ if (builtin.object_format != .elf)
@compileError("dl_iterate_phdr is not available for this target");
if (builtin.link_libc) {
@@ -2725,7 +2740,7 @@ pub const SigaltstackError = error{
} || UnexpectedError;
pub fn sigaltstack(ss: ?*stack_t, old_ss: ?*stack_t) SigaltstackError!void {
- if (windows.is_the_target or uefi.is_the_target or wasi.is_the_target)
+ if (builtin.os == .windows or builtin.os == .uefi or builtin.os == .wasi)
@compileError("std.os.sigaltstack not available for this target");
switch (errno(system.sigaltstack(ss, old_ss))) {
@@ -2797,7 +2812,7 @@ pub fn gethostname(name_buffer: *[HOST_NAME_MAX]u8) GetHostNameError![]u8 {
else => |err| return unexpectedErrno(err),
}
}
- if (linux.is_the_target) {
+ if (builtin.os == .linux) {
var uts: utsname = undefined;
switch (errno(system.uname(&uts))) {
0 => {
@@ -2813,16 +2828,3 @@ pub fn gethostname(name_buffer: *[HOST_NAME_MAX]u8) GetHostNameError![]u8 {
@compileError("TODO implement gethostname for this OS");
}
-
-test "" {
- _ = @import("os/darwin.zig");
- _ = @import("os/freebsd.zig");
- _ = @import("os/linux.zig");
- _ = @import("os/netbsd.zig");
- _ = @import("os/uefi.zig");
- _ = @import("os/wasi.zig");
- _ = @import("os/windows.zig");
- _ = @import("os/zen.zig");
-
- _ = @import("os/test.zig");
-}
diff --git a/lib/std/os/darwin.zig b/lib/std/os/darwin.zig
@@ -1,8 +1,4 @@
const builtin = @import("builtin");
const std = @import("../std.zig");
-pub const is_the_target = switch (builtin.os) {
- .macosx, .tvos, .watchos, .ios => true,
- else => false,
-};
pub usingnamespace std.c;
pub usingnamespace @import("bits.zig");
diff --git a/lib/std/os/freebsd.zig b/lib/std/os/freebsd.zig
@@ -1,5 +1,3 @@
const std = @import("../std.zig");
-const builtin = @import("builtin");
-pub const is_the_target = builtin.os == .freebsd;
pub usingnamespace std.c;
pub usingnamespace @import("bits.zig");
diff --git a/lib/std/os/linux.zig b/lib/std/os/linux.zig
@@ -13,7 +13,6 @@ const elf = std.elf;
const vdso = @import("linux/vdso.zig");
const dl = @import("../dynamic_library.zig");
-pub const is_the_target = builtin.os == .linux;
pub usingnamespace switch (builtin.arch) {
.x86_64 => @import("linux/x86_64.zig"),
.aarch64 => @import("linux/arm64.zig"),
@@ -1079,7 +1078,7 @@ pub fn io_uring_register(fd: i32, opcode: u32, arg: ?*const c_void, nr_args: u32
}
test "" {
- if (is_the_target) {
+ if (builtin.os == .linux) {
_ = @import("linux/test.zig");
}
}
diff --git a/lib/std/os/netbsd.zig b/lib/std/os/netbsd.zig
@@ -1,5 +1,3 @@
-const builtin = @import("builtin");
const std = @import("../std.zig");
-pub const is_the_target = builtin.os == .netbsd;
pub usingnamespace std.c;
pub usingnamespace @import("bits.zig");
diff --git a/lib/std/os/test.zig b/lib/std/os/test.zig
@@ -53,7 +53,7 @@ test "std.Thread.getCurrentId" {
thread.wait();
if (Thread.use_pthreads) {
expect(thread_current_id == thread_id);
- } else if (os.windows.is_the_target) {
+ } else if (builtin.os == .windows) {
expect(Thread.getCurrentId() != thread_current_id);
} else {
// If the thread completes very quickly, then thread_id can be 0. See the
@@ -212,7 +212,7 @@ test "dl_iterate_phdr" {
}
test "gethostname" {
- if (os.windows.is_the_target)
+ if (builtin.os == .windows)
return error.SkipZigTest;
var buf: [os.HOST_NAME_MAX]u8 = undefined;
@@ -221,7 +221,7 @@ test "gethostname" {
}
test "pipe" {
- if (os.windows.is_the_target)
+ if (builtin.os == .windows)
return error.SkipZigTest;
var fds = try os.pipe();
diff --git a/lib/std/os/uefi.zig b/lib/std/os/uefi.zig
@@ -1,16 +1,15 @@
/// A protocol is an interface identified by a GUID.
pub const protocols = @import("uefi/protocols.zig");
+
/// Status codes returned by EFI interfaces
pub const status = @import("uefi/status.zig");
pub const tables = @import("uefi/tables.zig");
const fmt = @import("std").fmt;
-const builtin = @import("builtin");
-pub const is_the_target = builtin.os == .uefi;
-
/// The EFI image's handle that is passed to its entry point.
pub var handle: Handle = undefined;
+
/// A pointer to the EFI System Table that is passed to the EFI image's entry point.
pub var system_table: *tables.SystemTable = undefined;
@@ -50,26 +49,35 @@ pub const Handle = *@OpaqueType();
pub const Time = extern struct {
/// 1900 - 9999
year: u16,
+
/// 1 - 12
month: u8,
+
/// 1 - 31
day: u8,
+
/// 0 - 23
hour: u8,
+
/// 0 - 59
minute: u8,
+
/// 0 - 59
second: u8,
_pad1: u8,
+
/// 0 - 999999999
nanosecond: u32,
+
/// The time's offset in minutes from UTC.
/// Allowed values are -1440 to 1440 or unspecified_timezone
timezone: i16,
daylight: packed struct {
_pad1: u6,
+
/// If true, the time has been adjusted for daylight savings time.
in_daylight: bool,
+
/// If true, the time is affected by daylight savings time.
adjust_daylight: bool,
},
@@ -83,8 +91,10 @@ pub const Time = extern struct {
pub const TimeCapabilities = extern struct {
/// Resolution in Hz
resolution: u32,
+
/// Accuracy in an error rate of 1e-6 parts per million.
accuracy: u32,
+
/// If true, a time set operation clears the device's time below the resolution level.
sets_to_zero: bool,
};
diff --git a/lib/std/os/wasi.zig b/lib/std/os/wasi.zig
@@ -1,10 +1,8 @@
// Based on https://github.com/CraneStation/wasi-sysroot/blob/wasi/libc-bottom-half/headers/public/wasi/core.h
// and https://github.com/WebAssembly/WASI/blob/master/design/WASI-core.md
-const builtin = @import("builtin");
const std = @import("std");
const assert = std.debug.assert;
-pub const is_the_target = builtin.os == .wasi;
pub usingnamespace @import("bits.zig");
comptime {
diff --git a/lib/std/os/windows.zig b/lib/std/os/windows.zig
@@ -11,7 +11,6 @@ const assert = std.debug.assert;
const math = std.math;
const maxInt = std.math.maxInt;
-pub const is_the_target = builtin.os == .windows;
pub const advapi32 = @import("windows/advapi32.zig");
pub const kernel32 = @import("windows/kernel32.zig");
pub const ntdll = @import("windows/ntdll.zig");
@@ -22,32 +21,6 @@ pub usingnamespace @import("windows/bits.zig");
pub const self_process_handle = @intToPtr(HANDLE, maxInt(usize));
-/// `builtin` is missing `subsystem` when the subsystem is automatically detected,
-/// so Zig standard library has the subsystem detection logic here. This should generally be
-/// used rather than `builtin.subsystem`.
-/// On non-windows targets, this is `null`.
-pub const subsystem: ?builtin.SubSystem = blk: {
- if (@hasDecl(builtin, "subsystem")) break :blk builtin.subsystem;
- switch (builtin.os) {
- .windows => {
- if (builtin.is_test) {
- break :blk builtin.SubSystem.Console;
- }
- const root = @import("root");
- if (@hasDecl(root, "WinMain") or
- @hasDecl(root, "wWinMain") or
- @hasDecl(root, "WinMainCRTStartup") or
- @hasDecl(root, "wWinMainCRTStartup"))
- {
- break :blk builtin.SubSystem.Windows;
- } else {
- break :blk builtin.SubSystem.Console;
- }
- },
- else => break :blk null,
- }
-};
-
pub const CreateFileError = error{
SharingViolation,
PathAlreadyExists,
diff --git a/lib/std/process.zig b/lib/std/process.zig
@@ -39,7 +39,7 @@ pub fn getEnvMap(allocator: *Allocator) !BufMap {
var result = BufMap.init(allocator);
errdefer result.deinit();
- if (os.windows.is_the_target) {
+ if (builtin.os == .windows) {
const ptr = try os.windows.GetEnvironmentStringsW();
defer os.windows.FreeEnvironmentStringsW(ptr);
@@ -129,7 +129,7 @@ pub const GetEnvVarOwnedError = error{
/// Caller must free returned memory.
/// TODO make this go through libc when we have it
pub fn getEnvVarOwned(allocator: *mem.Allocator, key: []const u8) GetEnvVarOwnedError![]u8 {
- if (os.windows.is_the_target) {
+ if (builtin.os == .windows) {
const key_with_null = try std.unicode.utf8ToUtf16LeWithNull(allocator, key);
defer allocator.free(key_with_null);
diff --git a/lib/std/special/panic.zig b/lib/std/special/panic.zig
@@ -1,31 +0,0 @@
-// This file is the default panic handler if the root source file does not
-// have a `pub fn panic`.
-// If this file wants to import other files *by name*, support for that would
-// have to be added in the compiler.
-
-const builtin = @import("builtin");
-const std = @import("std");
-
-pub fn panic(msg: []const u8, error_return_trace: ?*builtin.StackTrace) noreturn {
- @setCold(true);
- switch (builtin.os) {
- .freestanding => {
- while (true) {
- @breakpoint();
- }
- },
- .wasi => {
- std.debug.warn("{}", msg);
- _ = std.os.wasi.proc_raise(std.os.wasi.SIGABRT);
- unreachable;
- },
- .uefi => {
- // TODO look into using the debug info and logging helpful messages
- std.os.abort();
- },
- else => {
- const first_trace_addr = @returnAddress();
- std.debug.panicExtra(error_return_trace, first_trace_addr, "{}", msg);
- },
- }
-}
diff --git a/lib/std/std.zig b/lib/std/std.zig
@@ -22,11 +22,13 @@ pub const SpinLock = @import("spinlock.zig").SpinLock;
pub const StaticallyInitializedMutex = @import("statically_initialized_mutex.zig").StaticallyInitializedMutex;
pub const StringHashMap = @import("hash_map.zig").StringHashMap;
pub const TailQueue = @import("linked_list.zig").TailQueue;
+pub const Target = @import("target.zig").Target;
pub const Thread = @import("thread.zig").Thread;
pub const atomic = @import("atomic.zig");
pub const base64 = @import("base64.zig");
pub const build = @import("build.zig");
+pub const builtin = @import("builtin.zig");
pub const c = @import("c.zig");
pub const coff = @import("coff.zig");
pub const crypto = @import("crypto.zig");
@@ -63,6 +65,6 @@ pub const unicode = @import("unicode.zig");
pub const valgrind = @import("valgrind.zig");
pub const zig = @import("zig.zig");
-comptime {
+test "" {
meta.refAllDecls(@This());
}
diff --git a/lib/std/target.zig b/lib/std/target.zig
@@ -0,0 +1,617 @@
+const std = @import("std.zig");
+const builtin = std.builtin;
+
+/// TODO Nearly all the functions in this namespace would be
+/// better off if https://github.com/ziglang/zig/issues/425
+/// was solved.
+pub const Target = union(enum) {
+ Native: void,
+ Cross: Cross,
+
+ pub const Os = enum {
+ freestanding,
+ ananas,
+ cloudabi,
+ dragonfly,
+ freebsd,
+ fuchsia,
+ ios,
+ kfreebsd,
+ linux,
+ lv2,
+ macosx,
+ netbsd,
+ openbsd,
+ solaris,
+ windows,
+ haiku,
+ minix,
+ rtems,
+ nacl,
+ cnk,
+ aix,
+ cuda,
+ nvcl,
+ amdhsa,
+ ps4,
+ elfiamcu,
+ tvos,
+ watchos,
+ mesa3d,
+ contiki,
+ amdpal,
+ hermit,
+ hurd,
+ wasi,
+ emscripten,
+ zen,
+ uefi,
+ };
+
+ pub const Arch = union(enum) {
+ arm: Arm32,
+ armeb: Arm32,
+ aarch64: Arm64,
+ aarch64_be: Arm64,
+ aarch64_32: Arm64,
+ arc,
+ avr,
+ bpfel,
+ bpfeb,
+ hexagon,
+ mips,
+ mipsel,
+ mips64,
+ mips64el,
+ msp430,
+ powerpc,
+ powerpc64,
+ powerpc64le,
+ r600,
+ amdgcn,
+ riscv32,
+ riscv64,
+ sparc,
+ sparcv9,
+ sparcel,
+ s390x,
+ tce,
+ tcele,
+ thumb: Arm32,
+ thumbeb: Arm32,
+ i386,
+ x86_64,
+ xcore,
+ nvptx,
+ nvptx64,
+ le32,
+ le64,
+ amdil,
+ amdil64,
+ hsail,
+ hsail64,
+ spir,
+ spir64,
+ kalimba: Kalimba,
+ shave,
+ lanai,
+ wasm32,
+ wasm64,
+ renderscript32,
+ renderscript64,
+
+ pub const Arm32 = enum {
+ v8_5a,
+ v8_4a,
+ v8_3a,
+ v8_2a,
+ v8_1a,
+ v8,
+ v8r,
+ v8m_baseline,
+ v8m_mainline,
+ v8_1m_mainline,
+ v7,
+ v7em,
+ v7m,
+ v7s,
+ v7k,
+ v7ve,
+ v6,
+ v6m,
+ v6k,
+ v6t2,
+ v5,
+ v5te,
+ v4t,
+ };
+ pub const Arm64 = enum {
+ v8_5a,
+ v8_4a,
+ v8_3a,
+ v8_2a,
+ v8_1a,
+ v8,
+ v8r,
+ v8m_baseline,
+ v8m_mainline,
+ };
+ pub const Kalimba = enum {
+ v5,
+ v4,
+ v3,
+ };
+ pub const Mips = enum {
+ r6,
+ };
+ };
+
+ pub const Abi = enum {
+ none,
+ gnu,
+ gnuabin32,
+ gnuabi64,
+ gnueabi,
+ gnueabihf,
+ gnux32,
+ code16,
+ eabi,
+ eabihf,
+ elfv1,
+ elfv2,
+ android,
+ musl,
+ musleabi,
+ musleabihf,
+ msvc,
+ itanium,
+ cygnus,
+ coreclr,
+ simulator,
+ macabi,
+ };
+
+ pub const ObjectFormat = enum {
+ unknown,
+ coff,
+ elf,
+ macho,
+ wasm,
+ };
+
+ pub const SubSystem = enum {
+ Console,
+ Windows,
+ Posix,
+ Native,
+ EfiApplication,
+ EfiBootServiceDriver,
+ EfiRom,
+ EfiRuntimeDriver,
+ };
+
+ pub const Cross = struct {
+ arch: Arch,
+ os: Os,
+ abi: Abi,
+ };
+
+ pub const current = Target{
+ .Cross = Cross{
+ .arch = builtin.arch,
+ .os = builtin.os,
+ .abi = builtin.abi,
+ },
+ };
+
+ pub fn zigTriple(self: Target, allocator: *std.mem.Allocator) ![]u8 {
+ return std.fmt.allocPrint(
+ allocator,
+ "{}{}-{}-{}",
+ @tagName(self.getArch()),
+ Target.archSubArchName(self.getArch()),
+ @tagName(self.getOs()),
+ @tagName(self.getAbi()),
+ );
+ }
+
+ pub fn allocDescription(self: Target, allocator: *std.mem.Allocator) ![]u8 {
+ // TODO is there anything else worthy of the description that is not
+ // already captured in the triple?
+ return self.zigTriple(allocator);
+ }
+
+ pub fn zigTripleNoSubArch(self: Target, allocator: *std.mem.Allocator) ![]u8 {
+ return std.fmt.allocPrint(
+ allocator,
+ "{}-{}-{}",
+ @tagName(self.getArch()),
+ @tagName(self.getOs()),
+ @tagName(self.getAbi()),
+ );
+ }
+
+ pub fn linuxTriple(self: Target, allocator: *std.mem.Allocator) ![]u8 {
+ return std.fmt.allocPrint(
+ allocator,
+ "{}-{}-{}",
+ @tagName(self.getArch()),
+ @tagName(self.getOs()),
+ @tagName(self.getAbi()),
+ );
+ }
+
+ pub fn parse(text: []const u8) !Target {
+ var it = mem.separate(text, "-");
+ const arch_name = it.next() orelse return error.MissingArchitecture;
+ const os_name = it.next() orelse return error.MissingOperatingSystem;
+ const abi_name = it.next();
+
+ var cross = Cross{
+ .arch = try parseArchSub(arch_name),
+ .os = try parseOs(os_name),
+ .abi = undefined,
+ };
+ cross.abi = if (abi_name) |n| try parseAbi(n) else defaultAbi(cross.arch, cross.os);
+ return Target{ .Cross = cross };
+ }
+
+ pub fn defaultAbi(arch: Arch, target_os: Os) Abi {
+ switch (arch) {
+ .wasm32, .wasm64 => return .musl,
+ else => {},
+ }
+ switch (target_os) {
+ .freestanding,
+ .ananas,
+ .cloudabi,
+ .dragonfly,
+ .lv2,
+ .solaris,
+ .haiku,
+ .minix,
+ .rtems,
+ .nacl,
+ .cnk,
+ .aix,
+ .cuda,
+ .nvcl,
+ .amdhsa,
+ .ps4,
+ .elfiamcu,
+ .mesa3d,
+ .contiki,
+ .amdpal,
+ .zen,
+ .hermit,
+ => return .eabi,
+ .openbsd,
+ .macosx,
+ .freebsd,
+ .ios,
+ .tvos,
+ .watchos,
+ .fuchsia,
+ .kfreebsd,
+ .netbsd,
+ .hurd,
+ => return .gnu,
+ .windows,
+ .uefi,
+ => return .msvc,
+ .linux,
+ .wasi,
+ .emscripten,
+ => return .musl,
+ }
+ }
+
+ pub const ParseArchSubError = error{
+ UnknownArchitecture,
+ UnknownSubArchitecture,
+ };
+
+ pub fn parseArchSub(text: []const u8) ParseArchSubError!Arch {
+ const info = @typeInfo(Arch);
+ inline for (info.Union.fields) |field| {
+ if (mem.eql(u8, text, field.name)) {
+ if (field.field_type == void) {
+ return (Arch)(@field(Arch, field.name));
+ } else {
+ const sub_info = @typeInfo(field.field_type);
+ inline for (sub_info.Enum.fields) |sub_field| {
+ const combined = field.name ++ sub_field.name;
+ if (mem.eql(u8, text, combined)) {
+ return @unionInit(Arch, field.name, @field(field.field_type, sub_field.name));
+ }
+ }
+ return error.UnknownSubArchitecture;
+ }
+ }
+ }
+ return error.UnknownArchitecture;
+ }
+
+ pub fn parseOs(text: []const u8) !Os {
+ const info = @typeInfo(Os);
+ inline for (info.Enum.fields) |field| {
+ if (mem.eql(u8, text, field.name)) {
+ return @field(Os, field.name);
+ }
+ }
+ return error.UnknownOperatingSystem;
+ }
+
+ pub fn parseAbi(text: []const u8) !Abi {
+ const info = @typeInfo(Abi);
+ inline for (info.Enum.fields) |field| {
+ if (mem.eql(u8, text, field.name)) {
+ return @field(Abi, field.name);
+ }
+ }
+ return error.UnknownApplicationBinaryInterface;
+ }
+
+ fn archSubArchName(arch: Arch) []const u8 {
+ return switch (arch) {
+ .arm => |sub| @tagName(sub),
+ .armeb => |sub| @tagName(sub),
+ .thumb => |sub| @tagName(sub),
+ .thumbeb => |sub| @tagName(sub),
+ .aarch64 => |sub| @tagName(sub),
+ .aarch64_be => |sub| @tagName(sub),
+ .kalimba => |sub| @tagName(sub),
+ else => "",
+ };
+ }
+
+ pub fn subArchName(self: Target) []const u8 {
+ switch (self) {
+ .Native => return archSubArchName(builtin.arch),
+ .Cross => |cross| return archSubArchName(cross.arch),
+ }
+ }
+
+ pub fn oFileExt(self: Target) []const u8 {
+ return switch (self.getAbi()) {
+ .msvc => ".obj",
+ else => ".o",
+ };
+ }
+
+ pub fn exeFileExt(self: Target) []const u8 {
+ if (self.isWindows()) {
+ return ".exe";
+ } else if (self.isUefi()) {
+ return ".efi";
+ } else if (self.isWasm()) {
+ return ".wasm";
+ } else {
+ return "";
+ }
+ }
+
+ pub fn staticLibSuffix(self: Target) []const u8 {
+ if (self.isWasm()) {
+ return ".wasm";
+ }
+ switch (self.getAbi()) {
+ .msvc => return ".lib",
+ else => return ".a",
+ }
+ }
+
+ pub fn dynamicLibSuffix(self: Target) []const u8 {
+ if (self.isDarwin()) {
+ return ".dylib";
+ }
+ switch (self.getOs()) {
+ .windows => return ".dll",
+ else => return ".so",
+ }
+ }
+
+ pub fn libPrefix(self: Target) []const u8 {
+ if (self.isWasm()) {
+ return "";
+ }
+ switch (self.getAbi()) {
+ .msvc => return "",
+ else => return "lib",
+ }
+ }
+
+ pub fn getOs(self: Target) Os {
+ return switch (self) {
+ .Native => builtin.os,
+ .Cross => |t| t.os,
+ };
+ }
+
+ pub fn getArch(self: Target) Arch {
+ switch (self) {
+ .Native => return builtin.arch,
+ .Cross => |t| return t.arch,
+ }
+ }
+
+ pub fn getAbi(self: Target) Abi {
+ switch (self) {
+ .Native => return builtin.abi,
+ .Cross => |t| return t.abi,
+ }
+ }
+
+ pub fn isMinGW(self: Target) bool {
+ return self.isWindows() and self.isGnu();
+ }
+
+ pub fn isGnu(self: Target) bool {
+ return switch (self.getAbi()) {
+ .gnu, .gnuabin32, .gnuabi64, .gnueabi, .gnueabihf, .gnux32 => true,
+ else => false,
+ };
+ }
+
+ pub fn isDarwin(self: Target) bool {
+ return switch (self.getOs()) {
+ .ios, .macosx, .watchos, .tvos => true,
+ else => false,
+ };
+ }
+
+ pub fn isWindows(self: Target) bool {
+ return switch (self.getOs()) {
+ .windows => true,
+ else => false,
+ };
+ }
+
+ pub fn isLinux(self: Target) bool {
+ return switch (self.getOs()) {
+ .linux => true,
+ else => false,
+ };
+ }
+
+ pub fn isUefi(self: Target) bool {
+ return switch (self.getOs()) {
+ .uefi => true,
+ else => false,
+ };
+ }
+
+ pub fn isWasm(self: Target) bool {
+ return switch (self.getArch()) {
+ .wasm32, .wasm64 => true,
+ else => false,
+ };
+ }
+
+ pub fn isFreeBSD(self: Target) bool {
+ return switch (self.getOs()) {
+ .freebsd => true,
+ else => false,
+ };
+ }
+
+ pub fn isNetBSD(self: Target) bool {
+ return switch (self.getOs()) {
+ .netbsd => true,
+ else => false,
+ };
+ }
+
+ pub fn wantSharedLibSymLinks(self: Target) bool {
+ return !self.isWindows();
+ }
+
+ pub fn osRequiresLibC(self: Target) bool {
+ return self.isDarwin() or self.isFreeBSD() or self.isNetBSD();
+ }
+
+ pub fn getArchPtrBitWidth(self: Target) u32 {
+ switch (self.getArch()) {
+ .avr,
+ .msp430,
+ => return 16,
+
+ .arc,
+ .arm,
+ .armeb,
+ .hexagon,
+ .le32,
+ .mips,
+ .mipsel,
+ .powerpc,
+ .r600,
+ .riscv32,
+ .sparc,
+ .sparcel,
+ .tce,
+ .tcele,
+ .thumb,
+ .thumbeb,
+ .i386,
+ .xcore,
+ .nvptx,
+ .amdil,
+ .hsail,
+ .spir,
+ .kalimba,
+ .shave,
+ .lanai,
+ .wasm32,
+ .renderscript32,
+ .aarch64_32,
+ => return 32,
+
+ .aarch64,
+ .aarch64_be,
+ .mips64,
+ .mips64el,
+ .powerpc64,
+ .powerpc64le,
+ .riscv64,
+ .x86_64,
+ .nvptx64,
+ .le64,
+ .amdil64,
+ .hsail64,
+ .spir64,
+ .wasm64,
+ .renderscript64,
+ .amdgcn,
+ .bpfel,
+ .bpfeb,
+ .sparcv9,
+ .s390x,
+ => return 64,
+ }
+ }
+
+ pub const Executor = union(enum) {
+ native,
+ qemu: []const u8,
+ wine: []const u8,
+ unavailable,
+ };
+
+ pub fn getExternalExecutor(self: Target) Executor {
+ if (@TagType(Target)(self) == .Native) return .native;
+
+ // If the target OS matches the host OS, we can use QEMU to emulate a foreign architecture.
+ if (self.getOs() == builtin.os) {
+ return switch (self.getArch()) {
+ .aarch64 => Executor{ .qemu = "qemu-aarch64" },
+ .aarch64_be => Executor{ .qemu = "qemu-aarch64_be" },
+ .arm => Executor{ .qemu = "qemu-arm" },
+ .armeb => Executor{ .qemu = "qemu-armeb" },
+ .i386 => Executor{ .qemu = "qemu-i386" },
+ .mips => Executor{ .qemu = "qemu-mips" },
+ .mipsel => Executor{ .qemu = "qemu-mipsel" },
+ .mips64 => Executor{ .qemu = "qemu-mips64" },
+ .mips64el => Executor{ .qemu = "qemu-mips64el" },
+ .powerpc => Executor{ .qemu = "qemu-ppc" },
+ .powerpc64 => Executor{ .qemu = "qemu-ppc64" },
+ .powerpc64le => Executor{ .qemu = "qemu-ppc64le" },
+ .riscv32 => Executor{ .qemu = "qemu-riscv32" },
+ .riscv64 => Executor{ .qemu = "qemu-riscv64" },
+ .s390x => Executor{ .qemu = "qemu-s390x" },
+ .sparc => Executor{ .qemu = "qemu-sparc" },
+ .x86_64 => Executor{ .qemu = "qemu-x86_64" },
+ else => return .unavailable,
+ };
+ }
+
+ if (self.isWindows()) {
+ switch (self.getArchPtrBitWidth()) {
+ 32 => return Executor{ .wine = "wine" },
+ 64 => return Executor{ .wine = "wine64" },
+ else => return .unavailable,
+ }
+ }
+
+ return .unavailable;
+ }
+};
diff --git a/lib/std/thread.zig b/lib/std/thread.zig
@@ -9,7 +9,7 @@ const assert = std.debug.assert;
pub const Thread = struct {
data: Data,
- pub const use_pthreads = !windows.is_the_target and builtin.link_libc;
+ pub const use_pthreads = builtin.os != .windows and builtin.link_libc;
/// Represents a kernel thread handle.
/// May be an integer or a pointer depending on the platform.
@@ -309,7 +309,7 @@ pub const Thread = struct {
os.EINVAL => unreachable,
else => return os.unexpectedErrno(@intCast(usize, err)),
}
- } else if (os.linux.is_the_target) {
+ } else if (builtin.os == .linux) {
var flags: u32 = os.CLONE_VM | os.CLONE_FS | os.CLONE_FILES | os.CLONE_SIGHAND |
os.CLONE_THREAD | os.CLONE_SYSVSEM | os.CLONE_PARENT_SETTID | os.CLONE_CHILD_CLEARTID |
os.CLONE_DETACHED;
@@ -342,18 +342,18 @@ pub const Thread = struct {
};
pub fn cpuCount() CpuCountError!usize {
- if (os.linux.is_the_target) {
+ if (builtin.os == .linux) {
const cpu_set = try os.sched_getaffinity(0);
return usize(os.CPU_COUNT(cpu_set)); // TODO should not need this usize cast
}
- if (os.windows.is_the_target) {
+ if (builtin.os == .windows) {
var system_info: windows.SYSTEM_INFO = undefined;
windows.kernel32.GetSystemInfo(&system_info);
return @intCast(usize, system_info.dwNumberOfProcessors);
}
var count: c_int = undefined;
var count_len: usize = @sizeOf(c_int);
- const name = if (os.darwin.is_the_target) c"hw.logicalcpu" else c"hw.ncpu";
+ const name = if (comptime std.Target.current.isDarwin()) c"hw.logicalcpu" else c"hw.ncpu";
os.sysctlbynameC(name, &count, &count_len, null, 0) catch |err| switch (err) {
error.NameTooLong => unreachable,
else => |e| return e,
diff --git a/lib/std/time.zig b/lib/std/time.zig
@@ -9,7 +9,7 @@ pub const epoch = @import("time/epoch.zig");
/// Spurious wakeups are possible and no precision of timing is guaranteed.
pub fn sleep(nanoseconds: u64) void {
- if (os.windows.is_the_target) {
+ if (builtin.os == .windows) {
const ns_per_ms = ns_per_s / ms_per_s;
const big_ms_from_ns = nanoseconds / ns_per_ms;
const ms = math.cast(os.windows.DWORD, big_ms_from_ns) catch math.maxInt(os.windows.DWORD);
@@ -30,7 +30,7 @@ pub fn timestamp() u64 {
/// Get the posix timestamp, UTC, in milliseconds
/// TODO audit this function. is it possible to return an error?
pub fn milliTimestamp() u64 {
- if (os.windows.is_the_target) {
+ if (builtin.os == .windows) {
//FileTime has a granularity of 100 nanoseconds
// and uses the NTFS/Windows epoch
var ft: os.windows.FILETIME = undefined;
@@ -41,7 +41,7 @@ pub fn milliTimestamp() u64 {
const ft64 = (u64(ft.dwHighDateTime) << 32) | ft.dwLowDateTime;
return @divFloor(ft64, hns_per_ms) - -epoch_adj;
}
- if (os.wasi.is_the_target and !builtin.link_libc) {
+ if (builtin.os == .wasi and !builtin.link_libc) {
var ns: os.wasi.timestamp_t = undefined;
// TODO: Verify that precision is ignored
@@ -51,7 +51,7 @@ pub fn milliTimestamp() u64 {
const ns_per_ms = 1000;
return @divFloor(ns, ns_per_ms);
}
- if (os.darwin.is_the_target) {
+ if (comptime std.Target.current.isDarwin()) {
var tv: os.darwin.timeval = undefined;
var err = os.darwin.gettimeofday(&tv, null);
assert(err == 0);
@@ -126,11 +126,11 @@ pub const Timer = struct {
pub fn start() Error!Timer {
var self: Timer = undefined;
- if (os.windows.is_the_target) {
+ if (builtin.os == .windows) {
self.frequency = os.windows.QueryPerformanceFrequency();
self.resolution = @divFloor(ns_per_s, self.frequency);
self.start_time = os.windows.QueryPerformanceCounter();
- } else if (os.darwin.is_the_target) {
+ } else if (comptime std.Target.current.isDarwin()) {
os.darwin.mach_timebase_info(&self.frequency);
self.resolution = @divFloor(self.frequency.numer, self.frequency.denom);
self.start_time = os.darwin.mach_absolute_time();
@@ -154,10 +154,10 @@ pub const Timer = struct {
/// Reads the timer value since start or the last reset in nanoseconds
pub fn read(self: *Timer) u64 {
var clock = clockNative() - self.start_time;
- if (os.windows.is_the_target) {
+ if (builtin.os == .windows) {
return @divFloor(clock * ns_per_s, self.frequency);
}
- if (os.darwin.is_the_target) {
+ if (comptime std.Target.current.isDarwin()) {
return @divFloor(clock * self.frequency.numer, self.frequency.denom);
}
return clock;
@@ -177,10 +177,10 @@ pub const Timer = struct {
}
fn clockNative() u64 {
- if (os.windows.is_the_target) {
+ if (builtin.os == .windows) {
return os.windows.QueryPerformanceCounter();
}
- if (os.darwin.is_the_target) {
+ if (comptime std.Target.current.isDarwin()) {
return os.darwin.mach_absolute_time();
}
var ts: os.timespec = undefined;
diff --git a/src-self-hosted/target.zig b/src-self-hosted/target.zig
@@ -3,6 +3,8 @@ const builtin = @import("builtin");
const llvm = @import("llvm.zig");
const CInt = @import("c_int.zig").CInt;
+// TODO delete this file and use std.Target
+
pub const FloatAbi = enum {
Hard,
Soft,
diff --git a/src/all_types.hpp b/src/all_types.hpp
@@ -1930,7 +1930,6 @@ struct CodeGen {
ZigList<ZigType *> type_resolve_stack;
ZigPackage *std_package;
- ZigPackage *panic_package;
ZigPackage *test_runner_package;
ZigPackage *compile_var_package;
ZigType *compile_var_import;
@@ -2006,7 +2005,6 @@ struct CodeGen {
ZigFn *cur_fn;
ZigFn *main_fn;
ZigFn *panic_fn;
- TldFn *panic_tld_fn;
ZigFn *largest_frame_fn;
@@ -2030,7 +2028,6 @@ struct CodeGen {
bool have_winmain;
bool have_winmain_crt_startup;
bool have_dllmain_crt_startup;
- bool have_pub_panic;
bool have_err_ret_tracing;
bool c_want_stdint;
bool c_want_stdbool;
diff --git a/src/analyze.cpp b/src/analyze.cpp
@@ -3232,21 +3232,6 @@ static bool scope_is_root_decls(Scope *scope) {
zig_unreachable();
}
-void typecheck_panic_fn(CodeGen *g, TldFn *tld_fn, ZigFn *panic_fn) {
- ConstExprValue *panic_fn_type_val = get_builtin_value(g, "PanicFn");
- assert(panic_fn_type_val != nullptr);
- assert(panic_fn_type_val->type->id == ZigTypeIdMetaType);
- ZigType *panic_fn_type = panic_fn_type_val->data.x_type;
-
- AstNode *fake_decl = allocate<AstNode>(1);
- *fake_decl = *panic_fn->proto_node;
- fake_decl->type = NodeTypeSymbol;
- fake_decl->data.symbol_expr.symbol = tld_fn->base.name;
-
- // call this for the side effects of casting to panic_fn_type
- analyze_const_value(g, tld_fn->base.parent_scope, fake_decl, panic_fn_type, nullptr, UndefBad);
-}
-
ZigType *get_test_fn_type(CodeGen *g) {
if (g->test_fn_type)
return g->test_fn_type;
@@ -3356,16 +3341,9 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) {
fn_table_entry->inferred_async_node = fn_table_entry->proto_node;
}
- if (scope_is_root_decls(tld_fn->base.parent_scope) &&
- (import == g->root_import || import->data.structure.root_struct->package == g->panic_package))
- {
+ if (scope_is_root_decls(tld_fn->base.parent_scope) && import == g->root_import) {
if (g->have_pub_main && buf_eql_str(tld_fn->base.name, "main")) {
g->main_fn = fn_table_entry;
- } else if ((import->data.structure.root_struct->package == g->panic_package || g->have_pub_panic) &&
- buf_eql_str(tld_fn->base.name, "panic"))
- {
- g->panic_fn = fn_table_entry;
- g->panic_tld_fn = tld_fn;
}
}
} else if (source_node->type == NodeTypeTestDecl) {
@@ -4710,8 +4688,8 @@ ZigType *add_source_file(CodeGen *g, ZigPackage *package, Buf *resolved_path, Bu
ast_print(stderr, root_node, 0);
}
- if (source_kind == SourceKindRoot || package == g->panic_package) {
- // Look for panic and main
+ if (source_kind == SourceKindRoot) {
+ // Look for main
for (size_t decl_i = 0; decl_i < root_node->data.container_decl.decls.length; decl_i += 1) {
AstNode *top_level_decl = root_node->data.container_decl.decls.at(decl_i);
@@ -4724,8 +4702,6 @@ ZigType *add_source_file(CodeGen *g, ZigPackage *package, Buf *resolved_path, Bu
if (is_pub) {
if (buf_eql_str(proto_name, "main")) {
g->have_pub_main = true;
- } else if (buf_eql_str(proto_name, "panic")) {
- g->have_pub_panic = true;
}
}
}
@@ -8932,3 +8908,62 @@ IrInstruction *ir_create_alloca(CodeGen *g, Scope *scope, AstNode *source_node,
return &alloca_gen->base;
}
+Error analyze_import(CodeGen *g, ZigType *source_import, Buf *import_target_str,
+ ZigType **out_import, Buf **out_import_target_path, Buf *out_full_path)
+{
+ Error err;
+
+ Buf *search_dir;
+ ZigPackage *cur_scope_pkg = source_import->data.structure.root_struct->package;
+ assert(cur_scope_pkg);
+ ZigPackage *target_package;
+ auto package_entry = cur_scope_pkg->package_table.maybe_get(import_target_str);
+ SourceKind source_kind;
+ if (package_entry) {
+ target_package = package_entry->value;
+ *out_import_target_path = &target_package->root_src_path;
+ search_dir = &target_package->root_src_dir;
+ source_kind = SourceKindPkgMain;
+ } else {
+ // try it as a filename
+ target_package = cur_scope_pkg;
+ *out_import_target_path = import_target_str;
+
+ // search relative to importing file
+ search_dir = buf_alloc();
+ os_path_dirname(source_import->data.structure.root_struct->path, search_dir);
+
+ source_kind = SourceKindNonRoot;
+ }
+
+ buf_resize(out_full_path, 0);
+ os_path_join(search_dir, *out_import_target_path, out_full_path);
+
+ Buf *import_code = buf_alloc();
+ Buf *resolved_path = buf_alloc();
+
+ Buf *resolve_paths[] = { out_full_path, };
+ *resolved_path = os_path_resolve(resolve_paths, 1);
+
+ auto import_entry = g->import_table.maybe_get(resolved_path);
+ if (import_entry) {
+ *out_import = import_entry->value;
+ return ErrorNone;
+ }
+
+ if (source_kind == SourceKindNonRoot) {
+ Buf *pkg_root_src_dir = &cur_scope_pkg->root_src_dir;
+ Buf resolved_root_src_dir = os_path_resolve(&pkg_root_src_dir, 1);
+ if (!buf_starts_with_buf(resolved_path, &resolved_root_src_dir)) {
+ return ErrorImportOutsidePkgPath;
+ }
+ }
+
+ if ((err = file_fetch(g, resolved_path, import_code))) {
+ return err;
+ }
+
+ *out_import = add_source_file(g, target_package, resolved_path, import_code, source_kind);
+ return ErrorNone;
+}
+
diff --git a/src/analyze.hpp b/src/analyze.hpp
@@ -262,5 +262,7 @@ void add_async_error_notes(CodeGen *g, ErrorMsg *msg, ZigFn *fn);
IrInstruction *ir_create_alloca(CodeGen *g, Scope *scope, AstNode *source_node, ZigFn *fn,
ZigType *var_type, const char *name_hint);
+Error analyze_import(CodeGen *codegen, ZigType *source_import, Buf *import_target_str,
+ ZigType **out_import, Buf **out_import_target_path, Buf *out_full_path);
#endif
diff --git a/src/codegen.cpp b/src/codegen.cpp
@@ -8125,55 +8125,37 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
g->have_err_ret_tracing = detect_err_ret_tracing(g);
Buf *contents = buf_alloc();
-
- // NOTE: when editing this file, you may need to make modifications to the
- // cache input parameters in define_builtin_compile_vars
-
- // Modifications to this struct must be coordinated with code that does anything with
- // g->stack_trace_type. There are hard-coded references to the field indexes.
- buf_append_str(contents,
- "pub const StackTrace = struct {\n"
- " index: usize,\n"
- " instruction_addresses: []usize,\n"
- "};\n\n");
-
- buf_append_str(contents, "pub const PanicFn = fn([]const u8, ?*StackTrace) noreturn;\n\n");
+ buf_appendf(contents, "usingnamespace @import(\"std\").builtin;\n\n");
const char *cur_os = nullptr;
{
- buf_appendf(contents, "pub const Os = enum {\n");
uint32_t field_count = (uint32_t)target_os_count();
for (uint32_t i = 0; i < field_count; i += 1) {
Os os_type = target_os_enum(i);
const char *name = target_os_name(os_type);
- buf_appendf(contents, " %s,\n", name);
if (os_type == g->zig_target->os) {
g->target_os_index = i;
cur_os = name;
}
}
- buf_appendf(contents, "};\n\n");
}
assert(cur_os != nullptr);
const char *cur_arch = nullptr;
{
- buf_appendf(contents, "pub const Arch = union(enum) {\n");
uint32_t field_count = (uint32_t)target_arch_count();
for (uint32_t arch_i = 0; arch_i < field_count; arch_i += 1) {
ZigLLVM_ArchType arch = target_arch_enum(arch_i);
const char *arch_name = target_arch_name(arch);
SubArchList sub_arch_list = target_subarch_list(arch);
if (sub_arch_list == SubArchListNone) {
- buf_appendf(contents, " %s,\n", arch_name);
if (arch == g->zig_target->arch) {
g->target_arch_index = arch_i;
cur_arch = buf_ptr(buf_sprintf("Arch.%s", arch_name));
}
} else {
const char *sub_arch_list_name = target_subarch_list_name(sub_arch_list);
- buf_appendf(contents, " %s: %s,\n", arch_name, sub_arch_list_name);
if (arch == g->zig_target->arch) {
size_t sub_count = target_subarch_count(sub_arch_list);
for (size_t sub_i = 0; sub_i < sub_count; sub_i += 1) {
@@ -8187,50 +8169,30 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
}
}
}
-
- uint32_t list_count = target_subarch_list_count();
- // start at index 1 to skip None
- for (uint32_t list_i = 1; list_i < list_count; list_i += 1) {
- SubArchList sub_arch_list = target_subarch_list_enum(list_i);
- const char *subarch_list_name = target_subarch_list_name(sub_arch_list);
- buf_appendf(contents, " pub const %s = enum {\n", subarch_list_name);
- size_t sub_count = target_subarch_count(sub_arch_list);
- for (size_t sub_i = 0; sub_i < sub_count; sub_i += 1) {
- ZigLLVM_SubArchType sub = target_subarch_enum(sub_arch_list, sub_i);
- buf_appendf(contents, " %s,\n", target_subarch_name(sub));
- }
- buf_appendf(contents, " };\n");
- }
- buf_appendf(contents, "};\n\n");
}
assert(cur_arch != nullptr);
const char *cur_abi = nullptr;
{
- buf_appendf(contents, "pub const Abi = enum {\n");
uint32_t field_count = (uint32_t)target_abi_count();
for (uint32_t i = 0; i < field_count; i += 1) {
ZigLLVM_EnvironmentType abi = target_abi_enum(i);
const char *name = target_abi_name(abi);
- buf_appendf(contents, " %s,\n", name);
if (abi == g->zig_target->abi) {
g->target_abi_index = i;
cur_abi = name;
}
}
- buf_appendf(contents, "};\n\n");
}
assert(cur_abi != nullptr);
const char *cur_obj_fmt = nullptr;
{
- buf_appendf(contents, "pub const ObjectFormat = enum {\n");
uint32_t field_count = (uint32_t)target_oformat_count();
for (uint32_t i = 0; i < field_count; i += 1) {
ZigLLVM_ObjectFormatType oformat = target_oformat_enum(i);
const char *name = target_oformat_name(oformat);
- buf_appendf(contents, " %s,\n", name);
ZigLLVM_ObjectFormatType target_oformat = target_object_format(g->zig_target);
if (oformat == target_oformat) {
@@ -8239,311 +8201,39 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
}
}
- buf_appendf(contents, "};\n\n");
}
assert(cur_obj_fmt != nullptr);
- {
- buf_appendf(contents, "pub const GlobalLinkage = enum {\n");
- uint32_t field_count = array_length(global_linkage_values);
- for (uint32_t i = 0; i < field_count; i += 1) {
- const GlobalLinkageValue *value = &global_linkage_values[i];
- buf_appendf(contents, " %s,\n", value->name);
- }
- buf_appendf(contents, "};\n\n");
- }
- {
- buf_appendf(contents,
- "pub const AtomicOrder = enum {\n"
- " Unordered,\n"
- " Monotonic,\n"
- " Acquire,\n"
- " Release,\n"
- " AcqRel,\n"
- " SeqCst,\n"
- "};\n\n");
- }
- {
- buf_appendf(contents,
- "pub const AtomicRmwOp = enum {\n"
- " Xchg,\n"
- " Add,\n"
- " Sub,\n"
- " And,\n"
- " Nand,\n"
- " Or,\n"
- " Xor,\n"
- " Max,\n"
- " Min,\n"
- "};\n\n");
- }
- {
- buf_appendf(contents,
- "pub const Mode = enum {\n"
- " Debug,\n"
- " ReleaseSafe,\n"
- " ReleaseFast,\n"
- " ReleaseSmall,\n"
- "};\n\n");
- }
- {
- buf_appendf(contents, "pub const TypeId = enum {\n");
- size_t field_count = type_id_len();
- for (size_t i = 0; i < field_count; i += 1) {
- const ZigTypeId id = type_id_at_index(i);
- buf_appendf(contents, " %s,\n", type_id_name(id));
- }
- buf_appendf(contents, "};\n\n");
- }
- {
- buf_appendf(contents,
- "pub const TypeInfo = union(TypeId) {\n"
- " Type: void,\n"
- " Void: void,\n"
- " Bool: void,\n"
- " NoReturn: void,\n"
- " Int: Int,\n"
- " Float: Float,\n"
- " Pointer: Pointer,\n"
- " Array: Array,\n"
- " Struct: Struct,\n"
- " ComptimeFloat: void,\n"
- " ComptimeInt: void,\n"
- " Undefined: void,\n"
- " Null: void,\n"
- " Optional: Optional,\n"
- " ErrorUnion: ErrorUnion,\n"
- " ErrorSet: ErrorSet,\n"
- " Enum: Enum,\n"
- " Union: Union,\n"
- " Fn: Fn,\n"
- " BoundFn: Fn,\n"
- " ArgTuple: void,\n"
- " Opaque: void,\n"
- " Frame: void,\n"
- " AnyFrame: AnyFrame,\n"
- " Vector: Vector,\n"
- " EnumLiteral: void,\n"
- "\n\n"
- " pub const Int = struct {\n"
- " is_signed: bool,\n"
- " bits: comptime_int,\n"
- " };\n"
- "\n"
- " pub const Float = struct {\n"
- " bits: comptime_int,\n"
- " };\n"
- "\n"
- " pub const Pointer = struct {\n"
- " size: Size,\n"
- " is_const: bool,\n"
- " is_volatile: bool,\n"
- " alignment: comptime_int,\n"
- " child: type,\n"
- " is_allowzero: bool,\n"
- "\n"
- " pub const Size = enum {\n"
- " One,\n"
- " Many,\n"
- " Slice,\n"
- " C,\n"
- " };\n"
- " };\n"
- "\n"
- " pub const Array = struct {\n"
- " len: comptime_int,\n"
- " child: type,\n"
- " };\n"
- "\n"
- " pub const ContainerLayout = enum {\n"
- " Auto,\n"
- " Extern,\n"
- " Packed,\n"
- " };\n"
- "\n"
- " pub const StructField = struct {\n"
- " name: []const u8,\n"
- " offset: ?comptime_int,\n"
- " field_type: type,\n"
- " };\n"
- "\n"
- " pub const Struct = struct {\n"
- " layout: ContainerLayout,\n"
- " fields: []StructField,\n"
- " decls: []Declaration,\n"
- " };\n"
- "\n"
- " pub const Optional = struct {\n"
- " child: type,\n"
- " };\n"
- "\n"
- " pub const ErrorUnion = struct {\n"
- " error_set: type,\n"
- " payload: type,\n"
- " };\n"
- "\n"
- " pub const Error = struct {\n"
- " name: []const u8,\n"
- " value: comptime_int,\n"
- " };\n"
- "\n"
- " pub const ErrorSet = ?[]Error;\n"
- "\n"
- " pub const EnumField = struct {\n"
- " name: []const u8,\n"
- " value: comptime_int,\n"
- " };\n"
- "\n"
- " pub const Enum = struct {\n"
- " layout: ContainerLayout,\n"
- " tag_type: type,\n"
- " fields: []EnumField,\n"
- " decls: []Declaration,\n"
- " };\n"
- "\n"
- " pub const UnionField = struct {\n"
- " name: []const u8,\n"
- " enum_field: ?EnumField,\n"
- " field_type: type,\n"
- " };\n"
- "\n"
- " pub const Union = struct {\n"
- " layout: ContainerLayout,\n"
- " tag_type: ?type,\n"
- " fields: []UnionField,\n"
- " decls: []Declaration,\n"
- " };\n"
- "\n"
- " pub const CallingConvention = enum {\n"
- " Unspecified,\n"
- " C,\n"
- " Cold,\n"
- " Naked,\n"
- " Stdcall,\n"
- " Async,\n"
- " };\n"
- "\n"
- " pub const FnArg = struct {\n"
- " is_generic: bool,\n"
- " is_noalias: bool,\n"
- " arg_type: ?type,\n"
- " };\n"
- "\n"
- " pub const Fn = struct {\n"
- " calling_convention: CallingConvention,\n"
- " is_generic: bool,\n"
- " is_var_args: bool,\n"
- " return_type: ?type,\n"
- " args: []FnArg,\n"
- " };\n"
- "\n"
- " pub const AnyFrame = struct {\n"
- " child: ?type,\n"
- " };\n"
- "\n"
- " pub const Vector = struct {\n"
- " len: comptime_int,\n"
- " child: type,\n"
- " };\n"
- "\n"
- " pub const Declaration = struct {\n"
- " name: []const u8,\n"
- " is_pub: bool,\n"
- " data: Data,\n"
- "\n"
- " pub const Data = union(enum) {\n"
- " Type: type,\n"
- " Var: type,\n"
- " Fn: FnDecl,\n"
- "\n"
- " pub const FnDecl = struct {\n"
- " fn_type: type,\n"
- " inline_type: Inline,\n"
- " calling_convention: CallingConvention,\n"
- " is_var_args: bool,\n"
- " is_extern: bool,\n"
- " is_export: bool,\n"
- " lib_name: ?[]const u8,\n"
- " return_type: type,\n"
- " arg_names: [][] const u8,\n"
- "\n"
- " pub const Inline = enum {\n"
- " Auto,\n"
- " Always,\n"
- " Never,\n"
- " };\n"
- " };\n"
- " };\n"
- " };\n"
- "};\n\n");
- static_assert(ContainerLayoutAuto == 0, "");
- static_assert(ContainerLayoutExtern == 1, "");
- static_assert(ContainerLayoutPacked == 2, "");
-
- static_assert(CallingConventionUnspecified == 0, "");
- static_assert(CallingConventionC == 1, "");
- static_assert(CallingConventionCold == 2, "");
- static_assert(CallingConventionNaked == 3, "");
- static_assert(CallingConventionStdcall == 4, "");
- static_assert(CallingConventionAsync == 5, "");
-
- static_assert(FnInlineAuto == 0, "");
- static_assert(FnInlineAlways == 1, "");
- static_assert(FnInlineNever == 2, "");
-
- static_assert(BuiltinPtrSizeOne == 0, "");
- static_assert(BuiltinPtrSizeMany == 1, "");
- static_assert(BuiltinPtrSizeSlice == 2, "");
- static_assert(BuiltinPtrSizeC == 3, "");
- }
- {
- buf_appendf(contents,
- "pub const FloatMode = enum {\n"
- " Strict,\n"
- " Optimized,\n"
- "};\n\n");
- assert(FloatModeStrict == 0);
- assert(FloatModeOptimized == 1);
- }
- {
- buf_appendf(contents,
- "pub const Endian = enum {\n"
- " Big,\n"
- " Little,\n"
- "};\n\n");
- //assert(EndianBig == 0);
- //assert(EndianLittle == 1);
- }
- {
- buf_appendf(contents,
- "pub const Version = struct {\n"
- " major: u32,\n"
- " minor: u32,\n"
- " patch: u32,\n"
- "};\n\n");
- }
- {
- buf_appendf(contents,
- "pub const SubSystem = enum {\n"
- " Console,\n"
- " Windows,\n"
- " Posix,\n"
- " Native,\n"
- " EfiApplication,\n"
- " EfiBootServiceDriver,\n"
- " EfiRom,\n"
- " EfiRuntimeDriver,\n"
- "};\n\n");
-
- assert(TargetSubsystemConsole == 0);
- assert(TargetSubsystemWindows == 1);
- assert(TargetSubsystemPosix == 2);
- assert(TargetSubsystemNative == 3);
- assert(TargetSubsystemEfiApplication == 4);
- assert(TargetSubsystemEfiBootServiceDriver == 5);
- assert(TargetSubsystemEfiRom == 6);
- assert(TargetSubsystemEfiRuntimeDriver == 7);
- }
+ // If any of these asserts trip then you need to either fix the internal compiler enum
+ // or the corresponding one in std.Target or std.builtin.
+ static_assert(ContainerLayoutAuto == 0, "");
+ static_assert(ContainerLayoutExtern == 1, "");
+ static_assert(ContainerLayoutPacked == 2, "");
+
+ static_assert(CallingConventionUnspecified == 0, "");
+ static_assert(CallingConventionC == 1, "");
+ static_assert(CallingConventionCold == 2, "");
+ static_assert(CallingConventionNaked == 3, "");
+ static_assert(CallingConventionStdcall == 4, "");
+ static_assert(CallingConventionAsync == 5, "");
+
+ static_assert(FnInlineAuto == 0, "");
+ static_assert(FnInlineAlways == 1, "");
+ static_assert(FnInlineNever == 2, "");
+
+ static_assert(BuiltinPtrSizeOne == 0, "");
+ static_assert(BuiltinPtrSizeMany == 1, "");
+ static_assert(BuiltinPtrSizeSlice == 2, "");
+ static_assert(BuiltinPtrSizeC == 3, "");
+
+ static_assert(TargetSubsystemConsole == 0, "");
+ static_assert(TargetSubsystemWindows == 1, "");
+ static_assert(TargetSubsystemPosix == 2, "");
+ static_assert(TargetSubsystemNative == 3, "");
+ static_assert(TargetSubsystemEfiApplication == 4, "");
+ static_assert(TargetSubsystemEfiBootServiceDriver == 5, "");
+ static_assert(TargetSubsystemEfiRom == 6, "");
+ static_assert(TargetSubsystemEfiRuntimeDriver == 7, "");
{
const char *endian_str = g->is_big_endian ? "Endian.Big" : "Endian.Little";
buf_appendf(contents, "pub const endian = %s;\n", endian_str);
@@ -8573,7 +8263,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
{
TargetSubsystem detected_subsystem = detect_subsystem(g);
if (detected_subsystem != TargetSubsystemAuto) {
- buf_appendf(contents, "pub const subsystem = SubSystem.%s;\n", subsystem_to_str(detected_subsystem));
+ buf_appendf(contents, "pub const explicit_subsystem = SubSystem.%s;\n", subsystem_to_str(detected_subsystem));
}
}
@@ -8594,10 +8284,6 @@ static ZigPackage *create_test_runner_pkg(CodeGen *g) {
return codegen_create_package(g, buf_ptr(g->zig_std_special_dir), "test_runner.zig", "std.special");
}
-static ZigPackage *create_panic_pkg(CodeGen *g) {
- return codegen_create_package(g, buf_ptr(g->zig_std_special_dir), "panic.zig", "std.special");
-}
-
static Error define_builtin_compile_vars(CodeGen *g) {
if (g->std_package == nullptr)
return ErrorNone;
@@ -8679,6 +8365,7 @@ static Error define_builtin_compile_vars(CodeGen *g) {
assert(g->root_package);
assert(g->std_package);
g->compile_var_package = new_package(buf_ptr(this_dir), builtin_zig_basename, "builtin");
+ g->compile_var_package->package_table.put(buf_create_from_str("std"), g->std_package);
g->root_package->package_table.put(buf_create_from_str("builtin"), g->compile_var_package);
g->std_package->package_table.put(buf_create_from_str("builtin"), g->compile_var_package);
g->std_package->package_table.put(buf_create_from_str("std"), g->std_package);
@@ -9377,16 +9064,43 @@ static void gen_root_source(CodeGen *g) {
if (!g->is_dummy_so) {
// Zig has lazy top level definitions. Here we semantically analyze the panic function.
- ZigType *import_with_panic;
- if (g->have_pub_panic) {
- import_with_panic = g->root_import;
- } else {
- g->panic_package = create_panic_pkg(g);
- import_with_panic = add_special_code(g, g->panic_package, "panic.zig");
+ Buf *import_target_path;
+ Buf full_path = BUF_INIT;
+ ZigType *std_import;
+ if ((err = analyze_import(g, g->root_import, buf_create_from_str("std"), &std_import,
+ &import_target_path, &full_path)))
+ {
+ if (err == ErrorFileNotFound) {
+ fprintf(stderr, "unable to find '%s'", buf_ptr(import_target_path));
+ } else {
+ fprintf(stderr, "unable to open '%s': %s\n", buf_ptr(&full_path), err_str(err));
+ }
+ exit(1);
}
- Tld *panic_tld = find_decl(g, &get_container_scope(import_with_panic)->base, buf_create_from_str("panic"));
+
+ Tld *builtin_tld = find_decl(g, &get_container_scope(std_import)->base,
+ buf_create_from_str("builtin"));
+ assert(builtin_tld != nullptr);
+ resolve_top_level_decl(g, builtin_tld, nullptr, false);
+ report_errors_and_maybe_exit(g);
+ assert(builtin_tld->id == TldIdVar);
+ TldVar *builtin_tld_var = (TldVar*)builtin_tld;
+ ConstExprValue *builtin_val = builtin_tld_var->var->const_value;
+ assert(builtin_val->type->id == ZigTypeIdMetaType);
+ ZigType *builtin_type = builtin_val->data.x_type;
+
+ Tld *panic_tld = find_decl(g, &get_container_scope(builtin_type)->base,
+ buf_create_from_str("panic"));
assert(panic_tld != nullptr);
resolve_top_level_decl(g, panic_tld, nullptr, false);
+ report_errors_and_maybe_exit(g);
+ assert(panic_tld->id == TldIdVar);
+ TldVar *panic_tld_var = (TldVar*)panic_tld;
+ ConstExprValue *panic_fn_val = panic_tld_var->var->const_value;
+ assert(panic_fn_val->type->id == ZigTypeIdFn);
+ assert(panic_fn_val->data.x_ptr.special == ConstPtrSpecialFunction);
+ g->panic_fn = panic_fn_val->data.x_ptr.data.fn.fn_entry;
+ assert(g->panic_fn != nullptr);
}
@@ -9416,10 +9130,6 @@ static void gen_root_source(CodeGen *g) {
}
}
- if (!g->is_dummy_so) {
- typecheck_panic_fn(g, g->panic_tld_fn, g->panic_fn);
- }
-
report_errors_and_maybe_exit(g);
}
diff --git a/src/error.cpp b/src/error.cpp
@@ -57,6 +57,7 @@ const char *err_str(Error err) {
case ErrorNoCCompilerInstalled: return "no C compiler installed";
case ErrorNotLazy: return "not lazy";
case ErrorIsAsync: return "is async";
+ case ErrorImportOutsidePkgPath: return "import of file outside package path";
}
return "(invalid error)";
}
diff --git a/src/ir.cpp b/src/ir.cpp
@@ -19589,57 +19589,18 @@ static IrInstruction *ir_analyze_instruction_import(IrAnalyze *ira, IrInstructio
AstNode *source_node = import_instruction->base.source_node;
ZigType *import = source_node->owner;
+ ZigType *target_import;
Buf *import_target_path;
- Buf *search_dir;
- assert(import->data.structure.root_struct->package);
- ZigPackage *target_package;
- auto package_entry = import->data.structure.root_struct->package->package_table.maybe_get(import_target_str);
- SourceKind source_kind;
- if (package_entry) {
- target_package = package_entry->value;
- import_target_path = &target_package->root_src_path;
- search_dir = &target_package->root_src_dir;
- source_kind = SourceKindPkgMain;
- } else {
- // try it as a filename
- target_package = import->data.structure.root_struct->package;
- import_target_path = import_target_str;
-
- // search relative to importing file
- search_dir = buf_alloc();
- os_path_dirname(import->data.structure.root_struct->path, search_dir);
-
- source_kind = SourceKindNonRoot;
- }
-
Buf full_path = BUF_INIT;
- os_path_join(search_dir, import_target_path, &full_path);
-
- Buf *import_code = buf_alloc();
- Buf *resolved_path = buf_alloc();
-
- Buf *resolve_paths[] = { &full_path, };
- *resolved_path = os_path_resolve(resolve_paths, 1);
-
- auto import_entry = ira->codegen->import_table.maybe_get(resolved_path);
- if (import_entry) {
- return ir_const_type(ira, &import_instruction->base, import_entry->value);
- }
-
- if (source_kind == SourceKindNonRoot) {
- ZigPackage *cur_scope_pkg = scope_package(import_instruction->base.scope);
- Buf *pkg_root_src_dir = &cur_scope_pkg->root_src_dir;
- Buf resolved_root_src_dir = os_path_resolve(&pkg_root_src_dir, 1);
- if (!buf_starts_with_buf(resolved_path, &resolved_root_src_dir)) {
+ if ((err = analyze_import(ira->codegen, import, import_target_str, &target_import,
+ &import_target_path, &full_path)))
+ {
+ if (err == ErrorImportOutsidePkgPath) {
ir_add_error_node(ira, source_node,
buf_sprintf("import of file outside package path: '%s'",
buf_ptr(import_target_path)));
return ira->codegen->invalid_instruction;
- }
- }
-
- if ((err = file_fetch(ira->codegen, resolved_path, import_code))) {
- if (err == ErrorFileNotFound) {
+ } else if (err == ErrorFileNotFound) {
ir_add_error_node(ira, source_node,
buf_sprintf("unable to find '%s'", buf_ptr(import_target_path)));
return ira->codegen->invalid_instruction;
@@ -19650,8 +19611,6 @@ static IrInstruction *ir_analyze_instruction_import(IrAnalyze *ira, IrInstructio
}
}
- ZigType *target_import = add_source_file(ira->codegen, target_package, resolved_path, import_code, source_kind);
-
return ir_const_type(ira, &import_instruction->base, target_import);
}
diff --git a/src/userland.h b/src/userland.h
@@ -77,6 +77,7 @@ enum Error {
ErrorNoSpaceLeft,
ErrorNotLazy,
ErrorIsAsync,
+ ErrorImportOutsidePkgPath,
};
// ABI warning
diff --git a/test/compile_errors.zig b/test/compile_errors.zig
@@ -64,7 +64,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\ _ = @Type(0);
\\}
,
- "tmp.zig:2:15: error: expected type 'builtin.TypeInfo', found 'comptime_int'",
+ "tmp.zig:2:15: error: expected type 'std.builtin.TypeInfo', found 'comptime_int'",
);
cases.add(
@@ -88,7 +88,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\ });
\\}
,
- "tmp.zig:3:36: error: expected type 'builtin.TypeInfo', found 'builtin.Int'",
+ "tmp.zig:3:36: error: expected type 'std.builtin.TypeInfo', found 'std.builtin.Int'",
);
cases.add(
@@ -806,7 +806,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\pub fn panic() void {}
\\
,
- "tmp.zig:3:5: error: expected type 'fn([]const u8, ?*builtin.StackTrace) noreturn', found 'fn() void'",
+ "error: expected type 'fn([]const u8, ?*std.builtin.StackTrace) noreturn', found 'fn() void'",
);
cases.add(
@@ -815,8 +815,8 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\ while (true) {}
\\}
,
- "tmp.zig:1:5: error: expected type 'fn([]const u8, ?*builtin.StackTrace) noreturn', found 'fn([]const u8,var)var'",
- "tmp.zig:1:5: note: only one of the functions is generic",
+ "error: expected type 'fn([]const u8, ?*std.builtin.StackTrace) noreturn', found 'fn([]const u8,var)var'",
+ "note: only one of the functions is generic",
);
cases.add(
@@ -1473,7 +1473,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\ const field = @typeInfo(Struct).Struct.fields[index];
\\}
,
- "tmp.zig:9:51: error: values of type 'builtin.StructField' must be comptime known, but index value is runtime known",
+ "tmp.zig:9:51: error: values of type 'std.builtin.StructField' must be comptime known, but index value is runtime known",
);
cases.add(
@@ -3743,13 +3743,19 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
);
cases.add(
- "missing function name and param name",
+ "missing function name",
\\fn () void {}
- \\fn f(i32) void {}
\\export fn entry() usize { return @sizeOf(@typeOf(f)); }
,
"tmp.zig:1:1: error: missing function name",
- "tmp.zig:2:6: error: missing parameter name",
+ );
+
+ cases.add(
+ "missing param name",
+ \\fn f(i32) void {}
+ \\export fn entry() usize { return @sizeOf(@typeOf(f)); }
+ ,
+ "tmp.zig:1:6: error: missing parameter name",
);
cases.add(
@@ -3782,7 +3788,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\export fn entry() usize { return @sizeOf(@typeOf(func)); }
,
"tmp.zig:2:1: error: redefinition of 'func'",
- "tmp.zig:1:11: error: use of undeclared identifier 'bogus'",
);
cases.add(
@@ -5086,7 +5091,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\ const foo = builtin.Arch.x86;
\\}
,
- "tmp.zig:3:29: error: container 'builtin.Arch' has no member called 'x86'",
+ "tmp.zig:3:29: error: container 'std.target.Arch' has no member called 'x86'",
);
cases.add(
@@ -5731,7 +5736,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\ while (!@cmpxchgWeak(i32, &x, 1234, 5678, u32(1234), u32(1234))) {}
\\}
,
- "tmp.zig:3:50: error: expected type 'builtin.AtomicOrder', found 'u32'",
+ "tmp.zig:3:50: error: expected type 'std.builtin.AtomicOrder', found 'u32'",
);
cases.add(
@@ -5741,7 +5746,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\ @export("entry", entry, u32(1234));
\\}
,
- "tmp.zig:3:32: error: expected type 'builtin.GlobalLinkage', found 'u32'",
+ "tmp.zig:3:32: error: expected type 'std.builtin.GlobalLinkage', found 'u32'",
);
cases.add(