Merge remote-tracking branch 'origin/master' into llvm10

master
Andrew Kelley 2020-01-29 23:33:12 -05:00
commit a95dce15ae
No known key found for this signature in database
GPG Key ID: 7C5F548F728501A9
95 changed files with 32127 additions and 10809 deletions

View File

@ -10113,7 +10113,7 @@ Available libcs:
The Zig Standard Library ({#syntax#}@import("std"){#endsyntax#}) has architecture, environment, and operating system
abstractions, and thus takes additional work to support more platforms.
Not all standard library code requires operating system abstractions, however,
so things such as generic data structures work an all above platforms.
so things such as generic data structures work on all above platforms.
</p>
<p>The current list of targets supported by the Zig Standard Library is:</p>
<ul>

View File

@ -57,11 +57,11 @@ pub const Buffer = struct {
/// The caller owns the returned memory. The Buffer becomes null and
/// is safe to `deinit`.
pub fn toOwnedSlice(self: *Buffer) []u8 {
pub fn toOwnedSlice(self: *Buffer) [:0]u8 {
const allocator = self.list.allocator;
const result = allocator.shrink(self.list.items, self.len());
const result = self.list.toOwnedSlice();
self.* = initNull(allocator);
return result;
return result[0 .. result.len - 1 :0];
}
pub fn allocPrint(allocator: *Allocator, comptime format: []const u8, args: var) !Buffer {

View File

@ -484,6 +484,7 @@ pub const Builder = struct {
.arch = builtin.arch,
.os = builtin.os,
.abi = builtin.abi,
.cpu_features = builtin.cpu_features,
},
}).linuxTriple(self.allocator);
@ -1148,6 +1149,7 @@ pub const LibExeObjStep = struct {
name_prefix: []const u8,
filter: ?[]const u8,
single_threaded: bool,
code_model: builtin.CodeModel = .default,
root_src: ?FileSource,
out_h_filename: []const u8,
@ -1375,6 +1377,7 @@ pub const LibExeObjStep = struct {
.arch = target_arch,
.os = target_os,
.abi = target_abi,
.cpu_features = target_arch.getBaselineCpuFeatures(),
},
});
}
@ -1968,11 +1971,56 @@ pub const LibExeObjStep = struct {
try zig_args.append("-fno-sanitize-c");
}
if (self.code_model != .default) {
try zig_args.append("-code-model");
try zig_args.append(@tagName(self.code_model));
}
switch (self.target) {
.Native => {},
.Cross => {
.Cross => |cross| {
try zig_args.append("-target");
try zig_args.append(self.target.zigTriple(builder.allocator) catch unreachable);
const all_features = self.target.getArch().allFeaturesList();
var populated_cpu_features = cross.cpu_features.cpu.features;
if (self.target.getArch().subArchFeature()) |sub_arch_index| {
populated_cpu_features.addFeature(sub_arch_index);
}
populated_cpu_features.populateDependencies(all_features);
if (populated_cpu_features.eql(cross.cpu_features.features)) {
// The CPU name alone is sufficient.
// If it is the baseline CPU, no command line args are required.
if (cross.cpu_features.cpu != self.target.getArch().getBaselineCpuFeatures().cpu) {
try zig_args.append("-target-cpu");
try zig_args.append(cross.cpu_features.cpu.name);
}
} else {
try zig_args.append("-target-cpu");
try zig_args.append(cross.cpu_features.cpu.name);
try zig_args.append("-target-feature");
var feature_str_buffer = try std.Buffer.initSize(builder.allocator, 0);
for (all_features) |feature, i_usize| {
const i = @intCast(Target.Cpu.Feature.Set.Index, i_usize);
const in_cpu_set = populated_cpu_features.isEnabled(i);
const in_actual_set = cross.cpu_features.features.isEnabled(i);
if (in_cpu_set and !in_actual_set) {
try feature_str_buffer.appendByte('-');
try feature_str_buffer.append(feature.name);
try feature_str_buffer.appendByte(',');
} else if (!in_cpu_set and in_actual_set) {
try feature_str_buffer.appendByte('+');
try feature_str_buffer.append(feature.name);
try feature_str_buffer.appendByte(',');
}
}
if (mem.endsWith(u8, feature_str_buffer.toSliceConst(), ",")) {
feature_str_buffer.shrink(feature_str_buffer.len() - 1);
}
try zig_args.append(feature_str_buffer.toSliceConst());
}
},
}

View File

@ -1,5 +1,8 @@
pub usingnamespace @import("builtin");
/// Deprecated: use `std.Target`.
pub const Target = std.Target;
/// Deprecated: use `std.Target.Os`.
pub const Os = std.Target.Os;
@ -15,6 +18,12 @@ pub const ObjectFormat = std.Target.ObjectFormat;
/// Deprecated: use `std.Target.SubSystem`.
pub const SubSystem = std.Target.SubSystem;
/// Deprecated: use `std.Target.CpuFeatures`.
pub const CpuFeatures = std.Target.CpuFeatures;
/// 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`.
@ -82,6 +91,21 @@ pub const AtomicRmwOp = enum {
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 {

View File

@ -2,6 +2,12 @@ const builtin = @import("builtin");
const std = @import("std");
const page_size = std.mem.page_size;
pub const tokenizer = @import("c/tokenizer.zig");
pub const Token = tokenizer.Token;
pub const Tokenizer = tokenizer.Tokenizer;
pub const parse = @import("c/parse.zig").parse;
pub const ast = @import("c/ast.zig");
pub usingnamespace @import("os/bits.zig");
pub usingnamespace switch (builtin.os) {

681
lib/std/c/ast.zig Normal file
View File

@ -0,0 +1,681 @@
const std = @import("std");
const SegmentedList = std.SegmentedList;
const Token = std.c.Token;
const Source = std.c.tokenizer.Source;
pub const TokenIndex = usize;
pub const Tree = struct {
tokens: TokenList,
sources: SourceList,
root_node: *Node.Root,
arena_allocator: std.heap.ArenaAllocator,
msgs: MsgList,
pub const SourceList = SegmentedList(Source, 4);
pub const TokenList = Source.TokenList;
pub const MsgList = SegmentedList(Msg, 0);
pub fn deinit(self: *Tree) void {
// Here we copy the arena allocator into stack memory, because
// otherwise it would destroy itself while it was still working.
var arena_allocator = self.arena_allocator;
arena_allocator.deinit();
// self is destroyed
}
pub fn tokenSlice(tree: *Tree, token: TokenIndex) []const u8 {
return tree.tokens.at(token).slice();
}
pub fn tokenEql(tree: *Tree, a: TokenIndex, b: TokenIndex) bool {
const atok = tree.tokens.at(a);
const btok = tree.tokens.at(b);
return atok.eql(btok.*);
}
};
pub const Msg = struct {
kind: enum {
Error,
Warning,
Note,
},
inner: Error,
};
pub const Error = union(enum) {
InvalidToken: SingleTokenError("invalid token '{}'"),
ExpectedToken: ExpectedToken,
ExpectedExpr: SingleTokenError("expected expression, found '{}'"),
ExpectedTypeName: SingleTokenError("expected type name, found '{}'"),
ExpectedFnBody: SingleTokenError("expected function body, found '{}'"),
ExpectedDeclarator: SingleTokenError("expected declarator, found '{}'"),
ExpectedInitializer: SingleTokenError("expected initializer, found '{}'"),
ExpectedEnumField: SingleTokenError("expected enum field, found '{}'"),
ExpectedType: SingleTokenError("expected enum field, found '{}'"),
InvalidTypeSpecifier: InvalidTypeSpecifier,
InvalidStorageClass: SingleTokenError("invalid storage class, found '{}'"),
InvalidDeclarator: SimpleError("invalid declarator"),
DuplicateQualifier: SingleTokenError("duplicate type qualifier '{}'"),
DuplicateSpecifier: SingleTokenError("duplicate declaration specifier '{}'"),
MustUseKwToRefer: MustUseKwToRefer,
FnSpecOnNonFn: SingleTokenError("function specifier '{}' on non function"),
NothingDeclared: SimpleError("declaration doesn't declare anything"),
QualifierIgnored: SingleTokenError("qualifier '{}' ignored"),
pub fn render(self: *const Error, tree: *Tree, stream: var) !void {
switch (self.*) {
.InvalidToken => |*x| return x.render(tree, stream),
.ExpectedToken => |*x| return x.render(tree, stream),
.ExpectedExpr => |*x| return x.render(tree, stream),
.ExpectedTypeName => |*x| return x.render(tree, stream),
.ExpectedDeclarator => |*x| return x.render(tree, stream),
.ExpectedFnBody => |*x| return x.render(tree, stream),
.ExpectedInitializer => |*x| return x.render(tree, stream),
.ExpectedEnumField => |*x| return x.render(tree, stream),
.ExpectedType => |*x| return x.render(tree, stream),
.InvalidTypeSpecifier => |*x| return x.render(tree, stream),
.InvalidStorageClass => |*x| return x.render(tree, stream),
.InvalidDeclarator => |*x| return x.render(tree, stream),
.DuplicateQualifier => |*x| return x.render(tree, stream),
.DuplicateSpecifier => |*x| return x.render(tree, stream),
.MustUseKwToRefer => |*x| return x.render(tree, stream),
.FnSpecOnNonFn => |*x| return x.render(tree, stream),
.NothingDeclared => |*x| return x.render(tree, stream),
.QualifierIgnored => |*x| return x.render(tree, stream),
}
}
pub fn loc(self: *const Error) TokenIndex {
switch (self.*) {
.InvalidToken => |x| return x.token,
.ExpectedToken => |x| return x.token,
.ExpectedExpr => |x| return x.token,
.ExpectedTypeName => |x| return x.token,
.ExpectedDeclarator => |x| return x.token,
.ExpectedFnBody => |x| return x.token,
.ExpectedInitializer => |x| return x.token,
.ExpectedEnumField => |x| return x.token,
.ExpectedType => |*x| return x.token,
.InvalidTypeSpecifier => |x| return x.token,
.InvalidStorageClass => |x| return x.token,
.InvalidDeclarator => |x| return x.token,
.DuplicateQualifier => |x| return x.token,
.DuplicateSpecifier => |x| return x.token,
.MustUseKwToRefer => |*x| return x.name,
.FnSpecOnNonFn => |*x| return x.name,
.NothingDeclared => |*x| return x.name,
.QualifierIgnored => |*x| return x.name,
}
}
pub const ExpectedToken = struct {
token: TokenIndex,
expected_id: @TagType(Token.Id),
pub fn render(self: *const ExpectedToken, tree: *Tree, stream: var) !void {
const found_token = tree.tokens.at(self.token);
if (found_token.id == .Invalid) {
return stream.print("expected '{}', found invalid bytes", .{self.expected_id.symbol()});
} else {
const token_name = found_token.id.symbol();
return stream.print("expected '{}', found '{}'", .{ self.expected_id.symbol(), token_name });
}
}
};
pub const InvalidTypeSpecifier = struct {
token: TokenIndex,
type_spec: *Node.TypeSpec,
pub fn render(self: *const ExpectedToken, tree: *Tree, stream: var) !void {
try stream.write("invalid type specifier '");
try type_spec.spec.print(tree, stream);
const token_name = tree.tokens.at(self.token).id.symbol();
return stream.print("{}'", .{token_name});
}
};
pub const MustUseKwToRefer = struct {
kw: TokenIndex,
name: TokenIndex,
pub fn render(self: *const ExpectedToken, tree: *Tree, stream: var) !void {
return stream.print("must use '{}' tag to refer to type '{}'", .{ tree.slice(kw), tree.slice(name) });
}
};
fn SingleTokenError(comptime msg: []const u8) type {
return struct {
token: TokenIndex,
pub fn render(self: *const @This(), tree: *Tree, stream: var) !void {
const actual_token = tree.tokens.at(self.token);
return stream.print(msg, .{actual_token.id.symbol()});
}
};
}
fn SimpleError(comptime msg: []const u8) type {
return struct {
const ThisError = @This();
token: TokenIndex,
pub fn render(self: *const ThisError, tokens: *Tree.TokenList, stream: var) !void {
return stream.write(msg);
}
};
}
};
pub const Type = struct {
pub const TypeList = std.SegmentedList(*Type, 4);
@"const": bool = false,
atomic: bool = false,
@"volatile": bool = false,
restrict: bool = false,
id: union(enum) {
Int: struct {
id: Id,
is_signed: bool,
pub const Id = enum {
Char,
Short,
Int,
Long,
LongLong,
};
},
Float: struct {
id: Id,
pub const Id = enum {
Float,
Double,
LongDouble,
};
},
Pointer: *Type,
Function: struct {
return_type: *Type,
param_types: TypeList,
},
Typedef: *Type,
Record: *Node.RecordType,
Enum: *Node.EnumType,
/// Special case for macro parameters that can be any type.
/// Only present if `retain_macros == true`.
Macro,
},
};
pub const Node = struct {
id: Id,
pub const Id = enum {
Root,
EnumField,
RecordField,
RecordDeclarator,
JumpStmt,
ExprStmt,
LabeledStmt,
CompoundStmt,
IfStmt,
SwitchStmt,
WhileStmt,
DoStmt,
ForStmt,
StaticAssert,
Declarator,
Pointer,
FnDecl,
Typedef,
VarDecl,
};
pub const Root = struct {
base: Node = Node{ .id = .Root },
decls: DeclList,
eof: TokenIndex,
pub const DeclList = SegmentedList(*Node, 4);
};
pub const DeclSpec = struct {
storage_class: union(enum) {
Auto: TokenIndex,
Extern: TokenIndex,
Register: TokenIndex,
Static: TokenIndex,
Typedef: TokenIndex,
None,
} = .None,
thread_local: ?TokenIndex = null,
type_spec: TypeSpec = TypeSpec{},
fn_spec: union(enum) {
Inline: TokenIndex,
Noreturn: TokenIndex,
None,
} = .None,
align_spec: ?struct {
alignas: TokenIndex,
expr: *Node,
rparen: TokenIndex,
} = null,
};
pub const TypeSpec = struct {
qual: TypeQual = TypeQual{},
spec: union(enum) {
/// error or default to int
None,
Void: TokenIndex,
Char: struct {
sign: ?TokenIndex = null,
char: TokenIndex,
},
Short: struct {
sign: ?TokenIndex = null,
short: TokenIndex = null,
int: ?TokenIndex = null,
},
Int: struct {
sign: ?TokenIndex = null,
int: ?TokenIndex = null,
},
Long: struct {
sign: ?TokenIndex = null,
long: TokenIndex,
longlong: ?TokenIndex = null,
int: ?TokenIndex = null,
},
Float: struct {
float: TokenIndex,
complex: ?TokenIndex = null,
},
Double: struct {
long: ?TokenIndex = null,
double: ?TokenIndex,
complex: ?TokenIndex = null,
},
Bool: TokenIndex,
Atomic: struct {
atomic: TokenIndex,
typename: *Node,
rparen: TokenIndex,
},
Enum: *EnumType,
Record: *RecordType,
Typedef: struct {
sym: TokenIndex,
sym_type: *Type,
},
pub fn print(self: *@This(), self: *const @This(), tree: *Tree, stream: var) !void {
switch (self.spec) {
.None => unreachable,
.Void => |index| try stream.write(tree.slice(index)),
.Char => |char| {
if (char.sign) |s| {
try stream.write(tree.slice(s));
try stream.writeByte(' ');
}
try stream.write(tree.slice(char.char));
},
.Short => |short| {
if (short.sign) |s| {
try stream.write(tree.slice(s));
try stream.writeByte(' ');
}
try stream.write(tree.slice(short.short));
if (short.int) |i| {
try stream.writeByte(' ');
try stream.write(tree.slice(i));
}
},
.Int => |int| {
if (int.sign) |s| {
try stream.write(tree.slice(s));
try stream.writeByte(' ');
}
if (int.int) |i| {
try stream.writeByte(' ');
try stream.write(tree.slice(i));
}
},
.Long => |long| {
if (long.sign) |s| {
try stream.write(tree.slice(s));
try stream.writeByte(' ');
}
try stream.write(tree.slice(long.long));
if (long.longlong) |l| {
try stream.writeByte(' ');
try stream.write(tree.slice(l));
}
if (long.int) |i| {
try stream.writeByte(' ');
try stream.write(tree.slice(i));
}
},
.Float => |float| {
try stream.write(tree.slice(float.float));
if (float.complex) |c| {
try stream.writeByte(' ');
try stream.write(tree.slice(c));
}
},
.Double => |double| {
if (double.long) |l| {
try stream.write(tree.slice(l));
try stream.writeByte(' ');
}
try stream.write(tree.slice(double.double));
if (double.complex) |c| {
try stream.writeByte(' ');
try stream.write(tree.slice(c));
}
},
.Bool => |index| try stream.write(tree.slice(index)),
.Typedef => |typedef| try stream.write(tree.slice(typedef.sym)),
else => try stream.print("TODO print {}", self.spec),
}
}
} = .None,
};
pub const EnumType = struct {
tok: TokenIndex,
name: ?TokenIndex,
body: ?struct {
lbrace: TokenIndex,
/// always EnumField
fields: FieldList,
rbrace: TokenIndex,
},
pub const FieldList = Root.DeclList;
};
pub const EnumField = struct {
base: Node = Node{ .id = .EnumField },
name: TokenIndex,
value: ?*Node,
};
pub const RecordType = struct {
tok: TokenIndex,
kind: enum {
Struct,
Union,
},
name: ?TokenIndex,
body: ?struct {
lbrace: TokenIndex,
/// RecordField or StaticAssert
fields: FieldList,
rbrace: TokenIndex,
},
pub const FieldList = Root.DeclList;
};
pub const RecordField = struct {
base: Node = Node{ .id = .RecordField },
type_spec: TypeSpec,
declarators: DeclaratorList,
semicolon: TokenIndex,
pub const DeclaratorList = Root.DeclList;
};
pub const RecordDeclarator = struct {
base: Node = Node{ .id = .RecordDeclarator },
declarator: ?*Declarator,
bit_field_expr: ?*Expr,
};
pub const TypeQual = struct {
@"const": ?TokenIndex = null,
atomic: ?TokenIndex = null,
@"volatile": ?TokenIndex = null,
restrict: ?TokenIndex = null,
};
pub const JumpStmt = struct {
base: Node = Node{ .id = .JumpStmt },
ltoken: TokenIndex,
kind: union(enum) {
Break,
Continue,
Return: ?*Node,
Goto: TokenIndex,
},
semicolon: TokenIndex,
};
pub const ExprStmt = struct {
base: Node = Node{ .id = .ExprStmt },
expr: ?*Expr,
semicolon: TokenIndex,
};
pub const LabeledStmt = struct {
base: Node = Node{ .id = .LabeledStmt },
kind: union(enum) {
Label: TokenIndex,
Case: TokenIndex,
Default: TokenIndex,
},
stmt: *Node,
};
pub const CompoundStmt = struct {
base: Node = Node{ .id = .CompoundStmt },
lbrace: TokenIndex,
statements: StmtList,
rbrace: TokenIndex,
pub const StmtList = Root.DeclList;
};
pub const IfStmt = struct {
base: Node = Node{ .id = .IfStmt },
@"if": TokenIndex,
cond: *Node,
body: *Node,
@"else": ?struct {
tok: TokenIndex,
body: *Node,
},
};
pub const SwitchStmt = struct {
base: Node = Node{ .id = .SwitchStmt },
@"switch": TokenIndex,
expr: *Expr,
rparen: TokenIndex,
stmt: *Node,
};
pub const WhileStmt = struct {
base: Node = Node{ .id = .WhileStmt },
@"while": TokenIndex,
cond: *Expr,
rparen: TokenIndex,
body: *Node,
};
pub const DoStmt = struct {
base: Node = Node{ .id = .DoStmt },
do: TokenIndex,
body: *Node,
@"while": TokenIndex,
cond: *Expr,
semicolon: TokenIndex,
};
pub const ForStmt = struct {
base: Node = Node{ .id = .ForStmt },
@"for": TokenIndex,
init: ?*Node,
cond: ?*Expr,
semicolon: TokenIndex,
incr: ?*Expr,
rparen: TokenIndex,
body: *Node,
};
pub const StaticAssert = struct {
base: Node = Node{ .id = .StaticAssert },
assert: TokenIndex,
expr: *Node,
semicolon: TokenIndex,
};
pub const Declarator = struct {
base: Node = Node{ .id = .Declarator },
pointer: ?*Pointer,
prefix: union(enum) {
None,
Identifer: TokenIndex,
Complex: struct {
lparen: TokenIndex,
inner: *Node,
rparen: TokenIndex,
},
},
suffix: union(enum) {
None,
Fn: struct {
lparen: TokenIndex,
params: Params,
rparen: TokenIndex,
},
Array: Arrays,
},
pub const Arrays = std.SegmentedList(*Array, 2);
pub const Params = std.SegmentedList(*Param, 4);
};
pub const Array = struct {
lbracket: TokenIndex,
inner: union(enum) {
Inferred,
Unspecified: TokenIndex,
Variable: struct {
asterisk: ?TokenIndex,
static: ?TokenIndex,
qual: TypeQual,
expr: *Expr,
},
},
rbracket: TokenIndex,
};
pub const Pointer = struct {
base: Node = Node{ .id = .Pointer },
asterisk: TokenIndex,
qual: TypeQual,
pointer: ?*Pointer,
};
pub const Param = struct {
kind: union(enum) {
Variable,
Old: TokenIndex,
Normal: struct {
decl_spec: *DeclSpec,
declarator: *Node,
},
},
};
pub const FnDecl = struct {
base: Node = Node{ .id = .FnDecl },
decl_spec: DeclSpec,
declarator: *Declarator,
old_decls: OldDeclList,
body: ?*CompoundStmt,
pub const OldDeclList = SegmentedList(*Node, 0);
};
pub const Typedef = struct {
base: Node = Node{ .id = .Typedef },
decl_spec: DeclSpec,
declarators: DeclaratorList,
semicolon: TokenIndex,
pub const DeclaratorList = Root.DeclList;
};
pub const VarDecl = struct {
base: Node = Node{ .id = .VarDecl },
decl_spec: DeclSpec,
initializers: Initializers,
semicolon: TokenIndex,
pub const Initializers = Root.DeclList;
};
pub const Initialized = struct {
base: Node = Node{ .id = Initialized },
declarator: *Declarator,
eq: TokenIndex,
init: Initializer,
};
pub const Initializer = union(enum) {
list: struct {
initializers: InitializerList,
rbrace: TokenIndex,
},
expr: *Expr,
pub const InitializerList = std.SegmentedList(*Initializer, 4);
};
pub const Macro = struct {
base: Node = Node{ .id = Macro },
kind: union(enum) {
Undef: []const u8,
Fn: struct {
params: []const []const u8,
expr: *Expr,
},
Expr: *Expr,
},
};
};
pub const Expr = struct {
id: Id,
ty: *Type,
value: union(enum) {
None,
},
pub const Id = enum {
Infix,
Literal,
};
pub const Infix = struct {
base: Expr = Expr{ .id = .Infix },
lhs: *Expr,
op_token: TokenIndex,
op: Op,
rhs: *Expr,
pub const Op = enum {};
};
};

View File

@ -7,7 +7,10 @@ usingnamespace @import("../os/bits.zig");
extern "c" fn __error() *c_int;
pub extern "c" fn _NSGetExecutablePath(buf: [*]u8, bufsize: *u32) c_int;
pub extern "c" fn _dyld_image_count() u32;
pub extern "c" fn _dyld_get_image_header(image_index: u32) ?*mach_header;
pub extern "c" fn _dyld_get_image_vmaddr_slide(image_index: u32) usize;
pub extern "c" fn _dyld_get_image_name(image_index: u32) [*:0]const u8;
pub extern "c" fn __getdirentries64(fd: c_int, buf_ptr: [*]u8, buf_len: usize, basep: *i64) isize;

1431
lib/std/c/parse.zig Normal file

File diff suppressed because it is too large Load Diff

1583
lib/std/c/tokenizer.zig Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1135,6 +1135,11 @@ fn countSize(size: *usize, bytes: []const u8) (error{}!void) {
size.* += bytes.len;
}
pub fn allocPrint0(allocator: *mem.Allocator, comptime fmt: []const u8, args: var) AllocPrintError![:0]u8 {
const result = try allocPrint(allocator, fmt ++ "\x00", args);
return result[0 .. result.len - 1 :0];
}
test "bufPrintInt" {
var buffer: [100]u8 = undefined;
const buf = buffer[0..];

View File

@ -382,6 +382,10 @@ pub fn parseFloat(comptime T: type, s: []const u8) !T {
}
test "fmt.parseFloat" {
if (std.Target.current.isWindows()) {
// TODO https://github.com/ziglang/zig/issues/508
return error.SkipZigTest;
}
const testing = std.testing;
const expect = testing.expect;
const expectEqual = testing.expectEqual;

View File

@ -15,7 +15,7 @@ pub const Murmur2_32 = struct {
const m: u32 = 0x5bd1e995;
const len = @truncate(u32, str.len);
var h1: u32 = seed ^ len;
for (@ptrCast([*]allowzero align(1) const u32, str.ptr)[0..(len >> 2)]) |v| {
for (@ptrCast([*]align(1) const u32, str.ptr)[0..(len >> 2)]) |v| {
var k1: u32 = v;
if (builtin.endian == builtin.Endian.Big)
k1 = @byteSwap(u32, k1);
@ -100,7 +100,7 @@ pub const Murmur2_64 = struct {
const m: u64 = 0xc6a4a7935bd1e995;
const len = @as(u64, str.len);
var h1: u64 = seed ^ (len *% m);
for (@ptrCast([*]allowzero align(1) const u64, str.ptr)[0..@intCast(usize, len >> 3)]) |v| {
for (@ptrCast([*]align(1) const u64, str.ptr)[0..@intCast(usize, len >> 3)]) |v| {
var k1: u64 = v;
if (builtin.endian == builtin.Endian.Big)
k1 = @byteSwap(u64, k1);
@ -180,7 +180,7 @@ pub const Murmur3_32 = struct {
const c2: u32 = 0x1b873593;
const len = @truncate(u32, str.len);
var h1: u32 = seed;
for (@ptrCast([*]allowzero align(1) const u32, str.ptr)[0..(len >> 2)]) |v| {
for (@ptrCast([*]align(1) const u32, str.ptr)[0..(len >> 2)]) |v| {
var k1: u32 = v;
if (builtin.endian == builtin.Endian.Big)
k1 = @byteSwap(u32, k1);

View File

@ -172,7 +172,7 @@ pub const Headers = struct {
var dex = HeaderIndexList.init(self.allocator);
try dex.append(n - 1);
errdefer dex.deinit();
_ = try self.index.put(name, dex);
_ = try self.index.put(name_dup, dex);
}
self.data.appendAssumeCapacity(entry);
}

View File

@ -45,10 +45,14 @@ pub fn OutStream(comptime WriteError: type) type {
}
pub fn writeByteNTimes(self: *Self, byte: u8, n: usize) Error!void {
const slice = @as(*const [1]u8, &byte)[0..];
var i: usize = 0;
while (i < n) : (i += 1) {
try self.writeFn(self, slice);
var bytes: [256]u8 = undefined;
mem.set(u8, bytes[0..], byte);
var remaining: usize = n;
while (remaining > 0) {
const to_write = std.math.min(remaining, bytes.len);
try self.writeFn(self, bytes[0..to_write]);
remaining -= to_write;
}
}

View File

@ -547,6 +547,10 @@ fn testSerializerDeserializer(comptime endian: builtin.Endian, comptime packing:
}
test "Serializer/Deserializer generic" {
if (std.Target.current.isWindows()) {
// TODO https://github.com/ziglang/zig/issues/508
return error.SkipZigTest;
}
try testSerializerDeserializer(builtin.Endian.Big, .Byte);
try testSerializerDeserializer(builtin.Endian.Little, .Byte);
try testSerializerDeserializer(builtin.Endian.Big, .Bit);

View File

@ -95,6 +95,10 @@ test "math.fabs64.special" {
}
test "math.fabs128.special" {
if (std.Target.current.isWindows()) {
// TODO https://github.com/ziglang/zig/issues/508
return error.SkipZigTest;
}
expect(math.isPositiveInf(fabs(math.inf(f128))));
expect(math.isPositiveInf(fabs(-math.inf(f128))));
expect(math.isNan(fabs(math.nan(f128))));

View File

@ -74,6 +74,10 @@ pub fn isNegativeInf(x: var) bool {
}
test "math.isInf" {
if (std.Target.current.isWindows()) {
// TODO https://github.com/ziglang/zig/issues/508
return error.SkipZigTest;
}
expect(!isInf(@as(f16, 0.0)));
expect(!isInf(@as(f16, -0.0)));
expect(!isInf(@as(f32, 0.0)));
@ -93,6 +97,10 @@ test "math.isInf" {
}
test "math.isPositiveInf" {
if (std.Target.current.isWindows()) {
// TODO https://github.com/ziglang/zig/issues/508
return error.SkipZigTest;
}
expect(!isPositiveInf(@as(f16, 0.0)));
expect(!isPositiveInf(@as(f16, -0.0)));
expect(!isPositiveInf(@as(f32, 0.0)));
@ -112,6 +120,10 @@ test "math.isPositiveInf" {
}
test "math.isNegativeInf" {
if (std.Target.current.isWindows()) {
// TODO https://github.com/ziglang/zig/issues/508
return error.SkipZigTest;
}
expect(!isNegativeInf(@as(f16, 0.0)));
expect(!isNegativeInf(@as(f16, -0.0)));
expect(!isNegativeInf(@as(f32, 0.0)));

View File

@ -16,6 +16,10 @@ pub fn isSignalNan(x: var) bool {
}
test "math.isNan" {
if (std.Target.current.isWindows()) {
// TODO https://github.com/ziglang/zig/issues/508
return error.SkipZigTest;
}
expect(isNan(math.nan(f16)));
expect(isNan(math.nan(f32)));
expect(isNan(math.nan(f64)));

View File

@ -175,6 +175,7 @@ pub const Allocator = struct {
const old_byte_slice = @sliceToBytes(old_mem);
const byte_count = math.mul(usize, @sizeOf(T), new_n) catch return Error.OutOfMemory;
// Note: can't set shrunk memory to undefined as memory shouldn't be modified on realloc failure
const byte_slice = try self.reallocFn(self, old_byte_slice, Slice.alignment, byte_count, new_alignment);
assert(byte_slice.len == byte_count);
if (new_n > old_mem.len) {
@ -221,6 +222,7 @@ pub const Allocator = struct {
const byte_count = @sizeOf(T) * new_n;
const old_byte_slice = @sliceToBytes(old_mem);
@memset(old_byte_slice.ptr + byte_count, undefined, old_byte_slice.len - byte_count);
const byte_slice = self.shrinkFn(self, old_byte_slice, Slice.alignment, byte_count, new_alignment);
assert(byte_slice.len == byte_count);
return @bytesToSlice(T, @alignCast(new_alignment, byte_slice));
@ -234,6 +236,7 @@ pub const Allocator = struct {
const bytes_len = bytes.len + @boolToInt(Slice.sentinel != null);
if (bytes_len == 0) return;
const non_const_ptr = @intToPtr([*]u8, @ptrToInt(bytes.ptr));
@memset(non_const_ptr, undefined, bytes_len);
const shrink_result = self.shrinkFn(self, non_const_ptr[0..bytes_len], Slice.alignment, 0, 1);
assert(shrink_result.len == 0);
}

View File

@ -556,3 +556,21 @@ pub fn refAllDecls(comptime T: type) void {
if (!builtin.is_test) return;
_ = declarations(T);
}
/// Returns a slice of pointers to public declarations of a namespace.
pub fn declList(comptime Namespace: type, comptime Decl: type) []const *const Decl {
const S = struct {
fn declNameLessThan(lhs: *const Decl, rhs: *const Decl) bool {
return mem.lessThan(u8, lhs.name, rhs.name);
}
};
comptime {
const decls = declarations(Namespace);
var array: [decls.len]*const Decl = undefined;
for (decls) |decl, i| {
array[i] = &@field(Namespace, decl.name);
}
std.sort.sort(*const Decl, &array, S.declNameLessThan);
return &array;
}
}

View File

@ -2697,7 +2697,7 @@ pub fn dl_iterate_phdr(
// the whole ELF image
if (it.end()) {
var info = dl_phdr_info{
.dlpi_addr = elf_base,
.dlpi_addr = 0,
.dlpi_name = "/proc/self/exe",
.dlpi_phdr = phdrs.ptr,
.dlpi_phnum = ehdr.e_phnum,

View File

@ -1041,63 +1041,6 @@ pub fn uname(uts: *utsname) usize {
return syscall1(SYS_uname, @ptrToInt(uts));
}
// XXX: This should be weak
extern const __ehdr_start: elf.Ehdr;
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.link_libc) {
return std.c.dl_iterate_phdr(@ptrCast(std.c.dl_iterate_phdr_callback, callback), @ptrCast(?*c_void, data));
}
const elf_base = @ptrToInt(&__ehdr_start);
const n_phdr = __ehdr_start.e_phnum;
const phdrs = (@intToPtr([*]elf.Phdr, elf_base + __ehdr_start.e_phoff))[0..n_phdr];
var it = dl.linkmap_iterator(phdrs) catch return 0;
// The executable has no dynamic link segment, create a single entry for
// the whole ELF image
if (it.end()) {
var info = dl_phdr_info{
.dlpi_addr = elf_base,
.dlpi_name = "/proc/self/exe",
.dlpi_phdr = @intToPtr([*]elf.Phdr, elf_base + __ehdr_start.e_phoff),
.dlpi_phnum = __ehdr_start.e_phnum,
};
return callback(&info, @sizeOf(dl_phdr_info), data);
}
// Last return value from the callback function
var last_r: isize = 0;
while (it.next()) |entry| {
var dlpi_phdr: usize = undefined;
var dlpi_phnum: u16 = undefined;
if (entry.l_addr != 0) {
const elf_header = @intToPtr(*elf.Ehdr, entry.l_addr);
dlpi_phdr = entry.l_addr + elf_header.e_phoff;
dlpi_phnum = elf_header.e_phnum;
} else {
// This is the running ELF image
dlpi_phdr = elf_base + __ehdr_start.e_phoff;
dlpi_phnum = __ehdr_start.e_phnum;
}
var info = dl_phdr_info{
.dlpi_addr = entry.l_addr,
.dlpi_name = entry.l_name,
.dlpi_phdr = @intToPtr([*]elf.Phdr, dlpi_phdr),
.dlpi_phnum = dlpi_phnum,
};
last_r = callback(&info, @sizeOf(dl_phdr_info), data);
if (last_r != 0) break;
}
return last_r;
}
pub fn io_uring_setup(entries: u32, p: *io_uring_params) usize {
return syscall2(SYS_io_uring_setup, entries, @ptrToInt(p));
}

View File

@ -211,7 +211,7 @@ pub fn initTLS() ?*elf.Phdr {
if (tls_phdr) |phdr| {
// If the cpu is arm-based, check if it supports the TLS register
if (builtin.arch == builtin.Arch.arm and at_hwcap & std.os.linux.HWCAP_TLS == 0) {
if (builtin.arch == .arm and at_hwcap & std.os.linux.HWCAP_TLS == 0) {
// If the CPU does not support TLS via a coprocessor register,
// a kernel helper function can be used instead on certain linux kernels.
// See linux/arch/arm/include/asm/tls.h and musl/src/thread/arm/__set_thread_area.c.

View File

@ -186,8 +186,9 @@ fn iter_fn(info: *dl_phdr_info, size: usize, data: ?*usize) callconv(.C) i32 {
if (phdr.p_type != elf.PT_LOAD) continue;
const reloc_addr = info.dlpi_addr + phdr.p_vaddr;
// Find the ELF header
const elf_header = @intToPtr(*elf.Ehdr, phdr.p_vaddr - phdr.p_offset);
const elf_header = @intToPtr(*elf.Ehdr, reloc_addr - phdr.p_offset);
// Validate the magic
if (!mem.eql(u8, elf_header.e_ident[0..4], "\x7fELF")) return -1;
// Consistency check

View File

@ -7,16 +7,14 @@ const builtin = @import("builtin");
/// Stable in-place sort. O(n) best case, O(pow(n, 2)) worst case. O(1) memory (no allocator required).
pub fn insertionSort(comptime T: type, items: []T, lessThan: fn (lhs: T, rhs: T) bool) void {
{
var i: usize = 1;
while (i < items.len) : (i += 1) {
const x = items[i];
var j: usize = i;
while (j > 0 and lessThan(x, items[j - 1])) : (j -= 1) {
items[j] = items[j - 1];
}
items[j] = x;
var i: usize = 1;
while (i < items.len) : (i += 1) {
const x = items[i];
var j: usize = i;
while (j > 0 and lessThan(x, items[j - 1])) : (j -= 1) {
items[j] = items[j - 1];
}
items[j] = x;
}
}

View File

@ -130,6 +130,7 @@ comptime {
@export(@import("compiler_rt/int.zig").__udivmoddi4, .{ .name = "__udivmoddi4", .linkage = linkage });
@export(@import("compiler_rt/popcountdi2.zig").__popcountdi2, .{ .name = "__popcountdi2", .linkage = linkage });
@export(@import("compiler_rt/int.zig").__mulsi3, .{ .name = "__mulsi3", .linkage = linkage });
@export(@import("compiler_rt/muldi3.zig").__muldi3, .{ .name = "__muldi3", .linkage = linkage });
@export(@import("compiler_rt/int.zig").__divmoddi4, .{ .name = "__divmoddi4", .linkage = linkage });
@export(@import("compiler_rt/int.zig").__divsi3, .{ .name = "__divsi3", .linkage = linkage });

View File

@ -31,6 +31,10 @@ fn test__addtf3(a: f128, b: f128, expected_hi: u64, expected_lo: u64) void {
}
test "addtf3" {
if (@import("std").Target.current.isWindows()) {
// TODO https://github.com/ziglang/zig/issues/508
return error.SkipZigTest;
}
test__addtf3(qnan128, 0x1.23456789abcdefp+5, 0x7fff800000000000, 0x0);
// NaN + any = NaN
@ -71,6 +75,10 @@ fn test__subtf3(a: f128, b: f128, expected_hi: u64, expected_lo: u64) void {
}
test "subtf3" {
if (@import("std").Target.current.isWindows()) {
// TODO https://github.com/ziglang/zig/issues/508
return error.SkipZigTest;
}
// qNaN - any = qNaN
test__subtf3(qnan128, 0x1.23456789abcdefp+5, 0x7fff800000000000, 0x0);

View File

@ -11,6 +11,10 @@ fn test__fixtfdi(a: f128, expected: i64) void {
}
test "fixtfdi" {
if (@import("std").Target.current.isWindows()) {
// TODO https://github.com/ziglang/zig/issues/508
return error.SkipZigTest;
}
//warn("\n", .{});
test__fixtfdi(-math.f128_max, math.minInt(i64));

View File

@ -11,6 +11,10 @@ fn test__fixtfsi(a: f128, expected: i32) void {
}
test "fixtfsi" {
if (@import("std").Target.current.isWindows()) {
// TODO https://github.com/ziglang/zig/issues/508
return error.SkipZigTest;
}
//warn("\n", .{});
test__fixtfsi(-math.f128_max, math.minInt(i32));

View File

@ -11,6 +11,10 @@ fn test__fixtfti(a: f128, expected: i128) void {
}
test "fixtfti" {
if (@import("std").Target.current.isWindows()) {
// TODO https://github.com/ziglang/zig/issues/508
return error.SkipZigTest;
}
//warn("\n", .{});
test__fixtfti(-math.f128_max, math.minInt(i128));

View File

@ -7,6 +7,10 @@ fn test__fixunstfdi(a: f128, expected: u64) void {
}
test "fixunstfdi" {
if (@import("std").Target.current.isWindows()) {
// TODO https://github.com/ziglang/zig/issues/508
return error.SkipZigTest;
}
test__fixunstfdi(0.0, 0);
test__fixunstfdi(0.5, 0);

View File

@ -9,6 +9,10 @@ fn test__fixunstfsi(a: f128, expected: u32) void {
const inf128 = @bitCast(f128, @as(u128, 0x7fff0000000000000000000000000000));
test "fixunstfsi" {
if (@import("std").Target.current.isWindows()) {
// TODO https://github.com/ziglang/zig/issues/508
return error.SkipZigTest;
}
test__fixunstfsi(inf128, 0xffffffff);
test__fixunstfsi(0, 0x0);
test__fixunstfsi(0x1.23456789abcdefp+5, 0x24);

View File

@ -9,6 +9,10 @@ fn test__fixunstfti(a: f128, expected: u128) void {
const inf128 = @bitCast(f128, @as(u128, 0x7fff0000000000000000000000000000));
test "fixunstfti" {
if (@import("std").Target.current.isWindows()) {
// TODO https://github.com/ziglang/zig/issues/508
return error.SkipZigTest;
}
test__fixunstfti(inf128, 0xffffffffffffffffffffffffffffffff);
test__fixunstfti(0.0, 0);

View File

@ -7,6 +7,10 @@ fn test__floattitf(a: i128, expected: f128) void {
}
test "floattitf" {
if (@import("std").Target.current.isWindows()) {
// TODO https://github.com/ziglang/zig/issues/508
return error.SkipZigTest;
}
test__floattitf(0, 0.0);
test__floattitf(1, 1.0);

View File

@ -7,6 +7,10 @@ fn test__floatuntitf(a: u128, expected: f128) void {
}
test "floatuntitf" {
if (@import("std").Target.current.isWindows()) {
// TODO https://github.com/ziglang/zig/issues/508
return error.SkipZigTest;
}
test__floatuntitf(0, 0.0);
test__floatuntitf(1, 1.0);

View File

@ -1,6 +1,8 @@
// Builtin functions that operate on integer types
const builtin = @import("builtin");
const testing = @import("std").testing;
const maxInt = @import("std").math.maxInt;
const minInt = @import("std").math.minInt;
const udivmod = @import("udivmod.zig").udivmod;
@ -578,3 +580,61 @@ fn test_one_umodsi3(a: u32, b: u32, expected_r: u32) void {
const r: u32 = __umodsi3(a, b);
testing.expect(r == expected_r);
}
pub fn __mulsi3(a: i32, b: i32) callconv(.C) i32 {
@setRuntimeSafety(builtin.is_test);
var ua = @bitCast(u32, a);
var ub = @bitCast(u32, b);
var r: u32 = 0;
while (ua > 0) {
if ((ua & 1) != 0) r +%= ub;
ua >>= 1;
ub <<= 1;
}
return @bitCast(i32, r);
}
fn test_one_mulsi3(a: i32, b: i32, result: i32) void {
testing.expectEqual(result, __mulsi3(a, b));
}
test "mulsi3" {
test_one_mulsi3(0, 0, 0);
test_one_mulsi3(0, 1, 0);
test_one_mulsi3(1, 0, 0);
test_one_mulsi3(0, 10, 0);
test_one_mulsi3(10, 0, 0);
test_one_mulsi3(0, maxInt(i32), 0);
test_one_mulsi3(maxInt(i32), 0, 0);
test_one_mulsi3(0, -1, 0);
test_one_mulsi3(-1, 0, 0);
test_one_mulsi3(0, -10, 0);
test_one_mulsi3(-10, 0, 0);
test_one_mulsi3(0, minInt(i32), 0);
test_one_mulsi3(minInt(i32), 0, 0);
test_one_mulsi3(1, 1, 1);
test_one_mulsi3(1, 10, 10);
test_one_mulsi3(10, 1, 10);
test_one_mulsi3(1, maxInt(i32), maxInt(i32));
test_one_mulsi3(maxInt(i32), 1, maxInt(i32));
test_one_mulsi3(1, -1, -1);
test_one_mulsi3(1, -10, -10);
test_one_mulsi3(-10, 1, -10);
test_one_mulsi3(1, minInt(i32), minInt(i32));
test_one_mulsi3(minInt(i32), 1, minInt(i32));
test_one_mulsi3(46340, 46340, 2147395600);
test_one_mulsi3(-46340, 46340, -2147395600);
test_one_mulsi3(46340, -46340, -2147395600);
test_one_mulsi3(-46340, -46340, 2147395600);
test_one_mulsi3(4194303, 8192, @truncate(i32, 34359730176));
test_one_mulsi3(-4194303, 8192, @truncate(i32, -34359730176));
test_one_mulsi3(4194303, -8192, @truncate(i32, -34359730176));
test_one_mulsi3(-4194303, -8192, @truncate(i32, 34359730176));
test_one_mulsi3(8192, 4194303, @truncate(i32, 34359730176));
test_one_mulsi3(-8192, 4194303, @truncate(i32, -34359730176));
test_one_mulsi3(8192, -4194303, @truncate(i32, -34359730176));
test_one_mulsi3(-8192, -4194303, @truncate(i32, 34359730176));
}

View File

@ -44,6 +44,10 @@ fn makeNaN128(rand: u64) f128 {
return float_result;
}
test "multf3" {
if (@import("std").Target.current.isWindows()) {
// TODO https://github.com/ziglang/zig/issues/508
return error.SkipZigTest;
}
// qNaN * any = qNaN
test__multf3(qnan128, 0x1.23456789abcdefp+5, 0x7fff800000000000, 0x0);

View File

@ -151,6 +151,10 @@ fn test__trunctfsf2(a: f128, expected: u32) void {
}
test "trunctfsf2" {
if (@import("std").Target.current.isWindows()) {
// TODO https://github.com/ziglang/zig/issues/508
return error.SkipZigTest;
}
// qnan
test__trunctfsf2(@bitCast(f128, @as(u128, 0x7fff800000000000 << 64)), 0x7fc00000);
// nan
@ -186,6 +190,10 @@ fn test__trunctfdf2(a: f128, expected: u64) void {
}
test "trunctfdf2" {
if (@import("std").Target.current.isWindows()) {
// TODO https://github.com/ziglang/zig/issues/508
return error.SkipZigTest;
}
// qnan
test__trunctfdf2(@bitCast(f128, @as(u128, 0x7fff800000000000 << 64)), 0x7ff8000000000000);
// nan

View File

@ -49,6 +49,22 @@ pub const Target = union(enum) {
other,
};
pub const aarch64 = @import("target/aarch64.zig");
pub const amdgpu = @import("target/amdgpu.zig");
pub const arm = @import("target/arm.zig");
pub const avr = @import("target/avr.zig");
pub const bpf = @import("target/bpf.zig");
pub const hexagon = @import("target/hexagon.zig");
pub const mips = @import("target/mips.zig");
pub const msp430 = @import("target/msp430.zig");
pub const nvptx = @import("target/nvptx.zig");
pub const powerpc = @import("target/powerpc.zig");
pub const riscv = @import("target/riscv.zig");
pub const sparc = @import("target/sparc.zig");
pub const systemz = @import("target/systemz.zig");
pub const wasm = @import("target/wasm.zig");
pub const x86 = @import("target/x86.zig");
pub const Arch = union(enum) {
arm: Arm32,
armeb: Arm32,
@ -108,12 +124,12 @@ pub const Target = union(enum) {
v8_3a,
v8_2a,
v8_1a,
v8,
v8a,
v8r,
v8m_baseline,
v8m_mainline,
v8_1m_mainline,
v7,
v7a,
v7em,
v7m,
v7s,
@ -129,8 +145,8 @@ pub const Target = union(enum) {
pub fn version(version: Arm32) comptime_int {
return switch (version) {
.v8_5a, .v8_4a, .v8_3a, .v8_2a, .v8_1a, .v8, .v8r, .v8m_baseline, .v8m_mainline, .v8_1m_mainline => 8,
.v7, .v7em, .v7m, .v7s, .v7k, .v7ve => 7,
.v8_5a, .v8_4a, .v8_3a, .v8_2a, .v8_1a, .v8a, .v8r, .v8m_baseline, .v8m_mainline, .v8_1m_mainline => 8,
.v7a, .v7em, .v7m, .v7s, .v7k, .v7ve => 7,
.v6, .v6m, .v6k, .v6t2 => 6,
.v5, .v5te => 5,
.v4t => 4,
@ -143,10 +159,7 @@ pub const Target = union(enum) {
v8_3a,
v8_2a,
v8_1a,
v8,
v8r,
v8m_baseline,
v8m_mainline,
v8a,
};
pub const Kalimba = enum {
v5,
@ -160,6 +173,54 @@ pub const Target = union(enum) {
spe,
};
pub fn subArchName(arch: Arch) ?[]const u8 {
return switch (arch) {
.arm, .armeb, .thumb, .thumbeb => |arm32| @tagName(arm32),
.aarch64, .aarch64_be, .aarch64_32 => |arm64| @tagName(arm64),
.kalimba => |kalimba| @tagName(kalimba),
else => return null,
};
}
pub fn subArchFeature(arch: Arch) ?Cpu.Feature.Set.Index {
return switch (arch) {
.arm, .armeb, .thumb, .thumbeb => |arm32| switch (arm32) {
.v8_5a => @enumToInt(arm.Feature.armv8_5_a),
.v8_4a => @enumToInt(arm.Feature.armv8_4_a),
.v8_3a => @enumToInt(arm.Feature.armv8_3_a),
.v8_2a => @enumToInt(arm.Feature.armv8_2_a),
.v8_1a => @enumToInt(arm.Feature.armv8_1_a),
.v8a => @enumToInt(arm.Feature.armv8_a),
.v8r => @enumToInt(arm.Feature.armv8_r),
.v8m_baseline => @enumToInt(arm.Feature.armv8_m_base),
.v8m_mainline => @enumToInt(arm.Feature.armv8_m_main),
.v8_1m_mainline => @enumToInt(arm.Feature.armv8_1_m_main),
.v7a => @enumToInt(arm.Feature.armv7_a),
.v7em => @enumToInt(arm.Feature.armv7e_m),
.v7m => @enumToInt(arm.Feature.armv7_m),
.v7s => @enumToInt(arm.Feature.armv7s),
.v7k => @enumToInt(arm.Feature.armv7k),
.v7ve => @enumToInt(arm.Feature.armv7ve),
.v6 => @enumToInt(arm.Feature.armv6),
.v6m => @enumToInt(arm.Feature.armv6_m),
.v6k => @enumToInt(arm.Feature.armv6k),
.v6t2 => @enumToInt(arm.Feature.armv6t2),
.v5 => @enumToInt(arm.Feature.armv5t),
.v5te => @enumToInt(arm.Feature.armv5te),
.v4t => @enumToInt(arm.Feature.armv4t),
},
.aarch64, .aarch64_be, .aarch64_32 => |arm64| switch (arm64) {
.v8_5a => @enumToInt(aarch64.Feature.v8_5a),
.v8_4a => @enumToInt(aarch64.Feature.v8_4a),
.v8_3a => @enumToInt(aarch64.Feature.v8_3a),
.v8_2a => @enumToInt(aarch64.Feature.v8_2a),
.v8_1a => @enumToInt(aarch64.Feature.v8_1a),
.v8a => @enumToInt(aarch64.Feature.v8a),
},
else => return null,
};
}
pub fn isARM(arch: Arch) bool {
return switch (arch) {
.arm, .armeb => true,
@ -188,6 +249,53 @@ pub const Target = union(enum) {
};
}
pub fn parseCpu(arch: Arch, cpu_name: []const u8) !*const Cpu {
for (arch.allCpus()) |cpu| {
if (mem.eql(u8, cpu_name, cpu.name)) {
return cpu;
}
}
return error.UnknownCpu;
}
/// Comma-separated list of features, with + or - in front of each feature. This
/// form represents a deviation from baseline CPU, which is provided as a parameter.
/// Extra commas are ignored.
pub fn parseCpuFeatureSet(arch: Arch, cpu: *const Cpu, features_text: []const u8) !Cpu.Feature.Set {
const all_features = arch.allFeaturesList();
var set = cpu.features;
var it = mem.tokenize(features_text, ",");
while (it.next()) |item_text| {
var feature_name: []const u8 = undefined;
var op: enum {
add,
sub,
} = undefined;
if (mem.startsWith(u8, item_text, "+")) {
op = .add;
feature_name = item_text[1..];
} else if (mem.startsWith(u8, item_text, "-")) {
op = .sub;
feature_name = item_text[1..];
} else {
return error.InvalidCpuFeatures;
}
for (all_features) |feature, index_usize| {
const index = @intCast(Cpu.Feature.Set.Index, index_usize);
if (mem.eql(u8, feature_name, feature.name)) {
switch (op) {
.add => set.addFeature(index),
.sub => set.removeFeature(index),
}
break;
}
} else {
return error.UnknownCpuFeature;
}
}
return set;
}
pub fn toElfMachine(arch: Arch) std.elf.EM {
return switch (arch) {
.avr => ._AVR,
@ -300,6 +408,109 @@ pub const Target = union(enum) {
=> .Big,
};
}
/// Returns a name that matches the lib/std/target/* directory name.
pub fn genericName(arch: Arch) []const u8 {
return switch (arch) {
.arm, .armeb, .thumb, .thumbeb => "arm",
.aarch64, .aarch64_be, .aarch64_32 => "aarch64",
.avr => "avr",
.bpfel, .bpfeb => "bpf",
.hexagon => "hexagon",
.mips, .mipsel, .mips64, .mips64el => "mips",
.msp430 => "msp430",
.powerpc, .powerpc64, .powerpc64le => "powerpc",
.amdgcn => "amdgpu",
.riscv32, .riscv64 => "riscv",
.sparc, .sparcv9, .sparcel => "sparc",
.s390x => "systemz",
.i386, .x86_64 => "x86",
.nvptx, .nvptx64 => "nvptx",
.wasm32, .wasm64 => "wasm",
else => @tagName(arch),
};
}
/// All CPU features Zig is aware of, sorted lexicographically by name.
pub fn allFeaturesList(arch: Arch) []const Cpu.Feature {
return switch (arch) {
.arm, .armeb, .thumb, .thumbeb => &arm.all_features,
.aarch64, .aarch64_be, .aarch64_32 => &aarch64.all_features,
.avr => &avr.all_features,
.bpfel, .bpfeb => &bpf.all_features,
.hexagon => &hexagon.all_features,
.mips, .mipsel, .mips64, .mips64el => &mips.all_features,
.msp430 => &msp430.all_features,
.powerpc, .powerpc64, .powerpc64le => &powerpc.all_features,
.amdgcn => &amdgpu.all_features,
.riscv32, .riscv64 => &riscv.all_features,
.sparc, .sparcv9, .sparcel => &sparc.all_features,
.s390x => &systemz.all_features,
.i386, .x86_64 => &x86.all_features,
.nvptx, .nvptx64 => &nvptx.all_features,
.wasm32, .wasm64 => &wasm.all_features,
else => &[0]Cpu.Feature{},
};
}
/// The "default" set of CPU features for cross-compiling. A conservative set
/// of features that is expected to be supported on most available hardware.
pub fn getBaselineCpuFeatures(arch: Arch) CpuFeatures {
const S = struct {
const generic_cpu = Cpu{
.name = "generic",
.llvm_name = null,
.features = Cpu.Feature.Set.empty,
};
};
const cpu = switch (arch) {
.arm, .armeb, .thumb, .thumbeb => &arm.cpu.generic,
.aarch64, .aarch64_be, .aarch64_32 => &aarch64.cpu.generic,
.avr => &avr.cpu.avr1,
.bpfel, .bpfeb => &bpf.cpu.generic,
.hexagon => &hexagon.cpu.generic,
.mips, .mipsel => &mips.cpu.mips32,
.mips64, .mips64el => &mips.cpu.mips64,
.msp430 => &msp430.cpu.generic,
.powerpc, .powerpc64, .powerpc64le => &powerpc.cpu.generic,
.amdgcn => &amdgpu.cpu.generic,
.riscv32 => &riscv.cpu.baseline_rv32,
.riscv64 => &riscv.cpu.baseline_rv64,
.sparc, .sparcv9, .sparcel => &sparc.cpu.generic,
.s390x => &systemz.cpu.generic,
.i386 => &x86.cpu.pentium4,
.x86_64 => &x86.cpu.x86_64,
.nvptx, .nvptx64 => &nvptx.cpu.sm_20,
.wasm32, .wasm64 => &wasm.cpu.generic,
else => &S.generic_cpu,
};
return CpuFeatures.initFromCpu(arch, cpu);
}
/// All CPUs Zig is aware of, sorted lexicographically by name.
pub fn allCpus(arch: Arch) []const *const Cpu {
return switch (arch) {
.arm, .armeb, .thumb, .thumbeb => arm.all_cpus,
.aarch64, .aarch64_be, .aarch64_32 => aarch64.all_cpus,
.avr => avr.all_cpus,
.bpfel, .bpfeb => bpf.all_cpus,
.hexagon => hexagon.all_cpus,
.mips, .mipsel, .mips64, .mips64el => mips.all_cpus,
.msp430 => msp430.all_cpus,
.powerpc, .powerpc64, .powerpc64le => powerpc.all_cpus,
.amdgcn => amdgpu.all_cpus,
.riscv32, .riscv64 => riscv.all_cpus,
.sparc, .sparcv9, .sparcel => sparc.all_cpus,
.s390x => systemz.all_cpus,
.i386, .x86_64 => x86.all_cpus,
.nvptx, .nvptx64 => nvptx.all_cpus,
.wasm32, .wasm64 => wasm.all_cpus,
else => &[0]*const Cpu{},
};
}
};
pub const Abi = enum {
@ -325,6 +536,109 @@ pub const Target = union(enum) {
macabi,
};
pub const Cpu = struct {
name: []const u8,
llvm_name: ?[:0]const u8,
features: Feature.Set,
pub const Feature = struct {
/// The bit index into `Set`. Has a default value of `undefined` because the canonical
/// structures are populated via comptime logic.
index: Set.Index = undefined,
/// Has a default value of `undefined` because the canonical
/// structures are populated via comptime logic.
name: []const u8 = undefined,
/// If this corresponds to an LLVM-recognized feature, this will be populated;
/// otherwise null.
llvm_name: ?[:0]const u8,
/// Human-friendly UTF-8 text.
description: []const u8,
/// Sparse `Set` of features this depends on.
dependencies: Set,
/// A bit set of all the features.
pub const Set = struct {
ints: [usize_count]usize,
pub const needed_bit_count = 174;
pub const byte_count = (needed_bit_count + 7) / 8;
pub const usize_count = (byte_count + (@sizeOf(usize) - 1)) / @sizeOf(usize);
pub const Index = std.math.Log2Int(@IntType(false, usize_count * @bitSizeOf(usize)));
pub const ShiftInt = std.math.Log2Int(usize);
pub const empty = Set{ .ints = [1]usize{0} ** usize_count };
pub fn empty_workaround() Set {
return Set{ .ints = [1]usize{0} ** usize_count };
}
pub fn isEnabled(set: Set, arch_feature_index: Index) bool {
const usize_index = arch_feature_index / @bitSizeOf(usize);
const bit_index = @intCast(ShiftInt, arch_feature_index % @bitSizeOf(usize));
return (set.ints[usize_index] & (@as(usize, 1) << bit_index)) != 0;
}
/// Adds the specified feature but not its dependencies.
pub fn addFeature(set: *Set, arch_feature_index: Index) void {
const usize_index = arch_feature_index / @bitSizeOf(usize);
const bit_index = @intCast(ShiftInt, arch_feature_index % @bitSizeOf(usize));
set.ints[usize_index] |= @as(usize, 1) << bit_index;
}
/// Removes the specified feature but not its dependents.
pub fn removeFeature(set: *Set, arch_feature_index: Index) void {
const usize_index = arch_feature_index / @bitSizeOf(usize);
const bit_index = @intCast(ShiftInt, arch_feature_index % @bitSizeOf(usize));
set.ints[usize_index] &= ~(@as(usize, 1) << bit_index);
}
pub fn populateDependencies(set: *Set, all_features_list: []const Cpu.Feature) void {
var old = set.ints;
while (true) {
for (all_features_list) |feature, index_usize| {
const index = @intCast(Index, index_usize);
if (set.isEnabled(index)) {
set.ints = @as(@Vector(usize_count, usize), set.ints) |
@as(@Vector(usize_count, usize), feature.dependencies.ints);
}
}
const nothing_changed = mem.eql(usize, &old, &set.ints);
if (nothing_changed) return;
old = set.ints;
}
}
pub fn asBytes(set: *const Set) *const [byte_count]u8 {
return @ptrCast(*const [byte_count]u8, &set.ints);
}
pub fn eql(set: Set, other: Set) bool {
return mem.eql(usize, &set.ints, &other.ints);
}
};
pub fn feature_set_fns(comptime F: type) type {
return struct {
/// Populates only the feature bits specified.
pub fn featureSet(features: []const F) Set {
var x = Set.empty_workaround(); // TODO remove empty_workaround
for (features) |feature| {
x.addFeature(@enumToInt(feature));
}
return x;
}
pub fn featureSetHas(set: Set, feature: F) bool {
return set.isEnabled(@enumToInt(feature));
}
};
}
};
};
pub const ObjectFormat = enum {
unknown,
coff,
@ -348,6 +662,28 @@ pub const Target = union(enum) {
arch: Arch,
os: Os,
abi: Abi,
cpu_features: CpuFeatures,
};
pub const CpuFeatures = struct {
/// The CPU to target. It has a set of features
/// which are overridden with the `features` field.
cpu: *const Cpu,
/// Explicitly provide the entire CPU feature set.
features: Cpu.Feature.Set,
pub fn initFromCpu(arch: Arch, cpu: *const Cpu) CpuFeatures {
var features = cpu.features;
if (arch.subArchFeature()) |sub_arch_index| {
features.addFeature(sub_arch_index);
}
features.populateDependencies(arch.allFeaturesList());
return CpuFeatures{
.cpu = cpu,
.features = features,
};
}
};
pub const current = Target{
@ -355,11 +691,19 @@ pub const Target = union(enum) {
.arch = builtin.arch,
.os = builtin.os,
.abi = builtin.abi,
.cpu_features = builtin.cpu_features,
},
};
pub const stack_align = 16;
pub fn getCpuFeatures(self: Target) CpuFeatures {
return switch (self) {
.Native => builtin.cpu_features,
.Cross => |cross| cross.cpu_features,
};
}
pub fn zigTriple(self: Target, allocator: *mem.Allocator) ![]u8 {
return std.fmt.allocPrint(allocator, "{}{}-{}-{}", .{
@tagName(self.getArch()),
@ -425,14 +769,18 @@ pub const Target = union(enum) {
});
}
/// TODO: Support CPU features here?
/// https://github.com/ziglang/zig/issues/4261
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();
const arch = try parseArchSub(arch_name);
var cross = Cross{
.arch = try parseArchSub(arch_name),
.arch = arch,
.cpu_features = arch.getBaselineCpuFeatures(),
.os = try parseOs(os_name),
.abi = undefined,
};
@ -498,7 +846,7 @@ pub const Target = union(enum) {
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 (mem.startsWith(u8, text, field.name)) {
if (field.field_type == void) {
return @as(Arch, @field(Arch, field.name));
} else {
@ -819,3 +1167,15 @@ pub const Target = union(enum) {
return .unavailable;
}
};
test "parseCpuFeatureSet" {
const arch: Target.Arch = .x86_64;
const baseline = arch.getBaselineCpuFeatures();
const set = try arch.parseCpuFeatureSet(baseline.cpu, "-sse,-avx,-cx8");
std.testing.expect(!Target.x86.featureSetHas(set, .sse));
std.testing.expect(!Target.x86.featureSetHas(set, .avx));
std.testing.expect(!Target.x86.featureSetHas(set, .cx8));
// These are expected because they are part of the baseline
std.testing.expect(Target.x86.featureSetHas(set, .cmov));
std.testing.expect(Target.x86.featureSetHas(set, .fxsr));
}

1450
lib/std/target/aarch64.zig Normal file

File diff suppressed because it is too large Load Diff

1315
lib/std/target/amdgpu.zig Normal file

File diff suppressed because it is too large Load Diff

2333
lib/std/target/arm.zig Normal file

File diff suppressed because it is too large Load Diff

2380
lib/std/target/avr.zig Normal file

File diff suppressed because it is too large Load Diff

76
lib/std/target/bpf.zig Normal file
View File

@ -0,0 +1,76 @@
const std = @import("../std.zig");
const Cpu = std.Target.Cpu;
pub const Feature = enum {
alu32,
dummy,
dwarfris,
};
pub usingnamespace Cpu.Feature.feature_set_fns(Feature);
pub const all_features = blk: {
const len = @typeInfo(Feature).Enum.fields.len;
std.debug.assert(len <= Cpu.Feature.Set.needed_bit_count);
var result: [len]Cpu.Feature = undefined;
result[@enumToInt(Feature.alu32)] = .{
.llvm_name = "alu32",
.description = "Enable ALU32 instructions",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.dummy)] = .{
.llvm_name = "dummy",
.description = "unused feature",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.dwarfris)] = .{
.llvm_name = "dwarfris",
.description = "Disable MCAsmInfo DwarfUsesRelocationsAcrossSections",
.dependencies = featureSet(&[_]Feature{}),
};
const ti = @typeInfo(Feature);
for (result) |*elem, i| {
elem.index = i;
elem.name = ti.Enum.fields[i].name;
}
break :blk result;
};
pub const cpu = struct {
pub const generic = Cpu{
.name = "generic",
.llvm_name = "generic",
.features = featureSet(&[_]Feature{}),
};
pub const probe = Cpu{
.name = "probe",
.llvm_name = "probe",
.features = featureSet(&[_]Feature{}),
};
pub const v1 = Cpu{
.name = "v1",
.llvm_name = "v1",
.features = featureSet(&[_]Feature{}),
};
pub const v2 = Cpu{
.name = "v2",
.llvm_name = "v2",
.features = featureSet(&[_]Feature{}),
};
pub const v3 = Cpu{
.name = "v3",
.llvm_name = "v3",
.features = featureSet(&[_]Feature{}),
};
};
/// All bpf CPUs, sorted alphabetically by name.
/// TODO: Replace this with usage of `std.meta.declList`. It does work, but stage1
/// compiler has inefficient memory and CPU usage, affecting build times.
pub const all_cpus = &[_]*const Cpu{
&cpu.generic,
&cpu.probe,
&cpu.v1,
&cpu.v2,
&cpu.v3,
};

312
lib/std/target/hexagon.zig Normal file
View File

@ -0,0 +1,312 @@
const std = @import("../std.zig");
const Cpu = std.Target.Cpu;
pub const Feature = enum {
duplex,
hvx,
hvx_length128b,
hvx_length64b,
hvxv60,
hvxv62,
hvxv65,
hvxv66,
long_calls,
mem_noshuf,
memops,
noreturn_stack_elim,
nvj,
nvs,
packets,
reserved_r19,
small_data,
v5,
v55,
v60,
v62,
v65,
v66,
zreg,
};
pub usingnamespace Cpu.Feature.feature_set_fns(Feature);
pub const all_features = blk: {
const len = @typeInfo(Feature).Enum.fields.len;
std.debug.assert(len <= Cpu.Feature.Set.needed_bit_count);
var result: [len]Cpu.Feature = undefined;
result[@enumToInt(Feature.duplex)] = .{
.llvm_name = "duplex",
.description = "Enable generation of duplex instruction",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.hvx)] = .{
.llvm_name = "hvx",
.description = "Hexagon HVX instructions",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.hvx_length128b)] = .{
.llvm_name = "hvx-length128b",
.description = "Hexagon HVX 128B instructions",
.dependencies = featureSet(&[_]Feature{
.hvx,
}),
};
result[@enumToInt(Feature.hvx_length64b)] = .{
.llvm_name = "hvx-length64b",
.description = "Hexagon HVX 64B instructions",
.dependencies = featureSet(&[_]Feature{
.hvx,
}),
};
result[@enumToInt(Feature.hvxv60)] = .{
.llvm_name = "hvxv60",
.description = "Hexagon HVX instructions",
.dependencies = featureSet(&[_]Feature{
.hvx,
}),
};
result[@enumToInt(Feature.hvxv62)] = .{
.llvm_name = "hvxv62",
.description = "Hexagon HVX instructions",
.dependencies = featureSet(&[_]Feature{
.hvx,
.hvxv60,
}),
};
result[@enumToInt(Feature.hvxv65)] = .{
.llvm_name = "hvxv65",
.description = "Hexagon HVX instructions",
.dependencies = featureSet(&[_]Feature{
.hvx,
.hvxv60,
.hvxv62,
}),
};
result[@enumToInt(Feature.hvxv66)] = .{
.llvm_name = "hvxv66",
.description = "Hexagon HVX instructions",
.dependencies = featureSet(&[_]Feature{
.hvx,
.hvxv60,
.hvxv62,
.hvxv65,
.zreg,
}),
};
result[@enumToInt(Feature.long_calls)] = .{
.llvm_name = "long-calls",
.description = "Use constant-extended calls",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.mem_noshuf)] = .{
.llvm_name = "mem_noshuf",
.description = "Supports mem_noshuf feature",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.memops)] = .{
.llvm_name = "memops",
.description = "Use memop instructions",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.noreturn_stack_elim)] = .{
.llvm_name = "noreturn-stack-elim",
.description = "Eliminate stack allocation in a noreturn function when possible",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.nvj)] = .{
.llvm_name = "nvj",
.description = "Support for new-value jumps",
.dependencies = featureSet(&[_]Feature{
.packets,
}),
};
result[@enumToInt(Feature.nvs)] = .{
.llvm_name = "nvs",
.description = "Support for new-value stores",
.dependencies = featureSet(&[_]Feature{
.packets,
}),
};
result[@enumToInt(Feature.packets)] = .{
.llvm_name = "packets",
.description = "Support for instruction packets",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.reserved_r19)] = .{
.llvm_name = "reserved-r19",
.description = "Reserve register R19",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.small_data)] = .{
.llvm_name = "small-data",
.description = "Allow GP-relative addressing of global variables",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.v5)] = .{
.llvm_name = "v5",
.description = "Enable Hexagon V5 architecture",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.v55)] = .{
.llvm_name = "v55",
.description = "Enable Hexagon V55 architecture",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.v60)] = .{
.llvm_name = "v60",
.description = "Enable Hexagon V60 architecture",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.v62)] = .{
.llvm_name = "v62",
.description = "Enable Hexagon V62 architecture",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.v65)] = .{
.llvm_name = "v65",
.description = "Enable Hexagon V65 architecture",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.v66)] = .{
.llvm_name = "v66",
.description = "Enable Hexagon V66 architecture",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.zreg)] = .{
.llvm_name = "zreg",
.description = "Hexagon ZReg extension instructions",
.dependencies = featureSet(&[_]Feature{}),
};
const ti = @typeInfo(Feature);
for (result) |*elem, i| {
elem.index = i;
elem.name = ti.Enum.fields[i].name;
}
break :blk result;
};
pub const cpu = struct {
pub const generic = Cpu{
.name = "generic",
.llvm_name = "generic",
.features = featureSet(&[_]Feature{
.duplex,
.memops,
.nvj,
.nvs,
.packets,
.small_data,
.v5,
.v55,
.v60,
}),
};
pub const hexagonv5 = Cpu{
.name = "hexagonv5",
.llvm_name = "hexagonv5",
.features = featureSet(&[_]Feature{
.duplex,
.memops,
.nvj,
.nvs,
.packets,
.small_data,
.v5,
}),
};
pub const hexagonv55 = Cpu{
.name = "hexagonv55",
.llvm_name = "hexagonv55",
.features = featureSet(&[_]Feature{
.duplex,
.memops,
.nvj,
.nvs,
.packets,
.small_data,
.v5,
.v55,
}),
};
pub const hexagonv60 = Cpu{
.name = "hexagonv60",
.llvm_name = "hexagonv60",
.features = featureSet(&[_]Feature{
.duplex,
.memops,
.nvj,
.nvs,
.packets,
.small_data,
.v5,
.v55,
.v60,
}),
};
pub const hexagonv62 = Cpu{
.name = "hexagonv62",
.llvm_name = "hexagonv62",
.features = featureSet(&[_]Feature{
.duplex,
.memops,
.nvj,
.nvs,
.packets,
.small_data,
.v5,
.v55,
.v60,
.v62,
}),
};
pub const hexagonv65 = Cpu{
.name = "hexagonv65",
.llvm_name = "hexagonv65",
.features = featureSet(&[_]Feature{
.duplex,
.mem_noshuf,
.memops,
.nvj,
.nvs,
.packets,
.small_data,
.v5,
.v55,
.v60,
.v62,
.v65,
}),
};
pub const hexagonv66 = Cpu{
.name = "hexagonv66",
.llvm_name = "hexagonv66",
.features = featureSet(&[_]Feature{
.duplex,
.mem_noshuf,
.memops,
.nvj,
.nvs,
.packets,
.small_data,
.v5,
.v55,
.v60,
.v62,
.v65,
.v66,
}),
};
};
/// All hexagon CPUs, sorted alphabetically by name.
/// TODO: Replace this with usage of `std.meta.declList`. It does work, but stage1
/// compiler has inefficient memory and CPU usage, affecting build times.
pub const all_cpus = &[_]*const Cpu{
&cpu.generic,
&cpu.hexagonv5,
&cpu.hexagonv55,
&cpu.hexagonv60,
&cpu.hexagonv62,
&cpu.hexagonv65,
&cpu.hexagonv66,
};

518
lib/std/target/mips.zig Normal file
View File

@ -0,0 +1,518 @@
const std = @import("../std.zig");
const Cpu = std.Target.Cpu;
pub const Feature = enum {
abs2008,
cnmips,
crc,
dsp,
dspr2,
dspr3,
eva,
fp64,
fpxx,
ginv,
gp64,
long_calls,
micromips,
mips1,
mips16,
mips2,
mips3,
mips32,
mips32r2,
mips32r3,
mips32r5,
mips32r6,
mips3_32,
mips3_32r2,
mips4,
mips4_32,
mips4_32r2,
mips5,
mips5_32r2,
mips64,
mips64r2,
mips64r3,
mips64r5,
mips64r6,
msa,
mt,
nan2008,
noabicalls,
nomadd4,
nooddspreg,
p5600,
ptr64,
single_float,
soft_float,
sym32,
use_indirect_jump_hazard,
use_tcc_in_div,
vfpu,
virt,
};
pub usingnamespace Cpu.Feature.feature_set_fns(Feature);
pub const all_features = blk: {
const len = @typeInfo(Feature).Enum.fields.len;
std.debug.assert(len <= Cpu.Feature.Set.needed_bit_count);
var result: [len]Cpu.Feature = undefined;
result[@enumToInt(Feature.abs2008)] = .{
.llvm_name = "abs2008",
.description = "Disable IEEE 754-2008 abs.fmt mode",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.cnmips)] = .{
.llvm_name = "cnmips",
.description = "Octeon cnMIPS Support",
.dependencies = featureSet(&[_]Feature{
.mips64r2,
}),
};
result[@enumToInt(Feature.crc)] = .{
.llvm_name = "crc",
.description = "Mips R6 CRC ASE",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.dsp)] = .{
.llvm_name = "dsp",
.description = "Mips DSP ASE",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.dspr2)] = .{
.llvm_name = "dspr2",
.description = "Mips DSP-R2 ASE",
.dependencies = featureSet(&[_]Feature{
.dsp,
}),
};
result[@enumToInt(Feature.dspr3)] = .{
.llvm_name = "dspr3",
.description = "Mips DSP-R3 ASE",
.dependencies = featureSet(&[_]Feature{
.dsp,
.dspr2,
}),
};
result[@enumToInt(Feature.eva)] = .{
.llvm_name = "eva",
.description = "Mips EVA ASE",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.fp64)] = .{
.llvm_name = "fp64",
.description = "Support 64-bit FP registers",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.fpxx)] = .{
.llvm_name = "fpxx",
.description = "Support for FPXX",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.ginv)] = .{
.llvm_name = "ginv",
.description = "Mips Global Invalidate ASE",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.gp64)] = .{
.llvm_name = "gp64",
.description = "General Purpose Registers are 64-bit wide",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.long_calls)] = .{
.llvm_name = "long-calls",
.description = "Disable use of the jal instruction",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.micromips)] = .{
.llvm_name = "micromips",
.description = "microMips mode",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.mips1)] = .{
.llvm_name = "mips1",
.description = "Mips I ISA Support [highly experimental]",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.mips16)] = .{
.llvm_name = "mips16",
.description = "Mips16 mode",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.mips2)] = .{
.llvm_name = "mips2",
.description = "Mips II ISA Support [highly experimental]",
.dependencies = featureSet(&[_]Feature{
.mips1,
}),
};
result[@enumToInt(Feature.mips3)] = .{
.llvm_name = "mips3",
.description = "MIPS III ISA Support [highly experimental]",
.dependencies = featureSet(&[_]Feature{
.fp64,
.gp64,
.mips2,
.mips3_32,
.mips3_32r2,
}),
};
result[@enumToInt(Feature.mips32)] = .{
.llvm_name = "mips32",
.description = "Mips32 ISA Support",
.dependencies = featureSet(&[_]Feature{
.mips2,
.mips3_32,
.mips4_32,
}),
};
result[@enumToInt(Feature.mips32r2)] = .{
.llvm_name = "mips32r2",
.description = "Mips32r2 ISA Support",
.dependencies = featureSet(&[_]Feature{
.mips32,
.mips3_32r2,
.mips4_32r2,
.mips5_32r2,
}),
};
result[@enumToInt(Feature.mips32r3)] = .{
.llvm_name = "mips32r3",
.description = "Mips32r3 ISA Support",
.dependencies = featureSet(&[_]Feature{
.mips32r2,
}),
};
result[@enumToInt(Feature.mips32r5)] = .{
.llvm_name = "mips32r5",
.description = "Mips32r5 ISA Support",
.dependencies = featureSet(&[_]Feature{
.mips32r3,
}),
};
result[@enumToInt(Feature.mips32r6)] = .{
.llvm_name = "mips32r6",
.description = "Mips32r6 ISA Support [experimental]",
.dependencies = featureSet(&[_]Feature{
.abs2008,
.fp64,
.mips32r5,
.nan2008,
}),
};
result[@enumToInt(Feature.mips3_32)] = .{
.llvm_name = "mips3_32",
.description = "Subset of MIPS-III that is also in MIPS32 [highly experimental]",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.mips3_32r2)] = .{
.llvm_name = "mips3_32r2",
.description = "Subset of MIPS-III that is also in MIPS32r2 [highly experimental]",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.mips4)] = .{
.llvm_name = "mips4",
.description = "MIPS IV ISA Support",
.dependencies = featureSet(&[_]Feature{
.mips3,
.mips4_32,
.mips4_32r2,
}),
};
result[@enumToInt(Feature.mips4_32)] = .{
.llvm_name = "mips4_32",
.description = "Subset of MIPS-IV that is also in MIPS32 [highly experimental]",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.mips4_32r2)] = .{
.llvm_name = "mips4_32r2",
.description = "Subset of MIPS-IV that is also in MIPS32r2 [highly experimental]",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.mips5)] = .{
.llvm_name = "mips5",
.description = "MIPS V ISA Support [highly experimental]",
.dependencies = featureSet(&[_]Feature{
.mips4,
.mips5_32r2,
}),
};
result[@enumToInt(Feature.mips5_32r2)] = .{
.llvm_name = "mips5_32r2",
.description = "Subset of MIPS-V that is also in MIPS32r2 [highly experimental]",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.mips64)] = .{
.llvm_name = "mips64",
.description = "Mips64 ISA Support",
.dependencies = featureSet(&[_]Feature{
.mips32,
.mips5,
}),
};
result[@enumToInt(Feature.mips64r2)] = .{
.llvm_name = "mips64r2",
.description = "Mips64r2 ISA Support",
.dependencies = featureSet(&[_]Feature{
.mips32r2,
.mips64,
}),
};
result[@enumToInt(Feature.mips64r3)] = .{
.llvm_name = "mips64r3",
.description = "Mips64r3 ISA Support",
.dependencies = featureSet(&[_]Feature{
.mips32r3,
.mips64r2,
}),
};
result[@enumToInt(Feature.mips64r5)] = .{
.llvm_name = "mips64r5",
.description = "Mips64r5 ISA Support",
.dependencies = featureSet(&[_]Feature{
.mips32r5,
.mips64r3,
}),
};
result[@enumToInt(Feature.mips64r6)] = .{
.llvm_name = "mips64r6",
.description = "Mips64r6 ISA Support [experimental]",
.dependencies = featureSet(&[_]Feature{
.abs2008,
.mips32r6,
.mips64r5,
.nan2008,
}),
};
result[@enumToInt(Feature.msa)] = .{
.llvm_name = "msa",
.description = "Mips MSA ASE",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.mt)] = .{
.llvm_name = "mt",
.description = "Mips MT ASE",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.nan2008)] = .{
.llvm_name = "nan2008",
.description = "IEEE 754-2008 NaN encoding",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.noabicalls)] = .{
.llvm_name = "noabicalls",
.description = "Disable SVR4-style position-independent code",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.nomadd4)] = .{
.llvm_name = "nomadd4",
.description = "Disable 4-operand madd.fmt and related instructions",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.nooddspreg)] = .{
.llvm_name = "nooddspreg",
.description = "Disable odd numbered single-precision registers",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.p5600)] = .{
.llvm_name = "p5600",
.description = "The P5600 Processor",
.dependencies = featureSet(&[_]Feature{
.mips32r5,
}),
};
result[@enumToInt(Feature.ptr64)] = .{
.llvm_name = "ptr64",
.description = "Pointers are 64-bit wide",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.single_float)] = .{
.llvm_name = "single-float",
.description = "Only supports single precision float",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.soft_float)] = .{
.llvm_name = "soft-float",
.description = "Does not support floating point instructions",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.sym32)] = .{
.llvm_name = "sym32",
.description = "Symbols are 32 bit on Mips64",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.use_indirect_jump_hazard)] = .{
.llvm_name = "use-indirect-jump-hazard",
.description = "Use indirect jump guards to prevent certain speculation based attacks",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.use_tcc_in_div)] = .{
.llvm_name = "use-tcc-in-div",
.description = "Force the assembler to use trapping",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.vfpu)] = .{
.llvm_name = "vfpu",
.description = "Enable vector FPU instructions",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.virt)] = .{
.llvm_name = "virt",
.description = "Mips Virtualization ASE",
.dependencies = featureSet(&[_]Feature{}),
};
const ti = @typeInfo(Feature);
for (result) |*elem, i| {
elem.index = i;
elem.name = ti.Enum.fields[i].name;
}
break :blk result;
};
pub const cpu = struct {
pub const mips1 = Cpu{
.name = "mips1",
.llvm_name = "mips1",
.features = featureSet(&[_]Feature{
.mips1,
}),
};
pub const mips2 = Cpu{
.name = "mips2",
.llvm_name = "mips2",
.features = featureSet(&[_]Feature{
.mips2,
}),
};
pub const mips3 = Cpu{
.name = "mips3",
.llvm_name = "mips3",
.features = featureSet(&[_]Feature{
.mips3,
}),
};
pub const mips32 = Cpu{
.name = "mips32",
.llvm_name = "mips32",
.features = featureSet(&[_]Feature{
.mips32,
}),
};
pub const mips32r2 = Cpu{
.name = "mips32r2",
.llvm_name = "mips32r2",
.features = featureSet(&[_]Feature{
.mips32r2,
}),
};
pub const mips32r3 = Cpu{
.name = "mips32r3",
.llvm_name = "mips32r3",
.features = featureSet(&[_]Feature{
.mips32r3,
}),
};
pub const mips32r5 = Cpu{
.name = "mips32r5",
.llvm_name = "mips32r5",
.features = featureSet(&[_]Feature{
.mips32r5,
}),
};
pub const mips32r6 = Cpu{
.name = "mips32r6",
.llvm_name = "mips32r6",
.features = featureSet(&[_]Feature{
.mips32r6,
}),
};
pub const mips4 = Cpu{
.name = "mips4",
.llvm_name = "mips4",
.features = featureSet(&[_]Feature{
.mips4,
}),
};
pub const mips5 = Cpu{
.name = "mips5",
.llvm_name = "mips5",
.features = featureSet(&[_]Feature{
.mips5,
}),
};
pub const mips64 = Cpu{
.name = "mips64",
.llvm_name = "mips64",
.features = featureSet(&[_]Feature{
.mips64,
}),
};
pub const mips64r2 = Cpu{
.name = "mips64r2",
.llvm_name = "mips64r2",
.features = featureSet(&[_]Feature{
.mips64r2,
}),
};
pub const mips64r3 = Cpu{
.name = "mips64r3",
.llvm_name = "mips64r3",
.features = featureSet(&[_]Feature{
.mips64r3,
}),
};
pub const mips64r5 = Cpu{
.name = "mips64r5",
.llvm_name = "mips64r5",
.features = featureSet(&[_]Feature{
.mips64r5,
}),
};
pub const mips64r6 = Cpu{
.name = "mips64r6",
.llvm_name = "mips64r6",
.features = featureSet(&[_]Feature{
.mips64r6,
}),
};
pub const octeon = Cpu{
.name = "octeon",
.llvm_name = "octeon",
.features = featureSet(&[_]Feature{
.cnmips,
.mips64r2,
}),
};
pub const p5600 = Cpu{
.name = "p5600",
.llvm_name = "p5600",
.features = featureSet(&[_]Feature{
.p5600,
}),
};
};
/// All mips CPUs, sorted alphabetically by name.
/// TODO: Replace this with usage of `std.meta.declList`. It does work, but stage1
/// compiler has inefficient memory and CPU usage, affecting build times.
pub const all_cpus = &[_]*const Cpu{
&cpu.mips1,
&cpu.mips2,
&cpu.mips3,
&cpu.mips32,
&cpu.mips32r2,
&cpu.mips32r3,
&cpu.mips32r5,
&cpu.mips32r6,
&cpu.mips4,
&cpu.mips5,
&cpu.mips64,
&cpu.mips64r2,
&cpu.mips64r3,
&cpu.mips64r5,
&cpu.mips64r6,
&cpu.octeon,
&cpu.p5600,
};

72
lib/std/target/msp430.zig Normal file
View File

@ -0,0 +1,72 @@
const std = @import("../std.zig");
const Cpu = std.Target.Cpu;
pub const Feature = enum {
ext,
hwmult16,
hwmult32,
hwmultf5,
};
pub usingnamespace Cpu.Feature.feature_set_fns(Feature);
pub const all_features = blk: {
const len = @typeInfo(Feature).Enum.fields.len;
std.debug.assert(len <= Cpu.Feature.Set.needed_bit_count);
var result: [len]Cpu.Feature = undefined;
result[@enumToInt(Feature.ext)] = .{
.llvm_name = "ext",
.description = "Enable MSP430-X extensions",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.hwmult16)] = .{
.llvm_name = "hwmult16",
.description = "Enable 16-bit hardware multiplier",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.hwmult32)] = .{
.llvm_name = "hwmult32",
.description = "Enable 32-bit hardware multiplier",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.hwmultf5)] = .{
.llvm_name = "hwmultf5",
.description = "Enable F5 series hardware multiplier",
.dependencies = featureSet(&[_]Feature{}),
};
const ti = @typeInfo(Feature);
for (result) |*elem, i| {
elem.index = i;
elem.name = ti.Enum.fields[i].name;
}
break :blk result;
};
pub const cpu = struct {
pub const generic = Cpu{
.name = "generic",
.llvm_name = "generic",
.features = featureSet(&[_]Feature{}),
};
pub const msp430 = Cpu{
.name = "msp430",
.llvm_name = "msp430",
.features = featureSet(&[_]Feature{}),
};
pub const msp430x = Cpu{
.name = "msp430x",
.llvm_name = "msp430x",
.features = featureSet(&[_]Feature{
.ext,
}),
};
};
/// All msp430 CPUs, sorted alphabetically by name.
/// TODO: Replace this with usage of `std.meta.declList`. It does work, but stage1
/// compiler has inefficient memory and CPU usage, affecting build times.
pub const all_cpus = &[_]*const Cpu{
&cpu.generic,
&cpu.msp430,
&cpu.msp430x,
};

309
lib/std/target/nvptx.zig Normal file
View File

@ -0,0 +1,309 @@
const std = @import("../std.zig");
const Cpu = std.Target.Cpu;
pub const Feature = enum {
ptx32,
ptx40,
ptx41,
ptx42,
ptx43,
ptx50,
ptx60,
ptx61,
ptx63,
ptx64,
sm_20,
sm_21,
sm_30,
sm_32,
sm_35,
sm_37,
sm_50,
sm_52,
sm_53,
sm_60,
sm_61,
sm_62,
sm_70,
sm_72,
sm_75,
};
pub usingnamespace Cpu.Feature.feature_set_fns(Feature);
pub const all_features = blk: {
const len = @typeInfo(Feature).Enum.fields.len;
std.debug.assert(len <= Cpu.Feature.Set.needed_bit_count);
var result: [len]Cpu.Feature = undefined;
result[@enumToInt(Feature.ptx32)] = .{
.llvm_name = "ptx32",
.description = "Use PTX version 3.2",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.ptx40)] = .{
.llvm_name = "ptx40",
.description = "Use PTX version 4.0",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.ptx41)] = .{
.llvm_name = "ptx41",
.description = "Use PTX version 4.1",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.ptx42)] = .{
.llvm_name = "ptx42",
.description = "Use PTX version 4.2",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.ptx43)] = .{
.llvm_name = "ptx43",
.description = "Use PTX version 4.3",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.ptx50)] = .{
.llvm_name = "ptx50",
.description = "Use PTX version 5.0",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.ptx60)] = .{
.llvm_name = "ptx60",
.description = "Use PTX version 6.0",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.ptx61)] = .{
.llvm_name = "ptx61",
.description = "Use PTX version 6.1",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.ptx63)] = .{
.llvm_name = "ptx63",
.description = "Use PTX version 6.3",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.ptx64)] = .{
.llvm_name = "ptx64",
.description = "Use PTX version 6.4",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.sm_20)] = .{
.llvm_name = "sm_20",
.description = "Target SM 2.0",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.sm_21)] = .{
.llvm_name = "sm_21",
.description = "Target SM 2.1",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.sm_30)] = .{
.llvm_name = "sm_30",
.description = "Target SM 3.0",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.sm_32)] = .{
.llvm_name = "sm_32",
.description = "Target SM 3.2",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.sm_35)] = .{
.llvm_name = "sm_35",
.description = "Target SM 3.5",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.sm_37)] = .{
.llvm_name = "sm_37",
.description = "Target SM 3.7",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.sm_50)] = .{
.llvm_name = "sm_50",
.description = "Target SM 5.0",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.sm_52)] = .{
.llvm_name = "sm_52",
.description = "Target SM 5.2",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.sm_53)] = .{
.llvm_name = "sm_53",
.description = "Target SM 5.3",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.sm_60)] = .{
.llvm_name = "sm_60",
.description = "Target SM 6.0",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.sm_61)] = .{
.llvm_name = "sm_61",
.description = "Target SM 6.1",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.sm_62)] = .{
.llvm_name = "sm_62",
.description = "Target SM 6.2",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.sm_70)] = .{
.llvm_name = "sm_70",
.description = "Target SM 7.0",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.sm_72)] = .{
.llvm_name = "sm_72",
.description = "Target SM 7.2",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.sm_75)] = .{
.llvm_name = "sm_75",
.description = "Target SM 7.5",
.dependencies = featureSet(&[_]Feature{}),
};
const ti = @typeInfo(Feature);
for (result) |*elem, i| {
elem.index = i;
elem.name = ti.Enum.fields[i].name;
}
break :blk result;
};
pub const cpu = struct {
pub const sm_20 = Cpu{
.name = "sm_20",
.llvm_name = "sm_20",
.features = featureSet(&[_]Feature{
.sm_20,
}),
};
pub const sm_21 = Cpu{
.name = "sm_21",
.llvm_name = "sm_21",
.features = featureSet(&[_]Feature{
.sm_21,
}),
};
pub const sm_30 = Cpu{
.name = "sm_30",
.llvm_name = "sm_30",
.features = featureSet(&[_]Feature{
.sm_30,
}),
};
pub const sm_32 = Cpu{
.name = "sm_32",
.llvm_name = "sm_32",
.features = featureSet(&[_]Feature{
.ptx40,
.sm_32,
}),
};
pub const sm_35 = Cpu{
.name = "sm_35",
.llvm_name = "sm_35",
.features = featureSet(&[_]Feature{
.sm_35,
}),
};
pub const sm_37 = Cpu{
.name = "sm_37",
.llvm_name = "sm_37",
.features = featureSet(&[_]Feature{
.ptx41,
.sm_37,
}),
};
pub const sm_50 = Cpu{
.name = "sm_50",
.llvm_name = "sm_50",
.features = featureSet(&[_]Feature{
.ptx40,
.sm_50,
}),
};
pub const sm_52 = Cpu{
.name = "sm_52",
.llvm_name = "sm_52",
.features = featureSet(&[_]Feature{
.ptx41,
.sm_52,
}),
};
pub const sm_53 = Cpu{
.name = "sm_53",
.llvm_name = "sm_53",
.features = featureSet(&[_]Feature{
.ptx42,
.sm_53,
}),
};
pub const sm_60 = Cpu{
.name = "sm_60",
.llvm_name = "sm_60",
.features = featureSet(&[_]Feature{
.ptx50,
.sm_60,
}),
};
pub const sm_61 = Cpu{
.name = "sm_61",
.llvm_name = "sm_61",
.features = featureSet(&[_]Feature{
.ptx50,
.sm_61,
}),
};
pub const sm_62 = Cpu{
.name = "sm_62",
.llvm_name = "sm_62",
.features = featureSet(&[_]Feature{
.ptx50,
.sm_62,
}),
};
pub const sm_70 = Cpu{
.name = "sm_70",
.llvm_name = "sm_70",
.features = featureSet(&[_]Feature{
.ptx60,
.sm_70,
}),
};
pub const sm_72 = Cpu{
.name = "sm_72",
.llvm_name = "sm_72",
.features = featureSet(&[_]Feature{
.ptx61,
.sm_72,
}),
};
pub const sm_75 = Cpu{
.name = "sm_75",
.llvm_name = "sm_75",
.features = featureSet(&[_]Feature{
.ptx63,
.sm_75,
}),
};
};
/// All nvptx CPUs, sorted alphabetically by name.
/// TODO: Replace this with usage of `std.meta.declList`. It does work, but stage1
/// compiler has inefficient memory and CPU usage, affecting build times.
pub const all_cpus = &[_]*const Cpu{
&cpu.sm_20,
&cpu.sm_21,
&cpu.sm_30,
&cpu.sm_32,
&cpu.sm_35,
&cpu.sm_37,
&cpu.sm_50,
&cpu.sm_52,
&cpu.sm_53,
&cpu.sm_60,
&cpu.sm_61,
&cpu.sm_62,
&cpu.sm_70,
&cpu.sm_72,
&cpu.sm_75,
};

938
lib/std/target/powerpc.zig Normal file
View File

@ -0,0 +1,938 @@
const std = @import("../std.zig");
const Cpu = std.Target.Cpu;
pub const Feature = enum {
@"64bit",
@"64bitregs",
altivec,
booke,
bpermd,
cmpb,
crbits,
crypto,
direct_move,
e500,
extdiv,
fcpsgn,
float128,
fpcvt,
fprnd,
fpu,
fre,
fres,
frsqrte,
frsqrtes,
fsqrt,
hard_float,
htm,
icbt,
invariant_function_descriptors,
isa_v30_instructions,
isel,
ldbrx,
lfiwax,
longcall,
mfocrf,
msync,
partword_atomics,
popcntd,
power8_altivec,
power8_vector,
power9_altivec,
power9_vector,
ppc_postra_sched,
ppc_prera_sched,
ppc4xx,
ppc6xx,
qpx,
recipprec,
secure_plt,
slow_popcntd,
spe,
stfiwx,
two_const_nr,
vectors_use_two_units,
vsx,
};
pub usingnamespace Cpu.Feature.feature_set_fns(Feature);
pub const all_features = blk: {
const len = @typeInfo(Feature).Enum.fields.len;
std.debug.assert(len <= Cpu.Feature.Set.needed_bit_count);
var result: [len]Cpu.Feature = undefined;
result[@enumToInt(Feature.@"64bit")] = .{
.llvm_name = "64bit",
.description = "Enable 64-bit instructions",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.@"64bitregs")] = .{
.llvm_name = "64bitregs",
.description = "Enable 64-bit registers usage for ppc32 [beta]",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.altivec)] = .{
.llvm_name = "altivec",
.description = "Enable Altivec instructions",
.dependencies = featureSet(&[_]Feature{
.fpu,
}),
};
result[@enumToInt(Feature.booke)] = .{
.llvm_name = "booke",
.description = "Enable Book E instructions",
.dependencies = featureSet(&[_]Feature{
.icbt,
}),
};
result[@enumToInt(Feature.bpermd)] = .{
.llvm_name = "bpermd",
.description = "Enable the bpermd instruction",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.cmpb)] = .{
.llvm_name = "cmpb",
.description = "Enable the cmpb instruction",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.crbits)] = .{
.llvm_name = "crbits",
.description = "Use condition-register bits individually",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.crypto)] = .{
.llvm_name = "crypto",
.description = "Enable POWER8 Crypto instructions",
.dependencies = featureSet(&[_]Feature{
.power8_altivec,
}),
};
result[@enumToInt(Feature.direct_move)] = .{
.llvm_name = "direct-move",
.description = "Enable Power8 direct move instructions",
.dependencies = featureSet(&[_]Feature{
.vsx,
}),
};
result[@enumToInt(Feature.e500)] = .{
.llvm_name = "e500",
.description = "Enable E500/E500mc instructions",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.extdiv)] = .{
.llvm_name = "extdiv",
.description = "Enable extended divide instructions",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.fcpsgn)] = .{
.llvm_name = "fcpsgn",
.description = "Enable the fcpsgn instruction",
.dependencies = featureSet(&[_]Feature{
.fpu,
}),
};
result[@enumToInt(Feature.float128)] = .{
.llvm_name = "float128",
.description = "Enable the __float128 data type for IEEE-754R Binary128.",
.dependencies = featureSet(&[_]Feature{
.vsx,
}),
};
result[@enumToInt(Feature.fpcvt)] = .{
.llvm_name = "fpcvt",
.description = "Enable fc[ft]* (unsigned and single-precision) and lfiwzx instructions",
.dependencies = featureSet(&[_]Feature{
.fpu,
}),
};
result[@enumToInt(Feature.fprnd)] = .{
.llvm_name = "fprnd",
.description = "Enable the fri[mnpz] instructions",
.dependencies = featureSet(&[_]Feature{
.fpu,
}),
};
result[@enumToInt(Feature.fpu)] = .{
.llvm_name = "fpu",
.description = "Enable classic FPU instructions",
.dependencies = featureSet(&[_]Feature{
.hard_float,
}),
};
result[@enumToInt(Feature.fre)] = .{
.llvm_name = "fre",
.description = "Enable the fre instruction",
.dependencies = featureSet(&[_]Feature{
.fpu,
}),
};
result[@enumToInt(Feature.fres)] = .{
.llvm_name = "fres",
.description = "Enable the fres instruction",
.dependencies = featureSet(&[_]Feature{
.fpu,
}),
};
result[@enumToInt(Feature.frsqrte)] = .{
.llvm_name = "frsqrte",
.description = "Enable the frsqrte instruction",
.dependencies = featureSet(&[_]Feature{
.fpu,
}),
};
result[@enumToInt(Feature.frsqrtes)] = .{
.llvm_name = "frsqrtes",
.description = "Enable the frsqrtes instruction",
.dependencies = featureSet(&[_]Feature{
.fpu,
}),
};
result[@enumToInt(Feature.fsqrt)] = .{
.llvm_name = "fsqrt",
.description = "Enable the fsqrt instruction",
.dependencies = featureSet(&[_]Feature{
.fpu,
}),
};
result[@enumToInt(Feature.hard_float)] = .{
.llvm_name = "hard-float",
.description = "Enable floating-point instructions",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.htm)] = .{
.llvm_name = "htm",
.description = "Enable Hardware Transactional Memory instructions",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.icbt)] = .{
.llvm_name = "icbt",
.description = "Enable icbt instruction",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.invariant_function_descriptors)] = .{
.llvm_name = "invariant-function-descriptors",
.description = "Assume function descriptors are invariant",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.isa_v30_instructions)] = .{
.llvm_name = "isa-v30-instructions",
.description = "Enable instructions added in ISA 3.0.",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.isel)] = .{
.llvm_name = "isel",
.description = "Enable the isel instruction",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.ldbrx)] = .{
.llvm_name = "ldbrx",
.description = "Enable the ldbrx instruction",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.lfiwax)] = .{
.llvm_name = "lfiwax",
.description = "Enable the lfiwax instruction",
.dependencies = featureSet(&[_]Feature{
.fpu,
}),
};
result[@enumToInt(Feature.longcall)] = .{
.llvm_name = "longcall",
.description = "Always use indirect calls",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.mfocrf)] = .{
.llvm_name = "mfocrf",
.description = "Enable the MFOCRF instruction",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.msync)] = .{
.llvm_name = "msync",
.description = "Has only the msync instruction instead of sync",
.dependencies = featureSet(&[_]Feature{
.booke,
}),
};
result[@enumToInt(Feature.partword_atomics)] = .{
.llvm_name = "partword-atomics",
.description = "Enable l[bh]arx and st[bh]cx.",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.popcntd)] = .{
.llvm_name = "popcntd",
.description = "Enable the popcnt[dw] instructions",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.power8_altivec)] = .{
.llvm_name = "power8-altivec",
.description = "Enable POWER8 Altivec instructions",
.dependencies = featureSet(&[_]Feature{
.altivec,
}),
};
result[@enumToInt(Feature.power8_vector)] = .{
.llvm_name = "power8-vector",
.description = "Enable POWER8 vector instructions",
.dependencies = featureSet(&[_]Feature{
.power8_altivec,
.vsx,
}),
};
result[@enumToInt(Feature.power9_altivec)] = .{
.llvm_name = "power9-altivec",
.description = "Enable POWER9 Altivec instructions",
.dependencies = featureSet(&[_]Feature{
.isa_v30_instructions,
.power8_altivec,
}),
};
result[@enumToInt(Feature.power9_vector)] = .{
.llvm_name = "power9-vector",
.description = "Enable POWER9 vector instructions",
.dependencies = featureSet(&[_]Feature{
.isa_v30_instructions,
.power8_vector,
.power9_altivec,
}),
};
result[@enumToInt(Feature.ppc_postra_sched)] = .{
.llvm_name = "ppc-postra-sched",
.description = "Use PowerPC post-RA scheduling strategy",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.ppc_prera_sched)] = .{
.llvm_name = "ppc-prera-sched",
.description = "Use PowerPC pre-RA scheduling strategy",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.ppc4xx)] = .{
.llvm_name = "ppc4xx",
.description = "Enable PPC 4xx instructions",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.ppc6xx)] = .{
.llvm_name = "ppc6xx",
.description = "Enable PPC 6xx instructions",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.qpx)] = .{
.llvm_name = "qpx",
.description = "Enable QPX instructions",
.dependencies = featureSet(&[_]Feature{
.fpu,
}),
};
result[@enumToInt(Feature.recipprec)] = .{
.llvm_name = "recipprec",
.description = "Assume higher precision reciprocal estimates",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.secure_plt)] = .{
.llvm_name = "secure-plt",
.description = "Enable secure plt mode",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.slow_popcntd)] = .{
.llvm_name = "slow-popcntd",
.description = "Has slow popcnt[dw] instructions",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.spe)] = .{
.llvm_name = "spe",
.description = "Enable SPE instructions",
.dependencies = featureSet(&[_]Feature{
.hard_float,
}),
};
result[@enumToInt(Feature.stfiwx)] = .{
.llvm_name = "stfiwx",
.description = "Enable the stfiwx instruction",
.dependencies = featureSet(&[_]Feature{
.fpu,
}),
};
result[@enumToInt(Feature.two_const_nr)] = .{
.llvm_name = "two-const-nr",
.description = "Requires two constant Newton-Raphson computation",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.vectors_use_two_units)] = .{
.llvm_name = "vectors-use-two-units",
.description = "Vectors use two units",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.vsx)] = .{
.llvm_name = "vsx",
.description = "Enable VSX instructions",
.dependencies = featureSet(&[_]Feature{
.altivec,
}),
};
const ti = @typeInfo(Feature);
for (result) |*elem, i| {
elem.index = i;
elem.name = ti.Enum.fields[i].name;
}
break :blk result;
};
pub const cpu = struct {
pub const @"440" = Cpu{
.name = "440",
.llvm_name = "440",
.features = featureSet(&[_]Feature{
.booke,
.fres,
.frsqrte,
.icbt,
.isel,
.msync,
}),
};
pub const @"450" = Cpu{
.name = "450",
.llvm_name = "450",
.features = featureSet(&[_]Feature{
.booke,
.fres,
.frsqrte,
.icbt,
.isel,
.msync,
}),
};
pub const @"601" = Cpu{
.name = "601",
.llvm_name = "601",
.features = featureSet(&[_]Feature{
.fpu,
}),
};
pub const @"602" = Cpu{
.name = "602",
.llvm_name = "602",
.features = featureSet(&[_]Feature{
.fpu,
}),
};
pub const @"603" = Cpu{
.name = "603",
.llvm_name = "603",
.features = featureSet(&[_]Feature{
.fres,
.frsqrte,
}),
};
pub const @"603e" = Cpu{
.name = "603e",
.llvm_name = "603e",
.features = featureSet(&[_]Feature{
.fres,
.frsqrte,
}),
};
pub const @"603ev" = Cpu{
.name = "603ev",
.llvm_name = "603ev",
.features = featureSet(&[_]Feature{
.fres,
.frsqrte,
}),
};
pub const @"604" = Cpu{
.name = "604",
.llvm_name = "604",
.features = featureSet(&[_]Feature{
.fres,
.frsqrte,
}),
};
pub const @"604e" = Cpu{
.name = "604e",
.llvm_name = "604e",
.features = featureSet(&[_]Feature{
.fres,
.frsqrte,
}),
};
pub const @"620" = Cpu{
.name = "620",
.llvm_name = "620",
.features = featureSet(&[_]Feature{
.fres,
.frsqrte,
}),
};
pub const @"7400" = Cpu{
.name = "7400",
.llvm_name = "7400",
.features = featureSet(&[_]Feature{
.altivec,
.fres,
.frsqrte,
}),
};
pub const @"7450" = Cpu{
.name = "7450",
.llvm_name = "7450",
.features = featureSet(&[_]Feature{
.altivec,
.fres,
.frsqrte,
}),
};
pub const @"750" = Cpu{
.name = "750",
.llvm_name = "750",
.features = featureSet(&[_]Feature{
.fres,
.frsqrte,
}),
};
pub const @"970" = Cpu{
.name = "970",
.llvm_name = "970",
.features = featureSet(&[_]Feature{
.@"64bit",
.altivec,
.fres,
.frsqrte,
.fsqrt,
.mfocrf,
.stfiwx,
}),
};
pub const a2 = Cpu{
.name = "a2",
.llvm_name = "a2",
.features = featureSet(&[_]Feature{
.@"64bit",
.booke,
.cmpb,
.fcpsgn,
.fpcvt,
.fprnd,
.fre,
.fres,
.frsqrte,
.frsqrtes,
.fsqrt,
.icbt,
.isel,
.ldbrx,
.lfiwax,
.mfocrf,
.recipprec,
.slow_popcntd,
.stfiwx,
}),
};
pub const a2q = Cpu{
.name = "a2q",
.llvm_name = "a2q",
.features = featureSet(&[_]Feature{
.@"64bit",
.booke,
.cmpb,
.fcpsgn,
.fpcvt,
.fprnd,
.fre,
.fres,
.frsqrte,
.frsqrtes,
.fsqrt,
.icbt,
.isel,
.ldbrx,
.lfiwax,
.mfocrf,
.qpx,
.recipprec,
.slow_popcntd,
.stfiwx,
}),
};
pub const e500 = Cpu{
.name = "e500",
.llvm_name = "e500",
.features = featureSet(&[_]Feature{
.booke,
.icbt,
.isel,
}),
};
pub const e500mc = Cpu{
.name = "e500mc",
.llvm_name = "e500mc",
.features = featureSet(&[_]Feature{
.booke,
.icbt,
.isel,
.stfiwx,
}),
};
pub const e5500 = Cpu{
.name = "e5500",
.llvm_name = "e5500",
.features = featureSet(&[_]Feature{
.@"64bit",
.booke,
.icbt,
.isel,
.mfocrf,
.stfiwx,
}),
};
pub const g3 = Cpu{
.name = "g3",
.llvm_name = "g3",
.features = featureSet(&[_]Feature{
.fres,
.frsqrte,
}),
};
pub const g4 = Cpu{
.name = "g4",
.llvm_name = "g4",
.features = featureSet(&[_]Feature{
.altivec,
.fres,
.frsqrte,
}),
};
pub const @"g4+" = Cpu{
.name = "g4+",
.llvm_name = "g4+",
.features = featureSet(&[_]Feature{
.altivec,
.fres,
.frsqrte,
}),
};
pub const g5 = Cpu{
.name = "g5",
.llvm_name = "g5",
.features = featureSet(&[_]Feature{
.@"64bit",
.altivec,
.fres,
.frsqrte,
.fsqrt,
.mfocrf,
.stfiwx,
}),
};
pub const generic = Cpu{
.name = "generic",
.llvm_name = "generic",
.features = featureSet(&[_]Feature{
.hard_float,
}),
};
pub const ppc = Cpu{
.name = "ppc",
.llvm_name = "ppc",
.features = featureSet(&[_]Feature{
.hard_float,
}),
};
pub const ppc32 = Cpu{
.name = "ppc32",
.llvm_name = "ppc32",
.features = featureSet(&[_]Feature{
.hard_float,
}),
};
pub const ppc64 = Cpu{
.name = "ppc64",
.llvm_name = "ppc64",
.features = featureSet(&[_]Feature{
.@"64bit",
.altivec,
.fres,
.frsqrte,
.fsqrt,
.mfocrf,
.stfiwx,
}),
};
pub const ppc64le = Cpu{
.name = "ppc64le",
.llvm_name = "ppc64le",
.features = featureSet(&[_]Feature{
.@"64bit",
.altivec,
.bpermd,
.cmpb,
.crypto,
.direct_move,
.extdiv,
.fcpsgn,
.fpcvt,
.fprnd,
.fre,
.fres,
.frsqrte,
.frsqrtes,
.fsqrt,
.htm,
.icbt,
.isel,
.ldbrx,
.lfiwax,
.mfocrf,
.partword_atomics,
.popcntd,
.power8_altivec,
.power8_vector,
.recipprec,
.stfiwx,
.two_const_nr,
.vsx,
}),
};
pub const pwr3 = Cpu{
.name = "pwr3",
.llvm_name = "pwr3",
.features = featureSet(&[_]Feature{
.@"64bit",
.altivec,
.fres,
.frsqrte,
.mfocrf,
.stfiwx,
}),
};
pub const pwr4 = Cpu{
.name = "pwr4",
.llvm_name = "pwr4",
.features = featureSet(&[_]Feature{
.@"64bit",
.altivec,
.fres,
.frsqrte,
.fsqrt,
.mfocrf,
.stfiwx,
}),
};
pub const pwr5 = Cpu{
.name = "pwr5",
.llvm_name = "pwr5",
.features = featureSet(&[_]Feature{
.@"64bit",
.altivec,
.fre,
.fres,
.frsqrte,
.frsqrtes,
.fsqrt,
.mfocrf,
.stfiwx,
}),
};
pub const pwr5x = Cpu{
.name = "pwr5x",
.llvm_name = "pwr5x",
.features = featureSet(&[_]Feature{
.@"64bit",
.altivec,
.fprnd,
.fre,
.fres,
.frsqrte,
.frsqrtes,
.fsqrt,
.mfocrf,
.stfiwx,
}),
};
pub const pwr6 = Cpu{
.name = "pwr6",
.llvm_name = "pwr6",
.features = featureSet(&[_]Feature{
.@"64bit",
.altivec,
.cmpb,
.fcpsgn,
.fprnd,
.fre,
.fres,
.frsqrte,
.frsqrtes,
.fsqrt,
.lfiwax,
.mfocrf,
.recipprec,
.stfiwx,
}),
};
pub const pwr6x = Cpu{
.name = "pwr6x",
.llvm_name = "pwr6x",
.features = featureSet(&[_]Feature{
.@"64bit",
.altivec,
.cmpb,
.fcpsgn,
.fprnd,
.fre,
.fres,
.frsqrte,
.frsqrtes,
.fsqrt,
.lfiwax,
.mfocrf,
.recipprec,
.stfiwx,
}),
};
pub const pwr7 = Cpu{
.name = "pwr7",
.llvm_name = "pwr7",
.features = featureSet(&[_]Feature{
.@"64bit",
.altivec,
.bpermd,
.cmpb,
.extdiv,
.fcpsgn,
.fpcvt,
.fprnd,
.fre,
.fres,
.frsqrte,
.frsqrtes,
.fsqrt,
.isel,
.ldbrx,
.lfiwax,
.mfocrf,
.popcntd,
.recipprec,
.stfiwx,
.two_const_nr,
.vsx,
}),
};
pub const pwr8 = Cpu{
.name = "pwr8",
.llvm_name = "pwr8",
.features = featureSet(&[_]Feature{
.@"64bit",
.altivec,
.bpermd,
.cmpb,
.crypto,
.direct_move,
.extdiv,
.fcpsgn,
.fpcvt,
.fprnd,
.fre,
.fres,
.frsqrte,
.frsqrtes,
.fsqrt,
.htm,
.icbt,
.isel,
.ldbrx,
.lfiwax,
.mfocrf,
.partword_atomics,
.popcntd,
.power8_altivec,
.power8_vector,
.recipprec,
.stfiwx,
.two_const_nr,
.vsx,
}),
};
pub const pwr9 = Cpu{
.name = "pwr9",
.llvm_name = "pwr9",
.features = featureSet(&[_]Feature{
.@"64bit",
.altivec,
.bpermd,
.cmpb,
.crypto,
.direct_move,
.extdiv,
.fcpsgn,
.fpcvt,
.fprnd,
.fre,
.fres,
.frsqrte,
.frsqrtes,
.fsqrt,
.htm,
.icbt,
.isa_v30_instructions,
.isel,
.ldbrx,
.lfiwax,
.mfocrf,
.partword_atomics,
.popcntd,
.power8_altivec,
.power8_vector,
.power9_altivec,
.power9_vector,
.ppc_postra_sched,
.ppc_prera_sched,
.recipprec,
.stfiwx,
.two_const_nr,
.vectors_use_two_units,
.vsx,
}),
};
};
/// All powerpc CPUs, sorted alphabetically by name.
/// TODO: Replace this with usage of `std.meta.declList`. It does work, but stage1
/// compiler has inefficient memory and CPU usage, affecting build times.
pub const all_cpus = &[_]*const Cpu{
&cpu.@"440",
&cpu.@"450",
&cpu.@"601",
&cpu.@"602",
&cpu.@"603",
&cpu.@"603e",
&cpu.@"603ev",
&cpu.@"604",
&cpu.@"604e",
&cpu.@"620",
&cpu.@"7400",
&cpu.@"7450",
&cpu.@"750",
&cpu.@"970",
&cpu.a2,
&cpu.a2q,
&cpu.e500,
&cpu.e500mc,
&cpu.e5500,
&cpu.g3,
&cpu.g4,
&cpu.@"g4+",
&cpu.g5,
&cpu.generic,
&cpu.ppc,
&cpu.ppc32,
&cpu.ppc64,
&cpu.ppc64le,
&cpu.pwr3,
&cpu.pwr4,
&cpu.pwr5,
&cpu.pwr5x,
&cpu.pwr6,
&cpu.pwr6x,
&cpu.pwr7,
&cpu.pwr8,
&cpu.pwr9,
};

122
lib/std/target/riscv.zig Normal file
View File

@ -0,0 +1,122 @@
const std = @import("../std.zig");
const Cpu = std.Target.Cpu;
pub const Feature = enum {
@"64bit",
a,
c,
d,
e,
f,
m,
relax,
};
pub usingnamespace Cpu.Feature.feature_set_fns(Feature);
pub const all_features = blk: {
const len = @typeInfo(Feature).Enum.fields.len;
std.debug.assert(len <= Cpu.Feature.Set.needed_bit_count);
var result: [len]Cpu.Feature = undefined;
result[@enumToInt(Feature.@"64bit")] = .{
.llvm_name = "64bit",
.description = "Implements RV64",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.a)] = .{
.llvm_name = "a",
.description = "'A' (Atomic Instructions)",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.c)] = .{
.llvm_name = "c",
.description = "'C' (Compressed Instructions)",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.d)] = .{
.llvm_name = "d",
.description = "'D' (Double-Precision Floating-Point)",
.dependencies = featureSet(&[_]Feature{
.f,
}),
};
result[@enumToInt(Feature.e)] = .{
.llvm_name = "e",
.description = "Implements RV32E (provides 16 rather than 32 GPRs)",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.f)] = .{
.llvm_name = "f",
.description = "'F' (Single-Precision Floating-Point)",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.m)] = .{
.llvm_name = "m",
.description = "'M' (Integer Multiplication and Division)",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.relax)] = .{
.llvm_name = "relax",
.description = "Enable Linker relaxation.",
.dependencies = featureSet(&[_]Feature{}),
};
const ti = @typeInfo(Feature);
for (result) |*elem, i| {
elem.index = i;
elem.name = ti.Enum.fields[i].name;
}
break :blk result;
};
pub const cpu = struct {
pub const baseline_rv32 = Cpu{
.name = "baseline_rv32",
.llvm_name = "generic-rv32",
.features = featureSet(&[_]Feature{
.a,
.c,
.d,
.f,
.m,
.relax,
}),
};
pub const baseline_rv64 = Cpu{
.name = "baseline_rv64",
.llvm_name = "generic-rv64",
.features = featureSet(&[_]Feature{
.@"64bit",
.a,
.c,
.d,
.f,
.m,
.relax,
}),
};
pub const generic_rv32 = Cpu{
.name = "generic_rv32",
.llvm_name = "generic-rv32",
.features = featureSet(&[_]Feature{}),
};
pub const generic_rv64 = Cpu{
.name = "generic_rv64",
.llvm_name = "generic-rv64",
.features = featureSet(&[_]Feature{
.@"64bit",
}),
};
};
/// All riscv CPUs, sorted alphabetically by name.
/// TODO: Replace this with usage of `std.meta.declList`. It does work, but stage1
/// compiler has inefficient memory and CPU usage, affecting build times.
pub const all_cpus = &[_]*const Cpu{
&cpu.baseline_rv32,
&cpu.baseline_rv64,
&cpu.generic_rv32,
&cpu.generic_rv64,
};

495
lib/std/target/sparc.zig Normal file
View File

@ -0,0 +1,495 @@
const std = @import("../std.zig");
const Cpu = std.Target.Cpu;
pub const Feature = enum {
deprecated_v8,
detectroundchange,
fixallfdivsqrt,
hard_quad_float,
hasleoncasa,
hasumacsmac,
insertnopload,
leon,
leoncyclecounter,
leonpwrpsr,
no_fmuls,
no_fsmuld,
popc,
soft_float,
soft_mul_div,
v9,
vis,
vis2,
vis3,
};
pub usingnamespace Cpu.Feature.feature_set_fns(Feature);
pub const all_features = blk: {
const len = @typeInfo(Feature).Enum.fields.len;
std.debug.assert(len <= Cpu.Feature.Set.needed_bit_count);
var result: [len]Cpu.Feature = undefined;
result[@enumToInt(Feature.deprecated_v8)] = .{
.llvm_name = "deprecated-v8",
.description = "Enable deprecated V8 instructions in V9 mode",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.detectroundchange)] = .{
.llvm_name = "detectroundchange",
.description = "LEON3 erratum detection: Detects any rounding mode change request: use only the round-to-nearest rounding mode",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.fixallfdivsqrt)] = .{
.llvm_name = "fixallfdivsqrt",
.description = "LEON erratum fix: Fix FDIVS/FDIVD/FSQRTS/FSQRTD instructions with NOPs and floating-point store",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.hard_quad_float)] = .{
.llvm_name = "hard-quad-float",
.description = "Enable quad-word floating point instructions",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.hasleoncasa)] = .{
.llvm_name = "hasleoncasa",
.description = "Enable CASA instruction for LEON3 and LEON4 processors",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.hasumacsmac)] = .{
.llvm_name = "hasumacsmac",
.description = "Enable UMAC and SMAC for LEON3 and LEON4 processors",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.insertnopload)] = .{
.llvm_name = "insertnopload",
.description = "LEON3 erratum fix: Insert a NOP instruction after every single-cycle load instruction when the next instruction is another load/store instruction",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.leon)] = .{
.llvm_name = "leon",
.description = "Enable LEON extensions",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.leoncyclecounter)] = .{
.llvm_name = "leoncyclecounter",
.description = "Use the Leon cycle counter register",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.leonpwrpsr)] = .{
.llvm_name = "leonpwrpsr",
.description = "Enable the PWRPSR instruction",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.no_fmuls)] = .{
.llvm_name = "no-fmuls",
.description = "Disable the fmuls instruction.",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.no_fsmuld)] = .{
.llvm_name = "no-fsmuld",
.description = "Disable the fsmuld instruction.",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.popc)] = .{
.llvm_name = "popc",
.description = "Use the popc (population count) instruction",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.soft_float)] = .{
.llvm_name = "soft-float",
.description = "Use software emulation for floating point",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.soft_mul_div)] = .{
.llvm_name = "soft-mul-div",
.description = "Use software emulation for integer multiply and divide",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.v9)] = .{
.llvm_name = "v9",
.description = "Enable SPARC-V9 instructions",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.vis)] = .{
.llvm_name = "vis",
.description = "Enable UltraSPARC Visual Instruction Set extensions",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.vis2)] = .{
.llvm_name = "vis2",
.description = "Enable Visual Instruction Set extensions II",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.vis3)] = .{
.llvm_name = "vis3",
.description = "Enable Visual Instruction Set extensions III",
.dependencies = featureSet(&[_]Feature{}),
};
const ti = @typeInfo(Feature);
for (result) |*elem, i| {
elem.index = i;
elem.name = ti.Enum.fields[i].name;
}
break :blk result;
};
pub const cpu = struct {
pub const at697e = Cpu{
.name = "at697e",
.llvm_name = "at697e",
.features = featureSet(&[_]Feature{
.insertnopload,
.leon,
}),
};
pub const at697f = Cpu{
.name = "at697f",
.llvm_name = "at697f",
.features = featureSet(&[_]Feature{
.insertnopload,
.leon,
}),
};
pub const f934 = Cpu{
.name = "f934",
.llvm_name = "f934",
.features = featureSet(&[_]Feature{}),
};
pub const generic = Cpu{
.name = "generic",
.llvm_name = "generic",
.features = featureSet(&[_]Feature{}),
};
pub const gr712rc = Cpu{
.name = "gr712rc",
.llvm_name = "gr712rc",
.features = featureSet(&[_]Feature{
.hasleoncasa,
.leon,
}),
};
pub const gr740 = Cpu{
.name = "gr740",
.llvm_name = "gr740",
.features = featureSet(&[_]Feature{
.hasleoncasa,
.hasumacsmac,
.leon,
.leoncyclecounter,
.leonpwrpsr,
}),
};
pub const hypersparc = Cpu{
.name = "hypersparc",
.llvm_name = "hypersparc",
.features = featureSet(&[_]Feature{}),
};
pub const leon2 = Cpu{
.name = "leon2",
.llvm_name = "leon2",
.features = featureSet(&[_]Feature{
.leon,
}),
};
pub const leon3 = Cpu{
.name = "leon3",
.llvm_name = "leon3",
.features = featureSet(&[_]Feature{
.hasumacsmac,
.leon,
}),
};
pub const leon4 = Cpu{
.name = "leon4",
.llvm_name = "leon4",
.features = featureSet(&[_]Feature{
.hasleoncasa,
.hasumacsmac,
.leon,
}),
};
pub const ma2080 = Cpu{
.name = "ma2080",
.llvm_name = "ma2080",
.features = featureSet(&[_]Feature{
.hasleoncasa,
.leon,
}),
};
pub const ma2085 = Cpu{
.name = "ma2085",
.llvm_name = "ma2085",
.features = featureSet(&[_]Feature{
.hasleoncasa,
.leon,
}),
};
pub const ma2100 = Cpu{
.name = "ma2100",
.llvm_name = "ma2100",
.features = featureSet(&[_]Feature{
.hasleoncasa,
.leon,
}),
};
pub const ma2150 = Cpu{
.name = "ma2150",
.llvm_name = "ma2150",
.features = featureSet(&[_]Feature{
.hasleoncasa,
.leon,
}),
};
pub const ma2155 = Cpu{
.name = "ma2155",
.llvm_name = "ma2155",
.features = featureSet(&[_]Feature{
.hasleoncasa,
.leon,
}),
};
pub const ma2450 = Cpu{
.name = "ma2450",
.llvm_name = "ma2450",
.features = featureSet(&[_]Feature{
.hasleoncasa,
.leon,
}),
};
pub const ma2455 = Cpu{
.name = "ma2455",
.llvm_name = "ma2455",
.features = featureSet(&[_]Feature{
.hasleoncasa,
.leon,
}),
};
pub const ma2480 = Cpu{
.name = "ma2480",
.llvm_name = "ma2480",
.features = featureSet(&[_]Feature{
.hasleoncasa,
.leon,
}),
};
pub const ma2485 = Cpu{
.name = "ma2485",
.llvm_name = "ma2485",
.features = featureSet(&[_]Feature{
.hasleoncasa,
.leon,
}),
};
pub const ma2x5x = Cpu{
.name = "ma2x5x",
.llvm_name = "ma2x5x",
.features = featureSet(&[_]Feature{
.hasleoncasa,
.leon,
}),
};
pub const ma2x8x = Cpu{
.name = "ma2x8x",
.llvm_name = "ma2x8x",
.features = featureSet(&[_]Feature{
.hasleoncasa,
.leon,
}),
};
pub const myriad2 = Cpu{
.name = "myriad2",
.llvm_name = "myriad2",
.features = featureSet(&[_]Feature{
.hasleoncasa,
.leon,
}),
};
pub const myriad2_1 = Cpu{
.name = "myriad2_1",
.llvm_name = "myriad2.1",
.features = featureSet(&[_]Feature{
.hasleoncasa,
.leon,
}),
};
pub const myriad2_2 = Cpu{
.name = "myriad2_2",
.llvm_name = "myriad2.2",
.features = featureSet(&[_]Feature{
.hasleoncasa,
.leon,
}),
};
pub const myriad2_3 = Cpu{
.name = "myriad2_3",
.llvm_name = "myriad2.3",
.features = featureSet(&[_]Feature{
.hasleoncasa,
.leon,
}),
};
pub const niagara = Cpu{
.name = "niagara",
.llvm_name = "niagara",
.features = featureSet(&[_]Feature{
.deprecated_v8,
.v9,
.vis,
.vis2,
}),
};
pub const niagara2 = Cpu{
.name = "niagara2",
.llvm_name = "niagara2",
.features = featureSet(&[_]Feature{
.deprecated_v8,
.popc,
.v9,
.vis,
.vis2,
}),
};
pub const niagara3 = Cpu{
.name = "niagara3",
.llvm_name = "niagara3",
.features = featureSet(&[_]Feature{
.deprecated_v8,
.popc,
.v9,
.vis,
.vis2,
}),
};
pub const niagara4 = Cpu{
.name = "niagara4",
.llvm_name = "niagara4",
.features = featureSet(&[_]Feature{
.deprecated_v8,
.popc,
.v9,
.vis,
.vis2,
.vis3,
}),
};
pub const sparclet = Cpu{
.name = "sparclet",
.llvm_name = "sparclet",
.features = featureSet(&[_]Feature{}),
};
pub const sparclite = Cpu{
.name = "sparclite",
.llvm_name = "sparclite",
.features = featureSet(&[_]Feature{}),
};
pub const sparclite86x = Cpu{
.name = "sparclite86x",
.llvm_name = "sparclite86x",
.features = featureSet(&[_]Feature{}),
};
pub const supersparc = Cpu{
.name = "supersparc",
.llvm_name = "supersparc",
.features = featureSet(&[_]Feature{}),
};
pub const tsc701 = Cpu{
.name = "tsc701",
.llvm_name = "tsc701",
.features = featureSet(&[_]Feature{}),
};
pub const ultrasparc = Cpu{
.name = "ultrasparc",
.llvm_name = "ultrasparc",
.features = featureSet(&[_]Feature{
.deprecated_v8,
.v9,
.vis,
}),
};
pub const ultrasparc3 = Cpu{
.name = "ultrasparc3",
.llvm_name = "ultrasparc3",
.features = featureSet(&[_]Feature{
.deprecated_v8,
.v9,
.vis,
.vis2,
}),
};
pub const ut699 = Cpu{
.name = "ut699",
.llvm_name = "ut699",
.features = featureSet(&[_]Feature{
.fixallfdivsqrt,
.insertnopload,
.leon,
.no_fmuls,
.no_fsmuld,
}),
};
pub const v7 = Cpu{
.name = "v7",
.llvm_name = "v7",
.features = featureSet(&[_]Feature{
.no_fsmuld,
.soft_mul_div,
}),
};
pub const v8 = Cpu{
.name = "v8",
.llvm_name = "v8",
.features = featureSet(&[_]Feature{}),
};
pub const v9 = Cpu{
.name = "v9",
.llvm_name = "v9",
.features = featureSet(&[_]Feature{
.v9,
}),
};
};
/// All sparc CPUs, sorted alphabetically by name.
/// TODO: Replace this with usage of `std.meta.declList`. It does work, but stage1
/// compiler has inefficient memory and CPU usage, affecting build times.
pub const all_cpus = &[_]*const Cpu{
&cpu.at697e,
&cpu.at697f,
&cpu.f934,
&cpu.generic,
&cpu.gr712rc,
&cpu.gr740,
&cpu.hypersparc,
&cpu.leon2,
&cpu.leon3,
&cpu.leon4,
&cpu.ma2080,
&cpu.ma2085,
&cpu.ma2100,
&cpu.ma2150,
&cpu.ma2155,
&cpu.ma2450,
&cpu.ma2455,
&cpu.ma2480,
&cpu.ma2485,
&cpu.ma2x5x,
&cpu.ma2x8x,
&cpu.myriad2,
&cpu.myriad2_1,
&cpu.myriad2_2,
&cpu.myriad2_3,
&cpu.niagara,
&cpu.niagara2,
&cpu.niagara3,
&cpu.niagara4,
&cpu.sparclet,
&cpu.sparclite,
&cpu.sparclite86x,
&cpu.supersparc,
&cpu.tsc701,
&cpu.ultrasparc,
&cpu.ultrasparc3,
&cpu.ut699,
&cpu.v7,
&cpu.v8,
&cpu.v9,
};

510
lib/std/target/systemz.zig Normal file
View File

@ -0,0 +1,510 @@
const std = @import("../std.zig");
const Cpu = std.Target.Cpu;
pub const Feature = enum {
deflate_conversion,
dfp_packed_conversion,
dfp_zoned_conversion,
distinct_ops,
enhanced_dat_2,
enhanced_sort,
execution_hint,
fast_serialization,
fp_extension,
guarded_storage,
high_word,
insert_reference_bits_multiple,
interlocked_access1,
load_and_trap,
load_and_zero_rightmost_byte,
load_store_on_cond,
load_store_on_cond_2,
message_security_assist_extension3,
message_security_assist_extension4,
message_security_assist_extension5,
message_security_assist_extension7,
message_security_assist_extension8,
message_security_assist_extension9,
miscellaneous_extensions,
miscellaneous_extensions_2,
miscellaneous_extensions_3,
population_count,
processor_assist,
reset_reference_bits_multiple,
transactional_execution,
vector,
vector_enhancements_1,
vector_enhancements_2,
vector_packed_decimal,
vector_packed_decimal_enhancement,
};
pub usingnamespace Cpu.Feature.feature_set_fns(Feature);
pub const all_features = blk: {
const len = @typeInfo(Feature).Enum.fields.len;
std.debug.assert(len <= Cpu.Feature.Set.needed_bit_count);
var result: [len]Cpu.Feature = undefined;
result[@enumToInt(Feature.deflate_conversion)] = .{
.llvm_name = "deflate-conversion",
.description = "Assume that the deflate-conversion facility is installed",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.dfp_packed_conversion)] = .{
.llvm_name = "dfp-packed-conversion",
.description = "Assume that the DFP packed-conversion facility is installed",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.dfp_zoned_conversion)] = .{
.llvm_name = "dfp-zoned-conversion",
.description = "Assume that the DFP zoned-conversion facility is installed",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.distinct_ops)] = .{
.llvm_name = "distinct-ops",
.description = "Assume that the distinct-operands facility is installed",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.enhanced_dat_2)] = .{
.llvm_name = "enhanced-dat-2",
.description = "Assume that the enhanced-DAT facility 2 is installed",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.enhanced_sort)] = .{
.llvm_name = "enhanced-sort",
.description = "Assume that the enhanced-sort facility is installed",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.execution_hint)] = .{
.llvm_name = "execution-hint",
.description = "Assume that the execution-hint facility is installed",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.fast_serialization)] = .{
.llvm_name = "fast-serialization",
.description = "Assume that the fast-serialization facility is installed",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.fp_extension)] = .{
.llvm_name = "fp-extension",
.description = "Assume that the floating-point extension facility is installed",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.guarded_storage)] = .{
.llvm_name = "guarded-storage",
.description = "Assume that the guarded-storage facility is installed",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.high_word)] = .{
.llvm_name = "high-word",
.description = "Assume that the high-word facility is installed",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.insert_reference_bits_multiple)] = .{
.llvm_name = "insert-reference-bits-multiple",
.description = "Assume that the insert-reference-bits-multiple facility is installed",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.interlocked_access1)] = .{
.llvm_name = "interlocked-access1",
.description = "Assume that interlocked-access facility 1 is installed",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.load_and_trap)] = .{
.llvm_name = "load-and-trap",
.description = "Assume that the load-and-trap facility is installed",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.load_and_zero_rightmost_byte)] = .{
.llvm_name = "load-and-zero-rightmost-byte",
.description = "Assume that the load-and-zero-rightmost-byte facility is installed",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.load_store_on_cond)] = .{
.llvm_name = "load-store-on-cond",
.description = "Assume that the load/store-on-condition facility is installed",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.load_store_on_cond_2)] = .{
.llvm_name = "load-store-on-cond-2",
.description = "Assume that the load/store-on-condition facility 2 is installed",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.message_security_assist_extension3)] = .{
.llvm_name = "message-security-assist-extension3",
.description = "Assume that the message-security-assist extension facility 3 is installed",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.message_security_assist_extension4)] = .{
.llvm_name = "message-security-assist-extension4",
.description = "Assume that the message-security-assist extension facility 4 is installed",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.message_security_assist_extension5)] = .{
.llvm_name = "message-security-assist-extension5",
.description = "Assume that the message-security-assist extension facility 5 is installed",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.message_security_assist_extension7)] = .{
.llvm_name = "message-security-assist-extension7",
.description = "Assume that the message-security-assist extension facility 7 is installed",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.message_security_assist_extension8)] = .{
.llvm_name = "message-security-assist-extension8",
.description = "Assume that the message-security-assist extension facility 8 is installed",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.message_security_assist_extension9)] = .{
.llvm_name = "message-security-assist-extension9",
.description = "Assume that the message-security-assist extension facility 9 is installed",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.miscellaneous_extensions)] = .{
.llvm_name = "miscellaneous-extensions",
.description = "Assume that the miscellaneous-extensions facility is installed",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.miscellaneous_extensions_2)] = .{
.llvm_name = "miscellaneous-extensions-2",
.description = "Assume that the miscellaneous-extensions facility 2 is installed",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.miscellaneous_extensions_3)] = .{
.llvm_name = "miscellaneous-extensions-3",
.description = "Assume that the miscellaneous-extensions facility 3 is installed",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.population_count)] = .{
.llvm_name = "population-count",
.description = "Assume that the population-count facility is installed",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.processor_assist)] = .{
.llvm_name = "processor-assist",
.description = "Assume that the processor-assist facility is installed",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.reset_reference_bits_multiple)] = .{
.llvm_name = "reset-reference-bits-multiple",
.description = "Assume that the reset-reference-bits-multiple facility is installed",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.transactional_execution)] = .{
.llvm_name = "transactional-execution",
.description = "Assume that the transactional-execution facility is installed",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.vector)] = .{
.llvm_name = "vector",
.description = "Assume that the vectory facility is installed",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.vector_enhancements_1)] = .{
.llvm_name = "vector-enhancements-1",
.description = "Assume that the vector enhancements facility 1 is installed",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.vector_enhancements_2)] = .{
.llvm_name = "vector-enhancements-2",
.description = "Assume that the vector enhancements facility 2 is installed",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.vector_packed_decimal)] = .{
.llvm_name = "vector-packed-decimal",
.description = "Assume that the vector packed decimal facility is installed",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.vector_packed_decimal_enhancement)] = .{
.llvm_name = "vector-packed-decimal-enhancement",
.description = "Assume that the vector packed decimal enhancement facility is installed",
.dependencies = featureSet(&[_]Feature{}),
};
const ti = @typeInfo(Feature);
for (result) |*elem, i| {
elem.index = i;
elem.name = ti.Enum.fields[i].name;
}
break :blk result;
};
pub const cpu = struct {
pub const arch10 = Cpu{
.name = "arch10",
.llvm_name = "arch10",
.features = featureSet(&[_]Feature{
.dfp_zoned_conversion,
.distinct_ops,
.enhanced_dat_2,
.execution_hint,
.fast_serialization,
.fp_extension,
.high_word,
.interlocked_access1,
.load_and_trap,
.load_store_on_cond,
.message_security_assist_extension3,
.message_security_assist_extension4,
.miscellaneous_extensions,
.population_count,
.processor_assist,
.reset_reference_bits_multiple,
.transactional_execution,
}),
};
pub const arch11 = Cpu{
.name = "arch11",
.llvm_name = "arch11",
.features = featureSet(&[_]Feature{
.dfp_packed_conversion,
.dfp_zoned_conversion,
.distinct_ops,
.enhanced_dat_2,
.execution_hint,
.fast_serialization,
.fp_extension,
.high_word,
.interlocked_access1,
.load_and_trap,
.load_and_zero_rightmost_byte,
.load_store_on_cond,
.load_store_on_cond_2,
.message_security_assist_extension3,
.message_security_assist_extension4,
.message_security_assist_extension5,
.miscellaneous_extensions,
.population_count,
.processor_assist,
.reset_reference_bits_multiple,
.transactional_execution,
.vector,
}),
};
pub const arch12 = Cpu{
.name = "arch12",
.llvm_name = "arch12",
.features = featureSet(&[_]Feature{
.dfp_packed_conversion,
.dfp_zoned_conversion,
.distinct_ops,
.enhanced_dat_2,
.execution_hint,
.fast_serialization,
.fp_extension,
.guarded_storage,
.high_word,
.insert_reference_bits_multiple,
.interlocked_access1,
.load_and_trap,
.load_and_zero_rightmost_byte,
.load_store_on_cond,
.load_store_on_cond_2,
.message_security_assist_extension3,
.message_security_assist_extension4,
.message_security_assist_extension5,
.message_security_assist_extension7,
.message_security_assist_extension8,
.miscellaneous_extensions,
.miscellaneous_extensions_2,
.population_count,
.processor_assist,
.reset_reference_bits_multiple,
.transactional_execution,
.vector,
.vector_enhancements_1,
.vector_packed_decimal,
}),
};
pub const arch13 = Cpu{
.name = "arch13",
.llvm_name = "arch13",
.features = featureSet(&[_]Feature{
.deflate_conversion,
.dfp_packed_conversion,
.dfp_zoned_conversion,
.distinct_ops,
.enhanced_dat_2,
.enhanced_sort,
.execution_hint,
.fast_serialization,
.fp_extension,
.guarded_storage,
.high_word,
.insert_reference_bits_multiple,
.interlocked_access1,
.load_and_trap,
.load_and_zero_rightmost_byte,
.load_store_on_cond,
.load_store_on_cond_2,
.message_security_assist_extension3,
.message_security_assist_extension4,
.message_security_assist_extension5,
.message_security_assist_extension7,
.message_security_assist_extension8,
.message_security_assist_extension9,
.miscellaneous_extensions,
.miscellaneous_extensions_2,
.miscellaneous_extensions_3,
.population_count,
.processor_assist,
.reset_reference_bits_multiple,
.transactional_execution,
.vector,
.vector_enhancements_1,
.vector_enhancements_2,
.vector_packed_decimal,
.vector_packed_decimal_enhancement,
}),
};
pub const arch8 = Cpu{
.name = "arch8",
.llvm_name = "arch8",
.features = featureSet(&[_]Feature{}),
};
pub const arch9 = Cpu{
.name = "arch9",
.llvm_name = "arch9",
.features = featureSet(&[_]Feature{
.distinct_ops,
.fast_serialization,
.fp_extension,
.high_word,
.interlocked_access1,
.load_store_on_cond,
.message_security_assist_extension3,
.message_security_assist_extension4,
.population_count,
.reset_reference_bits_multiple,
}),
};
pub const generic = Cpu{
.name = "generic",
.llvm_name = "generic",
.features = featureSet(&[_]Feature{}),
};
pub const z10 = Cpu{
.name = "z10",
.llvm_name = "z10",
.features = featureSet(&[_]Feature{}),
};
pub const z13 = Cpu{
.name = "z13",
.llvm_name = "z13",
.features = featureSet(&[_]Feature{
.dfp_packed_conversion,
.dfp_zoned_conversion,
.distinct_ops,
.enhanced_dat_2,
.execution_hint,
.fast_serialization,
.fp_extension,
.high_word,
.interlocked_access1,
.load_and_trap,
.load_and_zero_rightmost_byte,
.load_store_on_cond,
.load_store_on_cond_2,
.message_security_assist_extension3,
.message_security_assist_extension4,
.message_security_assist_extension5,
.miscellaneous_extensions,
.population_count,
.processor_assist,
.reset_reference_bits_multiple,
.transactional_execution,
.vector,
}),
};
pub const z14 = Cpu{
.name = "z14",
.llvm_name = "z14",
.features = featureSet(&[_]Feature{
.dfp_packed_conversion,
.dfp_zoned_conversion,
.distinct_ops,
.enhanced_dat_2,
.execution_hint,
.fast_serialization,
.fp_extension,
.guarded_storage,
.high_word,
.insert_reference_bits_multiple,
.interlocked_access1,
.load_and_trap,
.load_and_zero_rightmost_byte,
.load_store_on_cond,
.load_store_on_cond_2,
.message_security_assist_extension3,
.message_security_assist_extension4,
.message_security_assist_extension5,
.message_security_assist_extension7,
.message_security_assist_extension8,
.miscellaneous_extensions,
.miscellaneous_extensions_2,
.population_count,
.processor_assist,
.reset_reference_bits_multiple,
.transactional_execution,
.vector,
.vector_enhancements_1,
.vector_packed_decimal,
}),
};
pub const z196 = Cpu{
.name = "z196",
.llvm_name = "z196",
.features = featureSet(&[_]Feature{
.distinct_ops,
.fast_serialization,
.fp_extension,
.high_word,
.interlocked_access1,
.load_store_on_cond,
.message_security_assist_extension3,
.message_security_assist_extension4,
.population_count,
.reset_reference_bits_multiple,
}),
};
pub const zEC12 = Cpu{
.name = "zEC12",
.llvm_name = "zEC12",
.features = featureSet(&[_]Feature{
.dfp_zoned_conversion,
.distinct_ops,
.enhanced_dat_2,
.execution_hint,
.fast_serialization,
.fp_extension,
.high_word,
.interlocked_access1,
.load_and_trap,
.load_store_on_cond,
.message_security_assist_extension3,
.message_security_assist_extension4,
.miscellaneous_extensions,
.population_count,
.processor_assist,
.reset_reference_bits_multiple,
.transactional_execution,
}),
};
};
/// All systemz CPUs, sorted alphabetically by name.
/// TODO: Replace this with usage of `std.meta.declList`. It does work, but stage1
/// compiler has inefficient memory and CPU usage, affecting build times.
pub const all_cpus = &[_]*const Cpu{
&cpu.arch10,
&cpu.arch11,
&cpu.arch12,
&cpu.arch13,
&cpu.arch8,
&cpu.arch9,
&cpu.generic,
&cpu.z10,
&cpu.z13,
&cpu.z14,
&cpu.z196,
&cpu.zEC12,
};

114
lib/std/target/wasm.zig Normal file
View File

@ -0,0 +1,114 @@
const std = @import("../std.zig");
const Cpu = std.Target.Cpu;
pub const Feature = enum {
atomics,
bulk_memory,
exception_handling,
multivalue,
mutable_globals,
nontrapping_fptoint,
sign_ext,
simd128,
tail_call,
unimplemented_simd128,
};
pub usingnamespace Cpu.Feature.feature_set_fns(Feature);
pub const all_features = blk: {
const len = @typeInfo(Feature).Enum.fields.len;
std.debug.assert(len <= Cpu.Feature.Set.needed_bit_count);
var result: [len]Cpu.Feature = undefined;
result[@enumToInt(Feature.atomics)] = .{
.llvm_name = "atomics",
.description = "Enable Atomics",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.bulk_memory)] = .{
.llvm_name = "bulk-memory",
.description = "Enable bulk memory operations",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.exception_handling)] = .{
.llvm_name = "exception-handling",
.description = "Enable Wasm exception handling",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.multivalue)] = .{
.llvm_name = "multivalue",
.description = "Enable multivalue blocks, instructions, and functions",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.mutable_globals)] = .{
.llvm_name = "mutable-globals",
.description = "Enable mutable globals",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.nontrapping_fptoint)] = .{
.llvm_name = "nontrapping-fptoint",
.description = "Enable non-trapping float-to-int conversion operators",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.sign_ext)] = .{
.llvm_name = "sign-ext",
.description = "Enable sign extension operators",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.simd128)] = .{
.llvm_name = "simd128",
.description = "Enable 128-bit SIMD",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.tail_call)] = .{
.llvm_name = "tail-call",
.description = "Enable tail call instructions",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.unimplemented_simd128)] = .{
.llvm_name = "unimplemented-simd128",
.description = "Enable 128-bit SIMD not yet implemented in engines",
.dependencies = featureSet(&[_]Feature{
.simd128,
}),
};
const ti = @typeInfo(Feature);
for (result) |*elem, i| {
elem.index = i;
elem.name = ti.Enum.fields[i].name;
}
break :blk result;
};
pub const cpu = struct {
pub const bleeding_edge = Cpu{
.name = "bleeding_edge",
.llvm_name = "bleeding-edge",
.features = featureSet(&[_]Feature{
.atomics,
.mutable_globals,
.nontrapping_fptoint,
.sign_ext,
.simd128,
}),
};
pub const generic = Cpu{
.name = "generic",
.llvm_name = "generic",
.features = featureSet(&[_]Feature{}),
};
pub const mvp = Cpu{
.name = "mvp",
.llvm_name = "mvp",
.features = featureSet(&[_]Feature{}),
};
};
/// All wasm CPUs, sorted alphabetically by name.
/// TODO: Replace this with usage of `std.meta.declList`. It does work, but stage1
/// compiler has inefficient memory and CPU usage, affecting build times.
pub const all_cpus = &[_]*const Cpu{
&cpu.bleeding_edge,
&cpu.generic,
&cpu.mvp,
};

2859
lib/std/target/x86.zig Normal file

File diff suppressed because it is too large Load Diff

View File

@ -776,6 +776,7 @@ pub extern fn ZigClangFieldDecl_getCanonicalDecl(field_decl: ?*const struct_ZigC
pub extern fn ZigClangEnumDecl_getCanonicalDecl(self: ?*const struct_ZigClangEnumDecl) ?*const struct_ZigClangTagDecl;
pub extern fn ZigClangTypedefNameDecl_getCanonicalDecl(self: ?*const struct_ZigClangTypedefNameDecl) ?*const struct_ZigClangTypedefNameDecl;
pub extern fn ZigClangFunctionDecl_getCanonicalDecl(self: ?*const struct_ZigClangFunctionDecl) ?*const struct_ZigClangFunctionDecl;
pub extern fn ZigClangParmVarDecl_getOriginalType(self: ?*const struct_ZigClangParmVarDecl) struct_ZigClangQualType;
pub extern fn ZigClangVarDecl_getCanonicalDecl(self: ?*const struct_ZigClangVarDecl) ?*const struct_ZigClangVarDecl;
pub extern fn ZigClangVarDecl_getSectionAttribute(self: *const ZigClangVarDecl, len: *usize) ?[*]const u8;
pub extern fn ZigClangFunctionDecl_getAlignedAttribute(self: *const ZigClangFunctionDecl, *const ZigClangASTContext) c_uint;
@ -817,6 +818,7 @@ pub extern fn ZigClangQualType_isRestrictQualified(self: struct_ZigClangQualType
pub extern fn ZigClangType_getTypeClass(self: ?*const struct_ZigClangType) ZigClangTypeClass;
pub extern fn ZigClangType_getPointeeType(self: ?*const struct_ZigClangType) struct_ZigClangQualType;
pub extern fn ZigClangType_isVoidType(self: ?*const struct_ZigClangType) bool;
pub extern fn ZigClangType_isConstantArrayType(self: ?*const struct_ZigClangType) bool;
pub extern fn ZigClangType_isRecordType(self: ?*const struct_ZigClangType) bool;
pub extern fn ZigClangType_isArrayType(self: ?*const struct_ZigClangType) bool;
pub extern fn ZigClangType_isBooleanType(self: ?*const struct_ZigClangType) bool;

View File

@ -79,7 +79,9 @@ pub fn main() !void {
} else if (mem.eql(u8, cmd, "libc")) {
return cmdLibC(allocator, cmd_args);
} else if (mem.eql(u8, cmd, "targets")) {
return cmdTargets(allocator, cmd_args);
// TODO figure out the current target rather than using the target that was specified when
// compiling the compiler
return @import("print_targets.zig").cmdTargets(allocator, cmd_args, stdout, Target.current);
} else if (mem.eql(u8, cmd, "version")) {
return cmdVersion(allocator, cmd_args);
} else if (mem.eql(u8, cmd, "zen")) {
@ -789,48 +791,6 @@ async fn fmtPath(fmt: *Fmt, file_path_ref: []const u8, check_mode: bool) FmtErro
}
}
// cmd:targets /////////////////////////////////////////////////////////////////////////////////////
fn cmdTargets(allocator: *Allocator, args: []const []const u8) !void {
try stdout.write("Architectures:\n");
{
comptime var i: usize = 0;
inline while (i < @memberCount(builtin.Arch)) : (i += 1) {
comptime const arch_tag = @memberName(builtin.Arch, i);
// NOTE: Cannot use empty string, see #918.
comptime const native_str = if (comptime mem.eql(u8, arch_tag, @tagName(builtin.arch))) " (native)\n" else "\n";
try stdout.print(" {}{}", .{ arch_tag, native_str });
}
}
try stdout.write("\n");
try stdout.write("Operating Systems:\n");
{
comptime var i: usize = 0;
inline while (i < @memberCount(Target.Os)) : (i += 1) {
comptime const os_tag = @memberName(Target.Os, i);
// NOTE: Cannot use empty string, see #918.
comptime const native_str = if (comptime mem.eql(u8, os_tag, @tagName(builtin.os))) " (native)\n" else "\n";
try stdout.print(" {}{}", .{ os_tag, native_str });
}
}
try stdout.write("\n");
try stdout.write("C ABIs:\n");
{
comptime var i: usize = 0;
inline while (i < @memberCount(Target.Abi)) : (i += 1) {
comptime const abi_tag = @memberName(Target.Abi, i);
// NOTE: Cannot use empty string, see #918.
comptime const native_str = if (comptime mem.eql(u8, abi_tag, @tagName(builtin.abi))) " (native)\n" else "\n";
try stdout.print(" {}{}", .{ abi_tag, native_str });
}
}
}
fn cmdVersion(allocator: *Allocator, args: []const []const u8) !void {
try stdout.print("{}\n", .{std.mem.toSliceConst(u8, c.ZIG_VERSION_STRING)});
}

View File

@ -0,0 +1,251 @@
const std = @import("std");
const fs = std.fs;
const io = std.io;
const mem = std.mem;
const Allocator = mem.Allocator;
const Target = std.Target;
// TODO this is hard-coded until self-hosted gains this information canonically
const available_libcs = [_][]const u8{
"aarch64_be-linux-gnu",
"aarch64_be-linux-musl",
"aarch64_be-windows-gnu",
"aarch64-linux-gnu",
"aarch64-linux-musl",
"aarch64-windows-gnu",
"armeb-linux-gnueabi",
"armeb-linux-gnueabihf",
"armeb-linux-musleabi",
"armeb-linux-musleabihf",
"armeb-windows-gnu",
"arm-linux-gnueabi",
"arm-linux-gnueabihf",
"arm-linux-musleabi",
"arm-linux-musleabihf",
"arm-windows-gnu",
"i386-linux-gnu",
"i386-linux-musl",
"i386-windows-gnu",
"mips64el-linux-gnuabi64",
"mips64el-linux-gnuabin32",
"mips64el-linux-musl",
"mips64-linux-gnuabi64",
"mips64-linux-gnuabin32",
"mips64-linux-musl",
"mipsel-linux-gnu",
"mipsel-linux-musl",
"mips-linux-gnu",
"mips-linux-musl",
"powerpc64le-linux-gnu",
"powerpc64le-linux-musl",
"powerpc64-linux-gnu",
"powerpc64-linux-musl",
"powerpc-linux-gnu",
"powerpc-linux-musl",
"riscv64-linux-gnu",
"riscv64-linux-musl",
"s390x-linux-gnu",
"s390x-linux-musl",
"sparc-linux-gnu",
"sparcv9-linux-gnu",
"wasm32-freestanding-musl",
"x86_64-linux-gnu (native)",
"x86_64-linux-gnux32",
"x86_64-linux-musl",
"x86_64-windows-gnu",
};
// TODO this is hard-coded until self-hosted gains this information canonically
const available_glibcs = [_][]const u8{
"2.0",
"2.1",
"2.1.1",
"2.1.2",
"2.1.3",
"2.2",
"2.2.1",
"2.2.2",
"2.2.3",
"2.2.4",
"2.2.5",
"2.2.6",
"2.3",
"2.3.2",
"2.3.3",
"2.3.4",
"2.4",
"2.5",
"2.6",
"2.7",
"2.8",
"2.9",
"2.10",
"2.11",
"2.12",
"2.13",
"2.14",
"2.15",
"2.16",
"2.17",
"2.18",
"2.19",
"2.22",
"2.23",
"2.24",
"2.25",
"2.26",
"2.27",
"2.28",
"2.29",
"2.30",
};
pub fn cmdTargets(
allocator: *Allocator,
args: []const []const u8,
stdout: *io.OutStream(fs.File.WriteError),
native_target: Target,
) !void {
const BOS = io.BufferedOutStream(fs.File.WriteError);
var bos = BOS.init(stdout);
var jws = std.json.WriteStream(BOS.Stream, 6).init(&bos.stream);
try jws.beginObject();
try jws.objectField("arch");
try jws.beginObject();
{
inline for (@typeInfo(Target.Arch).Union.fields) |field| {
try jws.objectField(field.name);
if (field.field_type == void) {
try jws.emitNull();
} else {
try jws.emitString(@typeName(field.field_type));
}
}
}
try jws.endObject();
try jws.objectField("subArch");
try jws.beginObject();
const sub_arch_list = [_]type{
Target.Arch.Arm32,
Target.Arch.Arm64,
Target.Arch.Kalimba,
Target.Arch.Mips,
};
inline for (sub_arch_list) |SubArch| {
try jws.objectField(@typeName(SubArch));
try jws.beginArray();
inline for (@typeInfo(SubArch).Enum.fields) |field| {
try jws.arrayElem();
try jws.emitString(field.name);
}
try jws.endArray();
}
try jws.endObject();
try jws.objectField("os");
try jws.beginArray();
inline for (@typeInfo(Target.Os).Enum.fields) |field| {
try jws.arrayElem();
try jws.emitString(field.name);
}
try jws.endArray();
try jws.objectField("abi");
try jws.beginArray();
inline for (@typeInfo(Target.Abi).Enum.fields) |field| {
try jws.arrayElem();
try jws.emitString(field.name);
}
try jws.endArray();
try jws.objectField("libc");
try jws.beginArray();
for (available_libcs) |libc| {
try jws.arrayElem();
try jws.emitString(libc);
}
try jws.endArray();
try jws.objectField("glibc");
try jws.beginArray();
for (available_glibcs) |glibc| {
try jws.arrayElem();
try jws.emitString(glibc);
}
try jws.endArray();
try jws.objectField("cpus");
try jws.beginObject();
inline for (@typeInfo(Target.Arch).Union.fields) |field| {
try jws.objectField(field.name);
try jws.beginObject();
const arch = @unionInit(Target.Arch, field.name, undefined);
for (arch.allCpus()) |cpu| {
try jws.objectField(cpu.name);
try jws.beginArray();
for (arch.allFeaturesList()) |feature, i| {
if (cpu.features.isEnabled(@intCast(u8, i))) {
try jws.arrayElem();
try jws.emitString(feature.name);
}
}
try jws.endArray();
}
try jws.endObject();
}
try jws.endObject();
try jws.objectField("cpuFeatures");
try jws.beginObject();
inline for (@typeInfo(Target.Arch).Union.fields) |field| {
try jws.objectField(field.name);
try jws.beginArray();
const arch = @unionInit(Target.Arch, field.name, undefined);
for (arch.allFeaturesList()) |feature| {
try jws.arrayElem();
try jws.emitString(feature.name);
}
try jws.endArray();
}
try jws.endObject();
try jws.objectField("native");
try jws.beginObject();
{
const triple = try native_target.zigTriple(allocator);
defer allocator.free(triple);
try jws.objectField("triple");
try jws.emitString(triple);
}
try jws.objectField("arch");
try jws.emitString(@tagName(native_target.getArch()));
try jws.objectField("os");
try jws.emitString(@tagName(native_target.getOs()));
try jws.objectField("abi");
try jws.emitString(@tagName(native_target.getAbi()));
try jws.objectField("cpuName");
const cpu_features = native_target.getCpuFeatures();
try jws.emitString(cpu_features.cpu.name);
{
try jws.objectField("cpuFeatures");
try jws.beginArray();
for (native_target.getArch().allFeaturesList()) |feature, i_usize| {
const index = @intCast(Target.Cpu.Feature.Set.Index, i_usize);
if (cpu_features.features.isEnabled(index)) {
try jws.arrayElem();
try jws.emitString(feature.name);
}
}
try jws.endArray();
}
// TODO implement native glibc version detection in self-hosted
try jws.endObject();
try jws.endObject();
try bos.stream.writeByte('\n');
return bos.flush();
}

View File

@ -9,9 +9,11 @@ const process = std.process;
const Allocator = mem.Allocator;
const ArrayList = std.ArrayList;
const Buffer = std.Buffer;
const Target = std.Target;
const self_hosted_main = @import("main.zig");
const errmsg = @import("errmsg.zig");
const DepTokenizer = @import("dep_tokenizer.zig").Tokenizer;
const assert = std.debug.assert;
var stderr_file: fs.File = undefined;
var stderr: *io.OutStream(fs.File.WriteError) = undefined;
@ -63,6 +65,7 @@ const Error = extern enum {
CacheUnavailable,
PathTooLong,
CCompilerCannotFindFile,
NoCCompilerInstalled,
ReadingDepFile,
InvalidDepFile,
MissingArchitecture,
@ -80,6 +83,15 @@ const Error = extern enum {
OperationAborted,
BrokenPipe,
NoSpaceLeft,
NotLazy,
IsAsync,
ImportOutsidePkgPath,
UnknownCpu,
UnknownSubArchitecture,
UnknownCpuFeature,
InvalidCpuFeatures,
InvalidLlvmCpuFeaturesFormat,
UnknownApplicationBinaryInterface,
};
const FILE = std.c.FILE;
@ -149,7 +161,7 @@ fn fmtMain(argc: c_int, argv: [*]const [*:0]const u8) !void {
const argc_usize = @intCast(usize, argc);
var arg_i: usize = 0;
while (arg_i < argc_usize) : (arg_i += 1) {
try args_list.append(std.mem.toSliceConst(u8, argv[arg_i]));
try args_list.append(mem.toSliceConst(u8, argv[arg_i]));
}
stdout = &std.io.getStdOut().outStream().stream;
@ -527,3 +539,294 @@ export fn stage2_progress_update_node(node: *std.Progress.Node, done_count: usiz
node.activate();
node.context.maybeRefresh();
}
fn cpuFeaturesFromLLVM(
arch: Target.Arch,
llvm_cpu_name_z: ?[*:0]const u8,
llvm_cpu_features_opt: ?[*:0]const u8,
) !Target.CpuFeatures {
var result = arch.getBaselineCpuFeatures();
if (llvm_cpu_name_z) |cpu_name_z| {
const llvm_cpu_name = mem.toSliceConst(u8, cpu_name_z);
for (arch.allCpus()) |cpu| {
const this_llvm_name = cpu.llvm_name orelse continue;
if (mem.eql(u8, this_llvm_name, llvm_cpu_name)) {
// Here we use the non-dependencies-populated set,
// so that subtracting features later in this function
// affect the prepopulated set.
result = Target.CpuFeatures{
.cpu = cpu,
.features = cpu.features,
};
break;
}
}
}
const all_features = arch.allFeaturesList();
if (llvm_cpu_features_opt) |llvm_cpu_features| {
var it = mem.tokenize(mem.toSliceConst(u8, llvm_cpu_features), ",");
while (it.next()) |decorated_llvm_feat| {
var op: enum {
add,
sub,
} = undefined;
var llvm_feat: []const u8 = undefined;
if (mem.startsWith(u8, decorated_llvm_feat, "+")) {
op = .add;
llvm_feat = decorated_llvm_feat[1..];
} else if (mem.startsWith(u8, decorated_llvm_feat, "-")) {
op = .sub;
llvm_feat = decorated_llvm_feat[1..];
} else {
return error.InvalidLlvmCpuFeaturesFormat;
}
for (all_features) |feature, index_usize| {
const this_llvm_name = feature.llvm_name orelse continue;
if (mem.eql(u8, llvm_feat, this_llvm_name)) {
const index = @intCast(Target.Cpu.Feature.Set.Index, index_usize);
switch (op) {
.add => result.features.addFeature(index),
.sub => result.features.removeFeature(index),
}
break;
}
}
}
}
result.features.populateDependencies(all_features);
return result;
}
// ABI warning
export fn stage2_cmd_targets(zig_triple: [*:0]const u8) c_int {
cmdTargets(zig_triple) catch |err| {
std.debug.warn("unable to list targets: {}\n", .{@errorName(err)});
return -1;
};
return 0;
}
fn cmdTargets(zig_triple: [*:0]const u8) !void {
var target = try Target.parse(mem.toSliceConst(u8, zig_triple));
target.Cross.cpu_features = blk: {
const llvm = @import("llvm.zig");
const llvm_cpu_name = llvm.GetHostCPUName();
const llvm_cpu_features = llvm.GetNativeFeatures();
break :blk try cpuFeaturesFromLLVM(target.Cross.arch, llvm_cpu_name, llvm_cpu_features);
};
return @import("print_targets.zig").cmdTargets(
std.heap.c_allocator,
&[0][]u8{},
&std.io.getStdOut().outStream().stream,
target,
);
}
const Stage2CpuFeatures = struct {
allocator: *mem.Allocator,
cpu_features: Target.CpuFeatures,
llvm_features_str: ?[*:0]const u8,
builtin_str: [:0]const u8,
cache_hash: [:0]const u8,
const Self = @This();
fn createFromNative(allocator: *mem.Allocator) !*Self {
const arch = Target.current.getArch();
const llvm = @import("llvm.zig");
const llvm_cpu_name = llvm.GetHostCPUName();
const llvm_cpu_features = llvm.GetNativeFeatures();
const cpu_features = try cpuFeaturesFromLLVM(arch, llvm_cpu_name, llvm_cpu_features);
return createFromCpuFeatures(allocator, arch, cpu_features);
}
fn createFromCpuFeatures(
allocator: *mem.Allocator,
arch: Target.Arch,
cpu_features: Target.CpuFeatures,
) !*Self {
const self = try allocator.create(Self);
errdefer allocator.destroy(self);
const cache_hash = try std.fmt.allocPrint0(allocator, "{}\n{}", .{
cpu_features.cpu.name,
cpu_features.features.asBytes(),
});
errdefer allocator.free(cache_hash);
const generic_arch_name = arch.genericName();
var builtin_str_buffer = try std.Buffer.allocPrint(allocator,
\\CpuFeatures{{
\\ .cpu = &Target.{}.cpu.{},
\\ .features = Target.{}.featureSet(&[_]Target.{}.Feature{{
\\
, .{
generic_arch_name,
cpu_features.cpu.name,
generic_arch_name,
generic_arch_name,
});
defer builtin_str_buffer.deinit();
var llvm_features_buffer = try std.Buffer.initSize(allocator, 0);
defer llvm_features_buffer.deinit();
for (arch.allFeaturesList()) |feature, index_usize| {
const index = @intCast(Target.Cpu.Feature.Set.Index, index_usize);
const is_enabled = cpu_features.features.isEnabled(index);
if (feature.llvm_name) |llvm_name| {
const plus_or_minus = "-+"[@boolToInt(is_enabled)];
try llvm_features_buffer.appendByte(plus_or_minus);
try llvm_features_buffer.append(llvm_name);
try llvm_features_buffer.append(",");
}
if (is_enabled) {
// TODO some kind of "zig identifier escape" function rather than
// unconditionally using @"" syntax
try builtin_str_buffer.append(" .@\"");
try builtin_str_buffer.append(feature.name);
try builtin_str_buffer.append("\",\n");
}
}
try builtin_str_buffer.append(
\\ }),
\\};
\\
);
assert(mem.endsWith(u8, llvm_features_buffer.toSliceConst(), ","));
llvm_features_buffer.shrink(llvm_features_buffer.len() - 1);
self.* = Self{
.allocator = allocator,
.cpu_features = cpu_features,
.llvm_features_str = llvm_features_buffer.toOwnedSlice().ptr,
.builtin_str = builtin_str_buffer.toOwnedSlice(),
.cache_hash = cache_hash,
};
return self;
}
fn destroy(self: *Self) void {
self.allocator.free(self.cache_hash);
self.allocator.free(self.builtin_str);
// TODO if (self.llvm_features_str) |llvm_features_str| self.allocator.free(llvm_features_str);
self.allocator.destroy(self);
}
};
// ABI warning
export fn stage2_cpu_features_parse(
result: **Stage2CpuFeatures,
zig_triple: ?[*:0]const u8,
cpu_name: ?[*:0]const u8,
cpu_features: ?[*:0]const u8,
) Error {
result.* = stage2ParseCpuFeatures(zig_triple, cpu_name, cpu_features) catch |err| switch (err) {
error.OutOfMemory => return .OutOfMemory,
error.UnknownArchitecture => return .UnknownArchitecture,
error.UnknownSubArchitecture => return .UnknownSubArchitecture,
error.UnknownOperatingSystem => return .UnknownOperatingSystem,
error.UnknownApplicationBinaryInterface => return .UnknownApplicationBinaryInterface,
error.MissingOperatingSystem => return .MissingOperatingSystem,
error.MissingArchitecture => return .MissingArchitecture,
error.InvalidLlvmCpuFeaturesFormat => return .InvalidLlvmCpuFeaturesFormat,
error.InvalidCpuFeatures => return .InvalidCpuFeatures,
};
return .None;
}
fn stage2ParseCpuFeatures(
zig_triple_oz: ?[*:0]const u8,
cpu_name_oz: ?[*:0]const u8,
cpu_features_oz: ?[*:0]const u8,
) !*Stage2CpuFeatures {
const zig_triple_z = zig_triple_oz orelse return Stage2CpuFeatures.createFromNative(std.heap.c_allocator);
const target = try Target.parse(mem.toSliceConst(u8, zig_triple_z));
const arch = target.Cross.arch;
const cpu = if (cpu_name_oz) |cpu_name_z| blk: {
const cpu_name = mem.toSliceConst(u8, cpu_name_z);
break :blk arch.parseCpu(cpu_name) catch |err| switch (err) {
error.UnknownCpu => {
std.debug.warn("Unknown CPU: '{}'\nAvailable CPUs for architecture '{}':\n", .{
cpu_name,
@tagName(arch),
});
for (arch.allCpus()) |cpu| {
std.debug.warn(" {}\n", .{cpu.name});
}
process.exit(1);
},
else => |e| return e,
};
} else target.Cross.cpu_features.cpu;
var set = if (cpu_features_oz) |cpu_features_z| blk: {
const cpu_features = mem.toSliceConst(u8, cpu_features_z);
break :blk arch.parseCpuFeatureSet(cpu, cpu_features) catch |err| switch (err) {
error.UnknownCpuFeature => {
std.debug.warn(
\\Unknown CPU features specified.
\\Available CPU features for architecture '{}':
\\
, .{@tagName(arch)});
for (arch.allFeaturesList()) |feature| {
std.debug.warn(" {}\n", .{feature.name});
}
process.exit(1);
},
else => |e| return e,
};
} else cpu.features;
if (arch.subArchFeature()) |index| {
set.addFeature(index);
}
set.populateDependencies(arch.allFeaturesList());
return Stage2CpuFeatures.createFromCpuFeatures(std.heap.c_allocator, arch, .{
.cpu = cpu,
.features = set,
});
}
// ABI warning
export fn stage2_cpu_features_get_cache_hash(
cpu_features: *const Stage2CpuFeatures,
ptr: *[*:0]const u8,
len: *usize,
) void {
ptr.* = cpu_features.cache_hash.ptr;
len.* = cpu_features.cache_hash.len;
}
// ABI warning
export fn stage2_cpu_features_get_builtin_str(
cpu_features: *const Stage2CpuFeatures,
ptr: *[*:0]const u8,
len: *usize,
) void {
ptr.* = cpu_features.builtin_str.ptr;
len.* = cpu_features.builtin_str.len;
}
// ABI warning
export fn stage2_cpu_features_get_llvm_cpu(cpu_features: *const Stage2CpuFeatures) ?[*:0]const u8 {
return if (cpu_features.cpu_features.cpu.llvm_name) |s| s.ptr else null;
}
// ABI warning
export fn stage2_cpu_features_get_llvm_features(cpu_features: *const Stage2CpuFeatures) ?[*:0]const u8 {
return cpu_features.llvm_features_str;
}

View File

@ -443,12 +443,22 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void {
};
var fn_qt = ZigClangFunctionDecl_getType(fn_decl);
var fn_type = ZigClangQualType_getTypePtr(fn_qt);
if (ZigClangType_getTypeClass(fn_type) == .Attributed) {
const attr_type = @ptrCast(*const ZigClangAttributedType, fn_type);
fn_qt = ZigClangAttributedType_getEquivalentType(attr_type);
fn_type = ZigClangQualType_getTypePtr(fn_qt);
}
const fn_type = while (true) {
const fn_type = ZigClangQualType_getTypePtr(fn_qt);
switch (ZigClangType_getTypeClass(fn_type)) {
.Attributed => {
const attr_type = @ptrCast(*const ZigClangAttributedType, fn_type);
fn_qt = ZigClangAttributedType_getEquivalentType(attr_type);
},
.Paren => {
const paren_type = @ptrCast(*const ZigClangParenType, fn_type);
fn_qt = ZigClangParenType_getInnerType(paren_type);
},
else => break fn_type,
}
} else unreachable;
const proto_node = switch (ZigClangType_getTypeClass(fn_type)) {
.FunctionProto => blk: {
@ -485,6 +495,7 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void {
block_scope.block_node = block_node;
var it = proto_node.params.iterator(0);
var param_id: c_uint = 0;
while (it.next()) |p| {
const param = @fieldParentPtr(ast.Node.ParamDecl, "base", p.*);
const param_name = if (param.name_token) |name_tok|
@ -498,18 +509,27 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void {
const mangled_param_name = try block_scope.makeMangledName(c, param_name);
const c_param = ZigClangFunctionDecl_getParamDecl(fn_decl, param_id);
const qual_type = ZigClangParmVarDecl_getOriginalType(c_param);
const is_const = ZigClangQualType_isConstQualified(qual_type);
const arg_name = blk: {
const bare_arg_name = try std.fmt.allocPrint(c.a(), "arg_{}", .{mangled_param_name});
const param_prefix = if (is_const) "" else "arg_";
const bare_arg_name = try std.fmt.allocPrint(c.a(), "{}{}", .{ param_prefix, mangled_param_name });
break :blk try block_scope.makeMangledName(c, bare_arg_name);
};
const node = try transCreateNodeVarDecl(c, false, false, mangled_param_name);
node.eq_token = try appendToken(c, .Equal, "=");
node.init_node = try transCreateNodeIdentifier(c, arg_name);
node.semicolon_token = try appendToken(c, .Semicolon, ";");
try block_node.statements.push(&node.base);
param.name_token = try appendIdentifier(c, arg_name);
_ = try appendToken(c, .Colon, ":");
if (!is_const) {
const node = try transCreateNodeVarDecl(c, false, false, mangled_param_name);
node.eq_token = try appendToken(c, .Equal, "=");
node.init_node = try transCreateNodeIdentifier(c, arg_name);
node.semicolon_token = try appendToken(c, .Semicolon, ";");
try block_node.statements.push(&node.base);
param.name_token = try appendIdentifier(c, arg_name);
_ = try appendToken(c, .Colon, ":");
}
param_id += 1;
}
transCompoundStmtInline(rp, &block_scope.base, @ptrCast(*const ZigClangCompoundStmt, body_stmt), block_node) catch |err| switch (err) {
@ -1982,7 +2002,8 @@ fn transInitListExprArray(
const arr_type = ZigClangType_getAsArrayTypeUnsafe(ty);
const child_qt = ZigClangArrayType_getElementType(arr_type);
const init_count = ZigClangInitListExpr_getNumInits(expr);
const const_arr_ty = @ptrCast(*const ZigClangConstantArrayType, ty);
assert(ZigClangType_isConstantArrayType(@ptrCast(*const ZigClangType, arr_type)));
const const_arr_ty = @ptrCast(*const ZigClangConstantArrayType, arr_type);
const size_ap_int = ZigClangConstantArrayType_getSize(const_arr_ty);
const all_count = ZigClangAPInt_getLimitedValue(size_ap_int, math.maxInt(usize));
const leftover_count = all_count - init_count;

File diff suppressed because it is too large Load Diff

View File

@ -199,7 +199,7 @@ ScopeLoop *create_loop_scope(CodeGen *g, AstNode *node, Scope *parent) {
return scope;
}
Scope *create_runtime_scope(CodeGen *g, AstNode *node, Scope *parent, IrInstruction *is_comptime) {
Scope *create_runtime_scope(CodeGen *g, AstNode *node, Scope *parent, IrInstSrc *is_comptime) {
ScopeRuntime *scope = allocate<ScopeRuntime>(1);
scope->is_comptime = is_comptime;
init_scope(g, &scope->base, ScopeIdRuntime, node, parent);
@ -593,9 +593,9 @@ ZigType *get_pointer_to_type_extra2(CodeGen *g, ZigType *child_type, bool is_con
}
if (inferred_struct_field != nullptr) {
entry->abi_size = g->builtin_types.entry_usize->abi_size;
entry->size_in_bits = g->builtin_types.entry_usize->size_in_bits;
entry->abi_align = g->builtin_types.entry_usize->abi_align;
entry->abi_size = SIZE_MAX;
entry->size_in_bits = SIZE_MAX;
entry->abi_align = UINT32_MAX;
} else if (type_is_resolved(child_type, ResolveStatusZeroBitsKnown)) {
if (type_has_bits(child_type)) {
entry->abi_size = g->builtin_types.entry_usize->abi_size;
@ -1102,11 +1102,28 @@ ZigType *get_partial_container_type(CodeGen *g, Scope *scope, ContainerKind kind
ZigValue *analyze_const_value(CodeGen *g, Scope *scope, AstNode *node, ZigType *type_entry,
Buf *type_name, UndefAllowed undef)
{
Error err;
ZigValue *result = create_const_vals(1);
ZigValue *result_ptr = create_const_vals(1);
result->special = ConstValSpecialUndef;
result->type = (type_entry == nullptr) ? g->builtin_types.entry_var : type_entry;
result_ptr->special = ConstValSpecialStatic;
result_ptr->type = get_pointer_to_type(g, result->type, false);
result_ptr->data.x_ptr.mut = ConstPtrMutComptimeVar;
result_ptr->data.x_ptr.special = ConstPtrSpecialRef;
result_ptr->data.x_ptr.data.ref.pointee = result;
size_t backward_branch_count = 0;
size_t backward_branch_quota = default_backward_branch_quota;
return ir_eval_const_value(g, scope, node, type_entry,
if ((err = ir_eval_const_value(g, scope, node, result_ptr,
&backward_branch_count, &backward_branch_quota,
nullptr, nullptr, node, type_name, nullptr, nullptr, undef);
nullptr, nullptr, node, type_name, nullptr, nullptr, undef)))
{
return g->invalid_inst_gen->value;
}
destroy(result_ptr, "ZigValue");
return result;
}
Error type_val_resolve_zero_bits(CodeGen *g, ZigValue *type_val, ZigType *parent_type,
@ -3350,7 +3367,7 @@ static void get_fully_qualified_decl_name(CodeGen *g, Buf *buf, Tld *tld, bool i
ZigFn *create_fn_raw(CodeGen *g, FnInline inline_value) {
ZigFn *fn_entry = allocate<ZigFn>(1, "ZigFn");
fn_entry->ir_executable = allocate<IrExecutable>(1, "IrExecutablePass1");
fn_entry->ir_executable = allocate<IrExecutableSrc>(1, "IrExecutableSrc");
fn_entry->prealloc_backward_branch_quota = default_backward_branch_quota;
@ -3829,7 +3846,6 @@ ZigVar *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf
variable_entry->var_type = var_type;
variable_entry->parent_scope = parent_scope;
variable_entry->shadowable = false;
variable_entry->mem_slot_index = SIZE_MAX;
variable_entry->src_arg_index = SIZE_MAX;
assert(name);
@ -3930,7 +3946,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var, bool allow_lazy) {
// TODO more validation for types that can't be used for export/extern variables
ZigType *implicit_type = nullptr;
if (explicit_type && explicit_type->id == ZigTypeIdInvalid) {
if (explicit_type != nullptr && explicit_type->id == ZigTypeIdInvalid) {
implicit_type = explicit_type;
} else if (var_decl->expr) {
init_value = analyze_const_value(g, tld_var->base.parent_scope, var_decl->expr, explicit_type,
@ -4097,7 +4113,7 @@ static void preview_use_decl(CodeGen *g, TldUsingNamespace *using_namespace, Sco
if (type_is_invalid(result->type)) {
dest_decls_scope->any_imports_failed = true;
using_namespace->base.resolution = TldResolutionInvalid;
using_namespace->using_namespace_value = g->invalid_instruction->value;
using_namespace->using_namespace_value = g->invalid_inst_gen->value;
return;
}
@ -4106,7 +4122,7 @@ static void preview_use_decl(CodeGen *g, TldUsingNamespace *using_namespace, Sco
buf_sprintf("expected struct, enum, or union; found '%s'", buf_ptr(&result->data.x_type->name)));
dest_decls_scope->any_imports_failed = true;
using_namespace->base.resolution = TldResolutionInvalid;
using_namespace->using_namespace_value = g->invalid_instruction->value;
using_namespace->using_namespace_value = g->invalid_inst_gen->value;
return;
}
}
@ -4667,12 +4683,12 @@ static void analyze_fn_async(CodeGen *g, ZigFn *fn, bool resolve_frame) {
}
for (size_t i = 0; i < fn->call_list.length; i += 1) {
IrInstructionCallGen *call = fn->call_list.at(i);
IrInstGenCall *call = fn->call_list.at(i);
if (call->fn_entry == nullptr) {
// TODO function pointer call here, could be anything
continue;
}
switch (analyze_callee_async(g, fn, call->fn_entry, call->base.source_node, must_not_be_async,
switch (analyze_callee_async(g, fn, call->fn_entry, call->base.base.source_node, must_not_be_async,
call->modifier))
{
case ErrorSemanticAnalyzeFail:
@ -4690,10 +4706,10 @@ static void analyze_fn_async(CodeGen *g, ZigFn *fn, bool resolve_frame) {
}
}
for (size_t i = 0; i < fn->await_list.length; i += 1) {
IrInstructionAwaitGen *await = fn->await_list.at(i);
IrInstGenAwait *await = fn->await_list.at(i);
// TODO If this is a noasync await, it doesn't count
// https://github.com/ziglang/zig/issues/3157
switch (analyze_callee_async(g, fn, await->target_fn, await->base.source_node, must_not_be_async,
switch (analyze_callee_async(g, fn, await->target_fn, await->base.base.source_node, must_not_be_async,
CallModifierNone))
{
case ErrorSemanticAnalyzeFail:
@ -4718,8 +4734,14 @@ static void analyze_fn_ir(CodeGen *g, ZigFn *fn, AstNode *return_type_node) {
assert(!fn_type->data.fn.is_generic);
FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id;
if (fn->analyzed_executable.begin_scope == nullptr) {
fn->analyzed_executable.begin_scope = &fn->def_scope->base;
}
if (fn->analyzed_executable.source_node == nullptr) {
fn->analyzed_executable.source_node = fn->body_node;
}
ZigType *block_return_type = ir_analyze(g, fn->ir_executable,
&fn->analyzed_executable, fn_type_id->return_type, return_type_node);
&fn->analyzed_executable, fn_type_id->return_type, return_type_node, nullptr);
fn->src_implicit_return_type = block_return_type;
if (type_is_invalid(block_return_type) || fn->analyzed_executable.first_err_trace_msg != nullptr) {
@ -4784,7 +4806,7 @@ static void analyze_fn_ir(CodeGen *g, ZigFn *fn, AstNode *return_type_node) {
if (g->verbose_ir) {
fprintf(stderr, "fn %s() { // (analyzed)\n", buf_ptr(&fn->symbol_name));
ir_print(g, stderr, &fn->analyzed_executable, 4, IrPassGen);
ir_print_gen(g, stderr, &fn->analyzed_executable, 4);
fprintf(stderr, "}\n");
}
fn->anal_state = FnAnalStateComplete;
@ -4827,7 +4849,7 @@ static void analyze_fn_body(CodeGen *g, ZigFn *fn_table_entry) {
fprintf(stderr, "\n");
ast_render(stderr, fn_table_entry->body_node, 4);
fprintf(stderr, "\nfn %s() { // (IR)\n", buf_ptr(&fn_table_entry->symbol_name));
ir_print(g, stderr, fn_table_entry->ir_executable, 4, IrPassSrc);
ir_print_src(g, stderr, fn_table_entry->ir_executable, 4);
fprintf(stderr, "}\n");
}
@ -5619,6 +5641,8 @@ OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry) {
return OnePossibleValueYes;
return type_has_one_possible_value(g, type_entry->data.array.child_type);
case ZigTypeIdStruct:
// If the recursive function call asks, then we are not one possible value.
type_entry->one_possible_value = OnePossibleValueNo;
for (size_t i = 0; i < type_entry->data.structure.src_field_count; i += 1) {
TypeStructField *field = type_entry->data.structure.fields[i];
OnePossibleValue opv = (field->type_entry != nullptr) ?
@ -5626,6 +5650,7 @@ OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry) {
type_val_resolve_has_one_possible_value(g, field->type_val);
switch (opv) {
case OnePossibleValueInvalid:
type_entry->one_possible_value = OnePossibleValueInvalid;
return OnePossibleValueInvalid;
case OnePossibleValueNo:
return OnePossibleValueNo;
@ -5633,6 +5658,7 @@ OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry) {
continue;
}
}
type_entry->one_possible_value = OnePossibleValueYes;
return OnePossibleValueYes;
case ZigTypeIdErrorSet:
case ZigTypeIdEnum:
@ -5678,6 +5704,9 @@ ZigValue *get_the_one_possible_value(CodeGen *g, ZigType *type_entry) {
assert(field_type != nullptr);
result->data.x_struct.fields[i] = get_the_one_possible_value(g, field_type);
}
} else if (result->type->id == ZigTypeIdPointer) {
result->data.x_ptr.special = ConstPtrSpecialRef;
result->data.x_ptr.data.ref.pointee = get_the_one_possible_value(g, result->type->data.pointer.child_type);
}
g->one_possible_values.put(type_entry, result);
return result;
@ -6191,13 +6220,13 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {
ZigType *fn_type = get_async_fn_type(g, fn->type_entry);
if (fn->analyzed_executable.need_err_code_spill) {
IrInstructionAllocaGen *alloca_gen = allocate<IrInstructionAllocaGen>(1);
alloca_gen->base.id = IrInstructionIdAllocaGen;
alloca_gen->base.source_node = fn->proto_node;
alloca_gen->base.scope = fn->child_scope;
IrInstGenAlloca *alloca_gen = allocate<IrInstGenAlloca>(1);
alloca_gen->base.id = IrInstGenIdAlloca;
alloca_gen->base.base.source_node = fn->proto_node;
alloca_gen->base.base.scope = fn->child_scope;
alloca_gen->base.value = allocate<ZigValue>(1, "ZigValue");
alloca_gen->base.value->type = get_pointer_to_type(g, g->builtin_types.entry_global_error_set, false);
alloca_gen->base.ref_count = 1;
alloca_gen->base.base.ref_count = 1;
alloca_gen->name_hint = "";
fn->alloca_gen_list.append(alloca_gen);
fn->err_code_spill = &alloca_gen->base;
@ -6205,18 +6234,18 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {
ZigType *largest_call_frame_type = nullptr;
// Later we'll change this to be largest_call_frame_type instead of void.
IrInstruction *all_calls_alloca = ir_create_alloca(g, &fn->fndef_scope->base, fn->body_node,
IrInstGen *all_calls_alloca = ir_create_alloca(g, &fn->fndef_scope->base, fn->body_node,
fn, g->builtin_types.entry_void, "@async_call_frame");
for (size_t i = 0; i < fn->call_list.length; i += 1) {
IrInstructionCallGen *call = fn->call_list.at(i);
IrInstGenCall *call = fn->call_list.at(i);
if (call->new_stack != nullptr) {
// don't need to allocate a frame for this
continue;
}
ZigFn *callee = call->fn_entry;
if (callee == nullptr) {
add_node_error(g, call->base.source_node,
add_node_error(g, call->base.base.source_node,
buf_sprintf("function is not comptime-known; @asyncCall required"));
return ErrorSemanticAnalyzeFail;
}
@ -6226,14 +6255,14 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {
if (callee->anal_state == FnAnalStateProbing) {
ErrorMsg *msg = add_node_error(g, fn->proto_node,
buf_sprintf("unable to determine async function frame of '%s'", buf_ptr(&fn->symbol_name)));
g->trace_err = add_error_note(g, msg, call->base.source_node,
g->trace_err = add_error_note(g, msg, call->base.base.source_node,
buf_sprintf("analysis of function '%s' depends on the frame", buf_ptr(&callee->symbol_name)));
return ErrorSemanticAnalyzeFail;
}
ZigType *callee_frame_type = get_fn_frame_type(g, callee);
frame_type->data.frame.resolve_loop_type = callee_frame_type;
frame_type->data.frame.resolve_loop_src_node = call->base.source_node;
frame_type->data.frame.resolve_loop_src_node = call->base.base.source_node;
analyze_fn_body(g, callee);
if (callee->anal_state == FnAnalStateInvalid) {
@ -6249,7 +6278,7 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {
if (!fn_is_async(callee))
continue;
mark_suspension_point(call->base.scope);
mark_suspension_point(call->base.base.scope);
if ((err = type_resolve(g, callee_frame_type, ResolveStatusSizeKnown))) {
return err;
@ -6271,7 +6300,7 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {
// For example: foo() + await z
// The funtion call result of foo() must be spilled.
for (size_t i = 0; i < fn->await_list.length; i += 1) {
IrInstructionAwaitGen *await = fn->await_list.at(i);
IrInstGenAwait *await = fn->await_list.at(i);
// TODO If this is a noasync await, it doesn't suspend
// https://github.com/ziglang/zig/issues/3157
if (await->base.value->special != ConstValSpecialRuntime) {
@ -6293,52 +6322,51 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {
}
// This await is a suspend point, but it might not need a spill.
// We do need to mark the ExprScope as having a suspend point in it.
mark_suspension_point(await->base.scope);
mark_suspension_point(await->base.base.scope);
if (await->result_loc != nullptr) {
// If there's a result location, that is the spill
continue;
}
if (await->base.ref_count == 0)
if (await->base.base.ref_count == 0)
continue;
if (!type_has_bits(await->base.value->type))
continue;
await->result_loc = ir_create_alloca(g, await->base.scope, await->base.source_node, fn,
await->result_loc = ir_create_alloca(g, await->base.base.scope, await->base.base.source_node, fn,
await->base.value->type, "");
}
for (size_t block_i = 0; block_i < fn->analyzed_executable.basic_block_list.length; block_i += 1) {
IrBasicBlock *block = fn->analyzed_executable.basic_block_list.at(block_i);
IrBasicBlockGen *block = fn->analyzed_executable.basic_block_list.at(block_i);
for (size_t instr_i = 0; instr_i < block->instruction_list.length; instr_i += 1) {
IrInstruction *instruction = block->instruction_list.at(instr_i);
if (instruction->id == IrInstructionIdSuspendFinish) {
mark_suspension_point(instruction->scope);
IrInstGen *instruction = block->instruction_list.at(instr_i);
if (instruction->id == IrInstGenIdSuspendFinish) {
mark_suspension_point(instruction->base.scope);
}
}
}
// Now that we've marked all the expr scopes that have to spill, we go over the instructions
// and spill the relevant ones.
for (size_t block_i = 0; block_i < fn->analyzed_executable.basic_block_list.length; block_i += 1) {
IrBasicBlock *block = fn->analyzed_executable.basic_block_list.at(block_i);
IrBasicBlockGen *block = fn->analyzed_executable.basic_block_list.at(block_i);
for (size_t instr_i = 0; instr_i < block->instruction_list.length; instr_i += 1) {
IrInstruction *instruction = block->instruction_list.at(instr_i);
if (instruction->id == IrInstructionIdAwaitGen ||
instruction->id == IrInstructionIdVarPtr ||
instruction->id == IrInstructionIdDeclRef ||
instruction->id == IrInstructionIdAllocaGen)
IrInstGen *instruction = block->instruction_list.at(instr_i);
if (instruction->id == IrInstGenIdAwait ||
instruction->id == IrInstGenIdVarPtr ||
instruction->id == IrInstGenIdAlloca)
{
// This instruction does its own spilling specially, or otherwise doesn't need it.
continue;
}
if (instruction->value->special != ConstValSpecialRuntime)
continue;
if (instruction->ref_count == 0)
if (instruction->base.ref_count == 0)
continue;
if ((err = type_resolve(g, instruction->value->type, ResolveStatusZeroBitsKnown)))
return ErrorSemanticAnalyzeFail;
if (!type_has_bits(instruction->value->type))
continue;
if (scope_needs_spill(instruction->scope)) {
instruction->spill = ir_create_alloca(g, instruction->scope, instruction->source_node,
if (scope_needs_spill(instruction->base.scope)) {
instruction->spill = ir_create_alloca(g, instruction->base.scope, instruction->base.source_node,
fn, instruction->value->type, "");
}
}
@ -6389,14 +6417,14 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {
}
for (size_t alloca_i = 0; alloca_i < fn->alloca_gen_list.length; alloca_i += 1) {
IrInstructionAllocaGen *instruction = fn->alloca_gen_list.at(alloca_i);
IrInstGenAlloca *instruction = fn->alloca_gen_list.at(alloca_i);
instruction->field_index = SIZE_MAX;
ZigType *ptr_type = instruction->base.value->type;
assert(ptr_type->id == ZigTypeIdPointer);
ZigType *child_type = ptr_type->data.pointer.child_type;
if (!type_has_bits(child_type))
continue;
if (instruction->base.ref_count == 0)
if (instruction->base.base.ref_count == 0)
continue;
if (instruction->base.value->special != ConstValSpecialRuntime) {
if (const_ptr_pointee(nullptr, g, instruction->base.value, nullptr)->special !=
@ -6407,7 +6435,7 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {
}
frame_type->data.frame.resolve_loop_type = child_type;
frame_type->data.frame.resolve_loop_src_node = instruction->base.source_node;
frame_type->data.frame.resolve_loop_src_node = instruction->base.base.source_node;
if ((err = type_resolve(g, child_type, ResolveStatusSizeKnown))) {
return err;
}
@ -6421,7 +6449,7 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {
instruction->field_index = fields.length;
src_assert(child_type->id != ZigTypeIdPointer || child_type->data.pointer.inferred_struct_field == nullptr,
instruction->base.source_node);
instruction->base.base.source_node);
fields.append({name, child_type, instruction->align});
}
@ -6453,7 +6481,21 @@ static Error resolve_pointer_zero_bits(CodeGen *g, ZigType *ty) {
}
ty->data.pointer.resolve_loop_flag_zero_bits = true;
ZigType *elem_type = ty->data.pointer.child_type;
ZigType *elem_type;
InferredStructField *isf = ty->data.pointer.inferred_struct_field;
if (isf != nullptr) {
TypeStructField *field = find_struct_type_field(isf->inferred_struct_type, isf->field_name);
assert(field != nullptr);
if (field->is_comptime) {
ty->abi_size = 0;
ty->size_in_bits = 0;
ty->abi_align = 0;
return ErrorNone;
}
elem_type = field->type_entry;
} else {
elem_type = ty->data.pointer.child_type;
}
bool has_bits;
if ((err = type_has_bits2(g, elem_type, &has_bits)))
@ -6554,8 +6596,10 @@ bool ir_get_var_is_comptime(ZigVar *var) {
// As an optimization, is_comptime values which are constant are allowed
// to be omitted from analysis. In this case, there is no child instruction
// and we simply look at the unanalyzed const parent instruction.
assert(var->is_comptime->value->type->id == ZigTypeIdBool);
var->is_comptime_memoized_value = var->is_comptime->value->data.x_bool;
assert(var->is_comptime->id == IrInstSrcIdConst);
IrInstSrcConst *const_inst = reinterpret_cast<IrInstSrcConst *>(var->is_comptime);
assert(const_inst->value->type->id == ZigTypeIdBool);
var->is_comptime_memoized_value = const_inst->value->data.x_bool;
var->is_comptime = nullptr;
return var->is_comptime_memoized_value;
}
@ -6874,6 +6918,7 @@ static void render_const_val_array(CodeGen *g, Buf *buf, Buf *type_name, ZigValu
}
case ConstArraySpecialNone: {
ZigValue *base = &array->data.s_none.elements[start];
assert(base != nullptr);
assert(start + len <= const_val->type->data.array.len);
buf_appendf(buf, "%s{", buf_ptr(type_name));
@ -6889,6 +6934,10 @@ static void render_const_val_array(CodeGen *g, Buf *buf, Buf *type_name, ZigValu
}
void render_const_value(CodeGen *g, Buf *buf, ZigValue *const_val) {
if (const_val == nullptr) {
buf_appendf(buf, "(invalid nullptr value)");
return;
}
switch (const_val->special) {
case ConstValSpecialRuntime:
buf_appendf(buf, "(runtime value)");
@ -9193,21 +9242,6 @@ void src_assert(bool ok, AstNode *source_node) {
stage2_panic(msg, strlen(msg));
}
IrInstruction *ir_create_alloca(CodeGen *g, Scope *scope, AstNode *source_node, ZigFn *fn,
ZigType *var_type, const char *name_hint)
{
IrInstructionAllocaGen *alloca_gen = allocate<IrInstructionAllocaGen>(1);
alloca_gen->base.id = IrInstructionIdAllocaGen;
alloca_gen->base.source_node = source_node;
alloca_gen->base.scope = scope;
alloca_gen->base.value = allocate<ZigValue>(1, "ZigValue");
alloca_gen->base.value->type = get_pointer_to_type(g, var_type, false);
alloca_gen->base.ref_count = 1;
alloca_gen->name_hint = name_hint;
fn->alloca_gen_list.append(alloca_gen);
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)
{
@ -9268,8 +9302,17 @@ Error analyze_import(CodeGen *g, ZigType *source_import, Buf *import_target_str,
}
void IrExecutable::src() {
IrExecutable *it;
void IrExecutableSrc::src() {
if (this->source_node != nullptr) {
this->source_node->src();
}
if (this->parent_exec != nullptr) {
this->parent_exec->src();
}
}
void IrExecutableGen::src() {
IrExecutableGen *it;
for (it = this; it != nullptr && it->source_node != nullptr; it = it->parent_exec) {
it->source_node->src();
}
@ -9300,10 +9343,13 @@ bool type_has_optional_repr(ZigType *ty) {
}
void copy_const_val(ZigValue *dest, ZigValue *src) {
uint32_t prev_align = dest->llvm_align;
ConstParent prev_parent = dest->parent;
memcpy(dest, src, sizeof(ZigValue));
dest->llvm_align = prev_align;
if (src->special != ConstValSpecialStatic)
return;
dest->parent.id = ConstParentIdNone;
dest->parent = prev_parent;
if (dest->type->id == ZigTypeIdStruct) {
dest->data.x_struct.fields = alloc_const_vals_ptrs(dest->type->data.structure.src_field_count);
for (size_t i = 0; i < dest->type->data.structure.src_field_count; i += 1) {
@ -9312,6 +9358,16 @@ void copy_const_val(ZigValue *dest, ZigValue *src) {
dest->data.x_struct.fields[i]->parent.data.p_struct.struct_val = dest;
dest->data.x_struct.fields[i]->parent.data.p_struct.field_index = i;
}
} else if (dest->type->id == ZigTypeIdArray) {
if (dest->data.x_array.special == ConstArraySpecialNone) {
dest->data.x_array.data.s_none.elements = create_const_vals(dest->type->data.array.len);
for (uint64_t i = 0; i < dest->type->data.array.len; i += 1) {
copy_const_val(&dest->data.x_array.data.s_none.elements[i], &src->data.x_array.data.s_none.elements[i]);
dest->data.x_array.data.s_none.elements[i].parent.id = ConstParentIdArray;
dest->data.x_array.data.s_none.elements[i].parent.data.p_array.array_val = dest;
dest->data.x_array.data.s_none.elements[i].parent.data.p_array.elem_index = i;
}
}
} else if (type_has_optional_repr(dest->type) && dest->data.x_optional != nullptr) {
dest->data.x_optional = create_const_vals(1);
copy_const_val(dest->data.x_optional, src->data.x_optional);
@ -9357,3 +9413,206 @@ bool type_is_numeric(ZigType *ty) {
}
zig_unreachable();
}
static void dump_value_indent(ZigValue *val, int indent) {
for (int i = 0; i < indent; i += 1) {
fprintf(stderr, " ");
}
fprintf(stderr, "Value@%p(", val);
if (val->type != nullptr) {
fprintf(stderr, "%s)", buf_ptr(&val->type->name));
} else {
fprintf(stderr, "type=nullptr)");
}
switch (val->special) {
case ConstValSpecialUndef:
fprintf(stderr, "[undefined]\n");
return;
case ConstValSpecialLazy:
fprintf(stderr, "[lazy]\n");
return;
case ConstValSpecialRuntime:
fprintf(stderr, "[runtime]\n");
return;
case ConstValSpecialStatic:
break;
}
if (val->type == nullptr)
return;
switch (val->type->id) {
case ZigTypeIdInvalid:
fprintf(stderr, "<invalid>\n");
return;
case ZigTypeIdUnreachable:
fprintf(stderr, "<unreachable>\n");
return;
case ZigTypeIdUndefined:
fprintf(stderr, "<undefined>\n");
return;
case ZigTypeIdVoid:
fprintf(stderr, "<{}>\n");
return;
case ZigTypeIdMetaType:
fprintf(stderr, "<%s>\n", buf_ptr(&val->data.x_type->name));
return;
case ZigTypeIdBool:
fprintf(stderr, "<%s>\n", val->data.x_bool ? "true" : "false");
return;
case ZigTypeIdComptimeInt:
case ZigTypeIdInt: {
Buf *tmp_buf = buf_alloc();
bigint_append_buf(tmp_buf, &val->data.x_bigint, 10);
fprintf(stderr, "<%s>\n", buf_ptr(tmp_buf));
buf_destroy(tmp_buf);
return;
}
case ZigTypeIdComptimeFloat:
case ZigTypeIdFloat:
fprintf(stderr, "<TODO dump number>\n");
return;
case ZigTypeIdStruct:
fprintf(stderr, "<struct\n");
for (size_t i = 0; i < val->type->data.structure.src_field_count; i += 1) {
for (int j = 0; j < indent; j += 1) {
fprintf(stderr, " ");
}
fprintf(stderr, "%s: ", buf_ptr(val->type->data.structure.fields[i]->name));
if (val->data.x_struct.fields == nullptr) {
fprintf(stderr, "<null>\n");
} else {
dump_value_indent(val->data.x_struct.fields[i], 1);
}
}
for (int i = 0; i < indent; i += 1) {
fprintf(stderr, " ");
}
fprintf(stderr, ">\n");
return;
case ZigTypeIdOptional:
fprintf(stderr, "<\n");
dump_value_indent(val->data.x_optional, indent + 1);
for (int i = 0; i < indent; i += 1) {
fprintf(stderr, " ");
}
fprintf(stderr, ">\n");
return;
case ZigTypeIdErrorUnion:
if (val->data.x_err_union.payload != nullptr) {
fprintf(stderr, "<\n");
dump_value_indent(val->data.x_err_union.payload, indent + 1);
} else {
fprintf(stderr, "<\n");
dump_value_indent(val->data.x_err_union.error_set, 0);
}
for (int i = 0; i < indent; i += 1) {
fprintf(stderr, " ");
}
fprintf(stderr, ">\n");
return;
case ZigTypeIdPointer:
switch (val->data.x_ptr.special) {
case ConstPtrSpecialInvalid:
fprintf(stderr, "<!invalid ptr!>\n");
return;
case ConstPtrSpecialRef:
fprintf(stderr, "<ref\n");
dump_value_indent(val->data.x_ptr.data.ref.pointee, indent + 1);
break;
case ConstPtrSpecialBaseStruct: {
ZigValue *struct_val = val->data.x_ptr.data.base_struct.struct_val;
size_t field_index = val->data.x_ptr.data.base_struct.field_index;
fprintf(stderr, "<struct %p field %zu\n", struct_val, field_index);
if (struct_val != nullptr) {
ZigValue *field_val = struct_val->data.x_struct.fields[field_index];
if (field_val != nullptr) {
dump_value_indent(field_val, indent + 1);
} else {
for (int i = 0; i < indent; i += 1) {
fprintf(stderr, " ");
}
fprintf(stderr, "(invalid null field)\n");
}
}
break;
}
case ConstPtrSpecialBaseOptionalPayload: {
ZigValue *optional_val = val->data.x_ptr.data.base_optional_payload.optional_val;
fprintf(stderr, "<optional %p payload\n", optional_val);
if (optional_val != nullptr) {
dump_value_indent(optional_val, indent + 1);
}
break;
}
default:
fprintf(stderr, "TODO dump more pointer things\n");
}
for (int i = 0; i < indent; i += 1) {
fprintf(stderr, " ");
}
fprintf(stderr, ">\n");
return;
case ZigTypeIdVector:
case ZigTypeIdArray:
case ZigTypeIdNull:
case ZigTypeIdErrorSet:
case ZigTypeIdEnum:
case ZigTypeIdUnion:
case ZigTypeIdFn:
case ZigTypeIdBoundFn:
case ZigTypeIdOpaque:
case ZigTypeIdFnFrame:
case ZigTypeIdAnyFrame:
case ZigTypeIdEnumLiteral:
fprintf(stderr, "<TODO dump value>\n");
return;
}
zig_unreachable();
}
void ZigValue::dump() {
dump_value_indent(this, 0);
}
// float ops that take a single argument
//TODO Powi, Pow, minnum, maxnum, maximum, minimum, copysign, lround, llround, lrint, llrint
const char *float_op_to_name(BuiltinFnId op) {
switch (op) {
case BuiltinFnIdSqrt:
return "sqrt";
case BuiltinFnIdSin:
return "sin";
case BuiltinFnIdCos:
return "cos";
case BuiltinFnIdExp:
return "exp";
case BuiltinFnIdExp2:
return "exp2";
case BuiltinFnIdLog:
return "log";
case BuiltinFnIdLog10:
return "log10";
case BuiltinFnIdLog2:
return "log2";
case BuiltinFnIdFabs:
return "fabs";
case BuiltinFnIdFloor:
return "floor";
case BuiltinFnIdCeil:
return "ceil";
case BuiltinFnIdTrunc:
return "trunc";
case BuiltinFnIdNearbyInt:
return "nearbyint";
case BuiltinFnIdRound:
return "round";
default:
zig_unreachable();
}
}

View File

@ -120,7 +120,7 @@ ScopeLoop *create_loop_scope(CodeGen *g, AstNode *node, Scope *parent);
ScopeSuspend *create_suspend_scope(CodeGen *g, AstNode *node, Scope *parent);
ScopeFnDef *create_fndef_scope(CodeGen *g, AstNode *node, Scope *parent, ZigFn *fn_entry);
Scope *create_comptime_scope(CodeGen *g, AstNode *node, Scope *parent);
Scope *create_runtime_scope(CodeGen *g, AstNode *node, Scope *parent, IrInstruction *is_comptime);
Scope *create_runtime_scope(CodeGen *g, AstNode *node, Scope *parent, IrInstSrc *is_comptime);
Scope *create_typeof_scope(CodeGen *g, AstNode *node, Scope *parent);
ScopeExpr *create_expr_scope(CodeGen *g, AstNode *node, Scope *parent);
@ -271,8 +271,6 @@ ZigType *resolve_struct_field_type(CodeGen *g, TypeStructField *struct_field);
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);
ZigValue *get_the_one_possible_value(CodeGen *g, ZigType *type_entry);
@ -281,4 +279,5 @@ void copy_const_val(ZigValue *dest, ZigValue *src);
bool type_has_optional_repr(ZigType *ty);
bool is_opt_err_set(ZigType *ty);
bool type_is_numeric(ZigType *ty);
const char *float_op_to_name(BuiltinFnId op);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -58,6 +58,12 @@ const char *err_str(Error err) {
case ErrorNotLazy: return "not lazy";
case ErrorIsAsync: return "is async";
case ErrorImportOutsidePkgPath: return "import of file outside package path";
case ErrorUnknownCpu: return "unknown CPU";
case ErrorUnknownSubArchitecture: return "unknown sub-architecture";
case ErrorUnknownCpuFeature: return "unknown CPU feature";
case ErrorInvalidCpuFeatures: return "invalid CPU features";
case ErrorInvalidLlvmCpuFeaturesFormat: return "invalid LLVM CPU features format";
case ErrorUnknownApplicationBinaryInterface: return "unknown application binary interface";
}
return "(invalid error)";
}

14637
src/ir.cpp

File diff suppressed because it is too large Load Diff

View File

@ -10,33 +10,33 @@
#include "all_types.hpp"
enum IrPass {
IrPassSrc,
IrPassGen,
};
bool ir_gen(CodeGen *g, AstNode *node, Scope *scope, IrExecutable *ir_executable);
bool ir_gen(CodeGen *g, AstNode *node, Scope *scope, IrExecutableSrc *ir_executable);
bool ir_gen_fn(CodeGen *g, ZigFn *fn_entry);
ZigValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node,
ZigType *expected_type, size_t *backward_branch_count, size_t *backward_branch_quota,
IrInstGen *ir_create_alloca(CodeGen *g, Scope *scope, AstNode *source_node, ZigFn *fn,
ZigType *var_type, const char *name_hint);
Error ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node,
ZigValue *return_ptr, size_t *backward_branch_count, size_t *backward_branch_quota,
ZigFn *fn_entry, Buf *c_import_buf, AstNode *source_node, Buf *exec_name,
IrExecutable *parent_exec, AstNode *expected_type_source_node, UndefAllowed undef);
IrExecutableGen *parent_exec, AstNode *expected_type_source_node, UndefAllowed undef);
Error ir_resolve_lazy(CodeGen *codegen, AstNode *source_node, ZigValue *val);
ZigType *ir_analyze(CodeGen *g, IrExecutable *old_executable, IrExecutable *new_executable,
ZigType *expected_type, AstNode *expected_type_source_node);
ZigType *ir_analyze(CodeGen *g, IrExecutableSrc *old_executable, IrExecutableGen *new_executable,
ZigType *expected_type, AstNode *expected_type_source_node, ZigValue *return_ptr);
bool ir_has_side_effects(IrInstruction *instruction);
bool ir_inst_gen_has_side_effects(IrInstGen *inst);
bool ir_inst_src_has_side_effects(IrInstSrc *inst);
struct IrAnalyze;
ZigValue *const_ptr_pointee(IrAnalyze *ira, CodeGen *codegen, ZigValue *const_val,
AstNode *source_node);
const char *float_op_to_name(BuiltinFnId op);
// for debugging purposes
void dbg_ir_break(const char *src_file, uint32_t line);
void dbg_ir_clear(void);
void destroy_instruction_gen(IrInstGen *inst);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -12,11 +12,14 @@
#include <stdio.h>
void ir_print(CodeGen *codegen, FILE *f, IrExecutable *executable, int indent_size, IrPass pass);
void ir_print_instruction(CodeGen *codegen, FILE *f, IrInstruction *instruction, int indent_size, IrPass pass);
void ir_print_const_expr(CodeGen *codegen, FILE *f, ZigValue *value, int indent_size, IrPass pass);
void ir_print_basic_block(CodeGen *codegen, FILE *f, IrBasicBlock *bb, int indent_size, IrPass pass);
void ir_print_src(CodeGen *codegen, FILE *f, IrExecutableSrc *executable, int indent_size);
void ir_print_gen(CodeGen *codegen, FILE *f, IrExecutableGen *executable, int indent_size);
void ir_print_inst_src(CodeGen *codegen, FILE *f, IrInstSrc *inst, int indent_size);
void ir_print_inst_gen(CodeGen *codegen, FILE *f, IrInstGen *inst, int indent_size);
void ir_print_basic_block_src(CodeGen *codegen, FILE *f, IrBasicBlockSrc *bb, int indent_size);
void ir_print_basic_block_gen(CodeGen *codegen, FILE *f, IrBasicBlockGen *bb, int indent_size);
const char* ir_instruction_type_str(IrInstructionId id);
const char* ir_inst_src_type_str(IrInstSrcId id);
const char* ir_inst_gen_type_str(IrInstGenId id);
#endif

View File

@ -1502,6 +1502,19 @@ static Buf *build_a_raw(CodeGen *parent_gen, const char *aname, Buf *full_path,
new_link_lib->provided_explicitly = parent_gen->libc_link_lib->provided_explicitly;
}
// Override the inherited build mode parameter
if (!parent_gen->is_test_build) {
switch (parent_gen->build_mode) {
case BuildModeDebug:
case BuildModeFastRelease:
case BuildModeSafeRelease:
child_gen->build_mode = BuildModeFastRelease;
break;
case BuildModeSmallRelease:
break;
}
}
child_gen->function_sections = true;
child_gen->want_stack_check = WantStackCheckDisabled;

View File

@ -93,6 +93,7 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) {
" --verbose-llvm-ir enable compiler debug output for LLVM IR\n"
" --verbose-cimport enable compiler debug output for C imports\n"
" --verbose-cc enable compiler debug output for C compilation\n"
" --verbose-llvm-cpu-features enable compiler debug output for LLVM CPU features\n"
" -dirafter [dir] add directory to AFTER include search path\n"
" -isystem [dir] add directory to SYSTEM include search path\n"
" -I[dir] add directory to include search path\n"
@ -100,6 +101,11 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) {
" --override-lib-dir [arg] override path to Zig lib directory\n"
" -ffunction-sections places each function in a separate section\n"
" -D[macro]=[value] define C [macro] to [value] (1 if [value] omitted)\n"
" -target-cpu [cpu] target one specific CPU by name\n"
" -target-feature [features] specify the set of CPU features to target\n"
" -code-model [default|tiny| set target code model\n"
" small|kernel|\n"
" medium|large]\n"
"\n"
"Link Options:\n"
" --bundle-compiler-rt for static libraries, include compiler-rt symbols\n"
@ -141,100 +147,18 @@ static int print_libc_usage(const char *arg0, FILE *file, int return_code) {
"You can save this into a file and then edit the paths to create a cross\n"
"compilation libc kit. Then you can pass `--libc [file]` for Zig to use it.\n"
"\n"
"When compiling natively and no `--libc` argument provided, Zig automatically\n"
"creates zig-cache/native_libc.txt so that it does not have to detect libc\n"
"on every invocation. You can remove this file to have Zig re-detect the\n"
"native libc.\n"
"When compiling natively and no `--libc` argument provided, Zig will create\n"
"`%s/native_libc.txt`\n"
"so that it does not have to detect libc on every invocation. You can remove\n"
"this file to have Zig re-detect the native libc.\n"
"\n\n"
"Usage: %s libc [file]\n"
"\n"
"Parse a libc installation text file and validate it.\n"
, arg0, arg0);
, arg0, buf_ptr(get_global_cache_dir()), arg0);
return return_code;
}
static bool arch_available_in_llvm(ZigLLVM_ArchType arch) {
LLVMTargetRef target_ref;
char *err_msg = nullptr;
char triple_string[128];
sprintf(triple_string, "%s-unknown-unknown-unknown", ZigLLVMGetArchTypeName(arch));
return !LLVMGetTargetFromTriple(triple_string, &target_ref, &err_msg);
}
static int print_target_list(FILE *f) {
ZigTarget native;
get_native_target(&native);
fprintf(f, "Architectures:\n");
size_t arch_count = target_arch_count();
for (size_t arch_i = 0; arch_i < arch_count; arch_i += 1) {
ZigLLVM_ArchType arch = target_arch_enum(arch_i);
if (!arch_available_in_llvm(arch))
continue;
const char *arch_name = target_arch_name(arch);
SubArchList sub_arch_list = target_subarch_list(arch);
size_t sub_count = target_subarch_count(sub_arch_list);
const char *arch_native_str = (native.arch == arch) ? " (native)" : "";
fprintf(f, " %s%s\n", arch_name, arch_native_str);
for (size_t sub_i = 0; sub_i < sub_count; sub_i += 1) {
ZigLLVM_SubArchType sub = target_subarch_enum(sub_arch_list, sub_i);
const char *sub_name = target_subarch_name(sub);
const char *sub_native_str = (native.arch == arch && native.sub_arch == sub) ? " (native)" : "";
fprintf(f, " %s%s\n", sub_name, sub_native_str);
}
}
fprintf(f, "\nOperating Systems:\n");
size_t os_count = target_os_count();
for (size_t i = 0; i < os_count; i += 1) {
Os os_type = target_os_enum(i);
const char *native_str = (native.os == os_type) ? " (native)" : "";
fprintf(f, " %s%s\n", target_os_name(os_type), native_str);
}
fprintf(f, "\nC ABIs:\n");
size_t abi_count = target_abi_count();
for (size_t i = 0; i < abi_count; i += 1) {
ZigLLVM_EnvironmentType abi = target_abi_enum(i);
const char *native_str = (native.abi == abi) ? " (native)" : "";
fprintf(f, " %s%s\n", target_abi_name(abi), native_str);
}
fprintf(f, "\nAvailable libcs:\n");
size_t libc_count = target_libc_count();
for (size_t i = 0; i < libc_count; i += 1) {
ZigTarget libc_target;
target_libc_enum(i, &libc_target);
bool is_native = native.arch == libc_target.arch &&
native.os == libc_target.os &&
native.abi == libc_target.abi;
const char *native_str = is_native ? " (native)" : "";
fprintf(f, " %s-%s-%s%s\n", target_arch_name(libc_target.arch),
target_os_name(libc_target.os), target_abi_name(libc_target.abi), native_str);
}
fprintf(f, "\nAvailable glibc versions:\n");
ZigGLibCAbi *glibc_abi;
Error err;
if ((err = glibc_load_metadata(&glibc_abi, get_zig_lib_dir(), true))) {
return EXIT_FAILURE;
}
for (size_t i = 0; i < glibc_abi->all_versions.length; i += 1) {
ZigGLibCVersion *this_ver = &glibc_abi->all_versions.at(i);
bool is_native = native.glibc_version != nullptr &&
native.glibc_version->major == this_ver->major &&
native.glibc_version->minor == this_ver->minor &&
native.glibc_version->patch == this_ver->patch;
const char *native_str = is_native ? " (native)" : "";
if (this_ver->patch == 0) {
fprintf(f, " %d.%d%s\n", this_ver->major, this_ver->minor, native_str);
} else {
fprintf(f, " %d.%d.%d%s\n", this_ver->major, this_ver->minor, this_ver->patch, native_str);
}
}
return EXIT_SUCCESS;
}
enum Cmd {
CmdNone,
CmdBuild,
@ -478,6 +402,7 @@ int main(int argc, char **argv) {
bool verbose_llvm_ir = false;
bool verbose_cimport = false;
bool verbose_cc = false;
bool verbose_llvm_cpu_features = false;
bool link_eh_frame_hdr = false;
ErrColor color = ErrColorAuto;
CacheOpt enable_cache = CacheOptAuto;
@ -528,6 +453,9 @@ int main(int argc, char **argv) {
WantStackCheck want_stack_check = WantStackCheckAuto;
WantCSanitize want_sanitize_c = WantCSanitizeAuto;
bool function_sections = false;
const char *cpu = nullptr;
const char *features = nullptr;
CodeModel code_model = CodeModelDefault;
ZigList<const char *> llvm_argv = {0};
llvm_argv.append("zig (LLVM option parsing)");
@ -692,6 +620,8 @@ int main(int argc, char **argv) {
verbose_cimport = true;
} else if (strcmp(arg, "--verbose-cc") == 0) {
verbose_cc = true;
} else if (strcmp(arg, "--verbose-llvm-cpu-features") == 0) {
verbose_llvm_cpu_features = true;
} else if (strcmp(arg, "-rdynamic") == 0) {
rdynamic = true;
} else if (strcmp(arg, "--each-lib-rpath") == 0) {
@ -842,6 +772,23 @@ int main(int argc, char **argv) {
clang_argv.append(argv[i]);
llvm_argv.append(argv[i]);
} else if (strcmp(arg, "-code-model") == 0) {
if (strcmp(argv[i], "default") == 0) {
code_model = CodeModelDefault;
} else if (strcmp(argv[i], "tiny") == 0) {
code_model = CodeModelTiny;
} else if (strcmp(argv[i], "small") == 0) {
code_model = CodeModelSmall;
} else if (strcmp(argv[i], "kernel") == 0) {
code_model = CodeModelKernel;
} else if (strcmp(argv[i], "medium") == 0) {
code_model = CodeModelMedium;
} else if (strcmp(argv[i], "large") == 0) {
code_model = CodeModelLarge;
} else {
fprintf(stderr, "-code-model options are 'default', 'tiny', 'small', 'kernel', 'medium', or 'large'\n");
return print_error_usage(arg0);
}
} else if (strcmp(arg, "--override-lib-dir") == 0) {
override_lib_dir = buf_create_from_str(argv[i]);
} else if (strcmp(arg, "--main-pkg-path") == 0) {
@ -936,6 +883,10 @@ int main(int argc, char **argv) {
, argv[i]);
return EXIT_FAILURE;
}
} else if (strcmp(arg, "-target-cpu") == 0) {
cpu = argv[i];
} else if (strcmp(arg, "-target-feature") == 0) {
features = argv[i];
} else {
fprintf(stderr, "Invalid argument: %s\n", arg);
return print_error_usage(arg0);
@ -1051,15 +1002,22 @@ int main(int argc, char **argv) {
}
}
Buf zig_triple_buf = BUF_INIT;
target_triple_zig(&zig_triple_buf, &target);
const char *stage2_triple_arg = target.is_native ? nullptr : buf_ptr(&zig_triple_buf);
if ((err = stage2_cpu_features_parse(&target.cpu_features, stage2_triple_arg, cpu, features))) {
fprintf(stderr, "unable to initialize CPU features: %s\n", err_str(err));
return main_exit(root_progress_node, EXIT_FAILURE);
}
if (output_dir != nullptr && enable_cache == CacheOptOn) {
fprintf(stderr, "`--output-dir` is incompatible with --cache on.\n");
return print_error_usage(arg0);
}
if (target_requires_pic(&target, have_libc) && want_pic == WantPICDisabled) {
Buf triple_buf = BUF_INIT;
target_triple_zig(&triple_buf, &target);
fprintf(stderr, "`--disable-pic` is incompatible with target '%s'\n", buf_ptr(&triple_buf));
fprintf(stderr, "`--disable-pic` is incompatible with target '%s'\n", buf_ptr(&zig_triple_buf));
return print_error_usage(arg0);
}
@ -1226,12 +1184,15 @@ int main(int argc, char **argv) {
g->verbose_llvm_ir = verbose_llvm_ir;
g->verbose_cimport = verbose_cimport;
g->verbose_cc = verbose_cc;
g->verbose_llvm_cpu_features = verbose_llvm_cpu_features;
g->output_dir = output_dir;
g->disable_gen_h = disable_gen_h;
g->bundle_compiler_rt = bundle_compiler_rt;
codegen_set_errmsg_color(g, color);
g->system_linker_hack = system_linker_hack;
g->function_sections = function_sections;
g->code_model = code_model;
for (size_t i = 0; i < lib_dirs.length; i += 1) {
codegen_add_lib_dir(g, lib_dirs.at(i));
@ -1413,7 +1374,7 @@ int main(int argc, char **argv) {
return main_exit(root_progress_node, EXIT_SUCCESS);
}
case CmdTargets:
return print_target_list(stdout);
return stage2_cmd_targets(buf_ptr(&zig_triple_buf));
case CmdNone:
return print_full_usage(arg0, stderr, EXIT_FAILURE);
}

View File

@ -147,7 +147,7 @@ static void ast_invalid_token_error(ParseContext *pc, Token *token) {
}
static AstNode *ast_create_node_no_line_info(ParseContext *pc, NodeType type) {
AstNode *node = allocate<AstNode>(1);
AstNode *node = allocate<AstNode>(1, "AstNode");
node->type = type;
node->owner = pc->owner;
return node;

View File

@ -12,4 +12,21 @@ extern "C" {
#include "softfloat.h"
}
static inline float16_t zig_double_to_f16(double x) {
float64_t y;
static_assert(sizeof(x) == sizeof(y), "");
memcpy(&y, &x, sizeof(x));
return f64_to_f16(y);
}
// Return value is safe to coerce to float even when |x| is NaN or Infinity.
static inline double zig_f16_to_double(float16_t x) {
float64_t y = f16_to_f64(x);
double z;
static_assert(sizeof(y) == sizeof(z), "");
memcpy(&z, &y, sizeof(y));
return z;
}
#endif

View File

@ -58,9 +58,6 @@ static const ZigLLVM_SubArchType subarch_list_arm64[] = {
ZigLLVM_ARMSubArch_v8_2a,
ZigLLVM_ARMSubArch_v8_1a,
ZigLLVM_ARMSubArch_v8,
ZigLLVM_ARMSubArch_v8r,
ZigLLVM_ARMSubArch_v8m_baseline,
ZigLLVM_ARMSubArch_v8m_mainline,
};
static const ZigLLVM_SubArchType subarch_list_kalimba[] = {
@ -693,7 +690,7 @@ const char *target_subarch_name(ZigLLVM_SubArchType subarch) {
case ZigLLVM_ARMSubArch_v8_1a:
return "v8_1a";
case ZigLLVM_ARMSubArch_v8:
return "v8";
return "v8a";
case ZigLLVM_ARMSubArch_v8r:
return "v8r";
case ZigLLVM_ARMSubArch_v8m_baseline:
@ -703,7 +700,7 @@ const char *target_subarch_name(ZigLLVM_SubArchType subarch) {
case ZigLLVM_ARMSubArch_v8_1m_mainline:
return "v8_1m_mainline";
case ZigLLVM_ARMSubArch_v7:
return "v7";
return "v7a";
case ZigLLVM_ARMSubArch_v7em:
return "v7em";
case ZigLLVM_ARMSubArch_v7m:
@ -846,10 +843,10 @@ void init_all_targets(void) {
void target_triple_zig(Buf *triple, const ZigTarget *target) {
buf_resize(triple, 0);
buf_appendf(triple, "%s%s-%s-%s",
ZigLLVMGetArchTypeName(target->arch),
ZigLLVMGetSubArchTypeName(target->sub_arch),
ZigLLVMGetOSTypeName(get_llvm_os_type(target->os)),
ZigLLVMGetEnvironmentTypeName(target->abi));
target_arch_name(target->arch),
target_subarch_name(target->sub_arch),
target_os_name(target->os),
target_abi_name(target->abi));
}
void target_triple_llvm(Buf *triple, const ZigTarget *target) {

View File

@ -92,6 +92,7 @@ struct ZigTarget {
Os os;
ZigLLVM_EnvironmentType abi;
ZigGLibCVersion *glibc_version; // null means default
Stage2CpuFeatures *cpu_features;
bool is_native;
};

View File

@ -2,7 +2,8 @@
// src-self-hosted/stage1.zig
#include "userland.h"
#include "ast_render.hpp"
#include "util.hpp"
#include "zig_llvm.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -88,3 +89,58 @@ void stage2_progress_end(Stage2ProgressNode *node) {}
void stage2_progress_complete_one(Stage2ProgressNode *node) {}
void stage2_progress_disable_tty(Stage2Progress *progress) {}
void stage2_progress_update_node(Stage2ProgressNode *node, size_t completed_count, size_t estimated_total_items){}
struct Stage2CpuFeatures {
const char *llvm_cpu_name;
const char *llvm_cpu_features;
const char *builtin_str;
const char *cache_hash;
};
Error stage2_cpu_features_parse(struct Stage2CpuFeatures **out, const char *zig_triple,
const char *cpu_name, const char *cpu_features)
{
if (zig_triple == nullptr) {
Stage2CpuFeatures *result = allocate<Stage2CpuFeatures>(1, "Stage2CpuFeatures");
result->llvm_cpu_name = ZigLLVMGetHostCPUName();
result->llvm_cpu_features = ZigLLVMGetNativeFeatures();
result->builtin_str = "arch.getBaselineCpuFeatures();\n";
result->cache_hash = "native\n\n";
*out = result;
return ErrorNone;
}
if (cpu_name == nullptr && cpu_features == nullptr) {
Stage2CpuFeatures *result = allocate<Stage2CpuFeatures>(1, "Stage2CpuFeatures");
result->builtin_str = "arch.getBaselineCpuFeatures();\n";
result->cache_hash = "\n\n";
*out = result;
return ErrorNone;
}
const char *msg = "stage0 called stage2_cpu_features_parse with non-null cpu name or features";
stage2_panic(msg, strlen(msg));
}
void stage2_cpu_features_get_cache_hash(const Stage2CpuFeatures *cpu_features,
const char **ptr, size_t *len)
{
*ptr = cpu_features->cache_hash;
*len = strlen(cpu_features->cache_hash);
}
const char *stage2_cpu_features_get_llvm_cpu(const Stage2CpuFeatures *cpu_features) {
return cpu_features->llvm_cpu_name;
}
const char *stage2_cpu_features_get_llvm_features(const Stage2CpuFeatures *cpu_features) {
return cpu_features->llvm_cpu_features;
}
void stage2_cpu_features_get_builtin_str(const Stage2CpuFeatures *cpu_features,
const char **ptr, size_t *len)
{
*ptr = cpu_features->builtin_str;
*len = strlen(cpu_features->builtin_str);
}
int stage2_cmd_targets(const char *zig_triple) {
const char *msg = "stage0 called stage2_cmd_targets";
stage2_panic(msg, strlen(msg));
}

View File

@ -78,6 +78,12 @@ enum Error {
ErrorNotLazy,
ErrorIsAsync,
ErrorImportOutsidePkgPath,
ErrorUnknownCpu,
ErrorUnknownSubArchitecture,
ErrorUnknownCpuFeature,
ErrorInvalidCpuFeatures,
ErrorInvalidLlvmCpuFeaturesFormat,
ErrorUnknownApplicationBinaryInterface,
};
// ABI warning
@ -174,4 +180,29 @@ ZIG_EXTERN_C void stage2_progress_complete_one(Stage2ProgressNode *node);
ZIG_EXTERN_C void stage2_progress_update_node(Stage2ProgressNode *node,
size_t completed_count, size_t estimated_total_items);
// ABI warning
struct Stage2CpuFeatures;
// ABI warning
ZIG_EXTERN_C Error stage2_cpu_features_parse(struct Stage2CpuFeatures **result,
const char *zig_triple, const char *cpu_name, const char *cpu_features);
// ABI warning
ZIG_EXTERN_C const char *stage2_cpu_features_get_llvm_cpu(const struct Stage2CpuFeatures *cpu_features);
// ABI warning
ZIG_EXTERN_C const char *stage2_cpu_features_get_llvm_features(const struct Stage2CpuFeatures *cpu_features);
// ABI warning
ZIG_EXTERN_C void stage2_cpu_features_get_builtin_str(const struct Stage2CpuFeatures *cpu_features,
const char **ptr, size_t *len);
// ABI warning
ZIG_EXTERN_C void stage2_cpu_features_get_cache_hash(const struct Stage2CpuFeatures *cpu_features,
const char **ptr, size_t *len);
// ABI warning
ZIG_EXTERN_C int stage2_cmd_targets(const char *zig_triple);
#endif

View File

@ -38,6 +38,8 @@
#if defined(__MINGW32__) || defined(__MINGW64__)
#define BREAKPOINT __debugbreak()
#elif defined(__i386__) || defined(__x86_64__)
#define BREAKPOINT __asm__ volatile("int $0x03");
#elif defined(__clang__)
#define BREAKPOINT __builtin_debugtrap()
#elif defined(__GNUC__)
@ -49,8 +51,6 @@
#endif
#include "softfloat.hpp"
ATTRIBUTE_COLD
ATTRIBUTE_NORETURN
ATTRIBUTE_PRINTF(1, 2)
@ -244,23 +244,6 @@ static inline uint8_t log2_u64(uint64_t x) {
return (63 - clzll(x));
}
static inline float16_t zig_double_to_f16(double x) {
float64_t y;
static_assert(sizeof(x) == sizeof(y), "");
memcpy(&y, &x, sizeof(x));
return f64_to_f16(y);
}
// Return value is safe to coerce to float even when |x| is NaN or Infinity.
static inline double zig_f16_to_double(float16_t x) {
float64_t y = f16_to_f64(x);
double z;
static_assert(sizeof(y) == sizeof(z), "");
memcpy(&z, &y, sizeof(y));
return z;
}
void zig_pretty_print_bytes(FILE *f, double n);
template<typename T>

View File

@ -1668,6 +1668,10 @@ unsigned ZigClangFunctionDecl_getAlignedAttribute(const struct ZigClangFunctionD
return 0;
}
ZigClangQualType ZigClangParmVarDecl_getOriginalType(const struct ZigClangParmVarDecl *self) {
return bitcast(reinterpret_cast<const clang::ParmVarDecl *>(self)->getOriginalType());
}
const ZigClangRecordDecl *ZigClangRecordDecl_getDefinition(const ZigClangRecordDecl *zig_record_decl) {
const clang::RecordDecl *record_decl = reinterpret_cast<const clang::RecordDecl *>(zig_record_decl);
const clang::RecordDecl *definition = record_decl->getDefinition();
@ -1920,6 +1924,11 @@ bool ZigClangType_isRecordType(const ZigClangType *self) {
return casted->isRecordType();
}
bool ZigClangType_isConstantArrayType(const ZigClangType *self) {
auto casted = reinterpret_cast<const clang::Type *>(self);
return casted->isConstantArrayType();
}
const char *ZigClangType_getTypeClassName(const ZigClangType *self) {
auto casted = reinterpret_cast<const clang::Type *>(self);
return casted->getTypeClassName();

View File

@ -886,6 +886,8 @@ ZIG_EXTERN_C const char* ZigClangVarDecl_getSectionAttribute(const struct ZigCla
ZIG_EXTERN_C unsigned ZigClangVarDecl_getAlignedAttribute(const struct ZigClangVarDecl *self, const ZigClangASTContext* ctx);
ZIG_EXTERN_C unsigned ZigClangFunctionDecl_getAlignedAttribute(const struct ZigClangFunctionDecl *self, const ZigClangASTContext* ctx);
ZIG_EXTERN_C struct ZigClangQualType ZigClangParmVarDecl_getOriginalType(const struct ZigClangParmVarDecl *self);
ZIG_EXTERN_C bool ZigClangRecordDecl_getPackedAttribute(const struct ZigClangRecordDecl *);
ZIG_EXTERN_C const struct ZigClangRecordDecl *ZigClangRecordDecl_getDefinition(const struct ZigClangRecordDecl *);
ZIG_EXTERN_C const struct ZigClangEnumDecl *ZigClangEnumDecl_getDefinition(const struct ZigClangEnumDecl *);
@ -965,6 +967,7 @@ ZIG_EXTERN_C bool ZigClangType_isBooleanType(const struct ZigClangType *self);
ZIG_EXTERN_C bool ZigClangType_isVoidType(const struct ZigClangType *self);
ZIG_EXTERN_C bool ZigClangType_isArrayType(const struct ZigClangType *self);
ZIG_EXTERN_C bool ZigClangType_isRecordType(const struct ZigClangType *self);
ZIG_EXTERN_C bool ZigClangType_isConstantArrayType(const ZigClangType *self);
ZIG_EXTERN_C const char *ZigClangType_getTypeClassName(const struct ZigClangType *self);
ZIG_EXTERN_C const struct ZigClangArrayType *ZigClangType_getAsArrayTypeUnsafe(const struct ZigClangType *self);
ZIG_EXTERN_C const ZigClangRecordType *ZigClangType_getAsRecordType(const ZigClangType *self);

View File

@ -824,7 +824,7 @@ const char *ZigLLVMGetSubArchTypeName(ZigLLVM_SubArchType sub_arch) {
case ZigLLVM_ARMSubArch_v8_1a:
return "v8.1a";
case ZigLLVM_ARMSubArch_v8:
return "v8";
return "v8a";
case ZigLLVM_ARMSubArch_v8r:
return "v8r";
case ZigLLVM_ARMSubArch_v8m_baseline:
@ -834,7 +834,7 @@ const char *ZigLLVMGetSubArchTypeName(ZigLLVM_SubArchType sub_arch) {
case ZigLLVM_ARMSubArch_v8_1m_mainline:
return "v8.1m.main";
case ZigLLVM_ARMSubArch_v7:
return "v7";
return "v7a";
case ZigLLVM_ARMSubArch_v7em:
return "v7em";
case ZigLLVM_ARMSubArch_v7m:

View File

@ -1,7 +1,14 @@
const tests = @import("tests.zig");
const builtin = @import("builtin");
const Target = @import("std").Target;
pub fn addCases(cases: *tests.CompileErrorContext) void {
cases.addTest("dependency loop in top-level decl with @TypeInfo",
\\export const foo = @typeInfo(@This());
, &[_][]const u8{
"tmp.zig:1:20: error: dependency loop detected",
});
cases.addTest("non-exhaustive enums",
\\const A = enum {
\\ a,
@ -272,9 +279,10 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
, &[_][]const u8{
"tmp.zig:3:5: error: target arch 'wasm32' does not support calling with a new stack",
});
tc.target = tests.Target{
.Cross = tests.CrossTarget{
tc.target = Target{
.Cross = .{
.arch = .wasm32,
.cpu_features = Target.Arch.wasm32.getBaselineCpuFeatures(),
.os = .wasi,
.abi = .none,
},
@ -673,9 +681,10 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
, &[_][]const u8{
"tmp.zig:2:14: error: could not find 'foo' in the inputs or outputs",
});
tc.target = tests.Target{
.Cross = tests.CrossTarget{
tc.target = Target{
.Cross = .{
.arch = .x86_64,
.cpu_features = Target.Arch.x86_64.getBaselineCpuFeatures(),
.os = .linux,
.abi = .gnu,
},
@ -1649,7 +1658,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
cases.addTest("return invalid type from test",
\\test "example" { return 1; }
, &[_][]const u8{
"tmp.zig:1:25: error: integer value 1 cannot be coerced to type 'void'",
"tmp.zig:1:25: error: expected type 'void', found 'comptime_int'",
});
cases.add("threadlocal qualifier on const",
@ -2478,7 +2487,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\ var rule_set = try Foo.init();
\\}
, &[_][]const u8{
"tmp.zig:2:10: error: expected type 'i32', found 'type'",
"tmp.zig:2:19: error: expected type 'i32', found 'type'",
});
cases.add("slicing single-item pointer",
@ -3384,7 +3393,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\
\\fn b() void {}
, &[_][]const u8{
"tmp.zig:3:6: error: unreachable code",
"tmp.zig:3:5: error: unreachable code",
});
cases.add("bad import",
@ -4002,8 +4011,8 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\
\\export fn entry() usize { return @sizeOf(@TypeOf(Foo)); }
, &[_][]const u8{
"tmp.zig:5:25: error: unable to evaluate constant expression",
"tmp.zig:2:12: note: referenced here",
"tmp.zig:5:25: error: cannot store runtime value in compile time variable",
"tmp.zig:2:12: note: called from here",
});
cases.add("addition with non numbers",
@ -4643,7 +4652,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\fn something() anyerror!void { }
, &[_][]const u8{
"tmp.zig:2:5: error: expected type 'void', found 'anyerror'",
"tmp.zig:1:15: note: return type declared here",
});
cases.add("invalid pointer for var type",
@ -5734,7 +5742,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\ @export(entry, .{.name = "entry", .linkage = @as(u32, 1234) });
\\}
, &[_][]const u8{
"tmp.zig:3:50: error: expected type 'std.builtin.GlobalLinkage', found 'u32'",
"tmp.zig:3:59: error: expected type 'std.builtin.GlobalLinkage', found 'comptime_int'",
});
cases.add("struct with invalid field",

View File

@ -51,11 +51,15 @@ pub fn addCases(cases: *tests.StackTracesContext) void {
// debug
\\error: TheSkyIsFalling
\\source.zig:4:5: [address] in main (test)
\\ return error.TheSkyIsFalling;
\\ ^
\\
,
// release-safe
\\error: TheSkyIsFalling
\\source.zig:4:5: [address] in std.start.main (test)
\\ return error.TheSkyIsFalling;
\\ ^
\\
,
// release-fast
@ -74,13 +78,21 @@ pub fn addCases(cases: *tests.StackTracesContext) void {
// debug
\\error: TheSkyIsFalling
\\source.zig:4:5: [address] in foo (test)
\\ return error.TheSkyIsFalling;
\\ ^
\\source.zig:8:5: [address] in main (test)
\\ try foo();
\\ ^
\\
,
// release-safe
\\error: TheSkyIsFalling
\\source.zig:4:5: [address] in std.start.main (test)
\\ return error.TheSkyIsFalling;
\\ ^
\\source.zig:8:5: [address] in std.start.main (test)
\\ try foo();
\\ ^
\\
,
// release-fast
@ -99,17 +111,33 @@ pub fn addCases(cases: *tests.StackTracesContext) void {
// debug
\\error: TheSkyIsFalling
\\source.zig:12:5: [address] in make_error (test)
\\ return error.TheSkyIsFalling;
\\ ^
\\source.zig:8:5: [address] in bar (test)
\\ return make_error();
\\ ^
\\source.zig:4:5: [address] in foo (test)
\\ try bar();
\\ ^
\\source.zig:16:5: [address] in main (test)
\\ try foo();
\\ ^
\\
,
// release-safe
\\error: TheSkyIsFalling
\\source.zig:12:5: [address] in std.start.main (test)
\\ return error.TheSkyIsFalling;
\\ ^
\\source.zig:8:5: [address] in std.start.main (test)
\\ return make_error();
\\ ^
\\source.zig:4:5: [address] in std.start.main (test)
\\ try bar();
\\ ^
\\source.zig:16:5: [address] in std.start.main (test)
\\ try foo();
\\ ^
\\
,
// release-fast
@ -130,11 +158,15 @@ pub fn addCases(cases: *tests.StackTracesContext) void {
// debug
\\error: TheSkyIsFalling
\\source.zig:4:5: [address] in main (test)
\\ return error.TheSkyIsFalling;
\\ ^
\\
,
// release-safe
\\error: TheSkyIsFalling
\\source.zig:4:5: [address] in std.start.posixCallMainAndExit (test)
\\ return error.TheSkyIsFalling;
\\ ^
\\
,
// release-fast
@ -153,13 +185,21 @@ pub fn addCases(cases: *tests.StackTracesContext) void {
// debug
\\error: TheSkyIsFalling
\\source.zig:4:5: [address] in foo (test)
\\ return error.TheSkyIsFalling;
\\ ^
\\source.zig:8:5: [address] in main (test)
\\ try foo();
\\ ^
\\
,
// release-safe
\\error: TheSkyIsFalling
\\source.zig:4:5: [address] in std.start.posixCallMainAndExit (test)
\\ return error.TheSkyIsFalling;
\\ ^
\\source.zig:8:5: [address] in std.start.posixCallMainAndExit (test)
\\ try foo();
\\ ^
\\
,
// release-fast
@ -178,17 +218,33 @@ pub fn addCases(cases: *tests.StackTracesContext) void {
// debug
\\error: TheSkyIsFalling
\\source.zig:12:5: [address] in make_error (test)
\\ return error.TheSkyIsFalling;
\\ ^
\\source.zig:8:5: [address] in bar (test)
\\ return make_error();
\\ ^
\\source.zig:4:5: [address] in foo (test)
\\ try bar();
\\ ^
\\source.zig:16:5: [address] in main (test)
\\ try foo();
\\ ^
\\
,
// release-safe
\\error: TheSkyIsFalling
\\source.zig:12:5: [address] in std.start.posixCallMainAndExit (test)
\\ return error.TheSkyIsFalling;
\\ ^
\\source.zig:8:5: [address] in std.start.posixCallMainAndExit (test)
\\ return make_error();
\\ ^
\\source.zig:4:5: [address] in std.start.posixCallMainAndExit (test)
\\ try bar();
\\ ^
\\source.zig:16:5: [address] in std.start.posixCallMainAndExit (test)
\\ try foo();
\\ ^
\\
,
// release-fast
@ -209,11 +265,15 @@ pub fn addCases(cases: *tests.StackTracesContext) void {
// debug
\\error: TheSkyIsFalling
\\source.zig:4:5: [address] in _main.0 (test.o)
\\ return error.TheSkyIsFalling;
\\ ^
\\
,
// release-safe
\\error: TheSkyIsFalling
\\source.zig:4:5: [address] in _main (test.o)
\\ return error.TheSkyIsFalling;
\\ ^
\\
,
// release-fast
@ -232,13 +292,21 @@ pub fn addCases(cases: *tests.StackTracesContext) void {
// debug
\\error: TheSkyIsFalling
\\source.zig:4:5: [address] in _foo (test.o)
\\ return error.TheSkyIsFalling;
\\ ^
\\source.zig:8:5: [address] in _main.0 (test.o)
\\ try foo();
\\ ^
\\
,
// release-safe
\\error: TheSkyIsFalling
\\source.zig:4:5: [address] in _main (test.o)
\\ return error.TheSkyIsFalling;
\\ ^
\\source.zig:8:5: [address] in _main (test.o)
\\ try foo();
\\ ^
\\
,
// release-fast
@ -257,17 +325,33 @@ pub fn addCases(cases: *tests.StackTracesContext) void {
// debug
\\error: TheSkyIsFalling
\\source.zig:12:5: [address] in _make_error (test.o)
\\ return error.TheSkyIsFalling;
\\ ^
\\source.zig:8:5: [address] in _bar (test.o)
\\ return make_error();
\\ ^
\\source.zig:4:5: [address] in _foo (test.o)
\\ try bar();
\\ ^
\\source.zig:16:5: [address] in _main.0 (test.o)
\\ try foo();
\\ ^
\\
,
// release-safe
\\error: TheSkyIsFalling
\\source.zig:12:5: [address] in _main (test.o)
\\ return error.TheSkyIsFalling;
\\ ^
\\source.zig:8:5: [address] in _main (test.o)
\\ return make_error();
\\ ^
\\source.zig:4:5: [address] in _main (test.o)
\\ try bar();
\\ ^
\\source.zig:16:5: [address] in _main (test.o)
\\ try foo();
\\ ^
\\
,
// release-fast
@ -288,6 +372,8 @@ pub fn addCases(cases: *tests.StackTracesContext) void {
// debug
\\error: TheSkyIsFalling
\\source.zig:4:5: [address] in main (test.obj)
\\ return error.TheSkyIsFalling;
\\ ^
\\
,
// release-safe
@ -309,7 +395,11 @@ pub fn addCases(cases: *tests.StackTracesContext) void {
// debug
\\error: TheSkyIsFalling
\\source.zig:4:5: [address] in foo (test.obj)
\\ return error.TheSkyIsFalling;
\\ ^
\\source.zig:8:5: [address] in main (test.obj)
\\ try foo();
\\ ^
\\
,
// release-safe
@ -331,9 +421,17 @@ pub fn addCases(cases: *tests.StackTracesContext) void {
// debug
\\error: TheSkyIsFalling
\\source.zig:12:5: [address] in make_error (test.obj)
\\ return error.TheSkyIsFalling;
\\ ^
\\source.zig:8:5: [address] in bar (test.obj)
\\ return make_error();
\\ ^
\\source.zig:4:5: [address] in foo (test.obj)
\\ try bar();
\\ ^
\\source.zig:16:5: [address] in main (test.obj)
\\ try foo();
\\ ^
\\
,
// release-safe

View File

@ -1182,6 +1182,42 @@ test "suspend in for loop" {
S.doTheTest();
}
test "suspend in while loop" {
const S = struct {
var global_frame: ?anyframe = null;
fn doTheTest() void {
_ = async atest();
while (global_frame) |f| resume f;
}
fn atest() void {
expect(optional(6) == 6);
expect(errunion(6) == 6);
}
fn optional(stuff: ?u32) u32 {
global_frame = @frame();
defer global_frame = null;
while (stuff) |val| {
suspend;
return val;
}
return 0;
}
fn errunion(stuff: anyerror!u32) u32 {
global_frame = @frame();
defer global_frame = null;
while (stuff) |val| {
suspend;
return val;
} else |err| {
return 0;
}
}
};
S.doTheTest();
}
test "correctly spill when returning the error union result of another async fn" {
const S = struct {
var global_frame: anyframe = undefined;

View File

@ -167,3 +167,23 @@ test "nested bitcast" {
S.foo(42);
comptime S.foo(42);
}
test "bitcast passed as tuple element" {
const S = struct {
fn foo(args: var) void {
comptime expect(@TypeOf(args[0]) == f32);
expect(args[0] == 12.34);
}
};
S.foo(.{@bitCast(f32, @as(u32, 0x414570A4))});
}
test "triple level result location with bitcast sandwich passed as tuple element" {
const S = struct {
fn foo(args: var) void {
comptime expect(@TypeOf(args[0]) == f64);
expect(args[0] > 12.33 and args[0] < 12.35);
}
};
S.foo(.{@as(f64, @bitCast(f32, @as(u32, 0x414570A4)))});
}

View File

@ -804,3 +804,16 @@ test "comptime assign int to optional int" {
expectEqual(20, x.?);
}
}
test "return 0 from function that has u0 return type" {
const S = struct {
fn foo_zero() u0 {
return 0;
}
};
comptime {
if (S.foo_zero() != 0) {
@compileError("test failed");
}
}
}

View File

@ -36,7 +36,7 @@ fn testSqrt() void {
// expect(@sqrt(a) == 7);
//}
{
var v: @Vector(4, f32) = [_]f32{1.1, 2.2, 3.3, 4.4};
var v: @Vector(4, f32) = [_]f32{ 1.1, 2.2, 3.3, 4.4 };
var result = @sqrt(v);
expect(math.approxEq(f32, @sqrt(@as(f32, 1.1)), result[0], epsilon));
expect(math.approxEq(f32, @sqrt(@as(f32, 2.2)), result[1], epsilon));
@ -86,7 +86,7 @@ fn testSin() void {
expect(@sin(a) == 0);
}
{
var v: @Vector(4, f32) = [_]f32{1.1, 2.2, 3.3, 4.4};
var v: @Vector(4, f32) = [_]f32{ 1.1, 2.2, 3.3, 4.4 };
var result = @sin(v);
expect(math.approxEq(f32, @sin(@as(f32, 1.1)), result[0], epsilon));
expect(math.approxEq(f32, @sin(@as(f32, 2.2)), result[1], epsilon));
@ -116,7 +116,7 @@ fn testCos() void {
expect(@cos(a) == 1);
}
{
var v: @Vector(4, f32) = [_]f32{1.1, 2.2, 3.3, 4.4};
var v: @Vector(4, f32) = [_]f32{ 1.1, 2.2, 3.3, 4.4 };
var result = @cos(v);
expect(math.approxEq(f32, @cos(@as(f32, 1.1)), result[0], epsilon));
expect(math.approxEq(f32, @cos(@as(f32, 2.2)), result[1], epsilon));
@ -146,7 +146,7 @@ fn testExp() void {
expect(@exp(a) == 1);
}
{
var v: @Vector(4, f32) = [_]f32{1.1, 2.2, 0.3, 0.4};
var v: @Vector(4, f32) = [_]f32{ 1.1, 2.2, 0.3, 0.4 };
var result = @exp(v);
expect(math.approxEq(f32, @exp(@as(f32, 1.1)), result[0], epsilon));
expect(math.approxEq(f32, @exp(@as(f32, 2.2)), result[1], epsilon));
@ -176,7 +176,7 @@ fn testExp2() void {
expect(@exp2(a) == 4);
}
{
var v: @Vector(4, f32) = [_]f32{1.1, 2.2, 0.3, 0.4};
var v: @Vector(4, f32) = [_]f32{ 1.1, 2.2, 0.3, 0.4 };
var result = @exp2(v);
expect(math.approxEq(f32, @exp2(@as(f32, 1.1)), result[0], epsilon));
expect(math.approxEq(f32, @exp2(@as(f32, 2.2)), result[1], epsilon));
@ -208,7 +208,7 @@ fn testLog() void {
expect(@log(a) == 1 or @log(a) == @bitCast(f64, @as(u64, 0x3ff0000000000000)));
}
{
var v: @Vector(4, f32) = [_]f32{1.1, 2.2, 0.3, 0.4};
var v: @Vector(4, f32) = [_]f32{ 1.1, 2.2, 0.3, 0.4 };
var result = @log(v);
expect(math.approxEq(f32, @log(@as(f32, 1.1)), result[0], epsilon));
expect(math.approxEq(f32, @log(@as(f32, 2.2)), result[1], epsilon));
@ -238,7 +238,7 @@ fn testLog2() void {
expect(@log2(a) == 2);
}
{
var v: @Vector(4, f32) = [_]f32{1.1, 2.2, 0.3, 0.4};
var v: @Vector(4, f32) = [_]f32{ 1.1, 2.2, 0.3, 0.4 };
var result = @log2(v);
expect(math.approxEq(f32, @log2(@as(f32, 1.1)), result[0], epsilon));
expect(math.approxEq(f32, @log2(@as(f32, 2.2)), result[1], epsilon));
@ -268,7 +268,7 @@ fn testLog10() void {
expect(@log10(a) == 3);
}
{
var v: @Vector(4, f32) = [_]f32{1.1, 2.2, 0.3, 0.4};
var v: @Vector(4, f32) = [_]f32{ 1.1, 2.2, 0.3, 0.4 };
var result = @log10(v);
expect(math.approxEq(f32, @log10(@as(f32, 1.1)), result[0], epsilon));
expect(math.approxEq(f32, @log10(@as(f32, 2.2)), result[1], epsilon));
@ -304,7 +304,7 @@ fn testFabs() void {
expect(@fabs(b) == 2.5);
}
{
var v: @Vector(4, f32) = [_]f32{1.1, -2.2, 0.3, -0.4};
var v: @Vector(4, f32) = [_]f32{ 1.1, -2.2, 0.3, -0.4 };
var result = @fabs(v);
expect(math.approxEq(f32, @fabs(@as(f32, 1.1)), result[0], epsilon));
expect(math.approxEq(f32, @fabs(@as(f32, -2.2)), result[1], epsilon));
@ -334,7 +334,7 @@ fn testFloor() void {
expect(@floor(a) == 3);
}
{
var v: @Vector(4, f32) = [_]f32{1.1, -2.2, 0.3, -0.4};
var v: @Vector(4, f32) = [_]f32{ 1.1, -2.2, 0.3, -0.4 };
var result = @floor(v);
expect(math.approxEq(f32, @floor(@as(f32, 1.1)), result[0], epsilon));
expect(math.approxEq(f32, @floor(@as(f32, -2.2)), result[1], epsilon));
@ -364,7 +364,7 @@ fn testCeil() void {
expect(@ceil(a) == 4);
}
{
var v: @Vector(4, f32) = [_]f32{1.1, -2.2, 0.3, -0.4};
var v: @Vector(4, f32) = [_]f32{ 1.1, -2.2, 0.3, -0.4 };
var result = @ceil(v);
expect(math.approxEq(f32, @ceil(@as(f32, 1.1)), result[0], epsilon));
expect(math.approxEq(f32, @ceil(@as(f32, -2.2)), result[1], epsilon));
@ -394,7 +394,7 @@ fn testTrunc() void {
expect(@trunc(a) == -3);
}
{
var v: @Vector(4, f32) = [_]f32{1.1, -2.2, 0.3, -0.4};
var v: @Vector(4, f32) = [_]f32{ 1.1, -2.2, 0.3, -0.4 };
var result = @trunc(v);
expect(math.approxEq(f32, @trunc(@as(f32, 1.1)), result[0], epsilon));
expect(math.approxEq(f32, @trunc(@as(f32, -2.2)), result[1], epsilon));
@ -403,6 +403,36 @@ fn testTrunc() void {
}
}
test "floating point comparisons" {
testFloatComparisons();
comptime testFloatComparisons();
}
fn testFloatComparisons() void {
inline for ([_]type{ f16, f32, f64, f128 }) |ty| {
// No decimal part
{
const x: ty = 1.0;
expect(x == 1);
expect(x != 0);
expect(x > 0);
expect(x < 2);
expect(x >= 1);
expect(x <= 1);
}
// Non-zero decimal part
{
const x: ty = 1.5;
expect(x != 1);
expect(x != 2);
expect(x > 1);
expect(x < 2);
expect(x >= 1);
expect(x <= 2);
}
}
}
// TODO This is waiting on library support for the Windows build (not sure why the other's don't need it)
//test "@nearbyint" {
// comptime testNearbyInt();

View File

@ -72,7 +72,7 @@ test "const result loc, runtime if cond, else unreachable" {
var t = true;
const x = if (t) Num.Two else unreachable;
if (x != .Two) @compileError("bad");
expect(x == .Two);
}
test "if prongs cast to expected type instead of peer type resolution" {

View File

@ -529,6 +529,10 @@ test "comptime_int xor" {
}
test "f128" {
if (std.Target.current.isWindows()) {
// TODO https://github.com/ziglang/zig/issues/508
return error.SkipZigTest;
}
test_f128();
comptime test_f128();
}
@ -627,6 +631,10 @@ test "NaN comparison" {
// TODO: https://github.com/ziglang/zig/issues/3338
return error.SkipZigTest;
}
if (std.Target.current.isWindows()) {
// TODO https://github.com/ziglang/zig/issues/508
return error.SkipZigTest;
}
testNanEqNan(f16);
testNanEqNan(f32);
testNanEqNan(f64);

View File

@ -781,3 +781,16 @@ test "pointer to thread local array" {
std.mem.copy(u8, buffer[0..], s);
std.testing.expectEqualSlices(u8, buffer[0..], s);
}
test "auto created variables have correct alignment" {
const S = struct {
fn foo(str: [*]const u8) u32 {
for (@ptrCast([*]align(1) const u32, str)[0..1]) |v| {
return v;
}
return 0;
}
};
expect(S.foo("\x7a\x7a\x7a\x7a") == 0x7a7a7a7a);
comptime expect(S.foo("\x7a\x7a\x7a\x7a") == 0x7a7a7a7a);
}

View File

@ -153,3 +153,25 @@ test "optional with void type" {
var x = Foo{ .x = null };
expect(x.x == null);
}
test "0-bit child type coerced to optional return ptr result location" {
const S = struct {
fn doTheTest() void {
var y = Foo{};
var z = y.thing();
expect(z != null);
}
const Foo = struct {
pub const Bar = struct {
field: *Foo,
};
pub fn thing(self: *Foo) ?Bar {
return Bar{ .field = self };
}
};
};
S.doTheTest();
comptime S.doTheTest();
}

View File

@ -479,3 +479,17 @@ test "switch on pointer type" {
comptime expect(2 == S.doTheTest(S.P2));
comptime expect(3 == S.doTheTest(S.P3));
}
test "switch on error set with single else" {
const S = struct {
fn doTheTest() void {
var some: error{Foo} = error.Foo;
expect(switch (some) {
else => |a| true,
});
}
};
S.doTheTest();
comptime S.doTheTest();
}

View File

@ -1,5 +1,6 @@
const expect = @import("std").testing.expect;
const mem = @import("std").mem;
const std = @import("std");
const expect = std.testing.expect;
const mem = std.mem;
fn initStaticArray() [10]i32 {
var array: [10]i32 = undefined;

View File

@ -38,236 +38,260 @@ const TestTarget = struct {
disable_native: bool = false,
};
const test_targets = [_]TestTarget{
TestTarget{},
TestTarget{
.link_libc = true,
},
TestTarget{
.single_threaded = true,
},
const test_targets = blk: {
// getBaselineCpuFeatures calls populateDependencies which has a O(N ^ 2) algorithm
// (where N is roughly 160, which technically makes it O(1), but it adds up to a
// lot of branches)
@setEvalBranchQuota(50000);
break :blk [_]TestTarget{
TestTarget{},
TestTarget{
.link_libc = true,
},
TestTarget{
.single_threaded = true,
},
TestTarget{
.target = Target{
.Cross = CrossTarget{
.os = .linux,
.arch = .x86_64,
.abi = .none,
TestTarget{
.target = Target{
.Cross = CrossTarget{
.os = .linux,
.arch = .x86_64,
.abi = .none,
.cpu_features = Target.Arch.x86_64.getBaselineCpuFeatures(),
},
},
},
},
TestTarget{
.target = Target{
.Cross = CrossTarget{
.os = .linux,
.arch = .x86_64,
.abi = .gnu,
TestTarget{
.target = Target{
.Cross = CrossTarget{
.os = .linux,
.arch = .x86_64,
.abi = .gnu,
.cpu_features = Target.Arch.x86_64.getBaselineCpuFeatures(),
},
},
.link_libc = true,
},
.link_libc = true,
},
TestTarget{
.target = Target{
.Cross = CrossTarget{
.os = .linux,
.arch = .x86_64,
.abi = .musl,
TestTarget{
.target = Target{
.Cross = CrossTarget{
.os = .linux,
.arch = .x86_64,
.cpu_features = Target.Arch.x86_64.getBaselineCpuFeatures(),
.abi = .musl,
},
},
.link_libc = true,
},
.link_libc = true,
},
TestTarget{
.target = Target{
.Cross = CrossTarget{
.os = .linux,
.arch = .i386,
.abi = .none,
TestTarget{
.target = Target{
.Cross = CrossTarget{
.os = .linux,
.arch = .i386,
.cpu_features = Target.Arch.i386.getBaselineCpuFeatures(),
.abi = .none,
},
},
},
},
TestTarget{
.target = Target{
.Cross = CrossTarget{
.os = .linux,
.arch = .i386,
.abi = .musl,
TestTarget{
.target = Target{
.Cross = CrossTarget{
.os = .linux,
.arch = .i386,
.cpu_features = Target.Arch.i386.getBaselineCpuFeatures(),
.abi = .musl,
},
},
.link_libc = true,
},
.link_libc = true,
},
TestTarget{
.target = Target{
.Cross = CrossTarget{
.os = .linux,
.arch = builtin.Arch{ .aarch64 = builtin.Arch.Arm64.v8_5a },
.abi = .none,
TestTarget{
.target = Target{
.Cross = CrossTarget{
.os = .linux,
.arch = Target.Arch{ .aarch64 = .v8a },
.cpu_features = (Target.Arch{ .aarch64 = .v8a }).getBaselineCpuFeatures(),
.abi = .none,
},
},
},
},
TestTarget{
.target = Target{
.Cross = CrossTarget{
.os = .linux,
.arch = builtin.Arch{ .aarch64 = builtin.Arch.Arm64.v8_5a },
.abi = .musl,
TestTarget{
.target = Target{
.Cross = CrossTarget{
.os = .linux,
.arch = Target.Arch{ .aarch64 = .v8a },
.cpu_features = (Target.Arch{ .aarch64 = .v8a }).getBaselineCpuFeatures(),
.abi = .musl,
},
},
.link_libc = true,
},
.link_libc = true,
},
TestTarget{
.target = Target{
.Cross = CrossTarget{
.os = .linux,
.arch = builtin.Arch{ .aarch64 = builtin.Arch.Arm64.v8_5a },
.abi = .gnu,
TestTarget{
.target = Target{
.Cross = CrossTarget{
.os = .linux,
.arch = Target.Arch{ .aarch64 = .v8a },
.cpu_features = (Target.Arch{ .aarch64 = .v8a }).getBaselineCpuFeatures(),
.abi = .gnu,
},
},
.link_libc = true,
},
.link_libc = true,
},
TestTarget{
.target = Target{
.Cross = CrossTarget{
.os = .linux,
.arch = builtin.Arch{ .arm = builtin.Arch.Arm32.v8_5a },
.abi = .none,
TestTarget{
.target = Target{
.Cross = CrossTarget{
.os = .linux,
.arch = Target.Arch{ .arm = .v8a },
.cpu_features = (Target.Arch{ .arm = .v8a }).getBaselineCpuFeatures(),
.abi = .none,
},
},
},
},
TestTarget{
.target = Target{
.Cross = CrossTarget{
.os = .linux,
.arch = builtin.Arch{ .arm = builtin.Arch.Arm32.v8_5a },
.abi = .musleabihf,
TestTarget{
.target = Target{
.Cross = CrossTarget{
.os = .linux,
.arch = Target.Arch{ .arm = .v8a },
.cpu_features = (Target.Arch{ .arm = .v8a }).getBaselineCpuFeatures(),
.abi = .musleabihf,
},
},
.link_libc = true,
},
// TODO https://github.com/ziglang/zig/issues/3287
//TestTarget{
// .target = Target{
// .Cross = CrossTarget{
// .os = .linux,
// .arch = Target.Arch{ .arm = .v8a },
// .cpu_features = (Target.Arch{ .arm = .v8a }).getBaselineCpuFeatures(),
// .abi = .gnueabihf,
// },
// },
// .link_libc = true,
//},
TestTarget{
.target = Target{
.Cross = CrossTarget{
.os = .linux,
.arch = .mipsel,
.cpu_features = Target.Arch.mipsel.getBaselineCpuFeatures(),
.abi = .none,
},
},
},
.link_libc = true,
},
// TODO https://github.com/ziglang/zig/issues/3287
//TestTarget{
// .target = Target{
// .Cross = CrossTarget{
// .os = .linux,
// .arch = builtin.Arch{ .arm = builtin.Arch.Arm32.v8_5a },
// .abi = .gnueabihf,
// },
// },
// .link_libc = true,
//},
TestTarget{
.target = Target{
.Cross = CrossTarget{
.os = .linux,
.arch = .mipsel,
.cpu_features = Target.Arch.mipsel.getBaselineCpuFeatures(),
.abi = .musl,
},
},
.link_libc = true,
},
TestTarget{
.target = Target{
.Cross = CrossTarget{
.os = .linux,
.arch = .mipsel,
.abi = .none,
TestTarget{
.target = Target{
.Cross = CrossTarget{
.os = .macosx,
.arch = .x86_64,
.cpu_features = Target.Arch.x86_64.getBaselineCpuFeatures(),
.abi = .gnu,
},
},
// TODO https://github.com/ziglang/zig/issues/3295
.disable_native = true,
},
TestTarget{
.target = Target{
.Cross = CrossTarget{
.os = .windows,
.arch = .i386,
.cpu_features = Target.Arch.i386.getBaselineCpuFeatures(),
.abi = .msvc,
},
},
},
},
TestTarget{
.target = Target{
.Cross = CrossTarget{
.os = .linux,
.arch = .mipsel,
.abi = .musl,
TestTarget{
.target = Target{
.Cross = CrossTarget{
.os = .windows,
.arch = .x86_64,
.cpu_features = Target.Arch.x86_64.getBaselineCpuFeatures(),
.abi = .msvc,
},
},
},
.link_libc = true,
},
TestTarget{
.target = Target{
.Cross = CrossTarget{
.os = .macosx,
.arch = .x86_64,
.abi = .gnu,
TestTarget{
.target = Target{
.Cross = CrossTarget{
.os = .windows,
.arch = .i386,
.cpu_features = Target.Arch.i386.getBaselineCpuFeatures(),
.abi = .gnu,
},
},
.link_libc = true,
},
// TODO https://github.com/ziglang/zig/issues/3295
.disable_native = true,
},
TestTarget{
.target = Target{
.Cross = CrossTarget{
.os = .windows,
.arch = .i386,
.abi = .msvc,
TestTarget{
.target = Target{
.Cross = CrossTarget{
.os = .windows,
.arch = .x86_64,
.cpu_features = Target.Arch.x86_64.getBaselineCpuFeatures(),
.abi = .gnu,
},
},
.link_libc = true,
},
},
TestTarget{
.target = Target{
.Cross = CrossTarget{
.os = .windows,
.arch = .x86_64,
.abi = .msvc,
},
// Do the release tests last because they take a long time
TestTarget{
.mode = .ReleaseFast,
},
},
TestTarget{
.target = Target{
.Cross = CrossTarget{
.os = .windows,
.arch = .i386,
.abi = .gnu,
},
TestTarget{
.link_libc = true,
.mode = .ReleaseFast,
},
.link_libc = true,
},
TestTarget{
.target = Target{
.Cross = CrossTarget{
.os = .windows,
.arch = .x86_64,
.abi = .gnu,
},
TestTarget{
.mode = .ReleaseFast,
.single_threaded = true,
},
.link_libc = true,
},
// Do the release tests last because they take a long time
TestTarget{
.mode = .ReleaseFast,
},
TestTarget{
.link_libc = true,
.mode = .ReleaseFast,
},
TestTarget{
.mode = .ReleaseFast,
.single_threaded = true,
},
TestTarget{
.mode = .ReleaseSafe,
},
TestTarget{
.link_libc = true,
.mode = .ReleaseSafe,
},
TestTarget{
.mode = .ReleaseSafe,
.single_threaded = true,
},
TestTarget{
.mode = .ReleaseSafe,
},
TestTarget{
.link_libc = true,
.mode = .ReleaseSafe,
},
TestTarget{
.mode = .ReleaseSafe,
.single_threaded = true,
},
TestTarget{
.mode = .ReleaseSmall,
},
TestTarget{
.link_libc = true,
.mode = .ReleaseSmall,
},
TestTarget{
.mode = .ReleaseSmall,
.single_threaded = true,
},
TestTarget{
.mode = .ReleaseSmall,
},
TestTarget{
.link_libc = true,
.mode = .ReleaseSmall,
},
TestTarget{
.mode = .ReleaseSmall,
.single_threaded = true,
},
};
};
const max_stdout_size = 1 * 1024 * 1024; // 1 MB
@ -598,6 +622,9 @@ pub const StackTracesContext = struct {
child.stderr_behavior = .Pipe;
child.env_map = b.env_map;
if (b.verbose) {
printInvocation(args.toSliceConst());
}
child.spawn() catch |err| debug.panic("Unable to spawn {}: {}\n", .{ full_exe_path, @errorName(err) });
var stdout = Buffer.initNull(b.allocator);

View File

@ -1,7 +1,43 @@
const tests = @import("tests.zig");
const builtin = @import("builtin");
const Target = @import("std").Target;
pub fn addCases(cases: *tests.TranslateCContext) void {
cases.add("function prototype with parenthesis",
\\void (f0) (void *L);
\\void ((f1)) (void *L);
\\void (((f2))) (void *L);
, &[_][]const u8{
\\pub extern fn f0(L: ?*c_void) void;
\\pub extern fn f1(L: ?*c_void) void;
\\pub extern fn f2(L: ?*c_void) void;
});
cases.add("array initializer w/ typedef",
\\typedef unsigned char uuid_t[16];
\\static const uuid_t UUID_NULL __attribute__ ((unused)) = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
, &[_][]const u8{
\\pub const uuid_t = [16]u8;
\\pub const UUID_NULL: uuid_t = .{
\\ @bitCast(u8, @truncate(i8, @as(c_int, 0))),
\\ @bitCast(u8, @truncate(i8, @as(c_int, 0))),
\\ @bitCast(u8, @truncate(i8, @as(c_int, 0))),
\\ @bitCast(u8, @truncate(i8, @as(c_int, 0))),
\\ @bitCast(u8, @truncate(i8, @as(c_int, 0))),
\\ @bitCast(u8, @truncate(i8, @as(c_int, 0))),
\\ @bitCast(u8, @truncate(i8, @as(c_int, 0))),
\\ @bitCast(u8, @truncate(i8, @as(c_int, 0))),
\\ @bitCast(u8, @truncate(i8, @as(c_int, 0))),
\\ @bitCast(u8, @truncate(i8, @as(c_int, 0))),
\\ @bitCast(u8, @truncate(i8, @as(c_int, 0))),
\\ @bitCast(u8, @truncate(i8, @as(c_int, 0))),
\\ @bitCast(u8, @truncate(i8, @as(c_int, 0))),
\\ @bitCast(u8, @truncate(i8, @as(c_int, 0))),
\\ @bitCast(u8, @truncate(i8, @as(c_int, 0))),
\\ @bitCast(u8, @truncate(i8, @as(c_int, 0))),
\\};
});
cases.add("empty declaration",
\\;
, &[_][]const u8{""});
@ -1005,7 +1041,12 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
});
cases.addWithTarget("Calling convention", tests.Target{
.Cross = .{ .os = .linux, .arch = .i386, .abi = .none },
.Cross = .{
.os = .linux,
.arch = .i386,
.abi = .none,
.cpu_features = Target.Arch.i386.getBaselineCpuFeatures(),
},
},
\\void __attribute__((fastcall)) foo1(float *a);
\\void __attribute__((stdcall)) foo2(float *a);
@ -1021,7 +1062,12 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
});
cases.addWithTarget("Calling convention", tests.Target{
.Cross = .{ .os = .linux, .arch = .{ .arm = .v8_5a }, .abi = .none },
.Cross = .{
.os = .linux,
.arch = .{ .arm = .v8_5a },
.abi = .none,
.cpu_features = (Target.Arch{ .arm = .v8_5a }).getBaselineCpuFeatures(),
},
},
\\void __attribute__((pcs("aapcs"))) foo1(float *a);
\\void __attribute__((pcs("aapcs-vfp"))) foo2(float *a);
@ -1031,7 +1077,12 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
});
cases.addWithTarget("Calling convention", tests.Target{
.Cross = .{ .os = .linux, .arch = .{ .aarch64 = .v8_5a }, .abi = .none },
.Cross = .{
.os = .linux,
.arch = .{ .aarch64 = .v8_5a },
.abi = .none,
.cpu_features = (Target.Arch{ .aarch64 = .v8_5a }).getBaselineCpuFeatures(),
},
},
\\void __attribute__((aarch64_vector_pcs)) foo1(float *a);
, &[_][]const u8{
@ -2590,4 +2641,15 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\ return foo((@intCast(c_int, @bitCast(i1, @intCast(u1, @boolToInt(c)))) != @intCast(c_int, @bitCast(i1, @intCast(u1, @boolToInt(b))))));
\\}
});
cases.add("Don't make const parameters mutable",
\\int max(const int x, int y) {
\\ return (x > y) ? x : y;
\\}
, &[_][]const u8{
\\pub export fn max(x: c_int, arg_y: c_int) c_int {
\\ var y = arg_y;
\\ return if (x > y) x else y;
\\}
});
}