zig/lib/std/builtin.zig
Andrew Kelley fa46bcb368
stage1: make get_optional_type more robust
Now it will emit a compile error rather than crashing when the child
type has not been resolved properly.

Introduces `get_optional_type2` which should be used generally inside
ir.cpp.

Fix some std lib compile errors noticed by the provided test case.

Thanks @LemonBoy for the test case. Closes #4377.

Fixes #4374.
2020-03-06 18:30:30 -05:00

555 lines
18 KiB
Zig

pub usingnamespace @import("builtin");
/// Deprecated: use `std.Target`.
pub const Target = std.Target;
/// Deprecated: use `std.Target.Os`.
pub const Os = std.Target.Os;
/// Deprecated: use `std.Target.Cpu.Arch`.
pub const Arch = std.Target.Cpu.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;
/// Deprecated: use `std.Target.Cpu`.
pub const Cpu = std.Target.Cpu;
/// `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.tag) {
.windows => {
if (is_test) {
break :blk SubSystem.Console;
}
if (@hasDecl(root, "main") or
@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,
};
/// The code model puts constraints on the location of symbols and the size of code and data.
/// The selection of a code model is a trade off on speed and restrictions that needs to be selected on a per application basis to meet its requirements.
/// A slightly more detailed explanation can be found in (for example) the [System V Application Binary Interface (x86_64)](https://github.com/hjl-tools/x86-psABI/wiki/x86-64-psABI-1.0.pdf) 3.5.1.
///
/// This data structure is used by the Zig language code generation and
/// therefore must be kept in sync with the compiler implementation.
pub const CodeModel = enum {
default,
tiny,
small,
kernel,
medium,
large,
};
/// 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 CallingConvention = enum {
Unspecified,
C,
Cold,
Naked,
Async,
Interrupt,
Signal,
Stdcall,
Fastcall,
Vectorcall,
Thiscall,
APCS,
AAPCS,
AAPCSVFP,
};
pub const TypeId = @TagType(TypeInfo);
/// 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(enum) {
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,
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 field is an optional type.
/// The type of the sentinel is the element type of the pointer, which is
/// the value of the `child` field in this struct. However there is no way
/// to refer to that type here, so we use `var`.
sentinel: var,
/// 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 field is an optional type.
/// The type of the sentinel is the element type of the array, which is
/// the value of the `child` field in this struct. However there is no way
/// to refer to that type here, so we use `var`.
sentinel: var,
};
/// 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,
default_value: var,
};
/// 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,
is_exhaustive: 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 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 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,
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 OutputMode = enum {
Exe,
Lib,
Obj,
};
/// This data structure is used by the Zig language code generation and
/// therefore must be kept in sync with the compiler implementation.
pub const LinkMode = enum {
Static,
Dynamic,
};
/// 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 = 0,
pub const Range = struct {
min: Version,
max: Version,
pub fn includesVersion(self: Range, ver: Version) bool {
if (self.min.order(ver) == .gt) return false;
if (self.max.order(ver) == .lt) return false;
return true;
}
};
pub fn order(lhs: Version, rhs: Version) std.math.Order {
if (lhs.major < rhs.major) return .lt;
if (lhs.major > rhs.major) return .gt;
if (lhs.minor < rhs.minor) return .lt;
if (lhs.minor > rhs.minor) return .gt;
if (lhs.patch < rhs.patch) return .lt;
if (lhs.patch > rhs.patch) return .gt;
return .eq;
}
pub fn parse(text: []const u8) !Version {
var it = std.mem.separate(text, ".");
return Version{
.major = try std.fmt.parseInt(u32, it.next() orelse return error.InvalidVersion, 10),
.minor = try std.fmt.parseInt(u32, it.next() orelse "0", 10),
.patch = try std.fmt.parseInt(u32, it.next() orelse "0", 10),
};
}
pub fn format(
self: Version,
comptime fmt: []const u8,
options: std.fmt.FormatOptions,
context: var,
comptime Error: type,
comptime output: fn (@TypeOf(context), []const u8) Error!void,
) Error!void {
if (fmt.len == 0) {
if (self.patch == 0) {
if (self.minor == 0) {
return std.fmt.format(context, Error, output, "{}", .{self.major});
} else {
return std.fmt.format(context, Error, output, "{}.{}", .{ self.major, self.minor });
}
} else {
return std.fmt.format(context, Error, output, "{}.{}.{}", .{ self.major, self.minor, self.patch });
}
} else {
@compileError("Unknown format string: '" ++ fmt ++ "'");
}
}
};
/// This data structure is used by the Zig language code generation and
/// therefore must be kept in sync with the compiler implementation.
pub const CallOptions = struct {
modifier: Modifier = .auto,
stack: ?[]align(std.Target.stack_align) u8 = null,
pub const Modifier = enum {
/// Equivalent to function call syntax.
auto,
/// Equivalent to async keyword used with function call syntax.
async_kw,
/// Prevents tail call optimization. This guarantees that the return
/// address will point to the callsite, as opposed to the callsite's
/// callsite. If the call is otherwise required to be tail-called
/// or inlined, a compile error is emitted instead.
never_tail,
/// Guarantees that the call will not be inlined. If the call is
/// otherwise required to be inlined, a compile error is emitted instead.
never_inline,
/// Asserts that the function call will not suspend. This allows a
/// non-async function to call an async function.
no_async,
/// Guarantees that the call will be generated with tail call optimization.
/// If this is not possible, a compile error is emitted instead.
always_tail,
/// Guarantees that the call will inlined at the callsite.
/// If this is not possible, a compile error is emitted instead.
always_inline,
/// Evaluates the call at compile-time. If the call cannot be completed at
/// compile-time, a compile error is emitted instead.
compile_time,
};
};
/// This data structure is used by the Zig language code generation and
/// therefore must be kept in sync with the compiler implementation.
pub const ExportOptions = struct {
name: []const u8,
linkage: GlobalLinkage = .Strong,
section: ?[]const u8 = null,
};
/// This function type is used by the Zig language code generation and
/// therefore must be kept in sync with the compiler implementation.
pub const TestFn = struct {
name: []const u8,
func: fn () anyerror!void,
async_frame_size: ?usize,
};
/// 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);
if (@hasDecl(root, "os") and @hasDecl(root.os, "panic")) {
root.os.panic(msg, error_return_trace);
unreachable;
}
switch (os.tag) {
.freestanding => {
while (true) {
@breakpoint();
}
},
.wasi => {
std.debug.warn("{}", .{msg});
std.os.abort();
},
.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");